Skip to content

Commit

Permalink
proper scopes for the type navigation logic (#372)
Browse files Browse the repository at this point in the history
* proper scopes for the type navigation logic

* typo

* make tests green
  • Loading branch information
Araq authored Jan 17, 2025
1 parent ad933df commit 940a88e
Show file tree
Hide file tree
Showing 10 changed files with 215 additions and 78 deletions.
48 changes: 27 additions & 21 deletions src/hexer/basics.nim
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import std / [tables, sets, syncio]


include nifprelude
import ".." / nimony / [nimony_model, typenav]

type
SymbolKey* = (SymId, SymId) # (symbol, owner)
MangleScope* {.acyclic.} = ref object
tab: Table[SymId, string]
parent: MangleScope

EContext* = object
dir*, main*, ext*: string
Expand All @@ -15,7 +16,7 @@ type
nestedIn*: seq[(StmtKind, SymId)]
headers*: HashSet[StrId]
currentOwner*: SymId
toMangle*: Table[SymbolKey, string]
toMangle*: MangleScope
strLits*: Table[string, SymId]
newTypes*: Table[string, SymId]
pending*: TokenBuf
Expand All @@ -26,6 +27,28 @@ type
# TODO: add a instID for each forStmt
tmpId*: int # per proc

proc openMangleScope*(e: var EContext) =
e.toMangle = MangleScope(tab: initTable[SymId, string](), parent: e.toMangle)
e.typeCache.openScope()

proc closeMangleScope*(e: var EContext) =
e.toMangle = e.toMangle.parent
e.typeCache.closeScope()

proc registerMangle*(e: var EContext; s: SymId; ext: string) =
e.toMangle.tab[s] = ext

proc registerMangleInParent*(e: var EContext; s: SymId; ext: string) =
e.toMangle.parent.tab[s] = ext

proc maybeMangle*(e: var EContext; s: SymId): string =
var it {.cursor.} = e.toMangle
while it != nil:
result = it.tab.getOrDefault(s)
if result != "":
return result
it = it.parent
return ""

proc error*(e: var EContext; msg: string; c: Cursor) {.noreturn.} =
write stdout, "[Error] "
Expand Down Expand Up @@ -72,21 +95,4 @@ template loop*(e: var EContext; c: var Cursor; body: untyped) =
body

proc takeTree*(e: var EContext; n: var Cursor) =
if n.kind != ParLe:
e.dest.add n
inc n
else:
var nested = 0
while true:
e.dest.add n
case n.kind
of ParLe: inc nested
of ParRi:
dec nested
if nested == 0:
inc n
break
of EofToken:
error e, "expected ')', but EOF reached"
else: discard
inc n
takeTree e.dest, n
42 changes: 37 additions & 5 deletions src/hexer/constparams.nim
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ proc rememberConstRefParams(c: var Context; params, pragmas: Cursor) =
proc trProcDecl(c: var Context; dest: var TokenBuf; n: var Cursor) =
var r = takeRoutine(n, SkipFinalParRi)
var c2 = Context(ptrSize: c.ptrSize, typeCache: createTypeCache())
c2.typeCache.openScope()
copyInto(dest, n):
copyTree dest, r.name
copyTree dest, r.exported
Expand All @@ -50,9 +51,11 @@ proc trProcDecl(c: var Context; dest: var TokenBuf; n: var Cursor) =
copyTree dest, r.effects
if r.body.stmtKind == StmtsS and not isGeneric(r):
rememberConstRefParams c2, r.params, r.pragmas
c2.typeCache.registerParams(r.name.symId, r.params)
tr c2, dest, r.body
else:
copyTree dest, r.body
c2.typeCache.closeScope()

proc trConstRef(c: var Context; dest: var TokenBuf; n: var Cursor) =
let info = n.info
Expand Down Expand Up @@ -100,6 +103,27 @@ proc trCall(c: var Context; dest: var TokenBuf; n: var Cursor) =
tr c, dest, n
wantParRi dest, n

proc trLocal(c: var Context; dest: var TokenBuf; n: var Cursor) =
let head = n
var r = takeLocal(n, SkipFinalParRi)
dest.add head
dest.add r.name
dest.add r.exported
dest.add r.pragmas
dest.add r.typ
tr c, dest, r.val
c.typeCache.registerLocal(r.name.symId, r.typ)
dest.addParRi()

proc trScope(c: var Context; dest: var TokenBuf; n: var Cursor) =
c.typeCache.openScope()
dest.add n
inc n
while n.kind != ParRi:
tr c, dest, n
wantParRi dest, n
c.typeCache.closeScope()

proc tr(c: var Context; dest: var TokenBuf; n: var Cursor) =
var nested = 0
while true:
Expand All @@ -117,12 +141,18 @@ proc tr(c: var Context; dest: var TokenBuf; n: var Cursor) =
of ParLe:
if n.exprKind in CallKinds:
trCall c, dest, n
elif n.stmtKind in {ProcS, FuncS, MacroS, MethodS, ConverterS}:
trProcDecl c, dest, n
else:
dest.add n
inc n
inc nested
case n.stmtKind
of ProcS, FuncS, MacroS, MethodS, ConverterS:
trProcDecl c, dest, n
of CursorS, LetS, VarS, ConstS, ResultS:
trLocal c, dest, n
of ScopeS:
trScope c, dest, n
else:
dest.add n
inc n
inc nested
of ParRi:
dest.add n
inc n
Expand All @@ -131,6 +161,8 @@ proc tr(c: var Context; dest: var TokenBuf; n: var Cursor) =

proc injectConstParamDerefs*(n: Cursor; ptrSize: int): TokenBuf =
var c = Context(ptrSize: ptrSize, typeCache: createTypeCache())
c.typeCache.openScope()
result = createTokenBuf(300)
var n = n
tr(c, result, n)
c.typeCache.closeScope()
10 changes: 10 additions & 0 deletions src/hexer/duplifier.nim
Original file line number Diff line number Diff line change
Expand Up @@ -356,10 +356,13 @@ proc trProcDecl(c: var Context; n: var Cursor) =
copyTree c.dest, r.pragmas
copyTree c.dest, r.effects
if r.body.stmtKind == StmtsS and not isGeneric(r):
c.typeCache.openScope()
c.typeCache.registerParams(r.name.symId, r.params)
if hasBuiltinPragma(r.pragmas, NoDestroy):
trOnlyEssentials c, r.body
else:
tr c, r.body, DontCare
c.typeCache.closeScope()
else:
copyTree c.dest, r.body
c.dest.addParRi()
Expand Down Expand Up @@ -504,6 +507,7 @@ proc trLocal(c: var Context; n: var Cursor) =
copyTree c.dest, r.exported
copyTree c.dest, r.pragmas
copyTree c.dest, r.typ
c.typeCache.registerLocal(r.name.symId, r.typ)

let destructor = getDestructor(c.lifter[], r.typ, n.info)
if destructor != NoSymId:
Expand Down Expand Up @@ -596,14 +600,20 @@ proc tr(c: var Context; n: var Cursor; e: Expects) =
trLocal c, n
of ProcS, FuncS, ConverterS, MethodS, MacroS:
trProcDecl c, n
of ScopeS:
c.typeCache.openScope()
trSons c, n, WantNonOwner
c.typeCache.closeScope()
else:
trSons c, n, WantNonOwner

proc injectDups*(n: Cursor; lifter: ref LiftingCtx): TokenBuf =
var c = Context(lifter: lifter, typeCache: createTypeCache(),
dest: createTokenBuf(400))
c.typeCache.openScope()
var n = n
tr(c, n, WantNonOwner)
genMissingHooks lifter[]

c.typeCache.closeScope()
result = ensureMove(c.dest)
63 changes: 40 additions & 23 deletions src/hexer/expander.nim
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,11 @@ proc traverseType(e: var EContext; c: var Cursor; flags: set[TypeFlag] = {}) =
inc c
of Symbol:
let s = c.symId
let ext = maybeMangle(e, s)
if ext.len != 0:
e.dest.addSymUse pool.syms.getOrIncl(ext), c.info
inc c
return
let res = tryLoadSym(s)
if res.status == LacksNothing:
var body = asTypeDecl(res.decl).body
Expand Down Expand Up @@ -525,14 +530,7 @@ proc closeGenPragmas(e: var EContext; g: GenPragmas) =
e.dest.addDotToken()

proc traverseProc(e: var EContext; c: var Cursor; mode: TraverseMode) =
# namePos* = 0
# patternPos* = 1 # empty except for term rewriting macros
# genericParamsPos* = 2
# paramsPos* = 3
# resultPos* = 4
# pragmasPos* = 5
# miscPos* = 6 # used for undocumented and hacky stuff
# bodyPos* = 7 # position of body; use rodread.getBody() instead!
e.openMangleScope()
var dst = createTokenBuf(50)
swap e.dest, dst
#let toPatch = e.dest.len
Expand Down Expand Up @@ -587,7 +585,7 @@ proc traverseProc(e: var EContext; c: var Cursor; mode: TraverseMode) =

var genPragmas = openGenPragmas()
if prag.externName.len > 0:
e.toMangle[(s, oldOwner)] = prag.externName & ".c"
e.registerMangleInParent(s, prag.externName & ".c")
e.addKeyVal genPragmas, "was", symToken(s, pinfo), pinfo
if Selectany in prag.flags:
e.addKey genPragmas, "selectany", pinfo
Expand Down Expand Up @@ -615,6 +613,7 @@ proc traverseProc(e: var EContext; c: var Cursor; mode: TraverseMode) =
if prag.header != StrId(0):
e.headers.incl prag.header
discard setOwner(e, oldOwner)
e.closeMangleScope()

proc traverseTypeDecl(e: var EContext; c: var Cursor) =
var dst = createTokenBuf(50)
Expand Down Expand Up @@ -856,7 +855,11 @@ proc traverseExpr(e: var EContext; c: var Cursor) =
e.offer c.symId
inc c
of Symbol:
e.dest.add c
let ext = maybeMangle(e, c.symId)
if ext.len != 0:
e.dest.addSymUse pool.syms.getOrIncl(ext), c.info
else:
e.dest.add c
e.demand c.symId
inc c
of StringLit:
Expand Down Expand Up @@ -886,7 +889,7 @@ proc traverseLocal(e: var EContext; c: var Cursor; tag: string; mode: TraverseMo
var genPragmas = openGenPragmas()

if prag.externName.len > 0:
e.toMangle[(s, e.currentOwner)] = prag.externName & ".c"
e.registerMangle(s, prag.externName & ".c")
e.addKeyVal genPragmas, "was", symToken(s, pinfo), pinfo

if Threadvar in prag.flags:
Expand All @@ -901,6 +904,7 @@ proc traverseLocal(e: var EContext; c: var Cursor; tag: string; mode: TraverseMo
closeGenPragmas e, genPragmas

var nodecl = prag.flags.contains(Nodecl)
e.typeCache.registerLocal(s, c)
if tag == "param" and typeKind(c) == VarargsT:
skip c
nodecl = true
Expand Down Expand Up @@ -1039,16 +1043,29 @@ proc traverseStmt(e: var EContext; c: var Cursor; mode = TraverseAll) =
inc c
e.loop c:
traverseStmt e, c, mode
of ScopeS:
e.openMangleScope()
if mode == TraverseTopLevel:
inc c
while c.kind notin {EofToken, ParRi}:
traverseStmt e, c, mode
skipParRi e, c
else:
e.dest.add c
inc c
e.loop c:
traverseStmt e, c, mode
e.closeMangleScope()
of VarS, LetS, CursorS, ResultS:
traverseLocal e, c, (if e.nestedIn[^1][0] == StmtsS and mode in {TraverseTopLevel, TraverseSig}: "gvar" else: "var"), mode
of ConstS:
traverseLocal e, c, "const", mode
of CmdS:
of CmdS, CallS:
e.dest.add tagToken("call", c.info)
inc c
e.loop c:
traverseExpr e, c
of EmitS, AsgnS, RetS, CallS:
of EmitS, AsgnS, RetS:
e.dest.add c
inc c
e.loop c:
Expand Down Expand Up @@ -1131,29 +1148,27 @@ proc writeOutput(e: var EContext) =
b.addIdent(pool.strings[c.litId])
of Symbol:
let owner = ownerStack[^1][0]
let key = (c.symId, owner)
let val = e.toMangle.getOrDefault(key)
let val = e.maybeMangle(c.symId)
if val.len > 0:
b.addSymbol(val)
else:
b.addSymbol(pool.syms[c.symId])
of IntLit:
b.addIntLit(pool.integers[c.intId])
of UIntLit:
b.addUIntLit(pool.uintegers[c.uintId])
of FloatLit:
b.addFloatLit(pool.floats[c.floatId])
of SymbolDef:
let owner = ownerStack[^1][0]
let key = (c.symId, owner)
let val = e.toMangle.getOrDefault(key)
let val = e.maybeMangle(c.symId)
if val.len > 0:
b.addSymbolDef(val)
else:
b.addSymbolDef(pool.syms[c.symId])
if nextIsOwner >= 0:
ownerStack.add (c.symId, nextIsOwner)
nextIsOwner = -1
of IntLit:
b.addIntLit(pool.integers[c.intId])
of UIntLit:
b.addUIntLit(pool.uintegers[c.uintId])
of FloatLit:
b.addFloatLit(pool.floats[c.floatId])
of CharLit:
b.addCharLit char(c.uoperand)
of StringLit:
Expand Down Expand Up @@ -1195,6 +1210,7 @@ proc expand*(infile: string) =
dest: createTokenBuf(),
nestedIn: @[(StmtsS, SymId(0))],
typeCache: createTypeCache())
e.openMangleScope()

var c0 = setupProgram(infile, infile.changeFileExt ".c.nif", true)
transformStmt(e, c0)
Expand All @@ -1220,6 +1236,7 @@ proc expand*(infile: string) =
inc i
skipParRi e, c
writeOutput e
e.closeMangleScope()

when isMainModule:
echo splitModulePath("/abc/def/name.4.nif")
Loading

0 comments on commit 940a88e

Please sign in to comment.