Made the serializer follow the spec (the 3 byte header was missing)
This commit is contained in:
parent
df67e7db64
commit
afa4369321
|
@ -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
|
||||
|
|
|
@ -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")
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue