-- JaMStackImpl.mesa -- Original version by John Warnock, December 1978. -- Last changed by Bill Paxton, January 21, 1:09 PM -- Last changed by Doug Wyatt, 7-Oct-81 11:07:22 DIRECTORY JaMBasic USING [Object], JaMInternal USING [Frame, Node, NodeSequence, Stack, StackRecord], JaMOps USING [APut, Array, Error, Install, InstallReason, MakeName, nullOb, Overflow, Pop, PopCardinal, PopInteger, Push, PushCardinal, rangechk, RegisterExplicit, StackOverflow, Top, Underflow], JaMStorage USING [Zone], Inline USING [LowHalf]; JaMStackImpl: MONITOR IMPORTS JaMOps, JaMStorage, Inline EXPORTS JaMOps = { OPEN JaMOps, JaMInternal, JaMBasic; -- Globals zone: UNCOUNTED ZONE = JaMStorage.Zone[]; stkundflw,stkovrflw: name Object; -- Error handling Underflow: PUBLIC PROC[stack: Stack] = { ERROR Error[stkundflw] }; Overflow: PUBLIC PROC[stack: Stack] = { ERROR StackOverflow[stack] }; Restore: PUBLIC PROC[stack: Stack, mark: Node] = { -- try to restore the stack so that mark is the head of the free list -- first, be sure the marked node is in the free list FOR node: Node _ stack.free, node.next UNTIL node=NIL DO IF node=mark THEN EXIT; REPEAT FINISHED => RETURN; -- not found ENDLOOP; -- move nodes from the free list back onto the stack UNTIL stack.free=mark DO node: Node _ stack.free; stack.free _ node.next; node.next _ stack.head; stack.head _ node; ENDLOOP; }; -- Stack allocation NewStack: PUBLIC PROC[n: CARDINAL] RETURNS[Stack] = { nodes: LONG POINTER TO NodeSequence _ zone.NEW[NodeSequence[n]]; stack: Stack _ zone.NEW[StackRecord _ [head: NIL, free: NIL, nodes: nodes]]; FOR i: CARDINAL IN[0..n) DO node: Node _ @nodes[i]; node^ _ [next: stack.free, ob: nullOb]; stack.free _ node; ENDLOOP; RETURN[stack]; }; FreeStack: PUBLIC PROC[stack: Stack] = { zone.FREE[@stack.nodes]; zone.FREE[@stack]; }; -- Stack operations Dup: PUBLIC PROC[stack: Stack] = { ob: Object _ Top[stack]; Push[stack,ob] }; Exch: PUBLIC PROC[stack: Stack] = { ob1: Object _ Pop[stack]; ob2: Object _ Pop[stack]; Push[stack,ob1]; Push[stack,ob2] }; -- Returns MIN[,max] Count: PROC[head: Node, max: CARDINAL _ LAST[CARDINAL]] RETURNS[CARDINAL] = INLINE { FOR i: CARDINAL IN[0..max) DO IF head=NIL THEN RETURN[i] ELSE head _ head.next; ENDLOOP; RETURN[max] }; -- Copy the top n entries Copy: PUBLIC PROC[stack: Stack, n: CARDINAL] = { head: Node _ NIL; -- will be new head of stack last: LONG POINTER TO Node _ @head; -- last link field temp: Node _ stack.head; IF n=0 THEN RETURN; IF Count[stack.head,n] { stkundflw _ MakeName[".stkundflw"L]; stkovrflw _ MakeName[".stkovrflw"L]; RegisterExplicit[frame, ".pop"L, JPop]; RegisterExplicit[frame, ".exch"L, JExch]; RegisterExplicit[frame, ".dup"L, JDup]; RegisterExplicit[frame, ".clrstk"L, JClrStk]; RegisterExplicit[frame, ".copy"L, JCopy]; RegisterExplicit[frame, ".roll"L, JRoll]; RegisterExplicit[frame, ".cntstk"L, JCntStk]; RegisterExplicit[frame, ".cnttomrk"L, JCntToMrk]; RegisterExplicit[frame, ".clrtomrk"L, JClrToMrk]; RegisterExplicit[frame, ".mark"L, JMark]; RegisterExplicit[frame, ".index"L, JIndex]; RegisterExplicit[frame, ".execstk"L, JExecStk]; RegisterExplicit[frame, ".dictstk"L, JDictStk]; }; ENDCASE; }; Install[InstallStack]; }.