nondescript/chunk.nim

117 lines
3.2 KiB
Nim
Raw Normal View History

2022-01-20 21:54:11 +01:00
import strformat
import strutils
import value
type
OpCode* = enum
2022-01-21 01:51:55 +01:00
opReturn, opCall, # functions
2022-01-20 21:54:11 +01:00
opPop, # pop
opPrint, # print
opNegate, opNot # unary
opAdd, opSubtract, opMultiply, opDivide, # math
opEqual, opGreater, opLess, # comparison
opTrue, opFalse, opNil, # literal
opConstant, # constant
opDefineGlobal, opGetGlobal, opSetGlobal, # globals (uses constants)
opGetLocal, opSetLocal, # locals
opJumpIfFalse, opJump, opLoop, opJumpIfFalsePop, # jumps
Chunk* = object
code*: seq[uint8]
constants*: seq[KonValue]
lines*: seq[int]
2022-01-21 00:18:58 +01:00
name*: string # name of the module/chunk/files
2022-01-20 21:54:11 +01:00
Triple* = array[3, uint8]
2022-01-21 00:18:58 +01:00
proc initChunk*(name: string): Chunk =
Chunk(code: @[], name: name, lines: @[], constants: @[])
2022-01-20 21:54:11 +01:00
proc writeChunk*(ch: var Chunk, code: uint8, line: int) =
ch.code.add(code)
ch.lines.add(line)
proc writeChunk*(ch: var Chunk, code: OpCode, line: int) =
ch.code.add(code.uint8)
ch.lines.add(line)
proc writeChunk*(ch: var Chunk, code: Triple, line: int) =
for c in code:
ch.code.add(c)
ch.lines.add(line)
proc len*(ch: Chunk): int =
ch.code.len
proc toTriple*(integer: int): Triple =
var integer = integer
result[0] = integer.uint8
integer = integer div 256
result[1] = integer.uint8
integer = integer div 256
result[2] = integer.uint8
proc toInt*(triple: Triple): int =
triple[0].int + triple[1].int * 256 + triple[2].int * 256 * 256
proc addConstant*(ch: var Chunk, constant: KonValue): int =
ch.constants.add(constant)
ch.constants.high
proc writeConstant*(ch: var Chunk, constant: KonValue, line: int): int =
result = ch.addConstant(constant)
ch.writeChunk(opConstant, line)
ch.writeChunk(result.toTriple, line)
const simpleInstructions = {
2022-01-21 01:51:55 +01:00
opReturn,
2022-01-20 21:54:11 +01:00
opPop,
opPrint,
opNegate, opNot,
opAdd, opSubtract, opMultiply, opDivide,
opEqual, opGreater, opLess,
opTrue, opFalse, opNil
}
const constantInstructions = {
opConstant,
opDefineGlobal, opGetGlobal, opSetGlobal,
}
const argInstructions = {
2022-01-21 01:51:55 +01:00
opCall,
2022-01-20 21:54:11 +01:00
opGetLocal, opSetLocal,
opJumpIfFalse, opJump, opLoop, opJumpIfFalsePop,
}
const tripleMax*: int = 16777215
proc disassembleChunk*(ch: Chunk) =
2022-01-21 00:18:58 +01:00
echo &"== Chunk {ch.name} begin =="
2022-01-20 21:54:11 +01:00
echo "index line instruction"
var c: int = 0
var lastLine = -1
while c < ch.code.len:
template instruction: uint8 = ch.code[c]
template line: int = ch.lines[c]
template triple: Triple = [ch.code[c+1], ch.code[c+2], ch.code[c+3]]
let cFmt = &"{c:04}"
let lineFmt = if lastLine == line: " | " else: &"{line:04}"
try:
write stdout, &"[{cFmt}] {lineFmt} {instruction.OpCode} ({instruction.toHex(2)}"
case instruction.OpCode:
of simpleInstructions:
write stdout, ")\n"
of argInstructions:
write stdout, &" {triple[0].toHex(2)} {triple[1].toHex(2)} {triple[2].toHex(2)})\n"
c += 3
of constantInstructions:
let i = triple.toInt
write stdout, &" {triple[0].toHex(2)} {triple[1].toHex(2)} {triple[2].toHex(2)})\n"
echo &" points to constant {ch.constants[i]} (i: {i})"
c += 3
except:
echo &"[{cFmt}] {lineFmt} Unknown opcode {instruction}"
c.inc
2022-01-21 00:18:58 +01:00
echo &"== Chunk {ch.name} end =="
2022-01-20 21:54:11 +01:00