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
parent 311253ef2f
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}
addFileToCompile(cf)
proc myClose(b: PPassContext, n: PNode): PNode =
proc myClose(graph: ModuleGraph; b: PPassContext, n: PNode): PNode =
result = n
if b == nil or passes.skipCodegen(n): return
var m = BModule(b)
@@ -1378,7 +1378,7 @@ proc myClose(b: PPassContext, n: PNode): PNode =
if sfMainModule in m.module.flags:
incl m.flags, objHasKidsValid
var disp = generateMethodDispatchers()
var disp = generateMethodDispatchers(graph)
for i in 0..sonsLen(disp)-1: genProcAux(m, disp.sons[i].sym)
genMainProc(m)

View File

@@ -11,7 +11,7 @@
import
intsets, options, ast, astalgo, msgs, idents, renderer, types, magicsys,
sempass2, strutils
sempass2, strutils, modulegraphs
proc genConv(n: PNode, d: PType, downcast: bool): PNode =
var dest = skipTypes(d, abstractPtrs)
@@ -38,16 +38,18 @@ proc genConv(n: PNode, d: PType, downcast: bool): PNode =
proc methodCall*(n: PNode): PNode =
result = n
# replace ordinary method by dispatcher method:
var disp = lastSon(result.sons[0].sym.ast).sym
assert sfDispatcher in disp.flags
result.sons[0].sym = disp
# change the arguments to up/downcasts to fit the dispatcher's parameters:
for i in countup(1, sonsLen(result)-1):
result.sons[i] = genConv(result.sons[i], disp.typ.sons[i], true)
# save for incremental compilation:
var
gMethods: seq[tuple[methods: TSymSeq, dispatcher: PSym]] = @[]
let dispn = lastSon(result.sons[0].sym.ast)
if dispn.kind == nkSym:
let disp = dispn.sym
if sfDispatcher notin disp.flags:
localError(n.info, "'" & $result & "' lacks a dispatcher")
return
result.sons[0].sym = disp
# change the arguments to up/downcasts to fit the dispatcher's parameters:
for i in countup(1, sonsLen(result)-1):
result.sons[i] = genConv(result.sons[i], disp.typ.sons[i], true)
else:
localError(n.info, "'" & $result.sons[0] & "' lacks a dispatcher")
type
MethodResult = enum No, Invalid, Yes
@@ -144,27 +146,27 @@ proc fixupDispatcher(meth, disp: PSym) =
if disp.typ.lockLevel < meth.typ.lockLevel:
disp.typ.lockLevel = meth.typ.lockLevel
proc methodDef*(s: PSym, fromCache: bool) =
let L = len(gMethods)
proc methodDef*(g: ModuleGraph; s: PSym, fromCache: bool) =
let L = len(g.methods)
var witness: PSym
for i in countup(0, L - 1):
let disp = gMethods[i].dispatcher
let disp = g.methods[i].dispatcher
case sameMethodBucket(disp, s)
of Yes:
add(gMethods[i].methods, s)
add(g.methods[i].methods, s)
attachDispatcher(s, lastSon(disp.ast))
fixupDispatcher(s, disp)
#echo "fixup ", disp.name.s, " ", disp.id
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?
localError(s.info, "method is not a base")
return
of No: discard
of Invalid:
if witness.isNil: witness = gMethods[i].methods[0]
if witness.isNil: witness = g.methods[i].methods[0]
# create a new dispatcher:
add(gMethods, (methods: @[s], dispatcher: createDispatcher(s)))
add(g.methods, (methods: @[s], dispatcher: createDispatcher(s)))
#echo "adding ", s.info
#if fromCache:
# internalError(s.info, "no method dispatcher found")
@@ -258,12 +260,12 @@ proc genDispatcher(methods: TSymSeq, relevantCols: IntSet): PSym =
disp = ret
result.ast.sons[bodyPos] = disp
proc generateMethodDispatchers*(): PNode =
proc generateMethodDispatchers*(g: ModuleGraph): PNode =
result = newNode(nkStmtList)
for bucket in countup(0, len(gMethods) - 1):
for bucket in countup(0, len(g.methods) - 1):
var relevantCols = initIntSet()
for col in countup(1, sonsLen(gMethods[bucket].methods[0].typ) - 1):
if relevantCol(gMethods[bucket].methods, col): incl(relevantCols, col)
sortBucket(gMethods[bucket].methods, relevantCols)
for col in countup(1, sonsLen(g.methods[bucket].methods[0].typ) - 1):
if relevantCol(g.methods[bucket].methods, col): incl(relevantCols, col)
sortBucket(g.methods[bucket].methods, relevantCols)
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:
discard
proc close(p: PPassContext, n: PNode): PNode =
proc close(graph: ModuleGraph; p: PPassContext, n: PNode): PNode =
closeImpl:
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:
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)
globals.unique = p.unique
proc wholeCode*(m: BModule): Rope =
proc wholeCode(graph: ModuleGraph; m: BModule): Rope =
for prc in globals.forwarded:
if not globals.generatedSyms.containsOrIncl(prc.id):
var p = newProc(globals, m, nil, m.module.options)
attachProc(p, prc)
var disp = generateMethodDispatchers()
var disp = generateMethodDispatchers(graph)
for i in 0..sonsLen(disp)-1:
let prc = disp.sons[i].sym
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)
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
result = myProcess(b, n)
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 f = if globals.classes.len == 0: m.module.filename
else: "nimsystem"
let code = wholeCode(m)
let code = wholeCode(graph, m)
let outfile =
if options.outFile.len > 0:
if options.outFile.isAbsolute: options.outFile

View File

@@ -115,7 +115,7 @@ proc errorSym*(c: PContext, n: PNode): PSym =
considerQuotedIdent(m)
else:
getIdent("err:" & renderTree(m))
result = newSym(skError, ident, getCurrOwner(), n.info)
result = newSym(skError, ident, getCurrOwner(c), n.info)
result.typ = errorType(c)
incl(result.flags, sfDiscardable)
# 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
config*: ConfigRef
doStopCompile*: proc(): bool {.closure.}
usageSym*: PSym # for nimsuggest
owners*: seq[PSym]
methods*: seq[tuple[methods: TSymSeq, dispatcher: PSym]]
{.this: g.}
@@ -58,6 +61,8 @@ proc newModuleGraph*(config: ConfigRef = nil): ModuleGraph =
result.config = newConfigRef()
else:
result.config = config
result.owners = @[]
result.methods = @[]
proc resetAllModules*(g: ModuleGraph) =
initStrTable(packageSyms)
@@ -65,6 +70,9 @@ proc resetAllModules*(g: ModuleGraph) =
modules = @[]
importStack = @[]
inclToMod = initTable[int32, int32]()
usageSym = nil
owners = @[]
methods = @[]
proc getModule*(g: ModuleGraph; fileIdx: int32): PSym =
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:
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 =
var
canon: string

View File

@@ -29,21 +29,3 @@ proc verboseProcess(context: PPassContext, n: PNode): PNode =
message(n.info, hintProcessing, $idgen.gFrontendId)
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.}
TPassOpenCached* =
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.}
TPass* = tuple[open: TPassOpen, openCached: TPassOpenCached,
@@ -94,7 +94,7 @@ proc carryPass*(g: ModuleGraph; p: TPass, module: PSym; cache: IdentCache;
m: TPassData): TPassData =
var c = p.open(g, module, cache)
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
proc carryPasses*(g: ModuleGraph; nodes: PNode, module: PSym;
@@ -121,10 +121,10 @@ proc openPassesCached(g: ModuleGraph; a: var TPassContextArray, module: PSym,
else:
a[i] = nil
proc closePasses(a: var TPassContextArray) =
proc closePasses(graph: ModuleGraph; a: var TPassContextArray) =
var m: PNode = nil
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
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):
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
for i in countup(0, gPassesLen - 1):
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
proc resolveMod(module, relativeTo: string): int32 =
@@ -215,7 +215,7 @@ proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream,
elif not processTopLevelStmt(n, a): break
closeParsers(p)
if s.kind != llsStdIn: break
closePasses(a)
closePasses(graph, a)
# id synchronization point for more consistent code generation:
idSynchronizationPoint(1000)
else:
@@ -224,5 +224,5 @@ proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream,
for i in countup(0, sonsLen(n) - 1):
if graph.stopCompile(): break
processTopLevelStmtCached(n.sons[i], a)
closePassesCached(a)
closePassesCached(graph, a)
result = true

View File

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

View File

@@ -28,7 +28,7 @@ proc semLocals(c: PContext, n: PNode): PNode =
it.typ.skipTypes({tyGenericInst, tyVar}).kind notin
{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.position = counter
inc(counter)

View File

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

View File

@@ -166,7 +166,7 @@ proc commonType*(x, y: PType): PType =
result.addSonSkipIntLit(r)
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 `$`(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
# will assign a wrong owner during the first pass over the
# template; we must fix it here: see #909
result.owner = getCurrOwner()
result.owner = getCurrOwner(c)
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:
# incl(result.flags, sfGlobal)
@@ -376,7 +376,7 @@ proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
flags: TExprFlags = {}): PNode =
pushInfoContext(nOrig.info)
markUsed(n.info, sym)
markUsed(n.info, sym, c.graph.usageSym)
styleCheckUse(n.info, sym)
if sym == c.p.owner:
globalError(n.info, errRecursiveDependencyX, sym.name.s)
@@ -434,7 +434,7 @@ proc myOpen(graph: ModuleGraph; module: PSym; cache: IdentCache): PPassContext =
c.instTypeBoundOp = sigmatch.instTypeBoundOp
pushProcCon(c, module)
pushOwner(c.module)
pushOwner(c, c.module)
c.importTable = openScope(c)
c.importTable.addSym(module) # a module knows itself
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 =
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 =
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
# requires far less code.
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
proc myProcess(context: PPassContext, n: PNode): PNode =
@@ -523,7 +523,7 @@ proc myProcess(context: PPassContext, n: PNode): PNode =
else: result = ast.emptyNode
#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)
closeScope(c) # close module's scope
rawCloseScope(c) # imported symbols; don't check for unused ones!
@@ -533,7 +533,7 @@ proc myClose(context: PPassContext, n: PNode): PNode =
addCodeForGenerics(c, result)
if c.module.ast != nil:
result.add(c.module.ast)
popOwner()
popOwner(c)
popProcCon(c)
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:
let op = t.destructor
if op != nil:
markUsed(c.info, op)
markUsed(c.info, op, c.c.graph.usageSym)
styleCheckUse(c.info, op)
body.add newDestructorCall(op, x)
result = true
@@ -123,14 +123,14 @@ proc considerOverloadedOp(c: var TLiftCtx; t: PType; body, x, y: PNode): bool =
op = t.assignment
if op == nil:
op = liftBody(c.c, t, c.info)
markUsed(c.info, op)
markUsed(c.info, op, c.c.graph.usageSym)
styleCheckUse(c.info, op)
body.add newAsgnCall(c.c, op, x, y)
result = true
of attachedDeepCopy:
let op = t.deepCopy
if op != nil:
markUsed(c.info, op)
markUsed(c.info, op, c.c.graph.usageSym)
styleCheckUse(c.info, op)
body.add newDeepCopyCall(op, x, y)
result = true

View File

@@ -335,7 +335,7 @@ proc inferWithMetatype(c: PContext, formal: PType,
proc semResolvedCall(c: PContext, n: PNode, x: TCandidate): PNode =
assert x.state == csMatch
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)
assert finalCallee.ast != nil
if x.hasFauxMatch:
@@ -411,7 +411,7 @@ proc explicitGenericSym(c: PContext, n: PNode, s: PSym): PNode =
let tm = typeRel(m, formal, arg, true)
if tm in {isNone, isConvertible}: return nil
var newInst = generateInstance(c, s, m.bindings, n.info)
markUsed(n.info, s)
markUsed(n.info, s, c.graph.usageSym)
styleCheckUse(n.info, s)
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
else: 0
var gOwners*: seq[PSym] = @[]
proc getCurrOwner*(): PSym =
proc getCurrOwner*(c: PContext): PSym =
# owner stack (used for initializing the
# owner field of syms)
# the documentation comment always gets
# assigned to the current owner
# BUGFIX: global array is needed!
result = gOwners[high(gOwners)]
result = c.graph.owners[^1]
proc pushOwner*(owner: PSym) =
add(gOwners, owner)
proc pushOwner*(c: PContext; owner: PSym) =
add(c.graph.owners, owner)
proc popOwner*() =
var length = len(gOwners)
if length > 0: setLen(gOwners, length - 1)
proc popOwner*(c: PContext) =
var length = len(c.graph.owners)
if length > 0: setLen(c.graph.owners, length - 1)
else: internalError("popOwner")
proc lastOptionEntry*(c: PContext): POptionEntry =
@@ -226,7 +224,7 @@ proc addToLib*(lib: PLib, sym: PSym) =
sym.annex = lib
proc newTypeS*(kind: TTypeKind, c: PContext): PType =
result = newType(kind, getCurrOwner())
result = newType(kind, getCurrOwner(c))
proc makePtrType*(c: PContext, baseType: PType): PType =
result = newTypeS(tyPtr, c)
@@ -245,7 +243,7 @@ proc makeTypeDesc*(c: PContext, typ: PType): PType =
proc makeTypeSymNode*(c: PContext, typ: PType, info: TLineInfo): PNode =
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)
proc makeTypeFromExpr*(c: PContext, n: PNode): PType =
@@ -255,7 +253,7 @@ proc makeTypeFromExpr*(c: PContext, n: PNode): PType =
proc newTypeWithSons*(c: PContext, kind: TTypeKind,
sons: seq[PType]): PType =
result = newType(kind, getCurrOwner())
result = newType(kind, getCurrOwner(c))
result.sons = sons
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) =
dest.kind = kind
dest.owner = getCurrOwner()
dest.owner = getCurrOwner(c)
dest.size = - 1
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])
if destructableT != nil:
n.sons[bodyPos].addSon(newNode(nkCall, t.sym.info, @[
useSym(destructableT.destructor),
useSym(destructableT.destructor, c.graph.usageSym),
n.sons[paramsPos][1][0]]))
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)
if destructableT != nil:
result = newNode(nkCall, field.info, @[
useSym(destructableT.destructor),
newNode(nkDotExpr, field.info, @[holder, useSym(field)])])
useSym(destructableT.destructor, c.graph.usageSym),
newNode(nkDotExpr, field.info, @[holder, useSym(field, c.graph.usageSym)])])
proc destroyCase(c: PContext, n: PNode, holder: PNode): PNode =
var nonTrivialFields = 0
@@ -181,7 +181,8 @@ proc createDestructorCall(c: PContext, s: PSym): PNode =
let destructableT = instantiateDestructor(c, varTyp)
if destructableT != nil:
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])
proc insertDestructors(c: PContext,
@@ -233,8 +234,8 @@ proc insertDestructors(c: PContext,
tryStmt.addSon(
newNode(nkFinally, info, @[
semStmt(c, newNode(nkCall, info, @[
useSym(destructableT.destructor),
useSym(varId.sym)]))]))
useSym(destructableT.destructor, c.graph.usageSym),
useSym(varId.sym, c.graph.usageSym)]))]))
result.outer = newNodeI(nkStmtList, info)
varSection.sons.setLen(j+1)

View File

@@ -12,10 +12,10 @@
proc semTemplateExpr(c: PContext, n: PNode, s: PSym,
flags: TExprFlags = {}): PNode =
markUsed(n.info, s)
markUsed(n.info, s, c.graph.usageSym)
styleCheckUse(n.info, s)
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)
popInfoContext()
@@ -209,7 +209,7 @@ proc semConv(c: PContext, n: PNode): PNode =
let it = op.sons[i]
let status = checkConvertible(c, result.typ, it.typ)
if status in {convOK, convNotNeedeed}:
markUsed(n.info, it.sym)
markUsed(n.info, it.sym, c.graph.usageSym)
styleCheckUse(n.info, it.sym)
markIndirect(c, it.sym)
return it
@@ -926,7 +926,7 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
let s = getGenSym(c, sym)
case s.kind
of skConst:
markUsed(n.info, s)
markUsed(n.info, s, c.graph.usageSym)
styleCheckUse(n.info, s)
case skipTypes(s.typ, abstractInst-{tyTypeDesc}).kind
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)
of skMacro:
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)
result = newSymNode(s, n.info)
else:
result = semMacroExpr(c, n, n, s, flags)
of skTemplate:
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)
result = newSymNode(s, n.info)
else:
result = semTemplateExpr(c, n, s, flags)
of skParam:
markUsed(n.info, s)
markUsed(n.info, s, c.graph.usageSym)
styleCheckUse(n.info, s)
if s.typ.kind == tyStatic and s.typ.n != nil:
# 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:
localError(n.info, "illegal context for 'nimvm' magic")
markUsed(n.info, s)
markUsed(n.info, s, c.graph.usageSym)
styleCheckUse(n.info, s)
result = newSymNode(s, n.info)
# 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
return n
of skType:
markUsed(n.info, s)
markUsed(n.info, s, c.graph.usageSym)
styleCheckUse(n.info, s)
if s.typ.kind == tyStatic and s.typ.n != nil:
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):
# is the access to a public field or in the same module or in a friend?
doAssert f == s
markUsed(n.info, f)
markUsed(n.info, f, c.graph.usageSym)
styleCheckUse(n.info, f)
result = newNodeIT(nkDotExpr, n.info, f.typ)
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
ty = skipTypes(ty.sons[0], skipPtrs)
# old code, not sure if it's live code:
markUsed(n.info, s)
markUsed(n.info, s, c.graph.usageSym)
styleCheckUse(n.info, s)
result = newSymNode(s, n.info)
else:
markUsed(n.info, s)
markUsed(n.info, s, c.graph.usageSym)
styleCheckUse(n.info, s)
result = newSymNode(s, n.info)
@@ -1062,7 +1062,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
result = symChoice(c, n, s, scClosed)
if result.kind == nkSym: result = semSym(c, n, s, flags)
else:
markUsed(n.sons[1].info, s)
markUsed(n.sons[1].info, s, c.graph.usageSym)
result = semSym(c, n, s, flags)
styleCheckUse(n.sons[1].info, s)
return
@@ -1087,7 +1087,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
result = newSymNode(f)
result.info = n.info
result.typ = ty
markUsed(n.info, f)
markUsed(n.info, f, c.graph.usageSym)
styleCheckUse(n.info, f)
return
of tyTypeParamsHolders:
@@ -1120,7 +1120,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
if f != nil:
if fieldVisible(c, f):
# 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)
n.sons[0] = makeDeref(n.sons[0])
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:
f = getSymFromList(ty.n, i)
if f != nil:
markUsed(n.sons[1].info, f)
markUsed(n.sons[1].info, f, c.graph.usageSym)
styleCheckUse(n.sons[1].info, f)
n.sons[0] = makeDeref(n.sons[0])
n.sons[1] = newSymNode(f)
@@ -1581,9 +1581,8 @@ proc getMagicSym(magic: TMagic): PSym =
result = newSym(skProc, getIdent($magic), systemModule, gCodegenLineInfo)
result.magic = magic
proc newAnonSym(c: PContext; kind: TSymKind, info: TLineInfo,
owner = getCurrOwner()): PSym =
result = newSym(kind, c.cache.idAnon, owner, info)
proc newAnonSym(c: PContext; kind: TSymKind, info: TLineInfo): PSym =
result = newSym(kind, c.cache.idAnon, getCurrOwner(c), info)
result.flags = {sfGenSym}
proc semExpandToAst(c: PContext, n: PNode): PNode =
@@ -1592,7 +1591,7 @@ proc semExpandToAst(c: PContext, n: PNode): PNode =
if expandedSym.kind == skError: return n
macroCall.sons[0] = newSymNode(expandedSym, macroCall.info)
markUsed(n.info, expandedSym)
markUsed(n.info, expandedSym, c.graph.usageSym)
styleCheckUse(n.info, expandedSym)
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:
let oldScope = c.currentScope
openScope(c)
let oldOwnerLen = len(gOwners)
let oldOwnerLen = len(c.graph.owners)
let oldGenerics = c.generics
let oldErrorOutputs = errorOutputs
errorOutputs = {}
@@ -1709,7 +1708,7 @@ proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
c.inGenericInst = oldInGenericInst
c.p = oldProcCon
msgs.setInfoContextLen(oldContextLen)
setLen(gOwners, oldOwnerLen)
setLen(c.graph.owners, oldOwnerLen)
c.currentScope = oldScope
errorOutputs = oldErrorOutputs
msgs.gErrorCounter = oldErrorCount
@@ -2108,7 +2107,7 @@ proc semBlock(c: PContext, n: PNode): PNode =
if sfGenSym notin labl.flags:
addDecl(c, labl)
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)
n.sons[1] = semExpr(c, n.sons[1])
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")
if trueSymbol == nil:
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)
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:
continue
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}
var t = PType(idTableGet(pt, q.typ))
if t == nil:
@@ -255,7 +255,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
incl(result.flags, sfFromGeneric)
result.owner = fn
result.ast = n
pushOwner(result)
pushOwner(c, result)
openScope(c)
let gp = n.sons[genericParamsPos]
@@ -304,7 +304,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
popProcCon(c)
popInfoContext()
closeScope(c) # close scope for parameters
popOwner()
popOwner(c)
c.currentScope = oldScope
discard c.friendModules.pop()
dec(c.instCounter)

View File

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

View File

@@ -35,7 +35,7 @@ proc semBreakOrContinue(c: PContext, n: PNode): PNode =
x.info = n.info
incl(s.flags, sfUsed)
n.sons[0] = x
suggestSym(x.info, s)
suggestSym(x.info, s, c.graph.usageSym)
styleCheckUse(x.info, s)
else:
localError(n.info, errInvalidControlFlowX, s.name.s)
@@ -366,11 +366,13 @@ proc semIdentDef(c: PContext, n: PNode, kind: TSymKind): PSym =
if isTopLevel(c):
result = semIdentWithPragma(c, kind, n, {sfExported})
incl(result.flags, sfGlobal)
#if kind in {skVar, skLet}:
# echo "global variable here ", n.info, " ", result.name.s
else:
result = semIdentWithPragma(c, kind, n, {})
if result.owner.kind == skModule:
incl(result.flags, sfGlobal)
suggestSym(n.info, result)
suggestSym(n.info, result, c.graph.usageSym)
styleCheckDef(result)
proc checkNilable(v: PSym) =
@@ -621,7 +623,7 @@ proc semForVars(c: PContext, n: PNode): PNode =
if iter.kind != tyTuple or length == 3:
if length == 3:
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
# the ``tyGenericInst``! See ``tests/compile/tgeneric.nim``
# for an example:
@@ -635,7 +637,7 @@ proc semForVars(c: PContext, n: PNode): PNode =
else:
for i in countup(0, length - 3):
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]
n.sons[i] = newSymNode(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,
# symbol lookup needs to be done here.
openScope(c)
pushOwner(s)
pushOwner(c, s)
if s.magic == mNone: s.typ.kind = tyGenericBody
# XXX for generic type aliases this is not correct! We need the
# underlying Id really:
@@ -769,11 +771,11 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
body.sym = s
body.size = -1 # could not be computed properly
s.typ.sons[sonsLen(s.typ) - 1] = body
popOwner()
popOwner(c)
closeScope(c)
elif a.sons[2].kind != nkEmpty:
# process the type's body:
pushOwner(s)
pushOwner(c, s)
var t = semTypeNode(c, a.sons[2], s.typ)
if s.typ == nil:
s.typ = t
@@ -782,7 +784,7 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
assignType(s.typ, t)
#debug s.typ
s.ast = a
popOwner()
popOwner(c)
let aa = a.sons[2]
if aa.kind in {nkRefTy, nkPtrTy} and aa.len == 1 and
aa.sons[0].kind == nkObjectTy:
@@ -793,7 +795,7 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
internalAssert st.lastSon.sym == nil
incl st.flags, tfRefsAnonObj
let obj = newSym(skType, getIdent(s.name.s & ":ObjectType"),
getCurrOwner(), s.info)
getCurrOwner(c), s.info)
obj.typ = st.lastSon
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) =
if t != nil:
var s = newSym(skResult, getIdent"result", getCurrOwner(), info)
var s = newSym(skResult, getIdent"result", getCurrOwner(c), info)
s.typ = t
incl(s.flags, sfUsed)
addParamOrResult(c, s, owner)
@@ -1002,12 +1004,12 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode =
checkSonsLen(n, bodyPos + 1)
var s: PSym
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
n.sons[namePos] = newSymNode(s)
else:
s = n[namePos].sym
pushOwner(s)
pushOwner(c, s)
openScope(c)
var gp: PNode
if n.sons[genericParamsPos].kind != nkEmpty:
@@ -1047,7 +1049,7 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode =
else:
localError(n.info, errImplOfXexpected, s.name.s)
closeScope(c) # close scope for parameters
popOwner()
popOwner(c)
result.typ = s.typ
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.owner = s
openScope(c)
pushOwner(s)
pushOwner(c, s)
addParams(c, params, skProc)
pushProcCon(c, s)
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]))
n.sons[bodyPos] = transformBody(c.module, semBody, s)
popProcCon(c)
popOwner()
popOwner(c)
closeScope(c)
# alternative variant (not quite working):
@@ -1193,6 +1195,42 @@ type
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,
validPragmas: TSpecialWords,
phase = stepRegisterSymbol): PNode =
@@ -1207,7 +1245,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
assert phase == stepRegisterSymbol
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)
isAnon = true
else:
@@ -1224,7 +1262,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
return
else:
s = n[namePos].sym
s.owner = getCurrOwner()
s.owner = getCurrOwner(c)
typeIsDetermined = s.typ == nil
s.ast = n
#s.scope = c.currentScope
@@ -1233,7 +1271,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
# where the proc was declared
let oldScope = c.currentScope
#c.currentScope = s.scope
pushOwner(s)
pushOwner(c, s)
openScope(c)
var gp: PNode
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):
n.comment = proto.ast.comment
proto.ast = n # needed for code generation
popOwner()
pushOwner(s)
popOwner(c)
pushOwner(c, s)
s.options = gOptions
if sfOverriden in s.flags or s.name.s[0] == '=': semOverride(c, s, n)
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
cursorInProc(n.sons[bodyPos]):
discard "speed up nimsuggest"
if s.kind == skMethod: semMethodPrototype(c, s, n)
else:
pushProcCon(c, s)
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
maybeAddResult(c, s, n)
if s.kind == skMethod: semMethodPrototype(c, s, n)
if lfDynamicLib notin s.loc.flags:
# no semantic checking for importc:
let semBody = hloBody(c, semProcBody(c, n.sons[bodyPos]))
@@ -1333,15 +1374,18 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
else:
if s.typ.sons[0] != nil and kind != skIterator:
addDecl(c, newSym(skUnknown, getIdent"result", nil, n.info))
openScope(c)
n.sons[bodyPos] = semGenericStmt(c, n.sons[bodyPos])
closeScope(c)
fixupInstantiatedSymbols(c, s)
if s.kind == skMethod: semMethodPrototype(c, s, n)
if sfImportc in s.flags:
# so we just ignore the body after semantic checking for importc:
n.sons[bodyPos] = ast.emptyNode
popProcCon(c)
else:
if s.kind == skMethod: semMethodPrototype(c, s, n)
if proto != nil: localError(n.info, errImplOfXexpected, proto.name.s)
if {sfImportc, sfBorrow} * s.flags == {} and s.magic == mNone:
incl(s.flags, sfForward)
@@ -1349,7 +1393,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
sideEffectsCheck(c, s)
closeScope(c) # close scope for parameters
# c.currentScope = oldScope
popOwner()
popOwner(c)
if n.sons[patternPos].kind != nkEmpty:
c.patterns.add(s)
if isAnon: result.typ = s.typ
@@ -1368,7 +1412,7 @@ proc semIterator(c: PContext, n: PNode): PNode =
let isAnon = n[namePos].kind == nkEmpty
if n[namePos].kind == nkSym:
# 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
result = semProcAux(c, n, skIterator, iteratorPragmas)
var s = result.sons[namePos].sym
@@ -1395,46 +1439,9 @@ proc semIterator(c: PContext, n: PNode): PNode =
proc semProc(c: PContext, n: PNode): PNode =
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 =
if not isTopLevel(c): localError(n.info, errXOnlyAtModuleScope, "method")
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 =
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):
# for instance 'nextTry' is both in tables.nim and astalgo.nim ...
result = newSymNode(s, n.info)
markUsed(n.info, s)
markUsed(n.info, s, c.graph.usageSym)
else:
# semantic checking requires a type; ``fitNode`` deals with it
# appropriately
@@ -559,7 +559,7 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
styleCheckDef(s)
# check parameter list:
#s.scope = c.currentScope
pushOwner(s)
pushOwner(c, s)
openScope(c)
n.sons[namePos] = newSymNode(s, n.sons[namePos].info)
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
semIdeForTemplateOrGeneric(c, n.sons[bodyPos], ctx.cursorInBody)
closeScope(c)
popOwner()
popOwner(c)
s.ast = n
result = n
if n.sons[bodyPos].kind == nkEmpty:
@@ -758,7 +758,7 @@ proc semPattern(c: PContext, n: PNode): PNode =
ctx.toMixin = initIntSet()
ctx.toInject = initIntSet()
ctx.c = c
ctx.owner = getCurrOwner()
ctx.owner = getCurrOwner(c)
result = flattenStmts(semPatternBody(ctx, n))
if result.kind in {nkStmtList, nkStmtListExpr}:
if result.len == 1:

View File

@@ -306,7 +306,7 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
else:
result = qualifiedLookUp(c, n, {checkAmbiguity, checkUndeclared})
if result != nil:
markUsed(n.info, result)
markUsed(n.info, result, c.graph.usageSym)
styleCheckUse(n.info, result)
if result.kind == skParam and result.typ.kind == tyTypeDesc:
# 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
for i in countup(0, sonsLen(n)-3):
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.position = pos
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
let owner = if typeClass.sym != nil: typeClass.sym
else: getCurrOwner()
else: getCurrOwner(c)
var s = newSym(skType, finalTypId, owner, info)
if typId == nil: s.flags.incl(sfAnon)
s.linkTo(typeClass)
@@ -850,7 +850,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
of tyGenericInst:
if paramType.lastSon.kind == tyUserTypeClass:
var cp = copyType(paramType, getCurrOwner(), false)
var cp = copyType(paramType, getCurrOwner(c), false)
cp.kind = tyUserTypeClassInst
return addImplicitGeneric(cp)
@@ -876,10 +876,10 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
result = liftingWalk(expanded, true)
of tyUserTypeClass, tyBuiltInTypeClass, tyAnd, tyOr, tyNot:
result = addImplicitGeneric(copyType(paramType, getCurrOwner(), true))
result = addImplicitGeneric(copyType(paramType, getCurrOwner(c), true))
of tyGenericParam:
markUsed(info, paramType.sym)
markUsed(info, paramType.sym, c.graph.usageSym)
styleCheckUse(info, paramType.sym)
if tfWildcard in paramType.flags:
paramType.flags.excl tfWildcard
@@ -1267,7 +1267,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
of mExpr:
result = semTypeNode(c, n.sons[0], nil)
if result != nil:
result = copyType(result, getCurrOwner(), false)
result = copyType(result, getCurrOwner(c), false)
for i in countup(1, n.len - 1):
result.rawAddSon(semTypeNode(c, n.sons[i], nil))
of mDistinct:
@@ -1330,7 +1330,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
else:
assignType(prev, t)
result = prev
markUsed(n.info, n.sym)
markUsed(n.info, n.sym, c.graph.usageSym)
styleCheckUse(n.info, n.sym)
else:
if s.kind != skError: localError(n.info, errTypeExpected)

View File

@@ -73,7 +73,7 @@ type
const
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
@@ -1291,7 +1291,7 @@ proc userConvMatch(c: PContext, m: var TCandidate, f, a: PType,
dest = generateTypeInstance(c, m.bindings, arg, dest)
let fdest = typeRel(m, f, dest)
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])
s.typ = c.converters[i].typ
s.info = arg.info
@@ -1551,7 +1551,7 @@ proc paramTypesMatch*(m: var TCandidate, f, a: PType,
else: result = nil
else:
# 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)
result = paramTypesMatchAux(m, f, arg.sons[best].typ, arg.sons[best],
argOrig)

View File

@@ -353,10 +353,10 @@ when defined(nimsuggest):
s.allUsages.add(info)
var
usageSym*: PSym
#usageSym*: PSym
lastLineInfo*: TLineInfo
proc findUsages(info: TLineInfo; s: PSym) =
proc findUsages(info: TLineInfo; s: PSym; usageSym: var PSym) =
if suggestVersion < 2:
if usageSym == nil and isTracked(info, s.name.s.len):
usageSym = s
@@ -385,7 +385,7 @@ proc ensureIdx[T](x: var T, y: int) =
proc ensureSeq[T](x: var seq[T]) =
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'
when defined(nimsuggest):
if suggestVersion == 2:
@@ -395,20 +395,20 @@ proc suggestSym*(info: TLineInfo; s: PSym; isDecl=true) {.inline.} =
s.addNoDup(info)
if gIdeCmd == ideUse:
findUsages(info, s)
findUsages(info, s, usageSym)
elif gIdeCmd == ideDef:
findDefinition(info, s)
elif gIdeCmd == ideDus and s != nil:
if isTracked(info, s.name.s.len):
suggestResult(symToSuggest(s, isLocal=false, $ideDef, 100))
findUsages(info, s)
findUsages(info, s, usageSym)
elif gIdeCmd == ideHighlight and info.fileIndex == gTrackPos.fileIndex:
suggestResult(symToSuggest(s, isLocal=false, $ideHighlight, info, 100))
elif gIdeCmd == ideOutline and info.fileIndex == gTrackPos.fileIndex and
isDecl:
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)
if s.kind == skEnumField and s.owner != nil:
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 sfError in s.flags: localError(info, errWrongSymbolX, s.name.s)
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)
markUsed(result.info, sym)
markUsed(result.info, sym, usageSym)
proc safeSemExpr*(c: PContext, n: PNode): PNode =
# 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:
# use the dispatcher for the call:
if s.sons[0].kind == nkSym and s.sons[0].sym.kind == skMethod:
let t = lastSon(s.sons[0].sym.ast)
if t.kind != nkSym or sfDispatcher notin t.sym.flags:
methodDef(s.sons[0].sym, false)
when false:
let t = lastSon(s.sons[0].sym.ast)
if t.kind != nkSym or sfDispatcher notin t.sym.flags:
methodDef(s.sons[0].sym, false)
result = methodCall(s).PTransNode
else:
result = s.PTransNode

View File

@@ -1556,7 +1556,10 @@ proc myProcess(c: PPassContext, n: PNode): PNode =
result = n
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,
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.
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))
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] =
let r = self.runInput(inp)
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:
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)
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(..))
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] =
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] =
next)