Minor improvements to debugger experience

This commit is contained in:
nocturn9x 2020-08-28 00:05:56 +02:00
parent 4a1fc8df6d
commit 21ab45ecc4
5 changed files with 41 additions and 21 deletions

View File

@ -51,3 +51,7 @@ type
proc initParser*(tokens: seq[Token]): Parser =
result = Parser(current: 0, tokens: tokens, hadError: false, panicMode: false)
const FRAMES_MAX* = 256
const STACK_MAX* = FRAMES_MAX * int uint8.high

View File

@ -716,6 +716,7 @@ proc compile*(self: var Compiler, source: string): ptr Function =
else:
return nil
proc initCompiler*(vm: var VM, context: FunctionType): Compiler =
result = Compiler(parser: initParser(@[]), function: nil, locals: @[], scopeDepth: 0, localCount: 0, loop: Loop(alive: false, loopEnd: -1), vm: vm, context: context)
result.locals.add(Local(depth: 0, name: Token(kind: EOF, lexeme: "")))

View File

@ -2,13 +2,17 @@ import vm
import strformat
import parseopt
import os
import common
proc repl(debug: bool = false) =
var bytecodeVM = initVM()
echo &"[JAPL 0.2.0 - Nim {NimVersion} - {CompileDate} {CompileTime}]"
echo &"[JAPL 0.2.0 - on Nim {NimVersion} - {CompileDate} {CompileTime}]"
if debug:
echo "Debug mode is enabled, bytecode will be disassembled"
echo "Debugger enabled, expect verbose output\n"
echo "==== VM Constants ====\n"
echo &"- FRAMES_MAX -> {FRAMES_MAX}\n- STACK_MAX -> {STACK_MAX}\n"
echo "==== Code starts ====\n"
var source: string = ""
while true:
try:
@ -16,11 +20,11 @@ proc repl(debug: bool = false) =
source = readLine(stdin)
except IOError:
echo ""
bytecodeVM.freeVM()
bytecodeVM.freeVM(debug)
break
except KeyboardInterrupt:
echo ""
bytecodeVM.freeVM()
bytecodeVM.freeVM(debug)
break
if source == "":
continue
@ -47,11 +51,14 @@ proc main(file: string = "", debug: bool = false) =
echo &"Error: '{file}' could not be read, probably you don't have the permission to read it"
var bytecodeVM = initVM()
if debug:
echo "Debug mode is enabled, bytecode will be disassembled"
echo "Debugger enabled, expect verbose output\n"
echo "==== VM Constants ====\n"
echo &"- FRAMES_MAX -> {FRAMES_MAX}\n- STACK_MAX -> {STACK_MAX}\n"
echo "==== Code starts ====\n"
var result = bytecodeVM.interpret(source, debug)
if debug:
echo &"Result: {result}"
bytecodeVM.freeVM()
bytecodeVM.freeVM(debug)
when isMainModule:

View File

@ -5,13 +5,13 @@ import strformat
proc simpleInstruction(name: string, index: int): int =
echo &"\tOpCode at offset: {name}\n"
echo &"\tInstruction at IP: {name}\n"
return index + 1
proc byteInstruction(name: string, chunk: Chunk, offset: int): int =
var slot = chunk.code[offset + 1]
echo &"\tOpCode at offset: {name}, points to slot {slot}\n"
echo &"\tInstruction at IP: {name}, points to slot {slot}\n"
return offset + 1
@ -20,28 +20,29 @@ proc constantLongInstruction(name: string, chunk: Chunk, offset: int): int =
var constantArray: array[3, uint8] = [chunk.code[offset + 1], chunk.code[offset + 2], chunk.code[offset + 3]]
var constant: int
copyMem(constant.addr, unsafeAddr(constantArray), sizeof(constantArray))
echo &"\tOpCode at offset: {name}, points to {constant}"
echo &"\tInstruction at IP: {name}, points to slot {constant}"
let obj = chunk.consts.values[constant]
echo &"\tValue: {stringify(obj)}\n\tKind: {obj.kind}\n"
echo &"\tOperand: {stringify(obj)}\n\tValue kind: {obj.kind}\n"
return offset + 4
proc constantInstruction(name: string, chunk: Chunk, offset: int): int =
var constant = chunk.code[offset + 1]
echo &"\tOpCode at offset: {name}, points to index {constant}"
echo &"\tInstruction at IP: {name}, points to index {constant}"
let obj = chunk.consts.values[constant]
echo &"\tValue: {stringify(obj)}\n\tKind: {obj.kind}\n"
echo &"\tOperand: {stringify(obj)}\n\tValue kind: {obj.kind}\n"
return offset + 2
proc jumpInstruction(name: string, chunk: Chunk, offset: int): int =
var jump = uint16 (chunk.code[offset + 1] shr 8)
jump = jump or chunk.code[offset + 2]
echo &"\tOpCode at offset: {name}\n\tJump size: {jump}\n"
echo &"\tInstruction at IP: {name}\n\tJump offset: {jump}\n"
return offset + 3
proc disassembleInstruction*(chunk: Chunk, offset: int): int =
echo &"Current offset: {offset}\nCurrent line: {chunk.lines[offset]}"
echo &"Current IP position: {offset}\nCurrent line: {chunk.lines[offset]}"
var opcode = OpCode(chunk.code[offset])
if opcode == OP_RETURN:
result = simpleInstruction("OP_RETURN", offset)

View File

@ -382,33 +382,42 @@ proc run(self: var VM, debug, repl: bool): InterpretResult =
return OK
proc freeObject(obj: ptr Obj) =
proc freeObject(obj: ptr Obj, debug: bool) =
case obj.kind:
of ObjectTypes.STRING:
var str = cast[ptr String](obj)
if debug:
echo &"Freeing string object with value '{stringify(str[])}' of length {str.len}"
discard freeArray(char, str.str, str.len)
discard free(ObjectTypes.STRING, obj)
of ObjectTypes.FUNCTION:
var fun = cast[ptr Function](obj)
echo "Freeing function object with value '{stringify(fun[])}'"
fun.chunk.freeChunk()
discard free(ObjectTypes.FUNCTION, fun)
else:
discard
proc freeObjects(self: var VM) =
proc freeObjects(self: var VM, debug: bool) =
var obj = self.objects
var next: ptr Obj
var i = 0
while obj != nil:
next = obj[].next
freeObject(obj)
freeObject(obj, debug)
i += 1
obj = next
if debug:
echo &"Freed {i} objects"
proc freeVM*(self: var VM) =
proc freeVM*(self: var VM, debug: bool) =
if debug:
echo "\nFreeing all allocated memory before exiting"
unsetControlCHook()
try:
self.freeObjects()
self.freeObjects(debug)
except NilAccessError:
echo "MemoryError: could not manage memory, exiting"
quit(71)
@ -427,8 +436,6 @@ proc interpret*(self: var VM, source: string, debug: bool = false, repl: bool =
except KeyboardInterrupt:
self.error(newInterruptedError(""))
return RUNTIME_ERROR
self.chunk.freeChunk()
self.freeVM()
proc resetStack*(self: var VM) =