This module defines the Chunk type, which represents a chunk of bytecode. It also defines the Script type, which represents a script being executed by the interpreter.
This module provides utilities for emitting bytecode into a chunk, as well as for managing line information for error reporting
Types
Chunk {.acyclic.} = ref object file*: string code*: seq[uint8] ## the raw bytecode ln*: int = 1 ## the current line number, used when emitting ## bytecode col*: int ## the current column number, used when emitting bytecode strings*: seq[string] = [] ## seq of strings used in this chunk (for string literals, global names, etc.)
- A chunk of bytecode
LineInfo = tuple[file: string, ln, col: int, runLength: int]
- Line information.
Opcode {..} = enum opcNoop = "noop", opcPushTrue = "pushTrue", opcPushFalse = "pushFalse", opcPushNil = "pushNil", opcPushJNil = "pushJNil", ## push a JSON nil opcPushI = "pushI", ## push int opcPushF = "pushF", ## push float opcPushS = "pushS", ## push string opcPushG = "pushG", ## push global opcPopG = "popG", ## pop global opcPushL = "pushL", ## push local opcPopL = "popL", ## pop local opcFFIGetProc = "ffiGetProc", ## get a symbol from a dynamic library opcPushPointer = "pushPointer", opcPopPointer = "popPointer", opcConstrObj = "constrObj", ## construct object opcGetF = "getF", ## push field opcSetF = "setF", ## pop field opcConstrArray = "constrArray", ## construct array opcGetI = "getI", ## get array item opcSetI = "setI", ## set array item opcDiscard = "discard", ## discard values opcGetJ = "getJ", ## get JSON value opcSetJ = "setJ", ## set JSON value opcNegI = "negI", ## negate int opcAddI = "addI", ## add ints opcSubI = "subI", ## subtract ints opcMultI = "multI", ## multiply ints opcDivI = "divI", ## divide ints opcNegF = "negF", ## negate float opcAddF = "addF", ## add floats opcSubF = "subF", ## subtract floats opcMultF = "multF", ## multiply floats opcDivF = "divF", ## divide floats opcInvB = "invB", ## invert bool opcEqB = "eqB", ## equal bools opcEqI = "eqI", ## equal ints opcLessI = "lessI", ## int less than opcGreaterI = "greaterI", ## int greater than opcEqF = "eqF", ## equal floats opcLessF = "lessF", ## float less than opcGreaterF = "greaterF", ## float greater than opcJumpFwd = "jumpFwd", ## jump forward opcJumpFwdT = "jumpFwdT", ## jump forward if true opcJumpFwdF = "jumpFwdF", ## jump forward if false opcJumpBack = "jumpBack", ## jump backward opcCallD = "callD", ## call direct opcCallI = "callI", ## call indirect opcReturnVal = "returnVal", ## return value from proc opcReturnVoid = "returnVoid", ## return void from proc opcImportModule = "importModule", ## import a module opcImportModuleAlias = "importModuleAlias", ## import a module with an alias opcImportFromModule = "importFromModule", ## import a symbol from a module opcHalt = "halt" ## halt the VM
- An opcode, used for execution.
Proc {.acyclic.} = ref object name*: string case kind*: ProcKind of pkNative: chunk*: Chunk ## the chunk of bytecode of this procedure of pkForeign: foreign*: ForeignProc ## the foreign implementation of this procedure paramCount*: int ## the number of parameters this procedure takes hasResult*: bool ## flag signifying whether the proc returns a value
- A runtime procedure.
ProcKind = enum pkNative, ## a native (bytecode) proc pkForeign ## a foreign (Nim) proc defined at compile-time
- The kind of a procedure. This is used to determine how the procedure should be called.
Script {.acyclic.} = ref object stdpos*: int libs*: Table[string, LibHandle] ## a table of dynamic libraries loaded by this script procs*: seq[Proc] ## all procs declared in this script procsExport*: seq[Proc] ## the public procs declared in this script ## these are the procs that can be called from ## other scripts mainChunk*: Chunk ## the main chunk of this script scripts*: Table[string, Script] ## a table of scripts, basically reprresenting the ## modules the script imports jsOutput*: string typeCount*: int ## the number of types in this script. ## used for compilation
Procs
proc addLineInfo(chunk: var Chunk; n: int) {....raises: [], tags: [], forbids: [].}
- Add n line info entries to the chunk.
proc getLineInfo(chunk: Chunk; i: int): LineInfo {....raises: [], tags: [], forbids: [].}
- Get the line info at position i. Warning: This is very slow, because it has to walk the entire chunk decoding the run length encoded line info!
proc getLineInfoTable(chunk: Chunk): seq[LineInfo] {....raises: [], tags: [], forbids: [].}
- Get the line info table for this chunk, expanding the run-length encoding.
proc rebuildStringIds(chunk: var Chunk) {....raises: [], tags: [], forbids: [].}
- Rebuild the string ID table from the strings sequence. This is necessary after deserializing a chunk, because the string IDs are not stored in the serialized form of the chunk.
proc setLineInfoTable(chunk: var Chunk; info: seq[LineInfo]) {....raises: [], tags: [], forbids: [].}
- Set the line info table for this chunk, compressing it with run-length encoding.