Got rid of serializedRaw in main module and prettyfied the output

This commit is contained in:
Mattia Giambirtone 2022-05-20 18:34:14 +02:00
parent 5b9206a580
commit e4c2ba2ce2
3 changed files with 76 additions and 68 deletions

View File

@ -2,6 +2,8 @@
import sequtils
import strformat
import strutils
import terminal
# Thanks art <3
import jale/editor as ed
import jale/templates
import jale/plugin/defaults
@ -45,7 +47,6 @@ when isMainModule:
tree: seq[Declaration] = @[]
compiled: Chunk
serialized: Serialized
serializedRaw: seq[byte]
tokenizer = newLexer()
parser = newParser()
compiler = newCompiler()
@ -55,6 +56,8 @@ when isMainModule:
input: string
tokenizer.fillSymbolTable()
editor.bindEvent(jeQuit):
stdout.styledWriteLine(fgGreen, "Goodbye!")
editor.prompt = ""
keep = false
editor.bindKey("ctrl+a"):
editor.content.home()
@ -66,90 +69,84 @@ when isMainModule:
if input.len() == 0:
continue
# Currently the parser doesn't handle these tokens well
tokens = filter(tokenizer.lex(input, "stdin"), proc (
x: Token): bool = x.kind notin {TokenType.Whitespace, Tab})
tokens = tokenizer.lex(input, "stdin")
if tokens.len() == 0:
continue
when debugLexer:
echo "Tokenization step:"
styledEcho fgCyan, "Tokenization step:"
for i, token in tokens:
if i == tokens.high():
# Who cares about EOF?
break
echo "\t", token
styledEcho fgGreen, "\t", $token
echo ""
tree = parser.parse(tokens, "stdin")
if tree.len() == 0:
continue
when debugParser:
echo "Parsing step:"
styledEcho fgCyan, "Parsing step:"
for node in tree:
echo "\t", node
styledEcho fgGreen, "\t", $node
echo ""
compiled = compiler.compile(tree, "stdin")
when debugCompiler:
echo "Compilation step:"
stdout.write("\t")
echo &"""Raw byte stream: [{compiled.code.join(", ")}]"""
echo "\nBytecode disassembler output below:\n"
styledEcho fgCyan, "Compilation step:"
stdout.styledWrite(fgCyan, "\tRaw byte stream: ", fgGreen, "[", fgYellow, compiled.code.join(", "), fgGreen, "]")
styledEcho fgCyan, "\n\nBytecode disassembler output below:\n"
disassembleChunk(compiled, "stdin")
echo ""
serializer.dumpToFile(compiled, input, "stdin", "stdin.pbc")
serializedRaw = serializer.dumpBytes(compiled, input, "stdin")
serializer.dumpFile(compiled, input, "stdin", "stdin.pbc")
serialized = serializer.loadFile("stdin.pbc")
when debugSerializer:
echo "Serialization step: "
stdout.write("\t")
echo &"""Raw hex output: {serializedRaw.mapIt(toHex(it)).join("").toLowerAscii()}"""
echo ""
echo &"\t- File hash: {serialized.fileHash} (matches: {computeSHA256(input).toHex().toLowerAscii() == serialized.fileHash})"
echo &"\t- Peon version: {serialized.peonVer.major}.{serialized.peonVer.minor}.{serialized.peonVer.patch} (commit {serialized.commitHash[0..8]} on branch {serialized.peonBranch})"
stdout.write("\t")
echo &"""- Compilation date & time: {fromUnix(serialized.compileDate).format("d/M/yyyy HH:mm:ss")}"""
stdout.write(&"\t- Reconstructed constants table: [")
for i, e in serialized.chunk.consts:
stdout.write(e)
if i < len(serialized.chunk.consts) - 1:
stdout.write(", ")
stdout.write(&"] (matches: {serialized.chunk.consts == compiled.consts})\n")
stdout.write(&"\t- Reconstructed bytecode: [")
for i, e in serialized.chunk.code:
stdout.write($e)
if i < len(serialized.chunk.code) - 1:
stdout.write(", ")
stdout.write(&"] (matches: {serialized.chunk.code == compiled.code})\n")
var hashMatches = computeSHA256(input).toHex().toLowerAscii() == serialized.fileHash
styledEcho fgCyan, "Serialization step: "
styledEcho fgBlue, &"\t- File hash: ", fgYellow, serialized.fileHash, fgBlue, " (", if hashMatches: fgGreen else: fgRed, if hashMatches: "OK" else: "Fail", fgBlue, ")"
styledEcho fgBlue, "\t- Peon version: ", fgYellow, &"{serialized.peonVer.major}.{serialized.peonVer.minor}.{serialized.peonVer.patch}", fgBlue, " (commit ", fgYellow, serialized.commitHash[0..8], fgBlue, ") on branch ", fgYellow, serialized.peonBranch
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"
when debugRuntime:
echo "Execution step: "
styledEcho fgCyan, "\n\nExecution step: "
vm.run(serialized.chunk)
except IOError:
break
# TODO: The code for error reporting completely
# breaks down with multiline input, fix it
except LexingError:
# let lineNo = tokenizer.getLine()
# let relPos = tokenizer.getRelPos(lineNo)
# let line = tokenizer.getSource().splitLines()[lineNo - 1].strip()
echo getCurrentExceptionMsg()
stderr.styledWriteLine(fgRed, getCurrentExceptionMsg())
# echo &"Source line: {line}"
# echo " ".repeat(relPos.start + len("Source line: ")) & "^".repeat(relPos.stop - relPos.start)
except ParseError:
# let lineNo = parser.getCurrentToken().line
# let relPos = tokenizer.getRelPos(lineNo)
# let line = tokenizer.getSource().splitLines()[lineNo - 1].strip()
echo getCurrentExceptionMsg()
stderr.styledWriteLine(fgRed, getCurrentExceptionMsg())
# echo &"Source line: {line}"
# echo " ".repeat(relPos.start + len("Source line: ")) & "^".repeat(relPos.stop - parser.getCurrentToken().lexeme.len())
except CompileError:
# let lineNo = compiler.getCurrentNode().token.line
# let relPos = tokenizer.getRelPos(lineNo)
# let line = tokenizer.getSource().splitLines()[lineNo - 1].strip()
echo getCurrentExceptionMsg()
stderr.styledWriteLine(fgRed, getCurrentExceptionMsg())
# echo &"Source line: {line}"
# echo " ".repeat(relPos.start + len("Source line: ")) & "^".repeat(relPos.stop - compiler.getCurrentNode().token.lexeme.len())
except SerializationError:
echo getCurrentExceptionMsg()
stderr.styledWriteLine(fgRed, getCurrentExceptionMsg())
quit(0)

View File

@ -25,15 +25,14 @@ proc nl = stdout.write("\n")
proc printDebug(s: string, newline: bool = false) =
stdout.write(&"DEBUG - Disassembler -> {s}")
stdout.styledWrite(fgMagenta, "DEBUG - Disassembler -> ")
stdout.styledWrite(fgGreen, s)
if newline:
nl()
proc printName(name: string, newline: bool = false) =
setForegroundColor(fgRed)
stdout.write(name)
setForegroundColor(fgGreen)
stdout.styledWrite(fgRed, name)
if newline:
nl()
@ -57,9 +56,8 @@ proc stackTripleInstruction(instruction: OpCode, chunk: Chunk,
var slot = [chunk.code[offset + 1], chunk.code[offset + 2], chunk.code[
offset + 3]].fromTriple()
printInstruction(instruction)
stdout.write(&", points to index ")
setForegroundColor(fgYellow)
stdout.write(&"{slot}")
stdout.styledWrite(fgGreen, &", points to index ")
stdout.styledWrite(fgYellow, &"{slot}")
nl()
return offset + 4
@ -70,14 +68,13 @@ proc stackDoubleInstruction(instruction: OpCode, chunk: Chunk,
var slot = [chunk.code[offset + 1], chunk.code[offset + 2]].fromDouble()
printInstruction(instruction)
stdout.write(&", points to index ")
setForegroundColor(fgYellow)
stdout.write(&"{slot}")
stdout.styledWrite(fgGreen, &", points to index ")
stdout.styledWrite(fgYellow, &"{slot}")
nl()
return offset + 3
proc argumentDoubleInstruction(instruction: OpCode, chunk: Chunk,
offset: int): int =
proc argumentDoubleInstruction(instruction: OpCode, chunk: Chunk, offset: int): int =
## Debugs instructions that operate on a hardcoded value on the stack using a 16-bit operand
var slot = [chunk.code[offset + 1], chunk.code[offset + 2]].fromDouble()
printInstruction(instruction)
@ -93,16 +90,13 @@ proc constantInstruction(instruction: OpCode, chunk: Chunk, offset: int): int =
var constant = [chunk.code[offset + 1], chunk.code[offset + 2], chunk.code[
offset + 3]].fromTriple()
printInstruction(instruction)
stdout.write(&", points to constant at position ")
stdout.styledWrite(fgGreen, &", points to constant at position ")
setForegroundColor(fgYellow)
stdout.write(&"{constant}")
nl()
let obj = chunk.consts[constant]
setForegroundColor(fgGreen)
printDebug("Operand: ")
setForegroundColor(fgYellow)
stdout.write(&"{obj}\n")
setForegroundColor(fgGreen)
stdout.styledWrite(fgYellow, &"{obj}\n")
return offset + 4
@ -120,23 +114,18 @@ proc jumpInstruction(instruction: OpCode, chunk: Chunk, offset: int): int =
discard # Unreachable
printInstruction(instruction, true)
printDebug("Jump size: ")
setForegroundColor(fgYellow)
stdout.write($jump)
stdout.styledWrite(fgYellow, $jump)
nl()
return offset + 3
proc disassembleInstruction*(chunk: Chunk, offset: int): int =
## Takes one bytecode instruction and prints it
setForegroundColor(fgGreen)
printDebug("Offset: ")
setForegroundColor(fgYellow)
echo offset
setForegroundColor(fgGreen)
stdout.styledWriteLine(fgYellow, $offset)
printDebug("Line: ")
setForegroundColor(fgYellow)
stdout.write(&"{chunk.getLine(offset)}\n")
setForegroundColor(fgGreen)
stdout.styledWriteLine(fgYellow, &"{chunk.getLine(offset)}")
var opcode = OpCode(chunk.code[offset])
case opcode:
of simpleInstructions:
@ -163,7 +152,6 @@ proc disassembleChunk*(chunk: Chunk, name: string) =
while index < chunk.code.len:
index = disassembleInstruction(chunk, index)
echo ""
setForegroundColor(fgDefault)
echo &"==== Debug session ended - Chunk '{name}' ===="

View File

@ -102,6 +102,14 @@ proc writeHeaders(self: Serializer, stream: var seq[byte], file: string) =
stream.extend(self.toBytes(computeSHA256(file)))
proc writeLineData(self: Serializer, stream: var seq[byte]) =
## Writes line information for debugging
## bytecode instructions
stream.extend(len(self.chunk.lines).toQuad())
for b in self.chunk.lines:
stream.extend(b.toTriple())
proc writeConstants(self: Serializer, stream: var seq[byte]) =
## Writes the constants table in-place into the
## given stream
@ -145,6 +153,18 @@ proc readHeaders(self: Serializer, stream: seq[byte], serialized: Serialized): i
result += 32
proc readLineData(self: Serializer, stream: seq[byte]): int =
## Reads line information from a stream
## of bytes
let size = [stream[0], stream[1], stream[2], stream[3]].fromQuad()
result += 4
var stream = stream[4..^1]
for i in countup(0, int(size) - 1):
self.chunk.lines.add(int([stream[0], stream[1], stream[2]].fromTriple()))
result += 3
stream = stream[3..^1]
proc readConstants(self: Serializer, stream: seq[byte]): int =
## Reads the constant table from the given stream
## of bytes
@ -169,16 +189,18 @@ proc readCode(self: Serializer, stream: seq[byte]): int =
proc dumpBytes*(self: Serializer, chunk: Chunk, file, filename: string): seq[byte] =
## Dumps the given bytecode and file to a sequence of bytes and returns it.
## The file argument must be the actual file's content and is needed to compute its SHA256 hash.
## The file argument must be the actual file's content and is needed to
## compute its SHA256 hash.
self.file = file
self.filename = filename
self.chunk = chunk
self.writeHeaders(result, self.file)
self.writeLineData(result)
self.writeConstants(result)
self.writeCode(result)
proc dumpToFile*(self: Serializer, chunk: Chunk, file, filename, dest: string) =
proc dumpFile*(self: Serializer, chunk: Chunk, file, filename, dest: string) =
## Dumps the result of dumpBytes to a file at dest
var fp = open(dest, fmWrite)
defer: fp.close()
@ -196,6 +218,7 @@ proc loadBytes*(self: Serializer, stream: seq[byte]): Serialized =
var stream = stream
try:
stream = stream[self.readHeaders(stream, result)..^1]
stream = stream[self.readLineData(stream)..^1]
stream = stream[self.readConstants(stream)..^1]
stream = stream[self.readCode(stream)..^1]
except IndexDefect: