{File name LispEval.mc Description: DandeLion InterLisp Emulator Eval Author: Charnley Last modified: Charnley 1-May-84 12:05:28 Created: 21-Dec-83 9:48:14 } {- - - - - - - - - - - - - - - - - - - - - - - - - - 54 EVAL 0 0 \EVAL takes single argument ARG If ARG=NIL or T return ARG If ARG= smallp or smallneg return ARG if ARG = FIXP or FLOATP return ARG] If ARG is a list, exit thru AtomEVALFORM{370'b} If ARG is an atom {not NIL or T} attempt free variable lookup: If bound, return value If top value is not NOBIND (atom #1), return top value else ufn-punt else ufn-punt - - - - - - - - - - - - - - - - - - - - - - - - - -} @EVAL: opcode[54'b], Q ← TOSH and 0FF, L2 ← L2.Eval, c1; {set L2 for NewTyp} Ybus ← Q xor smallpl, ZeroBr, L1 ← L1.fixFV, c2; {set L1 for evLookUp} Ybus ← Q xor smallneg, ZeroBr, BRANCH[$, evSmallPl], c3; BRANCH[$, evSmallNeg], c1; uChain ← Q, ZeroBr, c2; {set uChain to 0 for evLookUp} uTOS ← TOS, BRANCH[$, evAtom], c3; {set uTOS to TOS for evLookUp} TT ← 0, CALL[NewTyp], c1; MAR ← [rhRx, Rx + 0], c1, at[L2.Eval, 10, NewTypRet]; PC ← PC - PC16,{undo} c2; Q ← MD and Q, c3; Ybus ← Q xor FixpType, ZeroBr, c1; Ybus ← Q xor FloatpType, ZeroBr, BRANCH[$, evFixp], c2; Ybus ← Q xor ListType, ZeroBr, BRANCH[$, evFloatp], c3; BRANCH[$, evListp], c1; GOTO[ufnX3], c2;{can't deal with} evSmallPl: {simple ret} CANCELBR[IB.pc1], c1; evSmallNeg: {simple ret} GOTO[evFixp], c2; evFixp: {simple ret} CANCELBR[evFloatp], c3; evFloatp: {simple ret} CANCELBR[IB.pc1], c1; evAtom: uName ← TOS, ZeroBr, CANCELBR[$], c1; {set uName to name for evLookUp} Q ← TOS xor KTval, BRANCH[$, evNIL], c2; Ybus ← Q, ZeroBr, L3 ← L3.Eval, c3; {set L3 for evLookUp} uPV ← PV, BRANCH[evLookUp, evT], c1;{set uPV to PV for evLookUp} evNIL: {simple ret} GOTO[evFloatp], c3; evT: {simple ret} GOTO[evNIL], c2; evListp: Rx ← AtomEVALFORM{370'b}, L3{ib's} ← 0, c2; IB ← Rx LRot0, c3; MAR ← Q ← [rhS, S + 1], IBPtr ← 0, GOTO[FN1Ext], c1; evLookUp: { GOTO[ufnX3], c2; EvalLabel:} {free var lookup on tos, which is an atom} { look up variable in current frame; fill in binding pointer (chaining not implemented) This code assumes that NAMETABLE is contiguous in real memory {either it is on the stack, or within a code header which is non-page crossing} on Entry: c1 uTOS restored to TOS if fault uTOSH restored to TOSH if fault PV current frame (point to PV region) Q {uChain} (odd) stack pointer to variable to be looked up (Pv + ib + 1) rhTT, TT virtual address of name table (usually function header) L3 caller's return link at[L3, 10, fvCaller] also used with fvfixup after fault uses during subroutine: rhRx, Rx real address of name table PV frame extension pointers (point to PV region)(travel up alinks) uPV save local PV TOS used uChain TOSH{chain} rhTOSH nRhS {set once at odd time; must be left}{*} used with TOSH{chain} uName TOSH{name} ← [UvCL + T/2 {- UvCL.nlocals} + UvCL.fvaroffset] ntSize, offset, L0, L1 on Return: c1 preserves S, PV, PC, L2, uTOS, uTOSH smashes TOS, TOSH {but preserved in uTOS, uTOSH} rhTT, TT virtual address of free value @(chain) filled in binding pointer L1 binding type{fvStack, fvGlobal} Dispatch pending on Fault: TOS ← uTOS, TOSH ← uTOSH, PV ← uPV } uTOSH ← TOSH, c2; TOSH ← TOS, CALL[fvFF], c3;{start search at current frame} EvalGet: Map ← [rhTT, TT], CANCELBR[$, 0F], c1, at[L3.Eval, 10, fvCaller]; L1 ← L1.fixFV, c2; Rx ← rhRx ← MD, XRefBr, c3; MAR ← [rhRx, TT + 0], BRANCH[EvalMap, $], c1, at[L0.RedoEval, 10, RMapFixCaller]; , c2; TOSH ← MD, c3; MAR ← [rhRx, TT + 1], c1; L3Disp, CANCELBR[$, 2], c2; TOS ← MD, RET[EvalGetRet], c3; Ybus ← TOSH, ZeroBr, c1, at[L3.Eval, 10, EvalGetRet]; Ybus ← TOS xor 1, ZeroBr, BRANCH[$, evalTosh0], c2; CANCELBR[$], c3; evalEND: PC ← PC + PC16, GOTO[IB.nop], c1; evalTosh0: BRANCH[$, evalUnbound], c3; PC ← PC + PC16, GOTO[IB.nop], c1; evalUnbound: GOTO[ufnZ2], c1; PV ← uPV, GOTO[NoFixes], c3, at[L3.Eval, 10, fvfixup]; EvalMap: GOTO[RLMapFix], L0 ← L0.RedoEval, c2; { E N D }