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

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

View file

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

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:
for i in 0..<n.len-2:
if n[i].kind != nkSym:
genStmts(p, lowerTupleUnpacking(p.module.g.graph, n, p.prc))
genStmts(p, lowerTupleUnpacking(p.module.g.graph, n, p.module.idgen, p.prc))
return
# check only the first son
@ -1525,7 +1525,7 @@ proc genCaseObjDiscMapping(p: BProc, e: PNode, t: PType, field: PSym; d: var TLo
theProc = p
break
if theProc == nil:
theProc = genCaseObjDiscMapping(t, field, e.info, p.module.g.graph)
theProc = genCaseObjDiscMapping(t, field, e.info, p.module.g.graph, p.module.idgen)
t.methods.add((ObjDiscMappingProcSlot, theProc))
var call = newNodeIT(nkCall, e.info, getSysType(p.module.g.graph, e.info, tyUInt8))
call.add newSymNode(theProc)

View file

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

View file

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

View file

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

View file

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

View file

@ -59,7 +59,7 @@ proc loadConfigsAndRunMainCommand*(self: NimProg, cache: IdentCache; conf: Confi
graph: ModuleGraph): bool =
if self.suggestMode:
conf.command = "nimsuggest"
loadConfigs(DefaultConfig, cache, conf) # load all config files
loadConfigs(DefaultConfig, cache, conf, graph.idgen) # load all config files
if not self.suggestMode:
let scriptFile = conf.projectFull.changeFileExt("nims")

View file

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

View file

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

View file

@ -1,16 +1,16 @@
import ast, idents, lineinfos, modulegraphs, magicsys
proc genEnumToStrProc*(t: PType; info: TLineInfo; g: ModuleGraph): PSym =
result = newSym(skProc, getIdent(g.cache, "$"), t.owner, info)
proc genEnumToStrProc*(t: PType; info: TLineInfo; g: ModuleGraph; idgen: IdGenerator): PSym =
result = newSym(skProc, getIdent(g.cache, "$"), nextId idgen, t.owner, info)
let dest = newSym(skParam, getIdent(g.cache, "e"), result, info)
let dest = newSym(skParam, getIdent(g.cache, "e"), nextId idgen, result, info)
dest.typ = t
let res = newSym(skResult, getIdent(g.cache, "result"), result, info)
let res = newSym(skResult, getIdent(g.cache, "result"), nextId idgen, result, info)
res.typ = getSysType(g, info, tyString)
result.typ = newType(tyProc, t.owner)
result.typ = newType(tyProc, nextId idgen, t.owner)
result.typ.n = newNodeI(nkFormalParams, info)
rawAddSon(result.typ, res.typ)
result.typ.n.add newNodeI(nkEffectList, info)
@ -62,16 +62,16 @@ proc searchObjCase(t: PType; field: PSym): PNode =
result = searchObjCase(t[0].skipTypes({tyAlias, tyGenericInst, tyRef, tyPtr}), field)
doAssert result != nil
proc genCaseObjDiscMapping*(t: PType; field: PSym; info: TLineInfo; g: ModuleGraph): PSym =
result = newSym(skProc, getIdent(g.cache, "objDiscMapping"), t.owner, info)
proc genCaseObjDiscMapping*(t: PType; field: PSym; info: TLineInfo; g: ModuleGraph; idgen: IdGenerator): PSym =
result = newSym(skProc, getIdent(g.cache, "objDiscMapping"), nextId idgen, t.owner, info)
let dest = newSym(skParam, getIdent(g.cache, "e"), result, info)
let dest = newSym(skParam, getIdent(g.cache, "e"), nextId idgen, result, info)
dest.typ = field.typ
let res = newSym(skResult, getIdent(g.cache, "result"), result, info)
let res = newSym(skResult, getIdent(g.cache, "result"), nextId idgen, result, info)
res.typ = getSysType(g, info, tyUInt8)
result.typ = newType(tyProc, t.owner)
result.typ = newType(tyProc, nextId idgen, t.owner)
result.typ.n = newNodeI(nkFormalParams, info)
rawAddSon(result.typ, res.typ)
result.typ.n.add newNodeI(nkEffectList, info)

View file

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

View file

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

View file

@ -86,9 +86,9 @@ proc hlo(c: PContext, n: PNode): PNode =
else:
result = fitNode(c, n.typ, result, n.info)
# optimization has been applied so check again:
result = commonOptimizations(c.graph, c.module, result)
result = commonOptimizations(c.graph, c.idgen, c.module, result)
result = hlo(c, result)
result = commonOptimizations(c.graph, c.module, result)
result = commonOptimizations(c.graph, c.idgen, c.module, result)
proc hloBody(c: PContext, n: PNode): PNode =
# fast exit:

View file

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

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")
elif n[1].ident.id != realModule.name.id:
# some misguided guy will write 'import abc.foo as foo' ...
result = createModuleAlias(realModule, n[1].ident, realModule.info,
result = createModuleAlias(realModule, nextId c.idgen, n[1].ident, realModule.info,
c.config.options)
proc myImportModule(c: PContext, n: PNode; importStmtResult: PNode): PSym =

View file

@ -40,6 +40,7 @@ type
inLoop, inSpawn: int
uninit: IntSet # set of uninit'ed vars
uninitComputed: bool
idgen: IdGenerator
ProcessMode = enum
normal
@ -61,7 +62,7 @@ template dbg(body) =
body
proc getTemp(c: var Con; s: var Scope; typ: PType; info: TLineInfo): PNode =
let sym = newSym(skTemp, getIdent(c.graph.cache, ":tmpD"), c.owner, info)
let sym = newSym(skTemp, getIdent(c.graph.cache, ":tmpD"), nextId c.idgen, c.owner, info)
sym.typ = typ
s.vars.add(sym)
result = newSymNode(sym)
@ -250,16 +251,16 @@ proc checkForErrorPragma(c: Con; t: PType; ri: PNode; opname: string) =
m.add c.owner.name.s
localError(c.graph.config, ri.info, errGenerated, m)
proc makePtrType(c: Con, baseType: PType): PType =
result = newType(tyPtr, c.owner)
addSonSkipIntLit(result, baseType)
proc makePtrType(c: var Con, baseType: PType): PType =
result = newType(tyPtr, nextId c.idgen, c.owner)
addSonSkipIntLit(result, baseType, c.idgen)
proc genOp(c: Con; op: PSym; dest: PNode): PNode =
proc genOp(c: var Con; op: PSym; dest: PNode): PNode =
let addrExp = newNodeIT(nkHiddenAddr, dest.info, makePtrType(c, dest.typ))
addrExp.add(dest)
result = newTree(nkCall, newSymNode(op), addrExp)
proc genOp(c: Con; t: PType; kind: TTypeAttachedOp; dest, ri: PNode): PNode =
proc genOp(c: var Con; t: PType; kind: TTypeAttachedOp; dest, ri: PNode): PNode =
var op = t.attachedOps[kind]
if op == nil or op.ast[genericParamsPos].kind != nkEmpty:
# give up and find the canonical type instead:
@ -280,7 +281,7 @@ proc genOp(c: Con; t: PType; kind: TTypeAttachedOp; dest, ri: PNode): PNode =
if sfError in op.flags: checkForErrorPragma(c, t, ri, AttachedOpToStr[kind])
c.genOp(op, dest)
proc genDestroy(c: Con; dest: PNode): PNode =
proc genDestroy(c: var Con; dest: PNode): PNode =
let t = dest.typ.skipTypes({tyGenericInst, tyAlias, tySink})
result = c.genOp(t, attachedDestructor, dest, nil)
@ -310,7 +311,7 @@ proc genSink(c: var Con; dest, ri: PNode, isDecl = false): PNode =
# and copyMem(dest, source). This is efficient.
result = newTree(nkStmtList, c.genDestroy(dest), newTree(nkFastAsgn, dest, ri))
proc genCopyNoCheck(c: Con; dest, ri: PNode): PNode =
proc genCopyNoCheck(c: var Con; dest, ri: PNode): PNode =
let t = dest.typ.skipTypes({tyGenericInst, tyAlias, tySink})
result = c.genOp(t, attachedAsgn, dest, ri)
@ -346,7 +347,7 @@ It is best to factor out piece of object that needs custom destructor into separ
return
# generate: if le != tmp: `=destroy`(le)
let branchDestructor = produceDestructorForDiscriminator(c.graph, objType, leDotExpr[1].sym, n.info)
let branchDestructor = produceDestructorForDiscriminator(c.graph, objType, leDotExpr[1].sym, n.info, c.idgen)
let cond = newNodeIT(nkInfix, n.info, getSysType(c.graph, unknownLineInfo, tyBool))
cond.add newSymNode(getMagicEqSymForType(c.graph, le.typ, n.info))
cond.add le
@ -377,7 +378,7 @@ proc destructiveMoveVar(n: PNode; c: var Con; s: var Scope): PNode =
else:
result = newNodeIT(nkStmtListExpr, n.info, n.typ)
var temp = newSym(skLet, getIdent(c.graph.cache, "blitTmp"), c.owner, n.info)
var temp = newSym(skLet, getIdent(c.graph.cache, "blitTmp"), nextId c.idgen, c.owner, n.info)
temp.typ = n.typ
var v = newNodeI(nkLetSection, n.info)
let tempAsNode = newSymNode(temp)
@ -799,7 +800,7 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode): PNode =
for it in n:
var ri = it[^1]
if it.kind == nkVarTuple and hasDestructor(c, ri.typ):
let x = lowerTupleUnpacking(c.graph, it, c.owner)
let x = lowerTupleUnpacking(c.graph, it, c.idgen, c.owner)
result.add p(x, c, s, consumed)
elif it.kind == nkIdentDefs and hasDestructor(c, it[0].typ) and not isCursor(it[0], c):
for j in 0..<it.len-2:
@ -1010,10 +1011,10 @@ proc injectDefaultCalls(n: PNode, c: var Con) =
for i in 0..<n.safeLen:
injectDefaultCalls(n[i], c)
proc injectDestructorCalls*(g: ModuleGraph; owner: PSym; n: PNode): PNode =
proc injectDestructorCalls*(g: ModuleGraph; idgen: IdGenerator; owner: PSym; n: PNode): PNode =
if sfGeneratedOp in owner.flags or (owner.kind == skIterator and isInlineIterator(owner.typ)):
return n
var c = Con(owner: owner, graph: g, g: constructCfg(owner, n))
var c = Con(owner: owner, graph: g, g: constructCfg(owner, n), idgen: idgen)
dbg:
echo "\n### ", owner.name.s, ":\nCFG:"
echoCfg(c.g)

View file

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

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

View file

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

View file

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

View file

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

View file

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

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 ri
proc lowerTupleUnpacking*(g: ModuleGraph; n: PNode; owner: PSym): PNode =
proc lowerTupleUnpacking*(g: ModuleGraph; n: PNode; idgen: IdGenerator; owner: PSym): PNode =
assert n.kind == nkVarTuple
let value = n.lastSon
result = newNodeI(nkStmtList, n.info)
var temp = newSym(skTemp, getIdent(g.cache, genPrefix), owner, value.info, g.config.options)
var temp = newSym(skTemp, getIdent(g.cache, genPrefix), nextId(idgen),
owner, value.info, g.config.options)
temp.typ = skipTypes(value.typ, abstractInst)
incl(temp.flags, sfFromGeneric)
@ -85,12 +86,13 @@ proc lowerTupleUnpacking*(g: ModuleGraph; n: PNode; owner: PSym): PNode =
if n[i].kind == nkSym: v.addVar(n[i], val)
else: result.add newAsgnStmt(n[i], val)
proc evalOnce*(g: ModuleGraph; value: PNode; owner: PSym): PNode =
proc evalOnce*(g: ModuleGraph; value: PNode; idgen: IdGenerator; owner: PSym): PNode =
## Turns (value) into (let tmp = value; tmp) so that 'value' can be re-used
## freely, multiple times. This is frequently required and such a builtin would also be
## handy to have in macros.nim. The value that can be reused is 'result.lastSon'!
result = newNodeIT(nkStmtListExpr, value.info, value.typ)
var temp = newSym(skTemp, getIdent(g.cache, genPrefix), owner, value.info, g.config.options)
var temp = newSym(skTemp, getIdent(g.cache, genPrefix), nextId(idgen),
owner, value.info, g.config.options)
temp.typ = skipTypes(value.typ, abstractInst)
incl(temp.flags, sfFromGeneric)
@ -111,11 +113,11 @@ proc newTupleAccessRaw*(tup: PNode, i: int): PNode =
proc newTryFinally*(body, final: PNode): PNode =
result = newTree(nkHiddenTryStmt, body, newTree(nkFinally, final))
proc lowerTupleUnpackingForAsgn*(g: ModuleGraph; n: PNode; owner: PSym): PNode =
proc lowerTupleUnpackingForAsgn*(g: ModuleGraph; n: PNode; idgen: IdGenerator; owner: PSym): PNode =
let value = n.lastSon
result = newNodeI(nkStmtList, n.info)
var temp = newSym(skTemp, getIdent(g.cache, "_"), owner, value.info, owner.options)
var temp = newSym(skTemp, getIdent(g.cache, "_"), nextId(idgen), owner, value.info, owner.options)
var v = newNodeI(nkLetSection, value.info)
let tempAsNode = newSymNode(temp) #newIdentNode(getIdent(genPrefix & $temp.id), value.info)
@ -130,10 +132,10 @@ proc lowerTupleUnpackingForAsgn*(g: ModuleGraph; n: PNode; owner: PSym): PNode =
for i in 0..<lhs.len:
result.add newAsgnStmt(lhs[i], newTupleAccessRaw(tempAsNode, i))
proc lowerSwap*(g: ModuleGraph; n: PNode; owner: PSym): PNode =
proc lowerSwap*(g: ModuleGraph; n: PNode; idgen: IdGenerator; owner: PSym): PNode =
result = newNodeI(nkStmtList, n.info)
# note: cannot use 'skTemp' here cause we really need the copy for the VM :-(
var temp = newSym(skVar, getIdent(g.cache, genPrefix), owner, n.info, owner.options)
var temp = newSym(skVar, getIdent(g.cache, genPrefix), nextId(idgen), owner, n.info, owner.options)
temp.typ = n[1].typ
incl(temp.flags, sfFromGeneric)
@ -150,8 +152,8 @@ proc lowerSwap*(g: ModuleGraph; n: PNode; owner: PSym): PNode =
result.add newFastAsgnStmt(n[1], n[2])
result.add newFastAsgnStmt(n[2], tempAsNode)
proc createObj*(g: ModuleGraph; owner: PSym, info: TLineInfo; final=true): PType =
result = newType(tyObject, owner)
proc createObj*(g: ModuleGraph; idgen: IdGenerator; owner: PSym, info: TLineInfo; final=true): PType =
result = newType(tyObject, nextId(idgen), owner)
if final:
rawAddSon(result, nil)
incl result.flags, tfFinal
@ -159,6 +161,7 @@ proc createObj*(g: ModuleGraph; owner: PSym, info: TLineInfo; final=true): PType
rawAddSon(result, getCompilerProc(g, "RootObj").typ)
result.n = newNodeI(nkRecList, info)
let s = newSym(skType, getIdent(g.cache, "Env_" & toFilename(g.config, info) & "_" & $owner.name.s),
nextId(idgen),
owner, info, owner.options)
incl s.flags, sfAnon
s.typ = result
@ -196,7 +199,7 @@ proc rawDirectAccess*(obj, field: PSym): PNode =
result.add newSymNode(field)
result.typ = field.typ
proc lookupInRecord(n: PNode, id: int): PSym =
proc lookupInRecord(n: PNode, id: ItemId): PSym =
result = nil
case n.kind
of nkRecList:
@ -214,16 +217,16 @@ proc lookupInRecord(n: PNode, id: int): PSym =
if result != nil: return
else: discard
of nkSym:
if n.sym.id == -abs(id): result = n.sym
if n.sym.itemId.module == id.module and n.sym.itemId.item == -abs(id.item): result = n.sym
else: discard
proc addField*(obj: PType; s: PSym; cache: IdentCache) =
proc addField*(obj: PType; s: PSym; cache: IdentCache; idgen: IdGenerator) =
# because of 'gensym' support, we have to mangle the name with its ID.
# This is hacky but the clean solution is much more complex than it looks.
var field = newSym(skField, getIdent(cache, s.name.s & $obj.n.len), s.owner, s.info,
s.options)
field.id = -s.id
let t = skipIntLit(s.typ)
var field = newSym(skField, getIdent(cache, s.name.s & $obj.n.len),
nextId(idgen), s.owner, s.info, s.options)
field.itemId = ItemId(module: s.itemId.module, item: -s.itemId.item)
let t = skipIntLit(s.typ, idgen)
field.typ = t
assert t.kind != tyTyped
propagateToOwner(obj, t)
@ -232,13 +235,13 @@ proc addField*(obj: PType; s: PSym; cache: IdentCache) =
obj.n.add newSymNode(field)
fieldCheck()
proc addUniqueField*(obj: PType; s: PSym; cache: IdentCache): PSym {.discardable.} =
result = lookupInRecord(obj.n, s.id)
proc addUniqueField*(obj: PType; s: PSym; cache: IdentCache; idgen: IdGenerator): PSym {.discardable.} =
result = lookupInRecord(obj.n, s.itemId)
if result == nil:
var field = newSym(skField, getIdent(cache, s.name.s & $obj.n.len), s.owner, s.info,
s.options)
field.id = -s.id
let t = skipIntLit(s.typ)
var field = newSym(skField, getIdent(cache, s.name.s & $obj.n.len), nextId(idgen),
s.owner, s.info, s.options)
field.itemId = ItemId(module: s.itemId.module, item: -s.itemId.item)
let t = skipIntLit(s.typ, idgen)
field.typ = t
assert t.kind != tyTyped
propagateToOwner(obj, t)
@ -248,13 +251,13 @@ proc addUniqueField*(obj: PType; s: PSym; cache: IdentCache): PSym {.discardable
proc newDotExpr*(obj, b: PSym): PNode =
result = newNodeI(nkDotExpr, obj.info)
let field = lookupInRecord(obj.typ.n, b.id)
let field = lookupInRecord(obj.typ.n, b.itemId)
assert field != nil, b.name.s
result.add newSymNode(obj)
result.add newSymNode(field)
result.typ = field.typ
proc indirectAccess*(a: PNode, b: int, info: TLineInfo): PNode =
proc indirectAccess*(a: PNode, b: ItemId, info: TLineInfo): PNode =
# returns a[].b as a node
var deref = newNodeI(nkHiddenDeref, info)
deref.typ = a.typ.skipTypes(abstractInst)[0]
@ -306,7 +309,7 @@ proc getFieldFromObj*(t: PType; v: PSym): PSym =
var t = t
while true:
assert t.kind == tyObject
result = lookupInRecord(t.n, v.id)
result = lookupInRecord(t.n, v.itemId)
if result != nil: break
t = t[0]
if t == nil: break
@ -314,15 +317,15 @@ proc getFieldFromObj*(t: PType; v: PSym): PSym =
proc indirectAccess*(a: PNode, b: PSym, info: TLineInfo): PNode =
# returns a[].b as a node
result = indirectAccess(a, b.id, info)
result = indirectAccess(a, b.itemId, info)
proc indirectAccess*(a, b: PSym, info: TLineInfo): PNode =
result = indirectAccess(newSymNode(a), b, info)
proc genAddrOf*(n: PNode, typeKind = tyPtr): PNode =
proc genAddrOf*(n: PNode; idgen: IdGenerator; typeKind = tyPtr): PNode =
result = newNodeI(nkAddr, n.info, 1)
result[0] = n
result.typ = newType(typeKind, n.typ.owner)
result.typ = newType(typeKind, nextId(idgen), n.typ.owner)
result.typ.rawAddSon(n.typ)
proc genDeref*(n: PNode; k = nkHiddenDeref): PNode =

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -121,7 +121,7 @@ proc pragmaEnsures(c: PContext, n: PNode) =
openScope(c)
let o = getCurrOwner(c)
if o.kind in routineKinds and o.typ != nil and o.typ.sons[0] != nil:
var s = newSym(skResult, getIdent(c.cache, "result"), o, n.info)
var s = newSym(skResult, getIdent(c.cache, "result"), nextId(c.idgen), o, n.info)
s.typ = o.typ.sons[0]
incl(s.flags, sfUsed)
addDecl(c, s)
@ -636,7 +636,7 @@ proc processPragma(c: PContext, n: PNode, i: int) =
elif it.safeLen != 2 or it[0].kind != nkIdent or it[1].kind != nkIdent:
invalidPragma(c, n)
var userPragma = newSym(skTemplate, it[1].ident, nil, it.info, c.config.options)
var userPragma = newSym(skTemplate, it[1].ident, nextId(c.idgen), nil, it.info, c.config.options)
userPragma.ast = newTreeI(nkPragma, n.info, n.sons[i+1..^1])
strTableAdd(c.userPragmas, userPragma)
@ -717,7 +717,7 @@ proc deprecatedStmt(c: PContext; outerPragma: PNode) =
if dest == nil or dest.kind in routineKinds:
localError(c.config, n.info, warnUser, "the .deprecated pragma is unreliable for routines")
let src = considerQuotedIdent(c, n[0])
let alias = newSym(skAlias, src, dest, n[0].info, c.config.options)
let alias = newSym(skAlias, src, nextId(c.idgen), dest, n[0].info, c.config.options)
incl(alias.flags, sfExported)
if sfCompilerProc in dest.flags: markCompilerProc(c, alias)
addInterfaceDecl(c, alias)
@ -739,7 +739,7 @@ proc pragmaGuard(c: PContext; it: PNode; kind: TSymKind): PSym =
# We return a dummy symbol; later passes over the type will repair it.
# Generic instantiation needs to know about this too. But we're lazy
# and perform the lookup on demand instead.
result = newSym(skUnknown, considerQuotedIdent(c, n), nil, n.info,
result = newSym(skUnknown, considerQuotedIdent(c, n), nextId(c.idgen), nil, n.info,
c.config.options)
else:
result = qualifiedLookUp(c, n, {checkUndeclared})

View file

@ -9,14 +9,14 @@
## This module implements the canonalization for the various caching mechanisms.
import ast, idgen, lineinfos, incremental, modulegraphs, pathutils
import ast, lineinfos, incremental, modulegraphs, pathutils
when not nimIncremental:
template setupModuleCache*(g: ModuleGraph) = discard
template storeNode*(g: ModuleGraph; module: PSym; n: PNode) = discard
template loadNode*(g: ModuleGraph; module: PSym): PNode = newNode(nkStmtList)
proc loadModuleSym*(g: ModuleGraph; fileIdx: FileIndex; fullpath: AbsoluteFile): (PSym, int) {.inline.} = (nil, getID())
proc loadModuleSym*(g: ModuleGraph; fileIdx: FileIndex; fullpath: AbsoluteFile): (PSym) {.inline.} = nil
template addModuleDep*(g: ModuleGraph; module, fileIdx: FileIndex; isIncludeFile: bool) = discard

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 statics where module = ?", module[0])
proc loadModuleSym*(g: ModuleGraph; fileIdx: FileIndex; fullpath: AbsoluteFile): (PSym, int) =
proc loadModuleSym*(g: ModuleGraph; fileIdx: FileIndex; fullpath: AbsoluteFile): PSym =
let id = getModuleId(g, fileIdx, fullpath)
result = (g.incr.r.syms.getOrDefault(abs id), id)
result = g.incr.r.syms.getOrDefault(abs id)
proc pushType(w: var Writer, t: PType) =
if not containsOrIncl(w.tmarks, t.uniqueId):

View file

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

View file

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

View file

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

View file

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

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

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"))
if trueSymbol == nil:
localError(c.config, n.info, "system needs: 'true'")
trueSymbol = newSym(skUnknown, getIdent(c.cache, "true"), getCurrOwner(c), n.info)
trueSymbol = newSym(skUnknown, getIdent(c.cache, "true"), nextId c.idgen, getCurrOwner(c), n.info)
trueSymbol.typ = getSysType(c.graph, n.info, tyBool)
result[0] = newSymNode(trueSymbol, n.info)

View file

@ -17,7 +17,7 @@ import
proc errorType*(g: ModuleGraph): PType =
## creates a type representing an error state
result = newType(tyError, g.owners[^1])
result = newType(tyError, nextId(g.idgen), g.owners[^1])
result.flags.incl tfCheckedForDestructor
proc newIntNodeT*(intVal: Int128, n: PNode; g: ModuleGraph): PNode =
@ -42,7 +42,7 @@ proc newStrNodeT*(strVal: string, n: PNode; g: ModuleGraph): PNode =
result.typ = n.typ
result.info = n.info
proc getConstExpr*(m: PSym, n: PNode; g: ModuleGraph): PNode
proc getConstExpr*(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode
# evaluates the constant expression or returns nil if it is no constant
# expression
proc evalOp*(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode
@ -113,45 +113,6 @@ proc pickIntRange(a, b: PType): PType =
proc isIntRangeOrLit(t: PType): bool =
result = isIntRange(t) or isIntLit(t)
proc makeRange(typ: PType, first, last: BiggestInt; g: ModuleGraph): PType =
let minA = min(first, last)
let maxA = max(first, last)
let lowerNode = newIntNode(nkIntLit, minA)
if typ.kind == tyInt and minA == maxA:
result = getIntLitType(g, lowerNode)
elif typ.kind in {tyUInt, tyUInt64}:
# these are not ordinal types, so you get no subrange type for these:
result = typ
else:
var n = newNode(nkRange)
n.add lowerNode
n.add newIntNode(nkIntLit, maxA)
result = newType(tyRange, typ.owner)
result.n = n
addSonSkipIntLit(result, skipTypes(typ, {tyRange}))
proc makeRangeF(typ: PType, first, last: BiggestFloat; g: ModuleGraph): PType =
var n = newNode(nkRange)
n.add newFloatNode(nkFloatLit, min(first.float, last.float))
n.add newFloatNode(nkFloatLit, max(first.float, last.float))
result = newType(tyRange, typ.owner)
result.n = n
addSonSkipIntLit(result, skipTypes(typ, {tyRange}))
proc fitLiteral(c: ConfigRef, n: PNode): PNode {.deprecated: "no substitute".} =
# Trim the literal value in order to make it fit in the destination type
if n == nil:
# `n` may be nil if the overflow check kicks in
return
doAssert n.kind in {nkIntLit, nkCharLit}
result = n
let typ = n.typ.skipTypes(abstractRange)
if typ.kind in tyUInt..tyUInt32:
result.intVal = result.intVal and castToInt64(lastOrd(c, typ))
proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode =
# b and c may be nil
result = nil
@ -342,19 +303,19 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode =
exprStructuralEquivalent(a, b, strictSymEquality=true))), n, g)
else: discard
proc getConstIfExpr(c: PSym, n: PNode; g: ModuleGraph): PNode =
proc getConstIfExpr(c: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode =
result = nil
for i in 0..<n.len:
var it = n[i]
if it.len == 2:
var e = getConstExpr(c, it[0], g)
var e = getConstExpr(c, it[0], idgen, g)
if e == nil: return nil
if getOrdValue(e) != 0:
if result == nil:
result = getConstExpr(c, it[1], g)
result = getConstExpr(c, it[1], idgen, g)
if result == nil: return
elif it.len == 1:
if result == nil: result = getConstExpr(c, it[0], g)
if result == nil: result = getConstExpr(c, it[0], idgen, g)
else: internalError(g.config, it.info, "getConstIfExpr()")
proc leValueConv*(a, b: PNode): bool =
@ -372,18 +333,18 @@ proc leValueConv*(a, b: PNode): bool =
else: result = false # internalError(a.info, "leValueConv")
else: result = false # internalError(a.info, "leValueConv")
proc magicCall(m: PSym, n: PNode; g: ModuleGraph): PNode =
proc magicCall(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode =
if n.len <= 1: return
var s = n[0].sym
var a = getConstExpr(m, n[1], g)
var a = getConstExpr(m, n[1], idgen, g)
var b, c: PNode
if a == nil: return
if n.len > 2:
b = getConstExpr(m, n[2], g)
b = getConstExpr(m, n[2], idgen, g)
if b == nil: return
if n.len > 3:
c = getConstExpr(m, n[3], g)
c = getConstExpr(m, n[3], idgen, g)
if c == nil: return
result = evalOp(s.magic, n, a, b, c, g)
@ -451,19 +412,19 @@ proc foldConv(n, a: PNode; g: ModuleGraph; check = false): PNode =
result = a
result.typ = n.typ
proc getArrayConstr(m: PSym, n: PNode; g: ModuleGraph): PNode =
proc getArrayConstr(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode =
if n.kind == nkBracket:
result = n
else:
result = getConstExpr(m, n, g)
result = getConstExpr(m, n, idgen, g)
if result == nil: result = n
proc foldArrayAccess(m: PSym, n: PNode; g: ModuleGraph): PNode =
var x = getConstExpr(m, n[0], g)
proc foldArrayAccess(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode =
var x = getConstExpr(m, n[0], idgen, g)
if x == nil or x.typ.skipTypes({tyGenericInst, tyAlias, tySink}).kind == tyTypeDesc:
return
var y = getConstExpr(m, n[1], g)
var y = getConstExpr(m, n[1], idgen, g)
if y == nil: return
var idx = toInt64(getOrdValue(y))
@ -486,9 +447,9 @@ proc foldArrayAccess(m: PSym, n: PNode; g: ModuleGraph): PNode =
localError(g.config, n.info, formatErrorIndexBound(idx, x.strVal.len-1) & $n)
else: discard
proc foldFieldAccess(m: PSym, n: PNode; g: ModuleGraph): PNode =
proc foldFieldAccess(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode =
# a real field access; proc calls have already been transformed
var x = getConstExpr(m, n[0], g)
var x = getConstExpr(m, n[0], idgen, g)
if x == nil or x.kind notin {nkObjConstr, nkPar, nkTupleConstr}: return
var field = n[1].sym
@ -504,23 +465,23 @@ proc foldFieldAccess(m: PSym, n: PNode; g: ModuleGraph): PNode =
return
localError(g.config, n.info, "field not found: " & field.name.s)
proc foldConStrStr(m: PSym, n: PNode; g: ModuleGraph): PNode =
proc foldConStrStr(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode =
result = newNodeIT(nkStrLit, n.info, n.typ)
result.strVal = ""
for i in 1..<n.len:
let a = getConstExpr(m, n[i], g)
let a = getConstExpr(m, n[i], idgen, g)
if a == nil: return nil
result.strVal.add(getStrOrChar(a))
proc newSymNodeTypeDesc*(s: PSym; info: TLineInfo): PNode =
proc newSymNodeTypeDesc*(s: PSym; idgen: IdGenerator; info: TLineInfo): PNode =
result = newSymNode(s, info)
if s.typ.kind != tyTypeDesc:
result.typ = newType(tyTypeDesc, s.owner)
result.typ.addSonSkipIntLit(s.typ)
result.typ = newType(tyTypeDesc, idgen.nextId, s.owner)
result.typ.addSonSkipIntLit(s.typ, idgen)
else:
result.typ = s.typ
proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode =
proc getConstExpr(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode =
result = nil
case n.kind
of nkSym:
@ -570,12 +531,12 @@ proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode =
result = n
of skParam:
if s.typ != nil and s.typ.kind == tyTypeDesc:
result = newSymNodeTypeDesc(s, n.info)
result = newSymNodeTypeDesc(s, idgen, n.info)
of skType:
# XXX gensym'ed symbols can come here and cannot be resolved. This is
# dirty, but correct.
if s.typ != nil:
result = newSymNodeTypeDesc(s, n.info)
result = newSymNodeTypeDesc(s, idgen, n.info)
of skGenericParam:
if s.typ.kind == tyStatic:
if s.typ.n != nil and tfUnresolved notin s.typ.flags:
@ -584,12 +545,12 @@ proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode =
elif s.typ.isIntLit:
result = s.typ.n
else:
result = newSymNodeTypeDesc(s, n.info)
result = newSymNodeTypeDesc(s, idgen, n.info)
else: discard
of nkCharLit..nkNilLit:
result = copyNode(n)
of nkIfExpr:
result = getConstIfExpr(m, n, g)
result = getConstIfExpr(m, n, idgen, g)
of nkCallKinds:
if n[0].kind != nkSym: return
var s = n[0].sym
@ -612,17 +573,17 @@ proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode =
else:
result = newIntNodeT(lastOrd(g.config, skipTypes(n[1].typ, abstractVar)), n, g)
else:
var a = getArrayConstr(m, n[1], g)
var a = getArrayConstr(m, n[1], idgen, g)
if a.kind == nkBracket:
# we can optimize it away:
result = newIntNodeT(toInt128(a.len-1), n, g)
of mLengthOpenArray:
var a = getArrayConstr(m, n[1], g)
var a = getArrayConstr(m, n[1], idgen, g)
if a.kind == nkBracket:
# we can optimize it away! This fixes the bug ``len(134)``.
result = newIntNodeT(toInt128(a.len), n, g)
else:
result = magicCall(m, n, g)
result = magicCall(m, n, idgen, g)
of mLengthArray:
# It doesn't matter if the argument is const or not for mLengthArray.
# This fixes bug #544.
@ -636,33 +597,33 @@ proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode =
of mAstToStr:
result = newStrNodeT(renderTree(n[1], {renderNoComments}), n, g)
of mConStrStr:
result = foldConStrStr(m, n, g)
result = foldConStrStr(m, n, idgen, g)
of mIs:
# The only kind of mIs node that comes here is one depending on some
# generic parameter and that's (hopefully) handled at instantiation time
discard
else:
result = magicCall(m, n, g)
result = magicCall(m, n, idgen, g)
except OverflowDefect:
localError(g.config, n.info, "over- or underflow")
except DivByZeroDefect:
localError(g.config, n.info, "division by zero")
of nkAddr:
var a = getConstExpr(m, n[0], g)
var a = getConstExpr(m, n[0], idgen, g)
if a != nil:
result = n
n[0] = a
of nkBracket, nkCurly:
result = copyNode(n)
for i, son in n.pairs:
var a = getConstExpr(m, son, g)
var a = getConstExpr(m, son, idgen, g)
if a == nil: return nil
result.add a
incl(result.flags, nfAllConst)
of nkRange:
var a = getConstExpr(m, n[0], g)
var a = getConstExpr(m, n[0], idgen, g)
if a == nil: return
var b = getConstExpr(m, n[1], g)
var b = getConstExpr(m, n[1], idgen, g)
if b == nil: return
result = copyNode(n)
result.add a
@ -681,18 +642,18 @@ proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode =
for i, expr in n.pairs:
let exprNew = copyNode(expr) # nkExprColonExpr
exprNew.add expr[0]
let a = getConstExpr(m, expr[1], g)
let a = getConstExpr(m, expr[1], idgen, g)
if a == nil: return nil
exprNew.add a
result.add exprNew
else:
for i, expr in n.pairs:
let a = getConstExpr(m, expr, g)
let a = getConstExpr(m, expr, idgen, g)
if a == nil: return nil
result.add a
incl(result.flags, nfAllConst)
of nkChckRangeF, nkChckRange64, nkChckRange:
var a = getConstExpr(m, n[0], g)
var a = getConstExpr(m, n[0], idgen, g)
if a == nil: return
if leValueConv(n[1], a) and leValueConv(a, n[2]):
result = a # a <= x and x <= b
@ -702,31 +663,31 @@ proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode =
"conversion from $1 to $2 is invalid" %
[typeToString(n[0].typ), typeToString(n.typ)])
of nkStringToCString, nkCStringToString:
var a = getConstExpr(m, n[0], g)
var a = getConstExpr(m, n[0], idgen, g)
if a == nil: return
result = a
result.typ = n.typ
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
var a = getConstExpr(m, n[1], g)
var a = getConstExpr(m, n[1], idgen, g)
if a == nil: return
result = foldConv(n, a, g, check=true)
of nkCast:
var a = getConstExpr(m, n[1], g)
var a = getConstExpr(m, n[1], idgen, g)
if a == nil: return
if n.typ != nil and n.typ.kind in NilableTypes:
# we allow compile-time 'cast' for pointer types:
result = a
result.typ = n.typ
of nkBracketExpr: result = foldArrayAccess(m, n, g)
of nkDotExpr: result = foldFieldAccess(m, n, g)
of nkBracketExpr: result = foldArrayAccess(m, n, idgen, g)
of nkDotExpr: result = foldFieldAccess(m, n, idgen, g)
of nkCheckedFieldExpr:
result = foldFieldAccess(m, n[0], g)
result = foldFieldAccess(m, n[0], idgen, g)
of nkStmtListExpr:
var i = 0
while i <= n.len - 2:
if n[i].kind in {nkComesFrom, nkCommentStmt, nkEmpty}: i.inc
else: break
if i == n.len - 1:
result = getConstExpr(m, n[i], g)
result = getConstExpr(m, n[i], idgen, g)
else:
discard

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -176,7 +176,7 @@ proc onlyReplaceParams(c: var TemplCtx, n: PNode): PNode =
result[i] = onlyReplaceParams(c, n[i])
proc newGenSym(kind: TSymKind, n: PNode, c: var TemplCtx): PSym =
result = newSym(kind, considerQuotedIdent(c.c, n), c.owner, n.info)
result = newSym(kind, considerQuotedIdent(c.c, n), nextId c.c.idgen, c.owner, n.info)
incl(result.flags, sfGenSym)
incl(result.flags, sfShadowed)
@ -239,12 +239,12 @@ proc semTemplSymbol(c: PContext, n: PNode, s: PSym; isField: bool): PNode =
result = symChoice(c, n, s, scOpen, isField)
of skGenericParam:
if isField and sfGenSym in s.flags: result = n
else: result = newSymNodeTypeDesc(s, n.info)
else: result = newSymNodeTypeDesc(s, c.idgen, n.info)
of skParam:
result = n
of skType:
if isField and sfGenSym in s.flags: result = n
else: result = newSymNodeTypeDesc(s, n.info)
else: result = newSymNodeTypeDesc(s, c.idgen, n.info)
else:
if isField and sfGenSym in s.flags: result = n
else: result = newSymNode(s, n.info)

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -282,17 +282,18 @@ type
PEvalContext* = PCtx
proc newCtx*(module: PSym; cache: IdentCache; g: ModuleGraph): PCtx =
proc newCtx*(module: PSym; cache: IdentCache; g: ModuleGraph; idgen: IdGenerator): PCtx =
PCtx(code: @[], debug: @[],
globals: newNode(nkStmtListExpr), constants: newNode(nkStmtList), types: @[],
prc: PProc(blocks: @[]), module: module, loopIterations: g.config.maxLoopIterationsVM,
comesFromHeuristic: unknownLineInfo, callbacks: @[], errorFlag: "",
cache: cache, config: g.config, graph: g)
cache: cache, config: g.config, graph: g, idgen: idgen)
proc refresh*(c: PCtx, module: PSym) =
proc refresh*(c: PCtx, module: PSym; idgen: IdGenerator) =
c.module = module
c.prc = PProc(blocks: @[])
c.loopIterations = c.config.maxLoopIterationsVM
c.idgen = idgen
proc registerCallback*(c: PCtx; name: string; callback: VmCallback): int {.discardable.} =
result = c.callbacks.len

View file

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

View file

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

View file

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

View file

@ -268,7 +268,7 @@ proc registerAdditionalOps*(c: PCtx) =
fn.typ.n[0][effectIndex] != nil:
var list = newNodeI(nkBracket, fn.info)
for e in fn.typ.n[0][effectIndex]:
list.add opMapTypeInstToAst(c.cache, e.typ.skipTypes({tyRef}), e.info)
list.add opMapTypeInstToAst(c.cache, e.typ.skipTypes({tyRef}), e.info, c.idgen)
setResult(a, list)
registerCallback c, "stdlib.effecttraits.getRaisesListImpl", proc (a: VmArgs) =

View file

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