156 lines
3.0 KiB
CoffeeScript
156 lines
3.0 KiB
CoffeeScript
# _______
|
|
# | | <- 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 "
|
|
#console.log print_list(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
|
|
|
|
moveTos = (stackPos) ->
|
|
if tos <= stackPos
|
|
# we are moving the stack pointer
|
|
# "up" the stack (as if we were doing a push)
|
|
tos = stackPos
|
|
return
|
|
# we are moving the stack pointer
|
|
# "down" the stack i.e. as if we were
|
|
# doing a pop, we can zero-
|
|
# out all the elements that we pass
|
|
# so we can reclaim the memory
|
|
while tos > stackPos
|
|
stack[tos] = null
|
|
tos--
|
|
return
|
|
|
|
top = ->
|
|
stack[tos-1]
|
|
|
|
pop = ->
|
|
#popsNum++
|
|
#console.log "pop #" + popsNum
|
|
if (tos == 0)
|
|
debugger
|
|
stop("stack underflow")
|
|
if !stack[tos-1]?
|
|
debugger
|
|
elementToBeReturned = stack[--tos]
|
|
|
|
# give a chance to the garbage
|
|
# collection to reclaim space
|
|
# This is JS-specific, it would
|
|
# actually make the C garbage
|
|
# collector useless.
|
|
stack[tos] = null
|
|
|
|
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)
|
|
|
|
$.dupl = dupl
|
|
$.swap = swap
|
|
$.restore = restore
|
|
$.save = save
|
|
$.push = push
|
|
$.pop = pop
|