DIRECTORY JaM USING [AGet, Any, Array, Command, ErrorType, ExecuteRope, Load, Op, Pop, PopBool, PopInt, Push, PushInt, ROPE, State, AtomToRope], Rope USING [ROPE, Concat], IO USING [PutRope], Process USING [priorityBackground, priorityNormal, SetPriority, Yield], JaMPrimitives USING []; JaMExecImpl: CEDAR PROGRAM IMPORTS JaM, IO, Process, Rope EXPORTS JaM, JaMPrimitives = BEGIN OPEN JaM; Error: PUBLIC ERROR[type: ErrorType, msg: Rope.ROPE _ NIL] = CODE; Exit: PUBLIC ERROR = CODE; Stop: PUBLIC ERROR = CODE; ExecuteCommand: PROC[self: State, command: Command] = INLINE { command.proc[self] }; ExecuteOp: PROC[self: State, op: Op] = INLINE { ExecuteAny[self, op.body] }; ExecuteAtom: PROC[self: State, atom: ATOM] = INLINE { Execute[self, Load[self, atom]] }; GetKeyName: PROC[x: Any] RETURNS [ROPE] = { WITH x SELECT FROM x: ATOM => RETURN [AtomToRope[x]]; x: Command => RETURN [AtomToRope[x.name]]; ENDCASE => RETURN [""]; }; Execute: PUBLIC PROC[self: State, x: Any] = { DoIt: PROC = { IF self.aborted THEN {self.aborted _ FALSE; ERROR Stop}; WITH x SELECT FROM x: ATOM => ExecuteAtom[self, x]; x: Command => ExecuteCommand[self, x]; x: Op => ExecuteOp[self, x]; ENDCASE => Push[self, x]; }; DoIt [! Error => { rope: ROPE _ IF msg#NIL THEN msg ELSE SELECT type FROM AttachmentCycle => "attachment cycle", BoundsFault => "bounds fault", DictionaryUnderflow => "dictionary underflow", InvalidArgs => "invalid arguments", LoadFailed => "load failed", NotAttached => "not attached", NumericOverflow => "numeric overflow", OpenFailed => "open failed", StackOverflow => "stack overflow", StackUnderflow => "stack underflow", UndefinedKey => Rope.Concat["undefined key: ", GetKeyName[x]], Unimplemented => "unimplemented", WrongMark => "wrong mark", WrongType => "wrong type", ENDCASE => "unknown error"; self.out.PutRope[rope]; self.out.PutRope["\n"]; ERROR Stop; }]; Process.Yield[]; --to help abort infinite loops }; ExecuteAny: PROC[self: State, x: Any] = { WITH x SELECT FROM x: ATOM => ExecuteAtom[self, x]; x: Command => ExecuteCommand[self, x]; x: Op => ExecuteOp[self, x]; x: Array => ExecuteArray[self, x]; x: ROPE => ExecuteRope[self, x]; ENDCASE => Push[self, x]; }; ExecuteArray: PROC[self: State, array: Array] = { FOR i: INT IN[0..array.length) DO Execute[self, AGet[array, i]]; ENDLOOP; }; GetAbort: PUBLIC PROC[self: State] RETURNS[BOOL] = { RETURN[self.aborted] }; SetAbort: PUBLIC PROC[self: State, b: BOOL] = { self.aborted _ b }; ApplyStop: PUBLIC PROC[self: State] = { ERROR Stop; }; ApplyExec: PUBLIC PROC[self: State] = { Execute[self, Pop[self]]; }; ApplyIf: PUBLIC PROC[self: State] = { x: Any = Pop[self]; b: BOOL = PopBool[self]; IF b THEN Execute[self, x]; }; ApplyIfElse: PUBLIC PROC[self: State] = { xF: Any = Pop[self]; xT: Any = Pop[self]; b: BOOL = PopBool[self]; Execute[self, IF b THEN xT ELSE xF]; }; ApplyRept: PUBLIC PROC[self: State] = { x: Any = Pop[self]; n: INT = PopInt[self]; THROUGH [0..n) DO Execute[self, x ! Exit => EXIT] ENDLOOP; }; ApplyFor: PUBLIC PROC[self: State] = { x: Any = Pop[self]; k: INT = PopInt[self]; j: INT = PopInt[self]; i: INT = PopInt[self]; IF j>=0 THEN FOR n: INT _ i, n+j UNTIL n>k DO PushInt[self, n]; Execute[self, x ! Exit => EXIT]; ENDLOOP ELSE FOR n: INT _ i, n+j UNTIL n EXIT]; ENDLOOP; }; ApplyLoop: PUBLIC PROC[self: State] = { x: Any = Pop[self]; DO Execute[self, x ! Exit => EXIT] ENDLOOP; }; ApplyExit: PUBLIC PROC[self: State] = { ERROR Exit; }; ApplyNicePriority: PUBLIC PROC[self: JaM.State] = { nice: BOOL = JaM.PopBool[self]; Process.SetPriority[IF nice THEN Process.priorityBackground ELSE Process.priorityNormal]; }; END. DJaMExecImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Original version by John Warnock, January, 1978. Bill Paxton, 29-Jan-82 15:45:10 Maureen Stone February 6, 1984 5:13:11 pm PST Doug Wyatt, March 18, 1985 2:52:41 pm PST Michael Plass, August 15, 1985 11:09:16 am PDT Errors IF self.stepping THEN { self.stepping _ FALSE; Push[self, x]; ExecuteName[self, $.step]; self.stepping _ TRUE; }; "Stop" clears the execution stack and returns to the caller of the outermost instance of Execute. "Exec" executes the object on top of the operand stack. "If" is the implementation of the testing instruction. Two operands are required: an Object and a Boolean. If the Boolean is TRUE then the object is executed otherwise the object is popped. "IfElse" is the implementation of the two way conditional execution instruction. Three operands are required: Object1,Object2, and a Boolean. If the Boolean is TRUE then Object2 is executed otherwise Object1 is executed. "Rept" is the "loop for count" instruction. Two operands are required: an integer and an Object. The Object is executed for the number of times indicated by the integer. (0 for Negative). "For" is based on the Algol "for n _ i step j until k do" instruction. Four operands are required: three IntegerTypes and an Object. The Object is executed for each iteration, with the current loop index on the operand stack. "Loop" is the "loop forever" instruction. One operand is required: The Object is executed until an ".exit" command is executed. "Exit" pops the execution stack until the innermost loop is terminated. Κ‡˜codešœ™Kšœ Οmœ1™˜>Kšœ!˜!Kšœ˜Kšœ˜Kšžœ˜—Kšœ˜Kšœ˜Kšžœ˜ K˜—KšœΟc˜/šœ™Kšœ™K™)Kšœ™K™—K˜K˜—š  œžœ˜)šžœžœž˜Kšœžœ˜ K˜&K˜K˜"Kšœžœ˜ Kšžœ˜—K˜K˜—š  œžœ˜1šžœžœžœž˜!K˜Kšžœ˜—K˜K˜—Kš  œžœžœžœžœžœ˜LKš œžœžœžœ˜CK˜Kšœ;™;Kšœ%™%K˜š  œžœžœ˜'Kšžœ˜ K˜K˜—Kšœ7™7K˜š  œžœžœ˜'Kšœ˜K˜K˜—Kšœ6™6Kšœ:™:Kšœ:™:Kšœ™K˜š œžœžœ˜%Kšœ˜Kšœžœ˜Kšžœžœ˜K˜K˜—KšœC™CKšœJ™JKšœE™EKšœ ™ K˜š  œžœžœ˜)Kšœ˜Kšœ˜Kšœžœ˜Kšœžœžœžœ˜$K˜K˜—KšœF™FKšœ?™?Kšœ4™4K˜š  œžœžœ˜'Kšœ˜Kšœžœ˜Kšžœžœžœžœ˜:K˜K˜—KšœF™FKšœ=™=KšœI™IKšœ™K˜š œžœžœ˜&Kšœ˜Kšœžœ˜Kšœžœ˜Kšœžœ˜š žœžœžœžœ žœž˜-Kšœ,žœ˜2Kšž˜—š žœžœžœ žœž˜%Kšœ,žœ˜2Kšžœ˜—K˜K˜—KšœB™BKšœ<™