Even more cleanup. Added ✨pretty colors✨ to the VM's debugger
This commit is contained in:
parent
77fd5931fa
commit
47a6f16664
|
@ -77,21 +77,22 @@ proc newPeonVM*: PeonVM =
|
|||
result.initCache()
|
||||
|
||||
|
||||
# Getters for singleton types (they are cached!)
|
||||
# Getters for singleton types
|
||||
{.push inline.}
|
||||
|
||||
proc getNil*(self: PeonVM): uint64 {.inline.} = self.cache[2]
|
||||
proc getNil*(self: PeonVM): uint64 = self.cache[2]
|
||||
|
||||
proc getBool*(self: PeonVM, value: bool): uint64 {.inline.} =
|
||||
proc getBool*(self: PeonVM, value: bool): uint64 =
|
||||
if value:
|
||||
return self.cache[1]
|
||||
return self.cache[0]
|
||||
|
||||
proc getInf*(self: PeonVM, positive: bool): uint64 {.inline.} =
|
||||
proc getInf*(self: PeonVM, positive: bool): uint64 =
|
||||
if positive:
|
||||
return self.cache[3]
|
||||
return self.cache[4]
|
||||
|
||||
proc getNan*(self: PeonVM): uint64 {.inline.} = self.cache[5]
|
||||
proc getNan*(self: PeonVM): uint64 = self.cache[5]
|
||||
|
||||
|
||||
# Thanks to nim's *genius* idea of making x !> y a template
|
||||
|
@ -113,7 +114,6 @@ proc `!>=`[T](a, b: T): auto {.inline, used.} =
|
|||
# that go through the getc/setc wrappers is frame-relative,
|
||||
# meaning that the index is added to the current stack frame's
|
||||
# bottom to obtain an absolute stack index
|
||||
{.push inline.}
|
||||
proc push(self: PeonVM, obj: uint64) =
|
||||
## Pushes a value object onto the
|
||||
## operand stack
|
||||
|
@ -288,8 +288,6 @@ proc constReadUInt8(self: PeonVM, idx: int): uint8 =
|
|||
result = self.chunk.consts[idx]
|
||||
|
||||
|
||||
|
||||
|
||||
proc constReadFloat32(self: PeonVM, idx: int): float32 =
|
||||
## Reads a constant from the
|
||||
## chunk's constant table and
|
||||
|
@ -308,30 +306,66 @@ proc constReadFloat64(self: PeonVM, idx: int): float =
|
|||
self.chunk.consts[idx + 4], self.chunk.consts[idx + 5],
|
||||
self.chunk.consts[idx + 6], self.chunk.consts[idx + 7]]
|
||||
copyMem(result.addr, arr.addr, sizeof(arr))
|
||||
|
||||
{.pop.}
|
||||
|
||||
|
||||
when debugVM: # So nim shuts up
|
||||
proc debug(self: PeonVM) =
|
||||
## Implements the VM's runtime
|
||||
## debugger
|
||||
styledEcho fgMagenta, "IP: ", fgYellow, &"{self.ip}"
|
||||
styledEcho fgBlue, "Instruction: ", fgRed, &"{OpCode(self.chunk.code[self.ip])} (", fgYellow, $self.chunk.code[self.ip], fgRed, ")"
|
||||
if self.calls.len() !> 0:
|
||||
stdout.styledWrite(fgGreen, "Call Stack: ", fgMagenta, "[")
|
||||
for i, e in self.calls:
|
||||
stdout.styledWrite(fgYellow, $e)
|
||||
if i < self.calls.high():
|
||||
stdout.styledWrite(fgYellow, ", ")
|
||||
styledEcho fgMagenta, "]"
|
||||
if self.operands.len() !> 0:
|
||||
stdout.styledWrite(fgBlue, "Operand Stack: ", fgMagenta, "[")
|
||||
for i, e in self.operands:
|
||||
stdout.styledWrite(fgYellow, $e)
|
||||
if i < self.operands.high():
|
||||
stdout.styledWrite(fgYellow, ", ")
|
||||
styledEcho fgMagenta, "]"
|
||||
if self.frames.len() !> 0:
|
||||
stdout.styledWrite(fgCyan, "Current Frame: ", fgMagenta, "[")
|
||||
for i, e in self.calls[self.frames[^1]..^1]:
|
||||
stdout.styledWrite(fgYellow, $e)
|
||||
if i < self.calls.high():
|
||||
stdout.styledWrite(fgYellow, ", ")
|
||||
styledEcho fgMagenta, "]"
|
||||
stdout.styledWrite(fgRed, "Live stack frames: ", fgMagenta, "[")
|
||||
for i, e in self.frames:
|
||||
stdout.styledWrite(fgYellow, $e)
|
||||
if i < self.frames.high():
|
||||
stdout.styledWrite(fgYellow, ", ")
|
||||
styledEcho fgMagenta, "]"
|
||||
if self.closedOver.len() !> 0:
|
||||
stdout.styledWrite(fgGreen, "Closure Array: ", fgMagenta, "[")
|
||||
for i, e in self.closedOver:
|
||||
stdout.styledWrite(fgYellow, $e)
|
||||
if i < self.closedOver.high():
|
||||
stdout.styledWrite(fgYellow, ", ")
|
||||
styledEcho fgMagenta, "]"
|
||||
if self.results.len() !> 0:
|
||||
stdout.styledWrite(fgYellow, "Function Results: ", fgMagenta, "[")
|
||||
for i, e in self.results:
|
||||
stdout.styledWrite(fgYellow, $e)
|
||||
if i < self.results.high():
|
||||
stdout.styledWrite(fgYellow, ", ")
|
||||
styledEcho fgMagenta, "]"
|
||||
discard readLine stdin
|
||||
|
||||
|
||||
proc dispatch*(self: PeonVM) =
|
||||
## Main bytecode dispatch loop
|
||||
var instruction {.register.}: OpCode
|
||||
while true:
|
||||
{.computedgoto.} # https://nim-lang.org/docs/manual.html#pragmas-computedgoto-pragma
|
||||
when debugVM:
|
||||
echo &"IP: {self.ip}"
|
||||
echo &"Instruction: {OpCode(self.chunk.code[self.ip])}"
|
||||
if self.calls.len() !> 0:
|
||||
echo &"Call Stack: {self.calls}"
|
||||
if self.operands.len() !> 0:
|
||||
echo &"Operand Stack: {self.operands}"
|
||||
if self.frames.len() !> 0:
|
||||
echo &"Current Frame: {self.calls[self.frames[^1]..^1]}"
|
||||
echo &"Frames: {self.frames}"
|
||||
if self.closedOver.len() !> 0:
|
||||
echo &"Closure Array: {self.closedOver}"
|
||||
if self.results.len() !> 0:
|
||||
echo &"Results: {self.results}"
|
||||
discard readLine stdin
|
||||
self.debug()
|
||||
instruction = OpCode(self.readByte())
|
||||
case instruction:
|
||||
# Constant loading instructions
|
||||
|
@ -391,9 +425,9 @@ proc dispatch*(self: PeonVM) =
|
|||
# how the stack works, all arguments before the call
|
||||
# are in the reverse order in which they are passed
|
||||
# to the function
|
||||
var argc {.used.} = self.readLong().int
|
||||
let retAddr = self.peek(-argc - 1) # Return address
|
||||
let jmpAddr = self.peek(-argc - 2) # Function address
|
||||
let argc = self.readLong().int
|
||||
let retAddr = self.peek(-argc - 1) # Return address
|
||||
let jmpAddr = self.peek(-argc - 2) # Function address
|
||||
self.ip = jmpAddr
|
||||
self.pushc(jmpAddr)
|
||||
self.pushc(retAddr)
|
||||
|
@ -410,13 +444,6 @@ proc dispatch*(self: PeonVM) =
|
|||
# not needed there anymore
|
||||
discard self.pop()
|
||||
discard self.pop()
|
||||
# TODO: Use the frame's initial size once
|
||||
# we have more control over the
|
||||
# memory
|
||||
#[while argc !> 0:
|
||||
dec(argc)
|
||||
self.pushc(self.getNil())
|
||||
]#
|
||||
of Return:
|
||||
# Returns from a function.
|
||||
# Every peon program is wrapped
|
||||
|
@ -595,6 +622,7 @@ proc dispatch*(self: PeonVM) =
|
|||
self.push(not self.pop())
|
||||
of And:
|
||||
self.push(self.pop() and self.pop())
|
||||
# Comparison opcodes
|
||||
of Equal:
|
||||
self.push(self.getBool(self.pop() == self.pop()))
|
||||
of NotEqual:
|
||||
|
@ -607,12 +635,10 @@ proc dispatch*(self: PeonVM) =
|
|||
self.push(self.getBool(self.pop() !>= self.pop()))
|
||||
of LessOrEqual:
|
||||
self.push(self.getBool(self.pop() <= self.pop()))
|
||||
# Print opcodes
|
||||
of PrintInt64:
|
||||
# Prints the value at the top of the stack
|
||||
# as an int64
|
||||
echo int64(self.pop())
|
||||
of PrintUInt64:
|
||||
# Prints the value at the top of the stack
|
||||
echo self.pop()
|
||||
of PrintInt32:
|
||||
echo int32(self.pop())
|
||||
|
@ -631,8 +657,6 @@ proc dispatch*(self: PeonVM) =
|
|||
of PrintFloat64:
|
||||
echo cast[float](self.pop())
|
||||
of PrintHex:
|
||||
# Prints the value at the top of the stack
|
||||
# as a hexadecimal integer
|
||||
echo "0x" & self.pop().toHex().strip(chars={'0'})
|
||||
of PrintBool:
|
||||
if self.pop().bool:
|
||||
|
|
|
@ -123,8 +123,6 @@ proc repl =
|
|||
styledEcho fgGreen, "OK"
|
||||
else:
|
||||
styledEcho fgRed, "Corrupted"
|
||||
when debugVM:
|
||||
styledEcho fgCyan, "\n\nExecution step: "
|
||||
vm.run(serialized.chunk)
|
||||
except LexingError:
|
||||
input = ""
|
||||
|
@ -258,8 +256,6 @@ proc runFile(f: string, interactive: bool = false, fromString: bool = false) =
|
|||
styledEcho fgGreen, "OK"
|
||||
else:
|
||||
styledEcho fgRed, "Corrupted"
|
||||
when debugVM:
|
||||
styledEcho fgCyan, "\n\nExecution step: "
|
||||
vm.run(serialized.chunk)
|
||||
except LexingError:
|
||||
var exc = LexingError(getCurrentException())
|
||||
|
|
Loading…
Reference in New Issue