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)
This commit is contained in:
Andreas Rumpf 2020-10-25 08:50:47 +01:00 • committed by GitHub
commit 226595515c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
67 changed files with 853 additions and 903 deletions

View file

@ -10,7 +10,7 @@
# abstract syntax tree + symbol table # abstract syntax tree + symbol table
import import
lineinfos, hashes, options, ropes, idents, idgen, int128 lineinfos, hashes, options, ropes, idents, int128
from strutils import toLowerAscii from strutils import toLowerAscii
export int128 export int128
@ -717,6 +717,14 @@ const
mInSet, mRepr} mInSet, mRepr}
type type
ItemId* = object
module*: int32
item*: int32
TIdObj* = object of RootObj
itemId*: ItemId
PIdObj* = ref TIdObj
PNode* = ref TNode PNode* = ref TNode
TNodeSeq* = seq[PNode] TNodeSeq* = seq[PNode]
PType* = ref TType PType* = ref TType
@ -926,7 +934,7 @@ type
loc*: TLoc loc*: TLoc
typeInst*: PType # for generic instantiations the tyGenericInst that led to this typeInst*: PType # for generic instantiations the tyGenericInst that led to this
# type. # 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. # required by the --incremental:on mode.
TPair* = object TPair* = object
@ -1060,6 +1068,35 @@ proc getnimblePkg*(a: PSym): PSym =
else: else:
assert false, $result.kind 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 = proc getnimblePkgId*(a: PSym): int =
let b = a.getnimblePkg let b = a.getnimblePkg
result = if b == nil: -1 else: b.id 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 = template previouslyInferred*(t: PType): PType =
if t.sons.len > 1: t.lastSon else: nil 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 = info: TLineInfo; options: TOptions = {}): PSym =
# generates a symbol and initializes the hash field too # 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) options: options, owner: owner, offset: defaultOffset)
when debugIds:
registerId(result)
proc astdef*(s: PSym): PNode = proc astdef*(s: PSym): PNode =
# get only the definition (initializer) portion of the ast # get only the definition (initializer) portion of the ast
@ -1344,13 +1379,11 @@ proc `$`*(s: PSym): string =
else: else:
result = "<nil>" result = "<nil>"
proc newType*(kind: TTypeKind, owner: PSym): PType = proc newType*(kind: TTypeKind, id: ItemId; owner: PSym): PType =
let id = getID()
result = PType(kind: kind, owner: owner, size: defaultSize, result = PType(kind: kind, owner: owner, size: defaultSize,
align: defaultAlignment, id: id, uniqueId: id, align: defaultAlignment, itemId: id,
lockLevel: UnspecifiedLockLevel) lockLevel: UnspecifiedLockLevel,
when debugIds: uniqueId: id)
registerId(result)
when false: when false:
if result.id == 76426: if result.id == 76426:
echo "KNID ", kind echo "KNID ", kind
@ -1392,22 +1425,18 @@ proc assignType*(dest, src: PType) =
newSons(dest, src.len) newSons(dest, src.len)
for i in 0..<src.len: dest[i] = src[i] for i in 0..<src.len: dest[i] = src[i]
proc copyType*(t: PType, owner: PSym, keepId: bool): PType = proc copyType*(t: PType, id: ItemId, owner: PSym): PType =
result = newType(t.kind, owner) result = newType(t.kind, id, owner)
assignType(result, t) assignType(result, t)
if keepId:
result.id = t.id
else:
when debugIds: registerId(result)
result.sym = t.sym # backend-info should not be copied 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 = proc copySym*(s: PSym; id: ItemId): PSym =
result = newSym(s.kind, s.name, s.owner, s.info, s.options) result = newSym(s.kind, s.name, id, s.owner, s.info, s.options)
#result.ast = nil # BUGFIX; was: s.ast which made problems #result.ast = nil # BUGFIX; was: s.ast which made problems
result.typ = s.typ result.typ = s.typ
when debugIds: registerId(result)
result.flags = s.flags result.flags = s.flags
result.magic = s.magic result.magic = s.magic
if s.kind == skModule: if s.kind == skModule:
@ -1421,12 +1450,12 @@ proc copySym*(s: PSym): PSym =
result.bitsize = s.bitsize result.bitsize = s.bitsize
result.alignment = s.alignment 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 = options: TOptions): PSym =
result = newSym(s.kind, newIdent, s.owner, info, options) result = newSym(s.kind, newIdent, id, s.owner, info, options)
# keep ID! # keep ID!
result.ast = s.ast 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 result.flags = s.flags
system.shallowCopy(result.tab, s.tab) system.shallowCopy(result.tab, s.tab)
result.options = s.options result.options = s.options
@ -1576,7 +1605,7 @@ proc transitionNoneToSym*(n: PNode) =
template transitionSymKindCommon*(k: TSymKind) = template transitionSymKindCommon*(k: TSymKind) =
let obj {.inject.} = s[] 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, info: obj.info, owner: obj.owner, flags: obj.flags, ast: obj.ast,
options: obj.options, position: obj.position, offset: obj.offset, options: obj.options, position: obj.position, offset: obj.offset,
loc: obj.loc, annex: obj.annex, constraint: obj.constraint) loc: obj.loc, annex: obj.annex, constraint: obj.constraint)
@ -1797,19 +1826,19 @@ proc skipStmtList*(n: PNode): PNode =
else: else:
result = n 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 ## If ``typ`` is not a tyVar then it is converted into a `var <typ>` and
## returned. Otherwise ``typ`` is simply returned as-is. ## returned. Otherwise ``typ`` is simply returned as-is.
result = typ result = typ
if typ.kind != kind: if typ.kind != kind:
result = newType(kind, typ.owner) result = newType(kind, nextId(idgen), typ.owner)
rawAddSon(result, typ) 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 ## If ``typ`` is a tyObject then it is converted into a `ref <typ>` and
## returned. Otherwise ``typ`` is simply returned as-is. ## returned. Otherwise ``typ`` is simply returned as-is.
if typ.skipTypes({tyAlias, tyGenericInst}).kind == tyObject: if typ.skipTypes({tyAlias, tyGenericInst}).kind == tyObject:
result = newType(tyRef, typ.owner) result = newType(tyRef, nextId(idgen), typ.owner)
rawAddSon(result, typ) rawAddSon(result, typ)
proc toObject*(typ: PType): PType = proc toObject*(typ: PType): PType =
@ -1888,8 +1917,8 @@ proc isSinkParam*(s: PSym): bool {.inline.} =
proc isSinkType*(t: PType): bool {.inline.} = proc isSinkType*(t: PType): bool {.inline.} =
t.kind == tySink or tfHasOwned in t.flags t.kind == tySink or tfHasOwned in t.flags
proc newProcType*(info: TLineInfo; owner: PSym): PType = proc newProcType*(info: TLineInfo; id: ItemId; owner: PSym): PType =
result = newType(tyProc, owner) result = newType(tyProc, id, owner)
result.n = newNodeI(nkFormalParams, info) result.n = newNodeI(nkFormalParams, info)
rawAddSon(result, nil) # return type rawAddSon(result, nil) # return type
# result.n[0] used to be `nkType`, but now it's `nkEffectList` because # result.n[0] used to be `nkType`, but now it's `nkEffectList` because

View file

@ -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: putIntoDest(p, d, e, rope(lengthOrd(p.config, typ)))
else: internalError(p.config, e.info, "genArrayLen()") else: internalError(p.config, e.info, "genArrayLen()")
proc makePtrType(baseType: PType): PType = proc makePtrType(baseType: PType; idgen: IdGenerator): PType =
result = newType(tyPtr, baseType.owner) result = newType(tyPtr, nextId idgen, baseType.owner)
addSonSkipIntLit(result, baseType) addSonSkipIntLit(result, baseType, idgen)
proc makeAddr(n: PNode): PNode = proc makeAddr(n: PNode; idgen: IdGenerator): PNode =
if n.kind == nkHiddenAddr: if n.kind == nkHiddenAddr:
result = n result = n
else: else:
result = newTree(nkHiddenAddr, n) result = newTree(nkHiddenAddr, n)
result.typ = makePtrType(n.typ) result.typ = makePtrType(n.typ, idgen)
proc genSetLengthSeq(p: BProc, e: PNode, d: var TLoc) = proc genSetLengthSeq(p: BProc, e: PNode, d: var TLoc) =
if optSeqDestructors in p.config.globalOptions: if optSeqDestructors in p.config.globalOptions:
e[1] = makeAddr(e[1]) e[1] = makeAddr(e[1], p.module.idgen)
genCall(p, e, d) genCall(p, e, d)
return return
var a, b, call: TLoc var a, b, call: TLoc
@ -2240,7 +2240,7 @@ proc genEnumToStr(p: BProc, e: PNode, d: var TLoc) =
toStrProc = p toStrProc = p
break break
if toStrProc == nil: 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)) t.methods.add((ToStringProcSlot, toStrProc))
var n = copyTree(e) var n = copyTree(e)
n[0] = newSymNode(toStrProc) 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 mAppendStrStr: genStrAppend(p, e, d)
of mAppendSeqElem: of mAppendSeqElem:
if optSeqDestructors in p.config.globalOptions: if optSeqDestructors in p.config.globalOptions:
e[1] = makeAddr(e[1]) e[1] = makeAddr(e[1], p.module.idgen)
genCall(p, e, d) genCall(p, e, d)
else: else:
genSeqElemAppend(p, e, d) genSeqElemAppend(p, e, d)
@ -2393,13 +2393,13 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
when defined(leanCompiler): when defined(leanCompiler):
quit "compiler built without support for the 'spawn' statement" quit "compiler built without support for the 'spawn' statement"
else: 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) expr(p, n, d)
of mParallel: of mParallel:
when defined(leanCompiler): when defined(leanCompiler):
quit "compiler built without support for the 'parallel' statement" quit "compiler built without support for the 'parallel' statement"
else: 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) expr(p, n, d)
of mDeepCopy: of mDeepCopy:
if p.config.selectedGC in {gcArc, gcOrc} and optEnableDeepCopy notin p.config.globalOptions: if p.config.selectedGC in {gcArc, gcOrc} and optEnableDeepCopy notin p.config.globalOptions:

View file

@ -180,10 +180,6 @@ proc readKey(L: var TBaseLexer, result: var string) =
if L.buf[pos] != ':': doAssert(false, "ccgmerge: ':' expected") if L.buf[pos] != ':': doAssert(false, "ccgmerge: ':' expected")
L.bufpos = pos + 1 # skip ':' L.bufpos = pos + 1 # skip ':'
proc newFakeType(id: int): PType =
new(result)
result.id = id
proc readTypeCache(L: var TBaseLexer, result: var TypeCache) = proc readTypeCache(L: var TBaseLexer, result: var TypeCache) =
if ^L.bufpos != '{': doAssert(false, "ccgmerge: '{' expected") if ^L.bufpos != '{': doAssert(false, "ccgmerge: '{' expected")
inc L.bufpos inc L.bufpos
@ -192,10 +188,7 @@ proc readTypeCache(L: var TBaseLexer, result: var TypeCache) =
var key = decodeStr(L.buf, L.bufpos) var key = decodeStr(L.buf, L.bufpos)
if ^L.bufpos != ':': doAssert(false, "ccgmerge: ':' expected") if ^L.bufpos != ':': doAssert(false, "ccgmerge: ':' expected")
inc L.bufpos inc L.bufpos
var value = decodeStr(L.buf, L.bufpos) discard decodeStr(L.buf, L.bufpos)
# XXX implement me
when false:
idTablePut(result, newFakeType(key), value.rope)
inc L.bufpos inc L.bufpos
proc readIntSet(L: var TBaseLexer, result: var IntSet) = proc readIntSet(L: var TBaseLexer, result: var IntSet) =

View file

@ -66,7 +66,7 @@ proc genVarTuple(p: BProc, n: PNode) =
# if we have a something that's been captured, use the lowering instead: # if we have a something that's been captured, use the lowering instead:
for i in 0..<n.len-2: for i in 0..<n.len-2:
if n[i].kind != nkSym: 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 return
# check only the first son # check only the first son
@ -1525,7 +1525,7 @@ proc genCaseObjDiscMapping(p: BProc, e: PNode, t: PType, field: PSym; d: var TLo
theProc = p theProc = p
break break
if theProc == nil: 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)) t.methods.add((ObjDiscMappingProcSlot, theProc))
var call = newNodeIT(nkCall, e.info, getSysType(p.module.g.graph, e.info, tyUInt8)) var call = newNodeIT(nkCall, e.info, getSysType(p.module.g.graph, e.info, tyUInt8))
call.add newSymNode(theProc) call.add newSymNode(theProc)

View file

@ -1266,10 +1266,10 @@ proc genArrayInfo(m: BModule, typ: PType, name: Rope; info: TLineInfo) =
proc fakeClosureType(m: BModule; owner: PSym): PType = proc fakeClosureType(m: BModule; owner: PSym): PType =
# we generate the same RTTI as for a tuple[pointer, ref tuple[]] # we generate the same RTTI as for a tuple[pointer, ref tuple[]]
result = newType(tyTuple, owner) result = newType(tyTuple, nextId m.idgen, owner)
result.rawAddSon(newType(tyPointer, owner)) result.rawAddSon(newType(tyPointer, nextId m.idgen, owner))
var r = newType(tyRef, owner) var r = newType(tyRef, nextId m.idgen, owner)
let obj = createObj(m.g.graph, owner, owner.info, final=false) let obj = createObj(m.g.graph, m.idgen, owner, owner.info, final=false)
r.rawAddSon(obj) r.rawAddSon(obj)
result.rawAddSon(r) result.rawAddSon(r)
@ -1395,9 +1395,9 @@ proc genTypeInfoV2(m: BModule, t: PType; info: TLineInfo): Rope =
result = prefixTI.rope & result & ")".rope result = prefixTI.rope & result & ")".rope
proc openArrayToTuple(m: BModule; t: PType): PType = proc openArrayToTuple(m: BModule; t: PType): PType =
result = newType(tyTuple, t.owner) result = newType(tyTuple, nextId m.idgen, t.owner)
let p = newType(tyPtr, t.owner) let p = newType(tyPtr, nextId m.idgen, t.owner)
let a = newType(tyUncheckedArray, t.owner) let a = newType(tyUncheckedArray, nextId m.idgen, t.owner)
a.add t.lastSon a.add t.lastSon
p.add a p.add a
result.add p result.add p

View file

@ -996,9 +996,9 @@ proc genProcAux(m: BModule, prc: PSym) =
var returnStmt: Rope = nil var returnStmt: Rope = nil
assert(prc.ast != 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: 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 sfPure notin prc.flags and prc.typ[0] != nil:
if resultPos >= prc.ast.len: if resultPos >= prc.ast.len:
@ -1844,9 +1844,10 @@ template injectG() {.dirty.} =
when not defined(nimHasSinkInference): when not defined(nimHasSinkInference):
{.pragma: nosinks.} {.pragma: nosinks.}
proc myOpen(graph: ModuleGraph; module: PSym): PPassContext {.nosinks.} = proc myOpen(graph: ModuleGraph; module: PSym; idgen: IdGenerator): PPassContext {.nosinks.} =
injectG() injectG()
result = newModule(g, module, graph.config) result = newModule(g, module, graph.config)
result.idgen = idgen
if optGenIndex in graph.config.globalOptions and g.generatedHeader == nil: if optGenIndex in graph.config.globalOptions and g.generatedHeader == nil:
let f = if graph.config.headerFile.len > 0: AbsoluteFile graph.config.headerFile let f = if graph.config.headerFile.len > 0: AbsoluteFile graph.config.headerFile
else: graph.config.projectFull else: graph.config.projectFull
@ -1920,9 +1921,9 @@ proc myProcess(b: PPassContext, n: PNode): PNode =
m.initProc.options = initProcOptions(m) m.initProc.options = initProcOptions(m)
#softRnl = if optLineDir in m.config.options: noRnl else: rnl #softRnl = if optLineDir in m.config.options: noRnl else: rnl
# XXX replicate this logic! # 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: 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: if m.hcrOn:
addHcrInitGuards(m.initProc, transformedN, m.inHcrInitGuard) addHcrInitGuards(m.initProc, transformedN, m.inHcrInitGuard)

View file

@ -107,11 +107,11 @@ proc attachDispatcher(s: PSym, dispatcher: PNode) =
s.ast[resultPos] = newNodeI(nkEmpty, s.info) s.ast[resultPos] = newNodeI(nkEmpty, s.info)
s.ast[dispatcherPos] = dispatcher s.ast[dispatcherPos] = dispatcher
proc createDispatcher(s: PSym): PSym = proc createDispatcher(s: PSym; idgen: IdGenerator): PSym =
var disp = copySym(s) var disp = copySym(s, nextId(idgen))
incl(disp.flags, sfDispatcher) incl(disp.flags, sfDispatcher)
excl(disp.flags, sfExported) 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): # we can't inline the dispatcher itself (for now):
if disp.typ.callConv == ccInline: disp.typ.callConv = ccNimCall if disp.typ.callConv == ccInline: disp.typ.callConv = ccNimCall
disp.ast = copyTree(s.ast) disp.ast = copyTree(s.ast)
@ -119,7 +119,7 @@ proc createDispatcher(s: PSym): PSym =
disp.loc.r = nil disp.loc.r = nil
if s.typ[0] != nil: if s.typ[0] != nil:
if disp.ast.len > resultPos: 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: else:
# We've encountered a method prototype without a filled-in # We've encountered a method prototype without a filled-in
# resultPos slot. We put a placeholder in there that will # 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: if disp.typ.lockLevel < meth.typ.lockLevel:
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 var witness: PSym
for i in 0..<g.methods.len: for i in 0..<g.methods.len:
let disp = g.methods[i].dispatcher let disp = g.methods[i].dispatcher
@ -177,7 +177,7 @@ proc methodDef*(g: ModuleGraph; s: PSym, fromCache: bool) =
of Invalid: of Invalid:
if witness.isNil: witness = g.methods[i].methods[0] if witness.isNil: witness = g.methods[i].methods[0]
# create a new dispatcher: # 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 #echo "adding ", s.info
#if fromCache: #if fromCache:
# internalError(s.info, "no method dispatcher found") # internalError(s.info, "no method dispatcher found")

View file

@ -153,6 +153,7 @@ type
curExcHandlingState: int # Negative for except, positive for finally curExcHandlingState: int # Negative for except, positive for finally
nearestFinally: int # Index of the nearest finally block. For try/except it nearestFinally: int # Index of the nearest finally block. For try/except it
# is their finally. For finally it is parent finally. Otherwise -1 # is their finally. For finally it is parent finally. Otherwise -1
idgen: IdGenerator
const const
nkSkip = {nkEmpty..nkNilLit, nkTemplateDef, nkTypeSection, nkStaticStmt, 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))) ctx.newStateAssgn(newIntTypeNode(stateNo, ctx.g.getSysType(TLineInfo(), tyInt)))
proc newEnvVar(ctx: var Ctx, name: string, typ: PType): PSym = 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 result.typ = typ
assert(not typ.isNil) assert(not typ.isNil)
@ -189,7 +190,7 @@ proc newEnvVar(ctx: var Ctx, name: string, typ: PType): PSym =
else: else:
let envParam = getEnvParam(ctx.fn) let envParam = getEnvParam(ctx.fn)
# let obj = envParam.typ.lastSon # 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 = proc newEnvVarAccess(ctx: Ctx, s: PSym): PNode =
if ctx.stateVarSym.isNil: if ctx.stateVarSym.isNil:
@ -804,7 +805,7 @@ proc newEndFinallyNode(ctx: var Ctx, info: TLineInfo): PNode =
cmp.typ = ctx.g.getSysType(info, tyBool) cmp.typ = ctx.g.getSysType(info, tyBool)
let asgn = newTree(nkFastAsgn, let asgn = newTree(nkFastAsgn,
newSymNode(getClosureIterResult(ctx.g, ctx.fn), info), newSymNode(getClosureIterResult(ctx.g, ctx.fn, ctx.idgen), info),
ctx.newTmpResultAccess()) ctx.newTmpResultAccess())
let retStmt = newTree(nkReturnStmt, asgn) let retStmt = newTree(nkReturnStmt, asgn)
@ -1044,7 +1045,7 @@ proc transformStateAssignments(ctx: var Ctx, n: PNode): PNode =
if n[0][0].kind != nkEmpty: if n[0][0].kind != nkEmpty:
var a = newNodeI(nkAsgn, n[0][0].info) var a = newNodeI(nkAsgn, n[0][0].info)
var retVal = n[0][0] #liftCapturedVars(n[0], owner, d, c) 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 a.add retVal
retStmt.add(a) retStmt.add(a)
else: else:
@ -1116,10 +1117,10 @@ proc skipThroughEmptyStates(ctx: var Ctx, n: PNode): PNode=
for i in 0..<n.len: for i in 0..<n.len:
n[i] = ctx.skipThroughEmptyStates(n[i]) n[i] = ctx.skipThroughEmptyStates(n[i])
proc newArrayType(g: ModuleGraph; n: int, t: PType, owner: PSym): PType = proc newArrayType(g: ModuleGraph; n: int, t: PType; idgen: IdGenerator; owner: PSym): PType =
result = newType(tyArray, owner) 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.n = newTree(nkRange, g.newIntLit(owner.info, 0), g.newIntLit(owner.info, n))
rng.rawAddSon(t) 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.} = proc createExceptionTable(ctx: var Ctx): PNode {.inline.} =
result = newNodeI(nkBracket, ctx.fn.info) 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: for i in ctx.exceptionTable:
let elem = newIntNode(nkIntLit, i) let elem = newIntNode(nkIntLit, i)
@ -1289,10 +1290,12 @@ type
finallys: seq[PNode] finallys: seq[PNode]
config: ConfigRef config: ConfigRef
blocks: seq[(PNode, int)] blocks: seq[(PNode, int)]
idgen: IdGenerator
FreshVarsContext = object FreshVarsContext = object
tab: Table[int, PSym] tab: Table[int, PSym]
config: ConfigRef config: ConfigRef
info: TLineInfo info: TLineInfo
idgen: IdGenerator
proc freshVars(n: PNode; c: var FreshVarsContext): PNode = proc freshVars(n: PNode; c: var FreshVarsContext): PNode =
case n.kind case n.kind
@ -1311,7 +1314,7 @@ proc freshVars(n: PNode; c: var FreshVarsContext): PNode =
let idefs = copyNode(it) let idefs = copyNode(it)
for v in 0..it.len-3: for v in 0..it.len-3:
if it[v].kind == nkSym: 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 c.tab[it[v].sym.id] = x
idefs.add newSymNode(x) idefs.add newSymNode(x)
else: else:
@ -1371,27 +1374,29 @@ proc preprocess(c: var PreprocessContext; n: PNode): PNode =
if fin >= 0: if fin >= 0:
result = newNodeI(nkStmtList, n.info) result = newNodeI(nkStmtList, n.info)
for i in countdown(c.finallys.high, fin): 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) result.add freshVars(preprocess(c, c.finallys[i]), vars)
c.idgen = vars.idgen
result.add n result.add n
of nkSkip: discard of nkSkip: discard
else: else:
for i in 0 ..< n.len: for i in 0 ..< n.len:
result[i] = preprocess(c, n[i]) 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 var ctx: Ctx
ctx.g = g ctx.g = g
ctx.fn = fn ctx.fn = fn
ctx.idgen = idgen
if getEnvParam(fn).isNil: if getEnvParam(fn).isNil:
# Lambda lifting was not done yet. Use temporary :state sym, which will # Lambda lifting was not done yet. Use temporary :state sym, which will
# be handled specially by lambda lifting. Local temp vars (if needed) # be handled specially by lambda lifting. Local temp vars (if needed)
# should follow the same logic. # should follow the same logic.
ctx.stateVarSym = newSym(skVar, getIdent(ctx.g.cache, ":state"), fn, fn.info) ctx.stateVarSym = newSym(skVar, getIdent(ctx.g.cache, ":state"), nextId(idgen), fn, fn.info)
ctx.stateVarSym.typ = g.createClosureIterStateType(fn) ctx.stateVarSym.typ = g.createClosureIterStateType(fn, idgen)
ctx.stateLoopLabel = newSym(skLabel, getIdent(ctx.g.cache, ":stateLoop"), fn, fn.info) ctx.stateLoopLabel = newSym(skLabel, getIdent(ctx.g.cache, ":stateLoop"), nextId(idgen), fn, fn.info)
var pc = PreprocessContext(finallys: @[], config: g.config) var pc = PreprocessContext(finallys: @[], config: g.config, idgen: idgen)
var n = preprocess(pc, n.toStmtList) var n = preprocess(pc, n.toStmtList)
#echo "transformed into ", n #echo "transformed into ", n
#var n = n.toStmtList #var n = n.toStmtList

View file

@ -59,7 +59,7 @@ proc loadConfigsAndRunMainCommand*(self: NimProg, cache: IdentCache; conf: Confi
graph: ModuleGraph): bool = graph: ModuleGraph): bool =
if self.suggestMode: if self.suggestMode:
conf.command = "nimsuggest" 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: if not self.suggestMode:
let scriptFile = conf.projectFull.changeFileExt("nims") let scriptFile = conf.projectFull.changeFileExt("nims")

View file

@ -54,7 +54,7 @@ proc generateDot*(graph: ModuleGraph; project: AbsoluteFile) =
when not defined(nimHasSinkInference): when not defined(nimHasSinkInference):
{.pragma: nosinks.} {.pragma: nosinks.}
proc myOpen(graph: ModuleGraph; module: PSym): PPassContext {.nosinks.} = proc myOpen(graph: ModuleGraph; module: PSym; idgen: IdGenerator): PPassContext {.nosinks.} =
var g: PGen var g: PGen
new(g) new(g)
g.module = module g.module = module

View file

@ -68,10 +68,10 @@ template myOpenImpl(ext: untyped) {.dirty.} =
g.doc = d g.doc = d
result = g result = g
proc myOpen(graph: ModuleGraph; module: PSym): PPassContext = proc myOpen(graph: ModuleGraph; module: PSym; idgen: IdGenerator): PPassContext =
myOpenImpl(HtmlExt) myOpenImpl(HtmlExt)
proc myOpenJson(graph: ModuleGraph; module: PSym): PPassContext = proc myOpenJson(graph: ModuleGraph; module: PSym; idgen: IdGenerator): PPassContext =
myOpenImpl(JsonExt) myOpenImpl(JsonExt)
const docgen2Pass* = makePass(open = myOpen, process = processNode, close = close) const docgen2Pass* = makePass(open = myOpen, process = processNode, close = close)

View file

@ -1,16 +1,16 @@
import ast, idents, lineinfos, modulegraphs, magicsys import ast, idents, lineinfos, modulegraphs, magicsys
proc genEnumToStrProc*(t: PType; info: TLineInfo; g: ModuleGraph): PSym = proc genEnumToStrProc*(t: PType; info: TLineInfo; g: ModuleGraph; idgen: IdGenerator): PSym =
result = newSym(skProc, getIdent(g.cache, "$"), t.owner, info) 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 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) 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) result.typ.n = newNodeI(nkFormalParams, info)
rawAddSon(result.typ, res.typ) rawAddSon(result.typ, res.typ)
result.typ.n.add newNodeI(nkEffectList, info) 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) result = searchObjCase(t[0].skipTypes({tyAlias, tyGenericInst, tyRef, tyPtr}), field)
doAssert result != nil doAssert result != nil
proc genCaseObjDiscMapping*(t: PType; field: PSym; info: TLineInfo; g: ModuleGraph): PSym = proc genCaseObjDiscMapping*(t: PType; field: PSym; info: TLineInfo; g: ModuleGraph; idgen: IdGenerator): PSym =
result = newSym(skProc, getIdent(g.cache, "objDiscMapping"), t.owner, info) 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 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) 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) result.typ.n = newNodeI(nkFormalParams, info)
rawAddSon(result.typ, res.typ) rawAddSon(result.typ, res.typ)
result.typ.n.add newNodeI(nkEffectList, info) result.typ.n.add newNodeI(nkEffectList, info)

View file

@ -22,6 +22,7 @@ type
config: ConfigRef config: ConfigRef
ic: IdentCache ic: IdentCache
instID: int instID: int
idgen: IdGenerator
proc copyNode(ctx: TemplCtx, a, b: PNode): PNode = proc copyNode(ctx: TemplCtx, a, b: PNode): PNode =
result = copyNode(a) 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 internalAssert c.config, sfGenSym in s.flags or s.kind == skType
var x = PSym(idTableGet(c.mapping, s)) var x = PSym(idTableGet(c.mapping, s))
if x == nil: if x == nil:
x = copySym(s) x = copySym(s, nextId(c.idgen))
# sem'check needs to set the owner properly later, see bug #9476 # sem'check needs to set the owner properly later, see bug #9476
x.owner = nil # c.genSymOwner x.owner = nil # c.genSymOwner
#if x.kind == skParam and x.owner.kind == skModule: #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; proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym;
conf: ConfigRef; conf: ConfigRef;
ic: IdentCache; instID: ref int; ic: IdentCache; instID: ref int;
idgen: IdGenerator;
fromHlo=false): PNode = fromHlo=false): PNode =
inc(conf.evalTemplateCounter) inc(conf.evalTemplateCounter)
if conf.evalTemplateCounter > evalTemplateLimit: if conf.evalTemplateCounter > evalTemplateLimit:
@ -183,6 +185,7 @@ proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym;
ctx.ic = ic ctx.ic = ic
initIdTable(ctx.mapping) initIdTable(ctx.mapping)
ctx.instID = instID[] ctx.instID = instID[]
ctx.idgen = idgen
let body = tmpl.getBody let body = tmpl.getBody
#echo "instantion of ", renderTree(body, {renderIds}) #echo "instantion of ", renderTree(body, {renderIds})

View file

@ -993,8 +993,9 @@ proc addFactLt*(m: var TModel; a, b: PNode) =
addFactLe(m, a, bb) addFactLe(m, a, bb)
proc settype(n: PNode): PType = proc settype(n: PNode): PType =
result = newType(tySet, n.typ.owner) result = newType(tySet, ItemId(module: -1, item: -1), n.typ.owner)
addSonSkipIntLit(result, n.typ) var idgen: IdGenerator
addSonSkipIntLit(result, n.typ, idgen)
proc buildOf(it, loc: PNode; o: Operators): PNode = proc buildOf(it, loc: PNode; o: Operators): PNode =
var s = newNodeI(nkCurly, it.info, it.len-1) var s = newNodeI(nkCurly, it.info, it.len-1)

View file

@ -86,9 +86,9 @@ proc hlo(c: PContext, n: PNode): PNode =
else: else:
result = fitNode(c, n.typ, result, n.info) result = fitNode(c, n.typ, result, n.info)
# optimization has been applied so check again: # 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 = 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 = proc hloBody(c: PContext, n: PNode): PNode =
# fast exit: # fast exit:

View file

@ -15,12 +15,9 @@ import
hashes, wordrecg hashes, wordrecg
type type
TIdObj* = object of RootObj
id*: int # unique id; use this for comparisons and not the pointers
PIdObj* = ref TIdObj
PIdent* = ref TIdent 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 s*: string
next*: PIdent # for hash-table chaining next*: PIdent # for hash-table chaining
h*: Hash # hash value of s h*: Hash # hash value of s

View file

@ -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()

View file

@ -136,7 +136,7 @@ proc importModuleAs(c: PContext; n: PNode, realModule: PSym): PSym =
localError(c.config, n.info, "module alias must be an identifier") localError(c.config, n.info, "module alias must be an identifier")
elif n[1].ident.id != realModule.name.id: elif n[1].ident.id != realModule.name.id:
# some misguided guy will write 'import abc.foo as foo' ... # 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) c.config.options)
proc myImportModule(c: PContext, n: PNode; importStmtResult: PNode): PSym = proc myImportModule(c: PContext, n: PNode; importStmtResult: PNode): PSym =

View file

@ -40,6 +40,7 @@ type
inLoop, inSpawn: int inLoop, inSpawn: int
uninit: IntSet # set of uninit'ed vars uninit: IntSet # set of uninit'ed vars
uninitComputed: bool uninitComputed: bool
idgen: IdGenerator
ProcessMode = enum ProcessMode = enum
normal normal
@ -61,7 +62,7 @@ template dbg(body) =
body body
proc getTemp(c: var Con; s: var Scope; typ: PType; info: TLineInfo): PNode = 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 sym.typ = typ
s.vars.add(sym) s.vars.add(sym)
result = newSymNode(sym) result = newSymNode(sym)
@ -250,16 +251,16 @@ proc checkForErrorPragma(c: Con; t: PType; ri: PNode; opname: string) =
m.add c.owner.name.s m.add c.owner.name.s
localError(c.graph.config, ri.info, errGenerated, m) localError(c.graph.config, ri.info, errGenerated, m)
proc makePtrType(c: Con, baseType: PType): PType = proc makePtrType(c: var Con, baseType: PType): PType =
result = newType(tyPtr, c.owner) result = newType(tyPtr, nextId c.idgen, c.owner)
addSonSkipIntLit(result, baseType) 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)) let addrExp = newNodeIT(nkHiddenAddr, dest.info, makePtrType(c, dest.typ))
addrExp.add(dest) addrExp.add(dest)
result = newTree(nkCall, newSymNode(op), addrExp) 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] var op = t.attachedOps[kind]
if op == nil or op.ast[genericParamsPos].kind != nkEmpty: if op == nil or op.ast[genericParamsPos].kind != nkEmpty:
# give up and find the canonical type instead: # 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]) if sfError in op.flags: checkForErrorPragma(c, t, ri, AttachedOpToStr[kind])
c.genOp(op, dest) 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}) let t = dest.typ.skipTypes({tyGenericInst, tyAlias, tySink})
result = c.genOp(t, attachedDestructor, dest, nil) 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. # and copyMem(dest, source). This is efficient.
result = newTree(nkStmtList, c.genDestroy(dest), newTree(nkFastAsgn, dest, ri)) 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}) let t = dest.typ.skipTypes({tyGenericInst, tyAlias, tySink})
result = c.genOp(t, attachedAsgn, dest, ri) 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 return
# generate: if le != tmp: `=destroy`(le) # 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)) let cond = newNodeIT(nkInfix, n.info, getSysType(c.graph, unknownLineInfo, tyBool))
cond.add newSymNode(getMagicEqSymForType(c.graph, le.typ, n.info)) cond.add newSymNode(getMagicEqSymForType(c.graph, le.typ, n.info))
cond.add le cond.add le
@ -377,7 +378,7 @@ proc destructiveMoveVar(n: PNode; c: var Con; s: var Scope): PNode =
else: else:
result = newNodeIT(nkStmtListExpr, n.info, n.typ) 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 temp.typ = n.typ
var v = newNodeI(nkLetSection, n.info) var v = newNodeI(nkLetSection, n.info)
let tempAsNode = newSymNode(temp) 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: for it in n:
var ri = it[^1] var ri = it[^1]
if it.kind == nkVarTuple and hasDestructor(c, ri.typ): 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) result.add p(x, c, s, consumed)
elif it.kind == nkIdentDefs and hasDestructor(c, it[0].typ) and not isCursor(it[0], c): elif it.kind == nkIdentDefs and hasDestructor(c, it[0].typ) and not isCursor(it[0], c):
for j in 0..<it.len-2: for j in 0..<it.len-2:
@ -1010,10 +1011,10 @@ proc injectDefaultCalls(n: PNode, c: var Con) =
for i in 0..<n.safeLen: for i in 0..<n.safeLen:
injectDefaultCalls(n[i], c) 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)): if sfGeneratedOp in owner.flags or (owner.kind == skIterator and isInlineIterator(owner.typ)):
return n 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: dbg:
echo "\n### ", owner.name.s, ":\nCFG:" echo "\n### ", owner.name.s, ":\nCFG:"
echoCfg(c.g) echoCfg(c.g)

View file

@ -11,7 +11,7 @@
## https://github.com/nim-lang/RFCs/issues/244 for more details. ## https://github.com/nim-lang/RFCs/issues/244 for more details.
import import
ast, types, renderer, idents, intsets ast, types, renderer, intsets
proc canAlias(arg, ret: PType; marker: var IntSet): bool proc canAlias(arg, ret: PType; marker: var IntSet): bool

View file

@ -602,12 +602,12 @@ proc arithAux(p: PProc, n: PNode, r: var TCompRes, op: TMagic) =
of mMulF64: applyFormat("($1 * $2)", "($1 * $2)") of mMulF64: applyFormat("($1 * $2)", "($1 * $2)")
of mDivF64: applyFormat("($1 / $2)", "($1 / $2)") of mDivF64: applyFormat("($1 / $2)", "($1 / $2)")
of mShrI: applyFormat("", "") of mShrI: applyFormat("", "")
of mShlI: of mShlI:
if n[1].typ.size <= 4: if n[1].typ.size <= 4:
applyFormat("($1 << $2)", "($1 << $2)") applyFormat("($1 << $2)", "($1 << $2)")
else: else:
applyFormat("($1 * Math.pow(2,$2))", "($1 * Math.pow(2,$2))") applyFormat("($1 * Math.pow(2,$2))", "($1 * Math.pow(2,$2))")
of mAshrI: of mAshrI:
if n[1].typ.size <= 4: if n[1].typ.size <= 4:
applyFormat("($1 >> $2)", "($1 >> $2)") applyFormat("($1 >> $2)", "($1 >> $2)")
else: else:
@ -1804,7 +1804,7 @@ proc genVarStmt(p: PProc, n: PNode) =
var a = n[i] var a = n[i]
if a.kind != nkCommentStmt: if a.kind != nkCommentStmt:
if a.kind == nkVarTuple: 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) genStmt(p, unpacked)
else: else:
assert(a.kind == nkIdentDefs) assert(a.kind == nkIdentDefs)
@ -2316,9 +2316,9 @@ proc genProc(oldProc: PProc, prc: PSym): Rope =
else: else:
returnStmt = "return $#;$n" % [a.res] 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: 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) p.nested: genStmt(p, transformedBody)
@ -2607,9 +2607,9 @@ proc genModule(p: PProc, n: PNode) =
p.body.add(frameCreate(p, p.body.add(frameCreate(p,
makeJSString("module " & p.module.module.name.s), makeJSString("module " & p.module.module.name.s),
makeJSString(toFilenameOption(p.config, p.module.module.info.fileIndex, foStacktrace)))) 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: 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: if p.config.hcrOn and n.kind == nkStmtList:
let moduleSym = p.module.module let moduleSym = p.module.module
var moduleLoadedVar = rope(moduleSym.name.s) & "_loaded" & 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)) writeFile(outFile.string & ".map", $(%map))
discard writeRopeIfNotEqual(code, outFile) 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 = newModule(graph, s)
result.idgen = idgen
const JSgenPass* = makePass(myOpen, myProcess, myClose) const JSgenPass* = makePass(myOpen, myProcess, myClose)

View file

@ -126,32 +126,32 @@ proc newCall(a: PSym, b: PNode): PNode =
result.add newSymNode(a) result.add newSymNode(a)
result.add b 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) var n = newNodeI(nkRange, iter.info)
n.add newIntNode(nkIntLit, -1) n.add newIntNode(nkIntLit, -1)
n.add newIntNode(nkIntLit, 0) n.add newIntNode(nkIntLit, 0)
result = newType(tyRange, iter) result = newType(tyRange, nextId(idgen), iter)
result.n = n result.n = n
var intType = nilOrSysInt(g) var intType = nilOrSysInt(g)
if intType.isNil: intType = newType(tyInt, iter) if intType.isNil: intType = newType(tyInt, nextId(idgen), iter)
rawAddSon(result, intType) rawAddSon(result, intType)
proc createStateField(g: ModuleGraph; iter: PSym): PSym = proc createStateField(g: ModuleGraph; iter: PSym; idgen: IdGenerator): PSym =
result = newSym(skField, getIdent(g.cache, ":state"), iter, iter.info) result = newSym(skField, getIdent(g.cache, ":state"), nextId(idgen), iter, iter.info)
result.typ = createClosureIterStateType(g, iter) 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 # 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: # hard to figure out if it comes from a closure iterator:
result = createObj(g, owner, info, final=false) result = createObj(g, idgen, owner, info, final=false)
rawAddField(result, createStateField(g, owner)) 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: if resultPos < iter.ast.len:
result = iter.ast[resultPos].sym result = iter.ast[resultPos].sym
else: else:
# XXX a bit hacky: # 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] result.typ = iter.typ[0]
incl(result.flags, sfUsed) incl(result.flags, sfUsed)
iter.ast.add newSymNode(result) iter.ast.add newSymNode(result)
@ -209,7 +209,7 @@ proc newAsgnStmt(le, ri: PNode, info: TLineInfo): PNode =
result[0] = le result[0] = le
result[1] = ri 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 = newNodeIT(nkClosure, info, prc.typ)
result.add(newSymNode(prc)) result.add(newSymNode(prc))
if env == nil: 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") localError(g.config, info, "internal error: taking closure of closure")
result.add(env) result.add(env)
#if isClosureIterator(result.typ): #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: if tfHasAsgn in result.typ.flags or optSeqDestructors in g.config.globalOptions:
prc.flags.incl sfInjectDestructors 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 let isCompileTime = sfCompileTime in owner.flags or owner.kind == skMacro
result = conf.backend == backendJs and not isCompileTime result = conf.backend == backendJs and not isCompileTime
proc createTypeBoundOpsLL(g: ModuleGraph; refType: PType; info: TLineInfo; owner: PSym) = proc createTypeBoundOpsLL(g: ModuleGraph; refType: PType; info: TLineInfo; idgen: IdGenerator; owner: PSym) =
createTypeBoundOps(g, nil, refType.lastSon, info) createTypeBoundOps(g, nil, refType.lastSon, info, idgen)
createTypeBoundOps(g, nil, refType, info) createTypeBoundOps(g, nil, refType, info, idgen)
if tfHasAsgn in refType.flags or optSeqDestructors in g.config.globalOptions: if tfHasAsgn in refType.flags or optSeqDestructors in g.config.globalOptions:
owner.flags.incl sfInjectDestructors 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)) # transforms (iter) to (let env = newClosure[iter](); (iter, env))
if liftingHarmful(g.config, owner): return n if liftingHarmful(g.config, owner): return n
let iter = n.sym let iter = n.sym
@ -255,10 +255,10 @@ proc liftIterSym*(g: ModuleGraph; n: PNode; owner: PSym): PNode =
var env: PNode var env: PNode
if owner.isIterator: if owner.isIterator:
let it = getHiddenParam(g, owner) 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) env = indirectAccess(newSymNode(it), hp, hp.info)
else: 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.typ = hp.typ
e.flags = hp.flags e.flags = hp.flags
env = newSymNode(e) env = newSymNode(e)
@ -267,13 +267,13 @@ proc liftIterSym*(g: ModuleGraph; n: PNode; owner: PSym): PNode =
result.add(v) result.add(v)
# add 'new' statement: # add 'new' statement:
result.add newCall(getSysSym(g, n.info, "internalNew"), env) result.add newCall(getSysSym(g, n.info, "internalNew"), env)
createTypeBoundOpsLL(g, env.typ, n.info, owner) createTypeBoundOpsLL(g, env.typ, n.info, idgen, owner)
result.add makeClosure(g, iter, env, n.info) 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 envParam = getHiddenParam(g, owner)
let obj = envParam.typ.skipTypes({tyOwned, tyRef, tyPtr}) let obj = envParam.typ.skipTypes({tyOwned, tyRef, tyPtr})
addField(obj, s, g.cache) addField(obj, s, g.cache, idgen)
var access = newSymNode(envParam) var access = newSymNode(envParam)
assert obj.kind == tyObject assert obj.kind == tyObject
@ -305,13 +305,15 @@ type
ownerToType: Table[int, PType] ownerToType: Table[int, PType]
somethingToDo: bool somethingToDo: bool
graph: ModuleGraph graph: ModuleGraph
idgen: IdGenerator
proc initDetectionPass(g: ModuleGraph; fn: PSym): DetectionPass = proc initDetectionPass(g: ModuleGraph; fn: PSym; idgen: IdGenerator): DetectionPass =
result.processed = initIntSet() result.processed = initIntSet()
result.capturedVars = initIntSet() result.capturedVars = initIntSet()
result.ownerToType = initTable[int, PType]() result.ownerToType = initTable[int, PType]()
result.processed.incl(fn.id) result.processed.incl(fn.id)
result.graph = g result.graph = g
result.idgen = idgen
discard """ discard """
proc outer = proc outer =
@ -327,15 +329,15 @@ proc getEnvTypeForOwner(c: var DetectionPass; owner: PSym;
info: TLineInfo): PType = info: TLineInfo): PType =
result = c.ownerToType.getOrDefault(owner.id) result = c.ownerToType.getOrDefault(owner.id)
if result.isNil: if result.isNil:
result = newType(tyRef, owner) result = newType(tyRef, nextId(c.idgen), owner)
let obj = createEnvObj(c.graph, owner, info) let obj = createEnvObj(c.graph, c.idgen, owner, info)
rawAddSon(result, obj) rawAddSon(result, obj)
c.ownerToType[owner.id] = result 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: if optOwnedRefs in c.graph.config.globalOptions:
assert t.kind == tyRef assert t.kind == tyRef
result = newType(tyOwned, t.owner) result = newType(tyOwned, nextId(c.idgen), t.owner)
result.flags.incl tfHasOwned result.flags.incl tfHasOwned
result.rawAddSon t result.rawAddSon t
else: else:
@ -344,7 +346,7 @@ proc asOwnedRef(c: DetectionPass; t: PType): PType =
proc getEnvTypeForOwnerUp(c: var DetectionPass; owner: PSym; proc getEnvTypeForOwnerUp(c: var DetectionPass; owner: PSym;
info: TLineInfo): PType = info: TLineInfo): PType =
var r = c.getEnvTypeForOwner(owner, info) var r = c.getEnvTypeForOwner(owner, info)
result = newType(tyPtr, owner) result = newType(tyPtr, nextId(c.idgen), owner)
rawAddSon(result, r.skipTypes({tyOwned, tyRef, tyPtr})) rawAddSon(result, r.skipTypes({tyOwned, tyRef, tyPtr}))
proc createUpField(c: var DetectionPass; dest, dep: PSym; info: TLineInfo) = 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: 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") localError(c.graph.config, dep.info, "internal error: up reference is not a .cursor")
else: 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 result.typ = fieldType
when false: when false:
if c.graph.config.selectedGC == gcDestructors: 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 owner = if fn.kind == skIterator: fn else: fn.skipGenericOwner
let t = c.getEnvTypeForOwner(owner, info) let t = c.getEnvTypeForOwner(owner, info)
if cp == nil: 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) incl(cp.flags, sfFromGeneric)
cp.typ = t cp.typ = t
addHiddenParam(fn, cp) addHiddenParam(fn, cp)
@ -433,7 +435,7 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
if innerProc: if innerProc:
if s.isIterator: c.somethingToDo = true if s.isIterator: c.somethingToDo = true
if not c.processed.containsOrIncl(s.id): 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) detectCapturedVars(body, s, c)
let ow = s.skipGenericOwner let ow = s.skipGenericOwner
if ow == owner: 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}) #let obj = c.getEnvTypeForOwner(s.owner).skipTypes({tyOwned, tyRef, tyPtr})
if s.name.id == getIdent(c.graph.cache, ":state").id: 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: else:
addField(obj, s, c.graph.cache) addField(obj, s, c.graph.cache, c.idgen)
# direct or indirect dependency: # direct or indirect dependency:
elif (innerProc and s.typ.callConv == ccClosure) or interestingVar(s): elif (innerProc and s.typ.callConv == ccClosure) or interestingVar(s):
discard """ discard """
@ -470,7 +472,7 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
if interestingVar(s) and not c.capturedVars.containsOrIncl(s.id): if interestingVar(s) and not c.capturedVars.containsOrIncl(s.id):
let obj = c.getEnvTypeForOwner(ow, n.info).skipTypes({tyOwned, tyRef, tyPtr}) let obj = c.getEnvTypeForOwner(ow, n.info).skipTypes({tyOwned, tyRef, tyPtr})
#getHiddenParam(owner).typ.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: # create required upFields:
var w = owner.skipGenericOwner var w = owner.skipGenericOwner
if isInnerProc(w) or owner.isIterator: 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) localError(g.config, n.info, "internal error: environment misses: " & s.name.s)
result = n result = n
proc newEnvVar(cache: IdentCache; owner: PSym; typ: PType; info: TLineInfo): PNode = proc newEnvVar(cache: IdentCache; owner: PSym; typ: PType; info: TLineInfo; idgen: IdGenerator): PNode =
var v = newSym(skVar, getIdent(cache, envName), owner, info) var v = newSym(skVar, getIdent(cache, envName), nextId(idgen), owner, info)
v.flags = {sfShadowed, sfGeneratedOp} v.flags = {sfShadowed, sfGeneratedOp}
v.typ = typ v.typ = typ
result = newSymNode(v) result = newSymNode(v)
@ -548,7 +550,7 @@ proc newEnvVar(cache: IdentCache; owner: PSym; typ: PType; info: TLineInfo): PNo
else: else:
result = newSymNode(v) result = newSymNode(v)
proc setupEnvVar(owner: PSym; d: DetectionPass; proc setupEnvVar(owner: PSym; d: var DetectionPass;
c: var LiftingPass; info: TLineInfo): PNode = c: var LiftingPass; info: TLineInfo): PNode =
if owner.isIterator: if owner.isIterator:
return getHiddenParam(d.graph, owner).newSymNode return getHiddenParam(d.graph, owner).newSymNode
@ -557,10 +559,10 @@ proc setupEnvVar(owner: PSym; d: DetectionPass;
let envVarType = d.ownerToType.getOrDefault(owner.id) let envVarType = d.ownerToType.getOrDefault(owner.id)
if envVarType.isNil: if envVarType.isNil:
localError d.graph.config, owner.info, "internal error: could not determine closure type" 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 c.envVars[owner.id] = result
if optOwnedRefs in d.graph.config.globalOptions: 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.flags = {sfShadowed, sfGeneratedOp}
v.typ = envVarType v.typ = envVarType
c.unownedEnvVars[owner.id] = newSymNode(v) c.unownedEnvVars[owner.id] = newSymNode(v)
@ -576,7 +578,7 @@ proc getUpViaParam(g: ModuleGraph; owner: PSym): PNode =
result = rawIndirectAccess(result, upField, p.info) result = rawIndirectAccess(result, upField, p.info)
proc rawClosureCreation(owner: PSym; proc rawClosureCreation(owner: PSym;
d: DetectionPass; c: var LiftingPass; d: var DetectionPass; c: var LiftingPass;
info: TLineInfo): PNode = info: TLineInfo): PNode =
result = newNodeI(nkStmtList, owner.info) result = newNodeI(nkStmtList, owner.info)
@ -602,7 +604,7 @@ proc rawClosureCreation(owner: PSym;
let env2 = copyTree(env) let env2 = copyTree(env)
env2.typ = unowned.typ env2.typ = unowned.typ
result.add newAsgnStmt(unowned, env2, env.info) 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: # add assignment statements for captured parameters:
for i in 1..<owner.typ.n.len: for i in 1..<owner.typ.n.len:
@ -611,7 +613,7 @@ proc rawClosureCreation(owner: PSym;
let fieldAccess = indirectAccess(env, local, env.info) let fieldAccess = indirectAccess(env, local, env.info)
# add ``env.param = param`` # add ``env.param = param``
result.add(newAsgnStmt(fieldAccess, newSymNode(local), env.info)) 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: if tfHasAsgn in fieldAccess.typ.flags or optSeqDestructors in d.graph.config.globalOptions:
owner.flags.incl sfInjectDestructors owner.flags.incl sfInjectDestructors
@ -628,28 +630,28 @@ proc rawClosureCreation(owner: PSym;
localError(d.graph.config, env.info, "internal error: cannot create up reference") 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 # we are not in the sem'check phase anymore! so pass 'nil' for the PContext
# and hope for the best: # 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) = info: TLineInfo; res: PNode) =
if optOwnedRefs in d.graph.config.globalOptions: if optOwnedRefs in d.graph.config.globalOptions:
let unowned = c.unownedEnvVars[owner.id] let unowned = c.unownedEnvVars[owner.id]
assert unowned != nil assert unowned != nil
let nilLit = newNodeIT(nkNilLit, info, unowned.typ) let nilLit = newNodeIT(nkNilLit, info, unowned.typ)
res.add newAsgnStmt(unowned, nilLit, info) 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; 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) result = newNodeIT(nkStmtListExpr, iter.info, iter.sym.typ)
let owner = iter.sym.skipGenericOwner 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) incl(v.flags, sfShadowed)
v.typ = asOwnedRef(d, getHiddenParam(d.graph, iter.sym).typ) v.typ = asOwnedRef(d, getHiddenParam(d.graph, iter.sym).typ)
var vnode: PNode var vnode: PNode
if owner.isIterator: if owner.isIterator:
let it = getHiddenParam(d.graph, owner) 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) vnode = indirectAccess(newSymNode(it), v, v.info)
else: else:
vnode = v.newSymNode vnode = v.newSymNode
@ -657,7 +659,7 @@ proc closureCreationForIter(iter: PNode;
addVar(vs, vnode) addVar(vs, vnode)
result.add(vs) result.add(vs)
result.add(newCall(getSysSym(d.graph, iter.info, "internalNew"), vnode)) 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)) let upField = lookupInRecord(v.typ.skipTypes({tyOwned, tyRef, tyPtr}).n, getIdent(d.graph.cache, upName))
if upField != nil: if upField != nil:
@ -667,9 +669,9 @@ proc closureCreationForIter(iter: PNode;
u, iter.info)) u, iter.info))
else: else:
localError(d.graph.config, iter.info, "internal error: cannot create up reference for iter") 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 = c: var LiftingPass): PNode =
var access = setupEnvVar(owner, d, c, n.info) var access = setupEnvVar(owner, d, c, n.info)
if optOwnedRefs in d.graph.config.globalOptions: 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 = proc getStateField*(g: ModuleGraph; owner: PSym): PSym =
getHiddenParam(g, owner).typ.skipTypes({tyOwned, tyRef, tyPtr}).n[0].sym 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 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 = c: var LiftingPass): PNode =
let s = n.sym let s = n.sym
if s == owner: if s == owner:
# recursive calls go through (lambda, hiddenParam): # recursive calls go through (lambda, hiddenParam):
let available = getHiddenParam(d.graph, owner) 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: elif s.isIterator:
result = closureCreationForIter(n, d, c) result = closureCreationForIter(n, d, c)
elif s.skipGenericOwner == owner: elif s.skipGenericOwner == owner:
# direct dependency, so use the outer's env variable: # 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: else:
let available = getHiddenParam(d.graph, owner) let available = getHiddenParam(d.graph, owner)
let wanted = getHiddenParam(d.graph, s).typ let wanted = getHiddenParam(d.graph, s).typ
@ -707,7 +709,7 @@ proc symToClosure(n: PNode; owner: PSym; d: DetectionPass;
var access = newSymNode(available) var access = newSymNode(available)
while true: while true:
if access.typ == wanted: 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 obj = access.typ.skipTypes({tyOwned, tyRef, tyPtr})
let upField = lookupInRecord(obj.n, getIdent(d.graph.cache, upName)) let upField = lookupInRecord(obj.n, getIdent(d.graph.cache, upName))
if upField == nil: if upField == nil:
@ -715,7 +717,7 @@ proc symToClosure(n: PNode; owner: PSym; d: DetectionPass;
return n return n
access = rawIndirectAccess(access, upField, n.info) 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 = c: var LiftingPass): PNode =
result = n result = n
case n.kind case n.kind
@ -727,7 +729,7 @@ proc liftCapturedVars(n: PNode; owner: PSym; d: DetectionPass;
# echo renderTree(s.getBody, {renderIds}) # echo renderTree(s.getBody, {renderIds})
let oldInContainer = c.inContainer let oldInContainer = c.inContainer
c.inContainer = 0 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) body = liftCapturedVars(body, s, d, c)
if c.envVars.getOrDefault(s.id).isNil: if c.envVars.getOrDefault(s.id).isNil:
s.transformedBody = body s.transformedBody = body
@ -833,8 +835,9 @@ proc semCaptureSym*(s, owner: PSym) =
# since the analysis is not entirely correct, we don't set 'tfCapturesEnv' # since the analysis is not entirely correct, we don't set 'tfCapturesEnv'
# here # here
proc liftIterToProc*(g: ModuleGraph; fn: PSym; body: PNode; ptrType: PType): PNode = proc liftIterToProc*(g: ModuleGraph; fn: PSym; body: PNode; ptrType: PType;
var d = initDetectionPass(g, fn) idgen: IdGenerator): PNode =
var d = initDetectionPass(g, fn, idgen)
var c = initLiftingPass(fn) var c = initLiftingPass(fn)
# pretend 'fn' is a closure iterator for the analysis: # pretend 'fn' is a closure iterator for the analysis:
let oldKind = fn.kind let oldKind = fn.kind
@ -847,7 +850,8 @@ proc liftIterToProc*(g: ModuleGraph; fn: PSym; body: PNode; ptrType: PType): PNo
fn.transitionRoutineSymKind(oldKind) fn.transitionRoutineSymKind(oldKind)
fn.typ.callConv = oldCC 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 # XXX backend == backendJs does not suffice! The compiletime stuff needs
# the transformation even when compiling to JS ... # 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 result = body
tooEarly = true tooEarly = true
else: else:
var d = initDetectionPass(g, fn) var d = initDetectionPass(g, fn, idgen)
detectCapturedVars(body, fn, d) detectCapturedVars(body, fn, d)
if not d.somethingToDo and fn.isIterator: if not d.somethingToDo and fn.isIterator:
addClosureParam(d, fn, body.info) addClosureParam(d, fn, body.info)
@ -886,7 +890,7 @@ proc liftLambdasForTopLevel*(module: PSym, body: PNode): PNode =
# ------------------- iterator transformation -------------------------------- # ------------------- 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 # problem ahead: the iterator could be invoked indirectly, but then
# we don't know what environment to create here: # 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 iter = op.sym
let hp = getHiddenParam(g, iter) 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.typ = hp.typ
env.flags = hp.flags env.flags = hp.flags
@ -940,7 +944,7 @@ proc liftForLoop*(g: ModuleGraph; body: PNode; owner: PSym): PNode =
result.add(v) result.add(v)
# add 'new' statement: # add 'new' statement:
result.add(newCall(getSysSym(g, env.info, "internalNew"), env.newSymNode)) 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: elif op.kind == nkStmtListExpr:
let closure = op.lastSon 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 vpart.add newNodeI(nkEmpty, body.info) # no explicit type
if not env.isNil: 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 vpart.add call
v2.add vpart v2.add vpart

View file

@ -27,12 +27,14 @@ type
canRaise: bool canRaise: bool
filterDiscriminator: PSym # we generating destructor for case branch filterDiscriminator: PSym # we generating destructor for case branch
c: PContext # c can be nil, then we are called from lambdalifting! 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 fillBody(c: var TLiftCtx; t: PType; body, x, y: PNode)
proc produceSym(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp; 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 = proc at(a, i: PNode, elemType: PType): PNode =
result = newNodeI(nkBracketExpr, a.info, 2) result = newNodeI(nkBracketExpr, a.info, 2)
@ -73,12 +75,12 @@ proc defaultOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
call.typ = t call.typ = t
body.add newAsgnStmt(x, call) body.add newAsgnStmt(x, call)
proc genAddr(g: ModuleGraph; x: PNode): PNode = proc genAddr(c: var TLiftCtx; x: PNode): PNode =
if x.kind == nkHiddenDeref: if x.kind == nkHiddenDeref:
checkSonsLen(x, 1, g.config) checkSonsLen(x, 1, c.g.config)
result = x[0] result = x[0]
else: 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 result.add x
proc genWhileLoop(c: var TLiftCtx; i, dest: PNode): PNode = 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 = proc genIf(c: var TLiftCtx; cond, action: PNode): PNode =
result = newTree(nkIfStmt, newTree(nkElifBranch, cond, action)) 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)) # generate: cast[ptr ObjType](cast[int](addr(x)) - offsetOf(objType.field))
let intType = getSysType(c.g, unknownLineInfo, tyInt) 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)) addrOf.add newDeref(newSymNode(x))
let castExpr1 = newNodeIT(nkCast, c.info, intType) let castExpr1 = newNodeIT(nkCast, c.info, intType)
castExpr1.add newNodeIT(nkType, 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.typ = intType
minusExpr.add offsetOf minusExpr.add offsetOf
let objPtr = makePtrType(objType.owner, objType) let objPtr = makePtrType(objType.owner, objType, c.idgen)
result = newNodeIT(nkCast, c.info, objPtr) result = newNodeIT(nkCast, c.info, objPtr)
result.add newNodeIT(nkType, c.info, objPtr) result.add newNodeIT(nkType, c.info, objPtr)
result.add minusExpr 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 = proc destructorCall(c: var TLiftCtx; op: PSym; x: PNode): PNode =
var destroy = newNodeIT(nkCall, x.info, op.typ[0]) var destroy = newNodeIT(nkCall, x.info, op.typ[0])
destroy.add(newSymNode(op)) destroy.add(newSymNode(op))
destroy.add genAddr(c.g, x) destroy.add genAddr(c, x)
if sfNeverRaises notin op.flags: if sfNeverRaises notin op.flags:
c.canRaise = true c.canRaise = true
if c.addMemReset: 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): # for every field (dependent on dest.kind):
# `=` dest.field, src.field # `=` dest.field, src.field
# =destroy(blob) # =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 temp.typ = x.typ
incl(temp.flags, sfFromGeneric) incl(temp.flags, sfFromGeneric)
var v = newNodeI(nkVarSection, c.info) 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: if sfNeverRaises notin op.flags:
c.canRaise = true c.canRaise = true
if op.typ.sons[1].kind == tyVar: if op.typ.sons[1].kind == tyVar:
result.add genAddr(c.g, x) result.add genAddr(c, x)
else: else:
result.add x result.add x
if y != nil: if y != nil:
@ -311,7 +313,7 @@ proc considerAsgnOrSink(c: var TLiftCtx; t: PType; body, x, y: PNode;
else: else:
op = field op = field
if op == nil: 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: if sfError in op.flags:
incl c.fn.flags, sfError incl c.fn.flags, sfError
#else: #else:
@ -340,7 +342,7 @@ proc addDestructorCall(c: var TLiftCtx; orig: PType; body, x: PNode) =
t.attachedOps[attachedDestructor] = op t.attachedOps[attachedDestructor] = op
if op == nil and (useNoGc(c, t) or requiresDestructor(c, t)): 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 != nil
doAssert op == t.destructor doAssert op == t.destructor
@ -381,7 +383,7 @@ proc considerUserDefinedOp(c: var TLiftCtx; t: PType; body, x, y: PNode): bool =
result = true result = true
proc declareCounter(c: var TLiftCtx; body: PNode; first: BiggestInt): PNode = 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) temp.typ = getSysType(c.g, body.info, tyInt)
incl(temp.flags, sfFromGeneric) 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) body.add genBuiltin(c.g, mDestroy, "destroy", x)
proc useSeqOrStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) = 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 # recursions are tricky, so we might need to forward the generated
# operation here: # operation here:
var t = t 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) = proc fillStrOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
case c.kind case c.kind
of attachedAsgn, attachedDeepCopy: 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: of attachedSink:
let moveCall = genBuiltin(c.g, mMove, "move", x) let moveCall = genBuiltin(c.g, mMove, "move", x)
moveCall.add y moveCall.add y
@ -509,7 +511,7 @@ proc atomicRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
var actions = newNodeI(nkStmtList, c.info) var actions = newNodeI(nkStmtList, c.info)
let elemType = t.lastSon 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): if isFinal(elemType):
addDestructorCall(c, elemType, actions, genDeref(x, nkDerefExpr)) 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): if isFinal(elemType):
let typInfo = genBuiltin(c.g, mGetTypeInfoV2, "getTypeInfoV2", newNodeIT(nkType, x.info, elemType)) let typInfo = genBuiltin(c.g, mGetTypeInfoV2, "getTypeInfoV2", newNodeIT(nkType, x.info, elemType))
typInfo.typ = getSysType(c.g, c.info, tyPointer) 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: else:
# If the ref is polymorphic we have to account for this # 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: of attachedDispose:
# this is crucial! dispose is like =destroy but we don't follow refs # this is crucial! dispose is like =destroy but we don't follow refs
# as that is dealt within the cycle collector. # 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) body.add genIf(c, cond, actions)
of attachedDeepCopy: assert(false, "cannot happen") of attachedDeepCopy: assert(false, "cannot happen")
of attachedTrace: 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: of attachedDispose:
# this is crucial! dispose is like =destroy but we don't follow refs # this is crucial! dispose is like =destroy but we don't follow refs
# as that is dealt within the cycle collector. # 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 of tyOptDeprecated: doAssert false
proc produceSymDistinctType(g: ModuleGraph; c: PContext; typ: PType; proc produceSymDistinctType(g: ModuleGraph; c: PContext; typ: PType;
kind: TTypeAttachedOp; info: TLineInfo): PSym = kind: TTypeAttachedOp; info: TLineInfo;
idgen: IdGenerator): PSym =
assert typ.kind == tyDistinct assert typ.kind == tyDistinct
let baseType = typ[0] let baseType = typ[0]
if baseType.attachedOps[kind] == nil: 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] typ.attachedOps[kind] = baseType.attachedOps[kind]
result = typ.attachedOps[kind] result = typ.attachedOps[kind]
proc symPrototype(g: ModuleGraph; typ: PType; owner: PSym; kind: TTypeAttachedOp; 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]) let procname = getIdent(g.cache, AttachedOpToStr[kind])
result = newSym(skProc, procname, owner, info) result = newSym(skProc, procname, nextId(idgen), owner, info)
let dest = newSym(skParam, getIdent(g.cache, "dest"), result, 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"), result, info) let src = newSym(skParam, getIdent(g.cache, if kind == attachedTrace: "env" else: "src"),
dest.typ = makeVarType(typ.owner, typ) nextId(idgen), result, info)
dest.typ = makeVarType(typ.owner, typ, idgen)
if kind == attachedTrace: if kind == attachedTrace:
src.typ = getSysType(g, info, tyPointer) src.typ = getSysType(g, info, tyPointer)
else: else:
src.typ = typ src.typ = typ
result.typ = newProcType(info, owner) result.typ = newProcType(info, nextId(idgen), owner)
result.typ.addParam dest result.typ.addParam dest
if kind notin {attachedDestructor, attachedDispose}: if kind notin {attachedDestructor, attachedDispose}:
result.typ.addParam src 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; proc produceSym(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp;
info: TLineInfo): PSym = info: TLineInfo; idgen: IdGenerator): PSym =
if typ.kind == tyDistinct: if typ.kind == tyDistinct:
return produceSymDistinctType(g, c, typ, kind, info) return produceSymDistinctType(g, c, typ, kind, info, idgen)
result = typ.attachedOps[kind] result = typ.attachedOps[kind]
if result == nil: 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 a.fn = result
let dest = result.typ.n[1].sym 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 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) assert(typ.skipTypes({tyAlias, tyGenericInst}).kind == tyObject)
result = symPrototype(g, field.typ, typ.owner, attachedDestructor, info) result = symPrototype(g, field.typ, typ.owner, attachedDestructor, info, idgen)
var a = TLiftCtx(info: info, g: g, kind: attachedDestructor, asgnForType: typ) var a = TLiftCtx(info: info, g: g, kind: attachedDestructor, asgnForType: typ, idgen: idgen)
a.fn = result a.fn = result
a.asgnForType = typ a.asgnForType = typ
a.filterDiscriminator = field a.filterDiscriminator = field
a.addMemReset = true a.addMemReset = true
let discrimantDest = result.typ.n[1].sym let discrimantDest = result.typ.n[1].sym
let dst = newSym(skVar, getIdent(g.cache, "dest"), result, info) let dst = newSym(skVar, getIdent(g.cache, "dest"), nextId(idgen), result, info)
dst.typ = makePtrType(typ.owner, typ) dst.typ = makePtrType(typ.owner, typ, idgen)
let dstSym = newSymNode(dst) let dstSym = newSymNode(dst)
let d = newDeref(dstSym) let d = newDeref(dstSym)
let v = newNodeI(nkVarSection, info) 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) = template liftTypeBoundOps*(c: PContext; typ: PType; info: TLineInfo) =
discard "now a nop" 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.kind in nkCallKinds:
if n[0].kind == nkSym and n[0].sym.magic == mDestroy: if n[0].kind == nkSym and n[0].sym.magic == mDestroy:
let t = n[1].typ.skipTypes(abstractVar) let t = n[1].typ.skipTypes(abstractVar)
if t.destructor == nil: 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 != nil:
if t.destructor.ast[genericParamsPos].kind != nkEmpty: 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: if t.destructor.magic == mDestroy:
internalError(g.config, info, "patching mDestroy with mDestroy?") internalError(g.config, info, "patching mDestroy with mDestroy?")
n[0] = newSymNode(t.destructor) 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 field.ast != nil and field.ast[genericParamsPos].kind != nkEmpty:
if t.typeInst != nil: if t.typeInst != nil:
var a: TLiftCtx var a: TLiftCtx
@ -914,17 +919,19 @@ template inst(field, t) =
a.g = g a.g = g
a.kind = k a.kind = k
a.c = c a.c = c
a.idgen = idgen
field = instantiateGeneric(a, field, t, t.typeInst) field = instantiateGeneric(a, field, t, t.typeInst)
if field.ast != nil: if field.ast != nil:
patchBody(g, c, field.ast, info) patchBody(g, c, field.ast, info, a.idgen)
else: else:
localError(g.config, info, "unresolved generic parameter") localError(g.config, info, "unresolved generic parameter")
proc isTrival(s: PSym): bool {.inline.} = proc isTrival(s: PSym): bool {.inline.} =
s == nil or (s.ast != nil and s.ast[bodyPos].len == 0) 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 ## In the semantic pass this is called in strategic places
## to ensure we lift assignment, destructors and moves properly. ## to ensure we lift assignment, destructors and moves properly.
## The later 'injectdestructors' pass depends on it. ## 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: for k in attachedDestructor..lastAttached:
generics[k] = canon.attachedOps[k] != nil generics[k] = canon.attachedOps[k] != nil
if not generics[k]: 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: # we generate the destructor first so that other operators can depend on it:
for k in attachedDestructor..lastAttached: for k in attachedDestructor..lastAttached:
if not generics[k]: if not generics[k]:
discard produceSym(g, c, canon, k, info) discard produceSym(g, c, canon, k, info, idgen)
else: else:
inst(canon.attachedOps[k], canon) inst(canon.attachedOps[k], canon, idgen)
if canon != orig: if canon != orig:
orig.attachedOps[k] = canon.attachedOps[k] orig.attachedOps[k] = canon.attachedOps[k]

View file

@ -21,13 +21,14 @@ type
partialParam: PSym partialParam: PSym
objType: PType objType: PType
cache: IdentCache cache: IdentCache
idgen: IdGenerator
proc interestingVar(s: PSym): bool {.inline.} = proc interestingVar(s: PSym): bool {.inline.} =
result = s.kind in {skVar, skLet, skTemp, skForVar, skResult} and result = s.kind in {skVar, skLet, skTemp, skForVar, skResult} and
sfGlobal notin s.flags sfGlobal notin s.flags
proc lookupOrAdd(c: var Ctx; s: PSym; info: TLineInfo): PNode = 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) var deref = newNodeI(nkHiddenDeref, info)
deref.typ = c.objType deref.typ = c.objType
deref.add(newSymNode(c.partialParam, info)) 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: if params[i].kind == nkSym and params[i].sym.name.id == dest.ident.id:
return params[i].sym 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) let liftDest = getPragmaVal(prc.ast, wLiftLocals)
if liftDest == nil: return n if liftDest == nil: return n
let partialParam = lookupParam(prc.typ.n, liftDest) 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: if objType.kind != tyObject or tfPartial notin objType.flags:
localError(conf, liftDest.info, "parameter '$1' is not a pointer to a partial object" % $liftDest) localError(conf, liftDest.info, "parameter '$1' is not a pointer to a partial object" % $liftDest)
return n 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) let w = newTree(nkStmtList, n)
liftLocals(w, 0, c) liftLocals(w, 0, c)
result = w[0] result = w[0]

View file

@ -135,7 +135,7 @@ proc errorSym*(c: PContext, n: PNode): PSym =
considerQuotedIdent(c, m) considerQuotedIdent(c, m)
else: else:
getIdent(c.cache, "err:" & renderTree(m)) 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) result.typ = errorType(c)
incl(result.flags, sfDiscardable) incl(result.flags, sfDiscardable)
# pretend it's imported from some unknown module to prevent cascading errors: # pretend it's imported from some unknown module to prevent cascading errors:

View file

@ -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 newSymNode(getSysMagic(g, ri.info, "move", mMove))
result[1].add ri 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 assert n.kind == nkVarTuple
let value = n.lastSon let value = n.lastSon
result = newNodeI(nkStmtList, n.info) 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) temp.typ = skipTypes(value.typ, abstractInst)
incl(temp.flags, sfFromGeneric) 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) if n[i].kind == nkSym: v.addVar(n[i], val)
else: result.add newAsgnStmt(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 ## 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 ## 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'! ## handy to have in macros.nim. The value that can be reused is 'result.lastSon'!
result = newNodeIT(nkStmtListExpr, value.info, value.typ) 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) temp.typ = skipTypes(value.typ, abstractInst)
incl(temp.flags, sfFromGeneric) incl(temp.flags, sfFromGeneric)
@ -111,11 +113,11 @@ proc newTupleAccessRaw*(tup: PNode, i: int): PNode =
proc newTryFinally*(body, final: PNode): PNode = proc newTryFinally*(body, final: PNode): PNode =
result = newTree(nkHiddenTryStmt, body, newTree(nkFinally, final)) 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 let value = n.lastSon
result = newNodeI(nkStmtList, n.info) 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) var v = newNodeI(nkLetSection, value.info)
let tempAsNode = newSymNode(temp) #newIdentNode(getIdent(genPrefix & $temp.id), 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: for i in 0..<lhs.len:
result.add newAsgnStmt(lhs[i], newTupleAccessRaw(tempAsNode, i)) 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) result = newNodeI(nkStmtList, n.info)
# note: cannot use 'skTemp' here cause we really need the copy for the VM :-( # 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 temp.typ = n[1].typ
incl(temp.flags, sfFromGeneric) 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[1], n[2])
result.add newFastAsgnStmt(n[2], tempAsNode) result.add newFastAsgnStmt(n[2], tempAsNode)
proc createObj*(g: ModuleGraph; owner: PSym, info: TLineInfo; final=true): PType = proc createObj*(g: ModuleGraph; idgen: IdGenerator; owner: PSym, info: TLineInfo; final=true): PType =
result = newType(tyObject, owner) result = newType(tyObject, nextId(idgen), owner)
if final: if final:
rawAddSon(result, nil) rawAddSon(result, nil)
incl result.flags, tfFinal 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) rawAddSon(result, getCompilerProc(g, "RootObj").typ)
result.n = newNodeI(nkRecList, info) result.n = newNodeI(nkRecList, info)
let s = newSym(skType, getIdent(g.cache, "Env_" & toFilename(g.config, info) & "_" & $owner.name.s), let s = newSym(skType, getIdent(g.cache, "Env_" & toFilename(g.config, info) & "_" & $owner.name.s),
nextId(idgen),
owner, info, owner.options) owner, info, owner.options)
incl s.flags, sfAnon incl s.flags, sfAnon
s.typ = result s.typ = result
@ -196,7 +199,7 @@ proc rawDirectAccess*(obj, field: PSym): PNode =
result.add newSymNode(field) result.add newSymNode(field)
result.typ = field.typ result.typ = field.typ
proc lookupInRecord(n: PNode, id: int): PSym = proc lookupInRecord(n: PNode, id: ItemId): PSym =
result = nil result = nil
case n.kind case n.kind
of nkRecList: of nkRecList:
@ -214,16 +217,16 @@ proc lookupInRecord(n: PNode, id: int): PSym =
if result != nil: return if result != nil: return
else: discard else: discard
of nkSym: 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 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. # 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. # 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, var field = newSym(skField, getIdent(cache, s.name.s & $obj.n.len),
s.options) nextId(idgen), s.owner, s.info, s.options)
field.id = -s.id field.itemId = ItemId(module: s.itemId.module, item: -s.itemId.item)
let t = skipIntLit(s.typ) let t = skipIntLit(s.typ, idgen)
field.typ = t field.typ = t
assert t.kind != tyTyped assert t.kind != tyTyped
propagateToOwner(obj, t) propagateToOwner(obj, t)
@ -232,13 +235,13 @@ proc addField*(obj: PType; s: PSym; cache: IdentCache) =
obj.n.add newSymNode(field) obj.n.add newSymNode(field)
fieldCheck() fieldCheck()
proc addUniqueField*(obj: PType; s: PSym; cache: IdentCache): PSym {.discardable.} = proc addUniqueField*(obj: PType; s: PSym; cache: IdentCache; idgen: IdGenerator): PSym {.discardable.} =
result = lookupInRecord(obj.n, s.id) result = lookupInRecord(obj.n, s.itemId)
if result == nil: if result == nil:
var field = newSym(skField, getIdent(cache, s.name.s & $obj.n.len), s.owner, s.info, var field = newSym(skField, getIdent(cache, s.name.s & $obj.n.len), nextId(idgen),
s.options) s.owner, s.info, s.options)
field.id = -s.id field.itemId = ItemId(module: s.itemId.module, item: -s.itemId.item)
let t = skipIntLit(s.typ) let t = skipIntLit(s.typ, idgen)
field.typ = t field.typ = t
assert t.kind != tyTyped assert t.kind != tyTyped
propagateToOwner(obj, t) propagateToOwner(obj, t)
@ -248,13 +251,13 @@ proc addUniqueField*(obj: PType; s: PSym; cache: IdentCache): PSym {.discardable
proc newDotExpr*(obj, b: PSym): PNode = proc newDotExpr*(obj, b: PSym): PNode =
result = newNodeI(nkDotExpr, obj.info) 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 assert field != nil, b.name.s
result.add newSymNode(obj) result.add newSymNode(obj)
result.add newSymNode(field) result.add newSymNode(field)
result.typ = field.typ 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 # returns a[].b as a node
var deref = newNodeI(nkHiddenDeref, info) var deref = newNodeI(nkHiddenDeref, info)
deref.typ = a.typ.skipTypes(abstractInst)[0] deref.typ = a.typ.skipTypes(abstractInst)[0]
@ -306,7 +309,7 @@ proc getFieldFromObj*(t: PType; v: PSym): PSym =
var t = t var t = t
while true: while true:
assert t.kind == tyObject assert t.kind == tyObject
result = lookupInRecord(t.n, v.id) result = lookupInRecord(t.n, v.itemId)
if result != nil: break if result != nil: break
t = t[0] t = t[0]
if t == nil: break if t == nil: break
@ -314,15 +317,15 @@ proc getFieldFromObj*(t: PType; v: PSym): PSym =
proc indirectAccess*(a: PNode, b: PSym, info: TLineInfo): PNode = proc indirectAccess*(a: PNode, b: PSym, info: TLineInfo): PNode =
# returns a[].b as a node # 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 = proc indirectAccess*(a, b: PSym, info: TLineInfo): PNode =
result = indirectAccess(newSymNode(a), b, info) 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 = newNodeI(nkAddr, n.info, 1)
result[0] = n result[0] = n
result.typ = newType(typeKind, n.typ.owner) result.typ = newType(typeKind, nextId(idgen), n.typ.owner)
result.typ.rawAddSon(n.typ) result.typ.rawAddSon(n.typ)
proc genDeref*(n: PNode; k = nkHiddenDeref): PNode = proc genDeref*(n: PNode; k = nkHiddenDeref): PNode =

View file

@ -21,7 +21,7 @@ proc registerSysType*(g: ModuleGraph; t: PType) =
if g.sysTypes[t.kind] == nil: g.sysTypes[t.kind] = t if g.sysTypes[t.kind] == nil: g.sysTypes[t.kind] = t
proc newSysType(g: ModuleGraph; kind: TTypeKind, size: int): PType = 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.size = size
result.align = size.int16 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)) result = strTableGet(g.systemModule.tab, getIdent(g.cache, name))
if result == nil: if result == nil:
localError(g.config, info, "system module needs: " & name) localError(g.config, info, "system module needs: " & name)
result = newSym(skError, getIdent(g.cache, name), g.systemModule, g.systemModule.info, {}) result = newSym(skError, getIdent(g.cache, name), nextId(g.idgen), g.systemModule, g.systemModule.info, {})
result.typ = newType(tyError, g.systemModule) result.typ = newType(tyError, nextId(g.idgen), g.systemModule)
if result.kind == skAlias: result = result.owner if result.kind == skAlias: result = result.owner
proc getSysMagic*(g: ModuleGraph; info: TLineInfo; name: string, m: TMagic): PSym = 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) r = nextIdentIter(ti, g.systemModule.tab)
if result != nil: return result if result != nil: return result
localError(g.config, info, "system module needs: " & name) localError(g.config, info, "system module needs: " & name)
result = newSym(skError, id, g.systemModule, g.systemModule.info, {}) result = newSym(skError, id, nextId(g.idgen), g.systemModule, g.systemModule.info, {})
result.typ = newType(tyError, g.systemModule) result.typ = newType(tyError, nextId(g.idgen), g.systemModule)
proc sysTypeFromName*(g: ModuleGraph; info: TLineInfo; name: string): PType = proc sysTypeFromName*(g: ModuleGraph; info: TLineInfo; name: string): PType =
result = getSysSym(g, info, name).typ result = getSysSym(g, info, name).typ
@ -101,12 +101,12 @@ proc getIntLitType*(g: ModuleGraph; literal: PNode): PType =
result = g.intTypeCache[value.int] result = g.intTypeCache[value.int]
if result == nil: if result == nil:
let ti = getSysType(g, literal.info, tyInt) let ti = getSysType(g, literal.info, tyInt)
result = copyType(ti, ti.owner, false) result = copyType(ti, nextId(g.idgen), ti.owner)
result.n = literal result.n = literal
g.intTypeCache[value.int] = result g.intTypeCache[value.int] = result
else: else:
let ti = getSysType(g, literal.info, tyInt) let ti = getSysType(g, literal.info, tyInt)
result = copyType(ti, ti.owner, false) result = copyType(ti, nextId(g.idgen), ti.owner)
result.n = literal result.n = literal
proc getFloatLitType*(g: ModuleGraph; literal: PNode): PType = 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 = newSysType(g, tyFloat, size=8)
result.n = literal 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}: 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 result.n = nil
else: else:
result = t result = t
proc addSonSkipIntLit*(father, son: PType) = proc addSonSkipIntLit*(father, son: PType; id: IdGenerator) =
when not defined(nimNoNilSeqs): when not defined(nimNoNilSeqs):
if isNil(father.sons): father.sons = @[] if isNil(father.sons): father.sons = @[]
let s = son.skipIntLit let s = son.skipIntLit(id)
father.sons.add(s) father.sons.add(s)
propagateToOwner(father, s) propagateToOwner(father, s)
@ -181,13 +181,13 @@ proc resetNimScriptSymbols*(g: ModuleGraph) = initStrTable(g.exposed)
proc getMagicEqSymForType*(g: ModuleGraph; t: PType; info: TLineInfo): PSym = proc getMagicEqSymForType*(g: ModuleGraph; t: PType; info: TLineInfo): PSym =
case t.kind case t.kind
of tyInt, tyInt8, tyInt16, tyInt32, tyInt64, of tyInt, tyInt8, tyInt16, tyInt32, tyInt64,
tyUInt, tyUInt8, tyUInt16, tyUInt32, tyUInt64: tyUInt, tyUInt8, tyUInt16, tyUInt32, tyUInt64:
result = getSysMagic(g, info, "==", mEqI) result = getSysMagic(g, info, "==", mEqI)
of tyEnum: of tyEnum:
result = getSysMagic(g, info, "==", mEqEnum) result = getSysMagic(g, info, "==", mEqEnum)
of tyBool: of tyBool:
result = getSysMagic(g, info, "==", mEqB) result = getSysMagic(g, info, "==", mEqB)
of tyRef, tyPtr, tyPointer: of tyRef, tyPtr, tyPointer:
result = getSysMagic(g, info, "==", mEqRef) result = getSysMagic(g, info, "==", mEqRef)
of tyString: of tyString:
result = getSysMagic(g, info, "==", mEqStr) result = getSysMagic(g, info, "==", mEqStr)

View file

@ -17,7 +17,7 @@ import
condsyms, times, condsyms, times,
sem, idents, passes, extccomp, sem, idents, passes, extccomp,
cgen, json, nversion, cgen, json, nversion,
platform, nimconf, passaux, depends, vm, idgen, platform, nimconf, passaux, depends, vm,
modules, modules,
modulegraphs, tables, rod, lineinfos, pathutils, vmprofiler modulegraphs, tables, rod, lineinfos, pathutils, vmprofiler
@ -137,12 +137,8 @@ proc commandInteractive(graph: ModuleGraph) =
else: else:
var m = graph.makeStdinModule() var m = graph.makeStdinModule()
incl(m.flags, sfMainModule) incl(m.flags, sfMainModule)
processModule(graph, m, llStreamOpenStdIn()) var idgen = IdGenerator(module: m.itemId.module, item: m.itemId.item)
processModule(graph, m, idgen, llStreamOpenStdIn())
const evalPasses = [verbosePass, semPass, evalPass]
proc evalNim(graph: ModuleGraph; nodes: PNode, module: PSym) =
carryPasses(graph, nodes, module, evalPasses)
proc commandScan(cache: IdentCache, config: ConfigRef) = proc commandScan(cache: IdentCache, config: ConfigRef) =
var f = addFileExt(AbsoluteFile mainCommandArg(config), NimExt) var f = addFileExt(AbsoluteFile mainCommandArg(config), NimExt)
@ -173,7 +169,6 @@ proc mainCommand*(graph: ModuleGraph) =
clearPasses(graph) clearPasses(graph)
conf.lastCmdTime = epochTime() conf.lastCmdTime = epochTime()
conf.searchPaths.add(conf.libpath) conf.searchPaths.add(conf.libpath)
setId(100)
proc customizeForBackend(backend: TBackend) = proc customizeForBackend(backend: TBackend) =
## Sets backend specific options but don't compile to backend yet in ## Sets backend specific options but don't compile to backend yet in
@ -219,7 +214,7 @@ proc mainCommand*(graph: ModuleGraph) =
else: else:
wantMainModule(conf) wantMainModule(conf)
conf.cmd = cmdDoc conf.cmd = cmdDoc
loadConfigs(DocConfig, cache, conf) loadConfigs(DocConfig, cache, conf, graph.idgen)
defineSymbol(conf.symbols, "nimdoc") defineSymbol(conf.symbols, "nimdoc")
body body
@ -277,14 +272,14 @@ proc mainCommand*(graph: ModuleGraph) =
quit "compiler wasn't built with documentation generator" quit "compiler wasn't built with documentation generator"
else: else:
conf.cmd = cmdRst2html conf.cmd = cmdRst2html
loadConfigs(DocConfig, cache, conf) loadConfigs(DocConfig, cache, conf, graph.idgen)
commandRst2Html(cache, conf) commandRst2Html(cache, conf)
of "rst2tex": of "rst2tex":
when defined(leanCompiler): when defined(leanCompiler):
quit "compiler wasn't built with documentation generator" quit "compiler wasn't built with documentation generator"
else: else:
conf.cmd = cmdRst2tex conf.cmd = cmdRst2tex
loadConfigs(DocTexConfig, cache, conf) loadConfigs(DocTexConfig, cache, conf, graph.idgen)
commandRst2TeX(cache, conf) commandRst2TeX(cache, conf)
of "jsondoc0": docLikeCmd commandJson(cache, conf) of "jsondoc0": docLikeCmd commandJson(cache, conf)
of "jsondoc2", "jsondoc": docLikeCmd commandDoc2(graph, true) of "jsondoc2", "jsondoc": docLikeCmd commandDoc2(graph, true)

View file

@ -74,11 +74,13 @@ type
globalDestructors*: seq[PNode] globalDestructors*: seq[PNode]
strongSemCheck*: proc (graph: ModuleGraph; owner: PSym; body: PNode) {.nimcall.} strongSemCheck*: proc (graph: ModuleGraph; owner: PSym; body: PNode) {.nimcall.}
compatibleProps*: proc (graph: ModuleGraph; formal, actual: PType): bool {.nimcall.} compatibleProps*: proc (graph: ModuleGraph; formal, actual: PType): bool {.nimcall.}
idgen*: IdGenerator
TPassContext* = object of RootObj # the pass's context TPassContext* = object of RootObj # the pass's context
idgen*: IdGenerator
PPassContext* = ref TPassContext 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.} TPassClose* = proc (graph: ModuleGraph; p: PPassContext, n: PNode): PNode {.nimcall.}
TPassProcess* = proc (p: PPassContext, topLevelStmt: PNode): PNode {.nimcall.} TPassProcess* = proc (p: PPassContext, topLevelStmt: PNode): PNode {.nimcall.}
@ -165,12 +167,13 @@ proc stopCompile*(g: ModuleGraph): bool {.inline.} =
result = g.doStopCompile != nil and g.doStopCompile() result = g.doStopCompile != nil and g.doStopCompile()
proc createMagic*(g: ModuleGraph; name: string, m: TMagic): PSym = 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.magic = m
result.flags = {sfNeverRaises} result.flags = {sfNeverRaises}
proc newModuleGraph*(cache: IdentCache; config: ConfigRef): ModuleGraph = proc newModuleGraph*(cache: IdentCache; config: ConfigRef): ModuleGraph =
result = ModuleGraph() result = ModuleGraph()
result.idgen = IdGenerator(module: -1'i32, item: 0'i32)
initStrTable(result.packageSyms) initStrTable(result.packageSyms)
result.deps = initIntSet() result.deps = initIntSet()
result.importDeps = initTable[FileIndex, seq[FileIndex]]() result.importDeps = initTable[FileIndex, seq[FileIndex]]()

View file

@ -11,7 +11,7 @@
import import
ast, astalgo, magicsys, msgs, options, ast, astalgo, magicsys, msgs, options,
idents, lexer, idgen, passes, syntaxes, llstream, modulegraphs, rod, idents, lexer, passes, syntaxes, llstream, modulegraphs, rod,
lineinfos, pathutils, tables lineinfos, pathutils, tables
proc resetSystemArtifacts*(g: ModuleGraph) = proc resetSystemArtifacts*(g: ModuleGraph) =
@ -20,6 +20,8 @@ proc resetSystemArtifacts*(g: ModuleGraph) =
template getModuleIdent(graph: ModuleGraph, filename: AbsoluteFile): PIdent = template getModuleIdent(graph: ModuleGraph, filename: AbsoluteFile): PIdent =
getIdent(graph.cache, splitFile(filename).name) getIdent(graph.cache, splitFile(filename).name)
template packageId(): untyped {.dirty.} = ItemId(module: PackageModuleId, item: int32(fileIdx))
proc getPackage(graph: ModuleGraph; fileIdx: FileIndex): PSym = proc getPackage(graph: ModuleGraph; fileIdx: FileIndex): PSym =
## returns package symbol (skPackage) for yet to be defined module for fileIdx ## returns package symbol (skPackage) for yet to be defined module for fileIdx
let filename = AbsoluteFile toFullPath(graph.config, fileIdx) let filename = AbsoluteFile toFullPath(graph.config, fileIdx)
@ -31,7 +33,7 @@ proc getPackage(graph: ModuleGraph; fileIdx: FileIndex): PSym =
pack = getIdent(graph.cache, pck2) pack = getIdent(graph.cache, pck2)
var packSym = graph.packageSyms.strTableGet(pack) var packSym = graph.packageSyms.strTableGet(pack)
if packSym == nil: 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) initStrTable(packSym.tab)
graph.packageSyms.strTableAdd(packSym) graph.packageSyms.strTableAdd(packSym)
else: else:
@ -47,7 +49,7 @@ proc getPackage(graph: ModuleGraph; fileIdx: FileIndex): PSym =
# to resolve the conflicts: # to resolve the conflicts:
let pck3 = fakePackageName(graph.config, filename) let pck3 = fakePackageName(graph.config, filename)
# this makes the new `packSym`'s owner be the original `packSym` # 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) initStrTable(packSym.tab)
graph.packageSyms.strTableAdd(packSym) graph.packageSyms.strTableAdd(packSym)
result = packSym result = packSym
@ -69,7 +71,7 @@ proc newModule(graph: ModuleGraph; fileIdx: FileIndex): PSym =
let filename = AbsoluteFile toFullPath(graph.config, fileIdx) let filename = AbsoluteFile toFullPath(graph.config, fileIdx)
# We cannot call ``newSym`` here, because we have to circumvent the ID # 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. # 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), name: getModuleIdent(graph, filename),
info: newLineInfo(fileIdx, 1, 1)) info: newLineInfo(fileIdx, 1, 1))
if not isNimIdentifier(result.name.s): if not isNimIdentifier(result.name.s):
@ -82,25 +84,21 @@ proc compileModule*(graph: ModuleGraph; fileIdx: FileIndex; flags: TSymFlags): P
result = graph.getModule(fileIdx) result = graph.getModule(fileIdx)
if result == nil: if result == nil:
let filename = AbsoluteFile toFullPath(graph.config, fileIdx) let filename = AbsoluteFile toFullPath(graph.config, fileIdx)
let (r, id) = loadModuleSym(graph, fileIdx, filename) result = loadModuleSym(graph, fileIdx, filename)
result = r
if result == nil: if result == nil:
result = newModule(graph, fileIdx) result = newModule(graph, fileIdx)
result.flags.incl flags result.flags.incl flags
result.id = id
registerModule(graph, result) registerModule(graph, result)
else: else:
partialInitModule(result, graph, fileIdx, filename) partialInitModule(result, graph, fileIdx, filename)
result.id = id discard processModule(graph, result, idGeneratorFromModule(result),
assert result.id < 0
discard processModule(graph, result,
if sfMainModule in flags and graph.config.projectIsStdin: stdin.llStreamOpen else: nil) if sfMainModule in flags and graph.config.projectIsStdin: stdin.llStreamOpen else: nil)
elif graph.isDirty(result): elif graph.isDirty(result):
result.flags.excl sfDirty result.flags.excl sfDirty
# reset module fields: # reset module fields:
initStrTable(result.tab) initStrTable(result.tab)
result.ast = nil 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) if sfMainModule in flags and graph.config.projectIsStdin: stdin.llStreamOpen else: nil)
graph.markClientsDirty(fileIdx) graph.markClientsDirty(fileIdx)
@ -161,7 +159,6 @@ proc compileProject*(graph: ModuleGraph; projectFileIdx = InvalidFileIdx) =
proc makeModule*(graph: ModuleGraph; filename: AbsoluteFile): PSym = proc makeModule*(graph: ModuleGraph; filename: AbsoluteFile): PSym =
result = graph.newModule(fileInfoIdx(graph.config, filename)) result = graph.newModule(fileInfoIdx(graph.config, filename))
result.id = getID()
registerModule(graph, result) registerModule(graph, result)
proc makeModule*(graph: ModuleGraph; filename: string): PSym = proc makeModule*(graph: ModuleGraph; filename: string): PSym =

View file

@ -10,7 +10,7 @@
# This module handles the reading of the config file. # This module handles the reading of the config file.
import import
llstream, commands, os, strutils, msgs, lexer, llstream, commands, os, strutils, msgs, lexer, ast,
options, idents, wordrecg, strtabs, lineinfos, pathutils, scriptconfig options, idents, wordrecg, strtabs, lineinfos, pathutils, scriptconfig
# ---------------- configuration file parser ----------------------------- # ---------------- 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 = p / RelativeDir"etc/nim" / filename
if not fileExists(result): result = AbsoluteDir"/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) setDefaultLibpath(conf)
var configFiles = newSeq[AbsoluteFile]() var configFiles = newSeq[AbsoluteFile]()
@ -252,7 +252,7 @@ proc loadConfigs*(cfg: RelativeFile; cache: IdentCache; conf: ConfigRef) =
let p = path # eval once let p = path # eval once
if fileExists(p): if fileExists(p):
configFiles.add(p) configFiles.add(p)
runNimScript(cache, p, freshDefines = false, conf) runNimScript(cache, p, idgen, freshDefines = false, conf)
if optSkipSystemConfigFile notin conf.globalOptions: if optSkipSystemConfigFile notin conf.globalOptions:
readConfigFile(getSystemConfigPath(conf, cfg)) readConfigFile(getSystemConfigPath(conf, cfg))
@ -291,13 +291,12 @@ proc loadConfigs*(cfg: RelativeFile; cache: IdentCache; conf: ConfigRef) =
# delayed to here so that `hintConf` is honored # delayed to here so that `hintConf` is honored
rawMessage(conf, hintConf, filename.string) rawMessage(conf, hintConf, filename.string)
block: let scriptFile = conf.projectFull.changeFileExt("nims")
let scriptFile = conf.projectFull.changeFileExt("nims") if conf.command != "nimsuggest":
if conf.command != "nimsuggest": runNimScriptIfExists(scriptFile)
else:
if scriptFile != conf.projectFull:
runNimScriptIfExists(scriptFile) runNimScriptIfExists(scriptFile)
else: else:
if scriptFile != conf.projectFull: # 'nimsuggest foo.nims' means to just auto-complete the NimScript file
runNimScriptIfExists(scriptFile) discard
else:
# 'nimsuggest foo.nims' means to just auto-complete the NimScript file
discard

View file

@ -19,6 +19,7 @@ type
mainModule: PSym mainModule: PSym
graph: ModuleGraph graph: ModuleGraph
scriptName: string scriptName: string
idgen: IdGenerator
iterator exportedSymbols*(i: Interpreter): PSym = iterator exportedSymbols*(i: Interpreter): PSym =
assert i != nil assert i != nil
@ -74,7 +75,7 @@ proc evalScript*(i: Interpreter; scriptStream: PLLStream = nil) =
let s = if scriptStream != nil: scriptStream let s = if scriptStream != nil: scriptStream
else: llStreamOpen(findFile(i.graph.config, i.scriptName), fmRead) 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 = proc findNimStdLib*(): string =
## Tries to find a path to a valid "system.nim" file. ## Tries to find a path to a valid "system.nim" file.
@ -121,14 +122,15 @@ proc createInterpreter*(scriptName: string;
var m = graph.makeModule(scriptName) var m = graph.makeModule(scriptName)
incl(m.flags, sfMainModule) 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.mode = emRepl
vm.features = flags vm.features = flags
if registerOps: if registerOps:
vm.registerAdditionalOps() # Required to register parts of stdlib modules vm.registerAdditionalOps() # Required to register parts of stdlib modules
graph.vm = vm graph.vm = vm
graph.compileSystemModule() graph.compileSystemModule()
result = Interpreter(mainModule: m, graph: graph, scriptName: scriptName) result = Interpreter(mainModule: m, graph: graph, scriptName: scriptName, idgen: idgen)
proc destroyInterpreter*(i: Interpreter) = proc destroyInterpreter*(i: Interpreter) =
## destructor. ## destructor.
@ -162,6 +164,8 @@ proc runRepl*(r: TLLRepl;
registerPass(graph, evalPass) registerPass(graph, evalPass)
var m = graph.makeStdinModule() var m = graph.makeStdinModule()
incl(m.flags, sfMainModule) 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() graph.compileSystemModule()
processModule(graph, m, llStreamOpenStdIn(r)) processModule(graph, m, idgen, llStreamOpenStdIn(r))

View file

@ -10,7 +10,7 @@
## implements some little helper passes ## implements some little helper passes
import import
ast, passes, idents, msgs, options, idgen, lineinfos ast, passes, idents, msgs, options, lineinfos
from modulegraphs import ModuleGraph, PPassContext from modulegraphs import ModuleGraph, PPassContext
@ -18,9 +18,9 @@ type
VerboseRef = ref object of PPassContext VerboseRef = ref object of PPassContext
config: ConfigRef config: ConfigRef
proc verboseOpen(graph: ModuleGraph; s: PSym): PPassContext = proc verboseOpen(graph: ModuleGraph; s: PSym; idgen: IdGenerator): PPassContext =
#MessageOut('compiling ' + s.name.s); #MessageOut('compiling ' + s.name.s);
result = VerboseRef(config: graph.config) result = VerboseRef(config: graph.config, idgen: idgen)
rawMessage(graph.config, hintProcessing, s.name.s) rawMessage(graph.config, hintProcessing, s.name.s)
proc verboseProcess(context: PPassContext, n: PNode): PNode = 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 # system.nim deactivates all hints, for verbosity:3 we want the processing
# messages nonetheless, so we activate them again (but honor cmdlineNotes) # messages nonetheless, so we activate them again (but honor cmdlineNotes)
v.config.setNote(hintProcessing) 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) const verbosePass* = makePass(open = verboseOpen, process = verboseProcess)

View file

@ -13,7 +13,7 @@
import import
options, ast, llstream, msgs, options, ast, llstream, msgs,
idents, idents,
syntaxes, idgen, modulegraphs, reorder, rod, syntaxes, modulegraphs, reorder, rod,
lineinfos, pathutils lineinfos, pathutils
type type
@ -51,31 +51,18 @@ proc registerPass*(g: ModuleGraph; p: TPass) =
internalAssert g.config, g.passes.len < maxPasses internalAssert g.config, g.passes.len < maxPasses
g.passes.add(p) 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; proc openPasses(g: ModuleGraph; a: var TPassContextArray;
module: PSym) = module: PSym; idgen: IdGenerator) =
for i in 0..<g.passes.len: for i in 0..<g.passes.len:
if not isNil(g.passes[i].open): 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 else: a[i] = nil
proc closePasses(graph: ModuleGraph; a: var TPassContextArray) = proc closePasses(graph: ModuleGraph; a: var TPassContextArray) =
var m: PNode = nil var m: PNode = nil
for i in 0..<graph.passes.len: 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 a[i] = nil # free the memory here
proc processTopLevelStmt(graph: ModuleGraph, n: PNode, a: var TPassContextArray): bool = 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.} = proc moduleHasChanged*(graph: ModuleGraph; module: PSym): bool {.inline.} =
result = module.id >= 0 or isDefined(graph.config, "nimBackendAssumesChange") 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 if graph.stopCompile(): return true
var var
p: Parser p: Parser
@ -135,7 +123,7 @@ proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream): bool {
# new module caching mechanism: # new module caching mechanism:
for i in 0..<graph.passes.len: for i in 0..<graph.passes.len:
if not isNil(graph.passes[i].open) and not graph.passes[i].isFrontend: 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: else:
a[i] = nil 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) m = graph.passes[i].close(graph, a[i], m)
a[i] = nil a[i] = nil
else: else:
openPasses(graph, a, module) openPasses(graph, a, module, idgen)
if stream == nil: if stream == nil:
let filename = toFullPathConsiderDirty(graph.config, fileIdx) let filename = toFullPathConsiderDirty(graph.config, fileIdx)
s = llStreamOpen(filename, fmRead) s = llStreamOpen(filename, fmRead)
@ -215,6 +203,4 @@ proc processModule*(graph: ModuleGraph; module: PSym, stream: PLLStream): bool {
closeParser(p) closeParser(p)
if s.kind != llsStdIn: break if s.kind != llsStdIn: break
closePasses(graph, a) closePasses(graph, a)
# id synchronization point for more consistent code generation:
idSynchronizationPoint(1000)
result = true result = true

View file

@ -29,10 +29,10 @@ proc iterToProcImpl*(c: PContext, n: PNode): PNode =
localError(c.config, n[2].info, localError(c.config, n[2].info,
"type must be a non-generic ref|ptr to object with state field") "type must be a non-generic ref|ptr to object with state field")
return 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) let prc = newSym(skProc, n[3].ident, nextId c.idgen, iter.sym.owner, iter.sym.info)
prc.typ = copyType(iter.sym.typ, prc, false) prc.typ = copyType(iter.sym.typ, nextId c.idgen, prc)
excl prc.typ.flags, tfCapturesEnv excl prc.typ.flags, tfCapturesEnv
prc.typ.n.add newSymNode(getEnvParam(iter.sym)) prc.typ.n.add newSymNode(getEnvParam(iter.sym))
prc.typ.rawAddSon t prc.typ.rawAddSon t

View file

@ -27,13 +27,13 @@ proc semLocals*(c: PContext, n: PNode): PNode =
{tyVarargs, tyOpenArray, tyTypeDesc, tyStatic, tyUntyped, tyTyped, tyEmpty}: {tyVarargs, tyOpenArray, tyTypeDesc, tyStatic, tyUntyped, tyTyped, tyEmpty}:
if it.owner == owner: 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.typ = it.typ.skipTypes({tyVar})
field.position = counter field.position = counter
inc(counter) inc(counter)
tupleType.n.add newSymNode(field) tupleType.n.add newSymNode(field)
addSonSkipIntLit(tupleType, field.typ) addSonSkipIntLit(tupleType, field.typ, c.idgen)
var a = newSymNode(it, result.info) var a = newSymNode(it, result.info)
if it.typ.skipTypes({tyGenericInst}).kind == tyVar: a = newDeref(a) if it.typ.skipTypes({tyGenericInst}).kind == tyVar: a = newDeref(a)

View file

@ -121,7 +121,7 @@ proc pragmaEnsures(c: PContext, n: PNode) =
openScope(c) openScope(c)
let o = getCurrOwner(c) let o = getCurrOwner(c)
if o.kind in routineKinds and o.typ != nil and o.typ.sons[0] != nil: 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] s.typ = o.typ.sons[0]
incl(s.flags, sfUsed) incl(s.flags, sfUsed)
addDecl(c, s) 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: elif it.safeLen != 2 or it[0].kind != nkIdent or it[1].kind != nkIdent:
invalidPragma(c, n) 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]) userPragma.ast = newTreeI(nkPragma, n.info, n.sons[i+1..^1])
strTableAdd(c.userPragmas, userPragma) strTableAdd(c.userPragmas, userPragma)
@ -717,7 +717,7 @@ proc deprecatedStmt(c: PContext; outerPragma: PNode) =
if dest == nil or dest.kind in routineKinds: if dest == nil or dest.kind in routineKinds:
localError(c.config, n.info, warnUser, "the .deprecated pragma is unreliable for routines") localError(c.config, n.info, warnUser, "the .deprecated pragma is unreliable for routines")
let src = considerQuotedIdent(c, n[0]) 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) incl(alias.flags, sfExported)
if sfCompilerProc in dest.flags: markCompilerProc(c, alias) if sfCompilerProc in dest.flags: markCompilerProc(c, alias)
addInterfaceDecl(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. # 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 # Generic instantiation needs to know about this too. But we're lazy
# and perform the lookup on demand instead. # 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) c.config.options)
else: else:
result = qualifiedLookUp(c, n, {checkUndeclared}) result = qualifiedLookUp(c, n, {checkUndeclared})

View file

@ -9,14 +9,14 @@
## This module implements the canonalization for the various caching mechanisms. ## 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: when not nimIncremental:
template setupModuleCache*(g: ModuleGraph) = discard template setupModuleCache*(g: ModuleGraph) = discard
template storeNode*(g: ModuleGraph; module: PSym; n: PNode) = discard template storeNode*(g: ModuleGraph; module: PSym; n: PNode) = discard
template loadNode*(g: ModuleGraph; module: PSym): PNode = newNode(nkStmtList) 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 template addModuleDep*(g: ModuleGraph; module, fileIdx: FileIndex; isIncludeFile: bool) = discard

View file

@ -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 toplevelstmts where module = ?", module[0])
db.exec(sql"delete from statics 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) 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) = proc pushType(w: var Writer, t: PType) =
if not containsOrIncl(w.tmarks, t.uniqueId): if not containsOrIncl(w.tmarks, t.uniqueId):

View file

@ -27,9 +27,9 @@ proc listDirs(a: VmArgs, filter: set[PathComponent]) =
setResult(a, result) setResult(a, result)
proc setupVM*(module: PSym; cache: IdentCache; scriptName: string; proc setupVM*(module: PSym; cache: IdentCache; scriptName: string;
graph: ModuleGraph): PEvalContext = graph: ModuleGraph; idgen: IdGenerator): PEvalContext =
# For Nimble we need to export 'setupVM'. # For Nimble we need to export 'setupVM'.
result = newCtx(module, cache, graph) result = newCtx(module, cache, graph, idgen)
result.mode = emRepl result.mode = emRepl
registerAdditionalOps(result) registerAdditionalOps(result)
let conf = graph.config let conf = graph.config
@ -198,6 +198,7 @@ proc setupVM*(module: PSym; cache: IdentCache; scriptName: string;
setResult(a, stdin.readAll()) setResult(a, stdin.readAll())
proc runNimScript*(cache: IdentCache; scriptName: AbsoluteFile; proc runNimScript*(cache: IdentCache; scriptName: AbsoluteFile;
idgen: IdGenerator;
freshDefines=true; conf: ConfigRef) = freshDefines=true; conf: ConfigRef) =
let oldSymbolFiles = conf.symbolFiles let oldSymbolFiles = conf.symbolFiles
conf.symbolFiles = disabledSf conf.symbolFiles = disabledSf
@ -221,10 +222,11 @@ proc runNimScript*(cache: IdentCache; scriptName: AbsoluteFile;
var m = graph.makeModule(scriptName) var m = graph.makeModule(scriptName)
incl(m.flags, sfMainModule) 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() 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 # watch out, "newruntime" can be set within NimScript itself and then we need
# to remember this: # to remember this:

View file

@ -14,7 +14,7 @@ import
wordrecg, ropes, msgs, idents, renderer, types, platform, math, wordrecg, ropes, msgs, idents, renderer, types, platform, math,
magicsys, nversion, nimsets, semfold, modulepaths, importer, magicsys, nversion, nimsets, semfold, modulepaths, importer,
procfind, lookups, pragmas, passes, semdata, semtypinst, sigmatch, 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, evaltempl, patterns, parampatterns, sempass2, linter, semmacrosanity,
lowerings, plugins/active, rod, lineinfos, strtabs, int128, lowerings, plugins/active, rod, lineinfos, strtabs, int128,
isolation_check, typeallowed 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: if x.kind in {nkPar, nkTupleConstr, nkCurly} and formal.kind != tyUntyped:
changeType(c, x, formal, check=true) changeType(c, x, formal, check=true)
result = arg result = arg
result = skipHiddenSubConv(result) result = skipHiddenSubConv(result, c.idgen)
proc fitNode(c: PContext, formal: PType, arg: PNode; info: TLineInfo): PNode = 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) 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, # new type relation that is used for array constructors,
# if expressions, etc.: # if expressions, etc.:
if x == nil: return x if x == nil: return x
@ -124,8 +124,8 @@ proc commonType*(x, y: PType): PType =
# turn any concrete typedesc into the abstract typedesc type # turn any concrete typedesc into the abstract typedesc type
if a.len == 0: result = a if a.len == 0: result = a
else: else:
result = newType(tyTypeDesc, a.owner) result = newType(tyTypeDesc, nextId(c.idgen), a.owner)
rawAddSon(result, newType(tyNone, a.owner)) rawAddSon(result, newType(tyNone, nextId(c.idgen), a.owner))
elif b.kind in {tyArray, tySet, tySequence} and elif b.kind in {tyArray, tySet, tySequence} and
a.kind == b.kind: a.kind == b.kind:
# check for seq[empty] vs. seq[int] # check for seq[empty] vs. seq[int]
@ -137,7 +137,7 @@ proc commonType*(x, y: PType): PType =
let aEmpty = isEmptyContainer(a[i]) let aEmpty = isEmptyContainer(a[i])
let bEmpty = isEmptyContainer(b[i]) let bEmpty = isEmptyContainer(b[i])
if aEmpty != bEmpty: 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] nt[i] = if aEmpty: b[i] else: a[i]
if not nt.isNil: result = nt if not nt.isNil: result = nt
#elif b[idx].kind == tyEmpty: return x #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 # 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. # run people expect ranges to work properly within a tuple.
if not sameType(a, b): if not sameType(a, b):
result = skipTypes(a, {tyRange}).skipIntLit result = skipTypes(a, {tyRange}).skipIntLit(c.idgen)
when false: when false:
if a.kind != tyRange and b.kind == tyRange: if a.kind != tyRange and b.kind == tyRange:
# XXX This really needs a better solution, but a proper fix now breaks # 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 # ill-formed AST, no need for additional tyRef/tyPtr
if k != tyNone and x.kind != tyGenericInst: if k != tyNone and x.kind != tyGenericInst:
let r = result let r = result
result = newType(k, r.owner) result = newType(k, nextId(c.idgen), r.owner)
result.addSonSkipIntLit(r) result.addSonSkipIntLit(r, c.idgen)
proc endsInNoReturn(n: PNode): bool = proc endsInNoReturn(n: PNode): bool =
# check if expr ends in raise exception or call of noreturn proc # 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 result = it.kind in nkLastBlockStmts or
it.kind in nkCallKinds and it[0].kind == nkSym and sfNoReturn in it[0].sym.flags 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 # ignore exception raising branches in case/if expressions
if endsInNoReturn(y): return x if endsInNoReturn(y): return x
commonType(x, y.typ) commonType(c, x, y.typ)
proc newSymS(kind: TSymKind, n: PNode, c: PContext): PSym = 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): when defined(nimsuggest):
suggestDecl(c, n, result) 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 # template; we must fix it here: see #909
result.owner = getCurrOwner(c) result.owner = getCurrOwner(c)
else: 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: #if kind in {skForVar, skLet, skVar} and result.owner.kind == skModule:
# incl(result.flags, sfGlobal) # incl(result.flags, sfGlobal)
when defined(nimsuggest): 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 = proc symFromType(c: PContext; t: PType, info: TLineInfo): PSym =
if t.sym != nil: return t.sym 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.flags.incl sfAnon
result.typ = t result.typ = t
@ -316,7 +316,7 @@ proc tryConstExpr(c: PContext, n: PNode): PNode =
var e = semExprWithType(c, n) var e = semExprWithType(c, n)
if e == nil: return if e == nil: return
result = getConstExpr(c.module, e, c.graph) result = getConstExpr(c.module, e, c.idgen, c.graph)
if result != nil: return if result != nil: return
let oldErrorCount = c.config.errorCounter 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 c.config.errorMax = high(int) # `setErrorMaxHighMaybe` not appropriate here
try: try:
result = evalConstExpr(c.module, c.graph, e) result = evalConstExpr(c.module, c.idgen, c.graph, e)
if result == nil or result.kind == nkEmpty: if result == nil or result.kind == nkEmpty:
result = nil result = nil
else: else:
@ -348,10 +348,10 @@ proc semConstExpr(c: PContext, n: PNode): PNode =
if e == nil: if e == nil:
localError(c.config, n.info, errConstExprExpected) localError(c.config, n.info, errConstExprExpected)
return n return n
result = getConstExpr(c.module, e, c.graph) result = getConstExpr(c.module, e, c.idgen, c.graph)
if result == nil: if result == nil:
#if e.kind == nkEmpty: globalError(n.info, errConstExprExpected) #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 result == nil or result.kind == nkEmpty:
if e.info != n.info: if e.info != n.info:
pushInfoContext(c.config, n.info) pushInfoContext(c.config, n.info)
@ -373,7 +373,7 @@ proc semExprFlagDispatched(c: PContext, n: PNode, flags: TExprFlags): PNode =
else: else:
result = semExprWithType(c, n, flags) result = semExprWithType(c, n, flags)
if efPreferStatic in 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 if evaluated != nil: return evaluated
evaluated = evalAtCompileTime(c, result) evaluated = evalAtCompileTime(c, result)
if evaluated != nil: return evaluated if evaluated != nil: return evaluated
@ -399,7 +399,6 @@ proc semAfterMacroCall(c: PContext, call, macroResult: PNode,
if c.config.evalTemplateCounter > evalTemplateLimit: if c.config.evalTemplateCounter > evalTemplateLimit:
globalError(c.config, s.info, "template instantiation too nested") globalError(c.config, s.info, "template instantiation too nested")
c.friendModules.add(s.owner.getModule) c.friendModules.add(s.owner.getModule)
idSynchronizationPoint(5000)
result = macroResult result = macroResult
resetSemFlag result resetSemFlag result
if s.typ[0] == nil: if s.typ[0] == nil:
@ -469,7 +468,7 @@ proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
#if c.evalContext == nil: #if c.evalContext == nil:
# c.evalContext = c.createEvalContext(emStatic) # 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: if efNoSemCheck notin flags:
result = semAfterMacroCall(c, n, result, sym, flags) result = semAfterMacroCall(c, n, result, sym, flags)
if c.config.macrosToExpand.hasKey(sym.name.s): if c.config.macrosToExpand.hasKey(sym.name.s):
@ -502,8 +501,9 @@ proc addCodeForGenerics(c: PContext, n: PNode) =
n.add prc.ast n.add prc.ast
c.lastGenericIdx = c.generics.len 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) var c = newContext(graph, module)
c.idgen = idgen
if c.p != nil: internalError(graph.config, module.info, "sem.myOpen") if c.p != nil: internalError(graph.config, module.info, "sem.myOpen")
c.semConstExpr = semConstExpr c.semConstExpr = semConstExpr
c.semExpr = semExpr c.semExpr = semExpr

View file

@ -688,9 +688,9 @@ proc searchForBorrowProc(c: PContext, startScope: PScope, fn: PSym): PSym =
var x: PType var x: PType
if param.typ.kind == tyVar: if param.typ.kind == tyVar:
x = newTypeS(param.typ.kind, c) x = newTypeS(param.typ.kind, c)
x.addSonSkipIntLit t.baseOfDistinct x.addSonSkipIntLit(t.baseOfDistinct(c.idgen), c.idgen)
else: else:
x = t.baseOfDistinct x = t.baseOfDistinct(c.idgen)
call.add(newNodeIT(nkEmpty, fn.info, x)) call.add(newNodeIT(nkEmpty, fn.info, x))
if hasDistinct: if hasDistinct:
let filter = if fn.kind in {skProc, skFunc}: {skProc, skFunc} else: {fn.kind} let filter = if fn.kind in {skProc, skFunc}: {skProc, skFunc} else: {fn.kind}

View file

@ -277,14 +277,14 @@ proc addToLib*(lib: PLib, sym: PSym) =
sym.annex = lib sym.annex = lib
proc newTypeS*(kind: TTypeKind, c: PContext): PType = proc newTypeS*(kind: TTypeKind, c: PContext): PType =
result = newType(kind, getCurrOwner(c)) result = newType(kind, nextId(c.idgen), getCurrOwner(c))
proc makePtrType*(owner: PSym, baseType: PType): PType = proc makePtrType*(owner: PSym, baseType: PType; idgen: IdGenerator): PType =
result = newType(tyPtr, owner) result = newType(tyPtr, nextId(idgen), owner)
addSonSkipIntLit(result, baseType) addSonSkipIntLit(result, baseType, idgen)
proc makePtrType*(c: PContext, baseType: PType): PType = proc makePtrType*(c: PContext, baseType: PType): PType =
makePtrType(getCurrOwner(c), baseType) makePtrType(getCurrOwner(c), baseType, c.idgen)
proc makeTypeWithModifier*(c: PContext, proc makeTypeWithModifier*(c: PContext,
modifier: TTypeKind, modifier: TTypeKind,
@ -295,21 +295,21 @@ proc makeTypeWithModifier*(c: PContext,
result = baseType result = baseType
else: else:
result = newTypeS(modifier, c) result = newTypeS(modifier, c)
addSonSkipIntLit(result, baseType) addSonSkipIntLit(result, baseType, c.idgen)
proc makeVarType*(c: PContext, baseType: PType; kind = tyVar): PType = proc makeVarType*(c: PContext, baseType: PType; kind = tyVar): PType =
if baseType.kind == kind: if baseType.kind == kind:
result = baseType result = baseType
else: else:
result = newTypeS(kind, c) 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: if baseType.kind == kind:
result = baseType result = baseType
else: else:
result = newType(kind, owner) result = newType(kind, nextId(idgen), owner)
addSonSkipIntLit(result, baseType) addSonSkipIntLit(result, baseType, idgen)
proc makeTypeDesc*(c: PContext, typ: PType): PType = proc makeTypeDesc*(c: PContext, typ: PType): PType =
if typ.kind == tyTypeDesc: if typ.kind == tyTypeDesc:
@ -317,14 +317,14 @@ proc makeTypeDesc*(c: PContext, typ: PType): PType =
else: else:
result = newTypeS(tyTypeDesc, c) result = newTypeS(tyTypeDesc, c)
incl result.flags, tfCheckedForDestructor incl result.flags, tfCheckedForDestructor
result.addSonSkipIntLit(typ) result.addSonSkipIntLit(typ, c.idgen)
proc makeTypeSymNode*(c: PContext, typ: PType, info: TLineInfo): PNode = proc makeTypeSymNode*(c: PContext, typ: PType, info: TLineInfo): PNode =
let typedesc = newTypeS(tyTypeDesc, c) let typedesc = newTypeS(tyTypeDesc, c)
incl typedesc.flags, tfCheckedForDestructor incl typedesc.flags, tfCheckedForDestructor
internalAssert(c.config, typ != nil) internalAssert(c.config, typ != nil)
typedesc.addSonSkipIntLit(typ) typedesc.addSonSkipIntLit(typ, c.idgen)
let sym = newSym(skType, c.cache.idAnon, getCurrOwner(c), info, let sym = newSym(skType, c.cache.idAnon, nextId(c.idgen), getCurrOwner(c), info,
c.config.options).linkTo(typedesc) c.config.options).linkTo(typedesc)
return newSymNode(sym, info) return newSymNode(sym, info)
@ -333,13 +333,14 @@ proc makeTypeFromExpr*(c: PContext, n: PNode): PType =
assert n != nil assert n != nil
result.n = n result.n = n
proc newTypeWithSons*(owner: PSym, kind: TTypeKind, sons: seq[PType]): PType = proc newTypeWithSons*(owner: PSym, kind: TTypeKind, sons: seq[PType];
result = newType(kind, owner) idgen: IdGenerator): PType =
result = newType(kind, nextId(idgen), owner)
result.sons = sons result.sons = sons
proc newTypeWithSons*(c: PContext, kind: TTypeKind, proc newTypeWithSons*(c: PContext, kind: TTypeKind,
sons: seq[PType]): PType = sons: seq[PType]): PType =
result = newType(kind, getCurrOwner(c)) result = newType(kind, nextId(c.idgen), getCurrOwner(c))
result.sons = sons result.sons = sons
proc makeStaticExpr*(c: PContext, n: PNode): PNode = proc makeStaticExpr*(c: PContext, n: PNode): PNode =
@ -418,7 +419,7 @@ proc makeRangeType*(c: PContext; first, last: BiggestInt;
n.add newIntTypeNode(last, intType) n.add newIntTypeNode(last, intType)
result = newTypeS(tyRange, c) result = newTypeS(tyRange, c)
result.n = n result.n = n
addSonSkipIntLit(result, intType) # basetype of range addSonSkipIntLit(result, intType, c.idgen) # basetype of range
proc markIndirect*(c: PContext, s: PSym) {.inline.} = proc markIndirect*(c: PContext, s: PSym) {.inline.} =
if s.kind in {skProc, skFunc, skConverter, skMethod, skIterator}: if s.kind in {skProc, skFunc, skConverter, skMethod, skIterator}:

View file

@ -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 # Note: This is n.info on purpose. It prevents template from creating an info
# context when called from an another template # context when called from an another template
pushInfoContext(c.config, n.info, s.detailedInfo) 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) if efNoSemCheck notin flags: result = semAfterMacroCall(c, n, result, s, flags)
popInfoContext(c.config) popInfoContext(c.config)
@ -384,7 +385,7 @@ proc fixupStaticType(c: PContext, n: PNode) =
# apply this measure only in code that is enlightened to work # apply this measure only in code that is enlightened to work
# with static types. # with static types.
if n.typ.kind != tyStatic: 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. n.typ.n = n # XXX: cycles like the one here look dangerous.
# Consider using `n.copyTree` # Consider using `n.copyTree`
@ -555,7 +556,7 @@ proc arrayConstrType(c: PContext, n: PNode): PType =
rawAddSon(typ, newTypeS(tyEmpty, c)) # needs an empty basetype! rawAddSon(typ, newTypeS(tyEmpty, c)) # needs an empty basetype!
else: else:
var t = skipTypes(n[0].typ, {tyGenericInst, tyVar, tyLent, tyOrdinal, tyAlias, tySink}) 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) typ[0] = makeRangeType(c, 0, n.len - 1, n.info)
result = typ result = typ
@ -605,11 +606,11 @@ proc semArrayConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
let xx = semExprWithType(c, x, flags*{efAllowDestructor}) let xx = semExprWithType(c, x, flags*{efAllowDestructor})
result.add xx result.add xx
typ = commonType(typ, xx.typ) typ = commonType(c, typ, xx.typ)
#n[i] = semExprWithType(c, x, flags*{efAllowDestructor}) #n[i] = semExprWithType(c, x, flags*{efAllowDestructor})
#result.add fitNode(c, typ, n[i]) #result.add fitNode(c, typ, n[i])
inc(lastIndex) inc(lastIndex)
addSonSkipIntLit(result.typ, typ) addSonSkipIntLit(result.typ, typ, c.idgen)
for i in 0..<result.len: for i in 0..<result.len:
result[i] = fitNode(c, typ, result[i], result[i].info) result[i] = fitNode(c, typ, result[i], result[i].info)
result.typ[0] = makeRangeType(c, toInt64(firstIndex), toInt64(lastIndex), n.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]) call.add(n[0])
var allConst = true var allConst = true
for i in 1..<n.len: 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: if a == nil:
allConst = false allConst = false
a = n[i] a = n[i]
if a.kind == nkHiddenStdConv: a = a[1] if a.kind == nkHiddenStdConv: a = a[1]
call.add(a) call.add(a)
if allConst: 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 if result.isNil: result = n
else: return result else: return result
@ -800,19 +801,19 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode =
var call = newNodeIT(nkCall, n.info, n.typ) var call = newNodeIT(nkCall, n.info, n.typ)
call.add(n[0]) call.add(n[0])
for i in 1..<n.len: 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 if a == nil: return n
call.add(a) call.add(a)
#echo "NOW evaluating at compile time: ", call.renderTree #echo "NOW evaluating at compile time: ", call.renderTree
if c.inStaticContext == 0 or sfNoSideEffect in callee.flags: if c.inStaticContext == 0 or sfNoSideEffect in callee.flags:
if sfCompileTime 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: if result.isNil:
localError(c.config, n.info, errCannotInterpretNodeX % renderTree(call)) localError(c.config, n.info, errCannotInterpretNodeX % renderTree(call))
else: result = fixupTypeAfterEval(c, result, n) else: result = fixupTypeAfterEval(c, result, n)
else: else:
result = evalConstExpr(c.module, c.graph, call) result = evalConstExpr(c.module, c.idgen, c.graph, call)
if result.isNil: result = n if result.isNil: result = n
else: result = fixupTypeAfterEval(c, result, n) else: result = fixupTypeAfterEval(c, result, n)
else: else:
@ -827,7 +828,7 @@ proc semStaticExpr(c: PContext, n: PNode): PNode =
closeScope(c) closeScope(c)
dec c.inStaticContext dec c.inStaticContext
if a.findUnresolvedStatic != nil: return a 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: if result.isNil:
localError(c.config, n.info, errCannotInterpretNodeX % renderTree(n)) localError(c.config, n.info, errCannotInterpretNodeX % renderTree(n))
result = c.graph.emptyNode result = c.graph.emptyNode
@ -1115,7 +1116,7 @@ proc readTypeParameter(c: PContext, typ: PType,
# This seems semantically correct and then we'll be able # This seems semantically correct and then we'll be able
# to return the section symbol directly here # to return the section symbol directly here
let foundType = makeTypeDesc(c, def[2].typ) 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: of nkConstSection:
for def in statement: for def in statement:
@ -1140,7 +1141,7 @@ proc readTypeParameter(c: PContext, typ: PType,
return c.graph.emptyNode return c.graph.emptyNode
else: else:
let foundTyp = makeTypeDesc(c, rawTyp) 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 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 # unfortunately we need to rewrite ``(x, y) = foo()`` already here so
# that overloading of the assignment operator still works. Usually we # that overloading of the assignment operator still works. Usually we
# prefer to do these rewritings in transf.nim: # 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: else:
a = semExprWithType(c, a, {efLValue}) a = semExprWithType(c, a, {efLValue})
else: else:
@ -1930,7 +1931,7 @@ proc expectString(c: PContext, n: PNode): string =
localError(c.config, n.info, errStringLiteralExpected) localError(c.config, n.info, errStringLiteralExpected)
proc newAnonSym(c: PContext; kind: TSymKind, info: TLineInfo): PSym = 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 = proc semExpandToAst(c: PContext, n: PNode): PNode =
let macroCall = n[1] let macroCall = n[1]
@ -2145,9 +2146,9 @@ proc semShallowCopy(c: PContext, n: PNode, flags: TExprFlags): PNode =
result = semDirectOp(c, n, flags) result = semDirectOp(c, n, flags)
proc createFlowVar(c: PContext; t: PType; info: TLineInfo): PType = proc createFlowVar(c: PContext; t: PType; info: TLineInfo): PType =
result = newType(tyGenericInvocation, c.module) result = newType(tyGenericInvocation, nextId c.idgen, c.module)
addSonSkipIntLit(result, magicsys.getCompilerProc(c.graph, "FlowVar").typ) addSonSkipIntLit(result, magicsys.getCompilerProc(c.graph, "FlowVar").typ, c.idgen)
addSonSkipIntLit(result, t) addSonSkipIntLit(result, t, c.idgen)
result = instGenericContainer(c, info, result, allowMetaTypes = false) result = instGenericContainer(c, info, result, allowMetaTypes = false)
proc instantiateCreateFlowVarCall(c: PContext; t: PType; proc instantiateCreateFlowVarCall(c: PContext; t: PType;
@ -2328,7 +2329,7 @@ proc semWhen(c: PContext, n: PNode, semCheck = true): PNode =
if whenNimvm: if whenNimvm:
if semCheck: if semCheck:
it[1] = semExpr(c, it[1]) 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 result = n # when nimvm is not elimited until codegen
else: else:
let e = forceBool(c, semConstExpr(c, it[0])) 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 result == nil or whenNimvm:
if semCheck: if semCheck:
it[0] = semExpr(c, it[0]) it[0] = semExpr(c, it[0])
typ = commonType(typ, it[0].typ) typ = commonType(c, typ, it[0].typ)
if result == nil: if result == nil:
result = it[0] result = it[0]
else: illFormedAst(n, c.config) else: illFormedAst(n, c.config)
if result == nil: if result == nil:
result = newNodeI(nkEmpty, n.info) result = newNodeI(nkEmpty, n.info)
if whenNimvm: result.typ = typ 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 = proc semSetConstr(c: PContext, n: PNode): PNode =
result = newNodeI(nkCurly, n.info) result = newNodeI(nkCurly, n.info)
@ -2386,7 +2383,7 @@ proc semSetConstr(c: PContext, n: PNode): PNode =
typ = makeRangeType(c, 0, MaxSetElements-1, n.info) typ = makeRangeType(c, 0, MaxSetElements-1, n.info)
elif lengthOrd(c.config, typ) > MaxSetElements: elif lengthOrd(c.config, typ) > MaxSetElements:
typ = makeRangeType(c, 0, MaxSetElements-1, n.info) typ = makeRangeType(c, 0, MaxSetElements-1, n.info)
addSonSkipIntLit(result.typ, typ) addSonSkipIntLit(result.typ, typ, c.idgen)
for i in 0..<n.len: for i in 0..<n.len:
var m: PNode var m: PNode
let info = n[i].info let info = n[i].info
@ -2467,7 +2464,7 @@ proc semTupleFieldsConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
n[i][1].typ = errorType(c) n[i][1].typ = errorType(c)
var f = newSymS(skField, n[i][0], 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 f.position = i
rawAddSon(typ, f.typ) rawAddSon(typ, f.typ)
typ.n.add newSymNode(f) 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! var typ = newTypeS(tyTuple, c) # leave typ.n nil!
for i in 0..<n.len: for i in 0..<n.len:
n[i] = semExprWithType(c, n[i], flags*{efAllowDestructor}) n[i] = semExprWithType(c, n[i], flags*{efAllowDestructor})
addSonSkipIntLit(typ, n[i].typ) addSonSkipIntLit(typ, n[i].typ, c.idgen)
result.typ = typ result.typ = typ
include semobjconstr include semobjconstr
@ -2608,7 +2605,8 @@ proc hoistParamsUsedInDefault(c: PContext, call, letSection, defExpr: var PNode)
let paramPos = defExpr.sym.position + 1 let paramPos = defExpr.sym.position + 1
if call[paramPos].kind != nkSym: 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 hoistedVarSym.typ = call[paramPos].typ
letSection.add newTreeI(nkIdentDefs, letSection.info, letSection.add newTreeI(nkIdentDefs, letSection.info,

View file

@ -109,7 +109,7 @@ proc semForFields(c: PContext, n: PNode, m: TMagic): PNode =
var trueSymbol = strTableGet(c.graph.systemModule.tab, getIdent(c.cache, "true")) var trueSymbol = strTableGet(c.graph.systemModule.tab, getIdent(c.cache, "true"))
if trueSymbol == nil: if trueSymbol == nil:
localError(c.config, n.info, "system needs: 'true'") 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) trueSymbol.typ = getSysType(c.graph, n.info, tyBool)
result[0] = newSymNode(trueSymbol, n.info) result[0] = newSymNode(trueSymbol, n.info)

View file

@ -17,7 +17,7 @@ import
proc errorType*(g: ModuleGraph): PType = proc errorType*(g: ModuleGraph): PType =
## creates a type representing an error state ## 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 result.flags.incl tfCheckedForDestructor
proc newIntNodeT*(intVal: Int128, n: PNode; g: ModuleGraph): PNode = 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.typ = n.typ
result.info = n.info 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 # evaluates the constant expression or returns nil if it is no constant
# expression # expression
proc evalOp*(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode 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 = proc isIntRangeOrLit(t: PType): bool =
result = isIntRange(t) or isIntLit(t) 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 = proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode =
# b and c may be nil # b and c may be nil
result = 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) exprStructuralEquivalent(a, b, strictSymEquality=true))), n, g)
else: discard else: discard
proc getConstIfExpr(c: PSym, n: PNode; g: ModuleGraph): PNode = proc getConstIfExpr(c: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode =
result = nil result = nil
for i in 0..<n.len: for i in 0..<n.len:
var it = n[i] var it = n[i]
if it.len == 2: 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 e == nil: return nil
if getOrdValue(e) != 0: if getOrdValue(e) != 0:
if result == nil: if result == nil:
result = getConstExpr(c, it[1], g) result = getConstExpr(c, it[1], idgen, g)
if result == nil: return if result == nil: return
elif it.len == 1: 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()") else: internalError(g.config, it.info, "getConstIfExpr()")
proc leValueConv*(a, b: PNode): bool = 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")
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 if n.len <= 1: return
var s = n[0].sym var s = n[0].sym
var a = getConstExpr(m, n[1], g) var a = getConstExpr(m, n[1], idgen, g)
var b, c: PNode var b, c: PNode
if a == nil: return if a == nil: return
if n.len > 2: if n.len > 2:
b = getConstExpr(m, n[2], g) b = getConstExpr(m, n[2], idgen, g)
if b == nil: return if b == nil: return
if n.len > 3: if n.len > 3:
c = getConstExpr(m, n[3], g) c = getConstExpr(m, n[3], idgen, g)
if c == nil: return if c == nil: return
result = evalOp(s.magic, n, a, b, c, g) 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 = a
result.typ = n.typ 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: if n.kind == nkBracket:
result = n result = n
else: else:
result = getConstExpr(m, n, g) result = getConstExpr(m, n, idgen, g)
if result == nil: result = n if result == nil: result = n
proc foldArrayAccess(m: PSym, n: PNode; g: ModuleGraph): PNode = proc foldArrayAccess(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode =
var x = getConstExpr(m, n[0], g) var x = getConstExpr(m, n[0], idgen, g)
if x == nil or x.typ.skipTypes({tyGenericInst, tyAlias, tySink}).kind == tyTypeDesc: if x == nil or x.typ.skipTypes({tyGenericInst, tyAlias, tySink}).kind == tyTypeDesc:
return return
var y = getConstExpr(m, n[1], g) var y = getConstExpr(m, n[1], idgen, g)
if y == nil: return if y == nil: return
var idx = toInt64(getOrdValue(y)) 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) localError(g.config, n.info, formatErrorIndexBound(idx, x.strVal.len-1) & $n)
else: discard 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 # 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 if x == nil or x.kind notin {nkObjConstr, nkPar, nkTupleConstr}: return
var field = n[1].sym var field = n[1].sym
@ -504,23 +465,23 @@ proc foldFieldAccess(m: PSym, n: PNode; g: ModuleGraph): PNode =
return return
localError(g.config, n.info, "field not found: " & field.name.s) 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 = newNodeIT(nkStrLit, n.info, n.typ)
result.strVal = "" result.strVal = ""
for i in 1..<n.len: 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 if a == nil: return nil
result.strVal.add(getStrOrChar(a)) 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) result = newSymNode(s, info)
if s.typ.kind != tyTypeDesc: if s.typ.kind != tyTypeDesc:
result.typ = newType(tyTypeDesc, s.owner) result.typ = newType(tyTypeDesc, idgen.nextId, s.owner)
result.typ.addSonSkipIntLit(s.typ) result.typ.addSonSkipIntLit(s.typ, idgen)
else: else:
result.typ = s.typ 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 result = nil
case n.kind case n.kind
of nkSym: of nkSym:
@ -570,12 +531,12 @@ proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode =
result = n result = n
of skParam: of skParam:
if s.typ != nil and s.typ.kind == tyTypeDesc: if s.typ != nil and s.typ.kind == tyTypeDesc:
result = newSymNodeTypeDesc(s, n.info) result = newSymNodeTypeDesc(s, idgen, n.info)
of skType: of skType:
# XXX gensym'ed symbols can come here and cannot be resolved. This is # XXX gensym'ed symbols can come here and cannot be resolved. This is
# dirty, but correct. # dirty, but correct.
if s.typ != nil: if s.typ != nil:
result = newSymNodeTypeDesc(s, n.info) result = newSymNodeTypeDesc(s, idgen, n.info)
of skGenericParam: of skGenericParam:
if s.typ.kind == tyStatic: if s.typ.kind == tyStatic:
if s.typ.n != nil and tfUnresolved notin s.typ.flags: 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: elif s.typ.isIntLit:
result = s.typ.n result = s.typ.n
else: else:
result = newSymNodeTypeDesc(s, n.info) result = newSymNodeTypeDesc(s, idgen, n.info)
else: discard else: discard
of nkCharLit..nkNilLit: of nkCharLit..nkNilLit:
result = copyNode(n) result = copyNode(n)
of nkIfExpr: of nkIfExpr:
result = getConstIfExpr(m, n, g) result = getConstIfExpr(m, n, idgen, g)
of nkCallKinds: of nkCallKinds:
if n[0].kind != nkSym: return if n[0].kind != nkSym: return
var s = n[0].sym var s = n[0].sym
@ -612,17 +573,17 @@ proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode =
else: else:
result = newIntNodeT(lastOrd(g.config, skipTypes(n[1].typ, abstractVar)), n, g) result = newIntNodeT(lastOrd(g.config, skipTypes(n[1].typ, abstractVar)), n, g)
else: else:
var a = getArrayConstr(m, n[1], g) var a = getArrayConstr(m, n[1], idgen, g)
if a.kind == nkBracket: if a.kind == nkBracket:
# we can optimize it away: # we can optimize it away:
result = newIntNodeT(toInt128(a.len-1), n, g) result = newIntNodeT(toInt128(a.len-1), n, g)
of mLengthOpenArray: of mLengthOpenArray:
var a = getArrayConstr(m, n[1], g) var a = getArrayConstr(m, n[1], idgen, g)
if a.kind == nkBracket: if a.kind == nkBracket:
# we can optimize it away! This fixes the bug ``len(134)``. # we can optimize it away! This fixes the bug ``len(134)``.
result = newIntNodeT(toInt128(a.len), n, g) result = newIntNodeT(toInt128(a.len), n, g)
else: else:
result = magicCall(m, n, g) result = magicCall(m, n, idgen, g)
of mLengthArray: of mLengthArray:
# It doesn't matter if the argument is const or not for mLengthArray. # It doesn't matter if the argument is const or not for mLengthArray.
# This fixes bug #544. # This fixes bug #544.
@ -636,33 +597,33 @@ proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode =
of mAstToStr: of mAstToStr:
result = newStrNodeT(renderTree(n[1], {renderNoComments}), n, g) result = newStrNodeT(renderTree(n[1], {renderNoComments}), n, g)
of mConStrStr: of mConStrStr:
result = foldConStrStr(m, n, g) result = foldConStrStr(m, n, idgen, g)
of mIs: of mIs:
# The only kind of mIs node that comes here is one depending on some # The only kind of mIs node that comes here is one depending on some
# generic parameter and that's (hopefully) handled at instantiation time # generic parameter and that's (hopefully) handled at instantiation time
discard discard
else: else:
result = magicCall(m, n, g) result = magicCall(m, n, idgen, g)
except OverflowDefect: except OverflowDefect:
localError(g.config, n.info, "over- or underflow") localError(g.config, n.info, "over- or underflow")
except DivByZeroDefect: except DivByZeroDefect:
localError(g.config, n.info, "division by zero") localError(g.config, n.info, "division by zero")
of nkAddr: of nkAddr:
var a = getConstExpr(m, n[0], g) var a = getConstExpr(m, n[0], idgen, g)
if a != nil: if a != nil:
result = n result = n
n[0] = a n[0] = a
of nkBracket, nkCurly: of nkBracket, nkCurly:
result = copyNode(n) result = copyNode(n)
for i, son in n.pairs: for i, son in n.pairs:
var a = getConstExpr(m, son, g) var a = getConstExpr(m, son, idgen, g)
if a == nil: return nil if a == nil: return nil
result.add a result.add a
incl(result.flags, nfAllConst) incl(result.flags, nfAllConst)
of nkRange: of nkRange:
var a = getConstExpr(m, n[0], g) var a = getConstExpr(m, n[0], idgen, g)
if a == nil: return if a == nil: return
var b = getConstExpr(m, n[1], g) var b = getConstExpr(m, n[1], idgen, g)
if b == nil: return if b == nil: return
result = copyNode(n) result = copyNode(n)
result.add a result.add a
@ -681,18 +642,18 @@ proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode =
for i, expr in n.pairs: for i, expr in n.pairs:
let exprNew = copyNode(expr) # nkExprColonExpr let exprNew = copyNode(expr) # nkExprColonExpr
exprNew.add expr[0] exprNew.add expr[0]
let a = getConstExpr(m, expr[1], g) let a = getConstExpr(m, expr[1], idgen, g)
if a == nil: return nil if a == nil: return nil
exprNew.add a exprNew.add a
result.add exprNew result.add exprNew
else: else:
for i, expr in n.pairs: for i, expr in n.pairs:
let a = getConstExpr(m, expr, g) let a = getConstExpr(m, expr, idgen, g)
if a == nil: return nil if a == nil: return nil
result.add a result.add a
incl(result.flags, nfAllConst) incl(result.flags, nfAllConst)
of nkChckRangeF, nkChckRange64, nkChckRange: of nkChckRangeF, nkChckRange64, nkChckRange:
var a = getConstExpr(m, n[0], g) var a = getConstExpr(m, n[0], idgen, g)
if a == nil: return if a == nil: return
if leValueConv(n[1], a) and leValueConv(a, n[2]): if leValueConv(n[1], a) and leValueConv(a, n[2]):
result = a # a <= x and x <= b 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" % "conversion from $1 to $2 is invalid" %
[typeToString(n[0].typ), typeToString(n.typ)]) [typeToString(n[0].typ), typeToString(n.typ)])
of nkStringToCString, nkCStringToString: of nkStringToCString, nkCStringToString:
var a = getConstExpr(m, n[0], g) var a = getConstExpr(m, n[0], idgen, g)
if a == nil: return if a == nil: return
result = a result = a
result.typ = n.typ result.typ = n.typ
of nkHiddenStdConv, nkHiddenSubConv, nkConv: of nkHiddenStdConv, nkHiddenSubConv, nkConv:
var a = getConstExpr(m, n[1], g) var a = getConstExpr(m, n[1], idgen, g)
if a == nil: return if a == nil: return
result = foldConv(n, a, g, check=true) result = foldConv(n, a, g, check=true)
of nkCast: of nkCast:
var a = getConstExpr(m, n[1], g) var a = getConstExpr(m, n[1], idgen, g)
if a == nil: return if a == nil: return
if n.typ != nil and n.typ.kind in NilableTypes: if n.typ != nil and n.typ.kind in NilableTypes:
# we allow compile-time 'cast' for pointer types: # we allow compile-time 'cast' for pointer types:
result = a result = a
result.typ = n.typ result.typ = n.typ
of nkBracketExpr: result = foldArrayAccess(m, n, g) of nkBracketExpr: result = foldArrayAccess(m, n, idgen, g)
of nkDotExpr: result = foldFieldAccess(m, n, g) of nkDotExpr: result = foldFieldAccess(m, n, idgen, g)
of nkCheckedFieldExpr: of nkCheckedFieldExpr:
result = foldFieldAccess(m, n[0], g) result = foldFieldAccess(m, n[0], idgen, g)
of nkStmtListExpr: of nkStmtListExpr:
var i = 0 var i = 0
while i <= n.len - 2: while i <= n.len - 2:
if n[i].kind in {nkComesFrom, nkCommentStmt, nkEmpty}: i.inc if n[i].kind in {nkComesFrom, nkCommentStmt, nkEmpty}: i.inc
else: break else: break
if i == n.len - 1: if i == n.len - 1:
result = getConstExpr(m, n[i], g) result = getConstExpr(m, n[i], idgen, g)
else: else:
discard discard

View file

@ -95,7 +95,7 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym,
else: else:
result = n result = n
else: else:
result = newSymNodeTypeDesc(s, n.info) result = newSymNodeTypeDesc(s, c.idgen, n.info)
onUse(n.info, s) onUse(n.info, s)
of skParam: of skParam:
result = n result = n
@ -103,7 +103,7 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym,
of skType: of skType:
if (s.typ != nil) and if (s.typ != nil) and
(s.typ.flags * {tfGenericTypeParam, tfImplicitTypeParam} == {}): (s.typ.flags * {tfGenericTypeParam, tfImplicitTypeParam} == {}):
result = newSymNodeTypeDesc(s, n.info) result = newSymNodeTypeDesc(s, c.idgen, n.info)
else: else:
result = n result = n
onUse(n.info, s) onUse(n.info, s)
@ -267,13 +267,13 @@ proc semGenericStmt(c: PContext, n: PNode,
if s.magic == mRunnableExamples: if s.magic == mRunnableExamples:
first = result.safeLen # see trunnableexamples.fun3 first = result.safeLen # see trunnableexamples.fun3
of skGenericParam: of skGenericParam:
result[0] = newSymNodeTypeDesc(s, fn.info) result[0] = newSymNodeTypeDesc(s, c.idgen, fn.info)
onUse(fn.info, s) onUse(fn.info, s)
first = 1 first = 1
of skType: of skType:
# bad hack for generics: # bad hack for generics:
if (s.typ != nil) and (s.typ.kind != tyGenericParam): 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) onUse(fn.info, s)
first = 1 first = 1
else: else:
@ -470,7 +470,7 @@ proc semGenericStmt(c: PContext, n: PNode,
flags, ctx) flags, ctx)
if n[paramsPos].kind != nkEmpty: if n[paramsPos].kind != nkEmpty:
if n[paramsPos][0].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[paramsPos] = semGenericStmt(c, n[paramsPos], flags, ctx)
n[pragmasPos] = semGenericStmt(c, n[pragmasPos], flags, ctx) n[pragmasPos] = semGenericStmt(c, n[pragmasPos], flags, ctx)
var body: PNode var body: PNode

View file

@ -65,7 +65,7 @@ iterator instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable): PSym
if q.typ.kind notin {tyTypeDesc, tyGenericParam, tyStatic}+tyTypeClasses: if q.typ.kind notin {tyTypeDesc, tyGenericParam, tyStatic}+tyTypeClasses:
continue continue
let symKind = if q.typ.kind == tyStatic: skConst else: skType let symKind = if q.typ.kind == tyStatic: skConst else: skType
var s = newSym(symKind, q.name, getCurrOwner(c), q.info) var s = newSym(symKind, q.name, nextId c.idgen, getCurrOwner(c), q.info)
s.flags.incl {sfUsed, sfFromGeneric} s.flags.incl {sfUsed, sfFromGeneric}
var t = PType(idTableGet(pt, q.typ)) var t = PType(idTableGet(pt, q.typ))
if t == nil: if t == nil:
@ -105,7 +105,7 @@ when false:
proc `$`(x: PSym): string = proc `$`(x: PSym): string =
result = x.name.s & " " & " id " & $x.id 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: # we need to create a fresh set of gensym'ed symbols:
#if n.kind == nkSym and sfGenSym in n.sym.flags: #if n.kind == nkSym and sfGenSym in n.sym.flags:
# if n.sym.owner != orig: # if n.sym.owner != orig:
@ -118,12 +118,12 @@ proc freshGenSyms(n: PNode, owner, orig: PSym, symMap: var TIdTable) =
n.sym = x n.sym = x
elif s.owner == nil or s.owner.kind == skPackage: elif s.owner == nil or s.owner.kind == skPackage:
#echo "copied this ", s.name.s #echo "copied this ", s.name.s
x = copySym(s) x = copySym(s, nextId c.idgen)
x.owner = owner x.owner = owner
idTablePut(symMap, s, x) idTablePut(symMap, s, x)
n.sym = x n.sym = x
else: 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) 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 let param = params[i].sym
if sfGenSym in param.flags: if sfGenSym in param.flags:
idTablePut(symMap, params[i].sym, result.typ.n[param.position+1].sym) 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) b = semProcBody(c, b)
result.ast[bodyPos] = hloBody(c, b) result.ast[bodyPos] = hloBody(c, b)
trackProc(c, result, result.ast[bodyPos]) trackProc(c, result, result.ast[bodyPos])
@ -200,7 +200,7 @@ proc instGenericContainer(c: PContext, info: TLineInfo, header: PType,
var param: PSym var param: PSym
template paramSym(kind): untyped = 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: if genParam.kind == tyStatic:
param = paramSym skConst param = paramSym skConst
@ -270,7 +270,7 @@ proc instantiateProcType(c: PContext, pt: TIdTable,
internalAssert c.config, originalParams[i].kind == nkSym internalAssert c.config, originalParams[i].kind == nkSym
let oldParam = originalParams[i].sym let oldParam = originalParams[i].sym
let param = copySym(oldParam) let param = copySym(oldParam, nextId c.idgen)
param.owner = prc param.owner = prc
param.typ = result[i] param.typ = result[i]
@ -314,7 +314,7 @@ proc instantiateProcType(c: PContext, pt: TIdTable,
propagateToOwner(result, result[0]) propagateToOwner(result, result[0])
eraseVoidParams(result) eraseVoidParams(result)
skipIntLiteralParams(result) skipIntLiteralParams(result, c.idgen)
prc.typ = result prc.typ = result
popInfoContext(c.config) popInfoContext(c.config)
@ -339,7 +339,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
c.matchedConcept = nil c.matchedConcept = nil
let oldScope = c.currentScope let oldScope = c.currentScope
while not isTopLevel(c): c.currentScope = c.currentScope.parent while not isTopLevel(c): c.currentScope = c.currentScope.parent
result = copySym(fn) result = copySym(fn, nextId c.idgen)
incl(result.flags, sfFromGeneric) incl(result.flags, sfFromGeneric)
result.owner = fn result.owner = fn
result.ast = n result.ast = n

View file

@ -118,8 +118,8 @@ proc uninstantiate(t: PType): PType =
of tyCompositeTypeClass: uninstantiate t[1] of tyCompositeTypeClass: uninstantiate t[1]
else: t else: t
proc getTypeDescNode(typ: PType, sym: PSym, info: TLineInfo): PNode = proc getTypeDescNode(c: PContext; typ: PType, sym: PSym, info: TLineInfo): PNode =
var resType = newType(tyTypeDesc, sym) var resType = newType(tyTypeDesc, nextId c.idgen, sym)
rawAddSon(resType, typ) rawAddSon(resType, typ)
result = toNode(resType, info) result = toNode(resType, info)
@ -133,7 +133,7 @@ proc evalTypeTrait(c: PContext; traitCall: PNode, operand: PType, context: PSym)
traitCall[2].typ.skipTypes({tyTypeDesc}) traitCall[2].typ.skipTypes({tyTypeDesc})
template typeWithSonsResult(kind, sons): PNode = 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): if operand.kind == tyGenericParam or (traitCall.len > 2 and operand2.kind == tyGenericParam):
return traitCall ## too early to evaluate return traitCall ## too early to evaluate
@ -160,19 +160,19 @@ proc evalTypeTrait(c: PContext; traitCall: PNode, operand: PType, context: PSym)
result.info = traitCall.info result.info = traitCall.info
of "arity": of "arity":
result = newIntNode(nkIntLit, operand.len - ord(operand.kind==tyProc)) 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 result.info = traitCall.info
of "genericHead": of "genericHead":
var arg = operand var arg = operand
case arg.kind case arg.kind
of tyGenericInst: 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 # of tySequence: # this doesn't work
# var resType = newType(tySequence, operand.owner) # var resType = newType(tySequence, operand.owner)
# result = toNode(resType, traitCall.info) # doesn't work yet # result = toNode(resType, traitCall.info) # doesn't work yet
else: else:
localError(c.config, traitCall.info, "expected generic type, got: type $2 of kind $1" % [arg.kind.toHumanStr, typeToString(operand)]) 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": of "stripGenericParams":
result = uninstantiate(operand).toNode(traitCall.info) result = uninstantiate(operand).toNode(traitCall.info)
of "supportsCopyMem": of "supportsCopyMem":
@ -194,11 +194,11 @@ proc evalTypeTrait(c: PContext; traitCall: PNode, operand: PType, context: PSym)
while arg.kind == tyDistinct: while arg.kind == tyDistinct:
arg = arg.base arg = arg.base
arg = arg.skipTypes(skippedTypes + {tyGenericInst}) arg = arg.skipTypes(skippedTypes + {tyGenericInst})
result = getTypeDescNode(arg, operand.owner, traitCall.info) result = getTypeDescNode(c, arg, operand.owner, traitCall.info)
else: else:
localError(c.config, traitCall.info, localError(c.config, traitCall.info,
"distinctBase expects a distinct type as argument. The given type was " & typeToString(operand)) "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: else:
localError(c.config, traitCall.info, "unknown trait: " & s) localError(c.config, traitCall.info, "unknown trait: " & s)
result = newNodeI(nkEmpty, traitCall.info) result = newNodeI(nkEmpty, traitCall.info)
@ -286,7 +286,7 @@ proc semDynamicBindSym(c: PContext, n: PNode): PNode =
return semBindSym(c, n) return semBindSym(c, n)
if c.graph.vm.isNil: if c.graph.vm.isNil:
setupGlobalCtx(c.module, c.graph) setupGlobalCtx(c.module, c.graph, c.idgen)
let let
vm = PCtx c.graph.vm vm = PCtx c.graph.vm
@ -370,7 +370,7 @@ proc semUnown(c: PContext; n: PNode): PNode =
elems[i] = unownedType(c, t[i]) elems[i] = unownedType(c, t[i])
if elems[i] != t[i]: someChange = true if elems[i] != t[i]: someChange = true
if someChange: 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 # we have to use 'rawAddSon' here so that type flags are
# properly computed: # properly computed:
for e in elems: result.rawAddSon(e) for e in elems: result.rawAddSon(e)
@ -381,7 +381,7 @@ proc semUnown(c: PContext; n: PNode): PNode =
tyGenericInst, tyAlias: tyGenericInst, tyAlias:
let b = unownedType(c, t[^1]) let b = unownedType(c, t[^1])
if b != 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[^1] = b
result.flags.excl tfHasOwned result.flags.excl tfHasOwned
else: else:
@ -399,7 +399,7 @@ proc turnFinalizerIntoDestructor(c: PContext; orig: PSym; info: TLineInfo): PSym
# Replace nkDerefExpr by nkHiddenDeref # Replace nkDerefExpr by nkHiddenDeref
# nkDeref is for 'ref T': x[].field # nkDeref is for 'ref T': x[].field
# nkHiddenDeref is for 'var T': x<hidden deref [] here>.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) result = shallowCopy(n)
if sameTypeOrNil(n.typ, old): if sameTypeOrNil(n.typ, old):
result.typ = fresh result.typ = fresh
@ -407,26 +407,26 @@ proc turnFinalizerIntoDestructor(c: PContext; orig: PSym; info: TLineInfo): PSym
if n.sym == oldParam: if n.sym == oldParam:
result.sym = newParam result.sym = newParam
elif n.sym.owner == orig: elif n.sym.owner == orig:
result.sym = copySym(n.sym) result.sym = copySym(n.sym, nextId c.idgen)
result.sym.owner = procSym result.sym.owner = procSym
for i in 0 ..< safeLen(n): 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): #if n.kind == nkDerefExpr and sameType(n[0].typ, old):
# result = # result =
result = copySym(orig) result = copySym(orig, nextId c.idgen)
result.info = info result.info = info
result.flags.incl sfFromGeneric result.flags.incl sfFromGeneric
result.owner = orig result.owner = orig
let origParamType = orig.typ[1] 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 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 newParam.typ = newParamType
# proc body: # 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: # proc signature:
result.typ = newProcType(result.info, result) result.typ = newProcType(result.info, nextId c.idgen, result)
result.typ.addParam newParam result.typ.addParam newParam
proc semQuantifier(c: PContext; n: PNode): PNode = proc semQuantifier(c: PContext; n: PNode): PNode =

View file

@ -416,13 +416,13 @@ proc transformSlices(g: ModuleGraph; n: PNode): PNode =
else: else:
result = n result = n
proc transformSpawn(g: ModuleGraph; owner: PSym; n, barrier: PNode): PNode proc transformSpawn(g: ModuleGraph; idgen: IdGenerator;owner: PSym; n, barrier: PNode): PNode
proc transformSpawnSons(g: ModuleGraph; owner: PSym; n, barrier: PNode): PNode = proc transformSpawnSons(g: ModuleGraph; idgen: IdGenerator; owner: PSym; n, barrier: PNode): PNode =
result = shallowCopy(n) result = shallowCopy(n)
for i in 0..<n.len: 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 case n.kind
of nkVarSection, nkLetSection: of nkVarSection, nkLetSection:
result = nil result = nil
@ -436,25 +436,25 @@ proc transformSpawn(g: ModuleGraph; owner: PSym; n, barrier: PNode): PNode =
result.add n result.add n
let t = b[1][0].typ[0] let t = b[1][0].typ[0]
if spawnResult(t, true) == srByVar: 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) it[^1] = newNodeI(nkEmpty, it.info)
else: 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 if result.isNil: result = n
of nkAsgn, nkFastAsgn: of nkAsgn, nkFastAsgn:
let b = n[1] let b = n[1]
if getMagic(b) == mSpawn and (let t = b[1][0].typ[0]; if getMagic(b) == mSpawn and (let t = b[1][0].typ[0];
spawnResult(t, true) == srByVar): spawnResult(t, true) == srByVar):
let m = transformSlices(g, b) let m = transformSlices(g, b)
return wrapProcForSpawn(g, owner, m, b.typ, barrier, n[0]) return wrapProcForSpawn(g, idgen, owner, m, b.typ, barrier, n[0])
result = transformSpawnSons(g, owner, n, barrier) result = transformSpawnSons(g, idgen, owner, n, barrier)
of nkCallKinds: of nkCallKinds:
if getMagic(n) == mSpawn: if getMagic(n) == mSpawn:
result = transformSlices(g, n) result = transformSlices(g, n)
return wrapProcForSpawn(g, owner, result, n.typ, barrier, nil) return wrapProcForSpawn(g, idgen, owner, result, n.typ, barrier, nil)
result = transformSpawnSons(g, owner, n, barrier) result = transformSpawnSons(g, idgen, owner, n, barrier)
elif n.safeLen > 0: elif n.safeLen > 0:
result = transformSpawnSons(g, owner, n, barrier) result = transformSpawnSons(g, idgen, owner, n, barrier)
else: else:
result = n result = n
@ -464,7 +464,7 @@ proc checkArgs(a: var AnalysisCtx; n: PNode) =
proc generateAliasChecks(a: AnalysisCtx; result: PNode) = proc generateAliasChecks(a: AnalysisCtx; result: PNode) =
discard "too implement" 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 # this needs to be called after the 'for' loop elimination
# first pass: # first pass:
@ -482,16 +482,16 @@ proc liftParallel*(g: ModuleGraph; owner: PSym; n: PNode): PNode =
checkArgs(a, body) checkArgs(a, body)
var varSection = newNodeI(nkVarSection, n.info) 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 temp.typ = magicsys.getCompilerProc(g, "Barrier").typ
incl(temp.flags, sfFromGeneric) incl(temp.flags, sfFromGeneric)
let tempNode = newSymNode(temp) let tempNode = newSymNode(temp)
varSection.addVar tempNode varSection.addVar tempNode
let barrier = genAddrOf(tempNode) let barrier = genAddrOf(tempNode, idgen)
result = newNodeI(nkStmtList, n.info) result = newNodeI(nkStmtList, n.info)
generateAliasChecks(a, result) generateAliasChecks(a, result)
result.add varSection result.add varSection
result.add callCodegenProc(g, "openBarrier", barrier.info, barrier) 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) result.add callCodegenProc(g, "closeBarrier", barrier.info, barrier)

View file

@ -92,7 +92,7 @@ proc createTypeBoundOps(tracked: PEffects, typ: PType; info: TLineInfo) =
optSeqDestructors in tracked.config.globalOptions: optSeqDestructors in tracked.config.globalOptions:
createTypeBoundOps(tracked.graph, tracked.c, realType.lastSon, info) 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 if (tfHasAsgn in typ.flags) or
optSeqDestructors in tracked.config.globalOptions: optSeqDestructors in tracked.config.globalOptions:
tracked.owner.flags.incl sfInjectDestructors tracked.owner.flags.incl sfInjectDestructors
@ -219,7 +219,7 @@ proc markGcUnsafe(a: PEffects; reason: PNode) =
if reason.kind == nkSym: if reason.kind == nkSym:
a.owner.gcUnsafetyReason = reason.sym a.owner.gcUnsafetyReason = reason.sym
else: 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, {}) a.owner, reason.info, {})
when true: when true:
@ -755,7 +755,7 @@ proc trackCall(tracked: PEffects; n: PNode) =
if n.typ != nil: if n.typ != nil:
if tracked.owner.kind != skMacro and n.typ.skipTypes(abstractVar).kind != tyOpenArray: if tracked.owner.kind != skMacro and n.typ.skipTypes(abstractVar).kind != tyOpenArray:
createTypeBoundOps(tracked, n.typ, n.info) 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 return
if a.kind == nkCast and a[1].typ.kind == tyProc: if a.kind == nkCast and a[1].typ.kind == tyProc:
a = a[1] a = a[1]
@ -829,7 +829,7 @@ proc trackCall(tracked: PEffects; n: PNode) =
case op[i].kind case op[i].kind
of tySink: of tySink:
createTypeBoundOps(tracked, op[i][0], n.info) 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: of tyVar:
tracked.hasDangerousAssign = true tracked.hasDangerousAssign = true
#of tyOut: #of tyOut:
@ -947,7 +947,7 @@ proc track(tracked: PEffects, n: PNode) =
if tracked.owner.kind != skMacro: if tracked.owner.kind != skMacro:
createTypeBoundOps(tracked, n[0].typ, n.info) createTypeBoundOps(tracked, n[0].typ, n.info)
if n[0].kind != nkSym or not isLocalVar(tracked, n[0].sym): 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: if not tracked.hasDangerousAssign and n[0].kind != nkSym:
tracked.hasDangerousAssign = true tracked.hasDangerousAssign = true
of nkVarSection, nkLetSection: of nkVarSection, nkLetSection:
@ -1054,9 +1054,9 @@ proc track(tracked: PEffects, n: PNode) =
if x.kind == nkExprColonExpr: if x.kind == nkExprColonExpr:
if x[0].kind == nkSym: if x[0].kind == nkSym:
notNilCheck(tracked, x[1], x[0].sym.typ) 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: else:
checkForSink(tracked.config, tracked.owner, x) checkForSink(tracked.config, tracked.c.idgen, tracked.owner, x)
setLen(tracked.guards.s, oldFacts) setLen(tracked.guards.s, oldFacts)
if tracked.owner.kind != skMacro: if tracked.owner.kind != skMacro:
# XXX n.typ can be nil in runnableExamples, we need to do something about it. # 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) createTypeBoundOps(tracked, n[i][0].typ, n.info)
else: else:
createTypeBoundOps(tracked, n[i].typ, n.info) 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: of nkPragmaBlock:
let pragmaList = n[0] let pragmaList = n[0]
var bc = createBlockContext(tracked) var bc = createBlockContext(tracked)
@ -1122,7 +1122,7 @@ proc track(tracked: PEffects, n: PNode) =
of nkBracket: of nkBracket:
for i in 0..<n.safeLen: for i in 0..<n.safeLen:
track(tracked, n[i]) 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: if tracked.owner.kind != skMacro:
createTypeBoundOps(tracked, n.typ, n.info) createTypeBoundOps(tracked, n.typ, n.info)
of nkBracketExpr: of nkBracketExpr:

View file

@ -160,12 +160,12 @@ proc semIf(c: PContext, n: PNode; flags: TExprFlags): PNode =
openScope(c) openScope(c)
it[0] = forceBool(c, semExprWithType(c, it[0])) it[0] = forceBool(c, semExprWithType(c, it[0]))
it[1] = semExprBranch(c, it[1], flags) it[1] = semExprBranch(c, it[1], flags)
typ = commonType(typ, it[1]) typ = commonType(c, typ, it[1])
closeScope(c) closeScope(c)
elif it.len == 1: elif it.len == 1:
hasElse = true hasElse = true
it[0] = semExprBranchScope(c, it[0]) it[0] = semExprBranchScope(c, it[0])
typ = commonType(typ, it[0]) typ = commonType(c, typ, it[0])
else: illFormedAst(it, c.config) else: illFormedAst(it, c.config)
if isEmptyType(typ) or typ.kind in {tyNil, tyUntyped} or if isEmptyType(typ) or typ.kind in {tyNil, tyUntyped} or
(not hasElse and efInTypeof notin flags): (not hasElse and efInTypeof notin flags):
@ -203,7 +203,7 @@ proc semTry(c: PContext, n: PNode; flags: TExprFlags): PNode =
var typ = commonTypeBegin var typ = commonTypeBegin
n[0] = semExprBranchScope(c, n[0]) 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 last = n.len - 1
var catchAllExcepts = 0 var catchAllExcepts = 0
@ -223,7 +223,7 @@ proc semTry(c: PContext, n: PNode; flags: TExprFlags): PNode =
let isImported = semExceptBranchType(a[0][1]) let isImported = semExceptBranchType(a[0][1])
let symbol = newSymG(skLet, a[0][2], c) let symbol = newSymG(skLet, a[0][2], c)
symbol.typ = if isImported: a[0][1].typ 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) addDecl(c, symbol)
# Overwrite symbol in AST with the symbol in the symbol table. # Overwrite symbol in AST with the symbol in the symbol table.
a[0][2] = newSymNode(symbol, a[0][2].info) 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: # last child of an nkExcept/nkFinally branch is a statement:
a[^1] = semExprBranchScope(c, a[^1]) 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 else: dec last
closeScope(c) closeScope(c)
@ -411,8 +411,8 @@ proc fillPartialObject(c: PContext; n: PNode; typ: PType) =
let y = considerQuotedIdent(c, n[1]) let y = considerQuotedIdent(c, n[1])
let obj = x.typ.skipTypes(abstractPtrs) let obj = x.typ.skipTypes(abstractPtrs)
if obj.kind == tyObject and tfPartial in obj.flags: if obj.kind == tyObject and tfPartial in obj.flags:
let field = newSym(skField, getIdent(c.cache, y.s), obj.sym, n[1].info) let field = newSym(skField, getIdent(c.cache, y.s), nextId c.idgen, obj.sym, n[1].info)
field.typ = skipIntLit(typ) field.typ = skipIntLit(typ, c.idgen)
field.position = obj.n.len field.position = obj.n.len
obj.n.add newSymNode(field) obj.n.add newSymNode(field)
n[0] = makeDeref x n[0] = makeDeref x
@ -513,7 +513,7 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
def = fitNode(c, typ, def, def.info) def = fitNode(c, typ, def, def.info)
#changeType(def.skipConv, typ, check=true) #changeType(def.skipConv, typ, check=true)
else: else:
typ = def.typ.skipTypes({tyStatic}).skipIntLit typ = def.typ.skipTypes({tyStatic}).skipIntLit(c.idgen)
if typ.kind in tyUserTypeClasses and typ.isResolvedUserTypeClass: if typ.kind in tyUserTypeClasses and typ.isResolvedUserTypeClass:
typ = typ.lastSon typ = typ.lastSon
if hasEmpty(typ): if hasEmpty(typ):
@ -621,7 +621,7 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
if sfCompileTime in v.flags: if sfCompileTime in v.flags:
var x = newNodeI(result.kind, v.info) var x = newNodeI(result.kind, v.info)
x.add result[i] 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}: if v.flags * {sfGlobal, sfThread} == {sfGlobal}:
message(c.config, v.info, hintGlobalVar) 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) semCaseBranch(c, n, x, i, covered)
var last = x.len-1 var last = x.len-1
x[last] = semExprBranchScope(c, x[last]) x[last] = semExprBranchScope(c, x[last])
typ = commonType(typ, x[last]) typ = commonType(c, typ, x[last])
of nkElifBranch: of nkElifBranch:
chckCovered = false chckCovered = false
checkSonsLen(x, 2, c.config) checkSonsLen(x, 2, c.config)
openScope(c) openScope(c)
x[0] = forceBool(c, semExprWithType(c, x[0])) x[0] = forceBool(c, semExprWithType(c, x[0]))
x[1] = semExprBranch(c, x[1]) x[1] = semExprBranch(c, x[1])
typ = commonType(typ, x[1]) typ = commonType(c, typ, x[1])
closeScope(c) closeScope(c)
of nkElse: of nkElse:
checkSonsLen(x, 1, c.config) checkSonsLen(x, 1, c.config)
x[0] = semExprBranchScope(c, x[0]) 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: if (chckCovered and covered == toCover(c, n[0].typ)) or hasElse:
message(c.config, x.info, warnUnreachableElse) message(c.config, x.info, warnUnreachableElse)
hasElse = true hasElse = true
@ -1276,7 +1276,7 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
internalAssert c.config, st.lastSon.sym == nil internalAssert c.config, st.lastSon.sym == nil
incl st.flags, tfRefsAnonObj incl st.flags, tfRefsAnonObj
let obj = newSym(skType, getIdent(c.cache, s.name.s & ":ObjectType"), 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 obj.ast = a
if sfPure in s.flags: if sfPure in s.flags:
obj.flags.incl sfPure 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 s.typ != nil and s.typ.kind notin {tyAlias, tySink}:
if t.kind in {tyProc, tyGenericInst} and not t.isMetaType: if t.kind in {tyProc, tyGenericInst} and not t.isMetaType:
assignType(s.typ, t) assignType(s.typ, t)
s.typ.id = t.id s.typ.itemId = t.itemId
elif t.kind in {tyObject, tyEnum, tyDistinct}: elif t.kind in {tyObject, tyEnum, tyDistinct}:
assert s.typ != nil assert s.typ != nil
assignType(s.typ, t) 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) checkConstructedType(c.config, s.info, s.typ)
if s.typ.kind in {tyObject, tyTuple} and not s.typ.n.isNil: if s.typ.kind in {tyObject, tyTuple} and not s.typ.n.isNil:
checkForMetaFields(c, s.typ.n) 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") localError(c.config, n.info, "incorrect result proc symbol")
c.p.resultSym = n[resultPos].sym c.p.resultSym = n[resultPos].sym
else: 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 s.typ = t
incl(s.flags, sfUsed) incl(s.flags, sfUsed)
c.p.resultSym = s c.p.resultSym = s
@ -1535,7 +1535,7 @@ proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode =
checkSonsLen(n, bodyPos + 1, c.config) checkSonsLen(n, bodyPos + 1, c.config)
var s: PSym var s: PSym
if n[namePos].kind != nkSym: 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 s.ast = n
n[namePos] = newSymNode(s) n[namePos] = newSymNode(s)
else: else:
@ -1800,7 +1800,7 @@ proc hasObjParam(s: PSym): bool =
proc finishMethod(c: PContext, s: PSym) = proc finishMethod(c: PContext, s: PSym) =
if hasObjParam(s): if hasObjParam(s):
methodDef(c.graph, s, false) methodDef(c.graph, c.idgen, s, false)
proc semMethodPrototype(c: PContext; s: PSym; n: PNode) = proc semMethodPrototype(c: PContext; s: PSym; n: PNode) =
if isGenericRoutine(s): if isGenericRoutine(s):
@ -1825,7 +1825,7 @@ proc semMethodPrototype(c: PContext; s: PSym; n: PNode) =
# no sense either. # no sense either.
# and result[bodyPos].kind != nkEmpty: # and result[bodyPos].kind != nkEmpty:
if hasObjParam(s): if hasObjParam(s):
methodDef(c.graph, s, fromCache=false) methodDef(c.graph, c.idgen, s, fromCache=false)
else: else:
localError(c.config, n.info, "'method' needs a parameter that has an object type") 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 assert phase == stepRegisterSymbol
if n[namePos].kind == nkEmpty: 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) incl(s.flags, sfUsed)
isAnon = true isAnon = true
else: else:
@ -1998,7 +1998,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
if s.kind == skMethod: semMethodPrototype(c, s, n) if s.kind == skMethod: semMethodPrototype(c, s, n)
else: else:
if (s.typ[0] != nil and kind != skIterator) or kind == skMacro: 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) openScope(c)
n[bodyPos] = semGenericStmt(c, n[bodyPos]) n[bodyPos] = semGenericStmt(c, n[bodyPos])
@ -2189,7 +2189,7 @@ proc semStaticStmt(c: PContext, n: PNode): PNode =
closeScope(c) closeScope(c)
dec c.inStaticContext dec c.inStaticContext
n[0] = a 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: when false:
# for incremental replays, keep the AST as required for replays: # for incremental replays, keep the AST as required for replays:
result = n result = n

View file

@ -176,7 +176,7 @@ proc onlyReplaceParams(c: var TemplCtx, n: PNode): PNode =
result[i] = onlyReplaceParams(c, n[i]) result[i] = onlyReplaceParams(c, n[i])
proc newGenSym(kind: TSymKind, n: PNode, c: var TemplCtx): PSym = 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, sfGenSym)
incl(result.flags, sfShadowed) 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) result = symChoice(c, n, s, scOpen, isField)
of skGenericParam: of skGenericParam:
if isField and sfGenSym in s.flags: result = n 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: of skParam:
result = n result = n
of skType: of skType:
if isField and sfGenSym in s.flags: result = n if isField and sfGenSym in s.flags: result = n
else: result = newSymNodeTypeDesc(s, n.info) else: result = newSymNodeTypeDesc(s, c.idgen, n.info)
else: else:
if isField and sfGenSym in s.flags: result = n if isField and sfGenSym in s.flags: result = n
else: result = newSymNode(s, n.info) else: result = newSymNode(s, n.info)

View file

@ -51,7 +51,7 @@ proc newOrPrevType(kind: TTypeKind, prev: PType, c: PContext): PType =
proc newConstraint(c: PContext, k: TTypeKind): PType = proc newConstraint(c: PContext, k: TTypeKind): PType =
result = newTypeS(tyBuiltInTypeClass, c) result = newTypeS(tyBuiltInTypeClass, c)
result.flags.incl tfCheckedForDestructor 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 = proc semEnum(c: PContext, n: PNode, prev: PType): PType =
if n.len == 0: return newConstraint(c, tyEnum) 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) result = newOrPrevType(tySet, prev, c)
if n.len == 2 and n[1].kind != nkEmpty: if n.len == 2 and n[1].kind != nkEmpty:
var base = semTypeNode(c, n[1], nil) 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 in {tyGenericInst, tyAlias, tySink}: base = lastSon(base)
if base.kind != tyGenericParam: if base.kind != tyGenericParam:
if not isOrdinalType(base, allowEnumWithHoles = true): 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) localError(c.config, n.info, errSetTooBig)
else: else:
localError(c.config, n.info, errXExpectsOneTypeParam % "set") 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) = proc semContainerArg(c: PContext; n: PNode, kindStr: string; result: PType) =
if n.len == 2: if n.len == 2:
var base = semTypeNode(c, n[1], nil) var base = semTypeNode(c, n[1], nil)
if base.kind == tyVoid: if base.kind == tyVoid:
localError(c.config, n.info, errTIsNotAConcreteType % typeToString(base)) localError(c.config, n.info, errTIsNotAConcreteType % typeToString(base))
addSonSkipIntLit(result, base) addSonSkipIntLit(result, base, c.idgen)
else: else:
localError(c.config, n.info, errXExpectsOneTypeParam % kindStr) 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, proc semContainer(c: PContext, n: PNode, kind: TTypeKind, kindStr: string,
prev: PType): PType = prev: PType): PType =
@ -186,12 +186,12 @@ proc semVarargs(c: PContext, n: PNode, prev: PType): PType =
result = newOrPrevType(tyVarargs, prev, c) result = newOrPrevType(tyVarargs, prev, c)
if n.len == 2 or n.len == 3: if n.len == 2 or n.len == 3:
var base = semTypeNode(c, n[1], nil) var base = semTypeNode(c, n[1], nil)
addSonSkipIntLit(result, base) addSonSkipIntLit(result, base, c.idgen)
if n.len == 3: if n.len == 3:
result.n = newIdentNode(considerQuotedIdent(c, n[2]), n[2].info) result.n = newIdentNode(considerQuotedIdent(c, n[2]), n[2].info)
else: else:
localError(c.config, n.info, errXExpectsOneTypeParam % "varargs") 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 = proc semVarOutType(c: PContext, n: PNode, prev: PType; kind: TTypeKind): PType =
if n.len == 1: if n.len == 1:
@ -200,14 +200,14 @@ proc semVarOutType(c: PContext, n: PNode, prev: PType; kind: TTypeKind): PType =
if base.kind == tyVar: if base.kind == tyVar:
localError(c.config, n.info, "type 'var var' is not allowed") localError(c.config, n.info, "type 'var var' is not allowed")
base = base[0] base = base[0]
addSonSkipIntLit(result, base) addSonSkipIntLit(result, base, c.idgen)
else: else:
result = newConstraint(c, kind) result = newConstraint(c, kind)
proc semDistinct(c: PContext, n: PNode, prev: PType): PType = proc semDistinct(c: PContext, n: PNode, prev: PType): PType =
if n.len == 0: return newConstraint(c, tyDistinct) if n.len == 0: return newConstraint(c, tyDistinct)
result = newOrPrevType(tyDistinct, prev, c) 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] if n.len > 1: result.n = n[1]
proc semRangeAux(c: PContext, n: PNode, prev: PType): PType = 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) result.n = newNodeI(nkRange, n.info)
# always create a 'valid' range type, but overwrite it later # always create a 'valid' range type, but overwrite it later
# because 'semExprWithType' can raise an exception. See bug #6895. # 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): if (n[1].kind == nkEmpty) or (n[2].kind == nkEmpty):
localError(c.config, n.info, "range is empty") 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] var rangeT: array[2, PType]
for i in 0..1: 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 let hasUnknownTypes = c.inGenericContext > 0 and
rangeT[0].kind == tyFromExpr or rangeT[1].kind == tyFromExpr 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 # bug #6682: Do not propagate initialization requirements etc for the
# index type: # index type:
rawAddSonNoPropagationOfTypeFlags(result, indx) rawAddSonNoPropagationOfTypeFlags(result, indx)
addSonSkipIntLit(result, base) addSonSkipIntLit(result, base, c.idgen)
else: else:
localError(c.config, n.info, errArrayExpectsTwoTypeParams) localError(c.config, n.info, errArrayExpectsTwoTypeParams)
result = newOrPrevType(tyError, prev, c) result = newOrPrevType(tyError, prev, c)
@ -357,7 +357,7 @@ proc semOrdinal(c: PContext, n: PNode, prev: PType): PType =
if base.kind != tyGenericParam: if base.kind != tyGenericParam:
if not isOrdinalType(base): if not isOrdinalType(base):
localError(c.config, n[1].info, errOrdinalTypeExpected) localError(c.config, n[1].info, errOrdinalTypeExpected)
addSonSkipIntLit(result, base) addSonSkipIntLit(result, base, c.idgen)
else: else:
localError(c.config, n.info, errXExpectsOneTypeParam % "ordinal") localError(c.config, n.info, errXExpectsOneTypeParam % "ordinal")
result = newOrPrevType(tyError, prev, c) result = newOrPrevType(tyError, prev, c)
@ -384,7 +384,7 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
if result.typ.sym == nil: if result.typ.sym == nil:
localError(c.config, n.info, errTypeExpected) localError(c.config, n.info, errTypeExpected)
return errorSym(c, n) return errorSym(c, n)
result = result.typ.sym.copySym result = result.typ.sym.copySym(nextId c.idgen)
result.typ = exactReplica(result.typ) result.typ = exactReplica(result.typ)
result.typ.flags.incl tfUnresolved result.typ.flags.incl tfUnresolved
@ -429,7 +429,7 @@ proc semAnonTuple(c: PContext, n: PNode, prev: PType): PType =
localError(c.config, n.info, errTypeExpected) localError(c.config, n.info, errTypeExpected)
result = newOrPrevType(tyTuple, prev, c) result = newOrPrevType(tyTuple, prev, c)
for it in n: 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 = proc semTuple(c: PContext, n: PNode, prev: PType): PType =
var typ: 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 & "'") localError(c.config, a[j].info, "attempt to redefine: '" & field.name.s & "'")
else: else:
result.n.add newSymNode(field) result.n.add newSymNode(field)
addSonSkipIntLit(result, typ) addSonSkipIntLit(result, typ, c.idgen)
styleCheckDef(c.config, a[j].info, field) styleCheckDef(c.config, a[j].info, field)
onDef(field.info, field) onDef(field.info, field)
if result.n.len == 0: result.n = nil if result.n.len == 0: result.n = nil
if isTupleRecursive(result): if isTupleRecursive(result):
localError(c.config, n.info, errIllegalRecursionInTypeX % typeToString(result)) localError(c.config, n.info, errIllegalRecursionInTypeX % typeToString(result))
proc semIdentVis(c: PContext, kind: TSymKind, n: PNode, proc semIdentVis(c: PContext, kind: TSymKind, n: PNode,
allowed: TSymFlags): PSym = allowed: TSymFlags): PSym =
# identifier with visibility # 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 { elif region.skipTypes({tyGenericInst, tyAlias, tySink}).kind notin {
tyError, tyObject}: tyError, tyObject}:
message c.config, n[i].info, errGenerated, "region needs to be an object type" message c.config, n[i].info, errGenerated, "region needs to be an object type"
addSonSkipIntLit(result, region) addSonSkipIntLit(result, region, c.idgen)
else: else:
message(c.config, n.info, warnDeprecated, "region for pointer types is deprecated") message(c.config, n.info, warnDeprecated, "region for pointer types is deprecated")
addSonSkipIntLit(result, region) addSonSkipIntLit(result, region, c.idgen)
addSonSkipIntLit(result, t) addSonSkipIntLit(result, t, c.idgen)
if tfPartial in result.flags: if tfPartial in result.flags:
if result.lastSon.kind == tyObject: incl(result.lastSon.flags, tfPartial) if result.lastSon.kind == tyObject: incl(result.lastSon.flags, tfPartial)
#if not isNilable: result.flags.incl tfNotNil #if not isNilable: result.flags.incl tfNotNil
@ -963,7 +961,7 @@ proc addParamOrResult(c: PContext, param: PSym, kind: TSymKind) =
if kind == skMacro: if kind == skMacro:
let staticType = findEnforcedStaticType(param.typ) let staticType = findEnforcedStaticType(param.typ)
if staticType != nil: if staticType != nil:
var a = copySym(param) var a = copySym(param, nextId c.idgen)
a.typ = staticType.base a.typ = staticType.base
addDecl(c, a) addDecl(c, a)
#elif param.typ != nil and param.typ.kind == tyTypeDesc: #elif param.typ != nil and param.typ.kind == tyTypeDesc:
@ -971,7 +969,7 @@ proc addParamOrResult(c: PContext, param: PSym, kind: TSymKind) =
else: else:
# within a macro, every param has the type NimNode! # within a macro, every param has the type NimNode!
let nn = getSysSym(c.graph, param.info, "NimNode") let nn = getSysSym(c.graph, param.info, "NimNode")
var a = copySym(param) var a = copySym(param, nextId c.idgen)
a.typ = nn.typ a.typ = nn.typ
addDecl(c, a) addDecl(c, a)
else: else:
@ -1001,7 +999,7 @@ proc addImplicitGeneric(c: PContext; typeClass: PType, typId: PIdent;
let owner = if typeClass.sym != nil: typeClass.sym let owner = if typeClass.sym != nil: typeClass.sym
else: getCurrOwner(c) 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 sfExplain in owner.flags: s.flags.incl sfExplain
if typId == nil: s.flags.incl(sfAnon) if typId == nil: s.flags.incl(sfAnon)
s.linkTo(typeClass) s.linkTo(typeClass)
@ -1107,7 +1105,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
of tyGenericInst: of tyGenericInst:
if paramType.lastSon.kind == tyUserTypeClass: if paramType.lastSon.kind == tyUserTypeClass:
var cp = copyType(paramType, getCurrOwner(c), false) var cp = copyType(paramType, nextId c.idgen, getCurrOwner(c))
cp.kind = tyUserTypeClassInst cp.kind = tyUserTypeClassInst
return addImplicitGeneric(c, cp, paramTypId, info, genericParams, paramName) return addImplicitGeneric(c, cp, paramTypId, info, genericParams, paramName)
@ -1144,7 +1142,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
of tyUserTypeClasses, tyBuiltInTypeClass, tyCompositeTypeClass, of tyUserTypeClasses, tyBuiltInTypeClass, tyCompositeTypeClass,
tyAnd, tyOr, tyNot: tyAnd, tyOr, tyNot:
result = addImplicitGeneric(c, result = addImplicitGeneric(c,
copyType(paramType, getCurrOwner(c), false), paramTypId, copyType(paramType, nextId c.idgen, getCurrOwner(c)), paramTypId,
info, genericParams, paramName) info, genericParams, paramName)
of tyGenericParam: of tyGenericParam:
@ -1274,7 +1272,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
typ = errorType(c) typ = errorType(c)
let lifted = liftParamType(c, kind, genericParams, typ, let lifted = liftParamType(c, kind, genericParams, typ,
arg.name.s, arg.info) 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.typ = finalType
arg.position = counter arg.position = counter
arg.constraint = constraint arg.constraint = constraint
@ -1331,7 +1329,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
#if r.kind != tyGenericParam: #if r.kind != tyGenericParam:
#echo "came here for ", typeToString(r) #echo "came here for ", typeToString(r)
r.flags.incl tfRetType r.flags.incl tfRetType
r = skipIntLit(r) r = skipIntLit(r, c.idgen)
if kind == skIterator: if kind == skIterator:
# see tchainediterators # see tchainediterators
# in cases like iterator foo(it: iterator): type(it) # 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 t = t.base
result = newOrPrevType(tyGenericInvocation, prev, c) result = newOrPrevType(tyGenericInvocation, prev, c)
addSonSkipIntLit(result, t) addSonSkipIntLit(result, t, c.idgen)
template addToResult(typ) = template addToResult(typ) =
if typ.isNil: if typ.isNil:
internalAssert c.config, false internalAssert c.config, false
rawAddSon(result, typ) rawAddSon(result, typ)
else: addSonSkipIntLit(result, typ) else: addSonSkipIntLit(result, typ, c.idgen)
if t.kind == tyForward: if t.kind == tyForward:
for i in 1..<n.len: 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) localError(c.config, n.info, "expected type, but got: " & n.renderTree)
result = errorType(c) result = errorType(c)
proc freshType(res, prev: PType): PType {.inline.} = proc freshType(c: PContext; res, prev: PType): PType {.inline.} =
if prev.isNil: if prev.isNil:
result = copyType(res, res.owner, keepId=false) result = copyType(res, nextId c.idgen, res.owner)
else: else:
result = res result = res
@ -1542,7 +1540,7 @@ proc semTypeClass(c: PContext, n: PNode, prev: PType): PType =
result = newOrPrevType(tyUserTypeClass, prev, c) result = newOrPrevType(tyUserTypeClass, prev, c)
result.flags.incl tfCheckedForDestructor result.flags.incl tfCheckedForDestructor
var owner = getCurrOwner(c) var owner = getCurrOwner(c)
var candidateTypeSlot = newTypeWithSons(owner, tyAlias, @[c.errorType]) var candidateTypeSlot = newTypeWithSons(owner, tyAlias, @[c.errorType], c.idgen)
result.sons = @[candidateTypeSlot] result.sons = @[candidateTypeSlot]
result.n = n result.n = n
@ -1575,7 +1573,7 @@ proc semTypeClass(c: PContext, n: PNode, prev: PType): PType =
internalAssert c.config, dummyName.kind == nkIdent internalAssert c.config, dummyName.kind == nkIdent
var dummyParam = newSym(if modifier == tyTypeDesc: skType else: skVar, 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 dummyParam.typ = dummyType
incl dummyParam.flags, sfUsed incl dummyParam.flags, sfUsed
addDecl(c, dummyParam) addDecl(c, dummyParam)
@ -1713,7 +1711,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
result = semTypeNode(c, n[1], prev) result = semTypeNode(c, n[1], prev)
if result.skipTypes({tyGenericInst, tyAlias, tySink, tyOwned}).kind in NilableTypes+GenericTypes: if result.skipTypes({tyGenericInst, tyAlias, tySink, tyOwned}).kind in NilableTypes+GenericTypes:
if tfNotNil in result.flags: if tfNotNil in result.flags:
result = freshType(result, prev) result = freshType(c, result, prev)
result.flags.excl(tfNotNil) result.flags.excl(tfNotNil)
else: else:
localError(c.config, n.info, errGenerated, "invalid type") 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]`. # to other types such as `Option[T]`.
result = makeTypeFromExpr(c, newTree(nkStmtListType, n.copyTree)) result = makeTypeFromExpr(c, newTree(nkStmtListType, n.copyTree))
of NilableTypes + {tyGenericInvocation, tyForward}: of NilableTypes + {tyGenericInvocation, tyForward}:
result = freshType(result, prev) result = freshType(c, result, prev)
result.flags.incl(tfNotNil) result.flags.incl(tfNotNil)
else: else:
localError(c.config, n.info, errGenerated, "invalid type") localError(c.config, n.info, errGenerated, "invalid type")
@ -1828,19 +1826,19 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
of mExpr: of mExpr:
result = semTypeNode(c, n[0], nil) result = semTypeNode(c, n[0], nil)
if result != nil: if result != nil:
result = copyType(result, getCurrOwner(c), false) result = copyType(result, nextId c.idgen, getCurrOwner(c))
for i in 1..<n.len: for i in 1..<n.len:
result.rawAddSon(semTypeNode(c, n[i], nil)) result.rawAddSon(semTypeNode(c, n[i], nil))
of mDistinct: of mDistinct:
result = newOrPrevType(tyDistinct, prev, c) result = newOrPrevType(tyDistinct, prev, c)
addSonSkipIntLit(result, semTypeNode(c, n[1], nil)) addSonSkipIntLit(result, semTypeNode(c, n[1], nil), c.idgen)
of mVar: of mVar:
result = newOrPrevType(tyVar, prev, c) result = newOrPrevType(tyVar, prev, c)
var base = semTypeNode(c, n[1], nil) var base = semTypeNode(c, n[1], nil)
if base.kind in {tyVar, tyLent}: if base.kind in {tyVar, tyLent}:
localError(c.config, n.info, "type 'var var' is not allowed") localError(c.config, n.info, "type 'var var' is not allowed")
base = base[0] base = base[0]
addSonSkipIntLit(result, base) addSonSkipIntLit(result, base, c.idgen)
of mRef: result = semAnyRef(c, n, tyRef, prev) of mRef: result = semAnyRef(c, n, tyRef, prev)
of mPtr: result = semAnyRef(c, n, tyPtr, prev) of mPtr: result = semAnyRef(c, n, tyPtr, prev)
of mTuple: result = semTuple(c, n, 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: # bugfix: keep the fresh id for aliases to integral types:
if s.typ.kind notin {tyBool, tyChar, tyInt..tyInt64, tyFloat..tyFloat128, if s.typ.kind notin {tyBool, tyChar, tyInt..tyInt64, tyFloat..tyFloat128,
tyUInt..tyUInt64}: tyUInt..tyUInt64}:
prev.id = s.typ.id prev.itemId = s.typ.itemId
result = prev result = prev
of nkSym: of nkSym:
let s = getGenSym(c, n.sym) let s = getGenSym(c, n.sym)
@ -1929,7 +1927,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
result = newTypeS(tyBuiltInTypeClass, c) result = newTypeS(tyBuiltInTypeClass, c)
let child = newTypeS(tyProc, c) let child = newTypeS(tyProc, c)
child.flags.incl tfIterator child.flags.incl tfIterator
result.addSonSkipIntLit(child) result.addSonSkipIntLit(child, c.idgen)
else: else:
result = semProcTypeWithScope(c, n, prev, skIterator) result = semProcTypeWithScope(c, n, prev, skIterator)
if result.kind == tyProc: 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 = proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
template addSym(result: PNode, s: PSym): untyped = 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) if sfGenSym notin s.flags: addDecl(c, s)
result.add newSymNode(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: for j in 0..<a.len-2:
let finalType = if j == 0: typ 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 # it's important the we create an unique
# type for each generic param. the index # type for each generic param. the index
# of the parameter will be stored in the # of the parameter will be stored in the

View file

@ -279,7 +279,7 @@ proc replaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym =
var g: G[string] var g: G[string]
]# ]#
result = copySym(s) result = copySym(s, nextId cl.c.idgen)
incl(result.flags, sfFromGeneric) incl(result.flags, sfFromGeneric)
#idTablePut(cl.symMap, s, result) #idTablePut(cl.symMap, s, result)
result.owner = s.owner result.owner = s.owner
@ -302,7 +302,12 @@ proc lookupTypeVar(cl: var TReplTypeVars, t: PType): PType =
proc instCopyType*(cl: var TReplTypeVars, t: PType): PType = proc instCopyType*(cl: var TReplTypeVars, t: PType): PType =
# XXX: relying on allowMetaTypes is a kludge # 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 if cl.allowMetaTypes: return
result.flags.incl tfFromGeneric result.flags.incl tfFromGeneric
if not (t.kind in tyMetaTypes or if not (t.kind in tyMetaTypes or
@ -355,7 +360,7 @@ proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType =
else: else:
header = instCopyType(cl, t) header = instCopyType(cl, t)
result = newType(tyGenericInst, t[0].owner) result = newType(tyGenericInst, nextId(cl.c.idgen), t[0].owner)
result.flags = header.flags result.flags = header.flags
# be careful not to propagate unnecessary flags here (don't use rawAddSon) # be careful not to propagate unnecessary flags here (don't use rawAddSon)
result.sons = @[header[0]] result.sons = @[header[0]]
@ -459,11 +464,11 @@ proc eraseVoidParams*(t: PType) =
setLen t.n.sons, pos setLen t.n.sons, pos
break break
proc skipIntLiteralParams*(t: PType) = proc skipIntLiteralParams*(t: PType; idgen: IdGenerator) =
for i in 0..<t.len: for i in 0..<t.len:
let p = t[i] let p = t[i]
if p == nil: continue if p == nil: continue
let skipped = p.skipIntLit let skipped = p.skipIntLit(idgen)
if skipped != p: if skipped != p:
t[i] = skipped t[i] = skipped
if i > 0: t.n[i].sym.typ = 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 result = n.typ
of tyInt, tyFloat: of tyInt, tyFloat:
result = skipIntLit(t) result = skipIntLit(t, cl.c.idgen)
of tyTypeDesc: of tyTypeDesc:
let lookup = cl.typeMap.lookup(t) let lookup = cl.typeMap.lookup(t)
@ -617,7 +622,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
of tyProc: of tyProc:
eraseVoidParams(result) eraseVoidParams(result)
skipIntLiteralParams(result) skipIntLiteralParams(result, cl.c.idgen)
of tyRange: of tyRange:
result[0] = result[0].skipTypes({tyStatic, tyDistinct}) result[0] = result[0].skipTypes({tyStatic, tyDistinct})

View file

@ -143,7 +143,7 @@ proc put(c: var TCandidate, key, val: PType) {.inline.} =
writeStackTrace() writeStackTrace()
if c.c.module.name.s == "temp3": if c.c.module.name.s == "temp3":
echo "binding ", key, " -> ", val 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, proc initCandidate*(ctx: PContext, c: var TCandidate, callee: PSym,
binding: PNode, calleeScope = -1, binding: PNode, calleeScope = -1,
@ -726,7 +726,7 @@ proc matchUserTypeClass*(m: var TCandidate; ff, a: PType): PType =
if alreadyBound != nil: typ = alreadyBound if alreadyBound != nil: typ = alreadyBound
template paramSym(kind): untyped = 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: block addTypeParam:
for prev in typeParams: for prev in typeParams:
@ -739,6 +739,7 @@ proc matchUserTypeClass*(m: var TCandidate; ff, a: PType): PType =
of tyStatic: of tyStatic:
param = paramSym skConst param = paramSym skConst
param.typ = typ.exactReplica param.typ = typ.exactReplica
#copyType(typ, nextId(c.idgen), typ.owner)
if typ.n == nil: if typ.n == nil:
param.typ.flags.incl tfInferrableStatic param.typ.flags.incl tfInferrableStatic
else: else:
@ -746,6 +747,7 @@ proc matchUserTypeClass*(m: var TCandidate; ff, a: PType): PType =
of tyUnknown: of tyUnknown:
param = paramSym skVar param = paramSym skVar
param.typ = typ.exactReplica param.typ = typ.exactReplica
#copyType(typ, nextId(c.idgen), typ.owner)
else: else:
param = paramSym skType param = paramSym skType
param.typ = if typ.isMetaType: param.typ = if typ.isMetaType:
@ -796,7 +798,8 @@ proc matchUserTypeClass*(m: var TCandidate; ff, a: PType): PType =
if ff.kind == tyUserTypeClassInst: if ff.kind == tyUserTypeClassInst:
result = generateTypeInstance(c, m.bindings, typeClass.sym.info, ff) result = generateTypeInstance(c, m.bindings, typeClass.sym.info, ff)
else: else:
result = copyType(ff, ff.owner, true) result = ff.exactReplica
#copyType(ff, nextId(c.idgen), ff.owner)
result.n = checkedBody result.n = checkedBody
@ -1086,7 +1089,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
template bindingRet(res) = template bindingRet(res) =
if doBind: if doBind:
let bound = aOrig.skipTypes({tyRange}).skipIntLit let bound = aOrig.skipTypes({tyRange}).skipIntLit(c.c.idgen)
put(c, f, bound) put(c, f, bound)
return res return res
@ -1500,14 +1503,15 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
of tyGenericInvocation: of tyGenericInvocation:
var x = a.skipGenericAlias var x = a.skipGenericAlias
var preventHack = false var preventHack = false
if x.kind == tyOwned and f[0].kind != tyOwned: if x.kind == tyOwned and f[0].kind != tyOwned:
preventHack = true preventHack = true
x = x.lastSon x = x.lastSon
# XXX: This is very hacky. It should be moved back into liftTypeParam # XXX: This is very hacky. It should be moved back into liftTypeParam
if x.kind in {tyGenericInst, tyArray} and if x.kind in {tyGenericInst, tyArray} and
c.calleeSym != nil and c.calleeSym != nil and
c.calleeSym.kind in {skProc, skFunc} and c.call != nil and not preventHack: c.calleeSym.kind in {skProc, skFunc} and c.call != nil and not preventHack:
let inst = prepareMetatypeForSigmatch(c.c, c.bindings, c.call.info, f) let inst = prepareMetatypeForSigmatch(c.c, c.bindings, c.call.info, f)
#echo "inferred ", typeToString(inst), " for ", f #echo "inferred ", typeToString(inst), " for ", f
return typeRel(c, inst, a, flags) return typeRel(c, inst, a, flags)
@ -2291,7 +2295,7 @@ proc arrayConstr(c: PContext, n: PNode): PType =
result = newTypeS(tyArray, c) result = newTypeS(tyArray, c)
rawAddSon(result, makeRangeType(c, 0, 0, n.info)) rawAddSon(result, makeRangeType(c, 0, 0, n.info))
addSonSkipIntLit(result, skipTypes(n.typ, addSonSkipIntLit(result, skipTypes(n.typ,
{tyGenericInst, tyVar, tyLent, tyOrdinal})) {tyGenericInst, tyVar, tyLent, tyOrdinal}), c.idgen)
proc arrayConstr(c: PContext, info: TLineInfo): PType = proc arrayConstr(c: PContext, info: TLineInfo): PType =
result = newTypeS(tyArray, c) result = newTypeS(tyArray, c)

View file

@ -7,7 +7,7 @@
# distribution, for details about the copyright. # 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: #[ Patterns we seek to detect:
someLocation = p # ---> p: sink T someLocation = p # ---> p: sink T
@ -32,7 +32,7 @@ proc checkForSink*(config: ConfigRef; owner: PSym; arg: PNode) =
if sfWasForwarded notin owner.flags: if sfWasForwarded notin owner.flags:
let argType = arg.sym.typ let argType = arg.sym.typ
let sinkType = newType(tySink, owner) let sinkType = newType(tySink, nextId(idgen), owner)
sinkType.size = argType.size sinkType.size = argType.size
sinkType.align = argType.align sinkType.align = argType.align
sinkType.paddingAtEnd = argType.paddingAtEnd 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" #echo config $ arg.info, " candidate for a sink parameter here"
of nkStmtList, nkStmtListExpr, nkBlockStmt, nkBlockExpr: of nkStmtList, nkStmtListExpr, nkBlockStmt, nkBlockExpr:
if not isEmptyType(arg.typ): if not isEmptyType(arg.typ):
checkForSink(config, owner, arg.lastSon) checkForSink(config, idgen, owner, arg.lastSon)
of nkIfStmt, nkIfExpr, nkWhen: of nkIfStmt, nkIfExpr, nkWhen:
for branch in arg: for branch in arg:
let value = branch.lastSon let value = branch.lastSon
if not isEmptyType(value.typ): if not isEmptyType(value.typ):
checkForSink(config, owner, value) checkForSink(config, idgen, owner, value)
of nkCaseStmt: of nkCaseStmt:
for i in 1..<arg.len: for i in 1..<arg.len:
let value = arg[i].lastSon let value = arg[i].lastSon
if not isEmptyType(value.typ): if not isEmptyType(value.typ):
checkForSink(config, owner, value) checkForSink(config, idgen, owner, value)
of nkTryStmt: of nkTryStmt:
checkForSink(config, owner, arg[0]) checkForSink(config, idgen, owner, arg[0])
else: else:
discard "nothing to do" discard "nothing to do"

View file

@ -53,9 +53,9 @@ proc typeNeedsNoDeepCopy(t: PType): bool =
if t.kind in {tyVar, tyLent, tySequence}: t = t.lastSon if t.kind in {tyVar, tyLent, tySequence}: t = t.lastSon
result = not containsGarbageCollectedRef(t) 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 = 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) owner.options)
result.typ = typ result.typ = typ
incl(result.flags, sfFromGeneric) incl(result.flags, sfFromGeneric)
@ -111,22 +111,23 @@ stmtList:
proc createWrapperProc(g: ModuleGraph; f: PNode; threadParam, argsParam: PSym; proc createWrapperProc(g: ModuleGraph; f: PNode; threadParam, argsParam: PSym;
varSection, varInit, call, barrier, fv: PNode; varSection, varInit, call, barrier, fv: PNode;
idgen: IdGenerator;
spawnKind: TSpawnResult, result: PSym) = spawnKind: TSpawnResult, result: PSym) =
var body = newNodeI(nkStmtList, f.info) var body = newNodeI(nkStmtList, f.info)
var threadLocalBarrier: PSym var threadLocalBarrier: PSym
if barrier != nil: if barrier != nil:
var varSection2 = newNodeI(nkVarSection, barrier.info) var varSection2 = newNodeI(nkVarSection, barrier.info)
threadLocalBarrier = addLocalVar(g, varSection2, nil, result, threadLocalBarrier = addLocalVar(g, varSection2, nil, idgen, result,
barrier.typ, barrier) barrier.typ, barrier)
body.add varSection2 body.add varSection2
body.add callCodegenProc(g, "barrierEnter", threadLocalBarrier.info, body.add callCodegenProc(g, "barrierEnter", threadLocalBarrier.info,
threadLocalBarrier.newSymNode) threadLocalBarrier.newSymNode)
var threadLocalProm: PSym var threadLocalProm: PSym
if spawnKind == srByVar: 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: elif fv != nil:
internalAssert g.config, fv.typ.kind == tyGenericInst 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 varSection
body.add varInit body.add varInit
if fv != nil and spawnKind != srByVar: 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 threadParam.newSymNode
params.add argsParam.newSymNode params.add argsParam.newSymNode
var t = newType(tyProc, threadParam.owner) var t = newType(tyProc, nextId idgen, threadParam.owner)
t.rawAddSon nil t.rawAddSon nil
t.rawAddSon threadParam.typ t.rawAddSon threadParam.typ
t.rawAddSon argsParam.typ t.rawAddSon argsParam.typ
@ -184,15 +185,15 @@ proc createWrapperProc(g: ModuleGraph; f: PNode; threadParam, argsParam: PSym;
exceptions = emptyNode) exceptions = emptyNode)
result.typ = t 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 = newNodeI(nkCast, argsParam.info)
result.add newNodeI(nkEmpty, argsParam.info) result.add newNodeI(nkEmpty, argsParam.info)
result.add newSymNode(argsParam) result.add newSymNode(argsParam)
result.typ = newType(tyPtr, objType.owner) result.typ = newType(tyPtr, nextId idgen, objType.owner)
result.typ.rawAddSon(objType) result.typ.rawAddSon(objType)
proc setupArgsForConcurrency(g: ModuleGraph; n: PNode; objType: PType; proc setupArgsForConcurrency(g: ModuleGraph; n: PNode; objType: PType;
owner: PSym; scratchObj: PSym, idgen: IdGenerator; owner: PSym; scratchObj: PSym,
castExpr, call, castExpr, call,
varSection, varInit, result: PNode) = varSection, varInit, result: PNode) =
let formals = n[0].typ.n 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") # localError(n[i].info, "'spawn'ed function cannot refer to 'ref'/closure")
let fieldname = if i < formals.len: formals[i].sym.name else: tmpName 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 field.typ = argType
objType.addField(field, g.cache) objType.addField(field, g.cache, idgen)
result.add newFastAsgnStmt(newDotExpr(scratchObj, field), n[i]) 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)) indirectAccess(castExpr, field, n.info))
call.add(newSymNode(temp)) call.add(newSymNode(temp))
proc setupArgsForParallelism(g: ModuleGraph; n: PNode; objType: PType; proc setupArgsForParallelism(g: ModuleGraph; n: PNode; objType: PType;
idgen: IdGenerator;
owner: PSym; scratchObj: PSym; owner: PSym; scratchObj: PSym;
castExpr, call, castExpr, call,
varSection, varInit, result: PNode) = 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") # localError(n.info, "'spawn'ed function cannot refer to 'ref'/closure")
let fieldname = if i < formals.len: formals[i].sym.name else: tmpName 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}: if argType.kind in {tyVarargs, tyOpenArray}:
# important special case: we always create a zero-copy slice: # 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.typ = n.typ
slice[0] = newSymNode(createMagic(g, "slice", mSlice)) slice[0] = newSymNode(createMagic(g, "slice", mSlice))
slice[0].typ = getSysType(g, n.info, tyInt) # fake type 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) fieldB.typ = getSysType(g, n.info, tyInt)
objType.addField(fieldB, g.cache) objType.addField(fieldB, g.cache, idgen)
if getMagic(n) == mSlice: if getMagic(n) == mSlice:
let a = genAddrOf(n[1]) let a = genAddrOf(n[1], idgen)
field.typ = a.typ 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, 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) 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, fieldA), n[2])
result.add newFastAsgnStmt(newDotExpr(scratchObj, fieldB), n[3]) 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), indirectAccess(castExpr, fieldA, n.info),
useShallowCopy=true) useShallowCopy=true)
slice[2] = threadLocal.newSymNode slice[2] = threadLocal.newSymNode
else: else:
let a = genAddrOf(n) let a = genAddrOf(n, idgen)
field.typ = a.typ 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, field), a)
result.add newFastAsgnStmt(newDotExpr(scratchObj, fieldB), genHigh(g, n)) 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: # the array itself does not need to go through a thread local variable:
slice[1] = genDeref(indirectAccess(castExpr, field, n.info)) 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), indirectAccess(castExpr, fieldB, n.info),
useShallowCopy=true) useShallowCopy=true)
slice[3] = threadLocal.newSymNode 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 elif (let size = computeSize(g.config, argType); size < 0 or size > 16) and
n.getRoot != nil: n.getRoot != nil:
# it is more efficient to pass a pointer instead: # it is more efficient to pass a pointer instead:
let a = genAddrOf(n) let a = genAddrOf(n, idgen)
field.typ = a.typ 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, 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), indirectAccess(castExpr, field, n.info),
useShallowCopy=true) useShallowCopy=true)
call.add(genDeref(threadLocal.newSymNode)) call.add(genDeref(threadLocal.newSymNode))
else: else:
# boring case # boring case
field.typ = argType field.typ = argType
objType.addField(field, g.cache) objType.addField(field, g.cache, idgen)
result.add newFastAsgnStmt(newDotExpr(scratchObj, field), n) result.add newFastAsgnStmt(newDotExpr(scratchObj, field), n)
let threadLocal = addLocalVar(g, varSection, varInit, let threadLocal = addLocalVar(g, varSection, varInit,
owner, field.typ, idgen, owner, field.typ,
indirectAccess(castExpr, field, n.info), indirectAccess(castExpr, field, n.info),
useShallowCopy=true) useShallowCopy=true)
call.add(threadLocal.newSymNode) 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 = barrier, dest: PNode = nil): PNode =
# if 'barrier' != nil, then it is in a 'parallel' section and we # if 'barrier' != nil, then it is in a 'parallel' section and we
# generate quite different code # generate quite different code
@ -330,9 +332,9 @@ proc wrapProcForSpawn*(g: ModuleGraph; owner: PSym; spawnExpr: PNode; retType: P
var fn = n[0] var fn = n[0]
let let
name = (if fn.kind == nkSym: fn.sym.name.s else: genPrefix) & "Wrapper" 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) wrapperProc = newSym(skProc, getIdent(g.cache, name), nextId idgen, owner, fn.info, g.config.options)
threadParam = newSym(skParam, getIdent(g.cache, "thread"), wrapperProc, n.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"), 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 wrapperProc.flags.incl sfInjectDestructors
block: block:
@ -341,11 +343,11 @@ proc wrapProcForSpawn*(g: ModuleGraph; owner: PSym; spawnExpr: PNode; retType: P
argsParam.typ = ptrType argsParam.typ = ptrType
argsParam.position = 1 argsParam.position = 1
var objType = createObj(g, owner, n.info) var objType = createObj(g, idgen, owner, n.info)
incl(objType.flags, tfFinal) 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: block:
scratchObj.typ = objType scratchObj.typ = objType
incl(scratchObj.flags, sfFromGeneric) incl(scratchObj.flags, sfFromGeneric)
@ -362,9 +364,9 @@ proc wrapProcForSpawn*(g: ModuleGraph; owner: PSym; spawnExpr: PNode; retType: P
skFunc, skMethod, skConverter}): skFunc, skMethod, skConverter}):
# for indirect calls we pass the function pointer in the scratchObj # for indirect calls we pass the function pointer in the scratchObj
var argType = n[0].typ.skipTypes(abstractInst) 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 field.typ = argType
objType.addField(field, g.cache) objType.addField(field, g.cache, idgen)
result.add newFastAsgnStmt(newDotExpr(scratchObj, field), n[0]) result.add newFastAsgnStmt(newDotExpr(scratchObj, field), n[0])
fn = indirectAccess(castExpr, field, n.info) fn = indirectAccess(castExpr, field, n.info)
elif fn.kind == nkSym and fn.sym.kind == skIterator: 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 varSection = newNodeI(nkVarSection, n.info)
var varInit = newNodeI(nkStmtList, n.info) var varInit = newNodeI(nkStmtList, n.info)
if barrier.isNil: if barrier.isNil:
setupArgsForConcurrency(g, n, objType, wrapperProc, scratchObj, castExpr, call, setupArgsForConcurrency(g, n, objType, idgen, wrapperProc, scratchObj, castExpr, call,
varSection, varInit, result) varSection, varInit, result)
else: else:
setupArgsForParallelism(g, n, objType, wrapperProc, scratchObj, castExpr, call, setupArgsForParallelism(g, n, objType, idgen, wrapperProc, scratchObj, castExpr, call,
varSection, varInit, result) varSection, varInit, result)
var barrierAsExpr: PNode = nil var barrierAsExpr: PNode = nil
if barrier != nil: if barrier != nil:
let typ = newType(tyPtr, owner) let typ = newType(tyPtr, nextId idgen, owner)
typ.rawAddSon(magicsys.getCompilerProc(g, "Barrier").typ) 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 field.typ = typ
objType.addField(field, g.cache) objType.addField(field, g.cache, idgen)
result.add newFastAsgnStmt(newDotExpr(scratchObj, field), barrier) result.add newFastAsgnStmt(newDotExpr(scratchObj, field), barrier)
barrierAsExpr = indirectAccess(castExpr, field, n.info) barrierAsExpr = indirectAccess(castExpr, field, n.info)
var fvField, fvAsExpr: PNode = nil var fvField, fvAsExpr: PNode = nil
if spawnKind == srFlowVar: 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 field.typ = retType
objType.addField(field, g.cache) objType.addField(field, g.cache, idgen)
fvField = newDotExpr(scratchObj, field) fvField = newDotExpr(scratchObj, field)
fvAsExpr = indirectAccess(castExpr, field, n.info) fvAsExpr = indirectAccess(castExpr, field, n.info)
# create flowVar: # create flowVar:
result.add newFastAsgnStmt(fvField, callProc(spawnExpr[^1])) result.add newFastAsgnStmt(fvField, callProc(spawnExpr[^1]))
if barrier == nil: if barrier == nil:
result.add callCodegenProc(g, "nimFlowVarCreateSemaphore", fvField.info, result.add callCodegenProc(g, "nimFlowVarCreateSemaphore", fvField.info, fvField)
fvField)
elif spawnKind == srByVar: elif spawnKind == srByVar:
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 = newType(tyPtr, objType.owner) field.typ = newType(tyPtr, nextId idgen, objType.owner)
field.typ.rawAddSon(retType) field.typ.rawAddSon(retType)
objType.addField(field, g.cache) objType.addField(field, g.cache, idgen)
fvAsExpr = indirectAccess(castExpr, field, n.info) 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, createWrapperProc(g, fn, threadParam, argsParam,
varSection, varInit, call, varSection, varInit, call,
barrierAsExpr, fvAsExpr, spawnKind, wrapperProc) barrierAsExpr, fvAsExpr, idgen, spawnKind, wrapperProc)
result.add callCodegenProc(g, "nimSpawn" & $spawnExpr.len, wrapperProc.info, 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 if spawnKind == srFlowVar: result.add fvField

View file

@ -24,7 +24,7 @@ import
lowerings, liftlocals, lowerings, liftlocals,
modulegraphs, lineinfos 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 import closureiters, lambdalifting
@ -40,7 +40,7 @@ type
# if we encounter the 2nd yield statement # if we encounter the 2nd yield statement
next: PTransCon # for stacking next: PTransCon # for stacking
TTransfContext = object of TPassContext TTransfContext = object
module: PSym module: PSym
transCon: PTransCon # top of a TransCon stack transCon: PTransCon # top of a TransCon stack
inlining: int # > 0 if we are in inlining context (copy vars) 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' contSyms, breakSyms: seq[PSym] # to transform 'continue' and 'break'
deferDetected, tooEarly: bool deferDetected, tooEarly: bool
graph: ModuleGraph graph: ModuleGraph
idgen: IdGenerator
PTransf = ref TTransfContext PTransf = ref TTransfContext
proc newTransNode(a: PNode): PNode {.inline.} = proc newTransNode(a: PNode): PNode {.inline.} =
@ -86,12 +87,12 @@ proc getCurrOwner(c: PTransf): PSym =
else: result = c.module else: result = c.module
proc newTemp(c: PTransf, typ: PType, info: TLineInfo): PNode = 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}) r.typ = typ #skipTypes(typ, {tyGenericInst, tyAlias, tySink})
incl(r.flags, sfFromGeneric) incl(r.flags, sfFromGeneric)
let owner = getCurrOwner(c) let owner = getCurrOwner(c)
if owner.isIterator and not c.tooEarly: if owner.isIterator and not c.tooEarly:
result = freshVarForClosureIter(c.graph, r, owner) result = freshVarForClosureIter(c.graph, r, c.idgen, owner)
else: else:
result = newSymNode(r) result = newSymNode(r)
@ -111,13 +112,13 @@ proc transformSymAux(c: PTransf, n: PNode): PNode =
let s = n.sym let s = n.sym
if s.typ != nil and s.typ.callConv == ccClosure: if s.typ != nil and s.typ.callConv == ccClosure:
if s.kind in routineKinds: if s.kind in routineKinds:
discard transformBody(c.graph, s, true) discard transformBody(c.graph, c.idgen, s, true)
if s.kind == skIterator: if s.kind == skIterator:
if c.tooEarly: return n 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: elif s.kind in {skProc, skFunc, skConverter, skMethod} and not c.tooEarly:
# top level .closure procs are still somewhat supported for 'Nake': # 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: #elif n.sym.kind in {skVar, skLet} and n.sym.typ.callConv == ccClosure:
# echo n.info, " come heer for ", c.tooEarly # echo n.info, " come heer for ", c.tooEarly
# if not c.tooEarly: # if not c.tooEarly:
@ -160,9 +161,9 @@ proc transformSym(c: PTransf, n: PNode): PNode =
proc freshVar(c: PTransf; v: PSym): PNode = proc freshVar(c: PTransf; v: PSym): PNode =
let owner = getCurrOwner(c) let owner = getCurrOwner(c)
if owner.isIterator and not c.tooEarly: if owner.isIterator and not c.tooEarly:
result = freshVarForClosureIter(c.graph, v, owner) result = freshVarForClosureIter(c.graph, v, c.idgen, owner)
else: else:
var newVar = copySym(v) var newVar = copySym(v, nextId(c.idgen))
incl(newVar.flags, sfFromGeneric) incl(newVar.flags, sfFromGeneric)
newVar.owner = owner newVar.owner = owner
result = newSymNode(newVar) result = newSymNode(newVar)
@ -232,7 +233,7 @@ proc hasContinue(n: PNode): bool =
if hasContinue(n[i]): return true if hasContinue(n[i]): return true
proc newLabel(c: PTransf, n: PNode): PSym = 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) result.name = getIdent(c.graph.cache, genPrefix)
proc transformBlock(c: PTransf, n: PNode): PNode = 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: if n.typ.skipTypes(abstractVar).kind != tyOpenArray:
result.typ = n.typ result.typ = n.typ
elif n.typ.skipTypes(abstractInst).kind in {tyVar}: 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: of nkHiddenStdConv, nkHiddenSubConv, nkConv:
var m = n[0][1] var m = n[0][1]
if m.kind == a or m.kind == b: 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: if n.typ.skipTypes(abstractVar).kind != tyOpenArray:
result.typ = n.typ result.typ = n.typ
elif n.typ.skipTypes(abstractInst).kind in {tyVar}: 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: else:
if n[0].kind == a or n[0].kind == b: if n[0].kind == a or n[0].kind == b:
# addr ( deref ( x )) --> x # addr ( deref ( x )) --> x
@ -495,7 +496,7 @@ proc transformConv(c: PTransf, n: PNode): PNode =
of tyOpenArray, tyVarargs: of tyOpenArray, tyVarargs:
result = transform(c, n[1]) result = transform(c, n[1])
#result = transformSons(c, n) #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), #echo n.info, " came here and produced ", typeToString(result.typ),
# " from ", typeToString(n.typ), " and ", typeToString(n[1].typ) # " from ", typeToString(n.typ), " and ", typeToString(n[1].typ)
of tyCString: of tyCString:
@ -629,7 +630,7 @@ proc transformFor(c: PTransf, n: PNode): PNode =
result[1] = n result[1] = n
result[1][^1] = transformLoopBody(c, n[^1]) result[1][^1] = transformLoopBody(c, n[^1])
result[1][^2] = transform(c, n[^2]) 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 discard c.breakSyms.pop
return result return result
@ -698,7 +699,7 @@ proc transformFor(c: PTransf, n: PNode): PNode =
stmtList.add(newAsgnStmt(c, nkFastAsgn, temp, arg)) stmtList.add(newAsgnStmt(c, nkFastAsgn, temp, arg))
idNodeTablePut(newC.mapping, formal, temp) 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) pushInfoContext(c.graph.config, n.info)
inc(c.inlining) inc(c.inlining)
stmtList.add(transform(c, body)) stmtList.add(transform(c, body))
@ -830,7 +831,7 @@ proc transformExceptBranch(c: PTransf, n: PNode): PNode =
let convNode = newTransNode(nkHiddenSubConv, n[1].info, 2) let convNode = newTransNode(nkHiddenSubConv, n[1].info, 2)
convNode[0] = newNodeI(nkEmpty, n.info) convNode[0] = newNodeI(nkEmpty, n.info)
convNode[1] = excCall convNode[1] = excCall
convNode.typ = excTypeNode.typ.toRef() convNode.typ = excTypeNode.typ.toRef(c.idgen)
# -> let exc = ... # -> let exc = ...
let identDefs = newTransNode(nkIdentDefs, n[1].info, 3) let identDefs = newTransNode(nkIdentDefs, n[1].info, 3)
identDefs[0] = n[0][2] identDefs[0] = n[0][2]
@ -850,10 +851,10 @@ proc transformExceptBranch(c: PTransf, n: PNode): PNode =
else: else:
result = transformSons(c, n) 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 result = n
for i in 0..<n.safeLen: 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) var op = getMergeOp(n)
if (op != nil) and (op.magic != mNone) and (n.len >= 3): if (op != nil) and (op.magic != mNone) and (n.len >= 3):
result = newNodeIT(nkCall, n.info, n.typ) result = newNodeIT(nkCall, n.info, n.typ)
@ -873,7 +874,7 @@ proc commonOptimizations*(g: ModuleGraph; c: PSym, n: PNode): PNode =
result.add(a) result.add(a)
if result.len == 2: result = result[1] if result.len == 2: result = result[1]
else: else:
var cnst = getConstExpr(c, n, g) var cnst = getConstExpr(c, n, idgen, g)
# we inline constants if they are not complex constants: # we inline constants if they are not complex constants:
if cnst != nil and not dontInlineConstant(n, cnst): if cnst != nil and not dontInlineConstant(n, cnst):
result = cnst result = cnst
@ -1012,7 +1013,7 @@ proc transform(c: PTransf, n: PNode): PNode =
n.typ != nil and n.typ != nil and
n.typ.kind == tyPointer n.typ.kind == tyPointer
if not exprIsPointerCast: 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: # we inline constants if they are not complex constants:
if cnst != nil and not dontInlineConstant(n, cnst): if cnst != nil and not dontInlineConstant(n, cnst):
result = cnst # do not miss an optimization result = cnst # do not miss an optimization
@ -1027,12 +1028,13 @@ proc processTransf(c: PTransf, n: PNode, owner: PSym): PNode =
popTransCon(c) popTransCon(c)
incl(result.flags, nfTransf) 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) new(result)
result.contSyms = @[] result.contSyms = @[]
result.breakSyms = @[] result.breakSyms = @[]
result.module = module result.module = module
result.graph = g result.graph = g
result.idgen = idgen
proc flattenStmts(n: PNode) = proc flattenStmts(n: PNode) =
var goOn = true var goOn = true
@ -1075,7 +1077,7 @@ template liftDefer(c, root) =
if c.deferDetected: if c.deferDetected:
liftDeferAux(root) 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 assert prc.kind in routineKinds
if prc.transformedBody != nil: if prc.transformedBody != nil:
@ -1084,14 +1086,14 @@ proc transformBody*(g: ModuleGraph, prc: PSym, cache: bool): PNode =
result = prc.ast[bodyPos] result = prc.ast[bodyPos]
else: else:
prc.transformedBody = newNode(nkEmpty) # protects from recursion prc.transformedBody = newNode(nkEmpty) # protects from recursion
var c = openTransf(g, prc.getModule, "") var c = openTransf(g, prc.getModule, "", idgen)
result = liftLambdas(g, prc, prc.ast[bodyPos], c.tooEarly) result = liftLambdas(g, prc, prc.ast[bodyPos], c.tooEarly, c.idgen)
result = processTransf(c, result, prc) result = processTransf(c, result, prc)
liftDefer(c, result) liftDefer(c, result)
result = liftLocalsIfRequested(prc, result, g.cache, g.config) result = liftLocalsIfRequested(prc, result, g.cache, g.config, c.idgen)
if prc.isIterator: if prc.isIterator:
result = g.transformClosureIterator(prc, result) result = g.transformClosureIterator(c.idgen, prc, result)
incl(result.flags, nfTransf) incl(result.flags, nfTransf)
@ -1105,21 +1107,21 @@ proc transformBody*(g: ModuleGraph, prc: PSym, cache: bool): PNode =
#if prc.name.s == "main": #if prc.name.s == "main":
# echo "transformed into ", renderTree(result, {renderIds}) # 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: if nfTransf in n.flags:
result = n result = n
else: else:
var c = openTransf(g, module, "") var c = openTransf(g, module, "", idgen)
result = processTransf(c, n, module) result = processTransf(c, n, module)
liftDefer(c, result) liftDefer(c, result)
#result = liftLambdasForTopLevel(module, result) #result = liftLambdasForTopLevel(module, result)
incl(result.flags, nfTransf) 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: if nfTransf in n.flags:
result = n result = n
else: else:
var c = openTransf(g, module, "") var c = openTransf(g, module, "", idgen)
result = processTransf(c, n, module) result = processTransf(c, n, module)
liftDefer(c, result) liftDefer(c, result)
# expressions are not to be injected with destructor calls as that # expressions are not to be injected with destructor calls as that

View file

@ -1296,11 +1296,11 @@ proc containsGenericTypeIter(t: PType, closure: RootRef): bool =
proc containsGenericType*(t: PType): bool = proc containsGenericType*(t: PType): bool =
result = iterOverType(t, containsGenericTypeIter, nil) result = iterOverType(t, containsGenericTypeIter, nil)
proc baseOfDistinct*(t: PType): PType = proc baseOfDistinct*(t: PType; idgen: IdGenerator): PType =
if t.kind == tyDistinct: if t.kind == tyDistinct:
result = t[0] result = t[0]
else: else:
result = copyType(t, t.owner, false) result = copyType(t, nextId idgen, t.owner)
var parent: PType = nil var parent: PType = nil
var it = result var it = result
while it.kind in {tyPtr, tyRef, tyOwned}: while it.kind in {tyPtr, tyRef, tyOwned}:
@ -1438,7 +1438,7 @@ proc isEmptyContainer*(t: PType): bool =
of tyGenericInst, tyAlias, tySink: result = isEmptyContainer(t.lastSon) of tyGenericInst, tyAlias, tySink: result = isEmptyContainer(t.lastSon)
else: result = false else: result = false
proc takeType*(formal, arg: PType): PType = proc takeType*(formal, arg: PType; idgen: IdGenerator): PType =
# param: openArray[string] = [] # param: openArray[string] = []
# [] is an array constructor of length 0 of type string! # [] is an array constructor of length 0 of type string!
if arg.kind == tyNil: if arg.kind == tyNil:
@ -1446,7 +1446,7 @@ proc takeType*(formal, arg: PType): PType =
result = formal result = formal
elif formal.kind in {tyOpenArray, tyVarargs, tySequence} and elif formal.kind in {tyOpenArray, tyVarargs, tySequence} and
arg.isEmptyContainer: 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] a[ord(arg.kind == tyArray)] = formal[0]
result = a result = a
elif formal.kind in {tyTuple, tySet} and arg.kind == formal.kind: elif formal.kind in {tyTuple, tySet} and arg.kind == formal.kind:
@ -1454,14 +1454,14 @@ proc takeType*(formal, arg: PType): PType =
else: else:
result = arg result = arg
proc skipHiddenSubConv*(n: PNode): PNode = proc skipHiddenSubConv*(n: PNode; idgen: IdGenerator): PNode =
if n.kind == nkHiddenSubConv: if n.kind == nkHiddenSubConv:
# param: openArray[string] = [] # param: openArray[string] = []
# [] is an array constructor of length 0 of type string! # [] is an array constructor of length 0 of type string!
let formal = n.typ let formal = n.typ
result = n[1] result = n[1]
let arg = result.typ let arg = result.typ
let dest = takeType(formal, arg) let dest = takeType(formal, arg, idgen)
if dest == arg and formal.kind != tyUntyped: if dest == arg and formal.kind != tyUntyped:
#echo n.info, " came here for ", formal.typeToString #echo n.info, " came here for ", formal.typeToString
result = n result = n

View file

@ -1105,7 +1105,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
let ast = a.sym.ast.shallowCopy let ast = a.sym.ast.shallowCopy
for i in 0..<a.sym.ast.len: for i in 0..<a.sym.ast.len:
ast[i] = a.sym.ast[i] 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() ast.copyTree()
of opcSymOwner: of opcSymOwner:
decodeB(rkNode) decodeB(rkNode)
@ -1233,7 +1233,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
let node = regs[rb+i].regToNode let node = regs[rb+i].regToNode
node.info = c.debug[pc] node.info = c.debug[pc]
macroCall.add(node) 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] if a.kind == nkStmtList and a.len == 1: a = a[0]
a.recSetFlagIsRef a.recSetFlagIsRef
ensureKind(rkNode) ensureKind(rkNode)
@ -1599,9 +1599,9 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
# getType opcode: # getType opcode:
ensureKind(rkNode) ensureKind(rkNode)
if regs[rb].kind == rkNode and regs[rb].node.typ != nil: 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: 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: else:
stackTrace(c, tos, pc, "node has no type") stackTrace(c, tos, pc, "node has no type")
of 1: of 1:
@ -1617,18 +1617,18 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
# getTypeInst opcode: # getTypeInst opcode:
ensureKind(rkNode) ensureKind(rkNode)
if regs[rb].kind == rkNode and regs[rb].node.typ != nil: 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: 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: else:
stackTrace(c, tos, pc, "node has no type") stackTrace(c, tos, pc, "node has no type")
else: else:
# getTypeImpl opcode: # getTypeImpl opcode:
ensureKind(rkNode) ensureKind(rkNode)
if regs[rb].kind == rkNode and regs[rb].node.typ != nil: 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: 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: else:
stackTrace(c, tos, pc, "node has no type") stackTrace(c, tos, pc, "node has no type")
of opcNGetSize: of opcNGetSize:
@ -1938,7 +1938,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
else: regs[rc].node.strVal else: regs[rc].node.strVal
if k < 0 or k > ord(high(TSymKind)): if k < 0 or k > ord(high(TSymKind)):
internalError(c.config, c.debug[pc], "request to create symbol of invalid kind") 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) incl(sym.flags, sfGenSym)
regs[ra].node = newSymNode(sym) regs[ra].node = newSymNode(sym)
regs[ra].node.flags.incl nfIsRef regs[ra].node.flags.incl nfIsRef
@ -2058,7 +2058,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
let rb = instr.regB let rb = instr.regB
inc pc inc pc
let typ = c.types[c.code[pc].regBx - wordExcess] 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: of opcMarshalStore:
decodeB(rkNode) decodeB(rkNode)
inc pc 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) "NimScript: attempt to call non-routine: " & sym.name.s)
proc evalStmt*(c: PCtx, n: PNode) = 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) let start = genStmt(c, n)
# execute new instructions; this redundant opcEof check saves us lots # execute new instructions; this redundant opcEof check saves us lots
# of allocations in 'execute': # of allocations in 'execute':
@ -2111,7 +2111,7 @@ proc evalStmt*(c: PCtx, n: PNode) =
discard execute(c, start) discard execute(c, start)
proc evalExpr*(c: PCtx, n: PNode): PNode = 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) let start = genExpr(c, n)
assert c.code[start].opcode != opcEof assert c.code[start].opcode != opcEof
result = execute(c, start) result = execute(c, start)
@ -2122,20 +2122,20 @@ proc getGlobalValue*(c: PCtx; s: PSym): PNode =
include vmops include vmops
proc setupGlobalCtx*(module: PSym; graph: ModuleGraph) = proc setupGlobalCtx*(module: PSym; graph: ModuleGraph; idgen: IdGenerator) =
if graph.vm.isNil: if graph.vm.isNil:
graph.vm = newCtx(module, graph.cache, graph) graph.vm = newCtx(module, graph.cache, graph, idgen)
registerAdditionalOps(PCtx graph.vm) registerAdditionalOps(PCtx graph.vm)
else: 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) #var c = newEvalContext(module, emRepl)
#c.features = {allowCast, allowInfiniteLoops} #c.features = {allowCast, allowInfiniteLoops}
#pushStackFrame(c, newStackFrame()) #pushStackFrame(c, newStackFrame())
# XXX produce a new 'globals' environment here: # XXX produce a new 'globals' environment here:
setupGlobalCtx(module, graph) setupGlobalCtx(module, graph, idgen)
result = PCtx graph.vm result = PCtx graph.vm
proc myProcess(c: PPassContext, n: PNode): PNode = proc myProcess(c: PPassContext, n: PNode): PNode =
@ -2149,16 +2149,16 @@ proc myProcess(c: PPassContext, n: PNode): PNode =
c.oldErrorCount = c.config.errorCounter c.oldErrorCount = c.config.errorCounter
proc myClose(graph: ModuleGraph; c: PPassContext, n: PNode): PNode = proc myClose(graph: ModuleGraph; c: PPassContext, n: PNode): PNode =
myProcess(c, n) result = myProcess(c, n)
const evalPass* = makePass(myOpen, myProcess, myClose) const evalPass* = makePass(myOpen, myProcess, myClose)
proc evalConstExprAux(module: PSym; proc evalConstExprAux(module: PSym; idgen: IdGenerator;
g: ModuleGraph; prc: PSym, n: PNode, g: ModuleGraph; prc: PSym, n: PNode,
mode: TEvalMode): PNode = mode: TEvalMode): PNode =
if g.config.errorCounter > 0: return n if g.config.errorCounter > 0: return n
let n = transformExpr(g, module, n) let n = transformExpr(g, idgen, module, n)
setupGlobalCtx(module, g) setupGlobalCtx(module, g, idgen)
var c = PCtx g.vm var c = PCtx g.vm
let oldMode = c.mode let oldMode = c.mode
c.mode = mode c.mode = mode
@ -2173,17 +2173,17 @@ proc evalConstExprAux(module: PSym;
if result.info.col < 0: result.info = n.info if result.info.col < 0: result.info = n.info
c.mode = oldMode c.mode = oldMode
proc evalConstExpr*(module: PSym; g: ModuleGraph; e: PNode): PNode = proc evalConstExpr*(module: PSym; idgen: IdGenerator; g: ModuleGraph; e: PNode): PNode =
result = evalConstExprAux(module, g, nil, e, emConst) result = evalConstExprAux(module, idgen, g, nil, e, emConst)
proc evalStaticExpr*(module: PSym; g: ModuleGraph; e: PNode, prc: PSym): PNode = proc evalStaticExpr*(module: PSym; idgen: IdGenerator; g: ModuleGraph; e: PNode, prc: PSym): PNode =
result = evalConstExprAux(module, g, prc, e, emStaticExpr) result = evalConstExprAux(module, idgen, g, prc, e, emStaticExpr)
proc evalStaticStmt*(module: PSym; g: ModuleGraph; e: PNode, prc: PSym) = proc evalStaticStmt*(module: PSym; idgen: IdGenerator; g: ModuleGraph; e: PNode, prc: PSym) =
discard evalConstExprAux(module, g, prc, e, emStaticStmt) discard evalConstExprAux(module, idgen, g, prc, e, emStaticStmt)
proc setupCompileTimeVar*(module: PSym; g: ModuleGraph; n: PNode) = proc setupCompileTimeVar*(module: PSym; idgen: IdGenerator; g: ModuleGraph; n: PNode) =
discard evalConstExprAux(module, g, nil, n, emStaticStmt) discard evalConstExprAux(module, idgen, g, nil, n, emStaticStmt)
proc prepareVMValue(arg: PNode): PNode = proc prepareVMValue(arg: PNode): PNode =
## strip nkExprColonExpr from tuple values recurively. That is how ## 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 # to prevent endless recursion in macro instantiation
const evalMacroLimit = 1000 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 = newNodeI(nkEmpty, n.info)
result.typ = newType(tyError, owner) result.typ = newType(tyError, nextId idgen, owner)
result.typ.flags.incl tfCheckedForDestructor 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 = 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 # XXX globalError() is ugly here, but I don't know a better solution for now
inc(g.config.evalMacroCounter) 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)" % [ globalError(g.config, n.info, "in call '$#' got $#, but expected $# argument(s)" % [
n.renderTree, $(n.safeLen-1), $(sym.typ.len-1)]) n.renderTree, $(n.safeLen-1), $(sym.typ.len-1)])
setupGlobalCtx(module, g) setupGlobalCtx(module, g, idgen)
var c = PCtx g.vm var c = PCtx g.vm
let oldMode = c.mode let oldMode = c.mode
c.mode = emStaticStmt c.mode = emStaticStmt

View file

@ -282,17 +282,18 @@ type
PEvalContext* = PCtx 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: @[], PCtx(code: @[], debug: @[],
globals: newNode(nkStmtListExpr), constants: newNode(nkStmtList), types: @[], globals: newNode(nkStmtListExpr), constants: newNode(nkStmtList), types: @[],
prc: PProc(blocks: @[]), module: module, loopIterations: g.config.maxLoopIterationsVM, prc: PProc(blocks: @[]), module: module, loopIterations: g.config.maxLoopIterationsVM,
comesFromHeuristic: unknownLineInfo, callbacks: @[], errorFlag: "", 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.module = module
c.prc = PProc(blocks: @[]) c.prc = PProc(blocks: @[])
c.loopIterations = c.config.maxLoopIterationsVM c.loopIterations = c.config.maxLoopIterationsVM
c.idgen = idgen
proc registerCallback*(c: PCtx; name: string; callback: VmCallback): int {.discardable.} = proc registerCallback*(c: PCtx; name: string; callback: VmCallback): int {.discardable.} =
result = c.callbacks.len result = c.callbacks.len

View file

@ -24,8 +24,9 @@ proc opSlurp*(file: string, info: TLineInfo, module: PSym; conf: ConfigRef): str
localError(conf, info, "cannot open file: " & file) localError(conf, info, "cannot open file: " & file)
result = "" result = ""
proc atomicTypeX(cache: IdentCache; name: string; m: TMagic; t: PType; info: TLineInfo): PNode = proc atomicTypeX(cache: IdentCache; name: string; m: TMagic; t: PType; info: TLineInfo;
let sym = newSym(skType, getIdent(cache, name), t.owner, info) idgen: IdGenerator): PNode =
let sym = newSym(skType, getIdent(cache, name), nextId(idgen), t.owner, info)
sym.magic = m sym.magic = m
sym.typ = t sym.typ = t
result = newSymNode(sym) result = newSymNode(sym)
@ -35,44 +36,46 @@ proc atomicTypeX(s: PSym; info: TLineInfo): PNode =
result = newSymNode(s) result = newSymNode(s)
result.info = info 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 inst=false; allowRecursionX=false): PNode
proc mapTypeToBracketX(cache: IdentCache; name: string; m: TMagic; t: PType; info: TLineInfo; proc mapTypeToBracketX(cache: IdentCache; name: string; m: TMagic; t: PType; info: TLineInfo;
idgen: IdGenerator;
inst=false): PNode = inst=false): PNode =
result = newNodeIT(nkBracketExpr, if t.n.isNil: info else: t.n.info, t) 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: for i in 0..<t.len:
if t[i] == nil: if t[i] == nil:
let void = atomicTypeX(cache, "void", mVoid, t, info) let void = atomicTypeX(cache, "void", mVoid, t, info, idgen)
void.typ = newType(tyVoid, t.owner) void.typ = newType(tyVoid, nextId(idgen), t.owner)
result.add void result.add void
else: 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: if n.kind == nkSym:
result = newNodeI(nkIdentDefs, n.info) result = newNodeI(nkIdentDefs, n.info)
result.add n # name 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 result.add newNodeI(nkEmpty, n.info) # no assigned value
else: else:
result = copyNode(n) result = copyNode(n)
for i in 0..<n.safeLen: 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; proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo;
idgen: IdGenerator;
inst=false; allowRecursionX=false): PNode = inst=false; allowRecursionX=false): PNode =
var allowRecursion = allowRecursionX 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 atomicType(s): untyped = atomicTypeX(s, info)
template mapTypeToAst(t,info): untyped = mapTypeToAstX(cache, t, info, inst) template mapTypeToAst(t,info): untyped = mapTypeToAstX(cache, t, info, idgen, inst)
template mapTypeToAstR(t,info): untyped = mapTypeToAstX(cache, t, info, inst, true) template mapTypeToAstR(t,info): untyped = mapTypeToAstX(cache, t, info, idgen, inst, true)
template mapTypeToAst(t,i,info): untyped = 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) else: newNodeI(nkEmpty, info)
template mapTypeToBracket(name, m, t, info): untyped = 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 = template newNodeX(kind): untyped =
newNodeIT(kind, if t.n.isNil: info else: t.n.info, t) newNodeIT(kind, if t.n.isNil: info else: t.n.info, t)
template newIdentDefs(n,t): untyped = template newIdentDefs(n,t): untyped =
@ -134,14 +137,14 @@ proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo;
for i in 1..<t.len-1: for i in 1..<t.len-1:
result.add mapTypeToAst(t[i], info) result.add mapTypeToAst(t[i], info)
else: else:
result = mapTypeToAstX(cache, t.lastSon, info, inst, allowRecursion) result = mapTypeToAstX(cache, t.lastSon, info, idgen, inst, allowRecursion)
of tyGenericBody: of tyGenericBody:
if inst: if inst:
result = mapTypeToAstR(t.lastSon, info) result = mapTypeToAstR(t.lastSon, info)
else: else:
result = mapTypeToAst(t.lastSon, info) result = mapTypeToAst(t.lastSon, info)
of tyAlias: of tyAlias:
result = mapTypeToAstX(cache, t.lastSon, info, inst, allowRecursion) result = mapTypeToAstX(cache, t.lastSon, info, idgen, inst, allowRecursion)
of tyOrdinal: of tyOrdinal:
result = mapTypeToAst(t.lastSon, info) result = mapTypeToAst(t.lastSon, info)
of tyDistinct: of tyDistinct:
@ -169,7 +172,7 @@ proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo;
nn.add mapTypeToAst(t[0], info) nn.add mapTypeToAst(t[0], info)
result.add nn result.add nn
if t.n.len > 0: if t.n.len > 0:
result.add objectNode(cache, t.n) result.add objectNode(cache, t.n, idgen)
else: else:
result.add newNodeI(nkEmpty, info) result.add newNodeI(nkEmpty, info)
else: else:
@ -298,15 +301,15 @@ proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo;
of tyOwned: result = mapTypeToBracket("owned", mBuiltinType, t, info) of tyOwned: result = mapTypeToBracket("owned", mBuiltinType, t, info)
of tyOptDeprecated: doAssert false of tyOptDeprecated: doAssert false
proc opMapTypeToAst*(cache: IdentCache; t: PType; info: TLineInfo): PNode = proc opMapTypeToAst*(cache: IdentCache; t: PType; info: TLineInfo; idgen: IdGenerator): PNode =
result = mapTypeToAstX(cache, t, info, inst=false, allowRecursionX=true) result = mapTypeToAstX(cache, t, info, idgen, inst=false, allowRecursionX=true)
# the "Inst" version includes generic parameters in the resulting type tree # the "Inst" version includes generic parameters in the resulting type tree
# and also tries to look like the corresponding Nim type declaration # and also tries to look like the corresponding Nim type declaration
proc opMapTypeInstToAst*(cache: IdentCache; t: PType; info: TLineInfo): PNode = proc opMapTypeInstToAst*(cache: IdentCache; t: PType; info: TLineInfo; idgen: IdGenerator): PNode =
result = mapTypeToAstX(cache, t, info, inst=true, allowRecursionX=false) result = mapTypeToAstX(cache, t, info, idgen, inst=true, allowRecursionX=false)
# the "Impl" version includes generic parameters in the resulting type tree # the "Impl" version includes generic parameters in the resulting type tree
# and also tries to look like the corresponding Nim type implementation # and also tries to look like the corresponding Nim type implementation
proc opMapTypeImplToAst*(cache: IdentCache; t: PType; info: TLineInfo): PNode = proc opMapTypeImplToAst*(cache: IdentCache; t: PType; info: TLineInfo; idgen: IdGenerator): PNode =
result = mapTypeToAstX(cache, t, info, inst=true, allowRecursionX=true) result = mapTypeToAstX(cache, t, info, idgen, inst=true, allowRecursionX=true)

View file

@ -1118,7 +1118,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
c.freeTemp(d) c.freeTemp(d)
of mSwap: of mSwap:
unused(c, n, dest) 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 mIsNil: genUnaryABC(c, n, dest, opcIsNil)
of mParseBiggestFloat: of mParseBiggestFloat:
if dest < 0: dest = c.getTemp(n.typ) if dest < 0: dest = c.getTemp(n.typ)
@ -1819,7 +1819,7 @@ proc genVarSection(c: PCtx; n: PNode) =
if a[i].kind == nkSym: if a[i].kind == nkSym:
if not a[i].sym.isGlobal: setSlot(c, a[i].sym) if not a[i].sym.isGlobal: setSlot(c, a[i].sym)
checkCanEval(c, a[i]) 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: elif a[0].kind == nkSym:
let s = a[0].sym let s = a[0].sym
checkCanEval(c, a[0]) checkCanEval(c, a[0])
@ -2235,7 +2235,7 @@ proc genProc(c: PCtx; s: PSym): int =
s.ast[miscPos] = x s.ast[miscPos] = x
# thanks to the jmp we can add top level statements easily and also nest # thanks to the jmp we can add top level statements easily and also nest
# procs easily: # 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) let procStart = c.xjmp(body, opcJmp, 0)
var p = PProc(blocks: @[], sym: s) var p = PProc(blocks: @[], sym: s)
let oldPrc = c.prc let oldPrc = c.prc

View file

@ -136,7 +136,8 @@ proc storeAny*(s: var string; t: PType; a: PNode; conf: ConfigRef) =
proc loadAny(p: var JsonParser, t: PType, proc loadAny(p: var JsonParser, t: PType,
tab: var Table[BiggestInt, PNode]; tab: var Table[BiggestInt, PNode];
cache: IdentCache; cache: IdentCache;
conf: ConfigRef): PNode = conf: ConfigRef;
idgen: IdGenerator): PNode =
case t.kind case t.kind
of tyNone: assert false of tyNone: assert false
of tyBool: of tyBool:
@ -170,7 +171,7 @@ proc loadAny(p: var JsonParser, t: PType,
next(p) next(p)
result = newNode(nkBracket) result = newNode(nkBracket)
while p.kind != jsonArrayEnd and p.kind != jsonEof: 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) if p.kind == jsonArrayEnd: next(p)
else: raiseParseErr(p, "']' end of array expected") else: raiseParseErr(p, "']' end of array expected")
of tySequence: of tySequence:
@ -182,7 +183,7 @@ proc loadAny(p: var JsonParser, t: PType,
next(p) next(p)
result = newNode(nkBracket) result = newNode(nkBracket)
while p.kind != jsonArrayEnd and p.kind != jsonEof: 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) if p.kind == jsonArrayEnd: next(p)
else: raiseParseErr(p, "") else: raiseParseErr(p, "")
else: else:
@ -198,7 +199,7 @@ proc loadAny(p: var JsonParser, t: PType,
next(p) next(p)
if i >= t.len: if i >= t.len:
raiseParseErr(p, "too many fields to tuple type " & typeToString(t)) 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 inc i
if p.kind == jsonObjectEnd: next(p) if p.kind == jsonObjectEnd: next(p)
else: raiseParseErr(p, "'}' end of object expected") else: raiseParseErr(p, "'}' end of object expected")
@ -219,8 +220,8 @@ proc loadAny(p: var JsonParser, t: PType,
if pos >= result.len: if pos >= result.len:
setLen(result.sons, pos + 1) setLen(result.sons, pos + 1)
let fieldNode = newNode(nkExprColonExpr) let fieldNode = newNode(nkExprColonExpr)
fieldNode.add newSymNode(newSym(skField, ident, nil, unknownLineInfo)) fieldNode.add newSymNode(newSym(skField, ident, nextId(idgen), nil, unknownLineInfo))
fieldNode.add loadAny(p, field.typ, tab, cache, conf) fieldNode.add loadAny(p, field.typ, tab, cache, conf, idgen)
result[pos] = fieldNode result[pos] = fieldNode
if p.kind == jsonObjectEnd: next(p) if p.kind == jsonObjectEnd: next(p)
else: raiseParseErr(p, "'}' end of object expected") else: raiseParseErr(p, "'}' end of object expected")
@ -229,7 +230,7 @@ proc loadAny(p: var JsonParser, t: PType,
next(p) next(p)
result = newNode(nkCurly) result = newNode(nkCurly)
while p.kind != jsonArrayEnd and p.kind != jsonEof: 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) next(p)
if p.kind == jsonArrayEnd: next(p) if p.kind == jsonArrayEnd: next(p)
else: raiseParseErr(p, "']' end of array expected") else: raiseParseErr(p, "']' end of array expected")
@ -248,7 +249,7 @@ proc loadAny(p: var JsonParser, t: PType,
if p.kind == jsonInt: if p.kind == jsonInt:
let idx = p.getInt let idx = p.getInt
next(p) next(p)
result = loadAny(p, t.lastSon, tab, cache, conf) result = loadAny(p, t.lastSon, tab, cache, conf, idgen)
tab[idx] = result tab[idx] = result
else: raiseParseErr(p, "index for ref type expected") else: raiseParseErr(p, "index for ref type expected")
if p.kind == jsonArrayEnd: next(p) if p.kind == jsonArrayEnd: next(p)
@ -276,14 +277,14 @@ proc loadAny(p: var JsonParser, t: PType,
return return
raiseParseErr(p, "float expected") raiseParseErr(p, "float expected")
of tyRange, tyGenericInst, tyAlias, tySink: of tyRange, tyGenericInst, tyAlias, tySink:
result = loadAny(p, t.lastSon, tab, cache, conf) result = loadAny(p, t.lastSon, tab, cache, conf, idgen)
else: else:
internalError conf, "cannot marshal at compile-time " & t.typeToString 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 tab = initTable[BiggestInt, PNode]()
var p: JsonParser var p: JsonParser
open(p, newStringStream(s), "unknown file") open(p, newStringStream(s), "unknown file")
next(p) next(p)
result = loadAny(p, t, tab, cache, conf) result = loadAny(p, t, tab, cache, conf, idgen)
close(p) close(p)

View file

@ -268,7 +268,7 @@ proc registerAdditionalOps*(c: PCtx) =
fn.typ.n[0][effectIndex] != nil: fn.typ.n[0][effectIndex] != nil:
var list = newNodeI(nkBracket, fn.info) var list = newNodeI(nkBracket, fn.info)
for e in fn.typ.n[0][effectIndex]: 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) setResult(a, list)
registerCallback c, "stdlib.effecttraits.getRaisesListImpl", proc (a: VmArgs) = registerCallback c, "stdlib.effecttraits.getRaisesListImpl", proc (a: VmArgs) =

View file

@ -82,7 +82,7 @@ iterator mitems*(a: var cstring): var char {.inline.} =
yield a[i] yield a[i]
inc(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``. ## Iterates over the values of the enum ``E``.
for v in low(E) .. high(E): for v in low(E) .. high(E):
yield v yield v