File: [Indigo]<JaM>Cedar>JaM.doc Last edit by Doug Wyatt, 12-Oct-81 17:11:07 Differences from previous JaM * Added commands: .idiv .sqrt .putarray .sget .sput .scopename .abind .afind .lv .lvload .lvknown .lvstore .lvforall .lvlength .lvmaxlength .lvgrow .fetch .assign .attachdict .detachdict .attachedforall .detachall * Added errors: .undefname .deadstream .execovrflw .dictovrflw .dictundflw .notattached .attachmentcycle .undeflv .unknownname * Added Object types: name exec loop scope * Removed Object type: longinteger (integer is now LONG) * Removed commands: .keystream * Names * Array literals * Local variables * Comments * Re-entrant Execute * Multiple Frames * Robustness * Better error handling Array commands .array i => a % a is a new array of length i .acopy a => b % b is a copy of a .aput a i v => % a[i] ← v .aget a i => v % v = a[i] .astore v1 v2 .. vn a => a % stores into all elements of a .aload a => v1 v2 .. vn a % loads all elements of a .putarray a i b => a % a[i..i+n) ← b[0..n) where n = b.length .subarray a i j => b % b is a name for a[i..i+j) .arrayforall a x => % for each element v of a, push v on stack and execute x .afind a v => i .true % if v matches a[i] => .false % if v does not match any element of a .abind a d => % Dictionary commands % the 'current dictionary' is the dictionary on top of the dictionary stack % the 'current context' is a stack of dictionaries, searched from the top down .dict n => dict % dict is a new dictionary, with initial maxlength n .maxlength dict => n % n is the current maxlength of dict .known dict key => .true % if key is defined in dict => .false % if key is not defined in dict .where key => dict .true % if key is defined in the current context (in dict) => .false % if key is not defined in the current context .put dict key val => % enter [key,val] in dict .get dict key => val % get the definition of key in dict .def key val => % enter [key,val] in the current dictionary .store key val => % if key is known in current context, replace its definition with val % otherwise, do a .def .load key => val % get the definition of key in the current context .del dict key => % delete the definition of key in dict .clrdict dict => % delete all definitions in dict .begin dict => % push dict onto the dictionary stack .end => % pop the dictionary stack .dictforall dict x => % for each tuple in dict, push key and val and execute x .curdict => dict % dict is the top of the dictionary stack .attachdict .detachdict .attachedforall .detachall Local variable commands .lv key val => % push [key,val] on the locals stack .lvload key => val % get the local definition of key .lvknown key => .true % if key has a local definition => .false % if key does not have a local definition .lvstore key val => % if key has a local definition, replace it with val % otherwise, do a .lv .lvforall x => % for each local variable, push key and val and execute x .lvlength => n % n is the current number of local variables .lvmaxlength => n % n is the current maximum number of local variables .lvgrow n => % increase local maxlength by n .fetch key => val % if key is a local name then .lvload else .load .assign key val => % if key is a local name then .lvstore else .store Execution commands .exec x => % execute x .if bool x => % if bool is .true then execute x .ifelse bool x y => % if bool is .true then execute x else execute y .rept n x => % execute x n times .for i j k x => % mumble .loop x => % execute x 'forever' (until a .exit or .stop occurs) .exit => % exit the smallest enclosing loop .stop => % clear the execution stack Math commands .add a b => (a+b) .sub a b => (a-b) .mul a b => (a*b) .div a b => (a/b) % 7 3 .div => 2.333333 result always real .idiv a b => (a/b) % 7 3 .idiv => 2 arguments must be integer! .neg a => (-a) .sin a => sin(a) .cos a => cos(a) .atan a b => arctan(a/b) .exp a => exp(a) .log a => log(a) .sqrt a => sqrt(a) % numeric or string arguments, boolean result: .eq a b => (a=b) .lt a b => (a<b) .gt a b => (a>b) % boolean argument(s) and result: .not a => (NOT a) .and a b => (a AND b) .or a b => (a OR b) .xor a b => (a XOR b) % integer argument(s) and result (32 bits): .bitnot a => BITNOT[a] .bitand a b => BITAND[a,b] .bitor a b => BITOR[a,b] .bitxor a b => BITXOR[a,b] .bitshift a b => BITSHIFT[a,b] % shift left if b>0, right if b<0 Scanning .token src => rem tok .true => .false Stack commands .pop x => % remove the top object .dup x => x x % duplicate the top object .exch x y => y x % exchange the top two objects .copy xm .. x1 x0 n => xm .. x1 x0 xm .. x1 x0 % copy the top n objects .roll y xm .. x1 x0 k n => y x[k-1 MOD n] .. x1 x0 xm .. xk % roll the top n objects by k % if k>0, rolls the kth item 'up' to the top % if k<0, rolls the top item 'down' to the kth .index .. xi .. x1 x0 i => .. xi .. x1 x0 xi % push the ith item from the top .cntstk | x1 x2 .. xn => | x1 x2 .. xn n % count the items on the stack .clrstk | x1 x2 .. xn => | % clear the stack .cnttomrk mark x1 x2 .. xn => mark x1 x2 .. xn n % count the items above the topmost mark .clrtomrk mark x1 x2 .. xn => mark % clear the stack down to the topmost mark .mark => mark % push a mark onto the stack .execstk => array % mumble .dictstk => array % mumble Stream commands .run string => % mumble .bytestream string => stream % mumble .wordstream string => stream % mumble .readitem stream => item % mumble .writeitem stream item => % mumble .readline stream => string % mumble .writebytes stream string => % mumble .killstream stream => % mumble String commands .string .copystring .substring .putstring .sget .sput .search .asearch .cvs .cvis .cvrs .cvos .cvirs Literals .true .false .mark Attributes .length .type .litchk .cvlit .cvx .cvi .cvli .cvr Other .sysdict .reregister .commandname .scopename .print .quit .loadbcd .debugbcd .prompt .version .start .interrupt Errors .undefname .unregistered .rangechk .typechk .limitchk .syntaxerr .stkundflw .stkovrflw .dictundflw .dictovrflw .execovrflw .undefkey .dictfull .attachmentcycle .notattached .undeflv .overflow .badname .badfile .badversion