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 [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]] }; 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: ", AtomToRope[NARROW[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; }; END. äJaMExecImpl.mesa Last edited by: Original version by John Warnock, January, 1978. Bill Paxton, 29-Jan-82 15:45:10 Doug Wyatt, August 24, 1983 3:21 pm Maureen Stone February 6, 1984 5:13:11 pm PST 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. Êò˜Jšœ™J™™Jšœ0™0Jšœ™Jšœ#™#J™-—J˜šÏk ˜ Jšœœdœ˜†Jšœœœ ˜Jšœœ ˜Jšœœ ˜Jšœœ˜J˜—Jšœ œ˜Jšœ˜Jšœ˜Jšœœœ˜J˜Jšœ™J˜Jš œœœœœœ˜BJšœœœœ˜Jšœœœœ˜J˜šÏnœœ"œ˜TJ˜—Jšž œœœ˜LJ˜šž œœœœ%˜XJ˜—šžœœœ˜-šžœœ˜Jšœœœœ˜8šœœ˜Jšœœ˜ J˜&J˜Jšœ˜—J˜—šœ˜Jš œœœœœ˜ šœœ˜Jšœ&˜&Jšœ˜Jšœ.˜.Jšœ#˜#Jšœ˜Jšœ˜Jšœ&˜&Jšœ˜Jšœ"˜"Jšœ$˜$Jšœ:œ˜FJšœ!˜!Jšœ˜Jšœ˜Jšœ˜—Jšœ˜Jšœ˜Jšœ˜ J˜—JšœÏc˜/šœœ™Jšœœ™J™)Jšœœ™J™—J˜J˜—šž œœ˜)šœœ˜Jšœœ˜ J˜&J˜J˜"Jšœœ˜ Jšœ˜—J˜J˜—šž œœ˜1šœœœ˜!J˜Jšœ˜—J˜J˜—Jš žœœœœœœ˜LJšžœœœœ˜CJ˜Jšœ;™;Jšœ%™%J˜šž œœœ˜'Jšœ˜ J˜J˜—Jšœ7™7J˜šž œœœ˜'Jšœ˜J˜J˜—Jšœ6™6Jšœ:™:Jšœ:™:Jšœ™J˜šžœœœ˜%Jšœ˜Jšœœ˜Jšœœ˜J˜J˜—JšœC™CJšœJ™JJšœE™EJšœ ™ J˜šž œœœ˜)Jšœ˜Jšœ˜Jšœœ˜Jšœœœœ˜$J˜J˜—JšœF™FJšœ?™?Jšœ4™4J˜šž œœœ˜'Jšœ˜Jšœœ˜Jšœœœœ˜:J˜J˜—JšœF™FJšœ=™=JšœI™IJšœ™J˜šžœœœ˜&Jšœ˜Jšœœ˜Jšœœ˜Jšœœ˜š œœœœ œ˜-Jšœ,œ˜2Jš˜—š œœœ œ˜%Jšœ,œ˜2Jšœ˜—J˜J˜—JšœB™BJšœ<™