Implementing bytecode compiler.
h3rald h3rald@h3rald.com
Fri, 04 Aug 2023 20:48:45 +0200
3 files changed,
60 insertions(+),
50 deletions(-)
M
min.nim
→
min.nim
@@ -230,8 +230,9 @@ if op == "interpret":
i.interpret(s) discard newSeq[string](0) elif op == "bytecode-compile": - var vm = newVM() - let code = vm.compileToBytecode("") + i.open(s, i.filename) + discard i.parser.getToken() + let code = i.parser.compileToBytecode() vm.printBytecode(code) else: discard i.compile(s, main)
M
minpkg/core/opcodes.nim
→
minpkg/core/opcodes.nim
@@ -1,42 +1,37 @@
type MinOpCode* = enum - opUndef = 0x00 # Undefined + + opUndef = 0x00 # Terminator/Undefined #### Header - opHead = 0x01 # Header - # 9 bytes in total - # language: 3 - # version: 3 - # bytecode: 1 - # undefined:2 + opHead = 0x01 # Header + # 9 bytes in total + # language: 3 + # version: 3 + # bytecode: 1 + # undefined:2 #### Start - opStart = 0x02 # Program start + opStart = 0x02 # Program start #### Literal Values - opPushIn = 0x11 # Push integer value - # value: 8 - opPushFl = 0x12 # Push float value - # value: 8 - opPushNl = 0x13 # Push null value - opPushTr = 0x14 # Push true value - opPushFa = 0x15 # Push false value - opStrBeg = 0x16 # Begin string - OpStrEnd = 0x17 # End String - OpQuotBeg = 0x18 # Begin quotation - OpQuotEnd = 0x19 # End quotation - OpDictBeg = 0x1A # Begin dictionary - # typelength: 2 - # typevalue: ... - OpDictEnd = 0x1B # End dictionary - OptCmdBeg = 0x1C # Begin command - OptCmdEnd = 0x1D # End command + opPushIn = 0x11 # Push integer value + # value: 8 + opPushFl = 0x12 # Push float value + # value: 8 + opPushNl = 0x13 # Push null value + opPushTr = 0x14 # Push true value + opPushFa = 0x15 # Push false value + opStr = 0x16 # Begin string + OpQuot = 0x17 # Begin quotation + OpDict = 0x18 # Begin dictionary + # type: ... 0 + OptCmd = 0x19 # Begin command #### Symbols - opSym = 0x20 # Push symbol - # length: 2 - # value: ... + opSym = 0x20 # Begin symbol + # value: ... 0 #### Stop - opStop = 0xFF # Program stop + opStop = 0xFF # Program stop
M
minpkg/core/vm.nim
→
minpkg/core/vm.nim
@@ -16,26 +16,40 @@ proc bytecode(s: string, symbol = false): seq[byte] =
result = newSeq[byte](0) if symbol: result.add opSym.byte - result.add s.len.byte - for c in s: - result.add c.ord.byte else: - result.add opStrBeg.byte - for c in s: - result.add c.ord.byte - result.add OpStrEnd.byte + result.add opStr.byte + for c in s: + result.add c.ord.byte + result.add opUndef.byte -proc bytecode(n: BiggestInt): seq[byte] = - result = newSeq[byte](0) - result.add opPushIn.byte - result = result.concat(cast[array[0..7, byte]](n).toSeq) -proc bytecode(n: BiggestFloat): seq[byte] = - result = newSeq[byte](0) - result.add opPushFl.byte - result = result.concat(cast[array[0..7, byte]](n).toSeq) +when cpuEndian == littleEndian: + proc bytecode(n: BiggestInt): seq[byte] = + result = newSeq[byte](0) + result.add opPushIn.byte + result = result.concat(cast[array[0..7, byte]](n).toSeq) -proc compileToBytecode*(vm: MinVm, s = ""): seq[byte] = + proc bytecode(n: BiggestFloat): seq[byte] = + result = newSeq[byte](0) + result.add opPushFl.byte + result = result.concat(cast[array[0..7, byte]](n).toSeq) +else: + import algorithm + + proc bytecode(n: BiggestInt): seq[byte] = + result = newSeq[byte](0) + result.add opPushIn.byte + result = result.concat(cast[array[0..7, byte]](n).toSeq) + result.reverse() + + proc bytecode(n: BiggestFloat): seq[byte] = + result = newSeq[byte](0) + result.add opPushFl.byte + result = result.concat(cast[array[0..7, byte]](n).toSeq) + result.reverse() + + +proc compileToBytecode*(p: var MinParser): seq[byte] = result = newSeq[byte](0) result.add opHead.byte for c in pkgName:@@ -46,7 +60,6 @@ result.add v[1].parseInt.byte
result.add v[2].parseInt.byte result.add opUndef.byte result.add opUndef.byte - var p = vm.parser case p.token: of tkNull: result.add opPushNl.byte@@ -77,8 +90,9 @@ else:
raiseUndefined(p, "Undefined value: '"&p.a&"'") -proc printBytecode*(vm: MinVm, code: seq[byte]) = +proc printBytecode*(code: seq[byte]) = for b in code: - echo b.toHex + stdout.write(b.toHex & " ") + stdout.writeLine("")