#	 _______
#	|	| <- 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.



tos = 0

# p is a U
nil_symbols = 0
push = (p) ->
	if !p?
		debugger
	if p.isZero?
		debugger

	#console.log "pushing "
	#print1(p)

	if p == symbol(NIL)
		nil_symbols++
		if DEBUG then console.log "pushing symbol(NIL) #" + nil_symbols
		#if nil_symbols == 111
		#	debugger
	if (tos >= frame)
		stop("stack overflow")
	stack[tos++] = p

# returns a U

#popsNum = 0
pop = ->
	#popsNum++
	#console.log "pop #" + popsNum
	if (tos == 0)
		debugger
		stop("stack underflow")
	if !stack[tos-1]?
		debugger
	elementToBeReturned = stack[--tos]
	return elementToBeReturned

# n is an integer
push_frame = (n) ->
	i = 0
	frame -= n
	if (frame < tos)
		debugger
		stop("frame overflow, circular reference?")
	for i in [0...n]
		stack[frame + i] = symbol(NIL)

# n is an integer
pop_frame = (n) ->
	frame += n
	if (frame > TOS)
		stop("frame underflow")

save = ->
	frame -= 10
	if (frame < tos)
		debugger
		stop("frame overflow, circular reference?")
	stack[frame + 0] = p0
	stack[frame + 1] = p1
	stack[frame + 2] = p2
	stack[frame + 3] = p3
	stack[frame + 4] = p4
	stack[frame + 5] = p5
	stack[frame + 6] = p6
	stack[frame + 7] = p7
	stack[frame + 8] = p8
	stack[frame + 9] = p9

restore = ->
	if (frame > TOS - 10)
		stop("frame underflow")
	p0 = stack[frame + 0]
	p1 = stack[frame + 1]
	p2 = stack[frame + 2]
	p3 = stack[frame + 3]
	p4 = stack[frame + 4]
	p5 = stack[frame + 5]
	p6 = stack[frame + 6]
	p7 = stack[frame + 7]
	p8 = stack[frame + 8]
	p9 = stack[frame + 9]
	frame += 10

# Local U * is OK here because there is no functional path to the garbage collector.

swap = ->
	#U *p, *q
	# p and q are both Us
	p = pop()
	q = pop()
	push(p)
	push(q)

# Local U * is OK here because there is no functional path to the garbage collector.

dupl = ->
	#U *p
	p = pop()
	push(p)
	push(p)
