Skip to content
58 changes: 46 additions & 12 deletions compiler/ast.nim
Original file line number Diff line number Diff line change
Expand Up @@ -545,18 +545,28 @@ proc addAllowNil*(father, son: PNode) {.inline.} =
father.sons.add(son)

proc add*(father, son: PType) =
assert father.kind != tyProc or father.sonsImpl.len == 0
assert son != nil
father.sonsImpl.add son

proc addAllowNil*(father, son: PType) {.inline.} =
assert father.kind != tyProc or father.sonsImpl.len == 0
father.sonsImpl.add son

template `[]`*(n: PType, i: int): PType =
if n.state == Partial: loadType(n)
n.sonsImpl[i]
if n.kind == tyProc and i > 0:
assert n.nImpl[i] != nil and n.nImpl[i].sym != nil
n.nImpl[i].sym.typ
else:
n.sonsImpl[i]
template `[]=`*(n: PType, i: int; x: PType) =
if n.state == Partial: loadType(n)
n.sonsImpl[i] = x
if n.kind == tyProc and i > 0:
assert n.nImpl[i] != nil and n.nImpl[i].sym != nil
n.nImpl[i].sym.typ = x
else:
n.sonsImpl[i] = x

template `[]`*(n: PType, i: BackwardsIndex): PType =
if n.state == Partial: loadType(n)
Expand Down Expand Up @@ -802,7 +812,10 @@ proc replaceSon*(n: PNode; i: int; newson: PNode) {.inline.} =

proc last*(n: PType): PType {.inline.} =
if n.state == Partial: loadType(n)
n.sonsImpl[^1]
if n.kind == tyProc and n.nImpl.len > 1:
n.nImpl[^1].sym.typ
else:
n.sonsImpl[^1]

proc elementType*(n: PType): PType {.inline.} =
if n.state == Partial: loadType(n)
Expand Down Expand Up @@ -838,7 +851,10 @@ proc setIndexType*(n, idx: PType) {.inline.} =

proc firstParamType*(n: PType): PType {.inline.} =
if n.state == Partial: loadType(n)
n.sonsImpl[1]
if n.kind == tyProc:
n.nImpl[1].sym.typ
else:
n.sonsImpl[1]

proc firstGenericParam*(n: PType): PType {.inline.} =
if n.state == Partial: loadType(n)
Expand Down Expand Up @@ -910,10 +926,13 @@ proc `$`*(s: PSym): string =
result = "<nil>"

proc len*(n: PType): int {.inline.} =
result = n.sonsImpl.len
if n.kind == tyProc:
result = if n.nImpl == nil: 0 else: n.nImpl.len
else:
result = n.sonsImpl.len

proc sameTupleLengths*(a, b: PType): bool {.inline.} =
result = a.sonsImpl.len == b.sonsImpl.len
result = a.len == b.len

iterator tupleTypePairs*(a, b: PType): (int, PType, PType) =
for i in 0 ..< a.len:
Expand Down Expand Up @@ -1008,15 +1027,20 @@ proc newType*(kind: TTypeKind; idgen: IdGenerator; owner: PSym; son: sink PType
alignImpl: defaultAlignment, itemId: id,
uniqueId: id, sonsImpl: @[])
if son != nil:
assert kind != tyProc
result.sonsImpl.add son
when false:
if result.itemId.module == 55 and result.itemId.item == 2:
echo "KNID ", kind
writeStackTrace()

proc setSons*(dest: PType; sons: sink seq[PType]) {.inline.} = dest.sonsImpl = sons
proc setSon*(dest: PType; son: sink PType) {.inline.} = dest.sonsImpl = @[son]
proc setSons*(dest: PType; sons: sink seq[PType]) {.inline.} =
assert dest.kind != tyProc or sons.len <= 1
dest.sonsImpl = sons
proc setSon*(dest: PType; son: sink PType) {.inline.} =
dest.sonsImpl = @[son]
proc setSonsLen*(dest: PType; len: int) {.inline.} =
assert dest.kind != tyProc or len <= 1
setLen(dest.sonsImpl, len)

proc mergeLoc(a: var TLoc, b: TLoc) =
Expand All @@ -1030,6 +1054,7 @@ proc newSons*(father: PNode, length: int) =
setLen(father.sons, length)

proc newSons*(father: PType, length: int) =
assert father.kind != tyProc or length <= 1
setLen(father.sonsImpl, length)

proc truncateInferredTypeCandidates*(t: PType) {.inline.} =
Expand All @@ -1054,8 +1079,16 @@ proc assignType*(dest, src: PType) =
mergeLoc(dest.sym.locImpl, src.sym.loc)
else:
dest.symImpl = src.sym
newSons(dest, src.len)
for i in 0..<src.len: dest[i] = src[i]
if src.kind == tyProc:
# `tyProc` uses only `sonsImpl[0]` to store return type.
# parameter symbols and types are stored in `nImpl`.
assert src.sonsImpl.len <= 1
if src.len > 0:
setLen(dest.sonsImpl, 1)
dest.sonsImpl[0] = src.sonsImpl[0]
else:
newSons(dest, src.len)
for i in 0..<src.len: dest[i] = src[i]

proc copyType*(t: PType, idgen: IdGenerator, owner: PSym): PType =
result = newType(t.kind, idgen, owner)
Expand Down Expand Up @@ -1165,7 +1198,8 @@ proc propagateToOwner*(owner, elem: PType; propagateHasAsgn = true) =

proc rawAddSon*(father, son: PType; propagateHasAsgn = true) =
ensureMutable father
father.sonsImpl.add(son)
if father.kind != tyProc or father.sonsImpl.len == 0:
father.sonsImpl.add(son)
if not son.isNil: propagateToOwner(father, son, propagateHasAsgn)

proc addSonNilAllowed*(father, son: PNode) =
Expand Down Expand Up @@ -1571,7 +1605,7 @@ proc newProcType*(info: TLineInfo; idgen: IdGenerator; owner: PSym): PType =
result.n.add newNodeI(nkEffectList, info)

proc addParam*(procType: PType; param: PSym) =
param.position = procType.sons.len-1
param.position = procType.n.len - 1
procType.n.add newSymNode(param)
rawAddSon(procType, param.typ)

Expand Down
10 changes: 8 additions & 2 deletions compiler/ic/ic.nim
Original file line number Diff line number Diff line change
Expand Up @@ -370,8 +370,14 @@ proc storeType(t: PType; c: var PackedEncoder; m: var PackedModule): PackedItemI
paddingAtEnd: t.paddingAtEnd)
storeNode(p, t, n)
p.typeInst = t.typeInst.storeType(c, m)
for kid in kids t:
p.types.add kid.storeType(c, m)
if t.kind == tyProc and t.len > 0:
# if kind == tyProc, parameter types are stored in t.n
# and you can access them with `kits` iterator.
# return type is stored in t.sons[0].
p.types.add t[0].storeType(c, m)
else:
for kid in kids t:
p.types.add kid.storeType(c, m)
c.addMissing t.sym
p.sym = t.sym.safeItemId(c, m)
c.addMissing t.owner
Expand Down
21 changes: 11 additions & 10 deletions compiler/seminst.nim
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,8 @@ proc instantiateProcType(c: PContext, pt: LayeredIdTable,
var result = instCopyType(cl, prc.typ)
let originalParams = result.n
result.n = originalParams.shallowCopy
for i, resulti in paramTypes(result):
for i in 1 ..< originalParams.len:
let resulti = originalParams[i].sym.typ
# twrong_field_caching requires these 'resetIdTable' calls:
if i > FirstParamAt:
resetIdTable(cl.symMap)
Expand All @@ -258,23 +259,23 @@ proc instantiateProcType(c: PContext, pt: LayeredIdTable,
let needsTypeDescSkipping = resulti.kind == tyTypeDesc and tfUnresolved in resulti.flags
if resulti.kind == tyFromExpr:
resulti.incl tfNonConstExpr
result[i] = replaceTypeVarsT(cl, resulti)
var paramType = replaceTypeVarsT(cl, resulti)
if needsStaticSkipping:
result[i] = result[i].skipTypes({tyStatic})
paramType = paramType.skipTypes({tyStatic})
if needsTypeDescSkipping:
result[i] = result[i].skipTypes({tyTypeDesc})
typeToFit = result[i]
paramType = paramType.skipTypes({tyTypeDesc})
typeToFit = paramType

# ...otherwise, we use the instantiated type in `fitNode`
if (typeToFit.kind != tyTypeDesc or typeToFit.base.kind != tyNone) and
(typeToFit.kind != tyStatic):
typeToFit = result[i]
typeToFit = paramType

internalAssert c.config, originalParams[i].kind == nkSym
let oldParam = originalParams[i].sym
let param = copySym(oldParam, c.idgen)
setOwner(param, prc)
param.typ = result[i]
param.typ = paramType

# The default value is instantiated and fitted against the final
# concrete param type. We avoid calling `replaceTypeVarsN` on the
Expand Down Expand Up @@ -305,12 +306,12 @@ proc instantiateProcType(c: PContext, pt: LayeredIdTable,
param.ast.typ = def.typ
else:
param.ast = fitNodePostMatch(c, typeToFit, converted)
param.typ = result[i]
param.typ = paramType

result.n[i] = newSymNode(param)
if isRecursiveStructuralType(result[i]):
if isRecursiveStructuralType(paramType):
localError(c.config, originalParams[i].sym.info, "illegal recursion in type '" & typeToString(result[i]) & "'")
propagateToOwner(result, result[i])
propagateToOwner(result, paramType)
addDecl(c, param)

resetIdTable(cl.symMap)
Expand Down
7 changes: 3 additions & 4 deletions compiler/semtypinst.nim
Original file line number Diff line number Diff line change
Expand Up @@ -542,14 +542,12 @@ proc eraseVoidParams*(t: PType) =

for i in FirstParamAt..<t.signatureLen:
# don't touch any memory unless necessary
if t[i].kind == tyVoid:
if t.n[i].kind == nkRecList or t[i].kind == tyVoid:
var pos = i
for j in i+1..<t.signatureLen:
if t[j].kind != tyVoid:
t[pos] = t[j]
t.n[pos] = t.n[j]
inc pos
newSons t, pos
setLen t.n.sons, pos
break

Expand Down Expand Up @@ -743,7 +741,8 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType, isInstValue = false):
let r2 = r.skipTypes({tyAlias, tySink, tyOwned})
if r2.kind in {tyPtr, tyRef}:
r = skipTypes(r2, {tyPtr, tyRef})
result[i] = r
if result.kind != tyProc or i == 0:
result[i] = r
if result.kind != tyArray or i != 0:
propagateToOwner(result, r)
# bug #4677: Do not instantiate effect lists
Expand Down
2 changes: 0 additions & 2 deletions compiler/sigmatch.nim
Original file line number Diff line number Diff line change
Expand Up @@ -233,13 +233,11 @@ proc copyingEraseVoidParams(m: TCandidate, t: var PType) =
if not copied:
# keep first i children
t = copyType(original, m.c.idgen, t.owner)
t.setSonsLen(i)
t.n = copyNode(original.n)
t.n.sons = original.n.sons
t.n.sons.setLen(i)
copied = true
elif copied:
t.add(f)
t.n.add(original.n[i])

proc initCandidate*(ctx: PContext, callee: PSym,
Expand Down
2 changes: 1 addition & 1 deletion compiler/sinkparameter_inference.nim
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ proc checkForSink*(config: ConfigRef; idgen: IdGenerator; owner: PSym; arg: PNod
sinkType.add argType

arg.sym.typ = sinkType
owner.typ[arg.sym.position+1] = sinkType
assert owner.typ.n[arg.sym.position+1].sym == arg.sym

#message(config, arg.info, warnUser,
# ("turned '$1' to a sink parameter") % [$arg])
Expand Down
Loading