diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2020-10-25 08:50:47 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-10-25 08:50:47 +0100 |
commit | 226595515c25785eaf078834dfb6f0ac337a5278 (patch) | |
tree | a534966892d7712baf77b4d4f340fdbe42c0f3c8 | |
parent | 7252a50fefb844d97ad4630c1db00063380ff3c4 (diff) | |
download | Nim-226595515c25785eaf078834dfb6f0ac337a5278.tar.gz |
explicit ID generation for easier IC (#15559)
* refactoring: idents don't need inheritance * refactoring: adding an IdGenerator (part 1) * refactoring: adding an IdGenerator (part 2) * refactoring: adding an IdGenerator (part 3) * refactoring: adding an IdGenerator (part 4) * refactoring: adding an IdGenerator (part 5) * refactoring: adding an IdGenerator (part 5) * IdGenerator must be a ref type; hello world works again * make bootstrapping work again * progress: add back the 'exactReplica' ideas * added back the missing exactReplica hacks * make tcompilerapi work again * make important packages green * attempt to fix the build for 32 bit machines (probably need a better solution here)
67 files changed, 853 insertions, 903 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index d81ccf33b..a9793fb21 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -10,7 +10,7 @@ # abstract syntax tree + symbol table import - lineinfos, hashes, options, ropes, idents, idgen, int128 + lineinfos, hashes, options, ropes, idents, int128 from strutils import toLowerAscii export int128 @@ -717,6 +717,14 @@ const mInSet, mRepr} type + ItemId* = object + module*: int32 + item*: int32 + + TIdObj* = object of RootObj + itemId*: ItemId + PIdObj* = ref TIdObj + PNode* = ref TNode TNodeSeq* = seq[PNode] PType* = ref TType @@ -926,7 +934,7 @@ type loc*: TLoc typeInst*: PType # for generic instantiations the tyGenericInst that led to this # type. - uniqueId*: int # due to a design mistake, we need to keep the real ID here as it + uniqueId*: ItemId # due to a design mistake, we need to keep the real ID here as it # required by the --incremental:on mode. TPair* = object @@ -1060,6 +1068,35 @@ proc getnimblePkg*(a: PSym): PSym = else: assert false, $result.kind +const + moduleShift = when defined(cpu32): 20 else: 24 + +template id*(a: PIdObj): int = + let x = a + (x.itemId.module.int shl moduleShift) + x.itemId.item.int + +type + IdGenerator* = ref ItemId # unfortunately, we really need the 'shared mutable' aspect here. + +const + PackageModuleId* = -3'i32 + +proc idGeneratorFromModule*(m: PSym): IdGenerator = + assert m.kind == skModule + result = IdGenerator(module: m.itemId.module, item: m.itemId.item) + +proc nextId*(x: IdGenerator): ItemId {.inline.} = + inc x.item + result = x[] + +when false: + proc storeBack*(dest: var IdGenerator; src: IdGenerator) {.inline.} = + assert dest.ItemId.module == src.ItemId.module + if dest.ItemId.item > src.ItemId.item: + echo dest.ItemId.item, " ", src.ItemId.item, " ", src.ItemId.module + assert dest.ItemId.item <= src.ItemId.item + dest = src + proc getnimblePkgId*(a: PSym): int = let b = a.getnimblePkg result = if b == nil: -1 else: b.id @@ -1164,13 +1201,11 @@ proc newTreeIT*(kind: TNodeKind; info: TLineInfo; typ: PType; children: varargs[ template previouslyInferred*(t: PType): PType = if t.sons.len > 1: t.lastSon else: nil -proc newSym*(symKind: TSymKind, name: PIdent, owner: PSym, +proc newSym*(symKind: TSymKind, name: PIdent, id: ItemId, owner: PSym, info: TLineInfo; options: TOptions = {}): PSym = # generates a symbol and initializes the hash field too - result = PSym(name: name, kind: symKind, flags: {}, info: info, id: getID(), + result = PSym(name: name, kind: symKind, flags: {}, info: info, itemId: id, options: options, owner: owner, offset: defaultOffset) - when debugIds: - registerId(result) proc astdef*(s: PSym): PNode = # get only the definition (initializer) portion of the ast @@ -1344,13 +1379,11 @@ proc `$`*(s: PSym): string = else: result = "<nil>" -proc newType*(kind: TTypeKind, owner: PSym): PType = - let id = getID() +proc newType*(kind: TTypeKind, id: ItemId; owner: PSym): PType = result = PType(kind: kind, owner: owner, size: defaultSize, - align: defaultAlignment, id: id, uniqueId: id, - lockLevel: UnspecifiedLockLevel) - when debugIds: - registerId(result) + align: defaultAlignment, itemId: id, + lockLevel: UnspecifiedLockLevel, + uniqueId: id) when false: if result.id == 76426: echo "KNID ", kind @@ -1392,22 +1425,18 @@ proc assignType*(dest, src: PType) = newSons(dest, src.len) for i in 0..<src.len: dest[i] = src[i] -proc copyType*(t: PType, owner: PSym, keepId: bool): PType = - result = newType(t.kind, owner) +proc copyType*(t: PType, id: ItemId, owner: PSym): PType = + result = newType(t.kind, id, owner) assignType(result, t) - if keepId: - result.id = t.id - else: - when debugIds: registerId(result) result.sym = t.sym # backend-info should not be copied -proc exactReplica*(t: PType): PType = copyType(t, t.owner, true) +proc exactReplica*(t: PType): PType = + result = copyType(t, t.itemId, t.owner) -proc copySym*(s: PSym): PSym = - result = newSym(s.kind, s.name, s.owner, s.info, s.options) +proc copySym*(s: PSym; id: ItemId): PSym = + result = newSym(s.kind, s.name, id, s.owner, s.info, s.options) #result.ast = nil # BUGFIX; was: s.ast which made problems result.typ = s.typ - when debugIds: registerId(result) result.flags = s.flags result.magic = s.magic if s.kind == skModule: @@ -1421,12 +1450,12 @@ proc copySym*(s: PSym): PSym = result.bitsize = s.bitsize result.alignment = s.alignment -proc createModuleAlias*(s: PSym, newIdent: PIdent, info: TLineInfo; +proc createModuleAlias*(s: PSym, id: ItemId, newIdent: PIdent, info: TLineInfo; options: TOptions): PSym = - result = newSym(s.kind, newIdent, s.owner, info, options) + result = newSym(s.kind, newIdent, id, s.owner, info, options) # keep ID! result.ast = s.ast - result.id = s.id + #result.id = s.id # XXX figure out what to do with the ID. result.flags = s.flags system.shallowCopy(result.tab, s.tab) result.options = s.options @@ -1576,7 +1605,7 @@ proc transitionNoneToSym*(n: PNode) = template transitionSymKindCommon*(k: TSymKind) = let obj {.inject.} = s[] - s[] = TSym(kind: k, id: obj.id, magic: obj.magic, typ: obj.typ, name: obj.name, + s[] = TSym(kind: k, itemId: obj.itemId, magic: obj.magic, typ: obj.typ, name: obj.name, info: obj.info, owner: obj.owner, flags: obj.flags, ast: obj.ast, options: obj.options, position: obj.position, offset: obj.offset, loc: obj.loc, annex: obj.annex, constraint: obj.constraint) @@ -1797,19 +1826,19 @@ proc skipStmtList*(n: PNode): PNode = else: result = n -proc toVar*(typ: PType; kind: TTypeKind): PType = +proc toVar*(typ: PType; kind: TTypeKind; idgen: IdGenerator): PType = ## If ``typ`` is not a tyVar then it is converted into a `var <typ>` and ## returned. Otherwise ``typ`` is simply returned as-is. result = typ if typ.kind != kind: - result = newType(kind, typ.owner) + result = newType(kind, nextId(idgen), typ.owner) rawAddSon(result, typ) -proc toRef*(typ: PType): PType = +proc toRef*(typ: PType; idgen: IdGenerator): PType = ## If ``typ`` is a tyObject then it is converted into a `ref <typ>` and ## returned. Otherwise ``typ`` is simply returned as-is. if typ.skipTypes({tyAlias, tyGenericInst}).kind == tyObject: - result = newType(tyRef, typ.owner) + result = newType(tyRef, nextId(idgen), typ.owner) rawAddSon(result, typ) proc toObject*(typ: PType): PType = @@ -1888,8 +1917,8 @@ proc isSinkParam*(s: PSym): bool {.inline.} = proc isSinkType*(t: PType): bool {.inline.} = t.kind == tySink or tfHasOwned in t.flags -proc newProcType*(info: TLineInfo; owner: PSym): PType = - result = newType(tyProc, owner) +proc newProcType*(info: TLineInfo; id: ItemId; owner: PSym): PType = + result = newType(tyProc, id, owner) result.n = newNodeI(nkFormalParams, info) rawAddSon(result, nil) # return type # result.n[0] used to be `nkType`, but now it's `nkEffectList` because diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 5c897e1a4..b6caec760 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -1765,20 +1765,20 @@ proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) = else: putIntoDest(p, d, e, rope(lengthOrd(p.config, typ))) else: internalError(p.config, e.info, "genArrayLen()") -proc makePtrType(baseType: PType): PType = - result = newType(tyPtr, baseType.owner) - addSonSkipIntLit(result, baseType) +proc makePtrType(baseType: PType; idgen: IdGenerator): PType = + result = newType(tyPtr, nextId idgen, baseType.owner) + addSonSkipIntLit(result, baseType, idgen) -proc makeAddr(n: PNode): PNode = +proc makeAddr(n: PNode; idgen: IdGenerator): PNode = if n.kind == nkHiddenAddr: result = n else: result = newTree(nkHiddenAddr, n) - result.typ = makePtrType(n.typ) + result.typ = makePtrType(n.typ, idgen) proc genSetLengthSeq(p: BProc, e: PNode, d: var TLoc) = if optSeqDestructors in p.config.globalOptions: - e[1] = makeAddr(e[1]) + e[1] = makeAddr(e[1], p.module.idgen) genCall(p, e, d) return var a, b, call: TLoc @@ -2240,7 +2240,7 @@ proc genEnumToStr(p: BProc, e: PNode, d: var TLoc) = toStrProc = p break if toStrProc == nil: - toStrProc = genEnumToStrProc(t, e.info, p.module.g.graph) + toStrProc = genEnumToStrProc(t, e.info, p.module.g.graph, p.module.idgen) t.methods.add((ToStringProcSlot, toStrProc)) var n = copyTree(e) n[0] = newSymNode(toStrProc) @@ -2294,7 +2294,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) = of mAppendStrStr: genStrAppend(p, e, d) of mAppendSeqElem: if optSeqDestructors in p.config.globalOptions: - e[1] = makeAddr(e[1]) + e[1] = makeAddr(e[1], p.module.idgen) genCall(p, e, d) else: genSeqElemAppend(p, e, d) @@ -2393,13 +2393,13 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) = when defined(leanCompiler): quit "compiler built without support for the 'spawn' statement" else: - let n = spawn.wrapProcForSpawn(p.module.g.graph, p.module.module, e, e.typ, nil, nil) + let n = spawn.wrapProcForSpawn(p.module.g.graph, p.module.idgen, p.module.module, e, e.typ, nil, nil) expr(p, n, d) of mParallel: when defined(leanCompiler): quit "compiler built without support for the 'parallel' statement" else: - let n = semparallel.liftParallel(p.module.g.graph, p.module.module, e) + let n = semparallel.liftParallel(p.module.g.graph, p.module.idgen, p.module.module, e) expr(p, n, d) of mDeepCopy: if p.config.selectedGC in {gcArc, gcOrc} and optEnableDeepCopy notin p.config.globalOptions: diff --git a/compiler/ccgmerge.nim b/compiler/ccgmerge.nim index a87d5b609..40833a64e 100644 --- a/compiler/ccgmerge.nim +++ b/compiler/ccgmerge.nim @@ -180,10 +180,6 @@ proc readKey(L: var TBaseLexer, result: var string) = if L.buf[pos] != ':': doAssert(false, "ccgmerge: ':' expected") L.bufpos = pos + 1 # skip ':' -proc newFakeType(id: int): PType = - new(result) - result.id = id - proc readTypeCache(L: var TBaseLexer, result: var TypeCache) = if ^L.bufpos != '{': doAssert(false, "ccgmerge: '{' expected") inc L.bufpos @@ -192,10 +188,7 @@ proc readTypeCache(L: var TBaseLexer, result: var TypeCache) = var key = decodeStr(L.buf, L.bufpos) if ^L.bufpos != ':': doAssert(false, "ccgmerge: ':' expected") inc L.bufpos - var value = decodeStr(L.buf, L.bufpos) - # XXX implement me - when false: - idTablePut(result, newFakeType(key), value.rope) + discard decodeStr(L.buf, L.bufpos) inc L.bufpos proc readIntSet(L: var TBaseLexer, result: var IntSet) = diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index 1282cf11f..aaed37508 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -66,7 +66,7 @@ proc genVarTuple(p: BProc, n: PNode) = # if we have a something that's been captured, use the lowering instead: for i in 0..<n.len-2: if n[i].kind != nkSym: - genStmts(p, lowerTupleUnpacking(p.module.g.graph, n, p.prc)) + genStmts(p, lowerTupleUnpacking(p.module.g.graph, n, p.module.idgen, p.prc)) return # check only the first son @@ -1525,7 +1525,7 @@ proc genCaseObjDiscMapping(p: BProc, e: PNode, t: PType, field: PSym; d: var TLo theProc = p break if theProc == nil: - theProc = genCaseObjDiscMapping(t, field, e.info, p.module.g.graph) + theProc = genCaseObjDiscMapping(t, field, e.info, p.module.g.graph, p.module.idgen) t.methods.add((ObjDiscMappingProcSlot, theProc)) var call = newNodeIT(nkCall, e.info, getSysType(p.module.g.graph, e.info, tyUInt8)) call.add newSymNode(theProc) diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index 6c82a140b..e3f832d68 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -1266,10 +1266,10 @@ proc genArrayInfo(m: BModule, typ: PType, name: Rope; info: TLineInfo) = proc fakeClosureType(m: BModule; owner: PSym): PType = # we generate the same RTTI as for a tuple[pointer, ref tuple[]] - result = newType(tyTuple, owner) - result.rawAddSon(newType(tyPointer, owner)) - var r = newType(tyRef, owner) - let obj = createObj(m.g.graph, owner, owner.info, final=false) + result = newType(tyTuple, nextId m.idgen, owner) + result.rawAddSon(newType(tyPointer, nextId m.idgen, owner)) + var r = newType(tyRef, nextId m.idgen, owner) + let obj = createObj(m.g.graph, m.idgen, owner, owner.info, final=false) r.rawAddSon(obj) result.rawAddSon(r) @@ -1395,9 +1395,9 @@ proc genTypeInfoV2(m: BModule, t: PType; info: TLineInfo): Rope = result = prefixTI.rope & result & ")".rope proc openArrayToTuple(m: BModule; t: PType): PType = - result = newType(tyTuple, t.owner) - let p = newType(tyPtr, t.owner) - let a = newType(tyUncheckedArray, t.owner) + result = newType(tyTuple, nextId m.idgen, t.owner) + let p = newType(tyPtr, nextId m.idgen, t.owner) + let a = newType(tyUncheckedArray, nextId m.idgen, t.owner) a.add t.lastSon p.add a result.add p diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 5c60a3cf3..f0120c435 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -996,9 +996,9 @@ proc genProcAux(m: BModule, prc: PSym) = var returnStmt: Rope = nil assert(prc.ast != nil) - var procBody = transformBody(m.g.graph, prc, cache = false) + var procBody = transformBody(m.g.graph, m.idgen, prc, cache = false) if sfInjectDestructors in prc.flags: - procBody = injectDestructorCalls(m.g.graph, prc, procBody) + procBody = injectDestructorCalls(m.g.graph, m.idgen, prc, procBody) if sfPure notin prc.flags and prc.typ[0] != nil: if resultPos >= prc.ast.len: @@ -1844,9 +1844,10 @@ template injectG() {.dirty.} = when not defined(nimHasSinkInference): {.pragma: nosinks.} -proc myOpen(graph: ModuleGraph; module: PSym): PPassContext {.nosinks.} = +proc myOpen(graph: ModuleGraph; module: PSym; idgen: IdGenerator): PPassContext {.nosinks.} = injectG() result = newModule(g, module, graph.config) + result.idgen = idgen if optGenIndex in graph.config.globalOptions and g.generatedHeader == nil: let f = if graph.config.headerFile.len > 0: AbsoluteFile graph.config.headerFile else: graph.config.projectFull @@ -1920,9 +1921,9 @@ proc myProcess(b: PPassContext, n: PNode): PNode = m.initProc.options = initProcOptions(m) #softRnl = if optLineDir in m.config.options: noRnl else: rnl # XXX replicate this logic! - var transformedN = transformStmt(m.g.graph, m.module, n) + var transformedN = transformStmt(m.g.graph, m.idgen, m.module, n) if sfInjectDestructors in m.module.flags: - transformedN = injectDestructorCalls(m.g.graph, m.module, transformedN) + transformedN = injectDestructorCalls(m.g.graph, m.idgen, m.module, transformedN) if m.hcrOn: addHcrInitGuards(m.initProc, transformedN, m.inHcrInitGuard) diff --git a/compiler/cgmeth.nim b/compiler/cgmeth.nim index 9b871a898..a0c16f2ed 100644 --- a/compiler/cgmeth.nim +++ b/compiler/cgmeth.nim @@ -107,11 +107,11 @@ proc attachDispatcher(s: PSym, dispatcher: PNode) = s.ast[resultPos] = newNodeI(nkEmpty, s.info) s.ast[dispatcherPos] = dispatcher -proc createDispatcher(s: PSym): PSym = - var disp = copySym(s) +proc createDispatcher(s: PSym; idgen: IdGenerator): PSym = + var disp = copySym(s, nextId(idgen)) incl(disp.flags, sfDispatcher) excl(disp.flags, sfExported) - disp.typ = copyType(disp.typ, disp.typ.owner, false) + disp.typ = copyType(disp.typ, nextId(idgen), disp.typ.owner) # we can't inline the dispatcher itself (for now): if disp.typ.callConv == ccInline: disp.typ.callConv = ccNimCall disp.ast = copyTree(s.ast) @@ -119,7 +119,7 @@ proc createDispatcher(s: PSym): PSym = disp.loc.r = nil if s.typ[0] != nil: if disp.ast.len > resultPos: - disp.ast[resultPos].sym = copySym(s.ast[resultPos].sym) + disp.ast[resultPos].sym = copySym(s.ast[resultPos].sym, nextId(idgen)) else: # We've encountered a method prototype without a filled-in # resultPos slot. We put a placeholder in there that will @@ -157,7 +157,7 @@ proc fixupDispatcher(meth, disp: PSym; conf: ConfigRef) = if disp.typ.lockLevel < meth.typ.lockLevel: disp.typ.lockLevel = meth.typ.lockLevel -proc methodDef*(g: ModuleGraph; s: PSym, fromCache: bool) = +proc methodDef*(g: ModuleGraph; idgen: IdGenerator; s: PSym, fromCache: bool) = var witness: PSym for i in 0..<g.methods.len: let disp = g.methods[i].dispatcher @@ -177,7 +177,7 @@ proc methodDef*(g: ModuleGraph; s: PSym, fromCache: bool) = of Invalid: if witness.isNil: witness = g.methods[i].methods[0] # create a new dispatcher: - g.methods.add((methods: @[s], dispatcher: createDispatcher(s))) + g.methods.add((methods: @[s], dispatcher: createDispatcher(s, idgen))) #echo "adding ", s.info #if fromCache: # internalError(s.info, "no method dispatcher found") diff --git a/compiler/closureiters.nim b/compiler/closureiters.nim index 567bb3b91..48088a609 100644 --- a/compiler/closureiters.nim +++ b/compiler/closureiters.nim @@ -153,6 +153,7 @@ type curExcHandlingState: int # Negative for except, positive for finally nearestFinally: int # Index of the nearest finally block. For try/except it # is their finally. For finally it is parent finally. Otherwise -1 + idgen: IdGenerator const nkSkip = {nkEmpty..nkNilLit, nkTemplateDef, nkTypeSection, nkStaticStmt, @@ -176,7 +177,7 @@ proc newStateAssgn(ctx: var Ctx, stateNo: int = -2): PNode = ctx.newStateAssgn(newIntTypeNode(stateNo, ctx.g.getSysType(TLineInfo(), tyInt))) proc newEnvVar(ctx: var Ctx, name: string, typ: PType): PSym = - result = newSym(skVar, getIdent(ctx.g.cache, name), ctx.fn, ctx.fn.info) + result = newSym(skVar, getIdent(ctx.g.cache, name), nextId(ctx.idgen), ctx.fn, ctx.fn.info) result.typ = typ assert(not typ.isNil) @@ -189,7 +190,7 @@ proc newEnvVar(ctx: var Ctx, name: string, typ: PType): PSym = else: let envParam = getEnvParam(ctx.fn) # let obj = envParam.typ.lastSon - result = addUniqueField(envParam.typ.lastSon, result, ctx.g.cache) + result = addUniqueField(envParam.typ.lastSon, result, ctx.g.cache, ctx.idgen) proc newEnvVarAccess(ctx: Ctx, s: PSym): PNode = if ctx.stateVarSym.isNil: @@ -804,7 +805,7 @@ proc newEndFinallyNode(ctx: var Ctx, info: TLineInfo): PNode = cmp.typ = ctx.g.getSysType(info, tyBool) let asgn = newTree(nkFastAsgn, - newSymNode(getClosureIterResult(ctx.g, ctx.fn), info), + newSymNode(getClosureIterResult(ctx.g, ctx.fn, ctx.idgen), info), ctx.newTmpResultAccess()) let retStmt = newTree(nkReturnStmt, asgn) @@ -1044,7 +1045,7 @@ proc transformStateAssignments(ctx: var Ctx, n: PNode): PNode = if n[0][0].kind != nkEmpty: var a = newNodeI(nkAsgn, n[0][0].info) var retVal = n[0][0] #liftCapturedVars(n[0], owner, d, c) - a.add newSymNode(getClosureIterResult(ctx.g, ctx.fn)) + a.add newSymNode(getClosureIterResult(ctx.g, ctx.fn, ctx.idgen)) a.add retVal retStmt.add(a) else: @@ -1116,10 +1117,10 @@ proc skipThroughEmptyStates(ctx: var Ctx, n: PNode): PNode= for i in 0..<n.len: n[i] = ctx.skipThroughEmptyStates(n[i]) -proc newArrayType(g: ModuleGraph; n: int, t: PType, owner: PSym): PType = - result = newType(tyArray, owner) +proc newArrayType(g: ModuleGraph; n: int, t: PType; idgen: IdGenerator; owner: PSym): PType = + result = newType(tyArray, nextId(idgen), owner) - let rng = newType(tyRange, owner) + let rng = newType(tyRange, nextId(idgen), owner) rng.n = newTree(nkRange, g.newIntLit(owner.info, 0), g.newIntLit(owner.info, n)) rng.rawAddSon(t) @@ -1128,7 +1129,7 @@ proc newArrayType(g: ModuleGraph; n: int, t: PType, owner: PSym): PType = proc createExceptionTable(ctx: var Ctx): PNode {.inline.} = result = newNodeI(nkBracket, ctx.fn.info) - result.typ = ctx.g.newArrayType(ctx.exceptionTable.len, ctx.g.getSysType(ctx.fn.info, tyInt16), ctx.fn) + result.typ = ctx.g.newArrayType(ctx.exceptionTable.len, ctx.g.getSysType(ctx.fn.info, tyInt16), ctx.idgen, ctx.fn) for i in ctx.exceptionTable: let elem = newIntNode(nkIntLit, i) @@ -1289,10 +1290,12 @@ type finallys: seq[PNode] config: ConfigRef blocks: seq[(PNode, int)] + idgen: IdGenerator FreshVarsContext = object tab: Table[int, PSym] config: ConfigRef info: TLineInfo + idgen: IdGenerator proc freshVars(n: PNode; c: var FreshVarsContext): PNode = case n.kind @@ -1311,7 +1314,7 @@ proc freshVars(n: PNode; c: var FreshVarsContext): PNode = let idefs = copyNode(it) for v in 0..it.len-3: if it[v].kind == nkSym: - let x = copySym(it[v].sym) + let x = copySym(it[v].sym, nextId(c.idgen)) c.tab[it[v].sym.id] = x idefs.add newSymNode(x) else: @@ -1371,27 +1374,29 @@ proc preprocess(c: var PreprocessContext; n: PNode): PNode = if fin >= 0: result = newNodeI(nkStmtList, n.info) for i in countdown(c.finallys.high, fin): - var vars = FreshVarsContext(tab: initTable[int, PSym](), config: c.config, info: n.info) + var vars = FreshVarsContext(tab: initTable[int, PSym](), config: c.config, info: n.info, idgen: c.idgen) result.add freshVars(preprocess(c, c.finallys[i]), vars) + c.idgen = vars.idgen result.add n of nkSkip: discard else: for i in 0 ..< n.len: result[i] = preprocess(c, n[i]) -proc transformClosureIterator*(g: ModuleGraph; fn: PSym, n: PNode): PNode = +proc transformClosureIterator*(g: ModuleGraph; idgen: IdGenerator; fn: PSym, n: PNode): PNode = var ctx: Ctx ctx.g = g ctx.fn = fn + ctx.idgen = idgen if getEnvParam(fn).isNil: # Lambda lifting was not done yet. Use temporary :state sym, which will # be handled specially by lambda lifting. Local temp vars (if needed) # should follow the same logic. - ctx.stateVarSym = newSym(skVar, getIdent(ctx.g.cache, ":state"), fn, fn.info) - ctx.stateVarSym.typ = g.createClosureIterStateType(fn) - ctx.stateLoopLabel = newSym(skLabel, getIdent(ctx.g.cache, ":stateLoop"), fn, fn.info) - var pc = PreprocessContext(finallys: @[], config: g.config) + ctx.stateVarSym = newSym(skVar, getIdent(ctx.g.cache, ":state"), nextId(idgen), fn, fn.info) + ctx.stateVarSym.typ = g.createClosureIterStateType(fn, idgen) + ctx.stateLoopLabel = newSym(skLabel, getIdent(ctx.g.cache, ":stateLoop"), nextId(idgen), fn, fn.info) + var pc = PreprocessContext(finallys: @[], config: g.config, idgen: idgen) var n = preprocess(pc, n.toStmtList) #echo "transformed into ", n #var n = n.toStmtList diff --git a/compiler/cmdlinehelper.nim b/compiler/cmdlinehelper.nim index 5fb8ab471..a415afce9 100644 --- a/compiler/cmdlinehelper.nim +++ b/compiler/cmdlinehelper.nim @@ -59,7 +59,7 @@ proc loadConfigsAndRunMainCommand*(self: NimProg, cache: IdentCache; conf: Confi graph: ModuleGraph): bool = if self.suggestMode: conf.command = "nimsuggest" - loadConfigs(DefaultConfig, cache, conf) # load all config files + loadConfigs(DefaultConfig, cache, conf, graph.idgen) # load all config files if not self.suggestMode: let scriptFile = conf.projectFull.changeFileExt("nims") diff --git a/compiler/depends.nim b/compiler/depends.nim index cc385da4b..7225b6b47 100644 --- a/compiler/depends.nim +++ b/compiler/depends.nim @@ -54,7 +54,7 @@ proc generateDot*(graph: ModuleGraph; project: AbsoluteFile) = when not defined(nimHasSinkInference): {.pragma: nosinks.} -proc myOpen(graph: ModuleGraph; module: PSym): PPassContext {.nosinks.} = +proc myOpen(graph: ModuleGraph; module: PSym; idgen: IdGenerator): PPassContext {.nosinks.} = var g: PGen new(g) g.module = module diff --git a/compiler/docgen2.nim b/compiler/docgen2.nim index 9cb40a7fc..cfbb33156 100644 --- a/compiler/docgen2.nim +++ b/compiler/docgen2.nim @@ -68,10 +68,10 @@ template myOpenImpl(ext: untyped) {.dirty.} = g.doc = d result = g -proc myOpen(graph: ModuleGraph; module: PSym): PPassContext = +proc myOpen(graph: ModuleGraph; module: PSym; idgen: IdGenerator): PPassContext = myOpenImpl(HtmlExt) -proc myOpenJson(graph: ModuleGraph; module: PSym): PPassContext = +proc myOpenJson(graph: ModuleGraph; module: PSym; idgen: IdGenerator): PPassContext = myOpenImpl(JsonExt) const docgen2Pass* = makePass(open = myOpen, process = processNode, close = close) diff --git a/compiler/enumtostr.nim b/compiler/enumtostr.nim index 3eb703ade..3274462d7 100644 --- a/compiler/enumtostr.nim +++ b/compiler/enumtostr.nim @@ -1,16 +1,16 @@ import ast, idents, lineinfos, modulegraphs, magicsys -proc genEnumToStrProc*(t: PType; info: TLineInfo; g: ModuleGraph): PSym = - result = newSym(skProc, getIdent(g.cache, "$"), t.owner, info) +proc genEnumToStrProc*(t: PType; info: TLineInfo; g: ModuleGraph; idgen: IdGenerator): PSym = + result = newSym(skProc, getIdent(g.cache, "$"), nextId idgen, t.owner, info) - let dest = newSym(skParam, getIdent(g.cache, "e"), result, info) + let dest = newSym(skParam, getIdent(g.cache, "e"), nextId idgen, result, info) dest.typ = t - let res = newSym(skResult, getIdent(g.cache, "result"), result, info) + let res = newSym(skResult, getIdent(g.cache, "result"), nextId idgen, result, info) res.typ = getSysType(g, info, tyString) - result.typ = newType(tyProc, t.owner) + result.typ = newType(tyProc, nextId idgen, t.owner) result.typ.n = newNodeI(nkFormalParams, info) rawAddSon(result.typ, res.typ) result.typ.n.add newNodeI(nkEffectList, info) @@ -62,16 +62,16 @@ proc searchObjCase(t: PType; field: PSym): PNode = result = searchObjCase(t[0].skipTypes({tyAlias, tyGenericInst, tyRef, tyPtr}), field) doAssert result != nil -proc genCaseObjDiscMapping*(t: PType; field: PSym; info: TLineInfo; g: ModuleGraph): PSym = - result = newSym(skProc, getIdent(g.cache, "objDiscMapping"), t.owner, info) +proc genCaseObjDiscMapping*(t: PType; field: PSym; info: TLineInfo; g: ModuleGraph; idgen: IdGenerator): PSym = + result = newSym(skProc, getIdent(g.cache, "objDiscMapping"), nextId idgen, t.owner, info) - let dest = newSym(skParam, getIdent(g.cache, "e"), result, info) + let dest = newSym(skParam, getIdent(g.cache, "e"), nextId idgen, result, info) dest.typ = field.typ - let res = newSym(skResult, getIdent(g.cache, "result"), result, info) + let res = newSym(skResult, getIdent(g.cache, "result"), nextId idgen, result, info) res.typ = getSysType(g, info, tyUInt8) - result.typ = newType(tyProc, t.owner) + result.typ = newType(tyProc, nextId idgen, t.owner) result.typ.n = newNodeI(nkFormalParams, info) rawAddSon(result.typ, res.typ) result.typ.n.add newNodeI(nkEffectList, info) diff --git a/compiler/evaltempl.nim b/compiler/evaltempl.nim index c1024e2fe..218a597d8 100644 --- a/compiler/evaltempl.nim +++ b/compiler/evaltempl.nim @@ -22,6 +22,7 @@ type config: ConfigRef ic: IdentCache instID: int + idgen: IdGenerator proc copyNode(ctx: TemplCtx, a, b: PNode): PNode = result = copyNode(a) @@ -48,7 +49,7 @@ proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) = internalAssert c.config, sfGenSym in s.flags or s.kind == skType var x = PSym(idTableGet(c.mapping, s)) if x == nil: - x = copySym(s) + x = copySym(s, nextId(c.idgen)) # sem'check needs to set the owner properly later, see bug #9476 x.owner = nil # c.genSymOwner #if x.kind == skParam and x.owner.kind == skModule: @@ -168,6 +169,7 @@ proc wrapInComesFrom*(info: TLineInfo; sym: PSym; res: PNode): PNode = proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym; conf: ConfigRef; ic: IdentCache; instID: ref int; + idgen: IdGenerator; fromHlo=false): PNode = inc(conf.evalTemplateCounter) if conf.evalTemplateCounter > evalTemplateLimit: @@ -183,6 +185,7 @@ proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym; ctx.ic = ic initIdTable(ctx.mapping) ctx.instID = instID[] + ctx.idgen = idgen let body = tmpl.getBody #echo "instantion of ", renderTree(body, {renderIds}) diff --git a/compiler/guards.nim b/compiler/guards.nim index a6ca44978..4f07df201 100644 --- a/compiler/guards.nim +++ b/compiler/guards.nim @@ -993,8 +993,9 @@ proc addFactLt*(m: var TModel; a, b: PNode) = addFactLe(m, a, bb) proc settype(n: PNode): PType = - result = newType(tySet, n.typ.owner) - addSonSkipIntLit(result, n.typ) + result = newType(tySet, ItemId(module: -1, item: -1), n.typ.owner) + var idgen: IdGenerator + addSonSkipIntLit(result, n.typ, idgen) proc buildOf(it, loc: PNode; o: Operators): PNode = var s = newNodeI(nkCurly, it.info, it.len-1) diff --git a/compiler/hlo.nim b/compiler/hlo.nim index bb69a1477..af54cabbb 100644 --- a/compiler/hlo.nim +++ b/compiler/hlo.nim @@ -86,9 +86,9 @@ proc hlo(c: PContext, n: PNode): PNode = else: result = fitNode(c, n.typ, result, n.info) # optimization has been applied so check again: - result = commonOptimizations(c.graph, c.module, result) + result = commonOptimizations(c.graph, c.idgen, c.module, result) result = hlo(c, result) - result = commonOptimizations(c.graph, c.module, result) + result = commonOptimizations(c.graph, c.idgen, c.module, result) proc hloBody(c: PContext, n: PNode): PNode = # fast exit: diff --git a/compiler/idents.nim b/compiler/idents.nim index a035974f3..b621503ec 100644 --- a/compiler/idents.nim +++ b/compiler/idents.nim @@ -15,12 +15,9 @@ import hashes, wordrecg type - TIdObj* = object of RootObj - id*: int # unique id; use this for comparisons and not the pointers - - PIdObj* = ref TIdObj PIdent* = ref TIdent - TIdent*{.acyclic.} = object of TIdObj + TIdent*{.acyclic.} = object + id*: int # unique id; use this for comparisons and not the pointers s*: string next*: PIdent # for hash-table chaining h*: Hash # hash value of s diff --git a/compiler/idgen.nim b/compiler/idgen.nim deleted file mode 100644 index 7d49e33e3..000000000 --- a/compiler/idgen.nim +++ /dev/null @@ -1,59 +0,0 @@ -# -# -# The Nim Compiler -# (c) Copyright 2012 Andreas Rumpf -# -# See the file "copying.txt", included in this -# distribution, for details about the copyright. -# - -## This module contains a simple persistent id generator. - -import idents, strutils, options, pathutils - -var gFrontEndId*: int - -const - debugIds* = false - -when debugIds: - import intsets - - var usedIds = initIntSet() - -proc registerID*(id: PIdObj) = - when debugIds: - if id.id == -1 or containsOrIncl(usedIds, id.id): - internalError("ID already used: " & $id.id) - -proc getID*(): int {.inline.} = - result = gFrontEndId - inc(gFrontEndId) - -proc setId*(id: int) {.inline.} = - gFrontEndId = max(gFrontEndId, id + 1) - -proc idSynchronizationPoint*(idRange: int) = - gFrontEndId = (gFrontEndId div idRange + 1) * idRange + 1 - -proc toGid(conf: ConfigRef; f: AbsoluteFile): string = - # we used to use ``f.addFileExt("gid")`` (aka ``$project.gid``), but this - # will cause strange bugs if multiple projects are in the same folder, so - # we simply use a project independent name: - result = options.completeGeneratedFilePath(conf, AbsoluteFile"nim.gid").string - -proc saveMaxIds*(conf: ConfigRef; project: AbsoluteFile) = - var f = open(toGid(conf, project), fmWrite) - f.writeLine($gFrontEndId) - f.close() - -proc loadMaxIds*(conf: ConfigRef; project: AbsoluteFile) = - var f: File - if open(f, toGid(conf, project), fmRead): - var line = newStringOfCap(20) - if f.readLine(line): - var frontEndId = parseInt(line) - if f.readLine(line): - # var backEndId = parseInt(line) - gFrontEndId = max(gFrontEndId, frontEndId) - f.close() diff --git a/compiler/importer.nim b/compiler/importer.nim index 34e76d7d9..6722eab15 100644 --- a/compiler/importer.nim +++ b/compiler/importer.nim @@ -136,7 +136,7 @@ proc importModuleAs(c: PContext; n: PNode, realModule: PSym): PSym = localError(c.config, n.info, "module alias must be an identifier") elif n[1].ident.id != realModule.name.id: # some misguided guy will write 'import abc.foo as foo' ... - result = createModuleAlias(realModule, n[1].ident, realModule.info, + result = createModuleAlias(realModule, nextId c.idgen, n[1].ident, realModule.info, c.config.options) proc myImportModule(c: PContext, n: PNode; importStmtResult: PNode): PSym = diff --git a/compiler/injectdestructors.nim b/compiler/injectdestructors.nim index ea90299e2..0b893ede8 100644 --- a/compiler/injectdestructors.nim +++ b/compiler/injectdestructors.nim @@ -40,6 +40,7 @@ type inLoop, inSpawn: int uninit: IntSet # set of uninit'ed vars uninitComputed: bool + idgen: IdGenerator ProcessMode = enum normal @@ -61,7 +62,7 @@ template dbg(body) = body proc getTemp(c: var Con; s: var Scope; typ: PType; info: TLineInfo): PNode = - let sym = newSym(skTemp, getIdent(c.graph.cache, ":tmpD"), c.owner, info) + let sym = newSym(skTemp, getIdent(c.graph.cache, ":tmpD"), nextId c.idgen, c.owner, info) sym.typ = typ s.vars.add(sym) result = newSymNode(sym) @@ -250,16 +251,16 @@ proc checkForErrorPragma(c: Con; t: PType; ri: PNode; opname: string) = m.add c.owner.name.s localError(c.graph.config, ri.info, errGenerated, m) -proc makePtrType(c: Con, baseType: PType): PType = - result = newType(tyPtr, c.owner) - addSonSkipIntLit(result, baseType) +proc makePtrType(c: var Con, baseType: PType): PType = + result = newType(tyPtr, nextId c.idgen, c.owner) + addSonSkipIntLit(result, baseType, c.idgen) -proc genOp(c: Con; op: PSym; dest: PNode): PNode = +proc genOp(c: var Con; op: PSym; dest: PNode): PNode = let addrExp = newNodeIT(nkHiddenAddr, dest.info, makePtrType(c, dest.typ)) addrExp.add(dest) result = newTree(nkCall, newSymNode(op), addrExp) -proc genOp(c: Con; t: PType; kind: TTypeAttachedOp; dest, ri: PNode): PNode = +proc genOp(c: var Con; t: PType; kind: TTypeAttachedOp; dest, ri: PNode): PNode = var op = t.attachedOps[kind] if op == nil or op.ast[genericParamsPos].kind != nkEmpty: # give up and find the canonical type instead: @@ -280,7 +281,7 @@ proc genOp(c: Con; t: PType; kind: TTypeAttachedOp; dest, ri: PNode): PNode = if sfError in op.flags: checkForErrorPragma(c, t, ri, AttachedOpToStr[kind]) c.genOp(op, dest) -proc genDestroy(c: Con; dest: PNode): PNode = +proc genDestroy(c: var Con; dest: PNode): PNode = let t = dest.typ.skipTypes({tyGenericInst, tyAlias, tySink}) result = c.genOp(t, attachedDestructor, dest, nil) @@ -310,7 +311,7 @@ proc genSink(c: var Con; dest, ri: PNode, isDecl = false): PNode = # and copyMem(dest, source). This is efficient. result = newTree(nkStmtList, c.genDestroy(dest), newTree(nkFastAsgn, dest, ri)) -proc genCopyNoCheck(c: Con; dest, ri: PNode): PNode = +proc genCopyNoCheck(c: var Con; dest, ri: PNode): PNode = let t = dest.typ.skipTypes({tyGenericInst, tyAlias, tySink}) result = c.genOp(t, attachedAsgn, dest, ri) @@ -346,7 +347,7 @@ It is best to factor out piece of object that needs custom destructor into separ return # generate: if le != tmp: `=destroy`(le) - let branchDestructor = produceDestructorForDiscriminator(c.graph, objType, leDotExpr[1].sym, n.info) + let branchDestructor = produceDestructorForDiscriminator(c.graph, objType, leDotExpr[1].sym, n.info, c.idgen) let cond = newNodeIT(nkInfix, n.info, getSysType(c.graph, unknownLineInfo, tyBool)) cond.add newSymNode(getMagicEqSymForType(c.graph, le.typ, n.info)) cond.add le @@ -377,7 +378,7 @@ proc destructiveMoveVar(n: PNode; c: var Con; s: var Scope): PNode = else: result = newNodeIT(nkStmtListExpr, n.info, n.typ) - var temp = newSym(skLet, getIdent(c.graph.cache, "blitTmp"), c.owner, n.info) + var temp = newSym(skLet, getIdent(c.graph.cache, "blitTmp"), nextId c.idgen, c.owner, n.info) temp.typ = n.typ var v = newNodeI(nkLetSection, n.info) let tempAsNode = newSymNode(temp) @@ -799,7 +800,7 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode): PNode = for it in n: var ri = it[^1] if it.kind == nkVarTuple and hasDestructor(c, ri.typ): - let x = lowerTupleUnpacking(c.graph, it, c.owner) + let x = lowerTupleUnpacking(c.graph, it, c.idgen, c.owner) result.add p(x, c, s, consumed) elif it.kind == nkIdentDefs and hasDestructor(c, it[0].typ) and not isCursor(it[0], c): for j in 0..<it.len-2: @@ -1010,10 +1011,10 @@ proc injectDefaultCalls(n: PNode, c: var Con) = for i in 0..<n.safeLen: injectDefaultCalls(n[i], c) -proc injectDestructorCalls*(g: ModuleGraph; owner: PSym; n: PNode): PNode = +proc injectDestructorCalls*(g: ModuleGraph; idgen: IdGenerator; owner: PSym; n: PNode): PNode = if sfGeneratedOp in owner.flags or (owner.kind == skIterator and isInlineIterator(owner.typ)): return n - var c = Con(owner: owner, graph: g, g: constructCfg(owner, n)) + var c = Con(owner: owner, graph: g, g: constructCfg(owner, n), idgen: idgen) dbg: echo "\n### ", owner.name.s, ":\nCFG:" echoCfg(c.g) diff --git a/compiler/isolation_check.nim b/compiler/isolation_check.nim index f3b0c4919..8c40dd4ad 100644 --- a/compiler/isolation_check.nim +++ b/compiler/isolation_check.nim @@ -11,7 +11,7 @@ ## https://github.com/nim-lang/RFCs/issues/244 for more details. import - ast, types, renderer, idents, intsets + ast, types, renderer, intsets proc canAlias(arg, ret: PType; marker: var IntSet): bool diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index bea5225e6..4d913aa87 100644 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -602,12 +602,12 @@ proc arithAux(p: PProc, n: PNode, r: var TCompRes, op: TMagic) = of mMulF64: applyFormat("($1 * $2)", "($1 * $2)") of mDivF64: applyFormat("($1 / $2)", "($1 / $2)") of mShrI: applyFormat("", "") - of mShlI: + of mShlI: if n[1].typ.size <= 4: applyFormat("($1 << $2)", "($1 << $2)") else: applyFormat("($1 * Math.pow(2,$2))", "($1 * Math.pow(2,$2))") - of mAshrI: + of mAshrI: if n[1].typ.size <= 4: applyFormat("($1 >> $2)", "($1 >> $2)") else: @@ -1804,7 +1804,7 @@ proc genVarStmt(p: PProc, n: PNode) = var a = n[i] if a.kind != nkCommentStmt: if a.kind == nkVarTuple: - let unpacked = lowerTupleUnpacking(p.module.graph, a, p.prc) + let unpacked = lowerTupleUnpacking(p.module.graph, a, p.module.idgen, p.prc) genStmt(p, unpacked) else: assert(a.kind == nkIdentDefs) @@ -2316,9 +2316,9 @@ proc genProc(oldProc: PProc, prc: PSym): Rope = else: returnStmt = "return $#;$n" % [a.res] - var transformedBody = transformBody(oldProc.module.graph, prc, cache = false) + var transformedBody = transformBody(p.module.graph, p.module.idgen, prc, cache = false) if sfInjectDestructors in prc.flags: - transformedBody = injectDestructorCalls(oldProc.module.graph, prc, transformedBody) + transformedBody = injectDestructorCalls(p.module.graph, p.module.idgen, prc, transformedBody) p.nested: genStmt(p, transformedBody) @@ -2607,9 +2607,9 @@ proc genModule(p: PProc, n: PNode) = p.body.add(frameCreate(p, makeJSString("module " & p.module.module.name.s), makeJSString(toFilenameOption(p.config, p.module.module.info.fileIndex, foStacktrace)))) - var transformedN = transformStmt(p.module.graph, p.module.module, n) + var transformedN = transformStmt(p.module.graph, p.module.idgen, p.module.module, n) if sfInjectDestructors in p.module.module.flags: - transformedN = injectDestructorCalls(p.module.graph, p.module.module, transformedN) + transformedN = injectDestructorCalls(p.module.graph, p.module.idgen, p.module.module, transformedN) if p.config.hcrOn and n.kind == nkStmtList: let moduleSym = p.module.module var moduleLoadedVar = rope(moduleSym.name.s) & "_loaded" & @@ -2686,7 +2686,9 @@ proc myClose(graph: ModuleGraph; b: PPassContext, n: PNode): PNode = writeFile(outFile.string & ".map", $(%map)) discard writeRopeIfNotEqual(code, outFile) -proc myOpen(graph: ModuleGraph; s: PSym): PPassContext = + +proc myOpen(graph: ModuleGraph; s: PSym; idgen: IdGenerator): PPassContext = result = newModule(graph, s) + result.idgen = idgen const JSgenPass* = makePass(myOpen, myProcess, myClose) diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim index c23ca52cb..b552d9455 100644 --- a/compiler/lambdalifting.nim +++ b/compiler/lambdalifting.nim @@ -126,32 +126,32 @@ proc newCall(a: PSym, b: PNode): PNode = result.add newSymNode(a) result.add b -proc createClosureIterStateType*(g: ModuleGraph; iter: PSym): PType = +proc createClosureIterStateType*(g: ModuleGraph; iter: PSym; idgen: IdGenerator): PType = var n = newNodeI(nkRange, iter.info) n.add newIntNode(nkIntLit, -1) n.add newIntNode(nkIntLit, 0) - result = newType(tyRange, iter) + result = newType(tyRange, nextId(idgen), iter) result.n = n var intType = nilOrSysInt(g) - if intType.isNil: intType = newType(tyInt, iter) + if intType.isNil: intType = newType(tyInt, nextId(idgen), iter) rawAddSon(result, intType) -proc createStateField(g: ModuleGraph; iter: PSym): PSym = - result = newSym(skField, getIdent(g.cache, ":state"), iter, iter.info) - result.typ = createClosureIterStateType(g, iter) +proc createStateField(g: ModuleGraph; iter: PSym; idgen: IdGenerator): PSym = + result = newSym(skField, getIdent(g.cache, ":state"), nextId(idgen), iter, iter.info) + result.typ = createClosureIterStateType(g, iter, idgen) -proc createEnvObj(g: ModuleGraph; owner: PSym; info: TLineInfo): PType = +proc createEnvObj(g: ModuleGraph; idgen: IdGenerator; owner: PSym; info: TLineInfo): PType = # YYY meh, just add the state field for every closure for now, it's too # hard to figure out if it comes from a closure iterator: - result = createObj(g, owner, info, final=false) - rawAddField(result, createStateField(g, owner)) + result = createObj(g, idgen, owner, info, final=false) + rawAddField(result, createStateField(g, owner, idgen)) -proc getClosureIterResult*(g: ModuleGraph; iter: PSym): PSym = +proc getClosureIterResult*(g: ModuleGraph; iter: PSym; idgen: IdGenerator): PSym = if resultPos < iter.ast.len: result = iter.ast[resultPos].sym else: # XXX a bit hacky: - result = newSym(skResult, getIdent(g.cache, ":result"), iter, iter.info, {}) + result = newSym(skResult, getIdent(g.cache, ":result"), nextId(idgen), iter, iter.info, {}) result.typ = iter.typ[0] incl(result.flags, sfUsed) iter.ast.add newSymNode(result) @@ -209,7 +209,7 @@ proc newAsgnStmt(le, ri: PNode, info: TLineInfo): PNode = result[0] = le result[1] = ri -proc makeClosure*(g: ModuleGraph; prc: PSym; env: PNode; info: TLineInfo): PNode = +proc makeClosure*(g: ModuleGraph; idgen: IdGenerator; prc: PSym; env: PNode; info: TLineInfo): PNode = result = newNodeIT(nkClosure, info, prc.typ) result.add(newSymNode(prc)) if env == nil: @@ -219,7 +219,7 @@ proc makeClosure*(g: ModuleGraph; prc: PSym; env: PNode; info: TLineInfo): PNode localError(g.config, info, "internal error: taking closure of closure") result.add(env) #if isClosureIterator(result.typ): - createTypeBoundOps(g, nil, result.typ, info) + createTypeBoundOps(g, nil, result.typ, info, idgen) if tfHasAsgn in result.typ.flags or optSeqDestructors in g.config.globalOptions: prc.flags.incl sfInjectDestructors @@ -237,13 +237,13 @@ proc liftingHarmful(conf: ConfigRef; owner: PSym): bool {.inline.} = let isCompileTime = sfCompileTime in owner.flags or owner.kind == skMacro result = conf.backend == backendJs and not isCompileTime -proc createTypeBoundOpsLL(g: ModuleGraph; refType: PType; info: TLineInfo; owner: PSym) = - createTypeBoundOps(g, nil, refType.lastSon, info) - createTypeBoundOps(g, nil, refType, info) +proc createTypeBoundOpsLL(g: ModuleGraph; refType: PType; info: TLineInfo; idgen: IdGenerator; owner: PSym) = + createTypeBoundOps(g, nil, refType.lastSon, info, idgen) + createTypeBoundOps(g, nil, refType, info, idgen) if tfHasAsgn in refType.flags or optSeqDestructors in g.config.globalOptions: owner.flags.incl sfInjectDestructors -proc liftIterSym*(g: ModuleGraph; n: PNode; owner: PSym): PNode = +proc liftIterSym*(g: ModuleGraph; n: PNode; idgen: IdGenerator; owner: PSym): PNode = # transforms (iter) to (let env = newClosure[iter](); (iter, env)) if liftingHarmful(g.config, owner): return n let iter = n.sym @@ -255,10 +255,10 @@ proc liftIterSym*(g: ModuleGraph; n: PNode; owner: PSym): PNode = var env: PNode if owner.isIterator: let it = getHiddenParam(g, owner) - addUniqueField(it.typ.skipTypes({tyOwned})[0], hp, g.cache) + addUniqueField(it.typ.skipTypes({tyOwned})[0], hp, g.cache, idgen) env = indirectAccess(newSymNode(it), hp, hp.info) else: - let e = newSym(skLet, iter.name, owner, n.info) + let e = newSym(skLet, iter.name, nextId(idgen), owner, n.info) e.typ = hp.typ e.flags = hp.flags env = newSymNode(e) @@ -267,13 +267,13 @@ proc liftIterSym*(g: ModuleGraph; n: PNode; owner: PSym): PNode = result.add(v) # add 'new' statement: result.add newCall(getSysSym(g, n.info, "internalNew"), env) - createTypeBoundOpsLL(g, env.typ, n.info, owner) - result.add makeClosure(g, iter, env, n.info) + createTypeBoundOpsLL(g, env.typ, n.info, idgen, owner) + result.add makeClosure(g, idgen, iter, env, n.info) -proc freshVarForClosureIter*(g: ModuleGraph; s, owner: PSym): PNode = +proc freshVarForClosureIter*(g: ModuleGraph; s: PSym; idgen: IdGenerator; owner: PSym): PNode = let envParam = getHiddenParam(g, owner) let obj = envParam.typ.skipTypes({tyOwned, tyRef, tyPtr}) - addField(obj, s, g.cache) + addField(obj, s, g.cache, idgen) var access = newSymNode(envParam) assert obj.kind == tyObject @@ -305,13 +305,15 @@ type ownerToType: Table[int, PType] somethingToDo: bool graph: ModuleGraph + idgen: IdGenerator -proc initDetectionPass(g: ModuleGraph; fn: PSym): DetectionPass = +proc initDetectionPass(g: ModuleGraph; fn: PSym; idgen: IdGenerator): DetectionPass = result.processed = initIntSet() result.capturedVars = initIntSet() result.ownerToType = initTable[int, PType]() result.processed.incl(fn.id) result.graph = g + result.idgen = idgen discard """ proc outer = @@ -327,15 +329,15 @@ proc getEnvTypeForOwner(c: var DetectionPass; owner: PSym; info: TLineInfo): PType = result = c.ownerToType.getOrDefault(owner.id) if result.isNil: - result = newType(tyRef, owner) - let obj = createEnvObj(c.graph, owner, info) + result = newType(tyRef, nextId(c.idgen), owner) + let obj = createEnvObj(c.graph, c.idgen, owner, info) rawAddSon(result, obj) c.ownerToType[owner.id] = result -proc asOwnedRef(c: DetectionPass; t: PType): PType = +proc asOwnedRef(c: var DetectionPass; t: PType): PType = if optOwnedRefs in c.graph.config.globalOptions: assert t.kind == tyRef - result = newType(tyOwned, t.owner) + result = newType(tyOwned, nextId(c.idgen), t.owner) result.flags.incl tfHasOwned result.rawAddSon t else: @@ -344,7 +346,7 @@ proc asOwnedRef(c: DetectionPass; t: PType): PType = proc getEnvTypeForOwnerUp(c: var DetectionPass; owner: PSym; info: TLineInfo): PType = var r = c.getEnvTypeForOwner(owner, info) - result = newType(tyPtr, owner) + result = newType(tyPtr, nextId(c.idgen), owner) rawAddSon(result, r.skipTypes({tyOwned, tyRef, tyPtr})) proc createUpField(c: var DetectionPass; dest, dep: PSym; info: TLineInfo) = @@ -372,7 +374,7 @@ proc createUpField(c: var DetectionPass; dest, dep: PSym; info: TLineInfo) = if c.graph.config.selectedGC == gcDestructors and sfCursor notin upField.flags: localError(c.graph.config, dep.info, "internal error: up reference is not a .cursor") else: - let result = newSym(skField, upIdent, obj.owner, obj.owner.info) + let result = newSym(skField, upIdent, nextId(c.idgen), obj.owner, obj.owner.info) result.typ = fieldType when false: if c.graph.config.selectedGC == gcDestructors: @@ -410,7 +412,7 @@ proc addClosureParam(c: var DetectionPass; fn: PSym; info: TLineInfo) = let owner = if fn.kind == skIterator: fn else: fn.skipGenericOwner let t = c.getEnvTypeForOwner(owner, info) if cp == nil: - cp = newSym(skParam, getIdent(c.graph.cache, paramName), fn, fn.info) + cp = newSym(skParam, getIdent(c.graph.cache, paramName), nextId(c.idgen), fn, fn.info) incl(cp.flags, sfFromGeneric) cp.typ = t addHiddenParam(fn, cp) @@ -433,7 +435,7 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) = if innerProc: if s.isIterator: c.somethingToDo = true if not c.processed.containsOrIncl(s.id): - let body = transformBody(c.graph, s, cache = true) + let body = transformBody(c.graph, c.idgen, s, cache = true) detectCapturedVars(body, s, c) let ow = s.skipGenericOwner if ow == owner: @@ -446,9 +448,9 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) = #let obj = c.getEnvTypeForOwner(s.owner).skipTypes({tyOwned, tyRef, tyPtr}) if s.name.id == getIdent(c.graph.cache, ":state").id: - obj.n[0].sym.id = -s.id + obj.n[0].sym.itemId = ItemId(module: s.itemId.module, item: -s.itemId.item) else: - addField(obj, s, c.graph.cache) + addField(obj, s, c.graph.cache, c.idgen) # direct or indirect dependency: elif (innerProc and s.typ.callConv == ccClosure) or interestingVar(s): discard """ @@ -470,7 +472,7 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) = if interestingVar(s) and not c.capturedVars.containsOrIncl(s.id): let obj = c.getEnvTypeForOwner(ow, n.info).skipTypes({tyOwned, tyRef, tyPtr}) #getHiddenParam(owner).typ.skipTypes({tyOwned, tyRef, tyPtr}) - addField(obj, s, c.graph.cache) + addField(obj, s, c.graph.cache, c.idgen) # create required upFields: var w = owner.skipGenericOwner if isInnerProc(w) or owner.isIterator: @@ -535,8 +537,8 @@ proc accessViaEnvParam(g: ModuleGraph; n: PNode; owner: PSym): PNode = localError(g.config, n.info, "internal error: environment misses: " & s.name.s) result = n -proc newEnvVar(cache: IdentCache; owner: PSym; typ: PType; info: TLineInfo): PNode = - var v = newSym(skVar, getIdent(cache, envName), owner, info) +proc newEnvVar(cache: IdentCache; owner: PSym; typ: PType; info: TLineInfo; idgen: IdGenerator): PNode = + var v = newSym(skVar, getIdent(cache, envName), nextId(idgen), owner, info) v.flags = {sfShadowed, sfGeneratedOp} v.typ = typ result = newSymNode(v) @@ -548,7 +550,7 @@ proc newEnvVar(cache: IdentCache; owner: PSym; typ: PType; info: TLineInfo): PNo else: result = newSymNode(v) -proc setupEnvVar(owner: PSym; d: DetectionPass; +proc setupEnvVar(owner: PSym; d: var DetectionPass; c: var LiftingPass; info: TLineInfo): PNode = if owner.isIterator: return getHiddenParam(d.graph, owner).newSymNode @@ -557,10 +559,10 @@ proc setupEnvVar(owner: PSym; d: DetectionPass; let envVarType = d.ownerToType.getOrDefault(owner.id) if envVarType.isNil: localError d.graph.config, owner.info, "internal error: could not determine closure type" - result = newEnvVar(d.graph.cache, owner, asOwnedRef(d, envVarType), info) + result = newEnvVar(d.graph.cache, owner, asOwnedRef(d, envVarType), info, d.idgen) c.envVars[owner.id] = result if optOwnedRefs in d.graph.config.globalOptions: - var v = newSym(skVar, getIdent(d.graph.cache, envName & "Alt"), owner, info) + var v = newSym(skVar, getIdent(d.graph.cache, envName & "Alt"), nextId d.idgen, owner, info) v.flags = {sfShadowed, sfGeneratedOp} v.typ = envVarType c.unownedEnvVars[owner.id] = newSymNode(v) @@ -576,7 +578,7 @@ proc getUpViaParam(g: ModuleGraph; owner: PSym): PNode = result = rawIndirectAccess(result, upField, p.info) proc rawClosureCreation(owner: PSym; - d: DetectionPass; c: var LiftingPass; + d: var DetectionPass; c: var LiftingPass; info: TLineInfo): PNode = result = newNodeI(nkStmtList, owner.info) @@ -602,7 +604,7 @@ proc rawClosureCreation(owner: PSym; let env2 = copyTree(env) env2.typ = unowned.typ result.add newAsgnStmt(unowned, env2, env.info) - createTypeBoundOpsLL(d.graph, unowned.typ, env.info, owner) + createTypeBoundOpsLL(d.graph, unowned.typ, env.info, d.idgen, owner) # add assignment statements for captured parameters: for i in 1..<owner.typ.n.len: @@ -611,7 +613,7 @@ proc rawClosureCreation(owner: PSym; let fieldAccess = indirectAccess(env, local, env.info) # add ``env.param = param`` result.add(newAsgnStmt(fieldAccess, newSymNode(local), env.info)) - createTypeBoundOps(d.graph, nil, fieldAccess.typ, env.info) + createTypeBoundOps(d.graph, nil, fieldAccess.typ, env.info, d.idgen) if tfHasAsgn in fieldAccess.typ.flags or optSeqDestructors in d.graph.config.globalOptions: owner.flags.incl sfInjectDestructors @@ -628,28 +630,28 @@ proc rawClosureCreation(owner: PSym; localError(d.graph.config, env.info, "internal error: cannot create up reference") # we are not in the sem'check phase anymore! so pass 'nil' for the PContext # and hope for the best: - createTypeBoundOpsLL(d.graph, env.typ, owner.info, owner) + createTypeBoundOpsLL(d.graph, env.typ, owner.info, d.idgen, owner) -proc finishClosureCreation(owner: PSym; d: DetectionPass; c: LiftingPass; +proc finishClosureCreation(owner: PSym; d: var DetectionPass; c: LiftingPass; info: TLineInfo; res: PNode) = if optOwnedRefs in d.graph.config.globalOptions: let unowned = c.unownedEnvVars[owner.id] assert unowned != nil let nilLit = newNodeIT(nkNilLit, info, unowned.typ) res.add newAsgnStmt(unowned, nilLit, info) - createTypeBoundOpsLL(d.graph, unowned.typ, info, owner) + createTypeBoundOpsLL(d.graph, unowned.typ, info, d.idgen, owner) proc closureCreationForIter(iter: PNode; - d: DetectionPass; c: var LiftingPass): PNode = + d: var DetectionPass; c: var LiftingPass): PNode = result = newNodeIT(nkStmtListExpr, iter.info, iter.sym.typ) let owner = iter.sym.skipGenericOwner - var v = newSym(skVar, getIdent(d.graph.cache, envName), owner, iter.info) + var v = newSym(skVar, getIdent(d.graph.cache, envName), nextId(d.idgen), owner, iter.info) incl(v.flags, sfShadowed) v.typ = asOwnedRef(d, getHiddenParam(d.graph, iter.sym).typ) var vnode: PNode if owner.isIterator: let it = getHiddenParam(d.graph, owner) - addUniqueField(it.typ.skipTypes({tyOwned, tyRef, tyPtr}), v, d.graph.cache) + addUniqueField(it.typ.skipTypes({tyOwned, tyRef, tyPtr}), v, d.graph.cache, d.idgen) vnode = indirectAccess(newSymNode(it), v, v.info) else: vnode = v.newSymNode @@ -657,7 +659,7 @@ proc closureCreationForIter(iter: PNode; addVar(vs, vnode) result.add(vs) result.add(newCall(getSysSym(d.graph, iter.info, "internalNew"), vnode)) - createTypeBoundOpsLL(d.graph, vnode.typ, iter.info, owner) + createTypeBoundOpsLL(d.graph, vnode.typ, iter.info, d.idgen, owner) let upField = lookupInRecord(v.typ.skipTypes({tyOwned, tyRef, tyPtr}).n, getIdent(d.graph.cache, upName)) if upField != nil: @@ -667,9 +669,9 @@ proc closureCreationForIter(iter: PNode; u, iter.info)) else: localError(d.graph.config, iter.info, "internal error: cannot create up reference for iter") - result.add makeClosure(d.graph, iter.sym, vnode, iter.info) + result.add makeClosure(d.graph, d.idgen, iter.sym, vnode, iter.info) -proc accessViaEnvVar(n: PNode; owner: PSym; d: DetectionPass; +proc accessViaEnvVar(n: PNode; owner: PSym; d: var DetectionPass; c: var LiftingPass): PNode = var access = setupEnvVar(owner, d, c, n.info) if optOwnedRefs in d.graph.config.globalOptions: @@ -685,21 +687,21 @@ proc accessViaEnvVar(n: PNode; owner: PSym; d: DetectionPass; proc getStateField*(g: ModuleGraph; owner: PSym): PSym = getHiddenParam(g, owner).typ.skipTypes({tyOwned, tyRef, tyPtr}).n[0].sym -proc liftCapturedVars(n: PNode; owner: PSym; d: DetectionPass; +proc liftCapturedVars(n: PNode; owner: PSym; d: var DetectionPass; c: var LiftingPass): PNode -proc symToClosure(n: PNode; owner: PSym; d: DetectionPass; +proc symToClosure(n: PNode; owner: PSym; d: var DetectionPass; c: var LiftingPass): PNode = let s = n.sym if s == owner: # recursive calls go through (lambda, hiddenParam): let available = getHiddenParam(d.graph, owner) - result = makeClosure(d.graph, s, available.newSymNode, n.info) + result = makeClosure(d.graph, d.idgen, s, available.newSymNode, n.info) elif s.isIterator: result = closureCreationForIter(n, d, c) elif s.skipGenericOwner == owner: # direct dependency, so use the outer's env variable: - result = makeClosure(d.graph, s, setupEnvVar(owner, d, c, n.info), n.info) + result = makeClosure(d.graph, d.idgen, s, setupEnvVar(owner, d, c, n.info), n.info) else: let available = getHiddenParam(d.graph, owner) let wanted = getHiddenParam(d.graph, s).typ @@ -707,7 +709,7 @@ proc symToClosure(n: PNode; owner: PSym; d: DetectionPass; var access = newSymNode(available) while true: if access.typ == wanted: - return makeClosure(d.graph, s, access, n.info) + return makeClosure(d.graph, d.idgen, s, access, n.info) let obj = access.typ.skipTypes({tyOwned, tyRef, tyPtr}) let upField = lookupInRecord(obj.n, getIdent(d.graph.cache, upName)) if upField == nil: @@ -715,7 +717,7 @@ proc symToClosure(n: PNode; owner: PSym; d: DetectionPass; return n access = rawIndirectAccess(access, upField, n.info) -proc liftCapturedVars(n: PNode; owner: PSym; d: DetectionPass; +proc liftCapturedVars(n: PNode; owner: PSym; d: var DetectionPass; c: var LiftingPass): PNode = result = n case n.kind @@ -727,7 +729,7 @@ proc liftCapturedVars(n: PNode; owner: PSym; d: DetectionPass; # echo renderTree(s.getBody, {renderIds}) let oldInContainer = c.inContainer c.inContainer = 0 - var body = transformBody(d.graph, s, cache = false) + var body = transformBody(d.graph, d.idgen, s, cache = false) body = liftCapturedVars(body, s, d, c) if c.envVars.getOrDefault(s.id).isNil: s.transformedBody = body @@ -833,8 +835,9 @@ proc semCaptureSym*(s, owner: PSym) = # since the analysis is not entirely correct, we don't set 'tfCapturesEnv' # here -proc liftIterToProc*(g: ModuleGraph; fn: PSym; body: PNode; ptrType: PType): PNode = - var d = initDetectionPass(g, fn) +proc liftIterToProc*(g: ModuleGraph; fn: PSym; body: PNode; ptrType: PType; + idgen: IdGenerator): PNode = + var d = initDetectionPass(g, fn, idgen) var c = initLiftingPass(fn) # pretend 'fn' is a closure iterator for the analysis: let oldKind = fn.kind @@ -847,7 +850,8 @@ proc liftIterToProc*(g: ModuleGraph; fn: PSym; body: PNode; ptrType: PType): PNo fn.transitionRoutineSymKind(oldKind) fn.typ.callConv = oldCC -proc liftLambdas*(g: ModuleGraph; fn: PSym, body: PNode; tooEarly: var bool): PNode = +proc liftLambdas*(g: ModuleGraph; fn: PSym, body: PNode; tooEarly: var bool; + idgen: IdGenerator): PNode = # XXX backend == backendJs does not suffice! The compiletime stuff needs # the transformation even when compiling to JS ... @@ -862,7 +866,7 @@ proc liftLambdas*(g: ModuleGraph; fn: PSym, body: PNode; tooEarly: var bool): PN result = body tooEarly = true else: - var d = initDetectionPass(g, fn) + var d = initDetectionPass(g, fn, idgen) detectCapturedVars(body, fn, d) if not d.somethingToDo and fn.isIterator: addClosureParam(d, fn, body.info) @@ -886,7 +890,7 @@ proc liftLambdasForTopLevel*(module: PSym, body: PNode): PNode = # ------------------- iterator transformation -------------------------------- -proc liftForLoop*(g: ModuleGraph; body: PNode; owner: PSym): PNode = +proc liftForLoop*(g: ModuleGraph; body: PNode; idgen: IdGenerator; owner: PSym): PNode = # problem ahead: the iterator could be invoked indirectly, but then # we don't know what environment to create here: # @@ -931,7 +935,7 @@ proc liftForLoop*(g: ModuleGraph; body: PNode; owner: PSym): PNode = let iter = op.sym let hp = getHiddenParam(g, iter) - env = newSym(skLet, iter.name, owner, body.info) + env = newSym(skLet, iter.name, nextId(idgen), owner, body.info) env.typ = hp.typ env.flags = hp.flags @@ -940,7 +944,7 @@ proc liftForLoop*(g: ModuleGraph; body: PNode; owner: PSym): PNode = result.add(v) # add 'new' statement: result.add(newCall(getSysSym(g, env.info, "internalNew"), env.newSymNode)) - createTypeBoundOpsLL(g, env.typ, body.info, owner) + createTypeBoundOpsLL(g, env.typ, body.info, idgen, owner) elif op.kind == nkStmtListExpr: let closure = op.lastSon @@ -966,7 +970,7 @@ proc liftForLoop*(g: ModuleGraph; body: PNode; owner: PSym): PNode = vpart.add newNodeI(nkEmpty, body.info) # no explicit type if not env.isNil: - call[0] = makeClosure(g, call[0].sym, env.newSymNode, body.info) + call[0] = makeClosure(g, idgen, call[0].sym, env.newSymNode, body.info) vpart.add call v2.add vpart diff --git a/compiler/liftdestructors.nim b/compiler/liftdestructors.nim index 2735fb417..30094875c 100644 --- a/compiler/liftdestructors.nim +++ b/compiler/liftdestructors.nim @@ -27,12 +27,14 @@ type canRaise: bool filterDiscriminator: PSym # we generating destructor for case branch c: PContext # c can be nil, then we are called from lambdalifting! + idgen: IdGenerator proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) proc produceSym(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp; - info: TLineInfo): PSym + info: TLineInfo; idgen: IdGenerator): PSym -proc createTypeBoundOps*(g: ModuleGraph; c: PContext; orig: PType; info: TLineInfo) +proc createTypeBoundOps*(g: ModuleGraph; c: PContext; orig: PType; info: TLineInfo; + idgen: IdGenerator) proc at(a, i: PNode, elemType: PType): PNode = result = newNodeI(nkBracketExpr, a.info, 2) @@ -73,12 +75,12 @@ proc defaultOp(c: var TLiftCtx; t: PType; body, x, y: PNode) = call.typ = t body.add newAsgnStmt(x, call) -proc genAddr(g: ModuleGraph; x: PNode): PNode = +proc genAddr(c: var TLiftCtx; x: PNode): PNode = if x.kind == nkHiddenDeref: - checkSonsLen(x, 1, g.config) + checkSonsLen(x, 1, c.g.config) result = x[0] else: - result = newNodeIT(nkHiddenAddr, x.info, makeVarType(x.typ.owner, x.typ)) + result = newNodeIT(nkHiddenAddr, x.info, makeVarType(x.typ.owner, x.typ, c.idgen)) result.add x proc genWhileLoop(c: var TLiftCtx; i, dest: PNode): PNode = @@ -92,11 +94,11 @@ proc genWhileLoop(c: var TLiftCtx; i, dest: PNode): PNode = proc genIf(c: var TLiftCtx; cond, action: PNode): PNode = result = newTree(nkIfStmt, newTree(nkElifBranch, cond, action)) -proc genContainerOf(c: TLiftCtx; objType: PType, field, x: PSym): PNode = +proc genContainerOf(c: var TLiftCtx; objType: PType, field, x: PSym): PNode = # generate: cast[ptr ObjType](cast[int](addr(x)) - offsetOf(objType.field)) let intType = getSysType(c.g, unknownLineInfo, tyInt) - let addrOf = newNodeIT(nkAddr, c.info, makePtrType(x.owner, x.typ)) + let addrOf = newNodeIT(nkAddr, c.info, makePtrType(x.owner, x.typ, c.idgen)) addrOf.add newDeref(newSymNode(x)) let castExpr1 = newNodeIT(nkCast, c.info, intType) castExpr1.add newNodeIT(nkType, c.info, intType) @@ -113,7 +115,7 @@ proc genContainerOf(c: TLiftCtx; objType: PType, field, x: PSym): PNode = minusExpr.typ = intType minusExpr.add offsetOf - let objPtr = makePtrType(objType.owner, objType) + let objPtr = makePtrType(objType.owner, objType, c.idgen) result = newNodeIT(nkCast, c.info, objPtr) result.add newNodeIT(nkType, c.info, objPtr) result.add minusExpr @@ -121,7 +123,7 @@ proc genContainerOf(c: TLiftCtx; objType: PType, field, x: PSym): PNode = proc destructorCall(c: var TLiftCtx; op: PSym; x: PNode): PNode = var destroy = newNodeIT(nkCall, x.info, op.typ[0]) destroy.add(newSymNode(op)) - destroy.add genAddr(c.g, x) + destroy.add genAddr(c, x) if sfNeverRaises notin op.flags: c.canRaise = true if c.addMemReset: @@ -217,7 +219,7 @@ proc fillBodyObjT(c: var TLiftCtx; t: PType, body, x, y: PNode) = # for every field (dependent on dest.kind): # `=` dest.field, src.field # =destroy(blob) - var temp = newSym(skTemp, getIdent(c.g.cache, lowerings.genPrefix), c.fn, c.info) + var temp = newSym(skTemp, getIdent(c.g.cache, lowerings.genPrefix), nextId c.idgen, c.fn, c.info) temp.typ = x.typ incl(temp.flags, sfFromGeneric) var v = newNodeI(nkVarSection, c.info) @@ -251,7 +253,7 @@ proc newHookCall(c: var TLiftCtx; op: PSym; x, y: PNode): PNode = if sfNeverRaises notin op.flags: c.canRaise = true if op.typ.sons[1].kind == tyVar: - result.add genAddr(c.g, x) + result.add genAddr(c, x) else: result.add x if y != nil: @@ -311,7 +313,7 @@ proc considerAsgnOrSink(c: var TLiftCtx; t: PType; body, x, y: PNode; else: op = field if op == nil: - op = produceSym(c.g, c.c, t, c.kind, c.info) + op = produceSym(c.g, c.c, t, c.kind, c.info, c.idgen) if sfError in op.flags: incl c.fn.flags, sfError #else: @@ -340,7 +342,7 @@ proc addDestructorCall(c: var TLiftCtx; orig: PType; body, x: PNode) = t.attachedOps[attachedDestructor] = op if op == nil and (useNoGc(c, t) or requiresDestructor(c, t)): - op = produceSym(c.g, c.c, t, attachedDestructor, c.info) + op = produceSym(c.g, c.c, t, attachedDestructor, c.info, c.idgen) doAssert op != nil doAssert op == t.destructor @@ -381,7 +383,7 @@ proc considerUserDefinedOp(c: var TLiftCtx; t: PType; body, x, y: PNode): bool = result = true proc declareCounter(c: var TLiftCtx; body: PNode; first: BiggestInt): PNode = - var temp = newSym(skTemp, getIdent(c.g.cache, lowerings.genPrefix), c.fn, c.info) + var temp = newSym(skTemp, getIdent(c.g.cache, lowerings.genPrefix), nextId(c.idgen), c.fn, c.info) temp.typ = getSysType(c.g, body.info, tyInt) incl(temp.flags, sfFromGeneric) @@ -452,7 +454,7 @@ proc fillSeqOp(c: var TLiftCtx; t: PType; body, x, y: PNode) = body.add genBuiltin(c.g, mDestroy, "destroy", x) proc useSeqOrStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) = - createTypeBoundOps(c.g, c.c, t, body.info) + createTypeBoundOps(c.g, c.c, t, body.info, c.idgen) # recursions are tricky, so we might need to forward the generated # operation here: var t = t @@ -493,7 +495,7 @@ proc useSeqOrStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) = proc fillStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) = case c.kind of attachedAsgn, attachedDeepCopy: - body.add callCodegenProc(c.g, "nimAsgnStrV2", c.info, genAddr(c.g, x), y) + body.add callCodegenProc(c.g, "nimAsgnStrV2", c.info, genAddr(c, x), y) of attachedSink: let moveCall = genBuiltin(c.g, mMove, "move", x) moveCall.add y @@ -509,7 +511,7 @@ proc atomicRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) = var actions = newNodeI(nkStmtList, c.info) let elemType = t.lastSon - createTypeBoundOps(c.g, c.c, elemType, c.info) + createTypeBoundOps(c.g, c.c, elemType, c.info, c.idgen) if isFinal(elemType): addDestructorCall(c, elemType, actions, genDeref(x, nkDerefExpr)) @@ -548,10 +550,10 @@ proc atomicRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) = if isFinal(elemType): let typInfo = genBuiltin(c.g, mGetTypeInfoV2, "getTypeInfoV2", newNodeIT(nkType, x.info, elemType)) typInfo.typ = getSysType(c.g, c.info, tyPointer) - body.add callCodegenProc(c.g, "nimTraceRef", c.info, genAddrOf(x), typInfo, y) + body.add callCodegenProc(c.g, "nimTraceRef", c.info, genAddrOf(x, c.idgen), typInfo, y) else: # If the ref is polymorphic we have to account for this - body.add callCodegenProc(c.g, "nimTraceRefDyn", c.info, genAddrOf(x), y) + body.add callCodegenProc(c.g, "nimTraceRefDyn", c.info, genAddrOf(x, c.idgen), y) of attachedDispose: # this is crucial! dispose is like =destroy but we don't follow refs # as that is dealt within the cycle collector. @@ -593,7 +595,7 @@ proc atomicClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) = body.add genIf(c, cond, actions) of attachedDeepCopy: assert(false, "cannot happen") of attachedTrace: - body.add callCodegenProc(c.g, "nimTraceRefDyn", c.info, genAddrOf(xenv), y) + body.add callCodegenProc(c.g, "nimTraceRefDyn", c.info, genAddrOf(xenv, c.idgen), y) of attachedDispose: # this is crucial! dispose is like =destroy but we don't follow refs # as that is dealt within the cycle collector. @@ -788,28 +790,30 @@ proc fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode) = of tyOptDeprecated: doAssert false proc produceSymDistinctType(g: ModuleGraph; c: PContext; typ: PType; - kind: TTypeAttachedOp; info: TLineInfo): PSym = + kind: TTypeAttachedOp; info: TLineInfo; + idgen: IdGenerator): PSym = assert typ.kind == tyDistinct let baseType = typ[0] if baseType.attachedOps[kind] == nil: - discard produceSym(g, c, baseType, kind, info) + discard produceSym(g, c, baseType, kind, info, idgen) typ.attachedOps[kind] = baseType.attachedOps[kind] result = typ.attachedOps[kind] proc symPrototype(g: ModuleGraph; typ: PType; owner: PSym; kind: TTypeAttachedOp; - info: TLineInfo): PSym = + info: TLineInfo; idgen: IdGenerator): PSym = let procname = getIdent(g.cache, AttachedOpToStr[kind]) - result = newSym(skProc, procname, owner, info) - let dest = newSym(skParam, getIdent(g.cache, "dest"), result, info) - let src = newSym(skParam, getIdent(g.cache, if kind == attachedTrace: "env" else: "src"), result, info) - dest.typ = makeVarType(typ.owner, typ) + result = newSym(skProc, procname, nextId(idgen), owner, info) + let dest = newSym(skParam, getIdent(g.cache, "dest"), nextId(idgen), result, info) + let src = newSym(skParam, getIdent(g.cache, if kind == attachedTrace: "env" else: "src"), + nextId(idgen), result, info) + dest.typ = makeVarType(typ.owner, typ, idgen) if kind == attachedTrace: src.typ = getSysType(g, info, tyPointer) else: src.typ = typ - result.typ = newProcType(info, owner) + result.typ = newProcType(info, nextId(idgen), owner) result.typ.addParam dest if kind notin {attachedDestructor, attachedDispose}: result.typ.addParam src @@ -825,15 +829,15 @@ proc symPrototype(g: ModuleGraph; typ: PType; owner: PSym; kind: TTypeAttachedOp proc produceSym(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp; - info: TLineInfo): PSym = + info: TLineInfo; idgen: IdGenerator): PSym = if typ.kind == tyDistinct: - return produceSymDistinctType(g, c, typ, kind, info) + return produceSymDistinctType(g, c, typ, kind, info, idgen) result = typ.attachedOps[kind] if result == nil: - result = symPrototype(g, typ, typ.owner, kind, info) + result = symPrototype(g, typ, typ.owner, kind, info, idgen) - var a = TLiftCtx(info: info, g: g, kind: kind, c: c, asgnForType:typ) + var a = TLiftCtx(info: info, g: g, kind: kind, c: c, asgnForType:typ, idgen: idgen) a.fn = result let dest = result.typ.n[1].sym @@ -866,18 +870,19 @@ proc produceSym(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp; if not a.canRaise: incl result.flags, sfNeverRaises -proc produceDestructorForDiscriminator*(g: ModuleGraph; typ: PType; field: PSym, info: TLineInfo): PSym = +proc produceDestructorForDiscriminator*(g: ModuleGraph; typ: PType; field: PSym, + info: TLineInfo; idgen: IdGenerator): PSym = assert(typ.skipTypes({tyAlias, tyGenericInst}).kind == tyObject) - result = symPrototype(g, field.typ, typ.owner, attachedDestructor, info) - var a = TLiftCtx(info: info, g: g, kind: attachedDestructor, asgnForType: typ) + result = symPrototype(g, field.typ, typ.owner, attachedDestructor, info, idgen) + var a = TLiftCtx(info: info, g: g, kind: attachedDestructor, asgnForType: typ, idgen: idgen) a.fn = result a.asgnForType = typ a.filterDiscriminator = field a.addMemReset = true let discrimantDest = result.typ.n[1].sym - let dst = newSym(skVar, getIdent(g.cache, "dest"), result, info) - dst.typ = makePtrType(typ.owner, typ) + let dst = newSym(skVar, getIdent(g.cache, "dest"), nextId(idgen), result, info) + dst.typ = makePtrType(typ.owner, typ, idgen) let dstSym = newSymNode(dst) let d = newDeref(dstSym) let v = newNodeI(nkVarSection, info) @@ -891,12 +896,12 @@ proc produceDestructorForDiscriminator*(g: ModuleGraph; typ: PType; field: PSym, template liftTypeBoundOps*(c: PContext; typ: PType; info: TLineInfo) = discard "now a nop" -proc patchBody(g: ModuleGraph; c: PContext; n: PNode; info: TLineInfo) = +proc patchBody(g: ModuleGraph; c: PContext; n: PNode; info: TLineInfo; idgen: IdGenerator) = if n.kind in nkCallKinds: if n[0].kind == nkSym and n[0].sym.magic == mDestroy: let t = n[1].typ.skipTypes(abstractVar) if t.destructor == nil: - discard produceSym(g, c, t, attachedDestructor, info) + discard produceSym(g, c, t, attachedDestructor, info, idgen) if t.destructor != nil: if t.destructor.ast[genericParamsPos].kind != nkEmpty: @@ -904,9 +909,9 @@ proc patchBody(g: ModuleGraph; c: PContext; n: PNode; info: TLineInfo) = if t.destructor.magic == mDestroy: internalError(g.config, info, "patching mDestroy with mDestroy?") n[0] = newSymNode(t.destructor) - for x in n: patchBody(g, c, x, info) + for x in n: patchBody(g, c, x, info, idgen) -template inst(field, t) = +template inst(field, t, idgen) = if field.ast != nil and field.ast[genericParamsPos].kind != nkEmpty: if t.typeInst != nil: var a: TLiftCtx @@ -914,17 +919,19 @@ template inst(field, t) = a.g = g a.kind = k a.c = c + a.idgen = idgen field = instantiateGeneric(a, field, t, t.typeInst) if field.ast != nil: - patchBody(g, c, field.ast, info) + patchBody(g, c, field.ast, info, a.idgen) else: localError(g.config, info, "unresolved generic parameter") proc isTrival(s: PSym): bool {.inline.} = s == nil or (s.ast != nil and s.ast[bodyPos].len == 0) -proc createTypeBoundOps(g: ModuleGraph; c: PContext; orig: PType; info: TLineInfo) = +proc createTypeBoundOps(g: ModuleGraph; c: PContext; orig: PType; info: TLineInfo; + idgen: IdGenerator) = ## In the semantic pass this is called in strategic places ## to ensure we lift assignment, destructors and moves properly. ## The later 'injectdestructors' pass depends on it. @@ -959,14 +966,14 @@ proc createTypeBoundOps(g: ModuleGraph; c: PContext; orig: PType; info: TLineInf for k in attachedDestructor..lastAttached: generics[k] = canon.attachedOps[k] != nil if not generics[k]: - canon.attachedOps[k] = symPrototype(g, canon, canon.owner, k, info) + canon.attachedOps[k] = symPrototype(g, canon, canon.owner, k, info, idgen) # we generate the destructor first so that other operators can depend on it: for k in attachedDestructor..lastAttached: if not generics[k]: - discard produceSym(g, c, canon, k, info) + discard produceSym(g, c, canon, k, info, idgen) else: - inst(canon.attachedOps[k], canon) + inst(canon.attachedOps[k], canon, idgen) if canon != orig: orig.attachedOps[k] = canon.attachedOps[k] diff --git a/compiler/liftlocals.nim b/compiler/liftlocals.nim index 672dca5d9..0b46c73a2 100644 --- a/compiler/liftlocals.nim +++ b/compiler/liftlocals.nim @@ -21,13 +21,14 @@ type partialParam: PSym objType: PType cache: IdentCache + idgen: IdGenerator proc interestingVar(s: PSym): bool {.inline.} = result = s.kind in {skVar, skLet, skTemp, skForVar, skResult} and sfGlobal notin s.flags proc lookupOrAdd(c: var Ctx; s: PSym; info: TLineInfo): PNode = - let field = addUniqueField(c.objType, s, c.cache) + let field = addUniqueField(c.objType, s, c.cache, c.idgen) var deref = newNodeI(nkHiddenDeref, info) deref.typ = c.objType deref.add(newSymNode(c.partialParam, info)) @@ -53,7 +54,8 @@ proc lookupParam(params, dest: PNode): PSym = if params[i].kind == nkSym and params[i].sym.name.id == dest.ident.id: return params[i].sym -proc liftLocalsIfRequested*(prc: PSym; n: PNode; cache: IdentCache; conf: ConfigRef): PNode = +proc liftLocalsIfRequested*(prc: PSym; n: PNode; cache: IdentCache; conf: ConfigRef; + idgen: IdGenerator): PNode = let liftDest = getPragmaVal(prc.ast, wLiftLocals) if liftDest == nil: return n let partialParam = lookupParam(prc.typ.n, liftDest) @@ -65,7 +67,7 @@ proc liftLocalsIfRequested*(prc: PSym; n: PNode; cache: IdentCache; conf: Config if objType.kind != tyObject or tfPartial notin objType.flags: localError(conf, liftDest.info, "parameter '$1' is not a pointer to a partial object" % $liftDest) return n - var c = Ctx(partialParam: partialParam, objType: objType, cache: cache) + var c = Ctx(partialParam: partialParam, objType: objType, cache: cache, idgen: idgen) let w = newTree(nkStmtList, n) liftLocals(w, 0, c) result = w[0] diff --git a/compiler/lookups.nim b/compiler/lookups.nim index 744f77cf8..0a6a0b950 100644 --- a/compiler/lookups.nim +++ b/compiler/lookups.nim @@ -135,7 +135,7 @@ proc errorSym*(c: PContext, n: PNode): PSym = considerQuotedIdent(c, m) else: getIdent(c.cache, "err:" & renderTree(m)) - result = newSym(skError, ident, getCurrOwner(c), n.info, {}) + result = newSym(skError, ident, nextId(c.idgen), getCurrOwner(c), n.info, {}) result.typ = errorType(c) incl(result.flags, sfDiscardable) # pretend it's imported from some unknown module to prevent cascading errors: diff --git a/compiler/lowerings.nim b/compiler/lowerings.nim index 2d96f8a60..40d61b779 100644 --- a/compiler/lowerings.nim +++ b/compiler/lowerings.nim @@ -66,12 +66,13 @@ proc newFastMoveStmt*(g: ModuleGraph, le, ri: PNode): PNode = result[1].add newSymNode(getSysMagic(g, ri.info, "move", mMove)) result[1].add ri -proc lowerTupleUnpacking*(g: ModuleGraph; n: PNode; owner: PSym): PNode = +proc lowerTupleUnpacking*(g: ModuleGraph; n: PNode; idgen: IdGenerator; owner: PSym): PNode = assert n.kind == nkVarTuple let value = n.lastSon result = newNodeI(nkStmtList, n.info) - var temp = newSym(skTemp, getIdent(g.cache, genPrefix), owner, value.info, g.config.options) + var temp = newSym(skTemp, getIdent(g.cache, genPrefix), nextId(idgen), + owner, value.info, g.config.options) temp.typ = skipTypes(value.typ, abstractInst) incl(temp.flags, sfFromGeneric) @@ -85,12 +86,13 @@ proc lowerTupleUnpacking*(g: ModuleGraph; n: PNode; owner: PSym): PNode = if n[i].kind == nkSym: v.addVar(n[i], val) else: result.add newAsgnStmt(n[i], val) -proc evalOnce*(g: ModuleGraph; value: PNode; owner: PSym): PNode = +proc evalOnce*(g: ModuleGraph; value: PNode; idgen: IdGenerator; owner: PSym): PNode = ## Turns (value) into (let tmp = value; tmp) so that 'value' can be re-used ## freely, multiple times. This is frequently required and such a builtin would also be ## handy to have in macros.nim. The value that can be reused is 'result.lastSon'! result = newNodeIT(nkStmtListExpr, value.info, value.typ) - var temp = newSym(skTemp, getIdent(g.cache, genPrefix), owner, value.info, g.config.options) + var temp = newSym(skTemp, getIdent(g.cache, genPrefix), nextId(idgen), + owner, value.info, g.config.options) temp.typ = skipTypes(value.typ, abstractInst) incl(temp.flags, sfFromGeneric) @@ -111,11 +113,11 @@ proc newTupleAccessRaw*(tup: PNode, i: int): PNode = proc newTryFinally*(body, final: PNode): PNode = result = newTree(nkHiddenTryStmt, body, newTree(nkFinally, final)) -proc lowerTupleUnpackingForAsgn*(g: ModuleGraph; n: PNode; owner: PSym): PNode = +proc lowerTupleUnpackingForAsgn*(g: ModuleGraph; n: PNode; idgen: IdGenerator; owner: PSym): PNode = let value = n.lastSon result = newNodeI(nkStmtList, n.info) - var temp = newSym(skTemp, getIdent(g.cache, "_"), owner, value.info, owner.options) + var temp = newSym(skTemp, getIdent(g.cache, "_"), nextId(idgen), owner, value.info, owner.options) var v = newNodeI(nkLetSection, value.info) let tempAsNode = newSymNode(temp) #newIdentNode(getIdent(genPrefix & $temp.id), value.info) @@ -130,10 +132,10 @@ proc lowerTupleUnpackingForAsgn*(g: ModuleGraph; n: PNode; owner: PSym): PNode = for i in 0..<lhs.len: result.add newAsgnStmt(lhs[i], newTupleAccessRaw(tempAsNode, i)) -proc lowerSwap*(g: ModuleGraph; n: PNode; owner: PSym): PNode = +proc lowerSwap*(g: ModuleGraph; n: PNode; idgen: IdGenerator; owner: PSym): PNode = result = newNodeI(nkStmtList, n.info) # note: cannot use 'skTemp' here cause we really need the copy for the VM :-( - var temp = newSym(skVar, getIdent(g.cache, genPrefix), owner, n.info, owner.options) + var temp = newSym(skVar, getIdent(g.cache, genPrefix), nextId(idgen), owner, n.info, owner.options) temp.typ = n[1].typ incl(temp.flags, sfFromGeneric) @@ -150,8 +152,8 @@ proc lowerSwap*(g: ModuleGraph; n: PNode; owner: PSym): PNode = result.add newFastAsgnStmt(n[1], n[2]) result.add newFastAsgnStmt(n[2], tempAsNode) -proc createObj*(g: ModuleGraph; owner: PSym, info: TLineInfo; final=true): PType = - result = newType(tyObject, owner) +proc createObj*(g: ModuleGraph; idgen: IdGenerator; owner: PSym, info: TLineInfo; final=true): PType = + result = newType(tyObject, nextId(idgen), owner) if final: rawAddSon(result, nil) incl result.flags, tfFinal @@ -159,6 +161,7 @@ proc createObj*(g: ModuleGraph; owner: PSym, info: TLineInfo; final=true): PType rawAddSon(result, getCompilerProc(g, "RootObj").typ) result.n = newNodeI(nkRecList, info) let s = newSym(skType, getIdent(g.cache, "Env_" & toFilename(g.config, info) & "_" & $owner.name.s), + nextId(idgen), owner, info, owner.options) incl s.flags, sfAnon s.typ = result @@ -196,7 +199,7 @@ proc rawDirectAccess*(obj, field: PSym): PNode = result.add newSymNode(field) result.typ = field.typ -proc lookupInRecord(n: PNode, id: int): PSym = +proc lookupInRecord(n: PNode, id: ItemId): PSym = result = nil case n.kind of nkRecList: @@ -214,16 +217,16 @@ proc lookupInRecord(n: PNode, id: int): PSym = if result != nil: return else: discard of nkSym: - if n.sym.id == -abs(id): result = n.sym + if n.sym.itemId.module == id.module and n.sym.itemId.item == -abs(id.item): result = n.sym else: discard -proc addField*(obj: PType; s: PSym; cache: IdentCache) = +proc addField*(obj: PType; s: PSym; cache: IdentCache; idgen: IdGenerator) = # because of 'gensym' support, we have to mangle the name with its ID. # This is hacky but the clean solution is much more complex than it looks. - var field = newSym(skField, getIdent(cache, s.name.s & $obj.n.len), s.owner, s.info, - s.options) - field.id = -s.id - let t = skipIntLit(s.typ) + var field = newSym(skField, getIdent(cache, s.name.s & $obj.n.len), + nextId(idgen), s.owner, s.info, s.options) + field.itemId = ItemId(module: s.itemId.module, item: -s.itemId.item) + let t = skipIntLit(s.typ, idgen) field.typ = t assert t.kind != tyTyped propagateToOwner(obj, t) @@ -232,13 +235,13 @@ proc addField*(obj: PType; s: PSym; cache: IdentCache) = obj.n.add newSymNode(field) fieldCheck() -proc addUniqueField*(obj: PType; s: PSym; cache: IdentCache): PSym {.discardable.} = - result = lookupInRecord(obj.n, s.id) +proc addUniqueField*(obj: PType; s: PSym; cache: IdentCache; idgen: IdGenerator): PSym {.discardable.} = + result = lookupInRecord(obj.n, s.itemId) if result == nil: - var field = newSym(skField, getIdent(cache, s.name.s & $obj.n.len), s.owner, s.info, - s.options) - field.id = -s.id - let t = skipIntLit(s.typ) + var field = newSym(skField, getIdent(cache, s.name.s & $obj.n.len), nextId(idgen), + s.owner, s.info, s.options) + field.itemId = ItemId(module: s.itemId.module, item: -s.itemId.item) + let t = skipIntLit(s.typ, idgen) field.typ = t assert t.kind != tyTyped propagateToOwner(obj, t) @@ -248,13 +251,13 @@ proc addUniqueField*(obj: PType; s: PSym; cache: IdentCache): PSym {.discardable proc newDotExpr*(obj, b: PSym): PNode = result = newNodeI(nkDotExpr, obj.info) - let field = lookupInRecord(obj.typ.n, b.id) + let field = lookupInRecord(obj.typ.n, b.itemId) assert field != nil, b.name.s result.add newSymNode(obj) result.add newSymNode(field) result.typ = field.typ -proc indirectAccess*(a: PNode, b: int, info: TLineInfo): PNode = +proc indirectAccess*(a: PNode, b: ItemId, info: TLineInfo): PNode = # returns a[].b as a node var deref = newNodeI(nkHiddenDeref, info) deref.typ = a.typ.skipTypes(abstractInst)[0] @@ -306,7 +309,7 @@ proc getFieldFromObj*(t: PType; v: PSym): PSym = var t = t while true: assert t.kind == tyObject - result = lookupInRecord(t.n, v.id) + result = lookupInRecord(t.n, v.itemId) if result != nil: break t = t[0] if t == nil: break @@ -314,15 +317,15 @@ proc getFieldFromObj*(t: PType; v: PSym): PSym = proc indirectAccess*(a: PNode, b: PSym, info: TLineInfo): PNode = # returns a[].b as a node - result = indirectAccess(a, b.id, info) + result = indirectAccess(a, b.itemId, info) proc indirectAccess*(a, b: PSym, info: TLineInfo): PNode = result = indirectAccess(newSymNode(a), b, info) -proc genAddrOf*(n: PNode, typeKind = tyPtr): PNode = +proc genAddrOf*(n: PNode; idgen: IdGenerator; typeKind = tyPtr): PNode = result = newNodeI(nkAddr, n.info, 1) result[0] = n - result.typ = newType(typeKind, n.typ.owner) + result.typ = newType(typeKind, nextId(idgen), n.typ.owner) result.typ.rawAddSon(n.typ) proc genDeref*(n: PNode; k = nkHiddenDeref): PNode = diff --git a/compiler/magicsys.nim b/compiler/magicsys.nim index 604c5b537..71003371e 100644 --- a/compiler/magicsys.nim +++ b/compiler/magicsys.nim @@ -21,7 +21,7 @@ proc registerSysType*(g: ModuleGraph; t: PType) = if g.sysTypes[t.kind] == nil: g.sysTypes[t.kind] = t proc newSysType(g: ModuleGraph; kind: TTypeKind, size: int): PType = - result = newType(kind, g.systemModule) + result = newType(kind, nextId(g.idgen), g.systemModule) result.size = size result.align = size.int16 @@ -29,8 +29,8 @@ proc getSysSym*(g: ModuleGraph; info: TLineInfo; name: string): PSym = result = strTableGet(g.systemModule.tab, getIdent(g.cache, name)) if result == nil: localError(g.config, info, "system module needs: " & name) - result = newSym(skError, getIdent(g.cache, name), g.systemModule, g.systemModule.info, {}) - result.typ = newType(tyError, g.systemModule) + result = newSym(skError, getIdent(g.cache, name), nextId(g.idgen), g.systemModule, g.systemModule.info, {}) + result.typ = newType(tyError, nextId(g.idgen), g.systemModule) if result.kind == skAlias: result = result.owner proc getSysMagic*(g: ModuleGraph; info: TLineInfo; name: string, m: TMagic): PSym = @@ -45,8 +45,8 @@ proc getSysMagic*(g: ModuleGraph; info: TLineInfo; name: string, m: TMagic): PSy r = nextIdentIter(ti, g.systemModule.tab) if result != nil: return result localError(g.config, info, "system module needs: " & name) - result = newSym(skError, id, g.systemModule, g.systemModule.info, {}) - result.typ = newType(tyError, g.systemModule) + result = newSym(skError, id, nextId(g.idgen), g.systemModule, g.systemModule.info, {}) + result.typ = newType(tyError, nextId(g.idgen), g.systemModule) proc sysTypeFromName*(g: ModuleGraph; info: TLineInfo; name: string): PType = result = getSysSym(g, info, name).typ @@ -101,12 +101,12 @@ proc getIntLitType*(g: ModuleGraph; literal: PNode): PType = result = g.intTypeCache[value.int] if result == nil: let ti = getSysType(g, literal.info, tyInt) - result = copyType(ti, ti.owner, false) + result = copyType(ti, nextId(g.idgen), ti.owner) result.n = literal g.intTypeCache[value.int] = result else: let ti = getSysType(g, literal.info, tyInt) - result = copyType(ti, ti.owner, false) + result = copyType(ti, nextId(g.idgen), ti.owner) result.n = literal proc getFloatLitType*(g: ModuleGraph; literal: PNode): PType = @@ -114,17 +114,17 @@ proc getFloatLitType*(g: ModuleGraph; literal: PNode): PType = result = newSysType(g, tyFloat, size=8) result.n = literal -proc skipIntLit*(t: PType): PType {.inline.} = +proc skipIntLit*(t: PType; id: IdGenerator): PType {.inline.} = if t.n != nil and t.kind in {tyInt, tyFloat}: - result = copyType(t, t.owner, false) + result = copyType(t, nextId(id), t.owner) result.n = nil else: result = t -proc addSonSkipIntLit*(father, son: PType) = +proc addSonSkipIntLit*(father, son: PType; id: IdGenerator) = when not defined(nimNoNilSeqs): if isNil(father.sons): father.sons = @[] - let s = son.skipIntLit + let s = son.skipIntLit(id) father.sons.add(s) propagateToOwner(father, s) @@ -181,13 +181,13 @@ proc resetNimScriptSymbols*(g: ModuleGraph) = initStrTable(g.exposed) proc getMagicEqSymForType*(g: ModuleGraph; t: PType; info: TLineInfo): PSym = case t.kind of tyInt, tyInt8, tyInt16, tyInt32, tyInt64, - tyUInt, tyUInt8, tyUInt16, tyUInt32, tyUInt64: + tyUInt, tyUInt8, tyUInt16, tyUInt32, tyUInt64: result = getSysMagic(g, info, "==", mEqI) - of tyEnum: + of tyEnum: result = getSysMagic(g, info, "==", mEqEnum) - of tyBool: + of tyBool: result = getSysMagic(g, info, "==", mEqB) - of tyRef, tyPtr, tyPointer: + of tyRef, tyPtr, tyPointer: result = getSysMagic(g, info, "==", mEqRef) of tyString: result = getSysMagic(g, info, "==", mEqStr) diff --git a/compiler/main.nim b/compiler/main.nim index d85aa43dc..210933231 100644 --- a/compiler/main.nim +++ b/compiler/main.nim @@ -17,7 +17,7 @@ import condsyms, times, sem, idents, passes, extccomp, cgen, json, nversion, - platform, nimconf, passaux, depends, vm, idgen, + platform, nimconf, passaux, depends, vm, modules, modulegraphs, tables, rod, lineinfos, pathutils, vmprofiler @@ -137,12 +137,8 @@ proc commandInteractive(graph: ModuleGraph) = else: var m = graph.makeStdinModule() incl(m.flags, sfMainModule) - processModule(graph, m, llStreamOpenStdIn()) - -const evalPasses = [verbosePass, semPass, evalPass] - -proc evalNim(graph: ModuleGraph; nodes: PNode, module: PSym) = - carryPasses(graph, nodes, module, evalPasses) + var idgen = IdGenerator(module: m.itemId.module, item: m.itemId.item) + processModule(graph, m, idgen, llStreamOpenStdIn()) proc commandScan(cache: IdentCache, config: ConfigRef) = var f = addFileExt(AbsoluteFile mainCommandArg(config), NimExt) @@ -173,7 +169,6 @@ proc mainCommand*(graph: ModuleGraph) = clearPasses(graph) conf.lastCmdTime = epochTime() conf.searchPaths.add(conf.libpath) - setId(100) proc customizeForBackend(backend: TBackend) = ## Sets backend specific options but don't compile to backend yet in @@ -219,7 +214,7 @@ proc mainCommand*(graph: ModuleGraph) = else: wantMainModule(conf) conf.cmd = cmdDoc - loadConfigs(DocConfig, cache, conf) + loadConfigs(DocConfig, cache, conf, graph.idgen) defineSymbol(conf.symbols, "nimdoc") body @@ -277,14 +272,14 @@ proc mainCommand*(graph: ModuleGraph) = quit "compiler wasn't built with documentation generator" else: conf.cmd = cmdRst2html - loadConfigs(DocConfig, cache, conf) + loadConfigs(DocConfig, cache, conf, graph.idgen) commandRst2Html(cache, conf) of "rst2tex": when defined(leanCompiler): quit "compiler wasn't built with documentation generator" else: conf.cmd = cmdRst2tex - loadConfigs(DocTexConfig, cache, conf) + loadConfigs(DocTexConfig, cache, conf, graph.idgen) commandRst2TeX(cache, conf) of "jsondoc0": docLikeCmd commandJson(cache, conf) of "jsondoc2", "jsondoc": docLikeCmd commandDoc2(graph, true) diff --git a/compiler/modulegraphs.nim b/compiler/modulegraphs.nim index da2a222a4..9e7a487cf 100644 --- a/compiler/modulegraphs.nim +++ b/compiler/modulegraphs.nim @@ -74,11 +74,13 @@ type globalDestructors*: seq[PNode] strongSemCheck*: proc (graph: ModuleGraph; owner: PSym; body: PNode) {.nimcall.} compatibleProps*: proc (graph: ModuleGraph; formal, actual: PType): bool {.nimcall.} + idgen*: IdGenerator TPassContext* = object of RootObj # the pass's context + idgen*: IdGenerator PPassContext* = ref TPassContext - TPassOpen* = proc (graph: ModuleGraph; module: PSym): PPassContext {.nimcall.} + TPassOpen* = proc (graph: ModuleGraph; module: PSym; idgen: IdGenerator): PPassContext {.nimcall.} TPassClose* = proc (graph: ModuleGraph; p: PPassContext, n: PNode): PNode {.nimcall.} TPassProcess* = proc (p: PPassContext, topLevelStmt: PNode): PNode {.nimcall.} @@ -165,12 +167,13 @@ proc stopCompile*(g: ModuleGraph): bool {.inline.} = result = g.doStopCompile != nil and g.doStopCompile() proc createMagic*(g: ModuleGraph; name: string, m: TMagic): PSym = - result = newSym(skProc, getIdent(g.cache, name), nil, unknownLineInfo, {}) + result = newSym(skProc, getIdent(g.cache, name), nextId(g.idgen), nil, unknownLineInfo, {}) result.magic = m result.flags = {sfNeverRaises} proc newModuleGraph*(cache: IdentCache; config: ConfigRef): ModuleGraph = result = ModuleGraph() + result.idgen = IdGenerator(module: -1'i32, item: 0'i32) initStrTable(result.packageSyms) result.deps = initIntSet() result.importDeps = initTable[FileIndex, seq[FileIndex]]() diff --git a/compiler/modules.nim b/compiler/modules.nim index 8c5b86ea4..87a6bc507 100644 --- a/compiler/modules.nim +++ b/compiler/modules.nim @@ -11,7 +11,7 @@ import ast, astalgo, magicsys, msgs, options, - idents, lexer, idgen, passes, syntaxes, llstream, modulegraphs, rod, + idents, lexer, passes, syntaxes, llstream, modulegraphs, rod, lineinfos, pathutils, tables proc resetSystemArtifacts*(g: ModuleGraph) = @@ -20,6 +20,8 @@ proc resetSystemArtifacts*(g: ModuleGraph) = template getModuleIdent(graph: ModuleGraph, filename: AbsoluteFile): PIdent = getIdent(graph.cache, splitFile(filename).name) +template packageId(): untyped {.dirty.} = ItemId(module: PackageModuleId, item: int32(fileIdx)) + proc getPackage(graph: ModuleGraph; fileIdx: FileIndex): PSym = ## returns package symbol (skPackage) for yet to be defined module for fileIdx let filename = AbsoluteFile toFullPath(graph.config, fileIdx) @@ -31,7 +33,7 @@ proc getPackage(graph: ModuleGraph; fileIdx: FileIndex): PSym = pack = getIdent(graph.cache, pck2) var packSym = graph.packageSyms.strTableGet(pack) if packSym == nil: - packSym = newSym(skPackage, getIdent(graph.cache, pck2), nil, info) + packSym = newSym(skPackage, getIdent(graph.cache, pck2), packageId(), nil, info) initStrTable(packSym.tab) graph.packageSyms.strTableAdd(packSym) else: @@ -47,7 +49,7 @@ proc getPackage(graph: ModuleGraph; fileIdx: FileIndex): PSym = # to resolve the conflicts: let pck3 = fakePackageName(graph.config, filename) # this makes the new `packSym`'s owner be the original `packSym` - packSym = newSym(skPackage, getIdent(graph.cache, pck3), packSym, info) + packSym = newSym(skPackage, getIdent(graph.cache, pck3), packageId(), packSym, info) initStrTable(packSym.tab) graph.packageSyms.strTableAdd(packSym) result = packSym @@ -69,7 +71,7 @@ proc newModule(graph: ModuleGraph; fileIdx: FileIndex): PSym = let filename = AbsoluteFile toFullPath(graph.config, fileIdx) # We cannot call ``newSym`` here, because we have to circumvent the ID # mechanism, which we do in order to assign each module a persistent ID. - result = PSym(kind: skModule, id: -1, # for better error checking + result = PSym(kind: skModule, itemId: ItemId(module: int32(fileIdx), item: 0'i32), name: getModuleIdent(graph, filename), info: newLineInfo(fileIdx, 1, 1)) if not isNimIdentifier(result.name.s): @@ -82,25 +84,21 @@ proc compileModule*(graph: ModuleGraph; fileIdx: FileIndex; flags: TSymFlags): P result = graph.getModule(fileIdx) if result == nil: let filename = AbsoluteFile toFullPath(graph.config, fileIdx) - let (r, id) = loadModuleSym(graph, fileIdx, filename) - result = r + result = loadModuleSym(graph, fileIdx, filename) if result == nil: result = newModule(graph, fileIdx) result.flags.incl flags - result.id = id registerModule(graph, result) else: partialInitModule(result, graph, fileIdx, filename) - result.id = id - assert result.id < 0 - discard processModule(graph, result, + discard processModule(graph, result, idGeneratorFromModule(result), if sfMainModule in flags and graph.config.projectIsStdin: stdin.llStreamOpen else: nil) elif graph.isDirty(result): result.flags.excl sfDirty # reset module fields: initStrTable(result.tab) result.ast = nil - discard processModule(graph, result, + discard processModule(graph, result, idGeneratorFromModule(result), if sfMainModule in flags and graph.config.projectIsStdin: stdin.llStreamOpen else: nil) graph.markClientsDirty(fileIdx) @@ -161,7 +159,6 @@ proc compileProject*(graph: ModuleGraph; projectFileIdx = InvalidFileIdx) = proc makeModule*(graph: ModuleGraph; filename: AbsoluteFile): PSym = result = graph.newModule(fileInfoIdx(graph.config, filename)) - result.id = getID() registerModule(graph, result) proc makeModule*(graph: ModuleGraph; filename: string): PSym = diff --git a/compiler/nimconf.nim b/compiler/nimconf.nim index c3591a945..3e8c4d194 100644 --- a/compiler/nimconf.nim +++ b/compiler/nimconf.nim @@ -10,7 +10,7 @@ # This module handles the reading of the config file. import - llstream, commands, os, strutils, msgs, lexer, + llstream, commands, os, strutils, msgs, lexer, ast, options, idents, wordrecg, strtabs, lineinfos, pathutils, scriptconfig # ---------------- configuration file parser ----------------------------- @@ -238,7 +238,7 @@ proc getSystemConfigPath*(conf: ConfigRef; filename: RelativeFile): AbsoluteFile if not fileExists(result): result = p / RelativeDir"etc/nim" / filename if not fileExists(result): result = AbsoluteDir"/etc/nim" / filename -proc loadConfigs*(cfg: RelativeFile; cache: IdentCache; conf: ConfigRef) = +proc loadConfigs*(cfg: RelativeFile; cache: IdentCache; conf: ConfigRef; idgen: IdGenerator) = setDefaultLibpath(conf) var configFiles = newSeq[AbsoluteFile]() @@ -252,7 +252,7 @@ proc loadConfigs*(cfg: RelativeFile; cache: IdentCache; conf: ConfigRef) = let p = path # eval once if fileExists(p): configFiles.add(p) - runNimScript(cache, p, freshDefines = false, conf) + runNimScript(cache, p, idgen, freshDefines = false, conf) if optSkipSystemConfigFile notin conf.globalOptions: readConfigFile(getSystemConfigPath(conf, cfg)) @@ -291,13 +291,12 @@ proc loadConfigs*(cfg: RelativeFile; cache: IdentCache; conf: ConfigRef) = # delayed to here so that `hintConf` is honored rawMessage(conf, hintConf, filename.string) - block: - let scriptFile = conf.projectFull.changeFileExt("nims") - if conf.command != "nimsuggest": + let scriptFile = conf.projectFull.changeFileExt("nims") + if conf.command != "nimsuggest": + runNimScriptIfExists(scriptFile) + else: + if scriptFile != conf.projectFull: runNimScriptIfExists(scriptFile) else: - if scriptFile != conf.projectFull: - runNimScriptIfExists(scriptFile) - else: - # 'nimsuggest foo.nims' means to just auto-complete the NimScript file - discard + # 'nimsuggest foo.nims' means to just auto-complete the NimScript file + discard diff --git a/compiler/nimeval.nim b/compiler/nimeval.nim index 5d4fea9f3..3ffe347c2 100644 --- a/compiler/nimeval.nim +++ b/compiler/nimeval.nim @@ -19,6 +19,7 @@ type mainModule: PSym graph: ModuleGraph scriptName: string + idgen: IdGenerator iterator exportedSymbols*(i: Interpreter): PSym = assert i != nil @@ -74,7 +75,7 @@ proc evalScript*(i: Interpreter; scriptStream: PLLStream = nil) = let s = if scriptStream != nil: scriptStream else: llStreamOpen(findFile(i.graph.config, i.scriptName), fmRead) - processModule(i.graph, i.mainModule, s) + processModule(i.graph, i.mainModule, i.idgen, s) proc findNimStdLib*(): string = ## Tries to find a path to a valid "system.nim" file. @@ -121,14 +122,15 @@ proc createInterpreter*(scriptName: string; var m = graph.makeModule(scriptName) incl(m.flags, sfMainModule) - var vm = newCtx(m, cache, graph) + var idgen = idGeneratorFromModule(m) + var vm = newCtx(m, cache, graph, idgen) vm.mode = emRepl vm.features = flags if registerOps: vm.registerAdditionalOps() # Required to register parts of stdlib modules graph.vm = vm graph.compileSystemModule() - result = Interpreter(mainModule: m, graph: graph, scriptName: scriptName) + result = Interpreter(mainModule: m, graph: graph, scriptName: scriptName, idgen: idgen) proc destroyInterpreter*(i: Interpreter) = ## destructor. @@ -162,6 +164,8 @@ proc runRepl*(r: TLLRepl; registerPass(graph, evalPass) var m = graph.makeStdinModule() incl(m.flags, sfMainModule) - if supportNimscript: graph.vm = setupVM(m, cache, "stdin", graph) + var idgen = idGeneratorFromModule(m) + + if supportNimscript: graph.vm = setupVM(m, cache, "stdin", graph, idgen) graph.compileSystemModule() - processModule(graph, m, llStreamOpenStdIn(r)) + processModule(graph, m, idgen, llStreamOpenStdIn(r)) diff --git a/compiler/passaux.nim b/compiler/passaux.nim index 155b956df..715b7d676 100644 --- a/compiler/passaux.nim +++ b/compiler/passaux.nim @@ -10,7 +10,7 @@ ## implements some little helper passes import - ast, passes, idents, msgs, options, idgen, lineinfos + ast, passes, idents, msgs, options, lineinfos from modulegraphs import ModuleGraph, PPassContext @@ -18,9 +18,9 @@ type VerboseRef = ref object of PPassContext config: ConfigRef -proc verboseOpen(graph: ModuleGraph; s: PSym): PPassContext = +proc verboseOpen(graph: ModuleGraph; s: PSym; idgen: IdGenerator): PPassContext = #MessageOut('compiling ' + s.name.s); - result = VerboseRef(config: graph.config) + result = VerboseRef(config: graph.config, idgen: idgen) rawMessage(graph.config, hintProcessing, s.name.s) proc verboseProcess(context: PPassContext, n: PNode): PNode = @@ -30,6 +30,6 @@ proc verboseProcess(context: PPassContext, n: PNode): PNode = # system.nim deactivates all hints, for verbosity:3 we want the processing # messages nonetheless, so we activate them again (but honor cmdlineNotes) v.config.setNote(hintProcessing) - message(v.config, n.info, hintProcessing, $idgen.gFrontEndId) + message(v.config, n.info, hintProcessing, $v.idgen[]) const verbosePass* = makePass(open = verboseOpen, process = verboseProcess) diff --git a/compiler/passes.nim b/compiler/passes.nim index 2d30ebbb5..f266d2a6b 100644 --- a/compiler/passes.nim +++ b/compiler/passes.nim @@ -13,7 +13,7 @@ import options, ast, llstream, msgs, idents, - syntaxes, idgen, modulegraphs, reorder, rod, + syntaxes, modulegraphs, reorder, rod, lineinfos, pathutils type @@ -51,31 +51,18 @@ proc registerPass*(g: ModuleGraph; p: TPass) = internalAssert g.config, g.passes.len < maxPasses g.passes.add(p) -proc carryPass*(g: ModuleGraph; p: TPass, module: PSym; - m: TPassData): TPassData = - var c = p.open(g, module) - result.input = p.process(c, m.input) - result.closeOutput = if p.close != nil: p.close(g, c, m.closeOutput) - else: m.closeOutput - -proc carryPasses*(g: ModuleGraph; nodes: PNode, module: PSym; - passes: openArray[TPass]) = - var passdata: TPassData - passdata.input = nodes - for pass in passes: - passdata = carryPass(g, pass, module, passdata) - proc openPasses(g: ModuleGraph; a: var TPassContextArray; - module: PSym) = + module: PSym; idgen: IdGenerator) = for i in 0..<g.passes.len: if not isNil(g.passes[i].open): - a[i] = g.passes[i].open(g, module) + a[i] = g.passes[i].open(g, module, idgen) else: a[i] = nil proc closePasses(graph: ModuleGraph; a: var TPassContextArray) = var m: PNode = nil for i in 0..<graph.passes.len: - if not isNil(graph.passes[i].close): m = graph.passes[i].close(graph, a[i], m) + if not isNil(graph.passes[i].close): + m = graph.passes[i].close(graph, a[i], m) a[i] = nil # free the memory here proc processTopLevelStmt(graph: ModuleGraph, n: PNode, a: var TPassContextArray): bool = @@ -123,7 +110,8 @@ proc prepareConfigNotes(graph: ModuleGraph; module: PSym) = proc moduleHasChanged*(graph: ModuleGraph; module: PSym): bool {.inline.} = result = module.id >= 0 or isDefined(graph.config, "nimBackendAssumesChange") -proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream): bool {.discardable.} = +proc processModule*(graph: ModuleGraph; module: PSym; idgen: IdGenerator; + stream: PLLStream): bool {.discardable.} = if graph.stopCompile(): return true var p: Parser @@ -135,7 +123,7 @@ proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream): bool { # new module caching mechanism: for i in 0..<graph.passes.len: if not isNil(graph.passes[i].open) and not graph.passes[i].isFrontend: - a[i] = graph.passes[i].open(graph, module) + a[i] = graph.passes[i].open(graph, module, idgen) else: a[i] = nil @@ -154,7 +142,7 @@ proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream): bool { m = graph.passes[i].close(graph, a[i], m) a[i] = nil else: - openPasses(graph, a, module) + openPasses(graph, a, module, idgen) if stream == nil: let filename = toFullPathConsiderDirty(graph.config, fileIdx) s = llStreamOpen(filename, fmRead) @@ -215,6 +203,4 @@ proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream): bool { closeParser(p) if s.kind != llsStdIn: break closePasses(graph, a) - # id synchronization point for more consistent code generation: - idSynchronizationPoint(1000) result = true diff --git a/compiler/plugins/itersgen.nim b/compiler/plugins/itersgen.nim index 61dda62af..a004fd4fd 100644 --- a/compiler/plugins/itersgen.nim +++ b/compiler/plugins/itersgen.nim @@ -29,10 +29,10 @@ proc iterToProcImpl*(c: PContext, n: PNode): PNode = localError(c.config, n[2].info, "type must be a non-generic ref|ptr to object with state field") return - let body = liftIterToProc(c.graph, iter.sym, iter.sym.getBody, t) + let body = liftIterToProc(c.graph, iter.sym, iter.sym.getBody, t, c.idgen) - let prc = newSym(skProc, n[3].ident, iter.sym.owner, iter.sym.info) - prc.typ = copyType(iter.sym.typ, prc, false) + let prc = newSym(skProc, n[3].ident, nextId c.idgen, iter.sym.owner, iter.sym.info) + prc.typ = copyType(iter.sym.typ, nextId c.idgen, prc) excl prc.typ.flags, tfCapturesEnv prc.typ.n.add newSymNode(getEnvParam(iter.sym)) prc.typ.rawAddSon t diff --git a/compiler/plugins/locals.nim b/compiler/plugins/locals.nim index f3ee94547..efa8b1e94 100644 --- a/compiler/plugins/locals.nim +++ b/compiler/plugins/locals.nim @@ -27,13 +27,13 @@ proc semLocals*(c: PContext, n: PNode): PNode = {tyVarargs, tyOpenArray, tyTypeDesc, tyStatic, tyUntyped, tyTyped, tyEmpty}: if it.owner == owner: - var field = newSym(skField, it.name, owner, n.info) + var field = newSym(skField, it.name, nextId c.idgen, owner, n.info) field.typ = it.typ.skipTypes({tyVar}) field.position = counter inc(counter) tupleType.n.add newSymNode(field) - addSonSkipIntLit(tupleType, field.typ) + addSonSkipIntLit(tupleType, field.typ, c.idgen) var a = newSymNode(it, result.info) if it.typ.skipTypes({tyGenericInst}).kind == tyVar: a = newDeref(a) diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim index 4d5240e3c..c0c9cc06a 100644 --- a/compiler/pragmas.nim +++ b/compiler/pragmas.nim @@ -121,7 +121,7 @@ proc pragmaEnsures(c: PContext, n: PNode) = openScope(c) let o = getCurrOwner(c) if o.kind in routineKinds and o.typ != nil and o.typ.sons[0] != nil: - var s = newSym(skResult, getIdent(c.cache, "result"), o, n.info) + var s = newSym(skResult, getIdent(c.cache, "result"), nextId(c.idgen), o, n.info) s.typ = o.typ.sons[0] incl(s.flags, sfUsed) addDecl(c, s) @@ -636,7 +636,7 @@ proc processPragma(c: PContext, n: PNode, i: int) = elif it.safeLen != 2 or it[0].kind != nkIdent or it[1].kind != nkIdent: invalidPragma(c, n) - var userPragma = newSym(skTemplate, it[1].ident, nil, it.info, c.config.options) + var userPragma = newSym(skTemplate, it[1].ident, nextId(c.idgen), nil, it.info, c.config.options) userPragma.ast = newTreeI(nkPragma, n.info, n.sons[i+1..^1]) strTableAdd(c.userPragmas, userPragma) @@ -717,7 +717,7 @@ proc deprecatedStmt(c: PContext; outerPragma: PNode) = if dest == nil or dest.kind in routineKinds: localError(c.config, n.info, warnUser, "the .deprecated pragma is unreliable for routines") let src = considerQuotedIdent(c, n[0]) - let alias = newSym(skAlias, src, dest, n[0].info, c.config.options) + let alias = newSym(skAlias, src, nextId(c.idgen), dest, n[0].info, c.config.options) incl(alias.flags, sfExported) if sfCompilerProc in dest.flags: markCompilerProc(c, alias) addInterfaceDecl(c, alias) @@ -739,7 +739,7 @@ proc pragmaGuard(c: PContext; it: PNode; kind: TSymKind): PSym = # We return a dummy symbol; later passes over the type will repair it. # Generic instantiation needs to know about this too. But we're lazy # and perform the lookup on demand instead. - result = newSym(skUnknown, considerQuotedIdent(c, n), nil, n.info, + result = newSym(skUnknown, considerQuotedIdent(c, n), nextId(c.idgen), nil, n.info, c.config.options) else: result = qualifiedLookUp(c, n, {checkUndeclared}) diff --git a/compiler/rod.nim b/compiler/rod.nim index e3e568a0e..13a4a53c9 100644 --- a/compiler/rod.nim +++ b/compiler/rod.nim @@ -9,14 +9,14 @@ ## This module implements the canonalization for the various caching mechanisms. -import ast, idgen, lineinfos, incremental, modulegraphs, pathutils +import ast, lineinfos, incremental, modulegraphs, pathutils when not nimIncremental: template setupModuleCache*(g: ModuleGraph) = discard template storeNode*(g: ModuleGraph; module: PSym; n: PNode) = discard template loadNode*(g: ModuleGraph; module: PSym): PNode = newNode(nkStmtList) - proc loadModuleSym*(g: ModuleGraph; fileIdx: FileIndex; fullpath: AbsoluteFile): (PSym, int) {.inline.} = (nil, getID()) + proc loadModuleSym*(g: ModuleGraph; fileIdx: FileIndex; fullpath: AbsoluteFile): (PSym) {.inline.} = nil template addModuleDep*(g: ModuleGraph; module, fileIdx: FileIndex; isIncludeFile: bool) = discard diff --git a/compiler/rodimpl.nim b/compiler/rodimpl.nim index e50ab66de..692f9c843 100644 --- a/compiler/rodimpl.nim +++ b/compiler/rodimpl.nim @@ -85,9 +85,9 @@ proc getModuleId(g: ModuleGraph; fileIdx: FileIndex; fullpath: AbsoluteFile): in db.exec(sql"delete from toplevelstmts where module = ?", module[0]) db.exec(sql"delete from statics where module = ?", module[0]) -proc loadModuleSym*(g: ModuleGraph; fileIdx: FileIndex; fullpath: AbsoluteFile): (PSym, int) = +proc loadModuleSym*(g: ModuleGraph; fileIdx: FileIndex; fullpath: AbsoluteFile): PSym = let id = getModuleId(g, fileIdx, fullpath) - result = (g.incr.r.syms.getOrDefault(abs id), id) + result = g.incr.r.syms.getOrDefault(abs id) proc pushType(w: var Writer, t: PType) = if not containsOrIncl(w.tmarks, t.uniqueId): diff --git a/compiler/scriptconfig.nim b/compiler/scriptconfig.nim index b359c9a48..ab7e5e0b5 100644 --- a/compiler/scriptconfig.nim +++ b/compiler/scriptconfig.nim @@ -27,9 +27,9 @@ proc listDirs(a: VmArgs, filter: set[PathComponent]) = setResult(a, result) proc setupVM*(module: PSym; cache: IdentCache; scriptName: string; - graph: ModuleGraph): PEvalContext = + graph: ModuleGraph; idgen: IdGenerator): PEvalContext = # For Nimble we need to export 'setupVM'. - result = newCtx(module, cache, graph) + result = newCtx(module, cache, graph, idgen) result.mode = emRepl registerAdditionalOps(result) let conf = graph.config @@ -198,6 +198,7 @@ proc setupVM*(module: PSym; cache: IdentCache; scriptName: string; setResult(a, stdin.readAll()) proc runNimScript*(cache: IdentCache; scriptName: AbsoluteFile; + idgen: IdGenerator; freshDefines=true; conf: ConfigRef) = let oldSymbolFiles = conf.symbolFiles conf.symbolFiles = disabledSf @@ -221,10 +222,11 @@ proc runNimScript*(cache: IdentCache; scriptName: AbsoluteFile; var m = graph.makeModule(scriptName) incl(m.flags, sfMainModule) - graph.vm = setupVM(m, cache, scriptName.string, graph) + var vm = setupVM(m, cache, scriptName.string, graph, idgen) + graph.vm = vm graph.compileSystemModule() - discard graph.processModule(m, llStreamOpen(scriptName, fmRead)) + discard graph.processModule(m, vm.idgen, llStreamOpen(scriptName, fmRead)) # watch out, "newruntime" can be set within NimScript itself and then we need # to remember this: diff --git a/compiler/sem.nim b/compiler/sem.nim index 705e1b72c..f90d9e1f9 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -14,7 +14,7 @@ import wordrecg, ropes, msgs, idents, renderer, types, platform, math, magicsys, nversion, nimsets, semfold, modulepaths, importer, procfind, lookups, pragmas, passes, semdata, semtypinst, sigmatch, - intsets, transf, vmdef, vm, idgen, aliases, cgmeth, lambdalifting, + intsets, transf, vmdef, vm, aliases, cgmeth, lambdalifting, evaltempl, patterns, parampatterns, sempass2, linter, semmacrosanity, lowerings, plugins/active, rod, lineinfos, strtabs, int128, isolation_check, typeallowed @@ -83,7 +83,7 @@ proc fitNodePostMatch(c: PContext, formal: PType, arg: PNode): PNode = if x.kind in {nkPar, nkTupleConstr, nkCurly} and formal.kind != tyUntyped: changeType(c, x, formal, check=true) result = arg - result = skipHiddenSubConv(result) + result = skipHiddenSubConv(result, c.idgen) proc fitNode(c: PContext, formal: PType, arg: PNode; info: TLineInfo): PNode = @@ -108,7 +108,7 @@ proc inferWithMetatype(c: PContext, formal: PType, template commonTypeBegin*(): PType = PType(kind: tyUntyped) -proc commonType*(x, y: PType): PType = +proc commonType*(c: PContext; x, y: PType): PType = # new type relation that is used for array constructors, # if expressions, etc.: if x == nil: return x @@ -124,8 +124,8 @@ proc commonType*(x, y: PType): PType = # turn any concrete typedesc into the abstract typedesc type if a.len == 0: result = a else: - result = newType(tyTypeDesc, a.owner) - rawAddSon(result, newType(tyNone, a.owner)) + result = newType(tyTypeDesc, nextId(c.idgen), a.owner) + rawAddSon(result, newType(tyNone, nextId(c.idgen), a.owner)) elif b.kind in {tyArray, tySet, tySequence} and a.kind == b.kind: # check for seq[empty] vs. seq[int] @@ -137,7 +137,7 @@ proc commonType*(x, y: PType): PType = let aEmpty = isEmptyContainer(a[i]) let bEmpty = isEmptyContainer(b[i]) if aEmpty != bEmpty: - if nt.isNil: nt = copyType(a, a.owner, false) + if nt.isNil: nt = copyType(a, nextId(c.idgen), a.owner) nt[i] = if aEmpty: b[i] else: a[i] if not nt.isNil: result = nt #elif b[idx].kind == tyEmpty: return x @@ -149,7 +149,7 @@ proc commonType*(x, y: PType): PType = # type(if b: 0 else 1) == int and not range[0..1]. For now. In the long # run people expect ranges to work properly within a tuple. if not sameType(a, b): - result = skipTypes(a, {tyRange}).skipIntLit + result = skipTypes(a, {tyRange}).skipIntLit(c.idgen) when false: if a.kind != tyRange and b.kind == tyRange: # XXX This really needs a better solution, but a proper fix now breaks @@ -176,8 +176,8 @@ proc commonType*(x, y: PType): PType = # ill-formed AST, no need for additional tyRef/tyPtr if k != tyNone and x.kind != tyGenericInst: let r = result - result = newType(k, r.owner) - result.addSonSkipIntLit(r) + result = newType(k, nextId(c.idgen), r.owner) + result.addSonSkipIntLit(r, c.idgen) proc endsInNoReturn(n: PNode): bool = # check if expr ends in raise exception or call of noreturn proc @@ -187,13 +187,13 @@ proc endsInNoReturn(n: PNode): bool = result = it.kind in nkLastBlockStmts or it.kind in nkCallKinds and it[0].kind == nkSym and sfNoReturn in it[0].sym.flags -proc commonType*(x: PType, y: PNode): PType = +proc commonType*(c: PContext; x: PType, y: PNode): PType = # ignore exception raising branches in case/if expressions if endsInNoReturn(y): return x - commonType(x, y.typ) + commonType(c, x, y.typ) proc newSymS(kind: TSymKind, n: PNode, c: PContext): PSym = - result = newSym(kind, considerQuotedIdent(c, n), getCurrOwner(c), n.info) + result = newSym(kind, considerQuotedIdent(c, n), nextId c.idgen, getCurrOwner(c), n.info) when defined(nimsuggest): suggestDecl(c, n, result) @@ -216,7 +216,7 @@ proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym = # template; we must fix it here: see #909 result.owner = getCurrOwner(c) else: - result = newSym(kind, considerQuotedIdent(c, n), getCurrOwner(c), n.info) + result = newSym(kind, considerQuotedIdent(c, n), nextId c.idgen, getCurrOwner(c), n.info) #if kind in {skForVar, skLet, skVar} and result.owner.kind == skModule: # incl(result.flags, sfGlobal) when defined(nimsuggest): @@ -255,7 +255,7 @@ proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym, proc symFromType(c: PContext; t: PType, info: TLineInfo): PSym = if t.sym != nil: return t.sym - result = newSym(skType, getIdent(c.cache, "AnonType"), t.owner, info) + result = newSym(skType, getIdent(c.cache, "AnonType"), nextId c.idgen, t.owner, info) result.flags.incl sfAnon result.typ = t @@ -316,7 +316,7 @@ proc tryConstExpr(c: PContext, n: PNode): PNode = var e = semExprWithType(c, n) if e == nil: return - result = getConstExpr(c.module, e, c.graph) + result = getConstExpr(c.module, e, c.idgen, c.graph) if result != nil: return let oldErrorCount = c.config.errorCounter @@ -327,7 +327,7 @@ proc tryConstExpr(c: PContext, n: PNode): PNode = c.config.errorMax = high(int) # `setErrorMaxHighMaybe` not appropriate here try: - result = evalConstExpr(c.module, c.graph, e) + result = evalConstExpr(c.module, c.idgen, c.graph, e) if result == nil or result.kind == nkEmpty: result = nil else: @@ -348,10 +348,10 @@ proc semConstExpr(c: PContext, n: PNode): PNode = if e == nil: localError(c.config, n.info, errConstExprExpected) return n - result = getConstExpr(c.module, e, c.graph) + result = getConstExpr(c.module, e, c.idgen, c.graph) if result == nil: #if e.kind == nkEmpty: globalError(n.info, errConstExprExpected) - result = evalConstExpr(c.module, c.graph, e) + result = evalConstExpr(c.module, c.idgen, c.graph, e) if result == nil or result.kind == nkEmpty: if e.info != n.info: pushInfoContext(c.config, n.info) @@ -373,7 +373,7 @@ proc semExprFlagDispatched(c: PContext, n: PNode, flags: TExprFlags): PNode = else: result = semExprWithType(c, n, flags) if efPreferStatic in flags: - var evaluated = getConstExpr(c.module, result, c.graph) + var evaluated = getConstExpr(c.module, result, c.idgen, c.graph) if evaluated != nil: return evaluated evaluated = evalAtCompileTime(c, result) if evaluated != nil: return evaluated @@ -399,7 +399,6 @@ proc semAfterMacroCall(c: PContext, call, macroResult: PNode, if c.config.evalTemplateCounter > evalTemplateLimit: globalError(c.config, s.info, "template instantiation too nested") c.friendModules.add(s.owner.getModule) - idSynchronizationPoint(5000) result = macroResult resetSemFlag result if s.typ[0] == nil: @@ -469,7 +468,7 @@ proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym, #if c.evalContext == nil: # c.evalContext = c.createEvalContext(emStatic) - result = evalMacroCall(c.module, c.graph, c.templInstCounter, n, nOrig, sym) + result = evalMacroCall(c.module, c.idgen, c.graph, c.templInstCounter, n, nOrig, sym) if efNoSemCheck notin flags: result = semAfterMacroCall(c, n, result, sym, flags) if c.config.macrosToExpand.hasKey(sym.name.s): @@ -502,8 +501,9 @@ proc addCodeForGenerics(c: PContext, n: PNode) = n.add prc.ast c.lastGenericIdx = c.generics.len -proc myOpen(graph: ModuleGraph; module: PSym): PPassContext {.nosinks.} = +proc myOpen(graph: ModuleGraph; module: PSym; idgen: IdGenerator): PPassContext {.nosinks.} = var c = newContext(graph, module) + c.idgen = idgen if c.p != nil: internalError(graph.config, module.info, "sem.myOpen") c.semConstExpr = semConstExpr c.semExpr = semExpr diff --git a/compiler/semcall.nim b/compiler/semcall.nim index 50df1085f..dd2398f87 100644 --- a/compiler/semcall.nim +++ b/compiler/semcall.nim @@ -688,9 +688,9 @@ proc searchForBorrowProc(c: PContext, startScope: PScope, fn: PSym): PSym = var x: PType if param.typ.kind == tyVar: x = newTypeS(param.typ.kind, c) - x.addSonSkipIntLit t.baseOfDistinct + x.addSonSkipIntLit(t.baseOfDistinct(c.idgen), c.idgen) else: - x = t.baseOfDistinct + x = t.baseOfDistinct(c.idgen) call.add(newNodeIT(nkEmpty, fn.info, x)) if hasDistinct: let filter = if fn.kind in {skProc, skFunc}: {skProc, skFunc} else: {fn.kind} diff --git a/compiler/semdata.nim b/compiler/semdata.nim index b15f65967..8d1c25e4d 100644 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -277,14 +277,14 @@ proc addToLib*(lib: PLib, sym: PSym) = sym.annex = lib proc newTypeS*(kind: TTypeKind, c: PContext): PType = - result = newType(kind, getCurrOwner(c)) + result = newType(kind, nextId(c.idgen), getCurrOwner(c)) -proc makePtrType*(owner: PSym, baseType: PType): PType = - result = newType(tyPtr, owner) - addSonSkipIntLit(result, baseType) +proc makePtrType*(owner: PSym, baseType: PType; idgen: IdGenerator): PType = + result = newType(tyPtr, nextId(idgen), owner) + addSonSkipIntLit(result, baseType, idgen) proc makePtrType*(c: PContext, baseType: PType): PType = - makePtrType(getCurrOwner(c), baseType) + makePtrType(getCurrOwner(c), baseType, c.idgen) proc makeTypeWithModifier*(c: PContext, modifier: TTypeKind, @@ -295,21 +295,21 @@ proc makeTypeWithModifier*(c: PContext, result = baseType else: result = newTypeS(modifier, c) - addSonSkipIntLit(result, baseType) + addSonSkipIntLit(result, baseType, c.idgen) proc makeVarType*(c: PContext, baseType: PType; kind = tyVar): PType = if baseType.kind == kind: result = baseType else: result = newTypeS(kind, c) - addSonSkipIntLit(result, baseType) + addSonSkipIntLit(result, baseType, c.idgen) -proc makeVarType*(owner: PSym, baseType: PType; kind = tyVar): PType = +proc makeVarType*(owner: PSym, baseType: PType; idgen: IdGenerator; kind = tyVar): PType = if baseType.kind == kind: result = baseType else: - result = newType(kind, owner) - addSonSkipIntLit(result, baseType) + result = newType(kind, nextId(idgen), owner) + addSonSkipIntLit(result, baseType, idgen) proc makeTypeDesc*(c: PContext, typ: PType): PType = if typ.kind == tyTypeDesc: @@ -317,14 +317,14 @@ proc makeTypeDesc*(c: PContext, typ: PType): PType = else: result = newTypeS(tyTypeDesc, c) incl result.flags, tfCheckedForDestructor - result.addSonSkipIntLit(typ) + result.addSonSkipIntLit(typ, c.idgen) proc makeTypeSymNode*(c: PContext, typ: PType, info: TLineInfo): PNode = let typedesc = newTypeS(tyTypeDesc, c) incl typedesc.flags, tfCheckedForDestructor internalAssert(c.config, typ != nil) - typedesc.addSonSkipIntLit(typ) - let sym = newSym(skType, c.cache.idAnon, getCurrOwner(c), info, + typedesc.addSonSkipIntLit(typ, c.idgen) + let sym = newSym(skType, c.cache.idAnon, nextId(c.idgen), getCurrOwner(c), info, c.config.options).linkTo(typedesc) return newSymNode(sym, info) @@ -333,13 +333,14 @@ proc makeTypeFromExpr*(c: PContext, n: PNode): PType = assert n != nil result.n = n -proc newTypeWithSons*(owner: PSym, kind: TTypeKind, sons: seq[PType]): PType = - result = newType(kind, owner) +proc newTypeWithSons*(owner: PSym, kind: TTypeKind, sons: seq[PType]; + idgen: IdGenerator): PType = + result = newType(kind, nextId(idgen), owner) result.sons = sons proc newTypeWithSons*(c: PContext, kind: TTypeKind, sons: seq[PType]): PType = - result = newType(kind, getCurrOwner(c)) + result = newType(kind, nextId(c.idgen), getCurrOwner(c)) result.sons = sons proc makeStaticExpr*(c: PContext, n: PNode): PNode = @@ -418,7 +419,7 @@ proc makeRangeType*(c: PContext; first, last: BiggestInt; n.add newIntTypeNode(last, intType) result = newTypeS(tyRange, c) result.n = n - addSonSkipIntLit(result, intType) # basetype of range + addSonSkipIntLit(result, intType, c.idgen) # basetype of range proc markIndirect*(c: PContext, s: PSym) {.inline.} = if s.kind in {skProc, skFunc, skConverter, skMethod, skIterator}: diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index cb852c68a..2de25dadb 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -33,7 +33,8 @@ proc semTemplateExpr(c: PContext, n: PNode, s: PSym, # Note: This is n.info on purpose. It prevents template from creating an info # context when called from an another template pushInfoContext(c.config, n.info, s.detailedInfo) - result = evalTemplate(n, s, getCurrOwner(c), c.config, c.cache, c.templInstCounter, efFromHlo in flags) + result = evalTemplate(n, s, getCurrOwner(c), c.config, c.cache, + c.templInstCounter, c.idgen, efFromHlo in flags) if efNoSemCheck notin flags: result = semAfterMacroCall(c, n, result, s, flags) popInfoContext(c.config) @@ -384,7 +385,7 @@ proc fixupStaticType(c: PContext, n: PNode) = # apply this measure only in code that is enlightened to work # with static types. if n.typ.kind != tyStatic: - n.typ = newTypeWithSons(getCurrOwner(c), tyStatic, @[n.typ]) + n.typ = newTypeWithSons(getCurrOwner(c), tyStatic, @[n.typ], c.idgen) n.typ.n = n # XXX: cycles like the one here look dangerous. # Consider using `n.copyTree` @@ -555,7 +556,7 @@ proc arrayConstrType(c: PContext, n: PNode): PType = rawAddSon(typ, newTypeS(tyEmpty, c)) # needs an empty basetype! else: var t = skipTypes(n[0].typ, {tyGenericInst, tyVar, tyLent, tyOrdinal, tyAlias, tySink}) - addSonSkipIntLit(typ, t) + addSonSkipIntLit(typ, t, c.idgen) typ[0] = makeRangeType(c, 0, n.len - 1, n.info) result = typ @@ -605,11 +606,11 @@ proc semArrayConstr(c: PContext, n: PNode, flags: TExprFlags): PNode = let xx = semExprWithType(c, x, flags*{efAllowDestructor}) result.add xx - typ = commonType(typ, xx.typ) + typ = commonType(c, typ, xx.typ) #n[i] = semExprWithType(c, x, flags*{efAllowDestructor}) #result.add fitNode(c, typ, n[i]) inc(lastIndex) - addSonSkipIntLit(result.typ, typ) + addSonSkipIntLit(result.typ, typ, c.idgen) for i in 0..<result.len: result[i] = fitNode(c, typ, result[i], result[i].info) result.typ[0] = makeRangeType(c, toInt64(firstIndex), toInt64(lastIndex), n.info, @@ -756,14 +757,14 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode = call.add(n[0]) var allConst = true for i in 1..<n.len: - var a = getConstExpr(c.module, n[i], c.graph) + var a = getConstExpr(c.module, n[i], c.idgen, c.graph) if a == nil: allConst = false a = n[i] if a.kind == nkHiddenStdConv: a = a[1] call.add(a) if allConst: - result = semfold.getConstExpr(c.module, call, c.graph) + result = semfold.getConstExpr(c.module, call, c.idgen, c.graph) if result.isNil: result = n else: return result @@ -800,19 +801,19 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode = var call = newNodeIT(nkCall, n.info, n.typ) call.add(n[0]) for i in 1..<n.len: - let a = getConstExpr(c.module, n[i], c.graph) + let a = getConstExpr(c.module, n[i], c.idgen, c.graph) if a == nil: return n call.add(a) #echo "NOW evaluating at compile time: ", call.renderTree if c.inStaticContext == 0 or sfNoSideEffect in callee.flags: if sfCompileTime in callee.flags: - result = evalStaticExpr(c.module, c.graph, call, c.p.owner) + result = evalStaticExpr(c.module, c.idgen, c.graph, call, c.p.owner) if result.isNil: localError(c.config, n.info, errCannotInterpretNodeX % renderTree(call)) else: result = fixupTypeAfterEval(c, result, n) else: - result = evalConstExpr(c.module, c.graph, call) + result = evalConstExpr(c.module, c.idgen, c.graph, call) if result.isNil: result = n else: result = fixupTypeAfterEval(c, result, n) else: @@ -827,7 +828,7 @@ proc semStaticExpr(c: PContext, n: PNode): PNode = closeScope(c) dec c.inStaticContext if a.findUnresolvedStatic != nil: return a - result = evalStaticExpr(c.module, c.graph, a, c.p.owner) + result = evalStaticExpr(c.module, c.idgen, c.graph, a, c.p.owner) if result.isNil: localError(c.config, n.info, errCannotInterpretNodeX % renderTree(n)) result = c.graph.emptyNode @@ -1115,7 +1116,7 @@ proc readTypeParameter(c: PContext, typ: PType, # This seems semantically correct and then we'll be able # to return the section symbol directly here let foundType = makeTypeDesc(c, def[2].typ) - return newSymNode(copySym(def[0].sym).linkTo(foundType), info) + return newSymNode(copySym(def[0].sym, nextId c.idgen).linkTo(foundType), info) of nkConstSection: for def in statement: @@ -1140,7 +1141,7 @@ proc readTypeParameter(c: PContext, typ: PType, return c.graph.emptyNode else: let foundTyp = makeTypeDesc(c, rawTyp) - return newSymNode(copySym(tParam.sym).linkTo(foundTyp), info) + return newSymNode(copySym(tParam.sym, nextId c.idgen).linkTo(foundTyp), info) return nil @@ -1700,7 +1701,7 @@ proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode = # unfortunately we need to rewrite ``(x, y) = foo()`` already here so # that overloading of the assignment operator still works. Usually we # prefer to do these rewritings in transf.nim: - return semStmt(c, lowerTupleUnpackingForAsgn(c.graph, n, c.p.owner), {}) + return semStmt(c, lowerTupleUnpackingForAsgn(c.graph, n, c.idgen, c.p.owner), {}) else: a = semExprWithType(c, a, {efLValue}) else: @@ -1930,7 +1931,7 @@ proc expectString(c: PContext, n: PNode): string = localError(c.config, n.info, errStringLiteralExpected) proc newAnonSym(c: PContext; kind: TSymKind, info: TLineInfo): PSym = - result = newSym(kind, c.cache.idAnon, getCurrOwner(c), info) + result = newSym(kind, c.cache.idAnon, nextId c.idgen, getCurrOwner(c), info) proc semExpandToAst(c: PContext, n: PNode): PNode = let macroCall = n[1] @@ -2145,9 +2146,9 @@ proc semShallowCopy(c: PContext, n: PNode, flags: TExprFlags): PNode = result = semDirectOp(c, n, flags) proc createFlowVar(c: PContext; t: PType; info: TLineInfo): PType = - result = newType(tyGenericInvocation, c.module) - addSonSkipIntLit(result, magicsys.getCompilerProc(c.graph, "FlowVar").typ) - addSonSkipIntLit(result, t) + result = newType(tyGenericInvocation, nextId c.idgen, c.module) + addSonSkipIntLit(result, magicsys.getCompilerProc(c.graph, "FlowVar").typ, c.idgen) + addSonSkipIntLit(result, t, c.idgen) result = instGenericContainer(c, info, result, allowMetaTypes = false) proc instantiateCreateFlowVarCall(c: PContext; t: PType; @@ -2328,7 +2329,7 @@ proc semWhen(c: PContext, n: PNode, semCheck = true): PNode = if whenNimvm: if semCheck: it[1] = semExpr(c, it[1]) - typ = commonType(typ, it[1].typ) + typ = commonType(c, typ, it[1].typ) result = n # when nimvm is not elimited until codegen else: let e = forceBool(c, semConstExpr(c, it[0])) @@ -2343,17 +2344,13 @@ proc semWhen(c: PContext, n: PNode, semCheck = true): PNode = if result == nil or whenNimvm: if semCheck: it[0] = semExpr(c, it[0]) - typ = commonType(typ, it[0].typ) + typ = commonType(c, typ, it[0].typ) if result == nil: result = it[0] else: illFormedAst(n, c.config) if result == nil: result = newNodeI(nkEmpty, n.info) if whenNimvm: result.typ = typ - # The ``when`` statement implements the mechanism for platform dependent - # code. Thus we try to ensure here consistent ID allocation after the - # ``when`` statement. - idSynchronizationPoint(200) proc semSetConstr(c: PContext, n: PNode): PNode = result = newNodeI(nkCurly, n.info) @@ -2386,7 +2383,7 @@ proc semSetConstr(c: PContext, n: PNode): PNode = typ = makeRangeType(c, 0, MaxSetElements-1, n.info) elif lengthOrd(c.config, typ) > MaxSetElements: typ = makeRangeType(c, 0, MaxSetElements-1, n.info) - addSonSkipIntLit(result.typ, typ) + addSonSkipIntLit(result.typ, typ, c.idgen) for i in 0..<n.len: var m: PNode let info = n[i].info @@ -2467,7 +2464,7 @@ proc semTupleFieldsConstr(c: PContext, n: PNode, flags: TExprFlags): PNode = n[i][1].typ = errorType(c) var f = newSymS(skField, n[i][0], c) - f.typ = skipIntLit(n[i][1].typ) + f.typ = skipIntLit(n[i][1].typ, c.idgen) f.position = i rawAddSon(typ, f.typ) typ.n.add newSymNode(f) @@ -2481,7 +2478,7 @@ proc semTuplePositionsConstr(c: PContext, n: PNode, flags: TExprFlags): PNode = var typ = newTypeS(tyTuple, c) # leave typ.n nil! for i in 0..<n.len: n[i] = semExprWithType(c, n[i], flags*{efAllowDestructor}) - addSonSkipIntLit(typ, n[i].typ) + addSonSkipIntLit(typ, n[i].typ, c.idgen) result.typ = typ include semobjconstr @@ -2608,7 +2605,8 @@ proc hoistParamsUsedInDefault(c: PContext, call, letSection, defExpr: var PNode) let paramPos = defExpr.sym.position + 1 if call[paramPos].kind != nkSym: - let hoistedVarSym = newSym(skLet, getIdent(c.graph.cache, genPrefix), c.p.owner, letSection.info, c.p.owner.options) + let hoistedVarSym = newSym(skLet, getIdent(c.graph.cache, genPrefix), nextId c.idgen, + c.p.owner, letSection.info, c.p.owner.options) hoistedVarSym.typ = call[paramPos].typ letSection.add newTreeI(nkIdentDefs, letSection.info, diff --git a/compiler/semfields.nim b/compiler/semfields.nim index cea084d3a..d7563e33f 100644 --- a/compiler/semfields.nim +++ b/compiler/semfields.nim @@ -109,7 +109,7 @@ proc semForFields(c: PContext, n: PNode, m: TMagic): PNode = var trueSymbol = strTableGet(c.graph.systemModule.tab, getIdent(c.cache, "true")) if trueSymbol == nil: localError(c.config, n.info, "system needs: 'true'") - trueSymbol = newSym(skUnknown, getIdent(c.cache, "true"), getCurrOwner(c), n.info) + trueSymbol = newSym(skUnknown, getIdent(c.cache, "true"), nextId c.idgen, getCurrOwner(c), n.info) trueSymbol.typ = getSysType(c.graph, n.info, tyBool) result[0] = newSymNode(trueSymbol, n.info) diff --git a/compiler/semfold.nim b/compiler/semfold.nim index e94a15fbe..9b21c5fa3 100644 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -17,7 +17,7 @@ import proc errorType*(g: ModuleGraph): PType = ## creates a type representing an error state - result = newType(tyError, g.owners[^1]) + result = newType(tyError, nextId(g.idgen), g.owners[^1]) result.flags.incl tfCheckedForDestructor proc newIntNodeT*(intVal: Int128, n: PNode; g: ModuleGraph): PNode = @@ -42,7 +42,7 @@ proc newStrNodeT*(strVal: string, n: PNode; g: ModuleGraph): PNode = result.typ = n.typ result.info = n.info -proc getConstExpr*(m: PSym, n: PNode; g: ModuleGraph): PNode +proc getConstExpr*(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode # evaluates the constant expression or returns nil if it is no constant # expression proc evalOp*(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode @@ -113,45 +113,6 @@ proc pickIntRange(a, b: PType): PType = proc isIntRangeOrLit(t: PType): bool = result = isIntRange(t) or isIntLit(t) -proc makeRange(typ: PType, first, last: BiggestInt; g: ModuleGraph): PType = - let minA = min(first, last) - let maxA = max(first, last) - let lowerNode = newIntNode(nkIntLit, minA) - if typ.kind == tyInt and minA == maxA: - result = getIntLitType(g, lowerNode) - elif typ.kind in {tyUInt, tyUInt64}: - # these are not ordinal types, so you get no subrange type for these: - result = typ - else: - var n = newNode(nkRange) - n.add lowerNode - n.add newIntNode(nkIntLit, maxA) - result = newType(tyRange, typ.owner) - result.n = n - addSonSkipIntLit(result, skipTypes(typ, {tyRange})) - -proc makeRangeF(typ: PType, first, last: BiggestFloat; g: ModuleGraph): PType = - var n = newNode(nkRange) - n.add newFloatNode(nkFloatLit, min(first.float, last.float)) - n.add newFloatNode(nkFloatLit, max(first.float, last.float)) - result = newType(tyRange, typ.owner) - result.n = n - addSonSkipIntLit(result, skipTypes(typ, {tyRange})) - -proc fitLiteral(c: ConfigRef, n: PNode): PNode {.deprecated: "no substitute".} = - # Trim the literal value in order to make it fit in the destination type - if n == nil: - # `n` may be nil if the overflow check kicks in - return - - doAssert n.kind in {nkIntLit, nkCharLit} - - result = n - - let typ = n.typ.skipTypes(abstractRange) - if typ.kind in tyUInt..tyUInt32: - result.intVal = result.intVal and castToInt64(lastOrd(c, typ)) - proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode = # b and c may be nil result = nil @@ -342,19 +303,19 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode = exprStructuralEquivalent(a, b, strictSymEquality=true))), n, g) else: discard -proc getConstIfExpr(c: PSym, n: PNode; g: ModuleGraph): PNode = +proc getConstIfExpr(c: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode = result = nil for i in 0..<n.len: var it = n[i] if it.len == 2: - var e = getConstExpr(c, it[0], g) + var e = getConstExpr(c, it[0], idgen, g) if e == nil: return nil if getOrdValue(e) != 0: if result == nil: - result = getConstExpr(c, it[1], g) + result = getConstExpr(c, it[1], idgen, g) if result == nil: return elif it.len == 1: - if result == nil: result = getConstExpr(c, it[0], g) + if result == nil: result = getConstExpr(c, it[0], idgen, g) else: internalError(g.config, it.info, "getConstIfExpr()") proc leValueConv*(a, b: PNode): bool = @@ -372,18 +333,18 @@ proc leValueConv*(a, b: PNode): bool = else: result = false # internalError(a.info, "leValueConv") else: result = false # internalError(a.info, "leValueConv") -proc magicCall(m: PSym, n: PNode; g: ModuleGraph): PNode = +proc magicCall(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode = if n.len <= 1: return var s = n[0].sym - var a = getConstExpr(m, n[1], g) + var a = getConstExpr(m, n[1], idgen, g) var b, c: PNode if a == nil: return if n.len > 2: - b = getConstExpr(m, n[2], g) + b = getConstExpr(m, n[2], idgen, g) if b == nil: return if n.len > 3: - c = getConstExpr(m, n[3], g) + c = getConstExpr(m, n[3], idgen, g) if c == nil: return result = evalOp(s.magic, n, a, b, c, g) @@ -451,19 +412,19 @@ proc foldConv(n, a: PNode; g: ModuleGraph; check = false): PNode = result = a result.typ = n.typ -proc getArrayConstr(m: PSym, n: PNode; g: ModuleGraph): PNode = +proc getArrayConstr(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode = if n.kind == nkBracket: result = n else: - result = getConstExpr(m, n, g) + result = getConstExpr(m, n, idgen, g) if result == nil: result = n -proc foldArrayAccess(m: PSym, n: PNode; g: ModuleGraph): PNode = - var x = getConstExpr(m, n[0], g) +proc foldArrayAccess(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode = + var x = getConstExpr(m, n[0], idgen, g) if x == nil or x.typ.skipTypes({tyGenericInst, tyAlias, tySink}).kind == tyTypeDesc: return - var y = getConstExpr(m, n[1], g) + var y = getConstExpr(m, n[1], idgen, g) if y == nil: return var idx = toInt64(getOrdValue(y)) @@ -486,9 +447,9 @@ proc foldArrayAccess(m: PSym, n: PNode; g: ModuleGraph): PNode = localError(g.config, n.info, formatErrorIndexBound(idx, x.strVal.len-1) & $n) else: discard -proc foldFieldAccess(m: PSym, n: PNode; g: ModuleGraph): PNode = +proc foldFieldAccess(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode = # a real field access; proc calls have already been transformed - var x = getConstExpr(m, n[0], g) + var x = getConstExpr(m, n[0], idgen, g) if x == nil or x.kind notin {nkObjConstr, nkPar, nkTupleConstr}: return var field = n[1].sym @@ -504,23 +465,23 @@ proc foldFieldAccess(m: PSym, n: PNode; g: ModuleGraph): PNode = return localError(g.config, n.info, "field not found: " & field.name.s) -proc foldConStrStr(m: PSym, n: PNode; g: ModuleGraph): PNode = +proc foldConStrStr(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode = result = newNodeIT(nkStrLit, n.info, n.typ) result.strVal = "" for i in 1..<n.len: - let a = getConstExpr(m, n[i], g) + let a = getConstExpr(m, n[i], idgen, g) if a == nil: return nil result.strVal.add(getStrOrChar(a)) -proc newSymNodeTypeDesc*(s: PSym; info: TLineInfo): PNode = +proc newSymNodeTypeDesc*(s: PSym; idgen: IdGenerator; info: TLineInfo): PNode = result = newSymNode(s, info) if s.typ.kind != tyTypeDesc: - result.typ = newType(tyTypeDesc, s.owner) - result.typ.addSonSkipIntLit(s.typ) + result.typ = newType(tyTypeDesc, idgen.nextId, s.owner) + result.typ.addSonSkipIntLit(s.typ, idgen) else: result.typ = s.typ -proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode = +proc getConstExpr(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode = result = nil case n.kind of nkSym: @@ -570,12 +531,12 @@ proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode = result = n of skParam: if s.typ != nil and s.typ.kind == tyTypeDesc: - result = newSymNodeTypeDesc(s, n.info) + result = newSymNodeTypeDesc(s, idgen, n.info) of skType: # XXX gensym'ed symbols can come here and cannot be resolved. This is # dirty, but correct. if s.typ != nil: - result = newSymNodeTypeDesc(s, n.info) + result = newSymNodeTypeDesc(s, idgen, n.info) of skGenericParam: if s.typ.kind == tyStatic: if s.typ.n != nil and tfUnresolved notin s.typ.flags: @@ -584,12 +545,12 @@ proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode = elif s.typ.isIntLit: result = s.typ.n else: - result = newSymNodeTypeDesc(s, n.info) + result = newSymNodeTypeDesc(s, idgen, n.info) else: discard of nkCharLit..nkNilLit: result = copyNode(n) of nkIfExpr: - result = getConstIfExpr(m, n, g) + result = getConstIfExpr(m, n, idgen, g) of nkCallKinds: if n[0].kind != nkSym: return var s = n[0].sym @@ -612,17 +573,17 @@ proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode = else: result = newIntNodeT(lastOrd(g.config, skipTypes(n[1].typ, abstractVar)), n, g) else: - var a = getArrayConstr(m, n[1], g) + var a = getArrayConstr(m, n[1], idgen, g) if a.kind == nkBracket: # we can optimize it away: result = newIntNodeT(toInt128(a.len-1), n, g) of mLengthOpenArray: - var a = getArrayConstr(m, n[1], g) + var a = getArrayConstr(m, n[1], idgen, g) if a.kind == nkBracket: # we can optimize it away! This fixes the bug ``len(134)``. result = newIntNodeT(toInt128(a.len), n, g) else: - result = magicCall(m, n, g) + result = magicCall(m, n, idgen, g) of mLengthArray: # It doesn't matter if the argument is const or not for mLengthArray. # This fixes bug #544. @@ -636,33 +597,33 @@ proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode = of mAstToStr: result = newStrNodeT(renderTree(n[1], {renderNoComments}), n, g) of mConStrStr: - result = foldConStrStr(m, n, g) + result = foldConStrStr(m, n, idgen, g) of mIs: # The only kind of mIs node that comes here is one depending on some # generic parameter and that's (hopefully) handled at instantiation time discard else: - result = magicCall(m, n, g) + result = magicCall(m, n, idgen, g) except OverflowDefect: localError(g.config, n.info, "over- or underflow") except DivByZeroDefect: localError(g.config, n.info, "division by zero") of nkAddr: - var a = getConstExpr(m, n[0], g) + var a = getConstExpr(m, n[0], idgen, g) if a != nil: result = n n[0] = a of nkBracket, nkCurly: result = copyNode(n) for i, son in n.pairs: - var a = getConstExpr(m, son, g) + var a = getConstExpr(m, son, idgen, g) if a == nil: return nil result.add a incl(result.flags, nfAllConst) of nkRange: - var a = getConstExpr(m, n[0], g) + var a = getConstExpr(m, n[0], idgen, g) if a == nil: return - var b = getConstExpr(m, n[1], g) + var b = getConstExpr(m, n[1], idgen, g) if b == nil: return result = copyNode(n) result.add a @@ -681,18 +642,18 @@ proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode = for i, expr in n.pairs: let exprNew = copyNode(expr) # nkExprColonExpr exprNew.add expr[0] - let a = getConstExpr(m, expr[1], g) + let a = getConstExpr(m, expr[1], idgen, g) if a == nil: return nil exprNew.add a result.add exprNew else: for i, expr in n.pairs: - let a = getConstExpr(m, expr, g) + let a = getConstExpr(m, expr, idgen, g) if a == nil: return nil result.add a incl(result.flags, nfAllConst) of nkChckRangeF, nkChckRange64, nkChckRange: - var a = getConstExpr(m, n[0], g) + var a = getConstExpr(m, n[0], idgen, g) if a == nil: return if leValueConv(n[1], a) and leValueConv(a, n[2]): result = a # a <= x and x <= b @@ -702,31 +663,31 @@ proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode = "conversion from $1 to $2 is invalid" % [typeToString(n[0].typ), typeToString(n.typ)]) of nkStringToCString, nkCStringToString: - var a = getConstExpr(m, n[0], g) + var a = getConstExpr(m, n[0], idgen, g) if a == nil: return result = a result.typ = n.typ of nkHiddenStdConv, nkHiddenSubConv, nkConv: - var a = getConstExpr(m, n[1], g) + var a = getConstExpr(m, n[1], idgen, g) if a == nil: return result = foldConv(n, a, g, check=true) of nkCast: - var a = getConstExpr(m, n[1], g) + var a = getConstExpr(m, n[1], idgen, g) if a == nil: return if n.typ != nil and n.typ.kind in NilableTypes: # we allow compile-time 'cast' for pointer types: result = a result.typ = n.typ - of nkBracketExpr: result = foldArrayAccess(m, n, g) - of nkDotExpr: result = foldFieldAccess(m, n, g) + of nkBracketExpr: result = foldArrayAccess(m, n, idgen, g) + of nkDotExpr: result = foldFieldAccess(m, n, idgen, g) of nkCheckedFieldExpr: - result = foldFieldAccess(m, n[0], g) + result = foldFieldAccess(m, n[0], idgen, g) of nkStmtListExpr: var i = 0 while i <= n.len - 2: if n[i].kind in {nkComesFrom, nkCommentStmt, nkEmpty}: i.inc else: break if i == n.len - 1: - result = getConstExpr(m, n[i], g) + result = getConstExpr(m, n[i], idgen, g) else: discard diff --git a/compiler/semgnrc.nim b/compiler/semgnrc.nim index a80b1d057..5f55772e9 100644 --- a/compiler/semgnrc.nim +++ b/compiler/semgnrc.nim @@ -95,7 +95,7 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym, else: result = n else: - result = newSymNodeTypeDesc(s, n.info) + result = newSymNodeTypeDesc(s, c.idgen, n.info) onUse(n.info, s) of skParam: result = n @@ -103,7 +103,7 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym, of skType: if (s.typ != nil) and (s.typ.flags * {tfGenericTypeParam, tfImplicitTypeParam} == {}): - result = newSymNodeTypeDesc(s, n.info) + result = newSymNodeTypeDesc(s, c.idgen, n.info) else: result = n onUse(n.info, s) @@ -267,13 +267,13 @@ proc semGenericStmt(c: PContext, n: PNode, if s.magic == mRunnableExamples: first = result.safeLen # see trunnableexamples.fun3 of skGenericParam: - result[0] = newSymNodeTypeDesc(s, fn.info) + result[0] = newSymNodeTypeDesc(s, c.idgen, fn.info) onUse(fn.info, s) first = 1 of skType: # bad hack for generics: if (s.typ != nil) and (s.typ.kind != tyGenericParam): - result[0] = newSymNodeTypeDesc(s, fn.info) + result[0] = newSymNodeTypeDesc(s, c.idgen, fn.info) onUse(fn.info, s) first = 1 else: @@ -470,7 +470,7 @@ proc semGenericStmt(c: PContext, n: PNode, flags, ctx) if n[paramsPos].kind != nkEmpty: if n[paramsPos][0].kind != nkEmpty: - addPrelimDecl(c, newSym(skUnknown, getIdent(c.cache, "result"), nil, n.info)) + addPrelimDecl(c, newSym(skUnknown, getIdent(c.cache, "result"), nextId c.idgen, nil, n.info)) n[paramsPos] = semGenericStmt(c, n[paramsPos], flags, ctx) n[pragmasPos] = semGenericStmt(c, n[pragmasPos], flags, ctx) var body: PNode diff --git a/compiler/seminst.nim b/compiler/seminst.nim index ffeed00d6..8f2f51ae8 100644 --- a/compiler/seminst.nim +++ b/compiler/seminst.nim @@ -65,7 +65,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(c), q.info) + var s = newSym(symKind, q.name, nextId c.idgen, getCurrOwner(c), q.info) s.flags.incl {sfUsed, sfFromGeneric} var t = PType(idTableGet(pt, q.typ)) if t == nil: @@ -105,7 +105,7 @@ when false: proc `$`(x: PSym): string = result = x.name.s & " " & " id " & $x.id -proc freshGenSyms(n: PNode, owner, orig: PSym, symMap: var TIdTable) = +proc freshGenSyms(c: PContext; n: PNode, owner, orig: PSym, symMap: var TIdTable) = # we need to create a fresh set of gensym'ed symbols: #if n.kind == nkSym and sfGenSym in n.sym.flags: # if n.sym.owner != orig: @@ -118,12 +118,12 @@ proc freshGenSyms(n: PNode, owner, orig: PSym, symMap: var TIdTable) = n.sym = x elif s.owner == nil or s.owner.kind == skPackage: #echo "copied this ", s.name.s - x = copySym(s) + x = copySym(s, nextId c.idgen) x.owner = owner idTablePut(symMap, s, x) n.sym = x else: - for i in 0..<n.safeLen: freshGenSyms(n[i], owner, orig, symMap) + for i in 0..<n.safeLen: freshGenSyms(c, n[i], owner, orig, symMap) proc addParamOrResult(c: PContext, param: PSym, kind: TSymKind) @@ -144,7 +144,7 @@ proc instantiateBody(c: PContext, n, params: PNode, result, orig: PSym) = let param = params[i].sym if sfGenSym in param.flags: idTablePut(symMap, params[i].sym, result.typ.n[param.position+1].sym) - freshGenSyms(b, result, orig, symMap) + freshGenSyms(c, b, result, orig, symMap) b = semProcBody(c, b) result.ast[bodyPos] = hloBody(c, b) trackProc(c, result, result.ast[bodyPos]) @@ -200,7 +200,7 @@ proc instGenericContainer(c: PContext, info: TLineInfo, header: PType, var param: PSym template paramSym(kind): untyped = - newSym(kind, genParam.sym.name, genericTyp.sym, genParam.sym.info) + newSym(kind, genParam.sym.name, nextId c.idgen, genericTyp.sym, genParam.sym.info) if genParam.kind == tyStatic: param = paramSym skConst @@ -270,7 +270,7 @@ proc instantiateProcType(c: PContext, pt: TIdTable, internalAssert c.config, originalParams[i].kind == nkSym let oldParam = originalParams[i].sym - let param = copySym(oldParam) + let param = copySym(oldParam, nextId c.idgen) param.owner = prc param.typ = result[i] @@ -314,7 +314,7 @@ proc instantiateProcType(c: PContext, pt: TIdTable, propagateToOwner(result, result[0]) eraseVoidParams(result) - skipIntLiteralParams(result) + skipIntLiteralParams(result, c.idgen) prc.typ = result popInfoContext(c.config) @@ -339,7 +339,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable, c.matchedConcept = nil let oldScope = c.currentScope while not isTopLevel(c): c.currentScope = c.currentScope.parent - result = copySym(fn) + result = copySym(fn, nextId c.idgen) incl(result.flags, sfFromGeneric) result.owner = fn result.ast = n diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim index cffd58b92..5e6b4dbe2 100644 --- a/compiler/semmagic.nim +++ b/compiler/semmagic.nim @@ -118,8 +118,8 @@ proc uninstantiate(t: PType): PType = of tyCompositeTypeClass: uninstantiate t[1] else: t -proc getTypeDescNode(typ: PType, sym: PSym, info: TLineInfo): PNode = - var resType = newType(tyTypeDesc, sym) +proc getTypeDescNode(c: PContext; typ: PType, sym: PSym, info: TLineInfo): PNode = + var resType = newType(tyTypeDesc, nextId c.idgen, sym) rawAddSon(resType, typ) result = toNode(resType, info) @@ -133,7 +133,7 @@ proc evalTypeTrait(c: PContext; traitCall: PNode, operand: PType, context: PSym) traitCall[2].typ.skipTypes({tyTypeDesc}) template typeWithSonsResult(kind, sons): PNode = - newTypeWithSons(context, kind, sons).toNode(traitCall.info) + newTypeWithSons(context, kind, sons, c.idgen).toNode(traitCall.info) if operand.kind == tyGenericParam or (traitCall.len > 2 and operand2.kind == tyGenericParam): return traitCall ## too early to evaluate @@ -160,19 +160,19 @@ proc evalTypeTrait(c: PContext; traitCall: PNode, operand: PType, context: PSym) result.info = traitCall.info of "arity": result = newIntNode(nkIntLit, operand.len - ord(operand.kind==tyProc)) - result.typ = newType(tyInt, context) + result.typ = newType(tyInt, nextId c.idgen, context) result.info = traitCall.info of "genericHead": var arg = operand case arg.kind of tyGenericInst: - result = getTypeDescNode(arg.base, operand.owner, traitCall.info) + result = getTypeDescNode(c, arg.base, operand.owner, traitCall.info) # of tySequence: # this doesn't work # var resType = newType(tySequence, operand.owner) # result = toNode(resType, traitCall.info) # doesn't work yet else: localError(c.config, traitCall.info, "expected generic type, got: type $2 of kind $1" % [arg.kind.toHumanStr, typeToString(operand)]) - result = newType(tyError, context).toNode(traitCall.info) + result = newType(tyError, nextId c.idgen, context).toNode(traitCall.info) of "stripGenericParams": result = uninstantiate(operand).toNode(traitCall.info) of "supportsCopyMem": @@ -194,11 +194,11 @@ proc evalTypeTrait(c: PContext; traitCall: PNode, operand: PType, context: PSym) while arg.kind == tyDistinct: arg = arg.base arg = arg.skipTypes(skippedTypes + {tyGenericInst}) - result = getTypeDescNode(arg, operand.owner, traitCall.info) + result = getTypeDescNode(c, arg, operand.owner, traitCall.info) else: localError(c.config, traitCall.info, "distinctBase expects a distinct type as argument. The given type was " & typeToString(operand)) - result = newType(tyError, context).toNode(traitCall.info) + result = newType(tyError, nextId c.idgen, context).toNode(traitCall.info) else: localError(c.config, traitCall.info, "unknown trait: " & s) result = newNodeI(nkEmpty, traitCall.info) @@ -286,7 +286,7 @@ proc semDynamicBindSym(c: PContext, n: PNode): PNode = return semBindSym(c, n) if c.graph.vm.isNil: - setupGlobalCtx(c.module, c.graph) + setupGlobalCtx(c.module, c.graph, c.idgen) let vm = PCtx c.graph.vm @@ -370,7 +370,7 @@ proc semUnown(c: PContext; n: PNode): PNode = elems[i] = unownedType(c, t[i]) if elems[i] != t[i]: someChange = true if someChange: - result = newType(tyTuple, t.owner) + result = newType(tyTuple, nextId c.idgen, t.owner) # we have to use 'rawAddSon' here so that type flags are # properly computed: for e in elems: result.rawAddSon(e) @@ -381,7 +381,7 @@ proc semUnown(c: PContext; n: PNode): PNode = tyGenericInst, tyAlias: let b = unownedType(c, t[^1]) if b != t[^1]: - result = copyType(t, t.owner, keepId = false) + result = copyType(t, nextId c.idgen, t.owner) result[^1] = b result.flags.excl tfHasOwned else: @@ -399,7 +399,7 @@ proc turnFinalizerIntoDestructor(c: PContext; orig: PSym; info: TLineInfo): PSym # Replace nkDerefExpr by nkHiddenDeref # nkDeref is for 'ref T': x[].field # nkHiddenDeref is for 'var T': x<hidden deref [] here>.field - proc transform(procSym: PSym; n: PNode; old, fresh: PType; oldParam, newParam: PSym): PNode = + proc transform(c: PContext; procSym: PSym; n: PNode; old, fresh: PType; oldParam, newParam: PSym): PNode = result = shallowCopy(n) if sameTypeOrNil(n.typ, old): result.typ = fresh @@ -407,26 +407,26 @@ proc turnFinalizerIntoDestructor(c: PContext; orig: PSym; info: TLineInfo): PSym if n.sym == oldParam: result.sym = newParam elif n.sym.owner == orig: - result.sym = copySym(n.sym) + result.sym = copySym(n.sym, nextId c.idgen) result.sym.owner = procSym for i in 0 ..< safeLen(n): - result[i] = transform(procSym, n[i], old, fresh, oldParam, newParam) + result[i] = transform(c, procSym, n[i], old, fresh, oldParam, newParam) #if n.kind == nkDerefExpr and sameType(n[0].typ, old): # result = - result = copySym(orig) + result = copySym(orig, nextId c.idgen) result.info = info result.flags.incl sfFromGeneric result.owner = orig let origParamType = orig.typ[1] - let newParamType = makeVarType(result, origParamType.skipTypes(abstractPtrs)) + let newParamType = makeVarType(result, origParamType.skipTypes(abstractPtrs), c.idgen) let oldParam = orig.typ.n[1].sym - let newParam = newSym(skParam, oldParam.name, result, result.info) + let newParam = newSym(skParam, oldParam.name, nextId c.idgen, result, result.info) newParam.typ = newParamType # proc body: - result.ast = transform(result, orig.ast, origParamType, newParamType, oldParam, newParam) + result.ast = transform(c, result, orig.ast, origParamType, newParamType, oldParam, newParam) # proc signature: - result.typ = newProcType(result.info, result) + result.typ = newProcType(result.info, nextId c.idgen, result) result.typ.addParam newParam proc semQuantifier(c: PContext; n: PNode): PNode = diff --git a/compiler/semparallel.nim b/compiler/semparallel.nim index 578687e6c..82fb069db 100644 --- a/compiler/semparallel.nim +++ b/compiler/semparallel.nim @@ -416,13 +416,13 @@ proc transformSlices(g: ModuleGraph; n: PNode): PNode = else: result = n -proc transformSpawn(g: ModuleGraph; owner: PSym; n, barrier: PNode): PNode -proc transformSpawnSons(g: ModuleGraph; owner: PSym; n, barrier: PNode): PNode = +proc transformSpawn(g: ModuleGraph; idgen: IdGenerator;owner: PSym; n, barrier: PNode): PNode +proc transformSpawnSons(g: ModuleGraph; idgen: IdGenerator; owner: PSym; n, barrier: PNode): PNode = result = shallowCopy(n) for i in 0..<n.len: - result[i] = transformSpawn(g, owner, n[i], barrier) + result[i] = transformSpawn(g, idgen, owner, n[i], barrier) -proc transformSpawn(g: ModuleGraph; owner: PSym; n, barrier: PNode): PNode = +proc transformSpawn(g: ModuleGraph; idgen: IdGenerator; owner: PSym; n, barrier: PNode): PNode = case n.kind of nkVarSection, nkLetSection: result = nil @@ -436,25 +436,25 @@ proc transformSpawn(g: ModuleGraph; owner: PSym; n, barrier: PNode): PNode = result.add n let t = b[1][0].typ[0] if spawnResult(t, true) == srByVar: - result.add wrapProcForSpawn(g, owner, m, b.typ, barrier, it[0]) + result.add wrapProcForSpawn(g, idgen, owner, m, b.typ, barrier, it[0]) it[^1] = newNodeI(nkEmpty, it.info) else: - it[^1] = wrapProcForSpawn(g, owner, m, b.typ, barrier, nil) + it[^1] = wrapProcForSpawn(g, idgen, owner, m, b.typ, barrier, nil) if result.isNil: result = n of nkAsgn, nkFastAsgn: let b = n[1] if getMagic(b) == mSpawn and (let t = b[1][0].typ[0]; spawnResult(t, true) == srByVar): let m = transformSlices(g, b) - return wrapProcForSpawn(g, owner, m, b.typ, barrier, n[0]) - result = transformSpawnSons(g, owner, n, barrier) + return wrapProcForSpawn(g, idgen, owner, m, b.typ, barrier, n[0]) + result = transformSpawnSons(g, idgen, owner, n, barrier) of nkCallKinds: if getMagic(n) == mSpawn: result = transformSlices(g, n) - return wrapProcForSpawn(g, owner, result, n.typ, barrier, nil) - result = transformSpawnSons(g, owner, n, barrier) + return wrapProcForSpawn(g, idgen, owner, result, n.typ, barrier, nil) + result = transformSpawnSons(g, idgen, owner, n, barrier) elif n.safeLen > 0: - result = transformSpawnSons(g, owner, n, barrier) + result = transformSpawnSons(g, idgen, owner, n, barrier) else: result = n @@ -464,7 +464,7 @@ proc checkArgs(a: var AnalysisCtx; n: PNode) = proc generateAliasChecks(a: AnalysisCtx; result: PNode) = discard "too implement" -proc liftParallel*(g: ModuleGraph; owner: PSym; n: PNode): PNode = +proc liftParallel*(g: ModuleGraph; idgen: IdGenerator; owner: PSym; n: PNode): PNode = # this needs to be called after the 'for' loop elimination # first pass: @@ -482,16 +482,16 @@ proc liftParallel*(g: ModuleGraph; owner: PSym; n: PNode): PNode = checkArgs(a, body) var varSection = newNodeI(nkVarSection, n.info) - var temp = newSym(skTemp, getIdent(g.cache, "barrier"), owner, n.info) + var temp = newSym(skTemp, getIdent(g.cache, "barrier"), nextId idgen, owner, n.info) temp.typ = magicsys.getCompilerProc(g, "Barrier").typ incl(temp.flags, sfFromGeneric) let tempNode = newSymNode(temp) varSection.addVar tempNode - let barrier = genAddrOf(tempNode) + let barrier = genAddrOf(tempNode, idgen) result = newNodeI(nkStmtList, n.info) generateAliasChecks(a, result) result.add varSection result.add callCodegenProc(g, "openBarrier", barrier.info, barrier) - result.add transformSpawn(g, owner, body, barrier) + result.add transformSpawn(g, idgen, owner, body, barrier) result.add callCodegenProc(g, "closeBarrier", barrier.info, barrier) diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim index 352871412..92a896a38 100644 --- a/compiler/sempass2.nim +++ b/compiler/sempass2.nim @@ -92,7 +92,7 @@ proc createTypeBoundOps(tracked: PEffects, typ: PType; info: TLineInfo) = optSeqDestructors in tracked.config.globalOptions: createTypeBoundOps(tracked.graph, tracked.c, realType.lastSon, info) - createTypeBoundOps(tracked.graph, tracked.c, typ, info) + createTypeBoundOps(tracked.graph, tracked.c, typ, info, tracked.c.idgen) if (tfHasAsgn in typ.flags) or optSeqDestructors in tracked.config.globalOptions: tracked.owner.flags.incl sfInjectDestructors @@ -219,7 +219,7 @@ proc markGcUnsafe(a: PEffects; reason: PNode) = if reason.kind == nkSym: a.owner.gcUnsafetyReason = reason.sym else: - a.owner.gcUnsafetyReason = newSym(skUnknown, a.owner.name, + a.owner.gcUnsafetyReason = newSym(skUnknown, a.owner.name, nextId a.c.idgen, a.owner, reason.info, {}) when true: @@ -755,7 +755,7 @@ proc trackCall(tracked: PEffects; n: PNode) = if n.typ != nil: if tracked.owner.kind != skMacro and n.typ.skipTypes(abstractVar).kind != tyOpenArray: createTypeBoundOps(tracked, n.typ, n.info) - if getConstExpr(tracked.ownerModule, n, tracked.graph) != nil: + if getConstExpr(tracked.ownerModule, n, tracked.c.idgen, tracked.graph) != nil: return if a.kind == nkCast and a[1].typ.kind == tyProc: a = a[1] @@ -829,7 +829,7 @@ proc trackCall(tracked: PEffects; n: PNode) = case op[i].kind of tySink: createTypeBoundOps(tracked, op[i][0], n.info) - checkForSink(tracked.config, tracked.owner, n[i]) + checkForSink(tracked.config, tracked.c.idgen, tracked.owner, n[i]) of tyVar: tracked.hasDangerousAssign = true #of tyOut: @@ -947,7 +947,7 @@ proc track(tracked: PEffects, n: PNode) = if tracked.owner.kind != skMacro: createTypeBoundOps(tracked, n[0].typ, n.info) if n[0].kind != nkSym or not isLocalVar(tracked, n[0].sym): - checkForSink(tracked.config, tracked.owner, n[1]) + checkForSink(tracked.config, tracked.c.idgen, tracked.owner, n[1]) if not tracked.hasDangerousAssign and n[0].kind != nkSym: tracked.hasDangerousAssign = true of nkVarSection, nkLetSection: @@ -1054,9 +1054,9 @@ proc track(tracked: PEffects, n: PNode) = if x.kind == nkExprColonExpr: if x[0].kind == nkSym: notNilCheck(tracked, x[1], x[0].sym.typ) - checkForSink(tracked.config, tracked.owner, x[1]) + checkForSink(tracked.config, tracked.c.idgen, tracked.owner, x[1]) else: - checkForSink(tracked.config, tracked.owner, x) + checkForSink(tracked.config, tracked.c.idgen, tracked.owner, x) setLen(tracked.guards.s, oldFacts) if tracked.owner.kind != skMacro: # XXX n.typ can be nil in runnableExamples, we need to do something about it. @@ -1071,7 +1071,7 @@ proc track(tracked: PEffects, n: PNode) = createTypeBoundOps(tracked, n[i][0].typ, n.info) else: createTypeBoundOps(tracked, n[i].typ, n.info) - checkForSink(tracked.config, tracked.owner, n[i]) + checkForSink(tracked.config, tracked.c.idgen, tracked.owner, n[i]) of nkPragmaBlock: let pragmaList = n[0] var bc = createBlockContext(tracked) @@ -1122,7 +1122,7 @@ proc track(tracked: PEffects, n: PNode) = of nkBracket: for i in 0..<n.safeLen: track(tracked, n[i]) - checkForSink(tracked.config, tracked.owner, n[i]) + checkForSink(tracked.config, tracked.c.idgen, tracked.owner, n[i]) if tracked.owner.kind != skMacro: createTypeBoundOps(tracked, n.typ, n.info) of nkBracketExpr: diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index b5e69c135..2a058eee2 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -160,12 +160,12 @@ proc semIf(c: PContext, n: PNode; flags: TExprFlags): PNode = openScope(c) it[0] = forceBool(c, semExprWithType(c, it[0])) it[1] = semExprBranch(c, it[1], flags) - typ = commonType(typ, it[1]) + typ = commonType(c, typ, it[1]) closeScope(c) elif it.len == 1: hasElse = true it[0] = semExprBranchScope(c, it[0]) - typ = commonType(typ, it[0]) + typ = commonType(c, typ, it[0]) else: illFormedAst(it, c.config) if isEmptyType(typ) or typ.kind in {tyNil, tyUntyped} or (not hasElse and efInTypeof notin flags): @@ -203,7 +203,7 @@ proc semTry(c: PContext, n: PNode; flags: TExprFlags): PNode = var typ = commonTypeBegin n[0] = semExprBranchScope(c, n[0]) - typ = commonType(typ, n[0].typ) + typ = commonType(c, typ, n[0].typ) var last = n.len - 1 var catchAllExcepts = 0 @@ -223,7 +223,7 @@ proc semTry(c: PContext, n: PNode; flags: TExprFlags): PNode = let isImported = semExceptBranchType(a[0][1]) let symbol = newSymG(skLet, a[0][2], c) symbol.typ = if isImported: a[0][1].typ - else: a[0][1].typ.toRef() + else: a[0][1].typ.toRef(c.idgen) addDecl(c, symbol) # Overwrite symbol in AST with the symbol in the symbol table. a[0][2] = newSymNode(symbol, a[0][2].info) @@ -261,7 +261,7 @@ proc semTry(c: PContext, n: PNode; flags: TExprFlags): PNode = # last child of an nkExcept/nkFinally branch is a statement: a[^1] = semExprBranchScope(c, a[^1]) - if a.kind != nkFinally: typ = commonType(typ, a[^1]) + if a.kind != nkFinally: typ = commonType(c, typ, a[^1]) else: dec last closeScope(c) @@ -411,8 +411,8 @@ proc fillPartialObject(c: PContext; n: PNode; typ: PType) = let y = considerQuotedIdent(c, n[1]) let obj = x.typ.skipTypes(abstractPtrs) if obj.kind == tyObject and tfPartial in obj.flags: - let field = newSym(skField, getIdent(c.cache, y.s), obj.sym, n[1].info) - field.typ = skipIntLit(typ) + let field = newSym(skField, getIdent(c.cache, y.s), nextId c.idgen, obj.sym, n[1].info) + field.typ = skipIntLit(typ, c.idgen) field.position = obj.n.len obj.n.add newSymNode(field) n[0] = makeDeref x @@ -513,7 +513,7 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode = def = fitNode(c, typ, def, def.info) #changeType(def.skipConv, typ, check=true) else: - typ = def.typ.skipTypes({tyStatic}).skipIntLit + typ = def.typ.skipTypes({tyStatic}).skipIntLit(c.idgen) if typ.kind in tyUserTypeClasses and typ.isResolvedUserTypeClass: typ = typ.lastSon if hasEmpty(typ): @@ -621,7 +621,7 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode = if sfCompileTime in v.flags: var x = newNodeI(result.kind, v.info) x.add result[i] - vm.setupCompileTimeVar(c.module, c.graph, x) + vm.setupCompileTimeVar(c.module, c.idgen, c.graph, x) if v.flags * {sfGlobal, sfThread} == {sfGlobal}: message(c.config, v.info, hintGlobalVar) @@ -969,19 +969,19 @@ proc semCase(c: PContext, n: PNode; flags: TExprFlags): PNode = semCaseBranch(c, n, x, i, covered) var last = x.len-1 x[last] = semExprBranchScope(c, x[last]) - typ = commonType(typ, x[last]) + typ = commonType(c, typ, x[last]) of nkElifBranch: chckCovered = false checkSonsLen(x, 2, c.config) openScope(c) x[0] = forceBool(c, semExprWithType(c, x[0])) x[1] = semExprBranch(c, x[1]) - typ = commonType(typ, x[1]) + typ = commonType(c, typ, x[1]) closeScope(c) of nkElse: checkSonsLen(x, 1, c.config) x[0] = semExprBranchScope(c, x[0]) - typ = commonType(typ, x[0]) + typ = commonType(c, typ, x[0]) if (chckCovered and covered == toCover(c, n[0].typ)) or hasElse: message(c.config, x.info, warnUnreachableElse) hasElse = true @@ -1276,7 +1276,7 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) = internalAssert c.config, st.lastSon.sym == nil incl st.flags, tfRefsAnonObj let obj = newSym(skType, getIdent(c.cache, s.name.s & ":ObjectType"), - getCurrOwner(c), s.info) + nextId c.idgen, getCurrOwner(c), s.info) obj.ast = a if sfPure in s.flags: obj.flags.incl sfPure @@ -1337,11 +1337,11 @@ proc typeSectionFinalPass(c: PContext, n: PNode) = if s.typ != nil and s.typ.kind notin {tyAlias, tySink}: if t.kind in {tyProc, tyGenericInst} and not t.isMetaType: assignType(s.typ, t) - s.typ.id = t.id + s.typ.itemId = t.itemId elif t.kind in {tyObject, tyEnum, tyDistinct}: assert s.typ != nil assignType(s.typ, t) - s.typ.id = t.id # same id + s.typ.itemId = t.itemId # same id checkConstructedType(c.config, s.info, s.typ) if s.typ.kind in {tyObject, tyTuple} and not s.typ.n.isNil: checkForMetaFields(c, s.typ.n) @@ -1437,7 +1437,7 @@ proc addResult(c: PContext, n: PNode, t: PType, owner: TSymKind) = localError(c.config, n.info, "incorrect result proc symbol") c.p.resultSym = n[resultPos].sym else: - var s = newSym(skResult, getIdent(c.cache, "result"), getCurrOwner(c), n.info) + var s = newSym(skResult, getIdent(c.cache, "result"), nextId c.idgen, getCurrOwner(c), n.info) s.typ = t incl(s.flags, sfUsed) c.p.resultSym = s @@ -1535,7 +1535,7 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode = checkSonsLen(n, bodyPos + 1, c.config) var s: PSym if n[namePos].kind != nkSym: - s = newSym(skProc, c.cache.idAnon, getCurrOwner(c), n.info) + s = newSym(skProc, c.cache.idAnon, nextId c.idgen, getCurrOwner(c), n.info) s.ast = n n[namePos] = newSymNode(s) else: @@ -1800,7 +1800,7 @@ proc hasObjParam(s: PSym): bool = proc finishMethod(c: PContext, s: PSym) = if hasObjParam(s): - methodDef(c.graph, s, false) + methodDef(c.graph, c.idgen, s, false) proc semMethodPrototype(c: PContext; s: PSym; n: PNode) = if isGenericRoutine(s): @@ -1825,7 +1825,7 @@ proc semMethodPrototype(c: PContext; s: PSym; n: PNode) = # no sense either. # and result[bodyPos].kind != nkEmpty: if hasObjParam(s): - methodDef(c.graph, s, fromCache=false) + methodDef(c.graph, c.idgen, s, fromCache=false) else: localError(c.config, n.info, "'method' needs a parameter that has an object type") @@ -1843,7 +1843,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind, assert phase == stepRegisterSymbol if n[namePos].kind == nkEmpty: - s = newSym(kind, c.cache.idAnon, getCurrOwner(c), n.info) + s = newSym(kind, c.cache.idAnon, nextId c.idgen, getCurrOwner(c), n.info) incl(s.flags, sfUsed) isAnon = true else: @@ -1998,7 +1998,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind, if s.kind == skMethod: semMethodPrototype(c, s, n) else: if (s.typ[0] != nil and kind != skIterator) or kind == skMacro: - addDecl(c, newSym(skUnknown, getIdent(c.cache, "result"), nil, n.info)) + addDecl(c, newSym(skUnknown, getIdent(c.cache, "result"), nextId c.idgen, nil, n.info)) openScope(c) n[bodyPos] = semGenericStmt(c, n[bodyPos]) @@ -2189,7 +2189,7 @@ proc semStaticStmt(c: PContext, n: PNode): PNode = closeScope(c) dec c.inStaticContext n[0] = a - evalStaticStmt(c.module, c.graph, a, c.p.owner) + evalStaticStmt(c.module, c.idgen, c.graph, a, c.p.owner) when false: # for incremental replays, keep the AST as required for replays: result = n diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim index df832c814..03bf1af92 100644 --- a/compiler/semtempl.nim +++ b/compiler/semtempl.nim @@ -176,7 +176,7 @@ proc onlyReplaceParams(c: var TemplCtx, n: PNode): PNode = result[i] = onlyReplaceParams(c, n[i]) proc newGenSym(kind: TSymKind, n: PNode, c: var TemplCtx): PSym = - result = newSym(kind, considerQuotedIdent(c.c, n), c.owner, n.info) + result = newSym(kind, considerQuotedIdent(c.c, n), nextId c.c.idgen, c.owner, n.info) incl(result.flags, sfGenSym) incl(result.flags, sfShadowed) @@ -239,12 +239,12 @@ proc semTemplSymbol(c: PContext, n: PNode, s: PSym; isField: bool): PNode = result = symChoice(c, n, s, scOpen, isField) of skGenericParam: if isField and sfGenSym in s.flags: result = n - else: result = newSymNodeTypeDesc(s, n.info) + else: result = newSymNodeTypeDesc(s, c.idgen, n.info) of skParam: result = n of skType: if isField and sfGenSym in s.flags: result = n - else: result = newSymNodeTypeDesc(s, n.info) + else: result = newSymNodeTypeDesc(s, c.idgen, n.info) else: if isField and sfGenSym in s.flags: result = n else: result = newSymNode(s, n.info) diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index f2bb82a5c..97cf7c5ec 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -51,7 +51,7 @@ proc newOrPrevType(kind: TTypeKind, prev: PType, c: PContext): PType = proc newConstraint(c: PContext, k: TTypeKind): PType = result = newTypeS(tyBuiltInTypeClass, c) result.flags.incl tfCheckedForDestructor - result.addSonSkipIntLit(newTypeS(k, c)) + result.addSonSkipIntLit(newTypeS(k, c), c.idgen) proc semEnum(c: PContext, n: PNode, prev: PType): PType = if n.len == 0: return newConstraint(c, tyEnum) @@ -156,7 +156,7 @@ proc semSet(c: PContext, n: PNode, prev: PType): PType = result = newOrPrevType(tySet, prev, c) if n.len == 2 and n[1].kind != nkEmpty: var base = semTypeNode(c, n[1], nil) - addSonSkipIntLit(result, base) + addSonSkipIntLit(result, base, c.idgen) if base.kind in {tyGenericInst, tyAlias, tySink}: base = lastSon(base) if base.kind != tyGenericParam: if not isOrdinalType(base, allowEnumWithHoles = true): @@ -165,17 +165,17 @@ proc semSet(c: PContext, n: PNode, prev: PType): PType = localError(c.config, n.info, errSetTooBig) else: localError(c.config, n.info, errXExpectsOneTypeParam % "set") - addSonSkipIntLit(result, errorType(c)) + addSonSkipIntLit(result, errorType(c), c.idgen) proc semContainerArg(c: PContext; n: PNode, kindStr: string; result: PType) = if n.len == 2: var base = semTypeNode(c, n[1], nil) if base.kind == tyVoid: localError(c.config, n.info, errTIsNotAConcreteType % typeToString(base)) - addSonSkipIntLit(result, base) + addSonSkipIntLit(result, base, c.idgen) else: localError(c.config, n.info, errXExpectsOneTypeParam % kindStr) - addSonSkipIntLit(result, errorType(c)) + addSonSkipIntLit(result, errorType(c), c.idgen) proc semContainer(c: PContext, n: PNode, kind: TTypeKind, kindStr: string, prev: PType): PType = @@ -186,12 +186,12 @@ proc semVarargs(c: PContext, n: PNode, prev: PType): PType = result = newOrPrevType(tyVarargs, prev, c) if n.len == 2 or n.len == 3: var base = semTypeNode(c, n[1], nil) - addSonSkipIntLit(result, base) + addSonSkipIntLit(result, base, c.idgen) if n.len == 3: result.n = newIdentNode(considerQuotedIdent(c, n[2]), n[2].info) else: localError(c.config, n.info, errXExpectsOneTypeParam % "varargs") - addSonSkipIntLit(result, errorType(c)) + addSonSkipIntLit(result, errorType(c), c.idgen) proc semVarOutType(c: PContext, n: PNode, prev: PType; kind: TTypeKind): PType = if n.len == 1: @@ -200,14 +200,14 @@ proc semVarOutType(c: PContext, n: PNode, prev: PType; kind: TTypeKind): PType = if base.kind == tyVar: localError(c.config, n.info, "type 'var var' is not allowed") base = base[0] - addSonSkipIntLit(result, base) + addSonSkipIntLit(result, base, c.idgen) else: result = newConstraint(c, kind) proc semDistinct(c: PContext, n: PNode, prev: PType): PType = if n.len == 0: return newConstraint(c, tyDistinct) result = newOrPrevType(tyDistinct, prev, c) - addSonSkipIntLit(result, semTypeNode(c, n[0], nil)) + addSonSkipIntLit(result, semTypeNode(c, n[0], nil), c.idgen) if n.len > 1: result.n = n[1] proc semRangeAux(c: PContext, n: PNode, prev: PType): PType = @@ -217,7 +217,7 @@ proc semRangeAux(c: PContext, n: PNode, prev: PType): PType = result.n = newNodeI(nkRange, n.info) # always create a 'valid' range type, but overwrite it later # because 'semExprWithType' can raise an exception. See bug #6895. - addSonSkipIntLit(result, errorType(c)) + addSonSkipIntLit(result, errorType(c), c.idgen) if (n[1].kind == nkEmpty) or (n[2].kind == nkEmpty): localError(c.config, n.info, "range is empty") @@ -228,7 +228,7 @@ proc semRangeAux(c: PContext, n: PNode, prev: PType): PType = var rangeT: array[2, PType] for i in 0..1: - rangeT[i] = range[i].typ.skipTypes({tyStatic}).skipIntLit + rangeT[i] = range[i].typ.skipTypes({tyStatic}).skipIntLit(c.idgen) let hasUnknownTypes = c.inGenericContext > 0 and rangeT[0].kind == tyFromExpr or rangeT[1].kind == tyFromExpr @@ -345,7 +345,7 @@ proc semArray(c: PContext, n: PNode, prev: PType): PType = # bug #6682: Do not propagate initialization requirements etc for the # index type: rawAddSonNoPropagationOfTypeFlags(result, indx) - addSonSkipIntLit(result, base) + addSonSkipIntLit(result, base, c.idgen) else: localError(c.config, n.info, errArrayExpectsTwoTypeParams) result = newOrPrevType(tyError, prev, c) @@ -357,7 +357,7 @@ proc semOrdinal(c: PContext, n: PNode, prev: PType): PType = if base.kind != tyGenericParam: if not isOrdinalType(base): localError(c.config, n[1].info, errOrdinalTypeExpected) - addSonSkipIntLit(result, base) + addSonSkipIntLit(result, base, c.idgen) else: localError(c.config, n.info, errXExpectsOneTypeParam % "ordinal") result = newOrPrevType(tyError, prev, c) @@ -384,7 +384,7 @@ proc semTypeIdent(c: PContext, n: PNode): PSym = if result.typ.sym == nil: localError(c.config, n.info, errTypeExpected) return errorSym(c, n) - result = result.typ.sym.copySym + result = result.typ.sym.copySym(nextId c.idgen) result.typ = exactReplica(result.typ) result.typ.flags.incl tfUnresolved @@ -429,7 +429,7 @@ proc semAnonTuple(c: PContext, n: PNode, prev: PType): PType = localError(c.config, n.info, errTypeExpected) result = newOrPrevType(tyTuple, prev, c) for it in n: - addSonSkipIntLit(result, semTypeNode(c, it, nil)) + addSonSkipIntLit(result, semTypeNode(c, it, nil), c.idgen) proc semTuple(c: PContext, n: PNode, prev: PType): PType = var typ: PType @@ -457,15 +457,13 @@ proc semTuple(c: PContext, n: PNode, prev: PType): PType = localError(c.config, a[j].info, "attempt to redefine: '" & field.name.s & "'") else: result.n.add newSymNode(field) - addSonSkipIntLit(result, typ) + addSonSkipIntLit(result, typ, c.idgen) styleCheckDef(c.config, a[j].info, field) onDef(field.info, field) if result.n.len == 0: result.n = nil if isTupleRecursive(result): localError(c.config, n.info, errIllegalRecursionInTypeX % typeToString(result)) - - proc semIdentVis(c: PContext, kind: TSymKind, n: PNode, allowed: TSymFlags): PSym = # identifier with visibility @@ -925,11 +923,11 @@ proc semAnyRef(c: PContext; n: PNode; kind: TTypeKind; prev: PType): PType = elif region.skipTypes({tyGenericInst, tyAlias, tySink}).kind notin { tyError, tyObject}: message c.config, n[i].info, errGenerated, "region needs to be an object type" - addSonSkipIntLit(result, region) + addSonSkipIntLit(result, region, c.idgen) else: message(c.config, n.info, warnDeprecated, "region for pointer types is deprecated") - addSonSkipIntLit(result, region) - addSonSkipIntLit(result, t) + addSonSkipIntLit(result, region, c.idgen) + addSonSkipIntLit(result, t, c.idgen) if tfPartial in result.flags: if result.lastSon.kind == tyObject: incl(result.lastSon.flags, tfPartial) #if not isNilable: result.flags.incl tfNotNil @@ -963,7 +961,7 @@ proc addParamOrResult(c: PContext, param: PSym, kind: TSymKind) = if kind == skMacro: let staticType = findEnforcedStaticType(param.typ) if staticType != nil: - var a = copySym(param) + var a = copySym(param, nextId c.idgen) a.typ = staticType.base addDecl(c, a) #elif param.typ != nil and param.typ.kind == tyTypeDesc: @@ -971,7 +969,7 @@ proc addParamOrResult(c: PContext, param: PSym, kind: TSymKind) = else: # within a macro, every param has the type NimNode! let nn = getSysSym(c.graph, param.info, "NimNode") - var a = copySym(param) + var a = copySym(param, nextId c.idgen) a.typ = nn.typ addDecl(c, a) else: @@ -1001,7 +999,7 @@ proc addImplicitGeneric(c: PContext; typeClass: PType, typId: PIdent; let owner = if typeClass.sym != nil: typeClass.sym else: getCurrOwner(c) - var s = newSym(skType, finalTypId, owner, info) + var s = newSym(skType, finalTypId, nextId c.idgen, owner, info) if sfExplain in owner.flags: s.flags.incl sfExplain if typId == nil: s.flags.incl(sfAnon) s.linkTo(typeClass) @@ -1107,7 +1105,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode, of tyGenericInst: if paramType.lastSon.kind == tyUserTypeClass: - var cp = copyType(paramType, getCurrOwner(c), false) + var cp = copyType(paramType, nextId c.idgen, getCurrOwner(c)) cp.kind = tyUserTypeClassInst return addImplicitGeneric(c, cp, paramTypId, info, genericParams, paramName) @@ -1144,7 +1142,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode, of tyUserTypeClasses, tyBuiltInTypeClass, tyCompositeTypeClass, tyAnd, tyOr, tyNot: result = addImplicitGeneric(c, - copyType(paramType, getCurrOwner(c), false), paramTypId, + copyType(paramType, nextId c.idgen, getCurrOwner(c)), paramTypId, info, genericParams, paramName) of tyGenericParam: @@ -1274,7 +1272,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode, typ = errorType(c) let lifted = liftParamType(c, kind, genericParams, typ, arg.name.s, arg.info) - let finalType = if lifted != nil: lifted else: typ.skipIntLit + let finalType = if lifted != nil: lifted else: typ.skipIntLit(c.idgen) arg.typ = finalType arg.position = counter arg.constraint = constraint @@ -1331,7 +1329,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode, #if r.kind != tyGenericParam: #echo "came here for ", typeToString(r) r.flags.incl tfRetType - r = skipIntLit(r) + r = skipIntLit(r, c.idgen) if kind == skIterator: # see tchainediterators # in cases like iterator foo(it: iterator): type(it) @@ -1413,13 +1411,13 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType = t = t.base result = newOrPrevType(tyGenericInvocation, prev, c) - addSonSkipIntLit(result, t) + addSonSkipIntLit(result, t, c.idgen) template addToResult(typ) = if typ.isNil: internalAssert c.config, false rawAddSon(result, typ) - else: addSonSkipIntLit(result, typ) + else: addSonSkipIntLit(result, typ, c.idgen) if t.kind == tyForward: for i in 1..<n.len: @@ -1518,9 +1516,9 @@ proc semTypeExpr(c: PContext, n: PNode; prev: PType): PType = localError(c.config, n.info, "expected type, but got: " & n.renderTree) result = errorType(c) -proc freshType(res, prev: PType): PType {.inline.} = +proc freshType(c: PContext; res, prev: PType): PType {.inline.} = if prev.isNil: - result = copyType(res, res.owner, keepId=false) + result = copyType(res, nextId c.idgen, res.owner) else: result = res @@ -1542,7 +1540,7 @@ proc semTypeClass(c: PContext, n: PNode, prev: PType): PType = result = newOrPrevType(tyUserTypeClass, prev, c) result.flags.incl tfCheckedForDestructor var owner = getCurrOwner(c) - var candidateTypeSlot = newTypeWithSons(owner, tyAlias, @[c.errorType]) + var candidateTypeSlot = newTypeWithSons(owner, tyAlias, @[c.errorType], c.idgen) result.sons = @[candidateTypeSlot] result.n = n @@ -1575,7 +1573,7 @@ proc semTypeClass(c: PContext, n: PNode, prev: PType): PType = internalAssert c.config, dummyName.kind == nkIdent var dummyParam = newSym(if modifier == tyTypeDesc: skType else: skVar, - dummyName.ident, owner, param.info) + dummyName.ident, nextId c.idgen, owner, param.info) dummyParam.typ = dummyType incl dummyParam.flags, sfUsed addDecl(c, dummyParam) @@ -1713,7 +1711,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = result = semTypeNode(c, n[1], prev) if result.skipTypes({tyGenericInst, tyAlias, tySink, tyOwned}).kind in NilableTypes+GenericTypes: if tfNotNil in result.flags: - result = freshType(result, prev) + result = freshType(c, result, prev) result.flags.excl(tfNotNil) else: localError(c.config, n.info, errGenerated, "invalid type") @@ -1774,7 +1772,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = # to other types such as `Option[T]`. result = makeTypeFromExpr(c, newTree(nkStmtListType, n.copyTree)) of NilableTypes + {tyGenericInvocation, tyForward}: - result = freshType(result, prev) + result = freshType(c, result, prev) result.flags.incl(tfNotNil) else: localError(c.config, n.info, errGenerated, "invalid type") @@ -1828,19 +1826,19 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = of mExpr: result = semTypeNode(c, n[0], nil) if result != nil: - result = copyType(result, getCurrOwner(c), false) + result = copyType(result, nextId c.idgen, getCurrOwner(c)) for i in 1..<n.len: result.rawAddSon(semTypeNode(c, n[i], nil)) of mDistinct: result = newOrPrevType(tyDistinct, prev, c) - addSonSkipIntLit(result, semTypeNode(c, n[1], nil)) + addSonSkipIntLit(result, semTypeNode(c, n[1], nil), c.idgen) of mVar: result = newOrPrevType(tyVar, prev, c) var base = semTypeNode(c, n[1], nil) if base.kind in {tyVar, tyLent}: localError(c.config, n.info, "type 'var var' is not allowed") base = base[0] - addSonSkipIntLit(result, base) + addSonSkipIntLit(result, base, c.idgen) of mRef: result = semAnyRef(c, n, tyRef, prev) of mPtr: result = semAnyRef(c, n, tyPtr, prev) of mTuple: result = semTuple(c, n, prev) @@ -1886,7 +1884,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = # bugfix: keep the fresh id for aliases to integral types: if s.typ.kind notin {tyBool, tyChar, tyInt..tyInt64, tyFloat..tyFloat128, tyUInt..tyUInt64}: - prev.id = s.typ.id + prev.itemId = s.typ.itemId result = prev of nkSym: let s = getGenSym(c, n.sym) @@ -1929,7 +1927,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = result = newTypeS(tyBuiltInTypeClass, c) let child = newTypeS(tyProc, c) child.flags.incl tfIterator - result.addSonSkipIntLit(child) + result.addSonSkipIntLit(child, c.idgen) else: result = semProcTypeWithScope(c, n, prev, skIterator) if result.kind == tyProc: @@ -2060,7 +2058,7 @@ proc semGenericConstraints(c: PContext, x: PType): PType = proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode = template addSym(result: PNode, s: PSym): untyped = - if father != nil: addSonSkipIntLit(father, s.typ) + if father != nil: addSonSkipIntLit(father, s.typ, c.idgen) if sfGenSym notin s.flags: addDecl(c, s) result.add newSymNode(s) @@ -2107,7 +2105,7 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode = for j in 0..<a.len-2: let finalType = if j == 0: typ - else: copyType(typ, typ.owner, false) + else: copyType(typ, nextId c.idgen, typ.owner) # it's important the we create an unique # type for each generic param. the index # of the parameter will be stored in the diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim index 68ba93ebc..931581d12 100644 --- a/compiler/semtypinst.nim +++ b/compiler/semtypinst.nim @@ -279,7 +279,7 @@ proc replaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym = var g: G[string] ]# - result = copySym(s) + result = copySym(s, nextId cl.c.idgen) incl(result.flags, sfFromGeneric) #idTablePut(cl.symMap, s, result) result.owner = s.owner @@ -302,7 +302,12 @@ proc lookupTypeVar(cl: var TReplTypeVars, t: PType): PType = proc instCopyType*(cl: var TReplTypeVars, t: PType): PType = # XXX: relying on allowMetaTypes is a kludge - result = copyType(t, t.owner, cl.allowMetaTypes) + if cl.allowMetaTypes: + result = t.exactReplica + else: + result = copyType(t, nextId(cl.c.idgen), t.owner) + #cl.typeMap.topLayer.idTablePut(result, t) + if cl.allowMetaTypes: return result.flags.incl tfFromGeneric if not (t.kind in tyMetaTypes or @@ -355,7 +360,7 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType = else: header = instCopyType(cl, t) - result = newType(tyGenericInst, t[0].owner) + result = newType(tyGenericInst, nextId(cl.c.idgen), t[0].owner) result.flags = header.flags # be careful not to propagate unnecessary flags here (don't use rawAddSon) result.sons = @[header[0]] @@ -459,11 +464,11 @@ proc eraseVoidParams*(t: PType) = setLen t.n.sons, pos break -proc skipIntLiteralParams*(t: PType) = +proc skipIntLiteralParams*(t: PType; idgen: IdGenerator) = for i in 0..<t.len: let p = t[i] if p == nil: continue - let skipped = p.skipIntLit + let skipped = p.skipIntLit(idgen) if skipped != p: t[i] = skipped if i > 0: t.n[i].sym.typ = skipped @@ -553,7 +558,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType = result = n.typ of tyInt, tyFloat: - result = skipIntLit(t) + result = skipIntLit(t, cl.c.idgen) of tyTypeDesc: let lookup = cl.typeMap.lookup(t) @@ -617,7 +622,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType = of tyProc: eraseVoidParams(result) - skipIntLiteralParams(result) + skipIntLiteralParams(result, cl.c.idgen) of tyRange: result[0] = result[0].skipTypes({tyStatic, tyDistinct}) diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 687634e93..2cf2846c0 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -143,7 +143,7 @@ proc put(c: var TCandidate, key, val: PType) {.inline.} = writeStackTrace() if c.c.module.name.s == "temp3": echo "binding ", key, " -> ", val - idTablePut(c.bindings, key, val.skipIntLit) + idTablePut(c.bindings, key, val.skipIntLit(c.c.idgen)) proc initCandidate*(ctx: PContext, c: var TCandidate, callee: PSym, binding: PNode, calleeScope = -1, @@ -726,7 +726,7 @@ proc matchUserTypeClass*(m: var TCandidate; ff, a: PType): PType = if alreadyBound != nil: typ = alreadyBound template paramSym(kind): untyped = - newSym(kind, typeParamName, typeClass.sym, typeClass.sym.info, {}) + newSym(kind, typeParamName, nextId(c.idgen), typeClass.sym, typeClass.sym.info, {}) block addTypeParam: for prev in typeParams: @@ -739,6 +739,7 @@ proc matchUserTypeClass*(m: var TCandidate; ff, a: PType): PType = of tyStatic: param = paramSym skConst param.typ = typ.exactReplica + #copyType(typ, nextId(c.idgen), typ.owner) if typ.n == nil: param.typ.flags.incl tfInferrableStatic else: @@ -746,6 +747,7 @@ proc matchUserTypeClass*(m: var TCandidate; ff, a: PType): PType = of tyUnknown: param = paramSym skVar param.typ = typ.exactReplica + #copyType(typ, nextId(c.idgen), typ.owner) else: param = paramSym skType param.typ = if typ.isMetaType: @@ -796,7 +798,8 @@ proc matchUserTypeClass*(m: var TCandidate; ff, a: PType): PType = if ff.kind == tyUserTypeClassInst: result = generateTypeInstance(c, m.bindings, typeClass.sym.info, ff) else: - result = copyType(ff, ff.owner, true) + result = ff.exactReplica + #copyType(ff, nextId(c.idgen), ff.owner) result.n = checkedBody @@ -1086,7 +1089,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, template bindingRet(res) = if doBind: - let bound = aOrig.skipTypes({tyRange}).skipIntLit + let bound = aOrig.skipTypes({tyRange}).skipIntLit(c.c.idgen) put(c, f, bound) return res @@ -1500,14 +1503,15 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, of tyGenericInvocation: var x = a.skipGenericAlias + var preventHack = false if x.kind == tyOwned and f[0].kind != tyOwned: preventHack = true x = x.lastSon # XXX: This is very hacky. It should be moved back into liftTypeParam if x.kind in {tyGenericInst, tyArray} and - c.calleeSym != nil and - c.calleeSym.kind in {skProc, skFunc} and c.call != nil and not preventHack: + c.calleeSym != nil and + c.calleeSym.kind in {skProc, skFunc} and c.call != nil and not preventHack: let inst = prepareMetatypeForSigmatch(c.c, c.bindings, c.call.info, f) #echo "inferred ", typeToString(inst), " for ", f return typeRel(c, inst, a, flags) @@ -2291,7 +2295,7 @@ proc arrayConstr(c: PContext, n: PNode): PType = result = newTypeS(tyArray, c) rawAddSon(result, makeRangeType(c, 0, 0, n.info)) addSonSkipIntLit(result, skipTypes(n.typ, - {tyGenericInst, tyVar, tyLent, tyOrdinal})) + {tyGenericInst, tyVar, tyLent, tyOrdinal}), c.idgen) proc arrayConstr(c: PContext, info: TLineInfo): PType = result = newTypeS(tyArray, c) diff --git a/compiler/sinkparameter_inference.nim b/compiler/sinkparameter_inference.nim index 182e44324..841f2de8e 100644 --- a/compiler/sinkparameter_inference.nim +++ b/compiler/sinkparameter_inference.nim @@ -7,7 +7,7 @@ # distribution, for details about the copyright. # -proc checkForSink*(config: ConfigRef; owner: PSym; arg: PNode) = +proc checkForSink*(config: ConfigRef; idgen: IdGenerator; owner: PSym; arg: PNode) = #[ Patterns we seek to detect: someLocation = p # ---> p: sink T @@ -32,7 +32,7 @@ proc checkForSink*(config: ConfigRef; owner: PSym; arg: PNode) = if sfWasForwarded notin owner.flags: let argType = arg.sym.typ - let sinkType = newType(tySink, owner) + let sinkType = newType(tySink, nextId(idgen), owner) sinkType.size = argType.size sinkType.align = argType.align sinkType.paddingAtEnd = argType.paddingAtEnd @@ -52,18 +52,18 @@ proc checkForSink*(config: ConfigRef; owner: PSym; arg: PNode) = #echo config $ arg.info, " candidate for a sink parameter here" of nkStmtList, nkStmtListExpr, nkBlockStmt, nkBlockExpr: if not isEmptyType(arg.typ): - checkForSink(config, owner, arg.lastSon) + checkForSink(config, idgen, owner, arg.lastSon) of nkIfStmt, nkIfExpr, nkWhen: for branch in arg: let value = branch.lastSon if not isEmptyType(value.typ): - checkForSink(config, owner, value) + checkForSink(config, idgen, owner, value) of nkCaseStmt: for i in 1..<arg.len: let value = arg[i].lastSon if not isEmptyType(value.typ): - checkForSink(config, owner, value) + checkForSink(config, idgen, owner, value) of nkTryStmt: - checkForSink(config, owner, arg[0]) + checkForSink(config, idgen, owner, arg[0]) else: discard "nothing to do" diff --git a/compiler/spawn.nim b/compiler/spawn.nim index 15bed77b0..65e19b8db 100644 --- a/compiler/spawn.nim +++ b/compiler/spawn.nim @@ -53,9 +53,9 @@ proc typeNeedsNoDeepCopy(t: PType): bool = if t.kind in {tyVar, tyLent, tySequence}: t = t.lastSon result = not containsGarbageCollectedRef(t) -proc addLocalVar(g: ModuleGraph; varSection, varInit: PNode; owner: PSym; typ: PType; +proc addLocalVar(g: ModuleGraph; varSection, varInit: PNode; idgen: IdGenerator; owner: PSym; typ: PType; v: PNode; useShallowCopy=false): PSym = - result = newSym(skTemp, getIdent(g.cache, genPrefix), owner, varSection.info, + result = newSym(skTemp, getIdent(g.cache, genPrefix), nextId idgen, owner, varSection.info, owner.options) result.typ = typ incl(result.flags, sfFromGeneric) @@ -111,22 +111,23 @@ stmtList: proc createWrapperProc(g: ModuleGraph; f: PNode; threadParam, argsParam: PSym; varSection, varInit, call, barrier, fv: PNode; + idgen: IdGenerator; spawnKind: TSpawnResult, result: PSym) = var body = newNodeI(nkStmtList, f.info) var threadLocalBarrier: PSym if barrier != nil: var varSection2 = newNodeI(nkVarSection, barrier.info) - threadLocalBarrier = addLocalVar(g, varSection2, nil, result, + threadLocalBarrier = addLocalVar(g, varSection2, nil, idgen, result, barrier.typ, barrier) body.add varSection2 body.add callCodegenProc(g, "barrierEnter", threadLocalBarrier.info, threadLocalBarrier.newSymNode) var threadLocalProm: PSym if spawnKind == srByVar: - threadLocalProm = addLocalVar(g, varSection, nil, result, fv.typ, fv) + threadLocalProm = addLocalVar(g, varSection, nil, idgen, result, fv.typ, fv) elif fv != nil: internalAssert g.config, fv.typ.kind == tyGenericInst - threadLocalProm = addLocalVar(g, varSection, nil, result, fv.typ, fv) + threadLocalProm = addLocalVar(g, varSection, nil, idgen, result, fv.typ, fv) body.add varSection body.add varInit if fv != nil and spawnKind != srByVar: @@ -168,7 +169,7 @@ proc createWrapperProc(g: ModuleGraph; f: PNode; threadParam, argsParam: PSym; params.add threadParam.newSymNode params.add argsParam.newSymNode - var t = newType(tyProc, threadParam.owner) + var t = newType(tyProc, nextId idgen, threadParam.owner) t.rawAddSon nil t.rawAddSon threadParam.typ t.rawAddSon argsParam.typ @@ -184,15 +185,15 @@ proc createWrapperProc(g: ModuleGraph; f: PNode; threadParam, argsParam: PSym; exceptions = emptyNode) result.typ = t -proc createCastExpr(argsParam: PSym; objType: PType): PNode = +proc createCastExpr(argsParam: PSym; objType: PType; idgen: IdGenerator): PNode = result = newNodeI(nkCast, argsParam.info) result.add newNodeI(nkEmpty, argsParam.info) result.add newSymNode(argsParam) - result.typ = newType(tyPtr, objType.owner) + result.typ = newType(tyPtr, nextId idgen, objType.owner) result.typ.rawAddSon(objType) proc setupArgsForConcurrency(g: ModuleGraph; n: PNode; objType: PType; - owner: PSym; scratchObj: PSym, + idgen: IdGenerator; owner: PSym; scratchObj: PSym, castExpr, call, varSection, varInit, result: PNode) = let formals = n[0].typ.n @@ -210,16 +211,17 @@ proc setupArgsForConcurrency(g: ModuleGraph; n: PNode; objType: PType; # localError(n[i].info, "'spawn'ed function cannot refer to 'ref'/closure") let fieldname = if i < formals.len: formals[i].sym.name else: tmpName - var field = newSym(skField, fieldname, objType.owner, n.info, g.config.options) + var field = newSym(skField, fieldname, nextId idgen, objType.owner, n.info, g.config.options) field.typ = argType - objType.addField(field, g.cache) + objType.addField(field, g.cache, idgen) result.add newFastAsgnStmt(newDotExpr(scratchObj, field), n[i]) - let temp = addLocalVar(g, varSection, varInit, owner, argType, + let temp = addLocalVar(g, varSection, varInit, idgen, owner, argType, indirectAccess(castExpr, field, n.info)) call.add(newSymNode(temp)) proc setupArgsForParallelism(g: ModuleGraph; n: PNode; objType: PType; + idgen: IdGenerator; owner: PSym; scratchObj: PSym; castExpr, call, varSection, varInit, result: PNode) = @@ -237,7 +239,7 @@ proc setupArgsForParallelism(g: ModuleGraph; n: PNode; objType: PType; # localError(n.info, "'spawn'ed function cannot refer to 'ref'/closure") let fieldname = if i < formals.len: formals[i].sym.name else: tmpName - var field = newSym(skField, fieldname, objType.owner, n.info, g.config.options) + var field = newSym(skField, fieldname, nextId idgen, objType.owner, n.info, g.config.options) if argType.kind in {tyVarargs, tyOpenArray}: # important special case: we always create a zero-copy slice: @@ -245,30 +247,30 @@ proc setupArgsForParallelism(g: ModuleGraph; n: PNode; objType: PType; slice.typ = n.typ slice[0] = newSymNode(createMagic(g, "slice", mSlice)) slice[0].typ = getSysType(g, n.info, tyInt) # fake type - var fieldB = newSym(skField, tmpName, objType.owner, n.info, g.config.options) + var fieldB = newSym(skField, tmpName, nextId idgen, objType.owner, n.info, g.config.options) fieldB.typ = getSysType(g, n.info, tyInt) - objType.addField(fieldB, g.cache) + objType.addField(fieldB, g.cache, idgen) if getMagic(n) == mSlice: - let a = genAddrOf(n[1]) + let a = genAddrOf(n[1], idgen) field.typ = a.typ - objType.addField(field, g.cache) + objType.addField(field, g.cache, idgen) result.add newFastAsgnStmt(newDotExpr(scratchObj, field), a) - var fieldA = newSym(skField, tmpName, objType.owner, n.info, g.config.options) + var fieldA = newSym(skField, tmpName, nextId idgen, objType.owner, n.info, g.config.options) fieldA.typ = getSysType(g, n.info, tyInt) - objType.addField(fieldA, g.cache) + objType.addField(fieldA, g.cache, idgen) result.add newFastAsgnStmt(newDotExpr(scratchObj, fieldA), n[2]) result.add newFastAsgnStmt(newDotExpr(scratchObj, fieldB), n[3]) - let threadLocal = addLocalVar(g, varSection,nil, owner, fieldA.typ, + let threadLocal = addLocalVar(g, varSection, nil, idgen, owner, fieldA.typ, indirectAccess(castExpr, fieldA, n.info), useShallowCopy=true) slice[2] = threadLocal.newSymNode else: - let a = genAddrOf(n) + let a = genAddrOf(n, idgen) field.typ = a.typ - objType.addField(field, g.cache) + objType.addField(field, g.cache, idgen) result.add newFastAsgnStmt(newDotExpr(scratchObj, field), a) result.add newFastAsgnStmt(newDotExpr(scratchObj, fieldB), genHigh(g, n)) @@ -276,7 +278,7 @@ proc setupArgsForParallelism(g: ModuleGraph; n: PNode; objType: PType; # the array itself does not need to go through a thread local variable: slice[1] = genDeref(indirectAccess(castExpr, field, n.info)) - let threadLocal = addLocalVar(g, varSection,nil, owner, fieldB.typ, + let threadLocal = addLocalVar(g, varSection, nil, idgen, owner, fieldB.typ, indirectAccess(castExpr, fieldB, n.info), useShallowCopy=true) slice[3] = threadLocal.newSymNode @@ -284,26 +286,26 @@ proc setupArgsForParallelism(g: ModuleGraph; n: PNode; objType: PType; elif (let size = computeSize(g.config, argType); size < 0 or size > 16) and n.getRoot != nil: # it is more efficient to pass a pointer instead: - let a = genAddrOf(n) + let a = genAddrOf(n, idgen) field.typ = a.typ - objType.addField(field, g.cache) + objType.addField(field, g.cache, idgen) result.add newFastAsgnStmt(newDotExpr(scratchObj, field), a) - let threadLocal = addLocalVar(g, varSection,nil, owner, field.typ, + let threadLocal = addLocalVar(g, varSection, nil, idgen, owner, field.typ, indirectAccess(castExpr, field, n.info), useShallowCopy=true) call.add(genDeref(threadLocal.newSymNode)) else: # boring case field.typ = argType - objType.addField(field, g.cache) + objType.addField(field, g.cache, idgen) result.add newFastAsgnStmt(newDotExpr(scratchObj, field), n) let threadLocal = addLocalVar(g, varSection, varInit, - owner, field.typ, + idgen, owner, field.typ, indirectAccess(castExpr, field, n.info), useShallowCopy=true) call.add(threadLocal.newSymNode) -proc wrapProcForSpawn*(g: ModuleGraph; owner: PSym; spawnExpr: PNode; retType: PType; +proc wrapProcForSpawn*(g: ModuleGraph; idgen: IdGenerator; owner: PSym; spawnExpr: PNode; retType: PType; barrier, dest: PNode = nil): PNode = # if 'barrier' != nil, then it is in a 'parallel' section and we # generate quite different code @@ -330,9 +332,9 @@ proc wrapProcForSpawn*(g: ModuleGraph; owner: PSym; spawnExpr: PNode; retType: P var fn = n[0] let name = (if fn.kind == nkSym: fn.sym.name.s else: genPrefix) & "Wrapper" - wrapperProc = newSym(skProc, getIdent(g.cache, name), owner, fn.info, g.config.options) - threadParam = newSym(skParam, getIdent(g.cache, "thread"), wrapperProc, n.info, g.config.options) - argsParam = newSym(skParam, getIdent(g.cache, "args"), wrapperProc, n.info, g.config.options) + wrapperProc = newSym(skProc, getIdent(g.cache, name), nextId idgen, owner, fn.info, g.config.options) + threadParam = newSym(skParam, getIdent(g.cache, "thread"), nextId idgen, wrapperProc, n.info, g.config.options) + argsParam = newSym(skParam, getIdent(g.cache, "args"), nextId idgen, wrapperProc, n.info, g.config.options) wrapperProc.flags.incl sfInjectDestructors block: @@ -341,11 +343,11 @@ proc wrapProcForSpawn*(g: ModuleGraph; owner: PSym; spawnExpr: PNode; retType: P argsParam.typ = ptrType argsParam.position = 1 - var objType = createObj(g, owner, n.info) + var objType = createObj(g, idgen, owner, n.info) incl(objType.flags, tfFinal) - let castExpr = createCastExpr(argsParam, objType) + let castExpr = createCastExpr(argsParam, objType, idgen) - var scratchObj = newSym(skVar, getIdent(g.cache, "scratch"), owner, n.info, g.config.options) + var scratchObj = newSym(skVar, getIdent(g.cache, "scratch"), nextId idgen, owner, n.info, g.config.options) block: scratchObj.typ = objType incl(scratchObj.flags, sfFromGeneric) @@ -362,9 +364,9 @@ proc wrapProcForSpawn*(g: ModuleGraph; owner: PSym; spawnExpr: PNode; retType: P skFunc, skMethod, skConverter}): # for indirect calls we pass the function pointer in the scratchObj var argType = n[0].typ.skipTypes(abstractInst) - var field = newSym(skField, getIdent(g.cache, "fn"), owner, n.info, g.config.options) + var field = newSym(skField, getIdent(g.cache, "fn"), nextId idgen, owner, n.info, g.config.options) field.typ = argType - objType.addField(field, g.cache) + objType.addField(field, g.cache, idgen) result.add newFastAsgnStmt(newDotExpr(scratchObj, field), n[0]) fn = indirectAccess(castExpr, field, n.info) elif fn.kind == nkSym and fn.sym.kind == skIterator: @@ -376,49 +378,48 @@ proc wrapProcForSpawn*(g: ModuleGraph; owner: PSym; spawnExpr: PNode; retType: P var varSection = newNodeI(nkVarSection, n.info) var varInit = newNodeI(nkStmtList, n.info) if barrier.isNil: - setupArgsForConcurrency(g, n, objType, wrapperProc, scratchObj, castExpr, call, + setupArgsForConcurrency(g, n, objType, idgen, wrapperProc, scratchObj, castExpr, call, varSection, varInit, result) else: - setupArgsForParallelism(g, n, objType, wrapperProc, scratchObj, castExpr, call, + setupArgsForParallelism(g, n, objType, idgen, wrapperProc, scratchObj, castExpr, call, varSection, varInit, result) var barrierAsExpr: PNode = nil if barrier != nil: - let typ = newType(tyPtr, owner) + let typ = newType(tyPtr, nextId idgen, owner) typ.rawAddSon(magicsys.getCompilerProc(g, "Barrier").typ) - var field = newSym(skField, getIdent(g.cache, "barrier"), owner, n.info, g.config.options) + var field = newSym(skField, getIdent(g.cache, "barrier"), nextId idgen, owner, n.info, g.config.options) field.typ = typ - objType.addField(field, g.cache) + objType.addField(field, g.cache, idgen) result.add newFastAsgnStmt(newDotExpr(scratchObj, field), barrier) barrierAsExpr = indirectAccess(castExpr, field, n.info) var fvField, fvAsExpr: PNode = nil if spawnKind == srFlowVar: - var field = newSym(skField, getIdent(g.cache, "fv"), owner, n.info, g.config.options) + var field = newSym(skField, getIdent(g.cache, "fv"), nextId idgen, owner, n.info, g.config.options) field.typ = retType - objType.addField(field, g.cache) + objType.addField(field, g.cache, idgen) fvField = newDotExpr(scratchObj, field) fvAsExpr = indirectAccess(castExpr, field, n.info) # create flowVar: result.add newFastAsgnStmt(fvField, callProc(spawnExpr[^1])) if barrier == nil: - result.add callCodegenProc(g, "nimFlowVarCreateSemaphore", fvField.info, - fvField) + result.add callCodegenProc(g, "nimFlowVarCreateSemaphore", fvField.info, fvField) elif spawnKind == srByVar: - var field = newSym(skField, getIdent(g.cache, "fv"), owner, n.info, g.config.options) - field.typ = newType(tyPtr, objType.owner) + var field = newSym(skField, getIdent(g.cache, "fv"), nextId idgen, owner, n.info, g.config.options) + field.typ = newType(tyPtr, nextId idgen, objType.owner) field.typ.rawAddSon(retType) - objType.addField(field, g.cache) + objType.addField(field, g.cache, idgen) fvAsExpr = indirectAccess(castExpr, field, n.info) - result.add newFastAsgnStmt(newDotExpr(scratchObj, field), genAddrOf(dest)) + result.add newFastAsgnStmt(newDotExpr(scratchObj, field), genAddrOf(dest, idgen)) - createTypeBoundOps(g, nil, objType, n.info) + createTypeBoundOps(g, nil, objType, n.info, idgen) createWrapperProc(g, fn, threadParam, argsParam, varSection, varInit, call, - barrierAsExpr, fvAsExpr, spawnKind, wrapperProc) + barrierAsExpr, fvAsExpr, idgen, spawnKind, wrapperProc) result.add callCodegenProc(g, "nimSpawn" & $spawnExpr.len, wrapperProc.info, - wrapperProc.newSymNode, genAddrOf(scratchObj.newSymNode), nil, spawnExpr) + wrapperProc.newSymNode, genAddrOf(scratchObj.newSymNode, idgen), nil, spawnExpr) if spawnKind == srFlowVar: result.add fvField diff --git a/compiler/transf.nim b/compiler/transf.nim index 5922ca595..42a78c8e3 100644 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -24,7 +24,7 @@ import lowerings, liftlocals, modulegraphs, lineinfos -proc transformBody*(g: ModuleGraph, prc: PSym, cache: bool): PNode +proc transformBody*(g: ModuleGraph; idgen: IdGenerator, prc: PSym, cache: bool): PNode import closureiters, lambdalifting @@ -40,7 +40,7 @@ type # if we encounter the 2nd yield statement next: PTransCon # for stacking - TTransfContext = object of TPassContext + TTransfContext = object module: PSym transCon: PTransCon # top of a TransCon stack inlining: int # > 0 if we are in inlining context (copy vars) @@ -48,6 +48,7 @@ type contSyms, breakSyms: seq[PSym] # to transform 'continue' and 'break' deferDetected, tooEarly: bool graph: ModuleGraph + idgen: IdGenerator PTransf = ref TTransfContext proc newTransNode(a: PNode): PNode {.inline.} = @@ -86,12 +87,12 @@ proc getCurrOwner(c: PTransf): PSym = else: result = c.module proc newTemp(c: PTransf, typ: PType, info: TLineInfo): PNode = - let r = newSym(skTemp, getIdent(c.graph.cache, genPrefix), getCurrOwner(c), info) + let r = newSym(skTemp, getIdent(c.graph.cache, genPrefix), nextId(c.idgen), getCurrOwner(c), info) r.typ = typ #skipTypes(typ, {tyGenericInst, tyAlias, tySink}) incl(r.flags, sfFromGeneric) let owner = getCurrOwner(c) if owner.isIterator and not c.tooEarly: - result = freshVarForClosureIter(c.graph, r, owner) + result = freshVarForClosureIter(c.graph, r, c.idgen, owner) else: result = newSymNode(r) @@ -111,13 +112,13 @@ proc transformSymAux(c: PTransf, n: PNode): PNode = let s = n.sym if s.typ != nil and s.typ.callConv == ccClosure: if s.kind in routineKinds: - discard transformBody(c.graph, s, true) + discard transformBody(c.graph, c.idgen, s, true) if s.kind == skIterator: if c.tooEarly: return n - else: return liftIterSym(c.graph, n, getCurrOwner(c)) + else: return liftIterSym(c.graph, n, c.idgen, getCurrOwner(c)) elif s.kind in {skProc, skFunc, skConverter, skMethod} and not c.tooEarly: # top level .closure procs are still somewhat supported for 'Nake': - return makeClosure(c.graph, s, nil, n.info) + return makeClosure(c.graph, c.idgen, s, nil, n.info) #elif n.sym.kind in {skVar, skLet} and n.sym.typ.callConv == ccClosure: # echo n.info, " come heer for ", c.tooEarly # if not c.tooEarly: @@ -160,9 +161,9 @@ proc transformSym(c: PTransf, n: PNode): PNode = proc freshVar(c: PTransf; v: PSym): PNode = let owner = getCurrOwner(c) if owner.isIterator and not c.tooEarly: - result = freshVarForClosureIter(c.graph, v, owner) + result = freshVarForClosureIter(c.graph, v, c.idgen, owner) else: - var newVar = copySym(v) + var newVar = copySym(v, nextId(c.idgen)) incl(newVar.flags, sfFromGeneric) newVar.owner = owner result = newSymNode(newVar) @@ -232,7 +233,7 @@ proc hasContinue(n: PNode): bool = if hasContinue(n[i]): return true proc newLabel(c: PTransf, n: PNode): PSym = - result = newSym(skLabel, nil, getCurrOwner(c), n.info) + result = newSym(skLabel, nil, nextId(c.idgen), getCurrOwner(c), n.info) result.name = getIdent(c.graph.cache, genPrefix) proc transformBlock(c: PTransf, n: PNode): PNode = @@ -423,7 +424,7 @@ proc transformAddrDeref(c: PTransf, n: PNode, a, b: TNodeKind): PNode = if n.typ.skipTypes(abstractVar).kind != tyOpenArray: result.typ = n.typ elif n.typ.skipTypes(abstractInst).kind in {tyVar}: - result.typ = toVar(result.typ, n.typ.skipTypes(abstractInst).kind) + result.typ = toVar(result.typ, n.typ.skipTypes(abstractInst).kind, c.idgen) of nkHiddenStdConv, nkHiddenSubConv, nkConv: var m = n[0][1] if m.kind == a or m.kind == b: @@ -433,7 +434,7 @@ proc transformAddrDeref(c: PTransf, n: PNode, a, b: TNodeKind): PNode = if n.typ.skipTypes(abstractVar).kind != tyOpenArray: result.typ = n.typ elif n.typ.skipTypes(abstractInst).kind in {tyVar}: - result.typ = toVar(result.typ, n.typ.skipTypes(abstractInst).kind) + result.typ = toVar(result.typ, n.typ.skipTypes(abstractInst).kind, c.idgen) else: if n[0].kind == a or n[0].kind == b: # addr ( deref ( x )) --> x @@ -495,7 +496,7 @@ proc transformConv(c: PTransf, n: PNode): PNode = of tyOpenArray, tyVarargs: result = transform(c, n[1]) #result = transformSons(c, n) - result.typ = takeType(n.typ, n[1].typ) + result.typ = takeType(n.typ, n[1].typ, c.idgen) #echo n.info, " came here and produced ", typeToString(result.typ), # " from ", typeToString(n.typ), " and ", typeToString(n[1].typ) of tyCString: @@ -629,7 +630,7 @@ proc transformFor(c: PTransf, n: PNode): PNode = result[1] = n result[1][^1] = transformLoopBody(c, n[^1]) result[1][^2] = transform(c, n[^2]) - result[1] = lambdalifting.liftForLoop(c.graph, result[1], getCurrOwner(c)) + result[1] = lambdalifting.liftForLoop(c.graph, result[1], c.idgen, getCurrOwner(c)) discard c.breakSyms.pop return result @@ -698,7 +699,7 @@ proc transformFor(c: PTransf, n: PNode): PNode = stmtList.add(newAsgnStmt(c, nkFastAsgn, temp, arg)) idNodeTablePut(newC.mapping, formal, temp) - let body = transformBody(c.graph, iter, true) + let body = transformBody(c.graph, c.idgen, iter, true) pushInfoContext(c.graph.config, n.info) inc(c.inlining) stmtList.add(transform(c, body)) @@ -830,7 +831,7 @@ proc transformExceptBranch(c: PTransf, n: PNode): PNode = let convNode = newTransNode(nkHiddenSubConv, n[1].info, 2) convNode[0] = newNodeI(nkEmpty, n.info) convNode[1] = excCall - convNode.typ = excTypeNode.typ.toRef() + convNode.typ = excTypeNode.typ.toRef(c.idgen) # -> let exc = ... let identDefs = newTransNode(nkIdentDefs, n[1].info, 3) identDefs[0] = n[0][2] @@ -850,10 +851,10 @@ proc transformExceptBranch(c: PTransf, n: PNode): PNode = else: result = transformSons(c, n) -proc commonOptimizations*(g: ModuleGraph; c: PSym, n: PNode): PNode = +proc commonOptimizations*(g: ModuleGraph; idgen: IdGenerator; c: PSym, n: PNode): PNode = result = n for i in 0..<n.safeLen: - result[i] = commonOptimizations(g, c, n[i]) + result[i] = commonOptimizations(g, idgen, c, n[i]) var op = getMergeOp(n) if (op != nil) and (op.magic != mNone) and (n.len >= 3): result = newNodeIT(nkCall, n.info, n.typ) @@ -873,7 +874,7 @@ proc commonOptimizations*(g: ModuleGraph; c: PSym, n: PNode): PNode = result.add(a) if result.len == 2: result = result[1] else: - var cnst = getConstExpr(c, n, g) + var cnst = getConstExpr(c, n, idgen, g) # we inline constants if they are not complex constants: if cnst != nil and not dontInlineConstant(n, cnst): result = cnst @@ -1012,7 +1013,7 @@ proc transform(c: PTransf, n: PNode): PNode = n.typ != nil and n.typ.kind == tyPointer if not exprIsPointerCast: - var cnst = getConstExpr(c.module, result, c.graph) + var cnst = getConstExpr(c.module, result, c.idgen, c.graph) # we inline constants if they are not complex constants: if cnst != nil and not dontInlineConstant(n, cnst): result = cnst # do not miss an optimization @@ -1027,12 +1028,13 @@ proc processTransf(c: PTransf, n: PNode, owner: PSym): PNode = popTransCon(c) incl(result.flags, nfTransf) -proc openTransf(g: ModuleGraph; module: PSym, filename: string): PTransf = +proc openTransf(g: ModuleGraph; module: PSym, filename: string; idgen: IdGenerator): PTransf = new(result) result.contSyms = @[] result.breakSyms = @[] result.module = module result.graph = g + result.idgen = idgen proc flattenStmts(n: PNode) = var goOn = true @@ -1075,7 +1077,7 @@ template liftDefer(c, root) = if c.deferDetected: liftDeferAux(root) -proc transformBody*(g: ModuleGraph, prc: PSym, cache: bool): PNode = +proc transformBody*(g: ModuleGraph; idgen: IdGenerator; prc: PSym; cache: bool): PNode = assert prc.kind in routineKinds if prc.transformedBody != nil: @@ -1084,14 +1086,14 @@ proc transformBody*(g: ModuleGraph, prc: PSym, cache: bool): PNode = result = prc.ast[bodyPos] else: prc.transformedBody = newNode(nkEmpty) # protects from recursion - var c = openTransf(g, prc.getModule, "") - result = liftLambdas(g, prc, prc.ast[bodyPos], c.tooEarly) + var c = openTransf(g, prc.getModule, "", idgen) + result = liftLambdas(g, prc, prc.ast[bodyPos], c.tooEarly, c.idgen) result = processTransf(c, result, prc) liftDefer(c, result) - result = liftLocalsIfRequested(prc, result, g.cache, g.config) + result = liftLocalsIfRequested(prc, result, g.cache, g.config, c.idgen) if prc.isIterator: - result = g.transformClosureIterator(prc, result) + result = g.transformClosureIterator(c.idgen, prc, result) incl(result.flags, nfTransf) @@ -1105,21 +1107,21 @@ proc transformBody*(g: ModuleGraph, prc: PSym, cache: bool): PNode = #if prc.name.s == "main": # echo "transformed into ", renderTree(result, {renderIds}) -proc transformStmt*(g: ModuleGraph; module: PSym, n: PNode): PNode = +proc transformStmt*(g: ModuleGraph; idgen: IdGenerator; module: PSym, n: PNode): PNode = if nfTransf in n.flags: result = n else: - var c = openTransf(g, module, "") + var c = openTransf(g, module, "", idgen) result = processTransf(c, n, module) liftDefer(c, result) #result = liftLambdasForTopLevel(module, result) incl(result.flags, nfTransf) -proc transformExpr*(g: ModuleGraph; module: PSym, n: PNode): PNode = +proc transformExpr*(g: ModuleGraph; idgen: IdGenerator; module: PSym, n: PNode): PNode = if nfTransf in n.flags: result = n else: - var c = openTransf(g, module, "") + var c = openTransf(g, module, "", idgen) result = processTransf(c, n, module) liftDefer(c, result) # expressions are not to be injected with destructor calls as that diff --git a/compiler/types.nim b/compiler/types.nim index 75e12cac4..a3a4695b0 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -1296,11 +1296,11 @@ proc containsGenericTypeIter(t: PType, closure: RootRef): bool = proc containsGenericType*(t: PType): bool = result = iterOverType(t, containsGenericTypeIter, nil) -proc baseOfDistinct*(t: PType): PType = +proc baseOfDistinct*(t: PType; idgen: IdGenerator): PType = if t.kind == tyDistinct: result = t[0] else: - result = copyType(t, t.owner, false) + result = copyType(t, nextId idgen, t.owner) var parent: PType = nil var it = result while it.kind in {tyPtr, tyRef, tyOwned}: @@ -1438,7 +1438,7 @@ proc isEmptyContainer*(t: PType): bool = of tyGenericInst, tyAlias, tySink: result = isEmptyContainer(t.lastSon) else: result = false -proc takeType*(formal, arg: PType): PType = +proc takeType*(formal, arg: PType; idgen: IdGenerator): PType = # param: openArray[string] = [] # [] is an array constructor of length 0 of type string! if arg.kind == tyNil: @@ -1446,7 +1446,7 @@ proc takeType*(formal, arg: PType): PType = result = formal elif formal.kind in {tyOpenArray, tyVarargs, tySequence} and arg.isEmptyContainer: - let a = copyType(arg.skipTypes({tyGenericInst, tyAlias}), arg.owner, keepId=false) + let a = copyType(arg.skipTypes({tyGenericInst, tyAlias}), nextId(idgen), arg.owner) a[ord(arg.kind == tyArray)] = formal[0] result = a elif formal.kind in {tyTuple, tySet} and arg.kind == formal.kind: @@ -1454,14 +1454,14 @@ proc takeType*(formal, arg: PType): PType = else: result = arg -proc skipHiddenSubConv*(n: PNode): PNode = +proc skipHiddenSubConv*(n: PNode; idgen: IdGenerator): PNode = if n.kind == nkHiddenSubConv: # param: openArray[string] = [] # [] is an array constructor of length 0 of type string! let formal = n.typ result = n[1] let arg = result.typ - let dest = takeType(formal, arg) + let dest = takeType(formal, arg, idgen) if dest == arg and formal.kind != tyUntyped: #echo n.info, " came here for ", formal.typeToString result = n diff --git a/compiler/vm.nim b/compiler/vm.nim index bb217c4db..185975ec3 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -1105,7 +1105,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = let ast = a.sym.ast.shallowCopy for i in 0..<a.sym.ast.len: ast[i] = a.sym.ast[i] - ast[bodyPos] = transformBody(c.graph, a.sym, cache=true) + ast[bodyPos] = transformBody(c.graph, c.idgen, a.sym, cache=true) ast.copyTree() of opcSymOwner: decodeB(rkNode) @@ -1233,7 +1233,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = let node = regs[rb+i].regToNode node.info = c.debug[pc] macroCall.add(node) - var a = evalTemplate(macroCall, prc, genSymOwner, c.config, c.cache, c.templInstCounter) + var a = evalTemplate(macroCall, prc, genSymOwner, c.config, c.cache, c.templInstCounter, c.idgen) if a.kind == nkStmtList and a.len == 1: a = a[0] a.recSetFlagIsRef ensureKind(rkNode) @@ -1599,9 +1599,9 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = # getType opcode: ensureKind(rkNode) if regs[rb].kind == rkNode and regs[rb].node.typ != nil: - regs[ra].node = opMapTypeToAst(c.cache, regs[rb].node.typ, c.debug[pc]) + regs[ra].node = opMapTypeToAst(c.cache, regs[rb].node.typ, c.debug[pc], c.idgen) elif regs[rb].kind == rkNode and regs[rb].node.kind == nkSym and regs[rb].node.sym.typ != nil: - regs[ra].node = opMapTypeToAst(c.cache, regs[rb].node.sym.typ, c.debug[pc]) + regs[ra].node = opMapTypeToAst(c.cache, regs[rb].node.sym.typ, c.debug[pc], c.idgen) else: stackTrace(c, tos, pc, "node has no type") of 1: @@ -1617,18 +1617,18 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = # getTypeInst opcode: ensureKind(rkNode) if regs[rb].kind == rkNode and regs[rb].node.typ != nil: - regs[ra].node = opMapTypeInstToAst(c.cache, regs[rb].node.typ, c.debug[pc]) + regs[ra].node = opMapTypeInstToAst(c.cache, regs[rb].node.typ, c.debug[pc], c.idgen) elif regs[rb].kind == rkNode and regs[rb].node.kind == nkSym and regs[rb].node.sym.typ != nil: - regs[ra].node = opMapTypeInstToAst(c.cache, regs[rb].node.sym.typ, c.debug[pc]) + regs[ra].node = opMapTypeInstToAst(c.cache, regs[rb].node.sym.typ, c.debug[pc], c.idgen) else: stackTrace(c, tos, pc, "node has no type") else: # getTypeImpl opcode: ensureKind(rkNode) if regs[rb].kind == rkNode and regs[rb].node.typ != nil: - regs[ra].node = opMapTypeImplToAst(c.cache, regs[rb].node.typ, c.debug[pc]) + regs[ra].node = opMapTypeImplToAst(c.cache, regs[rb].node.typ, c.debug[pc], c.idgen) elif regs[rb].kind == rkNode and regs[rb].node.kind == nkSym and regs[rb].node.sym.typ != nil: - regs[ra].node = opMapTypeImplToAst(c.cache, regs[rb].node.sym.typ, c.debug[pc]) + regs[ra].node = opMapTypeImplToAst(c.cache, regs[rb].node.sym.typ, c.debug[pc], c.idgen) else: stackTrace(c, tos, pc, "node has no type") of opcNGetSize: @@ -1938,7 +1938,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = else: regs[rc].node.strVal if k < 0 or k > ord(high(TSymKind)): internalError(c.config, c.debug[pc], "request to create symbol of invalid kind") - var sym = newSym(k.TSymKind, getIdent(c.cache, name), c.module.owner, c.debug[pc]) + var sym = newSym(k.TSymKind, getIdent(c.cache, name), nextId c.idgen, c.module.owner, c.debug[pc]) incl(sym.flags, sfGenSym) regs[ra].node = newSymNode(sym) regs[ra].node.flags.incl nfIsRef @@ -2058,7 +2058,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = let rb = instr.regB inc pc let typ = c.types[c.code[pc].regBx - wordExcess] - putIntoReg(regs[ra], loadAny(regs[rb].node.strVal, typ, c.cache, c.config)) + putIntoReg(regs[ra], loadAny(regs[rb].node.strVal, typ, c.cache, c.config, c.idgen)) of opcMarshalStore: decodeB(rkNode) inc pc @@ -2103,7 +2103,7 @@ proc execProc*(c: PCtx; sym: PSym; args: openArray[PNode]): PNode = "NimScript: attempt to call non-routine: " & sym.name.s) proc evalStmt*(c: PCtx, n: PNode) = - let n = transformExpr(c.graph, c.module, n) + let n = transformExpr(c.graph, c.idgen, c.module, n) let start = genStmt(c, n) # execute new instructions; this redundant opcEof check saves us lots # of allocations in 'execute': @@ -2111,7 +2111,7 @@ proc evalStmt*(c: PCtx, n: PNode) = discard execute(c, start) proc evalExpr*(c: PCtx, n: PNode): PNode = - let n = transformExpr(c.graph, c.module, n) + let n = transformExpr(c.graph, c.idgen, c.module, n) let start = genExpr(c, n) assert c.code[start].opcode != opcEof result = execute(c, start) @@ -2122,20 +2122,20 @@ proc getGlobalValue*(c: PCtx; s: PSym): PNode = include vmops -proc setupGlobalCtx*(module: PSym; graph: ModuleGraph) = +proc setupGlobalCtx*(module: PSym; graph: ModuleGraph; idgen: IdGenerator) = if graph.vm.isNil: - graph.vm = newCtx(module, graph.cache, graph) + graph.vm = newCtx(module, graph.cache, graph, idgen) registerAdditionalOps(PCtx graph.vm) else: - refresh(PCtx graph.vm, module) + refresh(PCtx graph.vm, module, idgen) -proc myOpen(graph: ModuleGraph; module: PSym): PPassContext {.nosinks.} = +proc myOpen(graph: ModuleGraph; module: PSym; idgen: IdGenerator): PPassContext {.nosinks.} = #var c = newEvalContext(module, emRepl) #c.features = {allowCast, allowInfiniteLoops} #pushStackFrame(c, newStackFrame()) # XXX produce a new 'globals' environment here: - setupGlobalCtx(module, graph) + setupGlobalCtx(module, graph, idgen) result = PCtx graph.vm proc myProcess(c: PPassContext, n: PNode): PNode = @@ -2149,16 +2149,16 @@ proc myProcess(c: PPassContext, n: PNode): PNode = c.oldErrorCount = c.config.errorCounter proc myClose(graph: ModuleGraph; c: PPassContext, n: PNode): PNode = - myProcess(c, n) + result = myProcess(c, n) const evalPass* = makePass(myOpen, myProcess, myClose) -proc evalConstExprAux(module: PSym; +proc evalConstExprAux(module: PSym; idgen: IdGenerator; g: ModuleGraph; prc: PSym, n: PNode, mode: TEvalMode): PNode = if g.config.errorCounter > 0: return n - let n = transformExpr(g, module, n) - setupGlobalCtx(module, g) + let n = transformExpr(g, idgen, module, n) + setupGlobalCtx(module, g, idgen) var c = PCtx g.vm let oldMode = c.mode c.mode = mode @@ -2173,17 +2173,17 @@ proc evalConstExprAux(module: PSym; if result.info.col < 0: result.info = n.info c.mode = oldMode -proc evalConstExpr*(module: PSym; g: ModuleGraph; e: PNode): PNode = - result = evalConstExprAux(module, g, nil, e, emConst) +proc evalConstExpr*(module: PSym; idgen: IdGenerator; g: ModuleGraph; e: PNode): PNode = + result = evalConstExprAux(module, idgen, g, nil, e, emConst) -proc evalStaticExpr*(module: PSym; g: ModuleGraph; e: PNode, prc: PSym): PNode = - result = evalConstExprAux(module, g, prc, e, emStaticExpr) +proc evalStaticExpr*(module: PSym; idgen: IdGenerator; g: ModuleGraph; e: PNode, prc: PSym): PNode = + result = evalConstExprAux(module, idgen, g, prc, e, emStaticExpr) -proc evalStaticStmt*(module: PSym; g: ModuleGraph; e: PNode, prc: PSym) = - discard evalConstExprAux(module, g, prc, e, emStaticStmt) +proc evalStaticStmt*(module: PSym; idgen: IdGenerator; g: ModuleGraph; e: PNode, prc: PSym) = + discard evalConstExprAux(module, idgen, g, prc, e, emStaticStmt) -proc setupCompileTimeVar*(module: PSym; g: ModuleGraph; n: PNode) = - discard evalConstExprAux(module, g, nil, n, emStaticStmt) +proc setupCompileTimeVar*(module: PSym; idgen: IdGenerator; g: ModuleGraph; n: PNode) = + discard evalConstExprAux(module, idgen, g, nil, n, emStaticStmt) proc prepareVMValue(arg: PNode): PNode = ## strip nkExprColonExpr from tuple values recurively. That is how @@ -2227,14 +2227,14 @@ iterator genericParamsInMacroCall*(macroSym: PSym, call: PNode): (PSym, PNode) = # to prevent endless recursion in macro instantiation const evalMacroLimit = 1000 -proc errorNode(owner: PSym, n: PNode): PNode = +proc errorNode(idgen: IdGenerator; owner: PSym, n: PNode): PNode = result = newNodeI(nkEmpty, n.info) - result.typ = newType(tyError, owner) + result.typ = newType(tyError, nextId idgen, owner) result.typ.flags.incl tfCheckedForDestructor -proc evalMacroCall*(module: PSym; g: ModuleGraph; templInstCounter: ref int; +proc evalMacroCall*(module: PSym; idgen: IdGenerator; g: ModuleGraph; templInstCounter: ref int; n, nOrig: PNode, sym: PSym): PNode = - if g.config.errorCounter > 0: return errorNode(module, n) + if g.config.errorCounter > 0: return errorNode(idgen, module, n) # XXX globalError() is ugly here, but I don't know a better solution for now inc(g.config.evalMacroCounter) @@ -2247,7 +2247,7 @@ proc evalMacroCall*(module: PSym; g: ModuleGraph; templInstCounter: ref int; globalError(g.config, n.info, "in call '$#' got $#, but expected $# argument(s)" % [ n.renderTree, $(n.safeLen-1), $(sym.typ.len-1)]) - setupGlobalCtx(module, g) + setupGlobalCtx(module, g, idgen) var c = PCtx g.vm let oldMode = c.mode c.mode = emStaticStmt diff --git a/compiler/vmdef.nim b/compiler/vmdef.nim index 59ffe9581..202087af7 100644 --- a/compiler/vmdef.nim +++ b/compiler/vmdef.nim @@ -282,17 +282,18 @@ type PEvalContext* = PCtx -proc newCtx*(module: PSym; cache: IdentCache; g: ModuleGraph): PCtx = +proc newCtx*(module: PSym; cache: IdentCache; g: ModuleGraph; idgen: IdGenerator): PCtx = PCtx(code: @[], debug: @[], globals: newNode(nkStmtListExpr), constants: newNode(nkStmtList), types: @[], prc: PProc(blocks: @[]), module: module, loopIterations: g.config.maxLoopIterationsVM, comesFromHeuristic: unknownLineInfo, callbacks: @[], errorFlag: "", - cache: cache, config: g.config, graph: g) + cache: cache, config: g.config, graph: g, idgen: idgen) -proc refresh*(c: PCtx, module: PSym) = +proc refresh*(c: PCtx, module: PSym; idgen: IdGenerator) = c.module = module c.prc = PProc(blocks: @[]) c.loopIterations = c.config.maxLoopIterationsVM + c.idgen = idgen proc registerCallback*(c: PCtx; name: string; callback: VmCallback): int {.discardable.} = result = c.callbacks.len diff --git a/compiler/vmdeps.nim b/compiler/vmdeps.nim index 37e7e4b38..8083ae179 100644 --- a/compiler/vmdeps.nim +++ b/compiler/vmdeps.nim @@ -24,8 +24,9 @@ proc opSlurp*(file: string, info: TLineInfo, module: PSym; conf: ConfigRef): str localError(conf, info, "cannot open file: " & file) result = "" -proc atomicTypeX(cache: IdentCache; name: string; m: TMagic; t: PType; info: TLineInfo): PNode = - let sym = newSym(skType, getIdent(cache, name), t.owner, info) +proc atomicTypeX(cache: IdentCache; name: string; m: TMagic; t: PType; info: TLineInfo; + idgen: IdGenerator): PNode = + let sym = newSym(skType, getIdent(cache, name), nextId(idgen), t.owner, info) sym.magic = m sym.typ = t result = newSymNode(sym) @@ -35,44 +36,46 @@ proc atomicTypeX(s: PSym; info: TLineInfo): PNode = result = newSymNode(s) result.info = info -proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo; +proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo; idgen: IdGenerator; inst=false; allowRecursionX=false): PNode proc mapTypeToBracketX(cache: IdentCache; name: string; m: TMagic; t: PType; info: TLineInfo; + idgen: IdGenerator; inst=false): PNode = result = newNodeIT(nkBracketExpr, if t.n.isNil: info else: t.n.info, t) - result.add atomicTypeX(cache, name, m, t, info) + result.add atomicTypeX(cache, name, m, t, info, idgen) for i in 0..<t.len: if t[i] == nil: - let void = atomicTypeX(cache, "void", mVoid, t, info) - void.typ = newType(tyVoid, t.owner) + let void = atomicTypeX(cache, "void", mVoid, t, info, idgen) + void.typ = newType(tyVoid, nextId(idgen), t.owner) result.add void else: - result.add mapTypeToAstX(cache, t[i], info, inst) + result.add mapTypeToAstX(cache, t[i], info, idgen, inst) -proc objectNode(cache: IdentCache; n: PNode): PNode = +proc objectNode(cache: IdentCache; n: PNode; idgen: IdGenerator): PNode = if n.kind == nkSym: result = newNodeI(nkIdentDefs, n.info) result.add n # name - result.add mapTypeToAstX(cache, n.sym.typ, n.info, true, false) # type + result.add mapTypeToAstX(cache, n.sym.typ, n.info, idgen, true, false) # type result.add newNodeI(nkEmpty, n.info) # no assigned value else: result = copyNode(n) for i in 0..<n.safeLen: - result.add objectNode(cache, n[i]) + result.add objectNode(cache, n[i], idgen) proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo; + idgen: IdGenerator; inst=false; allowRecursionX=false): PNode = var allowRecursion = allowRecursionX - template atomicType(name, m): untyped = atomicTypeX(cache, name, m, t, info) + template atomicType(name, m): untyped = atomicTypeX(cache, name, m, t, info, idgen) template atomicType(s): untyped = atomicTypeX(s, info) - template mapTypeToAst(t,info): untyped = mapTypeToAstX(cache, t, info, inst) - template mapTypeToAstR(t,info): untyped = mapTypeToAstX(cache, t, info, inst, true) + template mapTypeToAst(t,info): untyped = mapTypeToAstX(cache, t, info, idgen, inst) + template mapTypeToAstR(t,info): untyped = mapTypeToAstX(cache, t, info, idgen, inst, true) template mapTypeToAst(t,i,info): untyped = - if i<t.len and t[i]!=nil: mapTypeToAstX(cache, t[i], info, inst) + if i<t.len and t[i]!=nil: mapTypeToAstX(cache, t[i], info, idgen, inst) else: newNodeI(nkEmpty, info) template mapTypeToBracket(name, m, t, info): untyped = - mapTypeToBracketX(cache, name, m, t, info, inst) + mapTypeToBracketX(cache, name, m, t, info, idgen, inst) template newNodeX(kind): untyped = newNodeIT(kind, if t.n.isNil: info else: t.n.info, t) template newIdentDefs(n,t): untyped = @@ -134,14 +137,14 @@ proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo; for i in 1..<t.len-1: result.add mapTypeToAst(t[i], info) else: - result = mapTypeToAstX(cache, t.lastSon, info, inst, allowRecursion) + result = mapTypeToAstX(cache, t.lastSon, info, idgen, inst, allowRecursion) of tyGenericBody: if inst: result = mapTypeToAstR(t.lastSon, info) else: result = mapTypeToAst(t.lastSon, info) of tyAlias: - result = mapTypeToAstX(cache, t.lastSon, info, inst, allowRecursion) + result = mapTypeToAstX(cache, t.lastSon, info, idgen, inst, allowRecursion) of tyOrdinal: result = mapTypeToAst(t.lastSon, info) of tyDistinct: @@ -169,7 +172,7 @@ proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo; nn.add mapTypeToAst(t[0], info) result.add nn if t.n.len > 0: - result.add objectNode(cache, t.n) + result.add objectNode(cache, t.n, idgen) else: result.add newNodeI(nkEmpty, info) else: @@ -298,15 +301,15 @@ proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo; of tyOwned: result = mapTypeToBracket("owned", mBuiltinType, t, info) of tyOptDeprecated: doAssert false -proc opMapTypeToAst*(cache: IdentCache; t: PType; info: TLineInfo): PNode = - result = mapTypeToAstX(cache, t, info, inst=false, allowRecursionX=true) +proc opMapTypeToAst*(cache: IdentCache; t: PType; info: TLineInfo; idgen: IdGenerator): PNode = + result = mapTypeToAstX(cache, t, info, idgen, inst=false, allowRecursionX=true) # the "Inst" version includes generic parameters in the resulting type tree # and also tries to look like the corresponding Nim type declaration -proc opMapTypeInstToAst*(cache: IdentCache; t: PType; info: TLineInfo): PNode = - result = mapTypeToAstX(cache, t, info, inst=true, allowRecursionX=false) +proc opMapTypeInstToAst*(cache: IdentCache; t: PType; info: TLineInfo; idgen: IdGenerator): PNode = + result = mapTypeToAstX(cache, t, info, idgen, inst=true, allowRecursionX=false) # the "Impl" version includes generic parameters in the resulting type tree # and also tries to look like the corresponding Nim type implementation -proc opMapTypeImplToAst*(cache: IdentCache; t: PType; info: TLineInfo): PNode = - result = mapTypeToAstX(cache, t, info, inst=true, allowRecursionX=true) +proc opMapTypeImplToAst*(cache: IdentCache; t: PType; info: TLineInfo; idgen: IdGenerator): PNode = + result = mapTypeToAstX(cache, t, info, idgen, inst=true, allowRecursionX=true) diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index 44b10ea67..5ba15bb2b 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -1118,7 +1118,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) = c.freeTemp(d) of mSwap: unused(c, n, dest) - c.gen(lowerSwap(c.graph, n, if c.prc == nil: c.module else: c.prc.sym)) + c.gen(lowerSwap(c.graph, n, c.idgen, if c.prc == nil: c.module else: c.prc.sym)) of mIsNil: genUnaryABC(c, n, dest, opcIsNil) of mParseBiggestFloat: if dest < 0: dest = c.getTemp(n.typ) @@ -1819,7 +1819,7 @@ proc genVarSection(c: PCtx; n: PNode) = if a[i].kind == nkSym: if not a[i].sym.isGlobal: setSlot(c, a[i].sym) checkCanEval(c, a[i]) - c.gen(lowerTupleUnpacking(c.graph, a, c.getOwner)) + c.gen(lowerTupleUnpacking(c.graph, a, c.idgen, c.getOwner)) elif a[0].kind == nkSym: let s = a[0].sym checkCanEval(c, a[0]) @@ -2235,7 +2235,7 @@ proc genProc(c: PCtx; s: PSym): int = s.ast[miscPos] = x # thanks to the jmp we can add top level statements easily and also nest # procs easily: - let body = transformBody(c.graph, s, cache = not isCompileTimeProc(s)) + let body = transformBody(c.graph, c.idgen, s, cache = not isCompileTimeProc(s)) let procStart = c.xjmp(body, opcJmp, 0) var p = PProc(blocks: @[], sym: s) let oldPrc = c.prc diff --git a/compiler/vmmarshal.nim b/compiler/vmmarshal.nim index 696183943..979e5de8a 100644 --- a/compiler/vmmarshal.nim +++ b/compiler/vmmarshal.nim @@ -136,7 +136,8 @@ proc storeAny*(s: var string; t: PType; a: PNode; conf: ConfigRef) = proc loadAny(p: var JsonParser, t: PType, tab: var Table[BiggestInt, PNode]; cache: IdentCache; - conf: ConfigRef): PNode = + conf: ConfigRef; + idgen: IdGenerator): PNode = case t.kind of tyNone: assert false of tyBool: @@ -170,7 +171,7 @@ proc loadAny(p: var JsonParser, t: PType, next(p) result = newNode(nkBracket) while p.kind != jsonArrayEnd and p.kind != jsonEof: - result.add loadAny(p, t.elemType, tab, cache, conf) + result.add loadAny(p, t.elemType, tab, cache, conf, idgen) if p.kind == jsonArrayEnd: next(p) else: raiseParseErr(p, "']' end of array expected") of tySequence: @@ -182,7 +183,7 @@ proc loadAny(p: var JsonParser, t: PType, next(p) result = newNode(nkBracket) while p.kind != jsonArrayEnd and p.kind != jsonEof: - result.add loadAny(p, t.elemType, tab, cache, conf) + result.add loadAny(p, t.elemType, tab, cache, conf, idgen) if p.kind == jsonArrayEnd: next(p) else: raiseParseErr(p, "") else: @@ -198,7 +199,7 @@ proc loadAny(p: var JsonParser, t: PType, next(p) if i >= t.len: raiseParseErr(p, "too many fields to tuple type " & typeToString(t)) - result.add loadAny(p, t[i], tab, cache, conf) + result.add loadAny(p, t[i], tab, cache, conf, idgen) inc i if p.kind == jsonObjectEnd: next(p) else: raiseParseErr(p, "'}' end of object expected") @@ -219,8 +220,8 @@ proc loadAny(p: var JsonParser, t: PType, if pos >= result.len: setLen(result.sons, pos + 1) let fieldNode = newNode(nkExprColonExpr) - fieldNode.add newSymNode(newSym(skField, ident, nil, unknownLineInfo)) - fieldNode.add loadAny(p, field.typ, tab, cache, conf) + fieldNode.add newSymNode(newSym(skField, ident, nextId(idgen), nil, unknownLineInfo)) + fieldNode.add loadAny(p, field.typ, tab, cache, conf, idgen) result[pos] = fieldNode if p.kind == jsonObjectEnd: next(p) else: raiseParseErr(p, "'}' end of object expected") @@ -229,7 +230,7 @@ proc loadAny(p: var JsonParser, t: PType, next(p) result = newNode(nkCurly) while p.kind != jsonArrayEnd and p.kind != jsonEof: - result.add loadAny(p, t.lastSon, tab, cache, conf) + result.add loadAny(p, t.lastSon, tab, cache, conf, idgen) next(p) if p.kind == jsonArrayEnd: next(p) else: raiseParseErr(p, "']' end of array expected") @@ -248,7 +249,7 @@ proc loadAny(p: var JsonParser, t: PType, if p.kind == jsonInt: let idx = p.getInt next(p) - result = loadAny(p, t.lastSon, tab, cache, conf) + result = loadAny(p, t.lastSon, tab, cache, conf, idgen) tab[idx] = result else: raiseParseErr(p, "index for ref type expected") if p.kind == jsonArrayEnd: next(p) @@ -276,14 +277,14 @@ proc loadAny(p: var JsonParser, t: PType, return raiseParseErr(p, "float expected") of tyRange, tyGenericInst, tyAlias, tySink: - result = loadAny(p, t.lastSon, tab, cache, conf) + result = loadAny(p, t.lastSon, tab, cache, conf, idgen) else: internalError conf, "cannot marshal at compile-time " & t.typeToString -proc loadAny*(s: string; t: PType; cache: IdentCache; conf: ConfigRef): PNode = +proc loadAny*(s: string; t: PType; cache: IdentCache; conf: ConfigRef; idgen: IdGenerator): PNode = var tab = initTable[BiggestInt, PNode]() var p: JsonParser open(p, newStringStream(s), "unknown file") next(p) - result = loadAny(p, t, tab, cache, conf) + result = loadAny(p, t, tab, cache, conf, idgen) close(p) diff --git a/compiler/vmops.nim b/compiler/vmops.nim index a3d4d74db..47df3d24f 100644 --- a/compiler/vmops.nim +++ b/compiler/vmops.nim @@ -268,7 +268,7 @@ proc registerAdditionalOps*(c: PCtx) = fn.typ.n[0][effectIndex] != nil: var list = newNodeI(nkBracket, fn.info) for e in fn.typ.n[0][effectIndex]: - list.add opMapTypeInstToAst(c.cache, e.typ.skipTypes({tyRef}), e.info) + list.add opMapTypeInstToAst(c.cache, e.typ.skipTypes({tyRef}), e.info, c.idgen) setResult(a, list) registerCallback c, "stdlib.effecttraits.getRaisesListImpl", proc (a: VmArgs) = diff --git a/lib/system/iterators.nim b/lib/system/iterators.nim index 99ad6eef6..c8c0edbd4 100644 --- a/lib/system/iterators.nim +++ b/lib/system/iterators.nim @@ -82,7 +82,7 @@ iterator mitems*(a: var cstring): var char {.inline.} = yield a[i] inc(i) -iterator items*(E: typedesc[enum]): E = +iterator items*[T: enum](E: typedesc[T]): T = ## Iterates over the values of the enum ``E``. for v in low(E) .. high(E): yield v |