DIRECTORY Basics USING [LowHalf], JaMBasic USING [Object, Tuple], JaMInternal USING [Frame, Locals, LocalsRecord, Node, Stack, TupleSequence], JaMOps USING [Assert, Equal, Error, Install, InstallReason, KeyName, limitchk, Load, MakeName, MarkLoop, nullOb, Pop, PopCardinal, PopInteger, Push, PushBoolean, PushCardinal, rangechk, RegisterExplicit, RegisterInternal, Store, Top, UnmarkLoop], JaMStorage USING [Zone]; JaMLocalImpl: PROGRAM IMPORTS Basics, JaMOps, JaMStorage EXPORTS JaMOps = { OPEN JaMOps, JaMInternal, JaMBasic; initLocalsSize: CARDINAL = 20; maxlenLimit: CARDINAL = LAST[CARDINAL]; zone: UNCOUNTED ZONE = JaMStorage.Zone[]; undeflv: name Object; lfacmd: command Object; IsLocal: PROC[key: Object] RETURNS[BOOLEAN] = INLINE { RETURN[WITH key:key SELECT FROM name => key.id.local, ENDCASE => FALSE] }; Fetch: PROC[frame: Frame] = { key: Object _ Pop[frame.opstk]; val: Object _ IF IsLocal[key] THEN LoadLocal[frame,key] ELSE Load[frame,key]; Push[frame.opstk,val]; }; Assign: PROC[frame: Frame] = { val: Object _ Pop[frame.opstk]; key: Object _ Pop[frame.opstk]; IF IsLocal[key] THEN StoreLocal[frame,key,val] ELSE Store[frame,key,val]; }; LoadLocal: PUBLIC PROC[frame: Frame, key: Object] RETURNS[Object] = { known: BOOLEAN; ob: Object; [known, ob] _ TryToLoadLocal[frame, key]; IF known THEN RETURN[ob] ELSE ERROR Error[undeflv]; }; TryToLoadLocal: PUBLIC PROC[frame: Frame, key: Object] RETURNS[BOOLEAN,Object] = { locals: Locals _ frame.locals; name: Object _ KeyName[key]; FOR i: CARDINAL DECREASING IN[0..locals.curlen) DO tuple: Tuple _ locals.array[i]; IF Equal[tuple.key,name] THEN RETURN[TRUE,tuple.value]; ENDLOOP; RETURN[FALSE,nullOb]; }; DefineLocal: PUBLIC PROC[frame: Frame, key,value: Object] = { locals: Locals _ frame.locals; tuple: Tuple _ [KeyName[key],value]; i: CARDINAL _ locals.curlen; IF i>=locals.maxlen THEN GrowLocals[locals,locals.maxlen/2]; Assert[ioldmax THEN ERROR Error[limitchk]; new _ zone.NEW[TupleSequence[newmax]]; FOR i: CARDINAL IN[0..oldmax) DO new[i] _ old[i] ENDLOOP; locals.array _ new; locals.maxlen _ newmax; zone.FREE[@old]; }; LvLoad: PROC[frame: Frame] = { key: Object _ Pop[frame.opstk]; val: Object _ LoadLocal[frame,key]; Push[frame.opstk,val]; }; LvKnown: PROC[frame: Frame] = { key: Object _ Pop[frame.opstk]; known: BOOLEAN; [known,] _ TryToLoadLocal[frame,key]; PushBoolean[frame.opstk, known]; }; LvDefine: PROC[frame: Frame] = { val: Object _ Pop[frame.opstk]; key: Object _ Pop[frame.opstk]; DefineLocal[frame,key,val]; }; LvStore: PROC[frame: Frame] = { val: Object _ Pop[frame.opstk]; key: Object _ Pop[frame.opstk]; StoreLocal[frame,key,val]; }; LvMaxLength: PROC[frame: Frame] = { locals: Locals _ frame.locals; PushCardinal[frame.opstk, locals.maxlen]; }; LvLength: PROC[frame: Frame] = { locals: Locals _ frame.locals; PushCardinal[frame.opstk, locals.curlen]; }; LvGrow: PROC[frame: Frame] = { inc: LONG INTEGER _ PopInteger[frame.opstk]; IF inc <= 0 THEN RETURN; IF inc>LAST[CARDINAL] THEN ERROR Error[rangechk]; GrowLocals[frame.locals, Basics.LowHalf[inc]]; }; LvForAll: PUBLIC PROC[frame: Frame] = { locals: Locals _ frame.locals; ob: Object _ Pop[frame.opstk]; MarkLoop[frame]; Push[frame.execstk, ob]; PushCardinal[frame.execstk, locals.curlen]; LvFAProc[frame]; }; LvFAProc: PROC[frame: Frame] = { lv: CARDINAL _ PopCardinal[frame.execstk]; ob: Object _ Top[frame.execstk]; locals: Locals _ frame.locals; IF (lv _ MIN[lv,locals.maxlen])>0 THEN { i: CARDINAL _ lv - 1; tuple: Tuple _ locals.array[i]; Push[frame.opstk,tuple.key]; Push[frame.opstk,tuple.value]; PushCardinal[frame.execstk, i]; Push[frame.execstk, lfacmd]; Push[frame.execstk, ob]; } ELSE { [] _ Pop[frame.execstk]; -- remove object UnmarkLoop[frame]; -- remove mark }; }; InstallLocal: PROC[why: InstallReason, frame: Frame] = { SELECT why FROM register => { undeflv _ MakeName[".undeflv"L]; lfacmd _ RegisterInternal["@lvforall"L, LvFAProc]; RegisterExplicit[frame, ".lvload"L, LvLoad]; RegisterExplicit[frame, ".lvknown"L, LvKnown]; RegisterExplicit[frame, ".lv"L, LvDefine]; RegisterExplicit[frame, ".lvstore"L, LvStore]; RegisterExplicit[frame, ".lvforall"L, LvForAll]; RegisterExplicit[frame, ".lvlength"L, LvLength]; RegisterExplicit[frame, ".lvmaxlength"L, LvMaxLength]; RegisterExplicit[frame, ".lvgrow"L, LvGrow]; RegisterExplicit[frame, ".fetch"L, Fetch]; RegisterExplicit[frame, ".assign"L, Assign]; }; ENDCASE; }; Install[InstallLocal]; }. œJaMLocalImpl.mesa Doug Wyatt, 7-Oct-81 17:14:10 Russ Atkinson, July 22, 1983 6:20 pm Constants Globals Procedures for local/global variables does load local or dictionary load does store local or dictionary store Procedures for local variables generates undeflv if not known Intrinsics pushes current max available for locals pushes current number of locals increases max available for locals by amount from opstk Expects opstk: (object) For each pair in locals put (name)(value) onto opstk and execute object Returns opstk: () save them on exec stack prime state start it set up opstk set up execstk and let it happen Initialization Local variable commands Ê”˜šœ™Jšœ™J™$—J˜šÏk ˜ Jšœœ ˜Jšœ œ˜Jšœ œ;˜Lšœ˜ Jšœé˜é—Jšœ œ˜J˜—šœ˜Jšœ˜"Jšœ ˜Jšœ˜#J˜—šœ ™ J˜Jšœœ˜Jšœ œœœ˜'J˜—šœ™J˜Jšœ œœ˜)J˜J˜J˜J˜—Jšœ&™&J˜š Ïnœœœœœ˜6Jš œœ œœœœ˜JJ˜—šžœœ˜Jšœ"™"J˜Jšœœœœ˜MJ˜J˜J˜—šžœœ˜Jšœ$™$J˜J˜Jšœœœ˜IJ˜J˜—Jšœ™J˜šž œœœœ ˜EJšœ™Jšœœ ˜J˜)Jš œœœœœ˜3J˜J˜—š žœœœœœ ˜RJ˜J˜š œœ œœ˜2J˜Jšœœœœ˜7Jšœ˜—Jšœœ ˜J˜J˜—šž œœœ%˜=J˜J˜$Jšœœ˜Jšœœ$˜