eigenmath/stack.cpp

120 lines
1.8 KiB
C++

// _______
// | | <- stack
// | |
// |_______|
// | | <- stack + tos
// | |
// | |
// |_______|
// | | <- frame
// |_______|
// <- stack + TOS
//
// The stack grows from low memory towards high memory. This is so that
// multiple expressions can be pushed on the stack and then accessed as an
// array.
//
// The frame area holds local variables and grows from high memory towards
// low memory. The frame area makes local variables visible to the garbage
// collector.
#include "stdafx.h"
#include "defs.h"
U **frame, *stack[TOS];
int tos;
void
push(U *p)
{
if (stack + tos >= frame)
stop("stack overflow");
stack[tos++] = p;
}
U *
pop()
{
if (tos == 0)
stop("stack underflow");
return stack[--tos];
}
void
push_frame(int n)
{
int i;
frame -= n;
if (frame < stack + tos)
stop("frame overflow, circular reference?");
for (i = 0; i < n; i++)
frame[i] = symbol(NIL);
}
void
pop_frame(int n)
{
frame += n;
if (frame > stack + TOS)
stop("frame underflow");
}
void
save(void)
{
frame -= 10;
if (frame < stack + tos)
stop("frame overflow, circular reference?");
frame[0] = p0;
frame[1] = p1;
frame[2] = p2;
frame[3] = p3;
frame[4] = p4;
frame[5] = p5;
frame[6] = p6;
frame[7] = p7;
frame[8] = p8;
frame[9] = p9;
}
void
restore(void)
{
if (frame > stack + TOS - 10)
stop("frame underflow");
p0 = frame[0];
p1 = frame[1];
p2 = frame[2];
p3 = frame[3];
p4 = frame[4];
p5 = frame[5];
p6 = frame[6];
p7 = frame[7];
p8 = frame[8];
p9 = frame[9];
frame += 10;
}
// Local U * is OK here because there is no functional path to the garbage collector.
void
swap(void)
{
U *p, *q;
p = pop();
q = pop();
push(p);
push(q);
}
// Local U * is OK here because there is no functional path to the garbage collector.
void
dupl(void)
{
U *p;
p = pop();
push(p);
push(p);
}