moved to using pointers for navigating the bytecode
This commit is contained in:
parent
b170338dac
commit
ab64d31271
|
@ -2,3 +2,5 @@ main
|
|||
compiler
|
||||
*.txt
|
||||
callgrind*
|
||||
test.nim
|
||||
test
|
|
@ -53,6 +53,9 @@ proc toDU8*(integ: int): DoubleUint8 =
|
|||
proc toInt*(du8: DoubleUint8): int =
|
||||
cast[uint16](du8).int
|
||||
|
||||
proc DU8ptrToInt*(du8: ptr uint8): int =
|
||||
cast[ptr uint16](du8)[].int
|
||||
|
||||
proc addConstant*(ch: var Chunk, constant: KonValue): int =
|
||||
ch.constants.add(constant)
|
||||
ch.constants.high
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
template padd*[T](x: ptr T, num: int): ptr T =
|
||||
cast[ptr T](cast[int](x) + num)
|
||||
|
||||
template psub*[T](x: ptr T, num: int): ptr T =
|
||||
cast[ptr T](cast[int](x) - num)
|
||||
|
||||
template pdiff*[T](x: ptr T, y: ptr): int =
|
||||
cast[int](x) - cast[int](y)
|
51
vm.nim
51
vm.nim
|
@ -4,17 +4,17 @@ import tables
|
|||
import value
|
||||
import chunk
|
||||
import config
|
||||
import pointerutils
|
||||
|
||||
type
|
||||
Frame = object
|
||||
stackBottom: int # the absolute index of where 0 inside the frame is
|
||||
ii: int
|
||||
returnIp: ptr uint8
|
||||
|
||||
VM* = ref object
|
||||
chunk: Chunk
|
||||
ii: int
|
||||
ip: ptr uint8
|
||||
stack: seq[KonValue]
|
||||
line: int
|
||||
hadError: bool
|
||||
globals: Table[string, KonValue]
|
||||
frames: seq[Frame]
|
||||
|
@ -24,7 +24,8 @@ type
|
|||
|
||||
|
||||
proc newVM*(ch: Chunk): VM =
|
||||
VM(chunk: ch, ii: 0, stack: @[], frames: @[Frame()])
|
||||
result = VM(chunk: ch, stack: newSeqOfCap[KonValue](256), frames: newSeqOfCap[Frame](4))
|
||||
result.ip = ch.code[0].unsafeAddr
|
||||
|
||||
proc push(vm: VM, val: KonValue) =
|
||||
vm.stack.add(val)
|
||||
|
@ -36,7 +37,9 @@ proc peek(vm: VM): KonValue =
|
|||
vm.stack[vm.stack.high]
|
||||
|
||||
proc runtimeError(vm: VM, msg: string) =
|
||||
write stderr, &"[line: {vm.line}] {msg}\n"
|
||||
let ii = vm.ip.pdiff(vm.chunk.code[0].unsafeAddr)
|
||||
let line = vm.chunk.lines[ii]
|
||||
write stderr, &"[line: {line}] {msg}\n"
|
||||
vm.hadError = true
|
||||
|
||||
proc pushSafe(vm: VM, val: KonValue): bool =
|
||||
|
@ -51,12 +54,12 @@ proc pushSafe(vm: VM, val: KonValue): bool =
|
|||
return true
|
||||
|
||||
proc advance(vm: VM): uint8 =
|
||||
vm.ii.inc
|
||||
vm.line = vm.chunk.lines[vm.ii-1]
|
||||
vm.chunk.code[vm.ii-1]
|
||||
result = vm.ip[]
|
||||
vm.ip = vm.ip.padd(1)
|
||||
|
||||
proc readDU8(vm: VM): int =
|
||||
[vm.advance, vm.advance].toInt
|
||||
result = vm.ip.DU8ptrToInt
|
||||
vm.ip = vm.ip.padd(argSize)
|
||||
|
||||
proc readConstant(vm: VM): KonValue =
|
||||
let index = vm.readDU8()
|
||||
|
@ -78,8 +81,9 @@ proc binary(op: OpCode, left: KonValue, right: KonValue): KonValue =
|
|||
proc run*(vm: VM): InterpretResult =
|
||||
|
||||
template frameBottom: int = vm.frames[vm.frames.high].stackBottom
|
||||
|
||||
while true:
|
||||
{.computedgoto.} # See https://nim-lang.org/docs/manual.html#pragmas-computedgoto-pragma
|
||||
|
||||
let ins = vm.advance.OpCode
|
||||
|
||||
when debugVM:
|
||||
|
@ -94,8 +98,9 @@ proc run*(vm: VM): InterpretResult =
|
|||
msg &= &"{e} "
|
||||
msg &= "]"
|
||||
echo msg
|
||||
{.computedgoto.} # See https://nim-lang.org/docs/manual.html#pragmas-computedgoto-pragma
|
||||
case ins:
|
||||
of opPop:
|
||||
discard vm.pop()
|
||||
of opConstant:
|
||||
let val: KonValue = vm.readConstant()
|
||||
vm.push(val)
|
||||
|
@ -109,11 +114,10 @@ proc run*(vm: VM): InterpretResult =
|
|||
if not vm.pushSafe(binary(ins, left, right)):
|
||||
break
|
||||
of opReturn:
|
||||
if frameBottom == 0:
|
||||
if vm.frames.len == 0:
|
||||
break
|
||||
else:
|
||||
discard vm.frames.pop() # remove frame that's over
|
||||
vm.ii = vm.frames[vm.frames.high].ii # get backed up ii
|
||||
vm.ip = vm.frames.pop().returnIp # remove frame that's over
|
||||
of opTrue:
|
||||
vm.push(toKonValue(true))
|
||||
of opFalse:
|
||||
|
@ -153,8 +157,6 @@ proc run*(vm: VM): InterpretResult =
|
|||
else:
|
||||
vm.runtimeError(&"Attempt to set undefined global variable {name}.")
|
||||
break
|
||||
of opPop:
|
||||
discard vm.pop()
|
||||
of opGetLocal:
|
||||
let slot = vm.readDU8()
|
||||
vm.push(vm.stack[slot + frameBottom])
|
||||
|
@ -164,17 +166,17 @@ proc run*(vm: VM): InterpretResult =
|
|||
of opJumpIfFalse:
|
||||
let offset = vm.readDU8()
|
||||
if vm.peek.isFalsey:
|
||||
vm.ii += offset
|
||||
vm.ip = vm.ip.padd(offset)
|
||||
of opJumpIfFalsePop:
|
||||
let offset = vm.readDU8()
|
||||
if vm.pop.isFalsey:
|
||||
vm.ii += offset
|
||||
vm.ip = vm.ip.padd(offset)
|
||||
of opJump:
|
||||
let offset = vm.readDU8()
|
||||
vm.ii += offset
|
||||
vm.ip = vm.ip.padd(offset)
|
||||
of opLoop:
|
||||
let offset = vm.readDU8()
|
||||
vm.ii -= offset
|
||||
vm.ip = vm.ip.psub(offset)
|
||||
of opCall:
|
||||
# create the call env
|
||||
# current stack before opCall:
|
||||
|
@ -193,15 +195,10 @@ proc run*(vm: VM): InterpretResult =
|
|||
|
||||
vm.stack[vm.stack.high - argcount] = toKonValue() # replace the function with nil: this is the return value slot
|
||||
|
||||
# save ii
|
||||
vm.frames[vm.frames.high].ii = vm.ii
|
||||
|
||||
# create new frame
|
||||
vm.frames.add(Frame(stackBottom: vm.stack.high - argcount))
|
||||
|
||||
vm.ii = funct.entryII # jump to the entry point
|
||||
|
||||
vm.frames.add(Frame(stackBottom: vm.stack.high - argcount, returnIp: vm.ip))
|
||||
|
||||
vm.ip = vm.chunk.code[0].unsafeAddr.padd(funct.entryII) # jump to the entry point
|
||||
|
||||
when assertionsVM:
|
||||
if not vm.hadError and vm.stack.len > 0:
|
||||
|
|
Loading…
Reference in New Issue