WIP closures: unclosed upvalues work; improved vm debugging and changed $ for functions, closures
This commit is contained in:
parent
f453de631d
commit
392955e290
|
@ -118,6 +118,43 @@ const argInstructions = {
|
|||
opGetUpvalue, opSetUpvalue,
|
||||
}
|
||||
|
||||
proc disassembleInstruction*(ch: Chunk, c: var int, lastLine: var int) =
|
||||
template instruction: uint8 = ch.code[c]
|
||||
template line: int = ch.lines[c]
|
||||
template double: DoubleUint8 = [ch.code[c+1], ch.code[c+2]]
|
||||
template shortArg: uint8 = ch.code[c+1]
|
||||
let cFmt = &"{c:04}"
|
||||
let lineFmt = if lastLine == line: " | " else: &"{line:04}"
|
||||
lastLine = line
|
||||
try:
|
||||
write stdout, &"[{cFmt}] {lineFmt} {instruction.OpCode} ({instruction.toHex(2)}"
|
||||
case instruction.OpCode:
|
||||
of simpleInstructions:
|
||||
write stdout, ")\n"
|
||||
of shortArgInstructions:
|
||||
write stdout, &" {shortArg.toHex(2)})\n"
|
||||
c += 1
|
||||
of argInstructions:
|
||||
write stdout, &" {double[0].toHex(2)} {double[1].toHex(2)})\n"
|
||||
c += 2
|
||||
of constantInstructions:
|
||||
let i = double.toInt
|
||||
write stdout, &" {double[0].toHex(2)} {double[1].toHex(2)})\n"
|
||||
echo &" points to constant {ch.constants[i]} (i: {i})"
|
||||
c += 2
|
||||
of opClosure:
|
||||
let upvalCount = double.toInt
|
||||
c += 2
|
||||
write stdout, &" length: {upvalCount} [ "
|
||||
for i in countup(1, upvalCount):
|
||||
let index = double.toInt
|
||||
c += 2
|
||||
let local = shortArg.int
|
||||
c += 1
|
||||
write stdout, &"(i: {index} l: {local}) "
|
||||
write stdout, &"])\n"
|
||||
except:
|
||||
echo &"[{cFmt}] {lineFmt} Unknown opcode {instruction}"
|
||||
|
||||
proc disassembleChunk*(ch: Chunk) =
|
||||
echo &"== Chunk {ch.name} begin =="
|
||||
|
@ -125,42 +162,7 @@ proc disassembleChunk*(ch: Chunk) =
|
|||
var c: int = 0
|
||||
var lastLine = -1
|
||||
while c < ch.code.len:
|
||||
template instruction: uint8 = ch.code[c]
|
||||
template line: int = ch.lines[c]
|
||||
template double: DoubleUint8 = [ch.code[c+1], ch.code[c+2]]
|
||||
template shortArg: uint8 = ch.code[c+1]
|
||||
let cFmt = &"{c:04}"
|
||||
let lineFmt = if lastLine == line: " | " else: &"{line:04}"
|
||||
try:
|
||||
write stdout, &"[{cFmt}] {lineFmt} {instruction.OpCode} ({instruction.toHex(2)}"
|
||||
case instruction.OpCode:
|
||||
of simpleInstructions:
|
||||
write stdout, ")\n"
|
||||
of shortArgInstructions:
|
||||
write stdout, &" {shortArg.toHex(2)})\n"
|
||||
c += 1
|
||||
of argInstructions:
|
||||
write stdout, &" {double[0].toHex(2)} {double[1].toHex(2)})\n"
|
||||
c += 2
|
||||
of constantInstructions:
|
||||
let i = double.toInt
|
||||
write stdout, &" {double[0].toHex(2)} {double[1].toHex(2)})\n"
|
||||
echo &" points to constant {ch.constants[i]} (i: {i})"
|
||||
c += 2
|
||||
of opClosure:
|
||||
let upvalCount = double.toInt
|
||||
c += 2
|
||||
write stdout, &" length: {upvalCount} [ "
|
||||
for i in countup(1, upvalCount):
|
||||
let index = double.toInt
|
||||
c += 2
|
||||
let local = shortArg.int
|
||||
c += 1
|
||||
write stdout, &"(i: {index} l: {local}) "
|
||||
write stdout, &"])\n"
|
||||
|
||||
except:
|
||||
echo &"[{cFmt}] {lineFmt} Unknown opcode {instruction}"
|
||||
disassembleInstruction(ch, c, lastLine)
|
||||
c.inc
|
||||
echo &"== Chunk {ch.name} end =="
|
||||
|
||||
|
|
|
@ -17,4 +17,20 @@ proc newClosure*[T](start: ptr uint8, upvalueCount: int): Closure[T] =
|
|||
result.upvalueCount = upvalueCount
|
||||
|
||||
proc getIp*[T](clos: Closure[T]): ptr uint8 {.inline.} =
|
||||
clos.start
|
||||
clos.start
|
||||
|
||||
proc set*[T](clos: Closure[T], index: int, val: Upvalue[T]) =
|
||||
clos.upvalues[index] = val
|
||||
|
||||
proc get*[T](clos: Closure[T], index: int): Upvalue[T] =
|
||||
clos.upvalues[index]
|
||||
|
||||
proc captureUpvalue*[T](location: ptr T): Upvalue[T] =
|
||||
result = cast[Upvalue[T]](alloc0(sizeof(UpvalueObj[T])))
|
||||
result.location = location
|
||||
|
||||
proc read*[T](upval: Upvalue[T]): T =
|
||||
upval.location[]
|
||||
|
||||
proc write*[T](upval: Upvalue[T], val: T) =
|
||||
upval.location[]= val
|
|
@ -1,4 +1,5 @@
|
|||
import strformat
|
||||
import strutils
|
||||
import bitops
|
||||
|
||||
import ndstring
|
||||
|
@ -155,7 +156,9 @@ proc `$`*(val: NdValue): string =
|
|||
elif val.isFloat():
|
||||
return $val.asFloat()
|
||||
elif val.isFunct():
|
||||
return &"Function object {cast[uint](val.asFunct())}"
|
||||
return &"Function object {(val).uint.toHex()}"
|
||||
elif val.isClosure():
|
||||
return &"Closure object {(val).uint.toHex()}"
|
||||
elif val.isString():
|
||||
return $val.asString()
|
||||
elif val.isTable():
|
||||
|
|
|
@ -27,6 +27,7 @@ type
|
|||
Frame = object
|
||||
stackBottom: int # the absolute index of where 0 inside the frame is
|
||||
returnIp: ptr uint8
|
||||
closure: Closure[NdValue]
|
||||
|
||||
InterpretResult* = enum
|
||||
irOK, irRuntimeError
|
||||
|
@ -72,7 +73,7 @@ proc run*(chunk: Chunk): InterpretResult =
|
|||
frames.add(Frame(stackBottom: stack.high - argcount, returnIp: ip))
|
||||
ip = funct.asFunct() # jump to the entry point
|
||||
elif funct.isClosure():
|
||||
frames.add(Frame(stackBottom: stack.high - argcount, returnIp: ip))
|
||||
frames.add(Frame(stackBottom: stack.high - argcount, returnIp: ip, closure: funct.asClosure()))
|
||||
ip = funct.asClosure().getIp()
|
||||
else:
|
||||
error
|
||||
|
@ -84,9 +85,10 @@ proc run*(chunk: Chunk): InterpretResult =
|
|||
ip = ip.padd(1)
|
||||
|
||||
when debugVM:
|
||||
let ii = ip.pdiff(chunk.code[0].unsafeAddr) - 1
|
||||
let opname = ($ins)
|
||||
var msg = &"[{ii:04}] {opname}"
|
||||
var ii = ip.pdiff(chunk.code[0].unsafeAddr) - 1
|
||||
var ll = -1
|
||||
disassembleInstruction(chunk, ii, ll)
|
||||
var msg = ""
|
||||
msg &= " Stack: [ "
|
||||
for i in 0 .. stack.high():
|
||||
let e = stack[i]
|
||||
|
@ -199,9 +201,11 @@ proc run*(chunk: Chunk): InterpretResult =
|
|||
let slot = ip.readDU8()
|
||||
stack[slot + frameBottom] = stack.peek()
|
||||
of opGetUpvalue:
|
||||
discard
|
||||
let slot = ip.readDU8()
|
||||
stack.push(frames.peek().closure.get(slot).read())
|
||||
of opSetUpvalue:
|
||||
discard
|
||||
let slot = ip.readDU8()
|
||||
frames.peek().closure.get(slot).write(stack.peek())
|
||||
of opJumpIfFalse:
|
||||
let offset = ip.readDU8()
|
||||
if stack.peek().isFalsey():
|
||||
|
@ -222,8 +226,18 @@ proc run*(chunk: Chunk): InterpretResult =
|
|||
ip = ip.padd(offset)
|
||||
stack.push(faddr.fromFunct())
|
||||
of opClosure:
|
||||
runtimeError("Closures are not implemented.")
|
||||
break
|
||||
let upvalCount = ip.readDU8()
|
||||
let funct = stack.peek()
|
||||
let closure = newClosure[NdValue](funct.asFunct(), upvalCount)
|
||||
stack.settip(closure.fromClosure())
|
||||
for i in countup(0, upvalCount - 1):
|
||||
let slot = ip.readDU8()
|
||||
let isLocal = ip.readUI8() == 0
|
||||
if isLocal:
|
||||
closure.set(i, stack[slot + frameBottom].addr.captureUpvalue())
|
||||
else:
|
||||
closure.set(i, frames.peek().closure.get(slot))
|
||||
|
||||
of opCheckArity:
|
||||
let arity = ip.readUI8()
|
||||
let argcount = stack.high() - frameBottom
|
||||
|
|
Loading…
Reference in New Issue