|
| 1 | +import std / [assertions, tables] |
| 2 | +import "../../dist/nimony/src/lib" / [bitabs, nifreader, nifstreams, nifcursors] |
| 3 | +import ".." / [ast, idents, lineinfos, options, modules, modulegraphs, msgs, pathutils] |
| 4 | +import enum2nif, icniftags |
| 5 | + |
| 6 | +type |
| 7 | + DecodeContext = object |
| 8 | + graph: ModuleGraph |
| 9 | + symbols: Table[int, PSym] |
| 10 | + types: Table[int, PType] |
| 11 | + |
| 12 | +proc nodeKind(n: Cursor): TNodeKind {.inline.} = |
| 13 | + assert n.kind == ParLe |
| 14 | + pool.tags[n.tagId].parseNodeKind() |
| 15 | + |
| 16 | +proc expect(n: Cursor; k: set[NifKind]) = |
| 17 | + if n.kind notin k: |
| 18 | + when defined(debug): |
| 19 | + writeStackTrace() |
| 20 | + quit "[NIF decoder] expected: " & $k & " but got: " & $n.kind & toString n |
| 21 | + |
| 22 | +proc expect(n: Cursor; k: NifKind) {.inline.} = |
| 23 | + expect n, {k} |
| 24 | + |
| 25 | +proc incExpect(n: var Cursor; k: set[NifKind]) = |
| 26 | + inc n |
| 27 | + expect n, k |
| 28 | + |
| 29 | +proc incExpect(n: var Cursor; k: NifKind) {.inline.} = |
| 30 | + incExpect n, {k} |
| 31 | + |
| 32 | +proc skipParRi(n: var Cursor) = |
| 33 | + expect n, {ParRi} |
| 34 | + inc n |
| 35 | + |
| 36 | +proc expectTag(n: Cursor; tagId: TagId) = |
| 37 | + if n.kind == ParLe and n.tagId == tagId: |
| 38 | + discard |
| 39 | + else: |
| 40 | + when defined(debug): |
| 41 | + writeStackTrace() |
| 42 | + if n.kind != ParLe: |
| 43 | + quit "[NIF decoder] expected: ParLe but got: " & $n.kind & toString n |
| 44 | + else: |
| 45 | + quit "[NIF decoder] expected: " & pool.tags[tagId] & " but got: " & pool.tags[n.tagId] & toString n |
| 46 | + |
| 47 | +proc incExpectTag(n: var Cursor; tagId: TagId) = |
| 48 | + inc n |
| 49 | + expectTag(n, tagId) |
| 50 | + |
| 51 | +when false: |
| 52 | + proc expectTag(n: Cursor; tag: string) = |
| 53 | + let id = pool.tags.getKeyId(tag) |
| 54 | + if id == TagId(0): |
| 55 | + when defined(debug): |
| 56 | + writeStackTrace() |
| 57 | + quit "[NIF decoder] expected: " & tag & " but doesn't exist" & toString n |
| 58 | + else: |
| 59 | + expectTag(n, id) |
| 60 | + |
| 61 | +proc fromNifSymbol(c: var DecodeContext; n: var Cursor): PSym |
| 62 | +proc fromNifType(c: var DecodeContext; n: var Cursor): PType |
| 63 | +proc fromNif(c: var DecodeContext; n: var Cursor): PNode |
| 64 | + |
| 65 | +proc fromNifSymDef(c: var DecodeContext; n: var Cursor): PSym = |
| 66 | + expectTag n, symIdTag |
| 67 | + incExpect n, IntLit |
| 68 | + let id = pool.integers[n.intId] |
| 69 | + incExpect n, Ident |
| 70 | + let ident = c.graph.cache.getIdent(pool.strings[n.litId]) |
| 71 | + incExpect n, IntLit |
| 72 | + let itemId = pool.integers[n.intId].int32 |
| 73 | + incExpect n, ParLe |
| 74 | + let kind = parseSymKind(pool.tags[n.tagId]) |
| 75 | + # TODO: add kind specific data |
| 76 | + inc n |
| 77 | + skipParRi n |
| 78 | + expect n, {Ident, DotToken} |
| 79 | + let flags = if n.kind == Ident: pool.strings[n.litId].parseSymFlags else: {} |
| 80 | + inc n |
| 81 | + var position = if kind == skModule: |
| 82 | + expect n, StringLit |
| 83 | + let path = pool.strings[n.litId].AbsoluteFile |
| 84 | + fileInfoIdx(c.graph.config, path).int |
| 85 | + else: |
| 86 | + expect n, IntLit |
| 87 | + pool.integers[n.intId] |
| 88 | + incExpect n, IntLit |
| 89 | + let disamb = pool.integers[n.intId].int32 |
| 90 | + inc n |
| 91 | + |
| 92 | + result = PSym(itemId: ItemId(module: 0, item: itemId), |
| 93 | + kind: kind, |
| 94 | + name: ident, |
| 95 | + flags: flags, |
| 96 | + position: position, |
| 97 | + disamb: disamb) |
| 98 | + |
| 99 | + # PNode, PSym or PType type fields in PSym can have cycles. |
| 100 | + # Add PSym to `c.symbols` before parsing these fields so that |
| 101 | + # they can refer this PSym. |
| 102 | + assert id notin c.symbols |
| 103 | + c.symbols[id] = result |
| 104 | + |
| 105 | + result.typ = c.fromNifType n |
| 106 | + result.setOwner(c.fromNifSymbol n) |
| 107 | + |
| 108 | + expect n, Ident |
| 109 | + result.loc.k = pool.strings[n.litId].parseLocKind() |
| 110 | + incExpect n, StringLit |
| 111 | + result.loc.snippet.add pool.strings[n.litId] |
| 112 | + inc n |
| 113 | + skipParRi n |
| 114 | + |
| 115 | +proc fromNifTypeDef(c: var DecodeContext; n: var Cursor): PType = |
| 116 | + expectTag n, typeIdTag |
| 117 | + incExpect n, IntLit |
| 118 | + let id = pool.integers[n.intId] |
| 119 | + incExpect n, IntLit |
| 120 | + let itemId = pool.integers[n.intId].int32 |
| 121 | + incExpect n, Ident |
| 122 | + let kind = parseTypeKind(pool.strings[n.litId]) |
| 123 | + incExpect n, {Ident, DotToken} |
| 124 | + let flags = if n.kind == Ident: pool.strings[n.litId].parseTypeFlags else: {} |
| 125 | + inc n |
| 126 | + |
| 127 | + result = PType(itemId: ItemId(module: 0, item: itemId), |
| 128 | + kind: kind, |
| 129 | + flags: flags) |
| 130 | + assert id notin c.types |
| 131 | + c.types[id] = result |
| 132 | + |
| 133 | + expect n, {DotToken, ParLe} |
| 134 | + if n.kind == DotToken: |
| 135 | + inc n |
| 136 | + else: |
| 137 | + expectTag n, sonsTag |
| 138 | + inc n |
| 139 | + while n.kind != ParRi: |
| 140 | + result.addAllowNil c.fromNifType n |
| 141 | + inc n |
| 142 | + result.n = c.fromNif n |
| 143 | + result.setOwner c.fromNifSymbol n |
| 144 | + result.sym = c.fromNifSymbol n |
| 145 | + skipParRi n |
| 146 | + |
| 147 | +proc fromNifNodeFlags(n: var Cursor): set[TNodeFlag] = |
| 148 | + if n.kind == DotToken: |
| 149 | + result = {} |
| 150 | + inc n |
| 151 | + elif n.kind == Ident: |
| 152 | + result = parseNodeFlags(pool.strings[n.litId]) |
| 153 | + inc n |
| 154 | + else: |
| 155 | + assert false, "expected Node flag but got " & $n.kind |
| 156 | + |
| 157 | +proc fromNifSymbol(c: var DecodeContext; n: var Cursor): PSym = |
| 158 | + if n.kind == DotToken: |
| 159 | + result = nil |
| 160 | + inc n |
| 161 | + else: |
| 162 | + expect n, ParLe |
| 163 | + if n.tagId == symIdTag: |
| 164 | + result = c.fromNifSymDef n |
| 165 | + elif n.tagId == symTag: |
| 166 | + incExpect n, IntLit |
| 167 | + result = c.symbols[pool.integers[n.intId]] |
| 168 | + inc n |
| 169 | + skipParRi n |
| 170 | + else: |
| 171 | + assert false, "expected symbol tag but got " & pool.tags[n.tagId] |
| 172 | + |
| 173 | +proc fromNifType(c: var DecodeContext; n: var Cursor): PType = |
| 174 | + if n.kind == DotToken: |
| 175 | + result = nil |
| 176 | + inc n |
| 177 | + else: |
| 178 | + expect n, ParLe |
| 179 | + if n.tagId == typeIdTag: |
| 180 | + result = c.fromNifTypeDef n |
| 181 | + elif n.tagId == typeTag: |
| 182 | + incExpect n, IntLit |
| 183 | + result = c.types[pool.integers[n.intId]] |
| 184 | + inc n |
| 185 | + skipParRi n |
| 186 | + else: |
| 187 | + assert false, "expected type tag but got " & pool.tags[n.tagId] |
| 188 | + |
| 189 | +template withNode(c: var DecodeContext; n: var Cursor; result: PNode; kind: TNodeKind; body: untyped) = |
| 190 | + incExpect n, {DotToken, Ident} |
| 191 | + let flags = fromNifNodeFlags n |
| 192 | + result = newNode(kind) |
| 193 | + result.flags = flags |
| 194 | + result.typ = c.fromNifType n |
| 195 | + body |
| 196 | + skipParRi n |
| 197 | + |
| 198 | +proc fromNif(c: var DecodeContext; n: var Cursor): PNode = |
| 199 | + result = nil |
| 200 | + case n.kind: |
| 201 | + of DotToken: |
| 202 | + result = nil |
| 203 | + inc n |
| 204 | + of ParLe: |
| 205 | + let kind = n.nodeKind |
| 206 | + case kind: |
| 207 | + of nkEmpty: |
| 208 | + result = newNode(nkEmpty) |
| 209 | + inc n |
| 210 | + skipParRi n |
| 211 | + of nkIdent: |
| 212 | + incExpect n, Ident |
| 213 | + result = newIdentNode(c.graph.cache.getIdent(pool.strings[n.litId]), unknownLineInfo) |
| 214 | + inc n |
| 215 | + skipParRi n |
| 216 | + of nkSym: |
| 217 | + c.withNode n, result, kind: |
| 218 | + result.sym = c.fromNifSymbol n |
| 219 | + of nkCharLit: |
| 220 | + c.withNode n, result, kind: |
| 221 | + expect n, CharLit |
| 222 | + result.intVal = n.charLit.int |
| 223 | + inc n |
| 224 | + of nkIntLit .. nkInt64Lit: |
| 225 | + c.withNode n, result, kind: |
| 226 | + expect n, IntLit |
| 227 | + result.intVal = pool.integers[n.intId] |
| 228 | + inc n |
| 229 | + of nkUIntLit .. nkUInt64Lit: |
| 230 | + c.withNode n, result, kind: |
| 231 | + expect n, UIntLit |
| 232 | + result.intVal = cast[BiggestInt](pool.uintegers[n.uintId]) |
| 233 | + inc n |
| 234 | + of nkFloatLit .. nkFloat128Lit: |
| 235 | + c.withNode n, result, kind: |
| 236 | + expect n, FloatLit |
| 237 | + result.floatVal = pool.floats[n.floatId] |
| 238 | + inc n |
| 239 | + of nkStrLit .. nkTripleStrLit: |
| 240 | + c.withNode n, result, kind: |
| 241 | + expect n, StringLit |
| 242 | + result.strVal = pool.strings[n.litId] |
| 243 | + inc n |
| 244 | + of nkNilLit: |
| 245 | + c.withNode n, result, kind: |
| 246 | + discard |
| 247 | + of nkNone: |
| 248 | + assert false, "Unknown tag " & pool.tags[n.tagId] |
| 249 | + else: |
| 250 | + c.withNode n, result, kind: |
| 251 | + while n.kind != ParRi: |
| 252 | + result.add c.fromNif n |
| 253 | + else: |
| 254 | + assert false, "Not yet implemented " & $n.kind |
| 255 | + |
| 256 | +proc loadNif(stream: var Stream; graph: ModuleGraph): PNode = |
| 257 | + discard processDirectives(stream.r) |
| 258 | + |
| 259 | + var buf = fromStream(stream) |
| 260 | + var n = beginRead(buf) |
| 261 | + |
| 262 | + var c = DecodeContext(graph: graph) |
| 263 | + |
| 264 | + result = fromNif(c, n) |
| 265 | + |
| 266 | + endRead(buf) |
| 267 | + |
| 268 | +proc loadNifFile*(infile: AbsoluteFile; graph: ModuleGraph): PNode = |
| 269 | + var stream = nifstreams.open(infile.string) |
| 270 | + result = loadNif(stream, graph) |
| 271 | + stream.close |
| 272 | + |
| 273 | +proc loadNifFromBuffer*(strbuf: sink string; graph: ModuleGraph): PNode = |
| 274 | + var stream = nifstreams.openFromBuffer(strbuf) |
| 275 | + result = loadNif(stream, graph) |
| 276 | + |
| 277 | +when isMainModule: |
| 278 | + import std/cmdline |
| 279 | + |
| 280 | + if paramCount() > 0: |
| 281 | + var graph = newModuleGraph(newIdentCache(), newConfigRef()) |
| 282 | + var node = loadNifFile(paramStr(1).toAbsolute(toAbsoluteDir(".")), graph) |
| 283 | + debug(node) |
0 commit comments