|
7 | 7 | # Made by Humans from OpenPeeps |
8 | 8 | # https://github.com/openpeeps/tim | https://openpeeps.dev/packages/tim |
9 | 9 |
|
10 | | -import std/[tables] |
| 10 | +import std/[tables, hashes, dynlib] |
11 | 11 |
|
12 | 12 | import value |
13 | 13 |
|
|
20 | 20 | opcPushTrue = "pushTrue" |
21 | 21 | opcPushFalse = "pushFalse" |
22 | 22 | opcPushNil = "pushNil" |
| 23 | + opcPushJNil = "pushJNil" ## push a JSON nil |
| 24 | + |
23 | 25 | opcPushI = "pushI" ## push int |
24 | 26 | opcPushF = "pushF" ## push float |
25 | 27 | opcPushS = "pushS" ## push string |
26 | 28 | opcPushG = "pushG" ## push global |
27 | 29 | opcPopG = "popG" ## pop global |
28 | 30 | opcPushL = "pushL" ## push local |
29 | 31 | opcPopL = "popL" ## pop local |
| 32 | + |
| 33 | + opcFFIGetProc = "ffiGetProc" ## get a symbol from a dynamic library |
| 34 | + opcPushPointer = "pushPointer" # push a pointer value onto the stack |
| 35 | + opcPopPointer = "popPointer" # pop a pointer value from the stack |
30 | 36 |
|
31 | 37 | opcConstrObj = "constrObj" ## construct object |
32 | 38 |
|
33 | 39 | opcGetF = "getF" ## push field |
34 | 40 | opcSetF = "setF" ## pop field |
| 41 | + |
35 | 42 | opcConstrArray = "constrArray" ## construct array |
36 | 43 | opcGetI = "getI" ## get array item |
| 44 | + opcSetI = "setI" ## set array item |
| 45 | + |
37 | 46 | opcDiscard = "discard" ## discard values |
38 | 47 |
|
39 | 48 | # json operations |
|
95 | 104 | opcViewLoader = "viewLoader" ## load a view |
96 | 105 | opcHalt = "halt" ## halt the VM |
97 | 106 |
|
98 | | - Script* = ref object |
| 107 | + Script* {.acyclic.} = ref object |
99 | 108 | stdpos*: int |
| 109 | + libs*: Table[string, LibHandle] |
| 110 | + ## a table of dynamic libraries loaded by this script |
100 | 111 | procs*: seq[Proc] |
101 | 112 | ## all procs declared in this script |
102 | 113 | procsExport*: seq[Proc] |
|
118 | 129 | ln, col: int |
119 | 130 | runLength: int |
120 | 131 |
|
121 | | - Chunk* = ref object |
| 132 | + Chunk* {.acyclic.} = ref object |
122 | 133 | ## A chunk of bytecode. |
123 | 134 | file*: string ## the filename of the module this chunk belongs to |
124 | 135 | code*: seq[uint8] ## the raw bytecode |
|
131 | 142 | pkNative ## a native (bytecode) proc |
132 | 143 | pkForeign ## a foreign (Nim) proc |
133 | 144 |
|
134 | | - Proc* = ref object |
| 145 | + Proc* {.acyclic.} = ref object |
135 | 146 | ## A runtime procedure. |
136 | 147 | name*: string |
137 | 148 | case kind*: ProcKind |
|
144 | 155 |
|
145 | 156 | proc addLineInfo*(chunk: var Chunk, n: int) = |
146 | 157 | ## Add ``n`` line info entries to the chunk. |
147 | | - |
148 | 158 | if chunk.lineInfo.len > 0: |
149 | 159 | if chunk.lineInfo[^1].ln == chunk.ln and |
150 | 160 | chunk.lineInfo[^1].col == chunk.col: |
@@ -191,6 +201,11 @@ proc emit*(chunk: var Chunk, val: float64) = |
191 | 201 | chunk.addLineInfo(ValueSize) |
192 | 202 | chunk.code.add(cast[array[sizeof(float64), uint8]](val)) |
193 | 203 |
|
| 204 | +proc emit*(chunk: var Chunk, xptr: pointer) = |
| 205 | + ## Emit a `pointer`. |
| 206 | + chunk.addLineInfo(sizeof(pointer)) |
| 207 | + chunk.code.add(cast[array[sizeof(pointer), uint8]](xptr)) |
| 208 | + |
194 | 209 | proc emitHole*(chunk: var Chunk, size: int): int = |
195 | 210 | ## Emit a hole, to be filled later by ``fillHole``. |
196 | 211 | result = chunk.code.len |
@@ -261,3 +276,10 @@ proc newScript*(main: Chunk): Script = |
261 | 276 | ## Create a new script, with the given main chunk. |
262 | 277 | result = Script(mainChunk: main) |
263 | 278 |
|
| 279 | +proc hash*(x: Chunk): Hash = |
| 280 | + ## Hashes a Chunk by its address |
| 281 | + hash(cast[pointer](x)) |
| 282 | + |
| 283 | +proc `==`*(a, b: Chunk): bool = |
| 284 | + ## Compares two Chunks by address |
| 285 | + hash(a) == hash(b) |
0 commit comments