Skip to content

Commit 8768299

Browse files
authored
implements #1162 (#1169)
1 parent 3007188 commit 8768299

File tree

1 file changed

+92
-15
lines changed

1 file changed

+92
-15
lines changed

src/nimony/indexgen.nim

Lines changed: 92 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@
66

77
## Nimony index generator.
88

9-
import std / [os, assertions]
9+
import std / [os, assertions, sets, tables]
1010
include ".." / lib / nifprelude
1111
import ".." / lib / [nifindexes, symparser]
12-
import decls, nimony_model, programs
12+
import decls, nimony_model, programs, vtables_frontend, semos
13+
import ".." / models / nifindex_tags
1314

1415
proc getAttachedOp(symId: SymId, attackedOp: var AttachedOp): bool =
1516
var name = pool.syms[symId]
@@ -26,6 +27,54 @@ proc getAttachedOp(symId: SymId, attackedOp: var AttachedOp): bool =
2627

2728
return true
2829

30+
proc indexMethod(classIndexMap: var seq[ClassIndexEntry]; symId: SymId; routine: Routine) =
31+
var param = routine.params
32+
if param.substructureKind == ParamsU:
33+
inc param
34+
if param.substructureKind == ParamU:
35+
var typ = param.takeLocal(SkipFinalParRi).typ
36+
# should use `getClass` proc in `nimony/typeprops.nim`,
37+
# but current `tryLoadSym` doesn't work with Nim v2 NIF.
38+
#let root = typ.getClass()
39+
if typ.typeKind == RefT:
40+
inc typ
41+
if typ.kind == Symbol:
42+
let root = typ.symId
43+
var methodName = pool.syms[symId]
44+
extractBasename methodName
45+
let signature = pool.strings.getOrIncl(methodKey(methodName, param))
46+
if routine.typevars.typeKind != InvokeT:
47+
# don't register instances
48+
for i in 0..<classIndexMap.len:
49+
if classIndexMap[i].cls == root:
50+
classIndexMap[i].methods.add MethodIndexEntry(fn:symId, signature: signature)
51+
continue
52+
classIndexMap.add ClassIndexEntry(cls: root, methods: @[MethodIndexEntry(fn: symId, signature: signature)])
53+
54+
proc buildIndexExports(exports: Table[string, HashSet[SymId]]; infile: string): TokenBuf =
55+
result = default(TokenBuf)
56+
let (dir, _, ext) = splitModulePath infile
57+
if exports.len != 0:
58+
result = createTokenBuf(32)
59+
for suffix, syms in exports:
60+
# open NIF file to get the path of source file of the module from the line info.
61+
let modPath = dir / (suffix & ext)
62+
var stream = nifstreams.open(modPath)
63+
discard processDirectives(stream.r)
64+
discard stream.next # first stmts node doesn't have line info.
65+
let t = stream.next
66+
let fileId = pool.man.getFileId(t.info)
67+
assert fileId.isValid
68+
stream.close
69+
let path = pool.files[fileId].toAbsolutePath
70+
result.addParLe(TagId(FromexportIdx))
71+
result.addStrLit path
72+
for s in syms:
73+
var isGlobal = false
74+
let ident = extractBasename(pool.syms[s], isGlobal)
75+
result.addIdent(ident)
76+
result.addParRi()
77+
2978
proc indexFromNif*(infile: string) =
3079
## Extract index from `infile` Nif file and write it to `*.idx.nif` file.
3180
##
@@ -40,35 +89,63 @@ proc indexFromNif*(infile: string) =
4089
var hookIndexLog = default array[AttachedOp, seq[HookIndexEntry]]
4190
var converterIndexMap = default seq[(SymId, SymId)]
4291
var classIndexMap = default seq[ClassIndexEntry]
92+
var exports = default Table[string, HashSet[SymId]] # Module suffix -> symbols to export in the module
4393

4494
assert n.stmtKind == StmtsS
4595
inc n
4696
while n.kind != ParRi:
4797
if n.kind == ParLe:
4898
case n.stmtKind:
4999
of ProcS, FuncS, ConverterS, MethodS:
100+
let kind = n.stmtKind
50101
let routine = takeRoutine(n, SkipFinalParRi)
51102
let symId = routine.name.symId
52-
var op = default AttachedOp
53-
if getAttachedOp(symId, op):
54-
var param = routine.params
55-
assert param.substructureKind == ParamsU
56-
inc param
57-
assert param.substructureKind == ParamU
58-
let typ = takeLocal(param, SkipExclBody).typ.skipModifier
59-
# this assertion fails when got generics proc as generics parameters are not supported yet.
60-
if typ.kind == Symbol:
61-
let obj = typ.symId
62-
let isGeneric = routine.typevars.substructureKind == TypevarsU
63-
hookIndexLog[op].add HookIndexEntry(typ: obj, hook: symId, isGeneric: isGeneric)
103+
if kind == ConverterS:
104+
if routine.exported.kind != DotToken and
105+
routine.typevars.typeKind != InvokeT:
106+
# don't register instances and not exported ones
107+
let root = routine.retType.skipModifier.symId
108+
converterIndexMap.add((root, symId))
109+
elif kind == MethodS:
110+
indexMethod(classIndexMap, symId, routine)
111+
else:
112+
var op = default AttachedOp
113+
if getAttachedOp(symId, op):
114+
var param = routine.params
115+
assert param.substructureKind == ParamsU
116+
inc param
117+
assert param.substructureKind == ParamU
118+
let typ = takeLocal(param, SkipExclBody).typ.skipModifier
119+
# this doesn't work with generics proc as generics parameters are not supported yet.
120+
if typ.kind == Symbol:
121+
let obj = typ.symId
122+
let isGeneric = routine.typevars.substructureKind == TypevarsU
123+
hookIndexLog[op].add HookIndexEntry(typ: obj, hook: symId, isGeneric: isGeneric)
124+
of ExportS:
125+
inc n
126+
# .nif files generated by `nim nif foo.nim` has `(exports symbol1, symbol2, ...)`, but doesn't have other kinds of export node.
127+
# export statement like `export modname` becomes `(exports symbols1, symbols2, ...)` where symbols1, symbols2, ... are exported symbols in the module.
128+
# So they are indexed only with `FromexportIdx`.
129+
while n.kind != ParRi:
130+
assert n.kind == Symbol
131+
let sym = n.symId
132+
let name = pool.syms[sym]
133+
let suffix = extractModule(name)
134+
assert suffix != ""
135+
exports.mgetOrPut(suffix).incl sym
136+
inc n
137+
inc n
64138
else:
65139
skip n
66140
else:
67141
skip n
68142

69143
endRead buf
70144

145+
var exportBuf = buildIndexExports(exports, infile)
146+
71147
createIndex infile, root, true,
72148
IndexSections(hooks: move hookIndexLog,
73149
converters: move converterIndexMap,
74-
classes: move classIndexMap)
150+
classes: move classIndexMap,
151+
exportBuf: exportBuf)

0 commit comments

Comments
 (0)