Skip to content

Commit 4bd7a93

Browse files
committed
adds Nim's AST to/from NIF
1 parent b8ce11d commit 4bd7a93

File tree

9 files changed

+2638
-0
lines changed

9 files changed

+2638
-0
lines changed

compiler/icnif/enum2nif.nim

Lines changed: 1829 additions & 0 deletions
Large diffs are not rendered by default.

compiler/icnif/icniftags.nim

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import "../../dist/nimony/src/lib" / [nifstreams]
2+
3+
let
4+
symIdTag* = registerTag("symId")
5+
symTag* = registerTag("s")
6+
typeIdTag* = registerTag("typeId")
7+
typeTag* = registerTag("t")
8+
sonsTag* = registerTag("sons")

compiler/icnif/nifdecoder.nim

Lines changed: 283 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,283 @@
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

Comments
 (0)