From 879fec20fe1797ecb6fdd438ce0039fa04ef0655 Mon Sep 17 00:00:00 2001 From: Mattia Giambirtone Date: Mon, 22 May 2023 13:10:15 +0200 Subject: [PATCH] Various components are now debuggable without recompiling --- src/config.nim | 13 +++-- src/frontend/compiler/compiler.nim | 2 +- src/main.nim | 92 +++++++++++++++--------------- 3 files changed, 55 insertions(+), 52 deletions(-) diff --git a/src/config.nim b/src/config.nim index 1f171a2..06217e9 100644 --- a/src/config.nim +++ b/src/config.nim @@ -15,14 +15,14 @@ import strformat # These variables can be tweaked to debug and test various components of the toolchain -const debugLexer* {.booldefine.} = false # Print the tokenizer's output -const debugParser* {.booldefine.} = false # Print the AST generated by the parser -const debugCompiler* {.booldefine.} = false # Disassemble and/or print the code generated by the compiler +var debugLexer* = false # Print the tokenizer's output +var debugParser* = false # Print the AST generated by the parser +var debugCompiler* = false # Disassemble and/or print the code generated by the compiler const debugVM* {.booldefine.} = false # Enable the runtime debugger in the bytecode VM const debugGC* {.booldefine.} = false # Debug the Garbage Collector (extremely verbose) const debugAlloc* {.booldefine.} = false # Trace object allocation (extremely verbose) const debugMem* {.booldefine.} = false # Debug the memory allocator (extremely verbose) -const debugSerializer* {.booldefine.} = false # Validate the bytecode serializer's output +var debugSerializer* = false # Validate the bytecode serializer's output const debugStressGC* {.booldefine.} = false # Make the GC run a collection at every allocation (VERY SLOW!) const debugMarkGC* {.booldefine.} = false # Trace the marking phase object by object (extremely verbose) const PeonBytecodeMarker* = "PEON_BYTECODE" # Magic value at the beginning of bytecode files @@ -70,8 +70,11 @@ Options yes/on and no/off --noWarn Disable a specific warning (for example, --noWarn:unusedVariable) --showMismatches Show all mismatches when function dispatching fails (output is really verbose) ---backend Select the compilation backend (valid values are: 'c', 'cpp' and 'bytecode'). Note +--backend Select the compilation backend (valid values are: 'c' and 'bytecode'). Note that the REPL always uses the bytecode target. Defaults to 'bytecode' -o, --output Rename the output file with this value (with --backend:bytecode, a '.pbc' extension is added if not already present) +--debug-dump Debug the bytecode serializer. Only makes sense with --backend:bytecode +--debug-lexer Debug the peon lexer +--debug-parser Debug the peon parser """ diff --git a/src/frontend/compiler/compiler.nim b/src/frontend/compiler/compiler.nim index a1be635..4f7181f 100644 --- a/src/frontend/compiler/compiler.nim +++ b/src/frontend/compiler/compiler.nim @@ -40,7 +40,7 @@ export ast, token, symbols, config, errors type PeonBackend* = enum ## An enumeration of the peon backends - Bytecode, NativeC, NativeCpp + Bytecode, NativeC PragmaKind* = enum ## An enumeration of pragma types diff --git a/src/main.nim b/src/main.nim index 3d6c66a..844af95 100644 --- a/src/main.nim +++ b/src/main.nim @@ -88,7 +88,7 @@ proc repl(warnings: seq[WarningKind] = @[], mismatches: bool = false, mode: Comp tokens = tokenizer.lex(input, "stdin") if tokens.len() == 0: continue - when debugLexer: + if debugLexer: styledEcho fgCyan, "Tokenization step:" for i, token in tokens: if i == tokens.high(): @@ -99,19 +99,19 @@ proc repl(warnings: seq[WarningKind] = @[], mismatches: bool = false, mode: Comp tree = parser.parse(tokens, "stdin", tokenizer.getLines(), input, persist=true) if tree.len() == 0: continue - when debugParser: + if debugParser: styledEcho fgCyan, "Parsing step:" for node in tree: styledEcho fgGreen, "\t", $node echo "" compiled = compiler.compile(tree, "stdin", tokenizer.getLines(), input, chunk=compiled, showMismatches=mismatches, disabledWarnings=warnings, mode=mode, incremental=true) - when debugCompiler: + if debugCompiler: styledEcho fgCyan, "Compilation step:\n" debugger.disassembleChunk(compiled, "stdin") echo "" serialized = serializer.loadBytes(serializer.dumpBytes(compiled, "stdin")) - when debugSerializer: + if debugSerializer: styledEcho fgCyan, "Serialization step: " styledEcho fgBlue, "\t- Peon version: ", fgYellow, &"{serialized.version.major}.{serialized.version.minor}.{serialized.version.patch}", fgBlue, " (commit ", fgYellow, serialized.commit[0..8], fgBlue, ") on branch ", fgYellow, serialized.branch stdout.styledWriteLine(fgBlue, "\t- Compilation date & time: ", fgYellow, fromUnix(serialized.compileDate).format("d/M/yyyy HH:mm:ss")) @@ -154,7 +154,7 @@ proc repl(warnings: seq[WarningKind] = @[], mismatches: bool = false, mode: Comp quit(0) -proc runFile(f: string, fromString: bool = false, dump: bool = true, breakpoints: seq[uint64] = @[], dis: bool = false, +proc runFile(f: string, fromString: bool = false, dump: bool = true, breakpoints: seq[uint64] = @[], warnings: seq[WarningKind] = @[], mismatches: bool = false, mode: CompileMode = Debug, run: bool = true, backend: PeonBackend = PeonBackend.Bytecode, output: string) = var @@ -183,7 +183,7 @@ proc runFile(f: string, fromString: bool = false, dump: bool = true, breakpoints tokens = tokenizer.lex(input, f) if tokens.len() == 0: return - when debugLexer: + if debugLexer: styledEcho fgCyan, "Tokenization step:" for i, token in tokens: if i == tokens.high(): @@ -194,7 +194,7 @@ proc runFile(f: string, fromString: bool = false, dump: bool = true, breakpoints tree = parser.parse(tokens, f, tokenizer.getLines(), input) if tree.len() == 0: return - when debugParser: + if debugParser: styledEcho fgCyan, "Parsing step:" for node in tree: styledEcho fgGreen, "\t", $node @@ -202,11 +202,9 @@ proc runFile(f: string, fromString: bool = false, dump: bool = true, breakpoints case backend: of PeonBackend.Bytecode: compiled = compiler.compile(tree, f, tokenizer.getLines(), input, disabledWarnings=warnings, showMismatches=mismatches, mode=mode) - when debugCompiler: + if debugCompiler: styledEcho fgCyan, "Compilation step:\n" debugger.disassembleChunk(compiled, f) - if dis: - debugger.disassembleChunk(compiled, f) var path = splitFile(if output.len() > 0: output else: f).dir if path.len() > 0: path &= "/" @@ -221,36 +219,35 @@ proc runFile(f: string, fromString: bool = false, dump: bool = true, breakpoints stderr.styledWriteLine(fgRed, styleBright, "Error: ", fgDefault, "the selected backend is not implemented yet") elif backend == PeonBackend.Bytecode: serialized = serializer.loadFile(f) - if backend == PeonBackend.Bytecode: - when debugSerializer: - styledEcho fgCyan, "Serialization step: " - styledEcho fgBlue, "\t- Peon version: ", fgYellow, &"{serialized.version.major}.{serialized.version.minor}.{serialized.version.patch}", fgBlue, " (commit ", fgYellow, serialized.commit[0..8], fgBlue, ") on branch ", fgYellow, serialized.branch - stdout.styledWriteLine(fgBlue, "\t- Compilation date & time: ", fgYellow, fromUnix(serialized.compileDate).format("d/M/yyyy HH:mm:ss")) - stdout.styledWrite(fgBlue, &"\t- Constants segment: ") - if serialized.chunk.consts == compiled.consts: - styledEcho fgGreen, "OK" - else: - styledEcho fgRed, "Corrupted" - stdout.styledWrite(fgBlue, &"\t- Code segment: ") - if serialized.chunk.code == compiled.code: - styledEcho fgGreen, "OK" - else: - styledEcho fgRed, "Corrupted" - stdout.styledWrite(fgBlue, "\t- Line info segment: ") - if serialized.chunk.lines == compiled.lines: - styledEcho fgGreen, "OK" - else: - styledEcho fgRed, "Corrupted" - stdout.styledWrite(fgBlue, "\t- Functions segment: ") - if serialized.chunk.functions == compiled.functions: - styledEcho fgGreen, "OK" - else: - styledEcho fgRed, "Corrupted" - stdout.styledWrite(fgBlue, "\t- Modules segment: ") - if serialized.chunk.modules == compiled.modules: - styledEcho fgGreen, "OK" - else: - styledEcho fgRed, "Corrupted" + if backend == PeonBackend.Bytecode and debugSerializer: + styledEcho fgCyan, "Serialization step: " + styledEcho fgBlue, "\t- Peon version: ", fgYellow, &"{serialized.version.major}.{serialized.version.minor}.{serialized.version.patch}", fgBlue, " (commit ", fgYellow, serialized.commit[0..8], fgBlue, ") on branch ", fgYellow, serialized.branch + stdout.styledWriteLine(fgBlue, "\t- Compilation date & time: ", fgYellow, fromUnix(serialized.compileDate).format("d/M/yyyy HH:mm:ss")) + stdout.styledWrite(fgBlue, &"\t- Constants segment: ") + if serialized.chunk.consts == compiled.consts: + styledEcho fgGreen, "OK" + else: + styledEcho fgRed, "Corrupted" + stdout.styledWrite(fgBlue, &"\t- Code segment: ") + if serialized.chunk.code == compiled.code: + styledEcho fgGreen, "OK" + else: + styledEcho fgRed, "Corrupted" + stdout.styledWrite(fgBlue, "\t- Line info segment: ") + if serialized.chunk.lines == compiled.lines: + styledEcho fgGreen, "OK" + else: + styledEcho fgRed, "Corrupted" + stdout.styledWrite(fgBlue, "\t- Functions segment: ") + if serialized.chunk.functions == compiled.functions: + styledEcho fgGreen, "OK" + else: + styledEcho fgRed, "Corrupted" + stdout.styledWrite(fgBlue, "\t- Modules segment: ") + if serialized.chunk.modules == compiled.modules: + styledEcho fgGreen, "OK" + else: + styledEcho fgRed, "Corrupted" if run: case backend: of PeonBackend.Bytecode: @@ -286,7 +283,6 @@ when isMainModule: var dump: bool = true var warnings: seq[WarningKind] = @[] var breaks: seq[uint64] = @[] - var dis: bool = false var mismatches: bool = false var mode: CompileMode = CompileMode.Debug var run: bool = true @@ -352,7 +348,7 @@ when isMainModule: stderr.styledWriteLine(fgRed, styleBright, "Error: ", fgDefault, &"error: invalid breakpoint value '{point}'") quit() of "disassemble": - dis = true + debugCompiler = true of "compile": run = false of "output": @@ -363,8 +359,12 @@ when isMainModule: backend = PeonBackend.Bytecode of "c": backend = PeonBackend.NativeC - of "cpp": - backend = PeonBackend.NativeCpp + of "debug-dump": + debugSerializer = true + of "debug-lexer": + debugLexer = true + of "debug-parser": + debugParser = true else: stderr.styledWriteLine(fgRed, styleBright, "Error: ", fgDefault, &"error: unkown option '{key}'") quit() @@ -405,7 +405,7 @@ when isMainModule: of "c": run = false of "d": - dis = true + debugCompiler = true else: stderr.styledWriteLine(fgRed, styleBright, "Error: ", fgDefault, &"unkown option '{key}'") quit() @@ -417,4 +417,4 @@ when isMainModule: if file == "": repl(warnings, mismatches, mode, breaks) else: - runFile(file, fromString, dump, breaks, dis, warnings, mismatches, mode, run, backend, output) + runFile(file, fromString, dump, breaks, warnings, mismatches, mode, run, backend, output)