(JaM Utilities of September 9, 1980 5:19 PM ).print ($help) .sysdict ($help) .known (.pop) .cvx (100 .dict .def) .cvx .ifelse (/def) (3 .copy .exch .pop .def .pop $help 3 1 .roll .put) .cvx .def (/xdef) (3 .copy .exch .pop .cvx .def .pop $help 3 1 .roll .put) .cvx .def (/def) ("/def" accepts three entries on the stack: a key, string, and value. the string is stored under the key in the $help dictionary, and the value is stored as a noun under the key in the current dictionary.) (/def) .load /def (/xdef) ("/xdef" accepts three entries on the stack: a key, string, and value. the string is stored under the key in the $help dictionary, and the value is stored as a verb under the key in the current dictionary.) (/xdef) .load /xdef (?) ("?" prints the explanation of the given key from the $help dictionary) ($help .exch .get =)/xdef (??) ("??" prints the names of all the utility commands found in the $help dictionary.) ($help /kdir)/xdef (=) ("=" prints the top of the stack on the default display followed by CR) (( ).cvis .print ( ).print)/xdef (:) (":" prints the top of the stack on the default display followed by SP) (( ).cvis .print ( ).print)/xdef (/stk) ("/stk" prints (without destroying) the contents of the operand stack.) (.cntstk .dup 1 .add .copy (.dup .type .print ( ).print = ) .cvx .rept .pop)/xdef (/clr) ("/clr" clears the operand stack (same as .clrstk)) (.clrstk) /xdef (/dir) ("/dir" prints the contents of the dictionary on top of the operand stack.) ((.exch ( ) .cvis .print ( ).print .dup .type .print ( ).print =) .cvx .dictforall)/xdef (/kdir) ("/kdir" prints the keys found in the dictionary on the top of the operand stack.) ((.exch = .pop) .cvx .dictforall)/xdef (/ifx) ("/ifx" is equivalent to ".cvx .if") (.cvx .if)/xdef (/ifelsex) ("/ifelsex" is equivalent to " .ifelse .cvx .exec") (.ifelse .cvx .exec)/xdef ([) ("[" is a command that marks the operand stack for use by the command "]". This pair of commands is use to create arrays. For example: [ 1 2 (hello) ] will create an array containing two integers (1 and 2) and the string "hello".) (.mark)/xdef (]) ("]" is a command that counts the elements after the mark on the stack and puts these elements into an array which is left on the stack. The pair of commands ( "[" and "]" ) is use to create arrays. For example: [ 1 2 (hello) ] will create an array containing two integers (1 and 2) and the string "hello".) (.cnttomrk .array .astore .exch .pop)/xdef (/compile) ("/compile" transforms the string on the top of the operand stack into an array. This array is returned (unexecutable) on the operand stack. Note: only one level of binding is done on the string.) (.dup /cnttoken .array /cmpstrngarray)/xdef (/cnttoken) ("/cnttoken" counts the number of tokens in a given string or stream and leaves the value on the stack. /cnttoken => ) (0 .exch (.token (.pop .exch 1 .add .exch)(.exit)/ifelsex).cvx .loop)/xdef (/cmpstrngarray) ("/cmpstrngarray" compiles a given string or stream into a given array. /cmpstrngarray => ) ( (!a) .exch .def (!i) 0 .def (/cvtoken !a !i 3 2 .roll .aput (!i) .dup .load 1 .add .store) .cvx /tokall !a)/xdef (/cvtoken) ("/cvtoken" determines if a token is an identifier and loads the value from the current context. If the value is a commandtype, then the identifier is replaced with its value. /cvtoken => if not command if t is a command) (.dup .type (.stringtype) .eq (.dup .litchk (.executable) .eq (.dup .load .dup .type (.commandtype) .eq (.exch .pop)(.pop) /ifelsex) /ifx) /ifx) /xdef (/tokall) ("/tokall" executes the object on top of the operand stack for each token in the string or stream that is next on stack. /tokall) ((!x).exch .def (!s) .exch .cvlit .def (!s .token (.exch (!s) .exch .def !x )( .exit).ifelse .cvx .exec ).cvx .loop)/xdef (/edit) ("/edit" lists the definition in a form suitable for redefinition after editing e.g. (procname)/edit ) ( /lp .print .dup .print /rp .print /lp .print .load .print /rp .print (.cvx .def ).print).cvx /def (/lp)(()) 0 1 .substring .def (/rp)(()) 1 1 .substring .def (/cr)( ) .def (/writedef) ("/writedef" writes the definition on a stream in a form suitable for reading e.g. outstream (procname)/writedef ) (.dup .load .dup .type (.stringtype) .eq (3 .copy .pop .pop .dup /lp .writebytes .dup 4 -1 .roll .writebytes .dup /rp .writebytes .dup ( ) .writebytes .dup /lp .writebytes 2 .copy .exch .writebytes .dup /rp .writebytes .pop .litchk .not (.dup (.cvx ) .writebytes).cvx .if (.def ).writebytes).cvx (.pop .pop .pop).cvx .ifelse ).cvx /def (/filout) ("/filout" writes all definitions in a given dictionary in a form suitable for reading e.g. dict (filename) /filout ) (6 .bytestream .exch .dup .begin (.pop 2 .copy .pop .exch /writedef).cvx .dictforall .killstream .end ).cvx /def (/lp)(()) 0 1 .substring .def (/rp)(()) 1 1 .substring .def (/cr)( ) .def (/list) ("/list" lists a file, e.g. (file.name) /list ) (1 .bytestream ( .dup .readline (.print ( ).print).cvx (.pop .exit).cvx .ifelse ).cvx .loop ).cvx /def (/type) ("/type" types the element on the top of the stack Arrays have their individual elements typed, the level of nesting being indicated by the number of '='s preceeding each element ) ( (indent) 0 .def dotype ).cvx /def (dotype) ( (indent) indent 1 .add .def .dup .type (.arraytype) .eq (.dup .length 1 .sub 0 .exch 1 .exch (.exch .dup 3 -1 .roll .aget dotype).cvx .for .pop).cvx (indent((=).print).cvx .rept =).cvx .ifelse (indent) indent 1 .sub .def ).cvx .def (/fed)(.exch .def).cvx .def (/concat) (concatenate two strings) (2 .copy .length .exch .length .dup 4 1 .roll .add .string 0 5 -1 .roll .putstring 3 1 .roll .putstring ).cvx /def (/ndir) (list nested dictionary) ( (indent) 0 .def /dondir ).cvx /def (/dondir) (supports /ndir) ( (indent) indent 1 .add .def .dup .type (.dicttype) .eq (( ).print (indent((=).print).cvx .rept .exch ( ) .cvis .print ( ).print /dondir).cvx .dictforall).cvx (=).cvx .ifelse (indent) indent 1 .sub .def ).cvx /def (/print) (like .print but appends cr ) (.print ( ).print).cvx /def (/printmouse) (print definition of mouse procedures ) (()/print (.reddown)/edit ()/print (.redup)/edit ()/print (.yellowdown)/edit ()/print (.yellowup)/edit ()/print (.bluedown)/edit ()/print (.blueup)/edit ()/print).cvx /def (/begin) (.begin a dictionary and execute its begin code ) (.begin (begin).load .exec ).cvx /def (/end) (execute a dictionary's end code and .end it ) ((end).load .exec .end ).cvx /def (/args) ( ... n /args will assign the n objects on the stack before to the n names useful as first command in a procedure ) (.dup 0 .eq (.pop).load ( .dup 2 .add -1 .roll 3 -1 .roll .exch .def 1 .sub /args ).cvx .ifelse ).cvx /def (/getargs) ( (name1 name2 ... namen) /getargs will assign the n objects on the stack before (name1 name2 ... namen) to the names useful as first command in a procedure ) (0 .exch (.exch 1 .add).cvx /tokall /args ).cvx /def (#)(.load).load .def (/wildsearch) (/wildsearch takes a string and array of search strings on the stack. It returns a .true or .false depending on whether the array of search strings are all found in the target string) [ (.true)# (.exch)# [ (.exch)# (.pop)# (.search)# [ (.pop)# (.pop)# (.true)# ] [ (.pop)# (.false)# (.exit)# ] (.ifelse)# (.cvx)# (.exec)# ] (.cvx)# (.arrayforall)# [ (.pop)# (.true)# ] [ (.false)# ] (.ifelse)# (.cvx)# (.exec)# ] /xdef (/wildbuild) (/wildbuild takes a string of the form *s1*s2*...sn* and builds the array: [s1,s2...,sn].) [ (.mark)# (.exch)# (*) [ (.search)# [ 3 1 (.roll)# ] [ (.cnttomrk)# (.array)# (.astore)# (.exch)# (.pop)# (.exit)# ] (.ifelse)# (.cvx)# (.exec)# ] (.cvx)# (.loop)# ] /xdef (!S) [ () ] .def (/wildcard) (/wildcard takes a dictionary and a string of the form *s1*s2*...sn* on the stack. It then prints all names in the dict that contain the search pattern.) [ (/wildbuild)# !S (.exch)# 0 (.exch)# (.aput)# [ (.pop)# ( ) (.cvis)# (.dup)# !S 0 (.aget)# (/wildsearch)# [ (=)# ] [ (.pop)# ] (.ifelse)# (.cvx)# (.exec)# ] (.cvx)# (.dictforall)# ] /xdef (.start) ((jamrun) jamrun 1 .add .def (JaM)/print ).cvx .def (jamrun)1 .def (watchmouse)((watchkeys).cvx .loop).cvx .def (.prompt)((*).print).cvx .def ()/print