JaM.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Maureen Stone January 26, 1984 5:40:32 pm PST
Doug Wyatt, March 18, 1985 2:50:41 pm PST
DIRECTORY
IO USING [STREAM],
Rope USING [ROPE];
JaM: CEDAR DEFINITIONS
= BEGIN
Types
ROPE: TYPE = Rope.ROPE;
STREAM: TYPE = IO.STREAM;
State: TYPE = REF StateRep;
StateRep:
TYPE =
RECORD[
aborted: BOOL ← FALSE,
stack: Stack, -- the operand stack
dictstk: LIST OF Dict, -- the dictionary stack
out: STREAM -- output stream, for .print
];
Stack: TYPE = REF StackRep;
StackRep: TYPE;
Any: TYPE = REF ANY;
Command: TYPE = REF CommandRep;
CommandRep: TYPE = RECORD[name: ATOM, proc: PROC[State]];
Op: TYPE = REF OpRep;
OpRep: TYPE = RECORD[body: Any];
Dict: TYPE = REF DictRep;
DictRep: TYPE = RECORD[impl: REF DictImplRep, attach: LIST OF Dict];
DictImplRep: TYPE;
Array: TYPE = REF ArrayRep;
ArrayRep: TYPE = RECORD[start, length: NAT, seq: Sequence];
Sequence: TYPE = REF SequenceRep;
SequenceRep: TYPE = RECORD[SEQUENCE size: NAT OF Any];
Mark: TYPE = REF MarkRep;
MarkRep: TYPE = RECORD[m: INT];
Creating a new interpreter
Create: PROC[out: STREAM] RETURNS[State];
Stack operations
NewStack: PROC RETURNS[Stack];
Push: PROC[self: State, x: Any];
PushBool: PROC[self: State, x: BOOL];
PushInt: PROC[self: State, x: INT];
PushReal: PROC[self: State, x: REAL];
PushRope: PROC[self: State, x: ROPE] = INLINE { Push[self, x] };
PushStream: PROC[self: State, x: STREAM] = INLINE { Push[self, x] };
PushArray: PROC[self: State, x: Array] = INLINE { Push[self, x] };
PushDict: PROC[self: State, x: Dict] = INLINE { Push[self, x] };
Pop: PROC[self: State] RETURNS[Any];
PopBool: PROC[self: State] RETURNS[BOOL];
PopInt: PROC[self: State] RETURNS[INT];
PopReal: PROC[self: State] RETURNS[REAL];
PopRope: PROC[self: State] RETURNS[ROPE];
PopStream: PROC[self: State] RETURNS[STREAM];
PopArray: PROC[self: State] RETURNS[Array];
PopDict: PROC[self: State] RETURNS[Dict];
Copy: PROC[self: State, n: INT];
Roll: PROC[self: State, n, k: INT];
Index: PROC[self: State, i: INT] RETURNS[Any];
Count: PROC[self: State] RETURNS[INT];
PushMark: PROC[self: State, m: INT ← 0];
PopMark: PROC[self: State, m: INT ← 0];
CountToMark: PROC[self: State, m: INT ← 0] RETURNS[INT];
Array operations
NewArray: PROC[length: INT] RETURNS[Array];
MakeArray: PROC[self: State, length: INT] RETURNS[Array];
SubArray: PROC[array: Array, start, length: INT] RETURNS[Array];
PutArray: PROC[from: Array, start: INT, into: Array];
APut: PROC[array: Array, i: INT, x: Any];
AGet: PROC[array: Array, i: INT] RETURNS[Any];
AFind: PROC[array: Array, x: Any] RETURNS[found: BOOL, i: INT];
ABind:
PROC[array: Array, dict: Dict];
Dictionary operations
sysDict: Dict;
NewDict: PROC[length: INT] RETURNS[Dict];
DictLength: PROC[dict: Dict] RETURNS[INT];
Put: PROC[dict: Dict, key, val: Any];
TryToGet: PROC[dict: Dict, key: Any] RETURNS[found: BOOL, val: Any];
Get: PROC[dict: Dict, key: Any] RETURNS[Any];
Del: PROC[dict: Dict, key: Any];
AttachDict: PROC[dict, adict: Dict];
DetachDict: PROC[dict, adict: Dict];
DetachAll: PROC[dict: Dict];
Def: PROC[self: State, key, val: Any];
Store: PROC[self: State, key, val: Any];
TryToLoad: PROC[self: State, key: Any] RETURNS[found: BOOL, val: Any];
Load: PROC[self: State, key: Any] RETURNS[Any];
Where: PROC[self: State, key: Any] RETURNS[found: BOOL, where: Dict];
Begin: PROC[self: State, dict: Dict];
End: PROC[self: State];
Atoms
AtomToRope: PROC[ATOM] RETURNS[ROPE];
RopeToAtom: PROC[ROPE] RETURNS[ATOM];
Key comparison
Equal: PROC[a, b: Any] RETURNS[BOOL];
Eq: PROC[a, b: Any] RETURNS[BOOL] = INLINE { RETURN[IF a=b THEN TRUE ELSE Equal[a, b]] };
JaM will raise Error if any problems are encountered. The main execution loop converters these errors to ropes and prints them on the state.out stream since the main client of these procedures is the JaM typescript. It then raises the ERROR Stop. All clients of ExecuteRope and Execute may see the error Stop. If you are the top level procedure, it is adequate to immediately continue ie: Execute[state, any ! Stop => CONTINUE].
Scanning
ExecuteRope: PROC[self: State, rope: ROPE];
LineComplete: PROC[text: ROPE] RETURNS[BOOL];
Execution
Execute: PROC[self: State, x: Any];
GetAbort: PROC[self: State] RETURNS[BOOL];
SetAbort: PROC[self: State, b: BOOL];
Errors
ErrorType: TYPE = {AttachmentCycle, BoundsFault, DictionaryUnderflow, InvalidArgs, LoadFailed, NotAttached, NumericOverflow, OpenFailed, StackOverflow, StackUnderflow, UndefinedKey, Unimplemented, WrongMark, WrongType};
Error: ERROR[type: ErrorType, msg: Rope.ROPE ← NIL];
Exit: ERROR;
Stop: ERROR;
Registration (JaMControlImpl)
There is a global list of names and initialization procedures kept in sysDict called .initprocs. Each program that wants to register commands with JaM should register an initialization procedure and a unique name (capitalization counts).
There is a separate JaM dictionary for each typescript. To register commands in a particular dictionary execute (name) .callinit. This calls the named initialization proc with the correct JaM State.
Note: you can create your own State independent of the typescripts by using JaM.Create. You can then register commands in that dictionary directly or simulate the typescript mechanism with ExecuteRope[state, "(name) .callinit \n"];
RegisterInit:
PROC[name:
ROPE, init:
PROC[State]];
Register a name and an initialization proc that does all the calls to Register (below)
Suggestion: make the name your module name
Register:
PROC[self: State, name:
ROPE, proc:
PROC[State]];
put all your calls to Register in your initialization proc (above)
END.