JaMStackImpl.mesa
Last edited by:
Doug Wyatt, August 24, 1983 5:51 pm
Maureen Stone February 2, 1984 5:03:06 pm PST
DIRECTORY
JaM USING [Any, Array, AtomToRope, Dict, Error, Mark, MarkRep, ROPE, STREAM, State],
JaMPrimitives USING [],
Real USING [Fix, RealException];
JaMStackImpl: CEDAR PROGRAM
IMPORTS JaM, Real
EXPORTS JaM, JaMPrimitives
= BEGIN OPEN JaM;
Node: TYPE = REF NodeRep;
NodeRep: TYPE = RECORD[x: Any, next: Node];
Stack: TYPE = REF StackRep;
StackRep: PUBLIC TYPE = RECORD[
depth: INT, -- number of items in the stack
top: Node
];
max: INT = 1000; -- maximum stack depth
NewStack: PUBLIC PROC RETURNS[Stack] = {
RETURN[NEW[StackRep ← [depth: 0, top: NIL]]];
};
Push: PUBLIC PROC[self: State, x: Any] = {
stack: Stack = self.stack;
IF stack.depth<max THEN {
node: Node = NEW[NodeRep ← [x, stack.top]];
stack.top ← node;
stack.depth ← stack.depth+1;
}
ELSE ERROR Error[StackOverflow];
};
Pop: PUBLIC PROC[self: State] RETURNS[x: Any] = {
stack: Stack = self.stack;
IF stack.depth>0 THEN {
node: Node = stack.top;
[x, stack.top] ← node^;
stack.depth ← stack.depth-1;
}
ELSE ERROR Error[StackUnderflow];
};
IntToReal: PROC[i: INT] RETURNS[REAL] = INLINE { RETURN[i] };
RealToInt: PROC[r: REAL] RETURNS[INT] = {
Fix: PROC[r: REAL] RETURNS[INT] = { RETURN[Real.Fix[r]] };
Wrap a procedure call around Real.Fix so we can catch RealException
i: INT = Fix[r ! Real.RealException => GOTO Fail];
IF i=r THEN RETURN[i] ELSE GOTO Fail;
EXITS Fail => ERROR Error[WrongType];
};
PushBool: PUBLIC PROC[self: State, x: BOOL] = {
PushInt[self, IF x THEN 1 ELSE 0]
};
PushInt: PUBLIC PROC[self: State, x: INT] = {
Push[self, NEW[INT ← x]];
};
PushReal: PUBLIC PROC[self: State, x: REAL] = {
Push[self, NEW[REAL ← x]]
};
PopBool: PUBLIC PROC[self: State] RETURNS[BOOL] = {
RETURN[PopInt[self]#0];
};
PopInt: PUBLIC PROC[self: State] RETURNS[INT] = {
x: Any = Pop[self];
WITH x SELECT FROM
x: REF INT => RETURN[x^];
x: REF REAL => RETURN[RealToInt[x^]];
ENDCASE => ERROR Error[WrongType];
};
PopReal: PUBLIC PROC[self: State] RETURNS[REAL] = {
x: Any = Pop[self];
WITH x SELECT FROM
x: REF INT => RETURN[IntToReal[x^]];
x: REF REAL => RETURN[x^];
ENDCASE => ERROR Error[WrongType];
};
PopRope: PUBLIC PROC[self: State] RETURNS[ROPE] = {
WITH Pop[self] SELECT FROM
x: ROPE => RETURN[x];
x: ATOM => RETURN[AtomToRope[x]];
ENDCASE => ERROR Error[WrongType];
};
PopStream: PUBLIC PROC[self: State] RETURNS[STREAM] = {
WITH Pop[self] SELECT FROM x: STREAM => RETURN[x];
ENDCASE => ERROR Error[WrongType];
};
PopArray: PUBLIC PROC[self: State] RETURNS[Array] = {
WITH Pop[self] SELECT FROM x: Array => RETURN[x];
ENDCASE => ERROR Error[WrongType];
};
PopDict: PUBLIC PROC[self: State] RETURNS[Dict] = {
WITH Pop[self] SELECT FROM x: Dict => RETURN[x];
ENDCASE => ERROR Error[WrongType];
};
Copy: PUBLIC PROC[self: State, n: INT] = {
Copy the top n entries on the stack.
stack: Stack = self.stack;
depth: INT = stack.depth;
IF n<0 THEN ERROR Error[InvalidArgs]
ELSE IF n>depth THEN ERROR Error[StackUnderflow]
ELSE IF n>(max-depth) THEN ERROR Error[StackOverflow]
ELSE {
head, tail: Node ← NIL;
node: Node ← stack.top;
THROUGH [0..n) DO
new: Node = NEW[NodeRep ← node^];
IF head=NIL THEN head ← new ELSE tail.next ← new;
tail ← new; node ← node.next;
ENDLOOP;
IF head#NIL THEN { tail.next ← stack.top; stack.top ← head };
stack.depth ← stack.depth+n;
};
};
Roll: PUBLIC PROC[self: State, n, k: INT] = {
stack: Stack = self.stack;
depth: INT = stack.depth;
IF k<0 THEN k ← n+k;
IF n<0 OR k<0 OR k>n THEN Error[InvalidArgs]
ELSE IF n>depth THEN ERROR Error[StackUnderflow]
ELSE IF n#0 AND k#0 AND k#n THEN {
kth, nth: Node ← NIL;
node: Node ← stack.top;
THROUGH [0..k) DO kth ← node; node ← node.next ENDLOOP;
THROUGH [k..n) DO nth ← node; node ← node.next ENDLOOP;
nth.next ← stack.top;
stack.top ← kth.next;
kth.next ← node;
};
};
Count: PUBLIC PROC[self: State] RETURNS[INT] = {
stack: Stack = self.stack;
RETURN[stack.depth];
};
Index: PUBLIC PROC[self: State, i: INT] RETURNS[Any] = {
stack: Stack = self.stack;
ERROR Error[Unimplemented];
};
PushMark: PUBLIC PROC[self: State, m: INT ← 0] = {
Push[self, NEW[MarkRep ← [m]]];
};
PopMark: PUBLIC PROC[self: State, m: INT ← 0] = {
WITH Pop[self] SELECT FROM
x: Mark => IF x.m#m THEN ERROR Error[WrongMark];
ENDCASE => ERROR Error[WrongType];
};
CountToMark: PUBLIC PROC[self: State, m: INT ← 0] RETURNS[INT] = {
stack: Stack = self.stack;
depth: INT = stack.depth;
node: Node ← stack.top;
FOR i: INT IN[0..depth) DO
WITH node.x SELECT FROM
x: Mark => IF x.m=m THEN RETURN[i] ELSE ERROR Error[WrongMark];
ENDCASE;
node ← node.next;
ENDLOOP;
RETURN[depth];
};
ApplyPop: PUBLIC PROC[self: State] = {
[] ← Pop[self];
};
ApplyCopy: PUBLIC PROC[self: State] = {
n: INT = PopInt[self];
Copy[self, n];
};
ApplyDup: PUBLIC PROC[self: State] = {
Copy[self, 1];
};
ApplyRoll: PUBLIC PROC[self: State] = {
k: INT = PopInt[self];
n: INT = PopInt[self];
Roll[self, n, k];
};
ApplyExch: PUBLIC PROC[self: State] = {
Roll[self, 2, 1];
};
ApplyCount: PUBLIC PROC[self: State] = {
n: INT = Count[self];
PushInt[self, n];
};
ApplyIndex: PUBLIC PROC[self: State] = {
i: INT = Count[self];
Push[self, Index[self, i]];
};
ApplyMark: PUBLIC PROC[self: State] = {
PushMark[self];
};
ApplyCountToMark: PUBLIC PROC[self: State] = {
n: INT = CountToMark[self];
PushInt[self, n];
};
END.