This probably won’t be of much interest to anyone else; but the very least, I need it up here for my own future reference. It involves the programming language that I built into the Massive Tool.
Back in college (Rhode Island College, to be precise), over twenty years ago, I decided to write a
FORTH interpreter for my senior project. I’d studied BASIC, PASCAL, C, FORTRAN, COBOL, and Assembly language; but RIC didn’t have FORTH (I’d played around a bit with a dinky implementation I’d found for the Apple II and found it interesting… and different from all the other languages). I started writing it on a
DEC VAX/VMS minicomputer, but never finished - I’d implemented variables and mathematical operations, but not any of the more complex structures (loops, if-else-then branches, etc.) I ended up handing in something else for my senior project credit, but that’s another story. I named my interpreter One/FORTH.
I kept the code, and later ported it over to the PC (sometime in the mid-90s). It ran under DOS, and I could use it to type mathematical formulas or other commands directly at the C> prompt or embed them in batch files. It occasionally came in useful, saving me the time to get a calculator, but it was still more of an amusement or a hobby.
Several years ago, while working on the Massive Tool, I decided that what it really need was a built-in language for composing macros, automating some tasks, and so FORTH. Once again I ported the code into a new system, and finally got the motivation to finish it… Well, as much as anything is ever “finished.” It has loops, conditional statements, and interfaces with the text in the Tool as well as allowing some direct access to the OS and the Internet. In fact, I’m constantly tweaking and expanding it as I see new needs (or just think of something nifty) and it’s hard to keep it neat and orderly, and also hard to keep up with exactly what the current structure is. I often find myself going back into the source code to remind me of how a particular command is supposed to be used, for instance, because I’ve never documented the language.
Well, that has finally changed. I’ve spent some time going over every command in the interpreter, describing what it does in a
standard format, and also removing some redundant and obsolete code in the process. While writing the documentation below, I removed at least a dozen commands and added a least a dozen more - by combining existing commands that were too similar, by breaking up complex commands into smaller pieces, and just adding a few more that were’t there yet. I’ve also tried to keep it fairly close to regular FORTH (although I am not even trying to make my version comply with the “standards;” I’m just using them as a starting point). The list below describes FORTH as it currently exists on my machine (
Allah Sulu's Massive Tool version 3.8.0); it won’t do the rest of you any good until I provide an update for downloading (which should be soon; this is a good occasion for an update). I just have to finish correcting all of the macro files I’ve already written (the ones with the .4TH and .RIM extensions); most of them no longer work properly under the new version of FORTH after all the changes I’ve made.
I’m not done yet - I will have to go into further detail on some of these commands (primarily the ones that say “different options are available”) - but this, and a standard FORTH tutorial to provide the basics of the language, is all anyone needs to get started learning to use my language if they are so inclined… and have version 3.8.0 of the Massive Tool. (I have a short list of additional commands or features I’m thinking of adding, but they can wait… And I’ll try to keep this updated to match future modifications.)
- ( n1 n2 -- n3 )Subtracts n2 from n1
' c ( -- n )The ASCII value of a single character immediately following the apostrophe is placed on the numeric stack
! ( n var -- ) or ( s var$ -- )Stores a number in a numeric variable or a string in a string variable
-! ( n var -- ) or ( s var$ -- )Subtracts a number from a numeric variable or prepends string to a string variable
!= ( n1 n2 -- flag )True if n1 does not equal n2; alternately, use <>
" ( -- s ) ccc"The string specified (a space must follow the opening quote) is placed on the string stack
" c ( -- s )The single character immediately following the quotation mark is placed on the string stack
#column ( -- addr )A system variable containing the cursor's column position in the Massive Tool's editor
#row ( -- addr )A system variable containing the cursor's row position in the Massive Tool's editor
#selectlength ( -- addr )A system variable containing the length, in characters, of the selected text in the Massive Tool's editor, starting at the position specified in #SELECTSTART
#selectstart ( -- addr )A system variable containing the position of the first selected character in the Massive Tool's editor; or, if there is no selected text, the position of the cursor. Always change #SELECTSTART before changing #SELECTLENGTH
%[ ( -- s ) ccc]A variation of [ccc] which allows special characters to be coded into the string as hex codes following a percent sign (CR-LF would be %0D%0A)
& ( s1 s2 -- s3 )Appends s2 to the end of s1
> ( n1 n2 -- flag )True if n1 is greater than n2
>$ ( s1 s2 -- flag )True if s1 is greater than s2
>= ( n1 n2 -- flag )True if n1 is greater than or equal to n2
>r ( n -- )Moves a number to the return stack
>r$ ( s -- )Moves a string to the return string stack
< ( n1 n2 -- flag )True if n1 is less than n2
<$ ( s1 s2 -- flag )True if s1 is less than s2
<> ( n1 n2 -- flag )True if n1 does not equal n2; alternately, use !=
<= ( n1 n2 -- flag )True if n1 is less than or equal to n2
( ( -- )Begins a comment
* ( n1 n2 -- n3 )Multiplies n1 times n2
*! ( n var -- ) or ( n var$ -- )Multiplies a numeric variable by a number or repeats a string variable a number of times
*/ ( n1 n2 n3 --- n4 )Multiplies n1 times n2, divides product by n3
. ( n -- )Displays a number
." ( -- ) ccc"Displays enclosed string
.$ ( s -- )Displays a string
/ ( n1 n2 -- n3 )Divides n2 from n1
/! ( n var -- )Divides a numeric variable by a number (is not used by string variables)
/mod ( n1 n2 -- n3 n4 )n3 is remainder, n4 is quotient of n1/n2
: ( -- sys ) nameStarts the creation of a new colon definition
:: ( -- sys ) nameStarts the creation of a colon definition; replaces existing definition if applicable
; ( -- )Finishes the compilation of a colon definition
? ( var -- ) or ( var$ -- )Displays the contents of a (numeric or string) variable
?dup ( n -- n n )Duplicates n if it is non-zero
?leave ( flag -- )Exits from a DO…LOOP if flag is nonzero
@ ( var -- n ) or ( var$ -- s )Fetches a number from numeric variable or a string from a string variable
[ ( -- s ) ccc]The string specified (unlike the quotes, no space need follow the open bracket) is placed on the string stack
^ ( n1 n2 -- n3 )Raises n1 to the power of n2
{ ( -- ) sys }Defines a block of code inside a loop or conditional; may be necessary when nesting
+ ( n1 n2 -- n3 )Adds n1 to n2
+! ( n var -- ) or ( s var$ -- )Adds a number to a numeric variable or appends string to a string variable
+loop ( n -- )Ends DO…+LOOP construct; adds n to loop index
= ( n1 n2 -- flag )True if n1 equals n2
=$ ( s1 s2 -- flag )True if s1 is equal to s2
0> ( n -- flag )True if n is greater than zero
0< ( n -- flag )True if n is less than zero
0= ( n -- flag )True if n is equal to zero
1- ( n1 -- n2 )Subtract 1
1+ ( n1 -- n2 )Add 1
2* ( n1 -- n2 )Multiply by 2
2/ ( n1 -- n2 )Divide by 2
2drop ( n1 n2 -- )Removes two numbers from stack
2dup ( n1 n2 -- n1 n2 n1 n2 )Duplicates top two items on the stack
abort$ ( s -- )Aborts current execution with message; alternately, use ABORT" ccc"
abs ( n1 -- n2 )Absolute value
again ( -- )Continues executing a BEGIN…AGAIN loop
and ( n1 n2 -- n3 )Logical and
array ( n -- ) nameDefines an array with n+1 (starting at zero) elements (array names containing a dollar sign are string arrays)
average ( n? -- n? n )The average of all values on the stack (use AVERAGE.RETAIN to retain the stack); alternately, use AVG
base ( -- addr )A system variable for determining the default base for numeric input and output. Legal values are 2 through 36, and 0 (Roman numerals).
begin ( -- )Initiates a BEGIN…AGAIN, BEGIN…WHILE…REPEAT, or BEGIN…UNTIL loop
between ( n1 n2 n3 -- flag )True if n2 <= n1 <= n3
binary ( -- )Set system variable BASE to 2; alternately, use BIN
bye ( -- )Exits from Forth
canonical ( s1 -- s2 )Converts a string to lower case; alternately, use CONVERT$.LOWERCASE.ALL
case ( selector -- selector )Begins a CASE…ENDCASE construct
case$ ( selector -- selector )Begins a CASE$…ENDCASE construct
chdir$ ( s -- )Changes the current directory to the top item on the string stack; alternately, use CHDIR" ccc"
clstk ( n? -- )Clears the numeric stack
clstk$ ( s? -- )Clears the string stack
command$ ( s -- )Executes the URL, Windows program, or file whose name is on the string stack; alternately, use COMMAND" ccc" (different options are available)
complement ( n1 -- n2 )Toggles all bits in an integer
concat$ ( s? -- s )Concatenates all items on the string stack into a single string (use CONCAT$.CR to insert a carriage return/linefeed between items)
constant ( n -- ) var or ( s -- ) var$Defines a constant (constant names containing a dollar sign are string constants)
convert ( s -- n )Converts a string to a number (current BASE unless otherwise specified) or generates error if not possible; see also NUMBER?
convert$ ( n -- s )Converts a number into a string in the current BASE (other options are available)
cos ( n1 -- n2 )The cosine of n1, in radians
cr ( -- )Terminates a line on the output and goes to the next line
cr$ ( -- s )A system string constant consisting of a carriage return and a line feed
currentdir$ ( -- s )Returns the current directory
date ( -- n1 n2 n3 )Returns the month (n2), day (n3), and year (n1) (different options are available)
decimal ( -- )Set system variable BASE to 10; alternately, use DEC
delete$ ( s1 n1 n2 -- s2 )Delete a substring of string s1, starting at position n1 and containing n2 characters
deleteall$ ( s1 s2 -- s3 )Delete all instances of substring s2 from string s1 (different options are available)
depth ( -- n )Number of items on the numeric stack
depth$ ( -- n )Number of items on the string stack
digits ( -- addr )A system variable for determining the default number of decimal places for numeric output (use a negative number to eliminate trailing zeroes)
div ( n1 n2 -- n3 )Performs an integer division of n2 from n1
do ( n1 n2 -- )Begins a DO…LOOP
download$ ( s -- )Downloads the file whose URL is on the string stack; alternately, use DOWNLOAD" ccc" (different options are available)
drop ( n -- )Removes top item from the stack
drop$ ( s -- )Removes top item from the string stack
dup ( n -- n n )Duplicates top item on the stack
dup$ ( s -- s s )Duplicates top item on the string stack
else ( -- )Executes the following code if IF failed
emit ( n -- )Displays an ASCII character
empty ( -- )Clears Forth of all user-defined words as well as all stacks, and resets all system variables
endcase ( selector -- )Ends a CASE…ENDCASE or CASE$…ENDCASE construct
endof ( -- )Ends an OF, OF<, OF>, RANGEOF, OTHERWISE, or FINALLY clause within a CASE or CASE$ construct
exit ( -- )Ends execution without exiting Forth
expect ( -- n )Accepts numeric input from the user (current BASE unless otherwise specified; other options are available)
expect$ ( -- s )Accepts string input from the user (other options are available)
extract$ ( s1 -- s? )Extracts all of the URLs (if any) from a string and places each as a separate item on the string stack (different options are available)
factorial ( n1 -- n2 )The factorial, or product of all integers from one through n1
filter ( s1 s2 -- )Adds a substitution filter for the Massive Tool's preview pane (different options are available)
finally ( selector test-value -- )Begins a FINALLY…ENDOF clause within a CASE or CASE$ construct
flipstk ( n1…n? -- n?…n1 )Reverses the order of the numeric stack
flipstk$ ( s1…s? -- s?…s1 )Reverses the order of the string stack
foreach ( -- ) sysInitiates a FOREACH…DO…LOOP, a custom variant of a DO…LOOP
forget ( -- ) nameRemoves a user-defined word (command, variable, constant, array) from Forth
gcf ( n1 n2 -- n3 )The greatest common factor of two integers
getfile$ ( s1 -- s2 )Can be used to get the drive, directory, extension, or other part of a filename/URL (different options are available)
hexadecimal ( -- )Set system variable BASE to 16; alternately, use HEX
i ( -- n )Numeric loop index
i$ ( -- s )String loop index
if ( flag -- )Executes following code if flag is true
insert$ ( s1 s2 n -- s3 )Insert string s2 into string s1 at position n
interpret$ ( s -- )Pass a string to the interpreter for execution
is ( -- flag ) nameIndicates whether or not the named word is a defined in Forth (different options are available)
is$ ( s -- flag )Indicates whether or not the word named on the string stack is a defined in Forth (different options are available)
j ( -- n )Numeric loop index for second enclosing loop
j$ ( -- s )String loop index for second enclosing loop
k ( -- n )Numeric loop index for third enclosing loop
k$ ( -- s )String loop index for third enclosing loop
kbdshortcut ( s1 s2 -- )Adds a keyboard shortcut (accessed with CTRL-K) to the Massive Tool (different options are available)
lcd ( n1 n2 -- n3 )The least common denominator (or lowest common multiple) of two integers
leave ( -- )Exits from a DO…LOOP
left$ ( s1 n -- s2 )The leftmost n characters of the top item on the string stack
length ( s -- n )The length, in characters, of the top item on the string stack
list ( -- )Displays all words, system and user-defined, currently within Forth (different options are available)
ln ( n1 -- n2 )The natural logarithm
load$ ( s -- )Interprets the file whose name is on the string stack; alternately, use LOAD" ccc"
loop ( n -- )Ends DO…LOOP construct
max ( n1 n2 -- n3 )n3 is greater of n1 and n2
median ( n? -- n? n )The median of all values on the stack (use MEDIAN.RETAIN to retain the stack)
mid$ ( s1 n1 n2 -- s2 )A substring of the top item on the string stack; n2 characters beginning at position n1
min ( n1 n2 -- n3 )n3 is lesser of n1 and n2
mkdir$ ( s -- )Creates a new directory from the top item on the string stack; alternately, use MKDIR" ccc"
mod ( n1 n2 -- n3 )The remainder of n1 divided by n2
negate ( n1 -- n2 )Changes the sign of n1
noop ( -- )Does nothing
not ( n1 -- n2 )Logical not (0 or non-zero)
null$ ( -- s )A system constant consisting of an empty (zero-length) string
number? ( s -- n flag )Converts a string to a number (current BASE unless otherwise specified) and a flag to indicate success; see also CONVERT
octal ( -- )Set system variable BASE to 8; alternately, use OCT
of ( selector test-value -- )Begins an OF…ENDOF clause within a CASE or CASE$ construct
of> ( selector test-value -- )Begins an OF>…ENDOF clause within a CASE or CASE$ construct
of< ( selector test-value -- )Begins an OF<…ENDOF clause within a CASE or CASE$ construct
open$ ( s -- )Opens a document within the Massive Tool; alternately, use OPEN" ccc" (different options are available)
or ( n1 n2 -- n3 )Logical or
otherwise ( selector test-value -- )Begins an OTHERWISE…ENDOF clause within a CASE or CASE$ construct
over ( n1 n2 -- n1 n2 n1 )Copies the second from the top item on the stack onto the top of the stack
over$ ( s1 s2 -- s1 s2 s1 )Copies the second from the top item on the string stack onto the top of the string stack
pick ( n1 -- n2 )Copies the n1-th value on the numeric stack (the top item is n1=1)
pick$ ( n -- s )Copies the n-th value on the string stack (the top item is n=1)
pop ( n -- )Moves the top item from the numeric stack onto the clipboard (other options are available)
pop$ ( s -- )Moves the top item from the string stack onto the clipboard (other options are available)
pos$ ( s1 s2 -- n )Returns the position of string s2 within string s1, or zero if s2 in not a substring of s1
push ( -- n)Passes a number to the stack from the clipboard (other options are available)
push$ ( -- s)Passes a string to the string stack from the clipboard (other options are available)
r$> ( -- s )Moves a string from the return string stack to the string stack
r$@ ( -- s )Copies the top of the return string stack to the string stack
r> ( -- n )Moves a number from the return stack to the numeric stack
r@ ( -- n )Copies the top of the return stack to the numeric stack
random ( n1 -- n2 )If n1>0, n2 will be a random integer from 1 through n1. If n1=0, the result will be a real number 0 <= n2 < 1
range ( n? -- n? n n )Pushes the lowest and highest of all values on the stack (use RANGE.RETAIN to retain the stack; other options are available)
rangeof ( selector test-value -- )Begins a RANGEOF…ENDOF clause within a CASE or CASE$ construct
rename$ ( s1 s2 -- )Renames file s1 to s2. File may also be moved if full path differs or is absent from s2
repeat ( -- )Ends a BEGIN…WHILE…REPEAT loop
replaceall$ ( s1 s2 s3 -- s4 )Replaces all instances of substring s2 in string s1 with substring s3 (different options are available)
right$ ( s1 n -- s2 )The rightmost n characters of the top item on the string stack
rmdir$ ( s -- )Deletes a directory (must be empty!) named by the top item on the string stack; alternately, use RMDIR" ccc"
roman ( -- )Set system variable BASE to 0
rot ( n1 n2 n3 --- n2 n3 n1 )Rotates top three stack items
-rot ( n1 n2 n3 --- n3 n1 n2 )Rotates top three stack items
rot$ ( s1 s2 s3 --- s2 s3 s1 )Rotates top three string stack items
-rot$ ( s1 s2 s3 --- s3 s1 s2 )Rotates top three string stack items
round ( n1 -- n2 )Round of a floating-point number to the nearest integer
see ( -- ) nameDisplays the definition of the named word
see$ ( s -- )Displays the definition of the word named on the string stack
select ( -- )Select all of the text in the Massive Tool if and only if no text is currently selected (different options are available)
sgn ( n1 -- n2 )Returns 1 for any positive number, -1 for any negative number, or 0 for zero
sin ( n1 -- n2 )The sine of n1, in radians
sort ( n? -- n? )Sorts the numeric stack (other options are available)
sort$ ( s? -- s? )Sorts the string stack (other options are available)
sound ( n1 n2 -- )Plays a note at n1 Hz for n2 milliseconds
space ( -- )Displays a space character
spaces ( n -- )Displays n spaces
spaces$ ( n -- s )Places a string containing n spaces onto the string stack
split$ ( s1 n -- s2 s3 )Splits string s1 into two pieces at position n
stdev ( n? -- n? n )The standard deviation of all values on the stack (use STDEV.RETAIN to retain the stack)
sum ( n? -- n? n )The sum of all values on the stack (use SUM.RETAIN to retain the stack)
swap ( n1 n2 -- n2 n1 )Exchanges the top two numbers on the stack
swap$ ( s1 s2 -- s2 s1 )Exchanges the top two string on the string stack
tan ( n1 -- n2 )The tangent of n1, in radians
td ( -- n ) numInterprets the next number in DECIMAL mode; alternately, prepend # to the number
th ( -- n ) xnumInterprets the next number in HEXADECIMAL mode; alternately, prepend 0x to the number
then ( -- )Terminates an IF…ELSE…THEN or IF…THEN structure
timer ( s n -- )After a delay of n milliseconds, will attempt to INTERPRET$ the contents of string s (different options are available)
trim$ ( s1 -- s2 )Removes leading and trailing spaces from a string
trunc ( n1 -- n2 )Truncate a floating-point number to an integer
tuck ( n1 n2 -- n2 n1 n2 )Copies the top item of the numeric stack underneath the second item
tuck$ ( s1 s2 -- s2 s1 s2 )Copies the top item of the string stack underneath the second item
until ( flag -- )Continues executing a BEGIN…UNTIL loop until flag is true
variable ( -- ) nameDefines a variable (variable names containing a dollar sign are string variables)
version$ ( -- s )A system string constant consisting of the current Forth version number
while ( flag -- )Continues execution of BEGIN…WHILE…REPEAT loop while flag is true
within ( n1 n2 n3 -- flag )True if n2 < n1 < n3
xor ( n1 n2 -- n3 )Logical exclusive or