big compiler refactoring; avoid globals for multi method dispatcher generation

This commit is contained in:
Andreas Rumpf 2017-02-22 16:27:52 +01:00
commit 46efaf294b
29 changed files with 225 additions and 215 deletions

View file

@ -1366,7 +1366,7 @@ proc updateCachedModule(m: BModule) =
cf.flags = {CfileFlag.Cached} cf.flags = {CfileFlag.Cached}
addFileToCompile(cf) addFileToCompile(cf)
proc myClose(b: PPassContext, n: PNode): PNode = proc myClose(graph: ModuleGraph; b: PPassContext, n: PNode): PNode =
result = n result = n
if b == nil or passes.skipCodegen(n): return if b == nil or passes.skipCodegen(n): return
var m = BModule(b) var m = BModule(b)
@ -1378,7 +1378,7 @@ proc myClose(b: PPassContext, n: PNode): PNode =
if sfMainModule in m.module.flags: if sfMainModule in m.module.flags:
incl m.flags, objHasKidsValid incl m.flags, objHasKidsValid
var disp = generateMethodDispatchers() var disp = generateMethodDispatchers(graph)
for i in 0..sonsLen(disp)-1: genProcAux(m, disp.sons[i].sym) for i in 0..sonsLen(disp)-1: genProcAux(m, disp.sons[i].sym)
genMainProc(m) genMainProc(m)

View file

@ -11,7 +11,7 @@
import import
intsets, options, ast, astalgo, msgs, idents, renderer, types, magicsys, intsets, options, ast, astalgo, msgs, idents, renderer, types, magicsys,
sempass2, strutils sempass2, strutils, modulegraphs
proc genConv(n: PNode, d: PType, downcast: bool): PNode = proc genConv(n: PNode, d: PType, downcast: bool): PNode =
var dest = skipTypes(d, abstractPtrs) var dest = skipTypes(d, abstractPtrs)
@ -38,16 +38,18 @@ proc genConv(n: PNode, d: PType, downcast: bool): PNode =
proc methodCall*(n: PNode): PNode = proc methodCall*(n: PNode): PNode =
result = n result = n
# replace ordinary method by dispatcher method: # replace ordinary method by dispatcher method:
var disp = lastSon(result.sons[0].sym.ast).sym let dispn = lastSon(result.sons[0].sym.ast)
assert sfDispatcher in disp.flags if dispn.kind == nkSym:
result.sons[0].sym = disp let disp = dispn.sym
# change the arguments to up/downcasts to fit the dispatcher's parameters: if sfDispatcher notin disp.flags:
for i in countup(1, sonsLen(result)-1): localError(n.info, "'" & $result & "' lacks a dispatcher")
result.sons[i] = genConv(result.sons[i], disp.typ.sons[i], true) return
result.sons[0].sym = disp
# save for incremental compilation: # change the arguments to up/downcasts to fit the dispatcher's parameters:
var for i in countup(1, sonsLen(result)-1):
gMethods: seq[tuple[methods: TSymSeq, dispatcher: PSym]] = @[] result.sons[i] = genConv(result.sons[i], disp.typ.sons[i], true)
else:
localError(n.info, "'" & $result.sons[0] & "' lacks a dispatcher")
type type
MethodResult = enum No, Invalid, Yes MethodResult = enum No, Invalid, Yes
@ -144,27 +146,27 @@ proc fixupDispatcher(meth, disp: PSym) =
if disp.typ.lockLevel < meth.typ.lockLevel: if disp.typ.lockLevel < meth.typ.lockLevel:
disp.typ.lockLevel = meth.typ.lockLevel disp.typ.lockLevel = meth.typ.lockLevel
proc methodDef*(s: PSym, fromCache: bool) = proc methodDef*(g: ModuleGraph; s: PSym, fromCache: bool) =
let L = len(gMethods) let L = len(g.methods)
var witness: PSym var witness: PSym
for i in countup(0, L - 1): for i in countup(0, L - 1):
let disp = gMethods[i].dispatcher let disp = g.methods[i].dispatcher
case sameMethodBucket(disp, s) case sameMethodBucket(disp, s)
of Yes: of Yes:
add(gMethods[i].methods, s) add(g.methods[i].methods, s)
attachDispatcher(s, lastSon(disp.ast)) attachDispatcher(s, lastSon(disp.ast))
fixupDispatcher(s, disp) fixupDispatcher(s, disp)
#echo "fixup ", disp.name.s, " ", disp.id #echo "fixup ", disp.name.s, " ", disp.id
when useEffectSystem: checkMethodEffects(disp, s) when useEffectSystem: checkMethodEffects(disp, s)
if sfBase in s.flags and gMethods[i].methods[0] != s: if sfBase in s.flags and g.methods[i].methods[0] != s:
# already exists due to forwarding definition? # already exists due to forwarding definition?
localError(s.info, "method is not a base") localError(s.info, "method is not a base")
return return
of No: discard of No: discard
of Invalid: of Invalid:
if witness.isNil: witness = gMethods[i].methods[0] if witness.isNil: witness = g.methods[i].methods[0]
# create a new dispatcher: # create a new dispatcher:
add(gMethods, (methods: @[s], dispatcher: createDispatcher(s))) add(g.methods, (methods: @[s], dispatcher: createDispatcher(s)))
#echo "adding ", s.info #echo "adding ", s.info
#if fromCache: #if fromCache:
# internalError(s.info, "no method dispatcher found") # internalError(s.info, "no method dispatcher found")
@ -258,12 +260,12 @@ proc genDispatcher(methods: TSymSeq, relevantCols: IntSet): PSym =
disp = ret disp = ret
result.ast.sons[bodyPos] = disp result.ast.sons[bodyPos] = disp
proc generateMethodDispatchers*(): PNode = proc generateMethodDispatchers*(g: ModuleGraph): PNode =
result = newNode(nkStmtList) result = newNode(nkStmtList)
for bucket in countup(0, len(gMethods) - 1): for bucket in countup(0, len(g.methods) - 1):
var relevantCols = initIntSet() var relevantCols = initIntSet()
for col in countup(1, sonsLen(gMethods[bucket].methods[0].typ) - 1): for col in countup(1, sonsLen(g.methods[bucket].methods[0].typ) - 1):
if relevantCol(gMethods[bucket].methods, col): incl(relevantCols, col) if relevantCol(g.methods[bucket].methods, col): incl(relevantCols, col)
sortBucket(gMethods[bucket].methods, relevantCols) sortBucket(g.methods[bucket].methods, relevantCols)
addSon(result, addSon(result,
newSymNode(genDispatcher(gMethods[bucket].methods, relevantCols))) newSymNode(genDispatcher(g.methods[bucket].methods, relevantCols)))

View file

@ -33,11 +33,11 @@ template closeImpl(body: untyped) {.dirty.} =
except IOError: except IOError:
discard discard
proc close(p: PPassContext, n: PNode): PNode = proc close(graph: ModuleGraph; p: PPassContext, n: PNode): PNode =
closeImpl: closeImpl:
writeOutput(g.doc, g.module.filename, HtmlExt, useWarning) writeOutput(g.doc, g.module.filename, HtmlExt, useWarning)
proc closeJson(p: PPassContext, n: PNode): PNode = proc closeJson(graph: ModuleGraph; p: PPassContext, n: PNode): PNode =
closeImpl: closeImpl:
writeOutputJson(g.doc, g.module.filename, ".json", useWarning) writeOutputJson(g.doc, g.module.filename, ".json", useWarning)

View file

@ -2237,13 +2237,13 @@ proc myProcess(b: PPassContext, n: PNode): PNode =
add(p.g.code, p.body) add(p.g.code, p.body)
globals.unique = p.unique globals.unique = p.unique
proc wholeCode*(m: BModule): Rope = proc wholeCode(graph: ModuleGraph; m: BModule): Rope =
for prc in globals.forwarded: for prc in globals.forwarded:
if not globals.generatedSyms.containsOrIncl(prc.id): if not globals.generatedSyms.containsOrIncl(prc.id):
var p = newProc(globals, m, nil, m.module.options) var p = newProc(globals, m, nil, m.module.options)
attachProc(p, prc) attachProc(p, prc)
var disp = generateMethodDispatchers() var disp = generateMethodDispatchers(graph)
for i in 0..sonsLen(disp)-1: for i in 0..sonsLen(disp)-1:
let prc = disp.sons[i].sym let prc = disp.sons[i].sym
if not globals.generatedSyms.containsOrIncl(prc.id): if not globals.generatedSyms.containsOrIncl(prc.id):
@ -2277,7 +2277,7 @@ proc genClass(obj: PType; content: Rope; ext: string) =
let outfile = changeFileExt(completeCFilePath($cls), ext) let outfile = changeFileExt(completeCFilePath($cls), ext)
discard writeRopeIfNotEqual(result, outfile) discard writeRopeIfNotEqual(result, outfile)
proc myClose(b: PPassContext, n: PNode): PNode = proc myClose(graph: ModuleGraph; b: PPassContext, n: PNode): PNode =
if passes.skipCodegen(n): return n if passes.skipCodegen(n): return n
result = myProcess(b, n) result = myProcess(b, n)
var m = BModule(b) var m = BModule(b)
@ -2285,7 +2285,7 @@ proc myClose(b: PPassContext, n: PNode): PNode =
let ext = if m.target == targetJS: "js" else: "php" let ext = if m.target == targetJS: "js" else: "php"
let f = if globals.classes.len == 0: m.module.filename let f = if globals.classes.len == 0: m.module.filename
else: "nimsystem" else: "nimsystem"
let code = wholeCode(m) let code = wholeCode(graph, m)
let outfile = let outfile =
if options.outFile.len > 0: if options.outFile.len > 0:
if options.outFile.isAbsolute: options.outFile if options.outFile.isAbsolute: options.outFile

View file

@ -115,7 +115,7 @@ proc errorSym*(c: PContext, n: PNode): PSym =
considerQuotedIdent(m) considerQuotedIdent(m)
else: else:
getIdent("err:" & renderTree(m)) getIdent("err:" & renderTree(m))
result = newSym(skError, ident, getCurrOwner(), n.info) result = newSym(skError, ident, getCurrOwner(c), n.info)
result.typ = errorType(c) result.typ = errorType(c)
incl(result.flags, sfDiscardable) incl(result.flags, sfDiscardable)
# pretend it's imported from some unknown module to prevent cascading errors: # pretend it's imported from some unknown module to prevent cascading errors:

View file

@ -41,6 +41,9 @@ type
backend*: RootRef # minor hack so that a backend can extend this easily backend*: RootRef # minor hack so that a backend can extend this easily
config*: ConfigRef config*: ConfigRef
doStopCompile*: proc(): bool {.closure.} doStopCompile*: proc(): bool {.closure.}
usageSym*: PSym # for nimsuggest
owners*: seq[PSym]
methods*: seq[tuple[methods: TSymSeq, dispatcher: PSym]]
{.this: g.} {.this: g.}
@ -58,6 +61,8 @@ proc newModuleGraph*(config: ConfigRef = nil): ModuleGraph =
result.config = newConfigRef() result.config = newConfigRef()
else: else:
result.config = config result.config = config
result.owners = @[]
result.methods = @[]
proc resetAllModules*(g: ModuleGraph) = proc resetAllModules*(g: ModuleGraph) =
initStrTable(packageSyms) initStrTable(packageSyms)
@ -65,6 +70,9 @@ proc resetAllModules*(g: ModuleGraph) =
modules = @[] modules = @[]
importStack = @[] importStack = @[]
inclToMod = initTable[int32, int32]() inclToMod = initTable[int32, int32]()
usageSym = nil
owners = @[]
methods = @[]
proc getModule*(g: ModuleGraph; fileIdx: int32): PSym = proc getModule*(g: ModuleGraph; fileIdx: int32): PSym =
if fileIdx >= 0 and fileIdx < modules.len: if fileIdx >= 0 and fileIdx < modules.len:

View file

@ -567,6 +567,15 @@ proc newFileInfo(fullPath, projPath: string): TFileInfo =
if optEmbedOrigSrc in gGlobalOptions or true: if optEmbedOrigSrc in gGlobalOptions or true:
result.lines = @[] result.lines = @[]
proc fileInfoKnown*(filename: string): bool =
var
canon: string
try:
canon = canonicalizePath(filename)
except:
canon = filename
result = filenameToIndexTbl.hasKey(canon)
proc fileInfoIdx*(filename: string; isKnownFile: var bool): int32 = proc fileInfoIdx*(filename: string; isKnownFile: var bool): int32 =
var var
canon: string canon: string

View file

@ -29,21 +29,3 @@ proc verboseProcess(context: PPassContext, n: PNode): PNode =
message(n.info, hintProcessing, $idgen.gFrontendId) message(n.info, hintProcessing, $idgen.gFrontendId)
const verbosePass* = makePass(open = verboseOpen, process = verboseProcess) const verbosePass* = makePass(open = verboseOpen, process = verboseProcess)
proc cleanUp(c: PPassContext, n: PNode): PNode =
result = n
# we cannot clean up if dead code elimination is activated
if optDeadCodeElim in gGlobalOptions or n == nil: return
case n.kind
of nkStmtList:
for i in countup(0, sonsLen(n) - 1): discard cleanUp(c, n.sons[i])
of nkProcDef, nkMethodDef:
if n.sons[namePos].kind == nkSym:
var s = n.sons[namePos].sym
if sfDeadCodeElim notin getModule(s).flags and not astNeeded(s):
s.ast.sons[bodyPos] = ast.emptyNode # free the memory
else:
discard
const cleanupPass* = makePass(process = cleanUp, close = cleanUp)

View file

@ -24,7 +24,7 @@ type
TPassOpen* = proc (graph: ModuleGraph; module: PSym; cache: IdentCache): PPassContext {.nimcall.} TPassOpen* = proc (graph: ModuleGraph; module: PSym; cache: IdentCache): PPassContext {.nimcall.}
TPassOpenCached* = TPassOpenCached* =
proc (graph: ModuleGraph; module: PSym, rd: PRodReader): PPassContext {.nimcall.} proc (graph: ModuleGraph; module: PSym, rd: PRodReader): PPassContext {.nimcall.}
TPassClose* = proc (p: PPassContext, n: PNode): PNode {.nimcall.} TPassClose* = proc (graph: ModuleGraph; p: PPassContext, n: PNode): PNode {.nimcall.}
TPassProcess* = proc (p: PPassContext, topLevelStmt: PNode): PNode {.nimcall.} TPassProcess* = proc (p: PPassContext, topLevelStmt: PNode): PNode {.nimcall.}
TPass* = tuple[open: TPassOpen, openCached: TPassOpenCached, TPass* = tuple[open: TPassOpen, openCached: TPassOpenCached,
@ -94,7 +94,7 @@ proc carryPass*(g: ModuleGraph; p: TPass, module: PSym; cache: IdentCache;
m: TPassData): TPassData = m: TPassData): TPassData =
var c = p.open(g, module, cache) var c = p.open(g, module, cache)
result.input = p.process(c, m.input) result.input = p.process(c, m.input)
result.closeOutput = if p.close != nil: p.close(c, m.closeOutput) result.closeOutput = if p.close != nil: p.close(g, c, m.closeOutput)
else: m.closeOutput else: m.closeOutput
proc carryPasses*(g: ModuleGraph; nodes: PNode, module: PSym; proc carryPasses*(g: ModuleGraph; nodes: PNode, module: PSym;
@ -121,10 +121,10 @@ proc openPassesCached(g: ModuleGraph; a: var TPassContextArray, module: PSym,
else: else:
a[i] = nil a[i] = nil
proc closePasses(a: var TPassContextArray) = proc closePasses(graph: ModuleGraph; a: var TPassContextArray) =
var m: PNode = nil var m: PNode = nil
for i in countup(0, gPassesLen - 1): for i in countup(0, gPassesLen - 1):
if not isNil(gPasses[i].close): m = gPasses[i].close(a[i], m) if not isNil(gPasses[i].close): m = gPasses[i].close(graph, a[i], m)
a[i] = nil # free the memory here a[i] = nil # free the memory here
proc processTopLevelStmt(n: PNode, a: var TPassContextArray): bool = proc processTopLevelStmt(n: PNode, a: var TPassContextArray): bool =
@ -142,11 +142,11 @@ proc processTopLevelStmtCached(n: PNode, a: var TPassContextArray) =
for i in countup(0, gPassesLen - 1): for i in countup(0, gPassesLen - 1):
if not isNil(gPasses[i].openCached): m = gPasses[i].process(a[i], m) if not isNil(gPasses[i].openCached): m = gPasses[i].process(a[i], m)
proc closePassesCached(a: var TPassContextArray) = proc closePassesCached(graph: ModuleGraph; a: var TPassContextArray) =
var m: PNode = nil var m: PNode = nil
for i in countup(0, gPassesLen - 1): for i in countup(0, gPassesLen - 1):
if not isNil(gPasses[i].openCached) and not isNil(gPasses[i].close): if not isNil(gPasses[i].openCached) and not isNil(gPasses[i].close):
m = gPasses[i].close(a[i], m) m = gPasses[i].close(graph, a[i], m)
a[i] = nil # free the memory here a[i] = nil # free the memory here
proc resolveMod(module, relativeTo: string): int32 = proc resolveMod(module, relativeTo: string): int32 =
@ -215,7 +215,7 @@ proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream,
elif not processTopLevelStmt(n, a): break elif not processTopLevelStmt(n, a): break
closeParsers(p) closeParsers(p)
if s.kind != llsStdIn: break if s.kind != llsStdIn: break
closePasses(a) closePasses(graph, a)
# id synchronization point for more consistent code generation: # id synchronization point for more consistent code generation:
idSynchronizationPoint(1000) idSynchronizationPoint(1000)
else: else:
@ -224,5 +224,5 @@ proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream,
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):
if graph.stopCompile(): break if graph.stopCompile(): break
processTopLevelStmtCached(n.sons[i], a) processTopLevelStmtCached(n.sons[i], a)
closePassesCached(a) closePassesCached(graph, a)
result = true result = true

View file

@ -289,7 +289,7 @@ proc applyRule*(c: PContext, s: PSym, n: PNode): PNode =
# constraint not fulfilled: # constraint not fulfilled:
if not ok: return nil if not ok: return nil
markUsed(n.info, s) markUsed(n.info, s, c.graph.usageSym)
if ctx.subMatch: if ctx.subMatch:
assert m.len == 3 assert m.len == 3
m.sons[1] = result m.sons[1] = result

View file

@ -28,7 +28,7 @@ proc semLocals(c: PContext, n: PNode): PNode =
it.typ.skipTypes({tyGenericInst, tyVar}).kind notin it.typ.skipTypes({tyGenericInst, tyVar}).kind notin
{tyVarargs, tyOpenArray, tyTypeDesc, tyStatic, tyExpr, tyStmt, tyEmpty}: {tyVarargs, tyOpenArray, tyTypeDesc, tyStatic, tyExpr, tyStmt, tyEmpty}:
var field = newSym(skField, it.name, getCurrOwner(), n.info) var field = newSym(skField, it.name, getCurrOwner(c), n.info)
field.typ = it.typ.skipTypes({tyGenericInst, tyVar}) field.typ = it.typ.skipTypes({tyGenericInst, tyVar})
field.position = counter field.position = counter
inc(counter) inc(counter)

View file

@ -641,7 +641,7 @@ proc myOpen(g: ModuleGraph; module: PSym; cache: IdentCache): PPassContext =
rawAddInterfaceSym(w, module) rawAddInterfaceSym(w, module)
result = w result = w
proc myClose(c: PPassContext, n: PNode): PNode = proc myClose(graph: ModuleGraph; c: PPassContext, n: PNode): PNode =
result = process(c, n) result = process(c, n)
var w = PRodWriter(c) var w = PRodWriter(c)
writeRod(w) writeRod(w)

View file

@ -166,7 +166,7 @@ proc commonType*(x, y: PType): PType =
result.addSonSkipIntLit(r) result.addSonSkipIntLit(r)
proc newSymS(kind: TSymKind, n: PNode, c: PContext): PSym = proc newSymS(kind: TSymKind, n: PNode, c: PContext): PSym =
result = newSym(kind, considerQuotedIdent(n), getCurrOwner(), n.info) result = newSym(kind, considerQuotedIdent(n), getCurrOwner(c), n.info)
proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym = proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym =
proc `$`(kind: TSymKind): string = substr(system.`$`(kind), 2).toLowerAscii proc `$`(kind: TSymKind): string = substr(system.`$`(kind), 2).toLowerAscii
@ -186,9 +186,9 @@ proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym =
# when there is a nested proc inside a template, semtmpl # when there is a nested proc inside a template, semtmpl
# will assign a wrong owner during the first pass over the # will assign a wrong owner during the first pass over the
# template; we must fix it here: see #909 # template; we must fix it here: see #909
result.owner = getCurrOwner() result.owner = getCurrOwner(c)
else: else:
result = newSym(kind, considerQuotedIdent(n), getCurrOwner(), n.info) result = newSym(kind, considerQuotedIdent(n), getCurrOwner(c), n.info)
#if kind in {skForVar, skLet, skVar} and result.owner.kind == skModule: #if kind in {skForVar, skLet, skVar} and result.owner.kind == skModule:
# incl(result.flags, sfGlobal) # incl(result.flags, sfGlobal)
@ -376,7 +376,7 @@ proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
flags: TExprFlags = {}): PNode = flags: TExprFlags = {}): PNode =
pushInfoContext(nOrig.info) pushInfoContext(nOrig.info)
markUsed(n.info, sym) markUsed(n.info, sym, c.graph.usageSym)
styleCheckUse(n.info, sym) styleCheckUse(n.info, sym)
if sym == c.p.owner: if sym == c.p.owner:
globalError(n.info, errRecursiveDependencyX, sym.name.s) globalError(n.info, errRecursiveDependencyX, sym.name.s)
@ -434,7 +434,7 @@ proc myOpen(graph: ModuleGraph; module: PSym; cache: IdentCache): PPassContext =
c.instTypeBoundOp = sigmatch.instTypeBoundOp c.instTypeBoundOp = sigmatch.instTypeBoundOp
pushProcCon(c, module) pushProcCon(c, module)
pushOwner(c.module) pushOwner(c, c.module)
c.importTable = openScope(c) c.importTable = openScope(c)
c.importTable.addSym(module) # a module knows itself c.importTable.addSym(module) # a module knows itself
if sfSystemModule in module.flags: if sfSystemModule in module.flags:
@ -450,7 +450,7 @@ proc myOpen(graph: ModuleGraph; module: PSym; cache: IdentCache): PPassContext =
proc myOpenCached(graph: ModuleGraph; module: PSym; rd: PRodReader): PPassContext = proc myOpenCached(graph: ModuleGraph; module: PSym; rd: PRodReader): PPassContext =
result = myOpen(graph, module, rd.cache) result = myOpen(graph, module, rd.cache)
for m in items(rd.methods): methodDef(m, true) for m in items(rd.methods): methodDef(graph, m, true)
proc isImportSystemStmt(n: PNode): bool = proc isImportSystemStmt(n: PNode): bool =
if magicsys.systemModule == nil: return false if magicsys.systemModule == nil: return false
@ -502,7 +502,7 @@ proc recoverContext(c: PContext) =
# faster than wrapping every stack operation in a 'try finally' block and # faster than wrapping every stack operation in a 'try finally' block and
# requires far less code. # requires far less code.
c.currentScope = c.topLevelScope c.currentScope = c.topLevelScope
while getCurrOwner().kind != skModule: popOwner() while getCurrOwner(c).kind != skModule: popOwner(c)
while c.p != nil and c.p.owner.kind != skModule: c.p = c.p.next while c.p != nil and c.p.owner.kind != skModule: c.p = c.p.next
proc myProcess(context: PPassContext, n: PNode): PNode = proc myProcess(context: PPassContext, n: PNode): PNode =
@ -523,7 +523,7 @@ proc myProcess(context: PPassContext, n: PNode): PNode =
else: result = ast.emptyNode else: result = ast.emptyNode
#if gCmd == cmdIdeTools: findSuggest(c, n) #if gCmd == cmdIdeTools: findSuggest(c, n)
proc myClose(context: PPassContext, n: PNode): PNode = proc myClose(graph: ModuleGraph; context: PPassContext, n: PNode): PNode =
var c = PContext(context) var c = PContext(context)
closeScope(c) # close module's scope closeScope(c) # close module's scope
rawCloseScope(c) # imported symbols; don't check for unused ones! rawCloseScope(c) # imported symbols; don't check for unused ones!
@ -533,7 +533,7 @@ proc myClose(context: PPassContext, n: PNode): PNode =
addCodeForGenerics(c, result) addCodeForGenerics(c, result)
if c.module.ast != nil: if c.module.ast != nil:
result.add(c.module.ast) result.add(c.module.ast)
popOwner() popOwner(c)
popProcCon(c) popProcCon(c)
const semPass* = makePass(myOpen, myOpenCached, myProcess, myClose) const semPass* = makePass(myOpen, myOpenCached, myProcess, myClose)

View file

@ -105,7 +105,7 @@ proc considerOverloadedOp(c: var TLiftCtx; t: PType; body, x, y: PNode): bool =
of attachedDestructor: of attachedDestructor:
let op = t.destructor let op = t.destructor
if op != nil: if op != nil:
markUsed(c.info, op) markUsed(c.info, op, c.c.graph.usageSym)
styleCheckUse(c.info, op) styleCheckUse(c.info, op)
body.add newDestructorCall(op, x) body.add newDestructorCall(op, x)
result = true result = true
@ -123,14 +123,14 @@ proc considerOverloadedOp(c: var TLiftCtx; t: PType; body, x, y: PNode): bool =
op = t.assignment op = t.assignment
if op == nil: if op == nil:
op = liftBody(c.c, t, c.info) op = liftBody(c.c, t, c.info)
markUsed(c.info, op) markUsed(c.info, op, c.c.graph.usageSym)
styleCheckUse(c.info, op) styleCheckUse(c.info, op)
body.add newAsgnCall(c.c, op, x, y) body.add newAsgnCall(c.c, op, x, y)
result = true result = true
of attachedDeepCopy: of attachedDeepCopy:
let op = t.deepCopy let op = t.deepCopy
if op != nil: if op != nil:
markUsed(c.info, op) markUsed(c.info, op, c.c.graph.usageSym)
styleCheckUse(c.info, op) styleCheckUse(c.info, op)
body.add newDeepCopyCall(op, x, y) body.add newDeepCopyCall(op, x, y)
result = true result = true

View file

@ -335,7 +335,7 @@ proc inferWithMetatype(c: PContext, formal: PType,
proc semResolvedCall(c: PContext, n: PNode, x: TCandidate): PNode = proc semResolvedCall(c: PContext, n: PNode, x: TCandidate): PNode =
assert x.state == csMatch assert x.state == csMatch
var finalCallee = x.calleeSym var finalCallee = x.calleeSym
markUsed(n.sons[0].info, finalCallee) markUsed(n.sons[0].info, finalCallee, c.graph.usageSym)
styleCheckUse(n.sons[0].info, finalCallee) styleCheckUse(n.sons[0].info, finalCallee)
assert finalCallee.ast != nil assert finalCallee.ast != nil
if x.hasFauxMatch: if x.hasFauxMatch:
@ -411,7 +411,7 @@ proc explicitGenericSym(c: PContext, n: PNode, s: PSym): PNode =
let tm = typeRel(m, formal, arg, true) let tm = typeRel(m, formal, arg, true)
if tm in {isNone, isConvertible}: return nil if tm in {isNone, isConvertible}: return nil
var newInst = generateInstance(c, s, m.bindings, n.info) var newInst = generateInstance(c, s, m.bindings, n.info)
markUsed(n.info, s) markUsed(n.info, s, c.graph.usageSym)
styleCheckUse(n.info, s) styleCheckUse(n.info, s)
result = newSymNode(newInst, n.info) result = newSymNode(newInst, n.info)

View file

@ -125,22 +125,20 @@ proc scopeDepth*(c: PContext): int {.inline.} =
result = if c.currentScope != nil: c.currentScope.depthLevel result = if c.currentScope != nil: c.currentScope.depthLevel
else: 0 else: 0
var gOwners*: seq[PSym] = @[] proc getCurrOwner*(c: PContext): PSym =
proc getCurrOwner*(): PSym =
# owner stack (used for initializing the # owner stack (used for initializing the
# owner field of syms) # owner field of syms)
# the documentation comment always gets # the documentation comment always gets
# assigned to the current owner # assigned to the current owner
# BUGFIX: global array is needed! # BUGFIX: global array is needed!
result = gOwners[high(gOwners)] result = c.graph.owners[^1]
proc pushOwner*(owner: PSym) = proc pushOwner*(c: PContext; owner: PSym) =
add(gOwners, owner) add(c.graph.owners, owner)
proc popOwner*() = proc popOwner*(c: PContext) =
var length = len(gOwners) var length = len(c.graph.owners)
if length > 0: setLen(gOwners, length - 1) if length > 0: setLen(c.graph.owners, length - 1)
else: internalError("popOwner") else: internalError("popOwner")
proc lastOptionEntry*(c: PContext): POptionEntry = proc lastOptionEntry*(c: PContext): POptionEntry =
@ -226,7 +224,7 @@ proc addToLib*(lib: PLib, sym: PSym) =
sym.annex = lib sym.annex = lib
proc newTypeS*(kind: TTypeKind, c: PContext): PType = proc newTypeS*(kind: TTypeKind, c: PContext): PType =
result = newType(kind, getCurrOwner()) result = newType(kind, getCurrOwner(c))
proc makePtrType*(c: PContext, baseType: PType): PType = proc makePtrType*(c: PContext, baseType: PType): PType =
result = newTypeS(tyPtr, c) result = newTypeS(tyPtr, c)
@ -245,7 +243,7 @@ proc makeTypeDesc*(c: PContext, typ: PType): PType =
proc makeTypeSymNode*(c: PContext, typ: PType, info: TLineInfo): PNode = proc makeTypeSymNode*(c: PContext, typ: PType, info: TLineInfo): PNode =
let typedesc = makeTypeDesc(c, typ) let typedesc = makeTypeDesc(c, typ)
let sym = newSym(skType, c.cache.idAnon, getCurrOwner(), info).linkTo(typedesc) let sym = newSym(skType, c.cache.idAnon, getCurrOwner(c), info).linkTo(typedesc)
return newSymNode(sym, info) return newSymNode(sym, info)
proc makeTypeFromExpr*(c: PContext, n: PNode): PType = proc makeTypeFromExpr*(c: PContext, n: PNode): PType =
@ -255,7 +253,7 @@ proc makeTypeFromExpr*(c: PContext, n: PNode): PType =
proc newTypeWithSons*(c: PContext, kind: TTypeKind, proc newTypeWithSons*(c: PContext, kind: TTypeKind,
sons: seq[PType]): PType = sons: seq[PType]): PType =
result = newType(kind, getCurrOwner()) result = newType(kind, getCurrOwner(c))
result.sons = sons result.sons = sons
proc makeStaticExpr*(c: PContext, n: PNode): PNode = proc makeStaticExpr*(c: PContext, n: PNode): PNode =
@ -326,7 +324,7 @@ proc errorNode*(c: PContext, n: PNode): PNode =
proc fillTypeS*(dest: PType, kind: TTypeKind, c: PContext) = proc fillTypeS*(dest: PType, kind: TTypeKind, c: PContext) =
dest.kind = kind dest.kind = kind
dest.owner = getCurrOwner() dest.owner = getCurrOwner(c)
dest.size = - 1 dest.size = - 1
proc makeRangeType*(c: PContext; first, last: BiggestInt; proc makeRangeType*(c: PContext; first, last: BiggestInt;

View file

@ -51,7 +51,7 @@ proc doDestructorStuff(c: PContext, s: PSym, n: PNode) =
let destructableT = instantiateDestructor(c, t.sons[i]) let destructableT = instantiateDestructor(c, t.sons[i])
if destructableT != nil: if destructableT != nil:
n.sons[bodyPos].addSon(newNode(nkCall, t.sym.info, @[ n.sons[bodyPos].addSon(newNode(nkCall, t.sym.info, @[
useSym(destructableT.destructor), useSym(destructableT.destructor, c.graph.usageSym),
n.sons[paramsPos][1][0]])) n.sons[paramsPos][1][0]]))
proc destroyFieldOrFields(c: PContext, field: PNode, holder: PNode): PNode proc destroyFieldOrFields(c: PContext, field: PNode, holder: PNode): PNode
@ -60,8 +60,8 @@ proc destroySym(c: PContext, field: PSym, holder: PNode): PNode =
let destructableT = instantiateDestructor(c, field.typ) let destructableT = instantiateDestructor(c, field.typ)
if destructableT != nil: if destructableT != nil:
result = newNode(nkCall, field.info, @[ result = newNode(nkCall, field.info, @[
useSym(destructableT.destructor), useSym(destructableT.destructor, c.graph.usageSym),
newNode(nkDotExpr, field.info, @[holder, useSym(field)])]) newNode(nkDotExpr, field.info, @[holder, useSym(field, c.graph.usageSym)])])
proc destroyCase(c: PContext, n: PNode, holder: PNode): PNode = proc destroyCase(c: PContext, n: PNode, holder: PNode): PNode =
var nonTrivialFields = 0 var nonTrivialFields = 0
@ -181,7 +181,8 @@ proc createDestructorCall(c: PContext, s: PSym): PNode =
let destructableT = instantiateDestructor(c, varTyp) let destructableT = instantiateDestructor(c, varTyp)
if destructableT != nil: if destructableT != nil:
let call = semStmt(c, newNode(nkCall, s.info, @[ let call = semStmt(c, newNode(nkCall, s.info, @[
useSym(destructableT.destructor), useSym(s)])) useSym(destructableT.destructor, c.graph.usageSym),
useSym(s, c.graph.usageSym)]))
result = newNode(nkDefer, s.info, @[call]) result = newNode(nkDefer, s.info, @[call])
proc insertDestructors(c: PContext, proc insertDestructors(c: PContext,
@ -233,8 +234,8 @@ proc insertDestructors(c: PContext,
tryStmt.addSon( tryStmt.addSon(
newNode(nkFinally, info, @[ newNode(nkFinally, info, @[
semStmt(c, newNode(nkCall, info, @[ semStmt(c, newNode(nkCall, info, @[
useSym(destructableT.destructor), useSym(destructableT.destructor, c.graph.usageSym),
useSym(varId.sym)]))])) useSym(varId.sym, c.graph.usageSym)]))]))
result.outer = newNodeI(nkStmtList, info) result.outer = newNodeI(nkStmtList, info)
varSection.sons.setLen(j+1) varSection.sons.setLen(j+1)

View file

@ -12,10 +12,10 @@
proc semTemplateExpr(c: PContext, n: PNode, s: PSym, proc semTemplateExpr(c: PContext, n: PNode, s: PSym,
flags: TExprFlags = {}): PNode = flags: TExprFlags = {}): PNode =
markUsed(n.info, s) markUsed(n.info, s, c.graph.usageSym)
styleCheckUse(n.info, s) styleCheckUse(n.info, s)
pushInfoContext(n.info) pushInfoContext(n.info)
result = evalTemplate(n, s, getCurrOwner(), efFromHlo in flags) result = evalTemplate(n, s, getCurrOwner(c), efFromHlo in flags)
if efNoSemCheck notin flags: result = semAfterMacroCall(c, result, s, flags) if efNoSemCheck notin flags: result = semAfterMacroCall(c, result, s, flags)
popInfoContext() popInfoContext()
@ -209,7 +209,7 @@ proc semConv(c: PContext, n: PNode): PNode =
let it = op.sons[i] let it = op.sons[i]
let status = checkConvertible(c, result.typ, it.typ) let status = checkConvertible(c, result.typ, it.typ)
if status in {convOK, convNotNeedeed}: if status in {convOK, convNotNeedeed}:
markUsed(n.info, it.sym) markUsed(n.info, it.sym, c.graph.usageSym)
styleCheckUse(n.info, it.sym) styleCheckUse(n.info, it.sym)
markIndirect(c, it.sym) markIndirect(c, it.sym)
return it return it
@ -926,7 +926,7 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
let s = getGenSym(c, sym) let s = getGenSym(c, sym)
case s.kind case s.kind
of skConst: of skConst:
markUsed(n.info, s) markUsed(n.info, s, c.graph.usageSym)
styleCheckUse(n.info, s) styleCheckUse(n.info, s)
case skipTypes(s.typ, abstractInst-{tyTypeDesc}).kind case skipTypes(s.typ, abstractInst-{tyTypeDesc}).kind
of tyNil, tyChar, tyInt..tyInt64, tyFloat..tyFloat128, of tyNil, tyChar, tyInt..tyInt64, tyFloat..tyFloat128,
@ -950,20 +950,20 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
result = newSymNode(s, n.info) result = newSymNode(s, n.info)
of skMacro: of skMacro:
if efNoEvaluateGeneric in flags and s.ast[genericParamsPos].len > 0: if efNoEvaluateGeneric in flags and s.ast[genericParamsPos].len > 0:
markUsed(n.info, s) markUsed(n.info, s, c.graph.usageSym)
styleCheckUse(n.info, s) styleCheckUse(n.info, s)
result = newSymNode(s, n.info) result = newSymNode(s, n.info)
else: else:
result = semMacroExpr(c, n, n, s, flags) result = semMacroExpr(c, n, n, s, flags)
of skTemplate: of skTemplate:
if efNoEvaluateGeneric in flags and s.ast[genericParamsPos].len > 0: if efNoEvaluateGeneric in flags and s.ast[genericParamsPos].len > 0:
markUsed(n.info, s) markUsed(n.info, s, c.graph.usageSym)
styleCheckUse(n.info, s) styleCheckUse(n.info, s)
result = newSymNode(s, n.info) result = newSymNode(s, n.info)
else: else:
result = semTemplateExpr(c, n, s, flags) result = semTemplateExpr(c, n, s, flags)
of skParam: of skParam:
markUsed(n.info, s) markUsed(n.info, s, c.graph.usageSym)
styleCheckUse(n.info, s) styleCheckUse(n.info, s)
if s.typ.kind == tyStatic and s.typ.n != nil: if s.typ.kind == tyStatic and s.typ.n != nil:
# XXX see the hack in sigmatch.nim ... # XXX see the hack in sigmatch.nim ...
@ -985,7 +985,7 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
if s.magic == mNimvm: if s.magic == mNimvm:
localError(n.info, "illegal context for 'nimvm' magic") localError(n.info, "illegal context for 'nimvm' magic")
markUsed(n.info, s) markUsed(n.info, s, c.graph.usageSym)
styleCheckUse(n.info, s) styleCheckUse(n.info, s)
result = newSymNode(s, n.info) result = newSymNode(s, n.info)
# We cannot check for access to outer vars for example because it's still # We cannot check for access to outer vars for example because it's still
@ -1003,7 +1003,7 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
n.typ = s.typ n.typ = s.typ
return n return n
of skType: of skType:
markUsed(n.info, s) markUsed(n.info, s, c.graph.usageSym)
styleCheckUse(n.info, s) styleCheckUse(n.info, s)
if s.typ.kind == tyStatic and s.typ.n != nil: if s.typ.kind == tyStatic and s.typ.n != nil:
return s.typ.n return s.typ.n
@ -1025,7 +1025,7 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
if f != nil and fieldVisible(c, f): if f != nil and fieldVisible(c, f):
# is the access to a public field or in the same module or in a friend? # is the access to a public field or in the same module or in a friend?
doAssert f == s doAssert f == s
markUsed(n.info, f) markUsed(n.info, f, c.graph.usageSym)
styleCheckUse(n.info, f) styleCheckUse(n.info, f)
result = newNodeIT(nkDotExpr, n.info, f.typ) result = newNodeIT(nkDotExpr, n.info, f.typ)
result.add makeDeref(newSymNode(p.selfSym)) result.add makeDeref(newSymNode(p.selfSym))
@ -1038,11 +1038,11 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
if ty.sons[0] == nil: break if ty.sons[0] == nil: break
ty = skipTypes(ty.sons[0], skipPtrs) ty = skipTypes(ty.sons[0], skipPtrs)
# old code, not sure if it's live code: # old code, not sure if it's live code:
markUsed(n.info, s) markUsed(n.info, s, c.graph.usageSym)
styleCheckUse(n.info, s) styleCheckUse(n.info, s)
result = newSymNode(s, n.info) result = newSymNode(s, n.info)
else: else:
markUsed(n.info, s) markUsed(n.info, s, c.graph.usageSym)
styleCheckUse(n.info, s) styleCheckUse(n.info, s)
result = newSymNode(s, n.info) result = newSymNode(s, n.info)
@ -1062,7 +1062,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
result = symChoice(c, n, s, scClosed) result = symChoice(c, n, s, scClosed)
if result.kind == nkSym: result = semSym(c, n, s, flags) if result.kind == nkSym: result = semSym(c, n, s, flags)
else: else:
markUsed(n.sons[1].info, s) markUsed(n.sons[1].info, s, c.graph.usageSym)
result = semSym(c, n, s, flags) result = semSym(c, n, s, flags)
styleCheckUse(n.sons[1].info, s) styleCheckUse(n.sons[1].info, s)
return return
@ -1087,7 +1087,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
result = newSymNode(f) result = newSymNode(f)
result.info = n.info result.info = n.info
result.typ = ty result.typ = ty
markUsed(n.info, f) markUsed(n.info, f, c.graph.usageSym)
styleCheckUse(n.info, f) styleCheckUse(n.info, f)
return return
of tyTypeParamsHolders: of tyTypeParamsHolders:
@ -1120,7 +1120,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
if f != nil: if f != nil:
if fieldVisible(c, f): if fieldVisible(c, f):
# is the access to a public field or in the same module or in a friend? # is the access to a public field or in the same module or in a friend?
markUsed(n.sons[1].info, f) markUsed(n.sons[1].info, f, c.graph.usageSym)
styleCheckUse(n.sons[1].info, f) styleCheckUse(n.sons[1].info, f)
n.sons[0] = makeDeref(n.sons[0]) n.sons[0] = makeDeref(n.sons[0])
n.sons[1] = newSymNode(f) # we now have the correct field n.sons[1] = newSymNode(f) # we now have the correct field
@ -1134,7 +1134,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
elif ty.kind == tyTuple and ty.n != nil: elif ty.kind == tyTuple and ty.n != nil:
f = getSymFromList(ty.n, i) f = getSymFromList(ty.n, i)
if f != nil: if f != nil:
markUsed(n.sons[1].info, f) markUsed(n.sons[1].info, f, c.graph.usageSym)
styleCheckUse(n.sons[1].info, f) styleCheckUse(n.sons[1].info, f)
n.sons[0] = makeDeref(n.sons[0]) n.sons[0] = makeDeref(n.sons[0])
n.sons[1] = newSymNode(f) n.sons[1] = newSymNode(f)
@ -1581,9 +1581,8 @@ proc getMagicSym(magic: TMagic): PSym =
result = newSym(skProc, getIdent($magic), systemModule, gCodegenLineInfo) result = newSym(skProc, getIdent($magic), systemModule, gCodegenLineInfo)
result.magic = magic result.magic = magic
proc newAnonSym(c: PContext; kind: TSymKind, info: TLineInfo, proc newAnonSym(c: PContext; kind: TSymKind, info: TLineInfo): PSym =
owner = getCurrOwner()): PSym = result = newSym(kind, c.cache.idAnon, getCurrOwner(c), info)
result = newSym(kind, c.cache.idAnon, owner, info)
result.flags = {sfGenSym} result.flags = {sfGenSym}
proc semExpandToAst(c: PContext, n: PNode): PNode = proc semExpandToAst(c: PContext, n: PNode): PNode =
@ -1592,7 +1591,7 @@ proc semExpandToAst(c: PContext, n: PNode): PNode =
if expandedSym.kind == skError: return n if expandedSym.kind == skError: return n
macroCall.sons[0] = newSymNode(expandedSym, macroCall.info) macroCall.sons[0] = newSymNode(expandedSym, macroCall.info)
markUsed(n.info, expandedSym) markUsed(n.info, expandedSym, c.graph.usageSym)
styleCheckUse(n.info, expandedSym) styleCheckUse(n.info, expandedSym)
for i in countup(1, macroCall.len-1): for i in countup(1, macroCall.len-1):
@ -1683,7 +1682,7 @@ proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
# open a scope for temporary symbol inclusions: # open a scope for temporary symbol inclusions:
let oldScope = c.currentScope let oldScope = c.currentScope
openScope(c) openScope(c)
let oldOwnerLen = len(gOwners) let oldOwnerLen = len(c.graph.owners)
let oldGenerics = c.generics let oldGenerics = c.generics
let oldErrorOutputs = errorOutputs let oldErrorOutputs = errorOutputs
errorOutputs = {} errorOutputs = {}
@ -1709,7 +1708,7 @@ proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
c.inGenericInst = oldInGenericInst c.inGenericInst = oldInGenericInst
c.p = oldProcCon c.p = oldProcCon
msgs.setInfoContextLen(oldContextLen) msgs.setInfoContextLen(oldContextLen)
setLen(gOwners, oldOwnerLen) setLen(c.graph.owners, oldOwnerLen)
c.currentScope = oldScope c.currentScope = oldScope
errorOutputs = oldErrorOutputs errorOutputs = oldErrorOutputs
msgs.gErrorCounter = oldErrorCount msgs.gErrorCounter = oldErrorCount
@ -2108,7 +2107,7 @@ proc semBlock(c: PContext, n: PNode): PNode =
if sfGenSym notin labl.flags: if sfGenSym notin labl.flags:
addDecl(c, labl) addDecl(c, labl)
n.sons[0] = newSymNode(labl, n.sons[0].info) n.sons[0] = newSymNode(labl, n.sons[0].info)
suggestSym(n.sons[0].info, labl) suggestSym(n.sons[0].info, labl, c.graph.usageSym)
styleCheckDef(labl) styleCheckDef(labl)
n.sons[1] = semExpr(c, n.sons[1]) n.sons[1] = semExpr(c, n.sons[1])
n.typ = n.sons[1].typ n.typ = n.sons[1].typ

View file

@ -108,7 +108,7 @@ proc semForFields(c: PContext, n: PNode, m: TMagic): PNode =
var trueSymbol = strTableGet(magicsys.systemModule.tab, getIdent"true") var trueSymbol = strTableGet(magicsys.systemModule.tab, getIdent"true")
if trueSymbol == nil: if trueSymbol == nil:
localError(n.info, errSystemNeeds, "true") localError(n.info, errSystemNeeds, "true")
trueSymbol = newSym(skUnknown, getIdent"true", getCurrOwner(), n.info) trueSymbol = newSym(skUnknown, getIdent"true", getCurrOwner(c), n.info)
trueSymbol.typ = getSysType(tyBool) trueSymbol.typ = getSysType(tyBool)
result.sons[0] = newSymNode(trueSymbol, n.info) result.sons[0] = newSymNode(trueSymbol, n.info)

View file

@ -61,7 +61,7 @@ iterator instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable): PSym
if q.typ.kind notin {tyTypeDesc, tyGenericParam, tyStatic}+tyTypeClasses: if q.typ.kind notin {tyTypeDesc, tyGenericParam, tyStatic}+tyTypeClasses:
continue continue
let symKind = if q.typ.kind == tyStatic: skConst else: skType let symKind = if q.typ.kind == tyStatic: skConst else: skType
var s = newSym(symKind, q.name, getCurrOwner(), q.info) var s = newSym(symKind, q.name, getCurrOwner(c), q.info)
s.flags = s.flags + {sfUsed, sfFromGeneric} s.flags = s.flags + {sfUsed, sfFromGeneric}
var t = PType(idTableGet(pt, q.typ)) var t = PType(idTableGet(pt, q.typ))
if t == nil: if t == nil:
@ -255,7 +255,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
incl(result.flags, sfFromGeneric) incl(result.flags, sfFromGeneric)
result.owner = fn result.owner = fn
result.ast = n result.ast = n
pushOwner(result) pushOwner(c, result)
openScope(c) openScope(c)
let gp = n.sons[genericParamsPos] let gp = n.sons[genericParamsPos]
@ -304,7 +304,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
popProcCon(c) popProcCon(c)
popInfoContext() popInfoContext()
closeScope(c) # close scope for parameters closeScope(c) # close scope for parameters
popOwner() popOwner(c)
c.currentScope = oldScope c.currentScope = oldScope
discard c.friendModules.pop() discard c.friendModules.pop()
dec(c.instCounter) dec(c.instCounter)

View file

@ -107,7 +107,7 @@ proc semTypeTraits(c: PContext, n: PNode): PNode =
if t.sonsLen > 0: if t.sonsLen > 0:
# This is either a type known to sem or a typedesc # This is either a type known to sem or a typedesc
# param to a regular proc (again, known at instantiation) # param to a regular proc (again, known at instantiation)
result = evalTypeTrait(n[0], t, getCurrOwner()) result = evalTypeTrait(n[0], t, getCurrOwner(c))
else: else:
# a typedesc variable, pass unmodified to evals # a typedesc variable, pass unmodified to evals
result = n result = n

View file

@ -35,7 +35,7 @@ proc semBreakOrContinue(c: PContext, n: PNode): PNode =
x.info = n.info x.info = n.info
incl(s.flags, sfUsed) incl(s.flags, sfUsed)
n.sons[0] = x n.sons[0] = x
suggestSym(x.info, s) suggestSym(x.info, s, c.graph.usageSym)
styleCheckUse(x.info, s) styleCheckUse(x.info, s)
else: else:
localError(n.info, errInvalidControlFlowX, s.name.s) localError(n.info, errInvalidControlFlowX, s.name.s)
@ -366,11 +366,13 @@ proc semIdentDef(c: PContext, n: PNode, kind: TSymKind): PSym =
if isTopLevel(c): if isTopLevel(c):
result = semIdentWithPragma(c, kind, n, {sfExported}) result = semIdentWithPragma(c, kind, n, {sfExported})
incl(result.flags, sfGlobal) incl(result.flags, sfGlobal)
#if kind in {skVar, skLet}:
# echo "global variable here ", n.info, " ", result.name.s
else: else:
result = semIdentWithPragma(c, kind, n, {}) result = semIdentWithPragma(c, kind, n, {})
if result.owner.kind == skModule: if result.owner.kind == skModule:
incl(result.flags, sfGlobal) incl(result.flags, sfGlobal)
suggestSym(n.info, result) suggestSym(n.info, result, c.graph.usageSym)
styleCheckDef(result) styleCheckDef(result)
proc checkNilable(v: PSym) = proc checkNilable(v: PSym) =
@ -621,7 +623,7 @@ proc semForVars(c: PContext, n: PNode): PNode =
if iter.kind != tyTuple or length == 3: if iter.kind != tyTuple or length == 3:
if length == 3: if length == 3:
var v = symForVar(c, n.sons[0]) var v = symForVar(c, n.sons[0])
if getCurrOwner().kind == skModule: incl(v.flags, sfGlobal) if getCurrOwner(c).kind == skModule: incl(v.flags, sfGlobal)
# BUGFIX: don't use `iter` here as that would strip away # BUGFIX: don't use `iter` here as that would strip away
# the ``tyGenericInst``! See ``tests/compile/tgeneric.nim`` # the ``tyGenericInst``! See ``tests/compile/tgeneric.nim``
# for an example: # for an example:
@ -635,7 +637,7 @@ proc semForVars(c: PContext, n: PNode): PNode =
else: else:
for i in countup(0, length - 3): for i in countup(0, length - 3):
var v = symForVar(c, n.sons[i]) var v = symForVar(c, n.sons[i])
if getCurrOwner().kind == skModule: incl(v.flags, sfGlobal) if getCurrOwner(c).kind == skModule: incl(v.flags, sfGlobal)
v.typ = iter.sons[i] v.typ = iter.sons[i]
n.sons[i] = newSymNode(v) n.sons[i] = newSymNode(v)
if sfGenSym notin v.flags and not isDiscardUnderscore(v): if sfGenSym notin v.flags and not isDiscardUnderscore(v):
@ -745,7 +747,7 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
# We have a generic type declaration here. In generic types, # We have a generic type declaration here. In generic types,
# symbol lookup needs to be done here. # symbol lookup needs to be done here.
openScope(c) openScope(c)
pushOwner(s) pushOwner(c, s)
if s.magic == mNone: s.typ.kind = tyGenericBody if s.magic == mNone: s.typ.kind = tyGenericBody
# XXX for generic type aliases this is not correct! We need the # XXX for generic type aliases this is not correct! We need the
# underlying Id really: # underlying Id really:
@ -769,11 +771,11 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
body.sym = s body.sym = s
body.size = -1 # could not be computed properly body.size = -1 # could not be computed properly
s.typ.sons[sonsLen(s.typ) - 1] = body s.typ.sons[sonsLen(s.typ) - 1] = body
popOwner() popOwner(c)
closeScope(c) closeScope(c)
elif a.sons[2].kind != nkEmpty: elif a.sons[2].kind != nkEmpty:
# process the type's body: # process the type's body:
pushOwner(s) pushOwner(c, s)
var t = semTypeNode(c, a.sons[2], s.typ) var t = semTypeNode(c, a.sons[2], s.typ)
if s.typ == nil: if s.typ == nil:
s.typ = t s.typ = t
@ -782,7 +784,7 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
assignType(s.typ, t) assignType(s.typ, t)
#debug s.typ #debug s.typ
s.ast = a s.ast = a
popOwner() popOwner(c)
let aa = a.sons[2] let aa = a.sons[2]
if aa.kind in {nkRefTy, nkPtrTy} and aa.len == 1 and if aa.kind in {nkRefTy, nkPtrTy} and aa.len == 1 and
aa.sons[0].kind == nkObjectTy: aa.sons[0].kind == nkObjectTy:
@ -793,7 +795,7 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
internalAssert st.lastSon.sym == nil internalAssert st.lastSon.sym == nil
incl st.flags, tfRefsAnonObj incl st.flags, tfRefsAnonObj
let obj = newSym(skType, getIdent(s.name.s & ":ObjectType"), let obj = newSym(skType, getIdent(s.name.s & ":ObjectType"),
getCurrOwner(), s.info) getCurrOwner(c), s.info)
obj.typ = st.lastSon obj.typ = st.lastSon
st.lastSon.sym = obj st.lastSon.sym = obj
@ -927,7 +929,7 @@ proc semBorrow(c: PContext, n: PNode, s: PSym) =
proc addResult(c: PContext, t: PType, info: TLineInfo, owner: TSymKind) = proc addResult(c: PContext, t: PType, info: TLineInfo, owner: TSymKind) =
if t != nil: if t != nil:
var s = newSym(skResult, getIdent"result", getCurrOwner(), info) var s = newSym(skResult, getIdent"result", getCurrOwner(c), info)
s.typ = t s.typ = t
incl(s.flags, sfUsed) incl(s.flags, sfUsed)
addParamOrResult(c, s, owner) addParamOrResult(c, s, owner)
@ -1002,12 +1004,12 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode =
checkSonsLen(n, bodyPos + 1) checkSonsLen(n, bodyPos + 1)
var s: PSym var s: PSym
if n[namePos].kind != nkSym: if n[namePos].kind != nkSym:
s = newSym(skProc, c.cache.idAnon, getCurrOwner(), n.info) s = newSym(skProc, c.cache.idAnon, getCurrOwner(c), n.info)
s.ast = n s.ast = n
n.sons[namePos] = newSymNode(s) n.sons[namePos] = newSymNode(s)
else: else:
s = n[namePos].sym s = n[namePos].sym
pushOwner(s) pushOwner(c, s)
openScope(c) openScope(c)
var gp: PNode var gp: PNode
if n.sons[genericParamsPos].kind != nkEmpty: if n.sons[genericParamsPos].kind != nkEmpty:
@ -1047,7 +1049,7 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode =
else: else:
localError(n.info, errImplOfXexpected, s.name.s) localError(n.info, errImplOfXexpected, s.name.s)
closeScope(c) # close scope for parameters closeScope(c) # close scope for parameters
popOwner() popOwner(c)
result.typ = s.typ result.typ = s.typ
proc semDo(c: PContext, n: PNode, flags: TExprFlags): PNode = proc semDo(c: PContext, n: PNode, flags: TExprFlags): PNode =
@ -1081,7 +1083,7 @@ proc semInferredLambda(c: PContext, pt: TIdTable, n: PNode): PNode =
params[i].sym.name.s) params[i].sym.name.s)
#params[i].sym.owner = s #params[i].sym.owner = s
openScope(c) openScope(c)
pushOwner(s) pushOwner(c, s)
addParams(c, params, skProc) addParams(c, params, skProc)
pushProcCon(c, s) pushProcCon(c, s)
addResult(c, n.typ.sons[0], n.info, skProc) addResult(c, n.typ.sons[0], n.info, skProc)
@ -1089,7 +1091,7 @@ proc semInferredLambda(c: PContext, pt: TIdTable, n: PNode): PNode =
let semBody = hloBody(c, semProcBody(c, n.sons[bodyPos])) let semBody = hloBody(c, semProcBody(c, n.sons[bodyPos]))
n.sons[bodyPos] = transformBody(c.module, semBody, s) n.sons[bodyPos] = transformBody(c.module, semBody, s)
popProcCon(c) popProcCon(c)
popOwner() popOwner(c)
closeScope(c) closeScope(c)
# alternative variant (not quite working): # alternative variant (not quite working):
@ -1193,6 +1195,42 @@ type
import compilerlog import compilerlog
proc hasObjParam(s: PSym): bool =
var t = s.typ
for col in countup(1, sonsLen(t)-1):
if skipTypes(t.sons[col], skipPtrs).kind == tyObject:
return true
proc finishMethod(c: PContext, s: PSym) =
if hasObjParam(s):
methodDef(c.graph, s, false)
proc semMethodPrototype(c: PContext; s: PSym; n: PNode) =
if isGenericRoutine(s):
let tt = s.typ
var foundObj = false
# we start at 1 for now so that tparsecombnum continues to compile.
# XXX Revisit this problem later.
for col in countup(1, sonsLen(tt)-1):
let t = tt.sons[col]
if t != nil and t.kind == tyGenericInvocation:
var x = skipTypes(t.sons[0], {tyVar, tyPtr, tyRef, tyGenericInst,
tyGenericInvocation, tyGenericBody,
tyAlias})
if x.kind == tyObject and t.len-1 == n.sons[genericParamsPos].len:
foundObj = true
x.methods.safeAdd((col,s))
if not foundObj:
message(n.info, warnDeprecated, "generic method not attachable to object type")
else:
# why check for the body? bug #2400 has none. Checking for sfForward makes
# no sense either.
# and result.sons[bodyPos].kind != nkEmpty:
if hasObjParam(s):
methodDef(c.graph, s, fromCache=false)
else:
localError(n.info, errXNeedsParamObjectType, "method")
proc semProcAux(c: PContext, n: PNode, kind: TSymKind, proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
validPragmas: TSpecialWords, validPragmas: TSpecialWords,
phase = stepRegisterSymbol): PNode = phase = stepRegisterSymbol): PNode =
@ -1207,7 +1245,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
assert phase == stepRegisterSymbol assert phase == stepRegisterSymbol
if n[namePos].kind == nkEmpty: if n[namePos].kind == nkEmpty:
s = newSym(kind, c.cache.idAnon, getCurrOwner(), n.info) s = newSym(kind, c.cache.idAnon, getCurrOwner(c), n.info)
incl(s.flags, sfUsed) incl(s.flags, sfUsed)
isAnon = true isAnon = true
else: else:
@ -1224,7 +1262,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
return return
else: else:
s = n[namePos].sym s = n[namePos].sym
s.owner = getCurrOwner() s.owner = getCurrOwner(c)
typeIsDetermined = s.typ == nil typeIsDetermined = s.typ == nil
s.ast = n s.ast = n
#s.scope = c.currentScope #s.scope = c.currentScope
@ -1233,7 +1271,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
# where the proc was declared # where the proc was declared
let oldScope = c.currentScope let oldScope = c.currentScope
#c.currentScope = s.scope #c.currentScope = s.scope
pushOwner(s) pushOwner(c, s)
openScope(c) openScope(c)
var gp: PNode var gp: PNode
if n.sons[genericParamsPos].kind != nkEmpty: if n.sons[genericParamsPos].kind != nkEmpty:
@ -1299,8 +1337,8 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
if importantComments() and not isNil(proto.ast.comment): if importantComments() and not isNil(proto.ast.comment):
n.comment = proto.ast.comment n.comment = proto.ast.comment
proto.ast = n # needed for code generation proto.ast = n # needed for code generation
popOwner() popOwner(c)
pushOwner(s) pushOwner(c, s)
s.options = gOptions s.options = gOptions
if sfOverriden in s.flags or s.name.s[0] == '=': semOverride(c, s, n) if sfOverriden in s.flags or s.name.s[0] == '=': semOverride(c, s, n)
if s.name.s[0] in {'.', '('}: if s.name.s[0] in {'.', '('}:
@ -1317,6 +1355,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
if not usePseudoGenerics and gIdeCmd in {ideSug, ideCon} and not if not usePseudoGenerics and gIdeCmd in {ideSug, ideCon} and not
cursorInProc(n.sons[bodyPos]): cursorInProc(n.sons[bodyPos]):
discard "speed up nimsuggest" discard "speed up nimsuggest"
if s.kind == skMethod: semMethodPrototype(c, s, n)
else: else:
pushProcCon(c, s) pushProcCon(c, s)
if n.sons[genericParamsPos].kind == nkEmpty or usePseudoGenerics: if n.sons[genericParamsPos].kind == nkEmpty or usePseudoGenerics:
@ -1324,6 +1363,8 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
c.p.wasForwarded = proto != nil c.p.wasForwarded = proto != nil
maybeAddResult(c, s, n) maybeAddResult(c, s, n)
if s.kind == skMethod: semMethodPrototype(c, s, n)
if lfDynamicLib notin s.loc.flags: if lfDynamicLib notin s.loc.flags:
# no semantic checking for importc: # no semantic checking for importc:
let semBody = hloBody(c, semProcBody(c, n.sons[bodyPos])) let semBody = hloBody(c, semProcBody(c, n.sons[bodyPos]))
@ -1333,15 +1374,18 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
else: else:
if s.typ.sons[0] != nil and kind != skIterator: if s.typ.sons[0] != nil and kind != skIterator:
addDecl(c, newSym(skUnknown, getIdent"result", nil, n.info)) addDecl(c, newSym(skUnknown, getIdent"result", nil, n.info))
openScope(c) openScope(c)
n.sons[bodyPos] = semGenericStmt(c, n.sons[bodyPos]) n.sons[bodyPos] = semGenericStmt(c, n.sons[bodyPos])
closeScope(c) closeScope(c)
fixupInstantiatedSymbols(c, s) fixupInstantiatedSymbols(c, s)
if s.kind == skMethod: semMethodPrototype(c, s, n)
if sfImportc in s.flags: if sfImportc in s.flags:
# so we just ignore the body after semantic checking for importc: # so we just ignore the body after semantic checking for importc:
n.sons[bodyPos] = ast.emptyNode n.sons[bodyPos] = ast.emptyNode
popProcCon(c) popProcCon(c)
else: else:
if s.kind == skMethod: semMethodPrototype(c, s, n)
if proto != nil: localError(n.info, errImplOfXexpected, proto.name.s) if proto != nil: localError(n.info, errImplOfXexpected, proto.name.s)
if {sfImportc, sfBorrow} * s.flags == {} and s.magic == mNone: if {sfImportc, sfBorrow} * s.flags == {} and s.magic == mNone:
incl(s.flags, sfForward) incl(s.flags, sfForward)
@ -1349,7 +1393,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
sideEffectsCheck(c, s) sideEffectsCheck(c, s)
closeScope(c) # close scope for parameters closeScope(c) # close scope for parameters
# c.currentScope = oldScope # c.currentScope = oldScope
popOwner() popOwner(c)
if n.sons[patternPos].kind != nkEmpty: if n.sons[patternPos].kind != nkEmpty:
c.patterns.add(s) c.patterns.add(s)
if isAnon: result.typ = s.typ if isAnon: result.typ = s.typ
@ -1368,7 +1412,7 @@ proc semIterator(c: PContext, n: PNode): PNode =
let isAnon = n[namePos].kind == nkEmpty let isAnon = n[namePos].kind == nkEmpty
if n[namePos].kind == nkSym: if n[namePos].kind == nkSym:
# gensym'ed iterators might need to become closure iterators: # gensym'ed iterators might need to become closure iterators:
n[namePos].sym.owner = getCurrOwner() n[namePos].sym.owner = getCurrOwner(c)
n[namePos].sym.kind = skIterator n[namePos].sym.kind = skIterator
result = semProcAux(c, n, skIterator, iteratorPragmas) result = semProcAux(c, n, skIterator, iteratorPragmas)
var s = result.sons[namePos].sym var s = result.sons[namePos].sym
@ -1395,46 +1439,9 @@ proc semIterator(c: PContext, n: PNode): PNode =
proc semProc(c: PContext, n: PNode): PNode = proc semProc(c: PContext, n: PNode): PNode =
result = semProcAux(c, n, skProc, procPragmas) result = semProcAux(c, n, skProc, procPragmas)
proc hasObjParam(s: PSym): bool =
var t = s.typ
for col in countup(1, sonsLen(t)-1):
if skipTypes(t.sons[col], skipPtrs).kind == tyObject:
return true
proc finishMethod(c: PContext, s: PSym) =
if hasObjParam(s):
methodDef(s, false)
proc semMethod(c: PContext, n: PNode): PNode = proc semMethod(c: PContext, n: PNode): PNode =
if not isTopLevel(c): localError(n.info, errXOnlyAtModuleScope, "method") if not isTopLevel(c): localError(n.info, errXOnlyAtModuleScope, "method")
result = semProcAux(c, n, skMethod, methodPragmas) result = semProcAux(c, n, skMethod, methodPragmas)
# macros can transform methods to nothing:
if namePos >= result.safeLen: return result
var s = result.sons[namePos].sym
if isGenericRoutine(s):
let tt = s.typ
var foundObj = false
# we start at 1 for now so that tparsecombnum continues to compile.
# XXX Revisit this problem later.
for col in countup(1, sonsLen(tt)-1):
let t = tt.sons[col]
if t != nil and t.kind == tyGenericInvocation:
var x = skipTypes(t.sons[0], {tyVar, tyPtr, tyRef, tyGenericInst,
tyGenericInvocation, tyGenericBody,
tyAlias})
if x.kind == tyObject and t.len-1 == result.sons[genericParamsPos].len:
foundObj = true
x.methods.safeAdd((col,s))
if not foundObj:
message(n.info, warnDeprecated, "generic method not attachable to object type")
else:
# why check for the body? bug #2400 has none. Checking for sfForward makes
# no sense either.
# and result.sons[bodyPos].kind != nkEmpty:
if hasObjParam(s):
methodDef(s, fromCache=false)
else:
localError(n.info, errXNeedsParamObjectType, "method")
proc semConverterDef(c: PContext, n: PNode): PNode = proc semConverterDef(c: PContext, n: PNode): PNode =
if not isTopLevel(c): localError(n.info, errXOnlyAtModuleScope, "converter") if not isTopLevel(c): localError(n.info, errXOnlyAtModuleScope, "converter")

View file

@ -60,7 +60,7 @@ proc symChoice(c: PContext, n: PNode, s: PSym, r: TSymChoiceRule): PNode =
# (s.kind notin routineKinds or s.magic != mNone): # (s.kind notin routineKinds or s.magic != mNone):
# for instance 'nextTry' is both in tables.nim and astalgo.nim ... # for instance 'nextTry' is both in tables.nim and astalgo.nim ...
result = newSymNode(s, n.info) result = newSymNode(s, n.info)
markUsed(n.info, s) markUsed(n.info, s, c.graph.usageSym)
else: else:
# semantic checking requires a type; ``fitNode`` deals with it # semantic checking requires a type; ``fitNode`` deals with it
# appropriately # appropriately
@ -559,7 +559,7 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
styleCheckDef(s) styleCheckDef(s)
# check parameter list: # check parameter list:
#s.scope = c.currentScope #s.scope = c.currentScope
pushOwner(s) pushOwner(c, s)
openScope(c) openScope(c)
n.sons[namePos] = newSymNode(s, n.sons[namePos].info) n.sons[namePos] = newSymNode(s, n.sons[namePos].info)
if n.sons[pragmasPos].kind != nkEmpty: if n.sons[pragmasPos].kind != nkEmpty:
@ -613,7 +613,7 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
# only parameters are resolved, no type checking is performed # only parameters are resolved, no type checking is performed
semIdeForTemplateOrGeneric(c, n.sons[bodyPos], ctx.cursorInBody) semIdeForTemplateOrGeneric(c, n.sons[bodyPos], ctx.cursorInBody)
closeScope(c) closeScope(c)
popOwner() popOwner(c)
s.ast = n s.ast = n
result = n result = n
if n.sons[bodyPos].kind == nkEmpty: if n.sons[bodyPos].kind == nkEmpty:
@ -758,7 +758,7 @@ proc semPattern(c: PContext, n: PNode): PNode =
ctx.toMixin = initIntSet() ctx.toMixin = initIntSet()
ctx.toInject = initIntSet() ctx.toInject = initIntSet()
ctx.c = c ctx.c = c
ctx.owner = getCurrOwner() ctx.owner = getCurrOwner(c)
result = flattenStmts(semPatternBody(ctx, n)) result = flattenStmts(semPatternBody(ctx, n))
if result.kind in {nkStmtList, nkStmtListExpr}: if result.kind in {nkStmtList, nkStmtListExpr}:
if result.len == 1: if result.len == 1:

View file

@ -306,7 +306,7 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
else: else:
result = qualifiedLookUp(c, n, {checkAmbiguity, checkUndeclared}) result = qualifiedLookUp(c, n, {checkAmbiguity, checkUndeclared})
if result != nil: if result != nil:
markUsed(n.info, result) markUsed(n.info, result, c.graph.usageSym)
styleCheckUse(n.info, result) styleCheckUse(n.info, result)
if result.kind == skParam and result.typ.kind == tyTypeDesc: if result.kind == skParam and result.typ.kind == tyTypeDesc:
# This is a typedesc param. is it already bound? # This is a typedesc param. is it already bound?
@ -608,7 +608,7 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var IntSet, pos: var int,
let rec = rectype.sym let rec = rectype.sym
for i in countup(0, sonsLen(n)-3): for i in countup(0, sonsLen(n)-3):
var f = semIdentWithPragma(c, skField, n.sons[i], {sfExported}) var f = semIdentWithPragma(c, skField, n.sons[i], {sfExported})
suggestSym(n.sons[i].info, f) suggestSym(n.sons[i].info, f, c.graph.usageSym)
f.typ = typ f.typ = typ
f.position = pos f.position = pos
if (rec != nil) and ({sfImportc, sfExportc} * rec.flags != {}) and if (rec != nil) and ({sfImportc, sfExportc} * rec.flags != {}) and
@ -750,7 +750,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
return genericParams.sons[i].typ return genericParams.sons[i].typ
let owner = if typeClass.sym != nil: typeClass.sym let owner = if typeClass.sym != nil: typeClass.sym
else: getCurrOwner() else: getCurrOwner(c)
var s = newSym(skType, finalTypId, owner, info) var s = newSym(skType, finalTypId, owner, info)
if typId == nil: s.flags.incl(sfAnon) if typId == nil: s.flags.incl(sfAnon)
s.linkTo(typeClass) s.linkTo(typeClass)
@ -850,7 +850,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
of tyGenericInst: of tyGenericInst:
if paramType.lastSon.kind == tyUserTypeClass: if paramType.lastSon.kind == tyUserTypeClass:
var cp = copyType(paramType, getCurrOwner(), false) var cp = copyType(paramType, getCurrOwner(c), false)
cp.kind = tyUserTypeClassInst cp.kind = tyUserTypeClassInst
return addImplicitGeneric(cp) return addImplicitGeneric(cp)
@ -876,10 +876,10 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
result = liftingWalk(expanded, true) result = liftingWalk(expanded, true)
of tyUserTypeClass, tyBuiltInTypeClass, tyAnd, tyOr, tyNot: of tyUserTypeClass, tyBuiltInTypeClass, tyAnd, tyOr, tyNot:
result = addImplicitGeneric(copyType(paramType, getCurrOwner(), true)) result = addImplicitGeneric(copyType(paramType, getCurrOwner(c), true))
of tyGenericParam: of tyGenericParam:
markUsed(info, paramType.sym) markUsed(info, paramType.sym, c.graph.usageSym)
styleCheckUse(info, paramType.sym) styleCheckUse(info, paramType.sym)
if tfWildcard in paramType.flags: if tfWildcard in paramType.flags:
paramType.flags.excl tfWildcard paramType.flags.excl tfWildcard
@ -1267,7 +1267,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
of mExpr: of mExpr:
result = semTypeNode(c, n.sons[0], nil) result = semTypeNode(c, n.sons[0], nil)
if result != nil: if result != nil:
result = copyType(result, getCurrOwner(), false) result = copyType(result, getCurrOwner(c), false)
for i in countup(1, n.len - 1): for i in countup(1, n.len - 1):
result.rawAddSon(semTypeNode(c, n.sons[i], nil)) result.rawAddSon(semTypeNode(c, n.sons[i], nil))
of mDistinct: of mDistinct:
@ -1330,7 +1330,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
else: else:
assignType(prev, t) assignType(prev, t)
result = prev result = prev
markUsed(n.info, n.sym) markUsed(n.info, n.sym, c.graph.usageSym)
styleCheckUse(n.info, n.sym) styleCheckUse(n.info, n.sym)
else: else:
if s.kind != skError: localError(n.info, errTypeExpected) if s.kind != skError: localError(n.info, errTypeExpected)

View file

@ -73,7 +73,7 @@ type
const const
isNilConversion = isConvertible # maybe 'isIntConv' fits better? isNilConversion = isConvertible # maybe 'isIntConv' fits better?
proc markUsed*(info: TLineInfo, s: PSym) proc markUsed*(info: TLineInfo, s: PSym; usageSym: var PSym)
template hasFauxMatch*(c: TCandidate): bool = c.fauxMatch != tyNone template hasFauxMatch*(c: TCandidate): bool = c.fauxMatch != tyNone
@ -1291,7 +1291,7 @@ proc userConvMatch(c: PContext, m: var TCandidate, f, a: PType,
dest = generateTypeInstance(c, m.bindings, arg, dest) dest = generateTypeInstance(c, m.bindings, arg, dest)
let fdest = typeRel(m, f, dest) let fdest = typeRel(m, f, dest)
if fdest in {isEqual, isGeneric}: if fdest in {isEqual, isGeneric}:
markUsed(arg.info, c.converters[i]) markUsed(arg.info, c.converters[i], c.graph.usageSym)
var s = newSymNode(c.converters[i]) var s = newSymNode(c.converters[i])
s.typ = c.converters[i].typ s.typ = c.converters[i].typ
s.info = arg.info s.info = arg.info
@ -1551,7 +1551,7 @@ proc paramTypesMatch*(m: var TCandidate, f, a: PType,
else: result = nil else: result = nil
else: else:
# only one valid interpretation found: # only one valid interpretation found:
markUsed(arg.info, arg.sons[best].sym) markUsed(arg.info, arg.sons[best].sym, m.c.graph.usageSym)
styleCheckUse(arg.info, arg.sons[best].sym) styleCheckUse(arg.info, arg.sons[best].sym)
result = paramTypesMatchAux(m, f, arg.sons[best].typ, arg.sons[best], result = paramTypesMatchAux(m, f, arg.sons[best].typ, arg.sons[best],
argOrig) argOrig)

View file

@ -353,10 +353,10 @@ when defined(nimsuggest):
s.allUsages.add(info) s.allUsages.add(info)
var var
usageSym*: PSym #usageSym*: PSym
lastLineInfo*: TLineInfo lastLineInfo*: TLineInfo
proc findUsages(info: TLineInfo; s: PSym) = proc findUsages(info: TLineInfo; s: PSym; usageSym: var PSym) =
if suggestVersion < 2: if suggestVersion < 2:
if usageSym == nil and isTracked(info, s.name.s.len): if usageSym == nil and isTracked(info, s.name.s.len):
usageSym = s usageSym = s
@ -385,7 +385,7 @@ proc ensureIdx[T](x: var T, y: int) =
proc ensureSeq[T](x: var seq[T]) = proc ensureSeq[T](x: var seq[T]) =
if x == nil: newSeq(x, 0) if x == nil: newSeq(x, 0)
proc suggestSym*(info: TLineInfo; s: PSym; isDecl=true) {.inline.} = proc suggestSym*(info: TLineInfo; s: PSym; usageSym: var PSym; isDecl=true) {.inline.} =
## misnamed: should be 'symDeclared' ## misnamed: should be 'symDeclared'
when defined(nimsuggest): when defined(nimsuggest):
if suggestVersion == 2: if suggestVersion == 2:
@ -395,20 +395,20 @@ proc suggestSym*(info: TLineInfo; s: PSym; isDecl=true) {.inline.} =
s.addNoDup(info) s.addNoDup(info)
if gIdeCmd == ideUse: if gIdeCmd == ideUse:
findUsages(info, s) findUsages(info, s, usageSym)
elif gIdeCmd == ideDef: elif gIdeCmd == ideDef:
findDefinition(info, s) findDefinition(info, s)
elif gIdeCmd == ideDus and s != nil: elif gIdeCmd == ideDus and s != nil:
if isTracked(info, s.name.s.len): if isTracked(info, s.name.s.len):
suggestResult(symToSuggest(s, isLocal=false, $ideDef, 100)) suggestResult(symToSuggest(s, isLocal=false, $ideDef, 100))
findUsages(info, s) findUsages(info, s, usageSym)
elif gIdeCmd == ideHighlight and info.fileIndex == gTrackPos.fileIndex: elif gIdeCmd == ideHighlight and info.fileIndex == gTrackPos.fileIndex:
suggestResult(symToSuggest(s, isLocal=false, $ideHighlight, info, 100)) suggestResult(symToSuggest(s, isLocal=false, $ideHighlight, info, 100))
elif gIdeCmd == ideOutline and info.fileIndex == gTrackPos.fileIndex and elif gIdeCmd == ideOutline and info.fileIndex == gTrackPos.fileIndex and
isDecl: isDecl:
suggestResult(symToSuggest(s, isLocal=false, $ideOutline, info, 100)) suggestResult(symToSuggest(s, isLocal=false, $ideOutline, info, 100))
proc markUsed(info: TLineInfo; s: PSym) = proc markUsed(info: TLineInfo; s: PSym; usageSym: var PSym) =
incl(s.flags, sfUsed) incl(s.flags, sfUsed)
if s.kind == skEnumField and s.owner != nil: if s.kind == skEnumField and s.owner != nil:
incl(s.owner.flags, sfUsed) incl(s.owner.flags, sfUsed)
@ -416,11 +416,11 @@ proc markUsed(info: TLineInfo; s: PSym) =
if sfDeprecated in s.flags: message(info, warnDeprecated, s.name.s) if sfDeprecated in s.flags: message(info, warnDeprecated, s.name.s)
if sfError in s.flags: localError(info, errWrongSymbolX, s.name.s) if sfError in s.flags: localError(info, errWrongSymbolX, s.name.s)
when defined(nimsuggest): when defined(nimsuggest):
suggestSym(info, s, false) suggestSym(info, s, usageSym, false)
proc useSym*(sym: PSym): PNode = proc useSym*(sym: PSym; usageSym: var PSym): PNode =
result = newSymNode(sym) result = newSymNode(sym)
markUsed(result.info, sym) markUsed(result.info, sym, usageSym)
proc safeSemExpr*(c: PContext, n: PNode): PNode = proc safeSemExpr*(c: PContext, n: PNode): PNode =
# use only for idetools support! # use only for idetools support!

View file

@ -694,9 +694,10 @@ proc transformCall(c: PTransf, n: PNode): PTransNode =
# bugfix: check after 'transformSons' if it's still a method call: # bugfix: check after 'transformSons' if it's still a method call:
# use the dispatcher for the call: # use the dispatcher for the call:
if s.sons[0].kind == nkSym and s.sons[0].sym.kind == skMethod: if s.sons[0].kind == nkSym and s.sons[0].sym.kind == skMethod:
let t = lastSon(s.sons[0].sym.ast) when false:
if t.kind != nkSym or sfDispatcher notin t.sym.flags: let t = lastSon(s.sons[0].sym.ast)
methodDef(s.sons[0].sym, false) if t.kind != nkSym or sfDispatcher notin t.sym.flags:
methodDef(s.sons[0].sym, false)
result = methodCall(s).PTransNode result = methodCall(s).PTransNode
else: else:
result = s.PTransNode result = s.PTransNode

View file

@ -1556,7 +1556,10 @@ proc myProcess(c: PPassContext, n: PNode): PNode =
result = n result = n
oldErrorCount = msgs.gErrorCounter oldErrorCount = msgs.gErrorCounter
const evalPass* = makePass(myOpen, nil, myProcess, myProcess) proc myClose(graph: ModuleGraph; c: PPassContext, n: PNode): PNode =
myProcess(c, n)
const evalPass* = makePass(myOpen, nil, myProcess, myClose)
proc evalConstExprAux(module: PSym; cache: IdentCache; prc: PSym, n: PNode, proc evalConstExprAux(module: PSym; cache: IdentCache; prc: PSym, n: PNode,
mode: TEvalMode): PNode = mode: TEvalMode): PNode =

View file

@ -29,10 +29,10 @@ method runInput[T, O](self: Parser[T, O], inp: Input[T]): Result[T, O] =
# XXX: above needed for now, as without the `tmp` bit below, it compiles to invalid C. # XXX: above needed for now, as without the `tmp` bit below, it compiles to invalid C.
tmp(self)(inp) tmp(self)(inp)
method run*[T, O](self: Parser[T, O], toks: seq[T]): Result[T, O] = proc run*[T, O](self: Parser[T, O], toks: seq[T]): Result[T, O] =
self.runInput(Input[T](toks: toks, index: 0)) self.runInput(Input[T](toks: toks, index: 0))
method chain*[T, O1, O2](self: Parser[T, O1], nextp: proc (v: O1): Parser[T, O2]): Parser[T, O2] = proc chain*[T, O1, O2](self: Parser[T, O1], nextp: proc (v: O1): Parser[T, O2]): Parser[T, O2] =
result = proc (inp: Input[T]): Result[T, O2] = result = proc (inp: Input[T]): Result[T, O2] =
let r = self.runInput(inp) let r = self.runInput(inp)
case r.kind: case r.kind:
@ -41,7 +41,7 @@ method chain*[T, O1, O2](self: Parser[T, O1], nextp: proc (v: O1): Parser[T, O2]
of rkFailure: of rkFailure:
Result[T, O2](kind: rkFailure) Result[T, O2](kind: rkFailure)
method skip[T](self: Input[T], n: int): Input[T] = method skip[T](self: Input[T], n: int): Input[T] {.base.} =
Input[T](toks: self.toks, index: self.index + n) Input[T](toks: self.toks, index: self.index + n)
proc pskip*[T](n: int): Parser[T, tuple[]] = proc pskip*[T](n: int): Parser[T, tuple[]] =
@ -69,11 +69,11 @@ proc `+`*[T, O](first: Parser[T, O], second: Parser[T, O]): Parser[T, O] =
# end of primitives (definitions involving Parser(..)) # end of primitives (definitions involving Parser(..))
method map*[T, O1, O2](self: Parser[T, O1], p: proc (v: O1): O2): Parser[T, O2] = proc map*[T, O1, O2](self: Parser[T, O1], p: proc (v: O1): O2): Parser[T, O2] =
self.chain(proc (v: O1): Parser[T, O2] = self.chain(proc (v: O1): Parser[T, O2] =
unit[T, O2](p(v))) unit[T, O2](p(v)))
method then*[T, O1, O2](self: Parser[T, O1], next: Parser[T, O2]): Parser[T, O2] = proc then*[T, O1, O2](self: Parser[T, O1], next: Parser[T, O2]): Parser[T, O2] =
self.chain(proc (v: O1): Parser[T, O2] = self.chain(proc (v: O1): Parser[T, O2] =
next) next)