Made the serializer follow the spec (the 3 byte header was missing)

This commit is contained in:
Nocturn9x 2021-11-12 16:56:41 +01:00
parent df67e7db64
commit afa4369321
3 changed files with 35 additions and 11 deletions

View File

@ -68,7 +68,7 @@ Once a JAPL source file (i.e. one with a ".jpl" extension, without quotes) has b
An object file starts with the headers, namely:
- A 13-byte constant string with the value `"JAPL_BYTECODE"` (without quotes)
- A 13-byte constant string with the value `"JAPL_BYTECODE"` (without quotes) encoded as a sequence of integers of the ASCII encoding of each character in the string
- A 3-byte version header composed of 3 unsigned integers representing the major, minor and patch version of the compiler used to generate the file, respectively. JAPL follows the SemVer standard for versioning
- A string representing the branch name of the git repo from which JAPL was compiled, prepended with its size represented as a single 8-bit unsigned integer. Due to this encoding the branch name can't be longer than 256 characters, which is a length deemed appropriate for this purpose
- A 40 bytes hexadecimal string, pinpointing the version of the compiler down to the exact commit hash in the JAPL repository, particularly useful when testing development versions
@ -77,7 +77,7 @@ An object file starts with the headers, namely:
### Constant section
This section of the file follows the headers and is meant to store all constants needed upon startup by the JAPL virtual machine. For example, the code `var x = 1;` would have the number one as a constant. Constants are a compile-time view of the state of the VM's stack at runtime.
This section of the file follows the headers and is meant to store all constants needed upon startup by the JAPL virtual machine. For example, the code `var x = 1;` would have the number one as a constant.
## Behavior

View File

@ -36,9 +36,10 @@ type
## procedures to store
## metadata
fileHash*: string
japlVer*: string
japlVer*: tuple[major, minor, patch: int]
japlBranch*: string
commitHash*: string
compileDate*: int
chunk*: Chunk
@ -68,6 +69,15 @@ proc toBytes(self: Serializer, d: SHA256Digest): seq[byte] =
result.add(b)
proc bytesToString(self: Serializer, input: seq[byte]): string =
for b in input:
result.add(char(b))
proc bytesToInt(self: Serializer, input: seq[byte]): int =
copyMem(result.addr, input.unsafeAddr, sizeof(int))
proc extend[T](s: var seq[T], a: openarray[T]) =
for e in a:
s.add(e)
@ -80,6 +90,9 @@ proc dumpBytes*(self: Serializer, chunk: Chunk, file, filename: string): seq[byt
self.filename = filename
self.chunk = chunk
result.extend(self.toBytes(BYTECODE_MARKER))
result.add(byte(JAPL_VERSION.major))
result.add(byte(JAPL_VERSION.minor))
result.add(byte(JAPL_VERSION.patch))
result.add(byte(len(JAPL_BRANCH)))
result.extend(self.toBytes(JAPL_BRANCH))
if len(JAPL_COMMIT_HASH) != 40:
@ -131,12 +144,23 @@ proc loadBytes*(self: Serializer, stream: seq[byte]): Serialized =
new(result)
result.chunk = newChunk()
var stream = stream
if stream[0..<len(BYTECODE_MARKER)] != self.toBytes(BYTECODE_MARKER):
self.error("malformed bytecode marker")
stream = stream[len(BYTECODE_MARKER)..^1]
try:
if stream[0..<len(BYTECODE_MARKER)] != self.toBytes(BYTECODE_MARKER):
self.error("malformed bytecode marker")
stream = stream[len(BYTECODE_MARKER) - 1..^1]
result.japlVer = (major: int(stream[0]), minor: int(stream[1]), patch: int(stream[2]))
stream = stream[2..^1]
let branchLength = stream[0]
stream = stream[1..^1]
result.japlBranch = self.bytesToString(stream[0..<branchLength])
stream = stream[branchLength..^1]
result.commitHash = self.bytesToString(stream[0..<40]).toHex()
stream = stream[39..^1]
result.compileDate = self.bytesToInt(stream[0..7])
stream = stream[7..^1]
result.fileHash = self.bytesToString(stream[0..<32]).toHex()
except IndexDefect:
self.error("truncated bytecode file")

View File

@ -18,7 +18,7 @@ const BYTECODE_MARKER* = "JAPL_BYTECODE"
const MAP_LOAD_FACTOR* = 0.75 # Load factor for builtin hashmaps
const HEAP_GROW_FACTOR* = 2 # How much extra memory to allocate for dynamic arrays and garbage collection when resizing
const MAX_STACK_FRAMES* = 800 # The maximum number of stack frames at any one time. Acts as a recursion limiter (1 frame = 1 call)
const JAPL_VERSION* = "0.4.0"
const JAPL_VERSION* = (major: 0, minor: 4, patch: 0)
const JAPL_RELEASE* = "alpha"
const JAPL_COMMIT_HASH* = "b252749d0e5448b8fef64150299d8318362bc08c"
const JAPL_BRANCH* = "master"
@ -27,7 +27,7 @@ const SKIP_STDLIB_INIT* = false # Skips stdlib initialization (can be imported m
const DEBUG_TRACE_GC* = false # Traces the garbage collector (TODO)
const DEBUG_TRACE_ALLOCATION* = false # Traces memory allocation/deallocation
const DEBUG_TRACE_COMPILER* = false # Traces the compiler
const JAPL_VERSION_STRING* = &"JAPL {JAPL_VERSION} ({JAPL_RELEASE}, {CompileDate}, {CompileTime}) on branch {JAPL_BRANCH} ({JAPL_COMMIT_HASH[0..8]})"
const JAPL_VERSION_STRING* = &"JAPL {JAPL_VERSION.major}.{JAPL_VERSION.minor}.{JAPL_VERSION.patch} ({JAPL_RELEASE}, {CompileDate}, {CompileTime}) on branch {JAPL_BRANCH} ({JAPL_COMMIT_HASH[0..8]})"
const HELP_MESSAGE* = """The JAPL language, Copyright (C) 2021 Mattia Giambirtone & All contributors
This program is free software, see the license distributed with this program or check