mirror of
https://github.com/nim-lang/Nim.git
synced 2026-06-23 19:49:44 +00:00
Merge branch 'devel' into araq-loadfromfield
This commit is contained in:
@@ -24,6 +24,6 @@ if not exist %nim_csources% (
|
||||
cd ..
|
||||
copy /y bin\nim.exe %nim_csources%
|
||||
)
|
||||
bin\nim.exe c --noNimblePath --skipUserCfg --skipParentCfg --hints:off koch
|
||||
koch boot -d:release --skipUserCfg --skipParentCfg --hints:off
|
||||
koch tools --skipUserCfg --skipParentCfg --hints:off
|
||||
bin\nim.exe c --noNimblePath --skipUserCfg --skipParentCfg --hints:off koch
|
||||
koch boot -d:release --skipUserCfg --skipParentCfg --hints:off
|
||||
koch tools --skipUserCfg --skipParentCfg --hints:off
|
||||
|
||||
@@ -14,6 +14,11 @@ rounding guarantees (via the
|
||||
|
||||
## Standard library additions and changes
|
||||
|
||||
[//]: # "Additions:"
|
||||
- `setutils.symmetricDifference` along with its operator version
|
||||
`` setutils.`-+-` `` and in-place version `setutils.toggle` have been added
|
||||
to more efficiently calculate the symmetric difference of bitsets.
|
||||
|
||||
[//]: # "Changes:"
|
||||
- `std/math` The `^` symbol now supports floating-point as exponent in addition to the Natural type.
|
||||
|
||||
|
||||
@@ -491,7 +491,7 @@ type
|
||||
mAnd, mOr,
|
||||
mImplies, mIff, mExists, mForall, mOld,
|
||||
mEqStr, mLeStr, mLtStr,
|
||||
mEqSet, mLeSet, mLtSet, mMulSet, mPlusSet, mMinusSet,
|
||||
mEqSet, mLeSet, mLtSet, mMulSet, mPlusSet, mMinusSet, mXorSet,
|
||||
mConStrStr, mSlice,
|
||||
mDotDot, # this one is only necessary to give nice compile time warnings
|
||||
mFields, mFieldPairs, mOmpParFor,
|
||||
@@ -559,7 +559,7 @@ const
|
||||
mStrToStr, mEnumToStr,
|
||||
mAnd, mOr,
|
||||
mEqStr, mLeStr, mLtStr,
|
||||
mEqSet, mLeSet, mLtSet, mMulSet, mPlusSet, mMinusSet,
|
||||
mEqSet, mLeSet, mLtSet, mMulSet, mPlusSet, mMinusSet, mXorSet,
|
||||
mConStrStr, mAppendStrCh, mAppendStrStr, mAppendSeqElem,
|
||||
mInSet, mRepr, mOpenArrayToSeq}
|
||||
|
||||
@@ -591,7 +591,7 @@ type
|
||||
TNode*{.final, acyclic.} = object # on a 32bit machine, this takes 32 bytes
|
||||
when defined(useNodeIds):
|
||||
id*: int
|
||||
typ*: PType
|
||||
typField: PType
|
||||
info*: TLineInfo
|
||||
flags*: TNodeFlags
|
||||
case kind*: TNodeKind
|
||||
@@ -708,7 +708,7 @@ type
|
||||
when defined(nimsuggest):
|
||||
endInfo*: TLineInfo
|
||||
hasUserSpecifiedType*: bool # used for determining whether to display inlay type hints
|
||||
owner*: PSym
|
||||
ownerField: PSym
|
||||
flags*: TSymFlags
|
||||
ast*: PNode # syntax tree of proc, iterator, etc.:
|
||||
# the whole proc including header; this is used
|
||||
@@ -779,7 +779,7 @@ type
|
||||
# formal param list
|
||||
# for concepts, the concept body
|
||||
# else: unused
|
||||
owner*: PSym # the 'owner' of the type
|
||||
ownerField: PSym # the 'owner' of the type
|
||||
sym*: PSym # types have the sym associated with them
|
||||
# it is used for converting types to strings
|
||||
size*: BiggestInt # the size of the type in bytes
|
||||
@@ -818,6 +818,15 @@ type
|
||||
|
||||
template nodeId(n: PNode): int = cast[int](n)
|
||||
|
||||
template typ*(n: PNode): PType =
|
||||
n.typField
|
||||
|
||||
proc owner*(s: PSym|PType): PSym {.inline.} =
|
||||
result = s.ownerField
|
||||
|
||||
proc setOwner*(s: PSym|PType, owner: PSym) {.inline.} =
|
||||
s.ownerField = owner
|
||||
|
||||
type Gconfig = object
|
||||
# we put comments in a side channel to avoid increasing `sizeof(TNode)`, which
|
||||
# reduces memory usage given that `PNode` is the most allocated type by far.
|
||||
@@ -1136,7 +1145,7 @@ proc newNodeIT*(kind: TNodeKind, info: TLineInfo, typ: PType): PNode =
|
||||
## new node with line info, type, and no children
|
||||
result = newNode(kind)
|
||||
result.info = info
|
||||
result.typ = typ
|
||||
result.typ() = typ
|
||||
|
||||
proc newNode*(kind: TNodeKind, info: TLineInfo): PNode =
|
||||
## new node with line info, no type, and no children
|
||||
@@ -1201,7 +1210,7 @@ proc newSym*(symKind: TSymKind, name: PIdent, idgen: IdGenerator; owner: PSym,
|
||||
assert not name.isNil
|
||||
let id = nextSymId idgen
|
||||
result = PSym(name: name, kind: symKind, flags: {}, info: info, itemId: id,
|
||||
options: options, owner: owner, offset: defaultOffset,
|
||||
options: options, ownerField: owner, offset: defaultOffset,
|
||||
disamb: getOrDefault(idgen.disambTable, name).int32)
|
||||
idgen.disambTable.inc name
|
||||
when false:
|
||||
@@ -1282,13 +1291,13 @@ proc newIdentNode*(ident: PIdent, info: TLineInfo): PNode =
|
||||
proc newSymNode*(sym: PSym): PNode =
|
||||
result = newNode(nkSym)
|
||||
result.sym = sym
|
||||
result.typ = sym.typ
|
||||
result.typ() = sym.typ
|
||||
result.info = sym.info
|
||||
|
||||
proc newSymNode*(sym: PSym, info: TLineInfo): PNode =
|
||||
result = newNode(nkSym)
|
||||
result.sym = sym
|
||||
result.typ = sym.typ
|
||||
result.typ() = sym.typ
|
||||
result.info = info
|
||||
|
||||
proc newOpenSym*(n: PNode): PNode {.inline.} =
|
||||
@@ -1368,7 +1377,7 @@ proc newIntTypeNode*(intVal: BiggestInt, typ: PType): PNode =
|
||||
result = newNode(nkIntLit)
|
||||
else: raiseAssert $kind
|
||||
result.intVal = intVal
|
||||
result.typ = typ
|
||||
result.typ() = typ
|
||||
|
||||
proc newIntTypeNode*(intVal: Int128, typ: PType): PNode =
|
||||
# XXX: introduce range check
|
||||
@@ -1507,7 +1516,7 @@ iterator signature*(t: PType): PType =
|
||||
|
||||
proc newType*(kind: TTypeKind; idgen: IdGenerator; owner: PSym; son: sink PType = nil): PType =
|
||||
let id = nextTypeId idgen
|
||||
result = PType(kind: kind, owner: owner, size: defaultSize,
|
||||
result = PType(kind: kind, ownerField: owner, size: defaultSize,
|
||||
align: defaultAlignment, itemId: id,
|
||||
uniqueId: id, sons: @[])
|
||||
if son != nil: result.sons.add son
|
||||
@@ -1562,7 +1571,7 @@ proc copyType*(t: PType, idgen: IdGenerator, owner: PSym): PType =
|
||||
result.sym = t.sym # backend-info should not be copied
|
||||
|
||||
proc exactReplica*(t: PType): PType =
|
||||
result = PType(kind: t.kind, owner: t.owner, size: defaultSize,
|
||||
result = PType(kind: t.kind, ownerField: t.owner, size: defaultSize,
|
||||
align: defaultAlignment, itemId: t.itemId,
|
||||
uniqueId: t.uniqueId)
|
||||
assignType(result, t)
|
||||
@@ -1670,7 +1679,7 @@ proc copyNode*(src: PNode): PNode =
|
||||
return nil
|
||||
result = newNode(src.kind)
|
||||
result.info = src.info
|
||||
result.typ = src.typ
|
||||
result.typ() = src.typ
|
||||
result.flags = src.flags * PersistentNodeFlags
|
||||
result.comment = src.comment
|
||||
when defined(useNodeIds):
|
||||
@@ -1688,7 +1697,7 @@ proc copyNode*(src: PNode): PNode =
|
||||
|
||||
template transitionNodeKindCommon(k: TNodeKind) =
|
||||
let obj {.inject.} = n[]
|
||||
n[] = TNode(kind: k, typ: obj.typ, info: obj.info, flags: obj.flags)
|
||||
n[] = TNode(kind: k, typField: n.typ, info: obj.info, flags: obj.flags)
|
||||
# n.comment = obj.comment # shouldn't be needed, the address doesnt' change
|
||||
when defined(useNodeIds):
|
||||
n.id = obj.id
|
||||
@@ -1711,7 +1720,7 @@ proc transitionNoneToSym*(n: PNode) =
|
||||
template transitionSymKindCommon*(k: TSymKind) =
|
||||
let obj {.inject.} = s[]
|
||||
s[] = TSym(kind: k, itemId: obj.itemId, magic: obj.magic, typ: obj.typ, name: obj.name,
|
||||
info: obj.info, owner: obj.owner, flags: obj.flags, ast: obj.ast,
|
||||
info: obj.info, ownerField: obj.ownerField, flags: obj.flags, ast: obj.ast,
|
||||
options: obj.options, position: obj.position, offset: obj.offset,
|
||||
loc: obj.loc, annex: obj.annex, constraint: obj.constraint)
|
||||
when hasFFI:
|
||||
@@ -1739,7 +1748,7 @@ template copyNodeImpl(dst, src, processSonsStmt) =
|
||||
dst.info = src.info
|
||||
when defined(nimsuggest):
|
||||
result.endInfo = src.endInfo
|
||||
dst.typ = src.typ
|
||||
dst.typ() = src.typ
|
||||
dst.flags = src.flags * PersistentNodeFlags
|
||||
dst.comment = src.comment
|
||||
when defined(useNodeIds):
|
||||
|
||||
@@ -54,6 +54,32 @@ template addVarWithTypeAndInitializer(builder: var Builder, kind: VarKind = Loca
|
||||
initializerBody
|
||||
builder.add(";\n")
|
||||
|
||||
proc addArrayVar(builder: var Builder, kind: VarKind = Local, name: string, elementType: Snippet, len: int, initializer: Snippet = "") =
|
||||
## adds an array variable declaration to the builder
|
||||
builder.addVarHeader(kind)
|
||||
builder.add(elementType)
|
||||
builder.add(" ")
|
||||
builder.add(name)
|
||||
builder.add("[")
|
||||
builder.addInt(len)
|
||||
builder.add("]")
|
||||
if initializer.len != 0:
|
||||
builder.add(" = ")
|
||||
builder.add(initializer)
|
||||
builder.add(";\n")
|
||||
|
||||
template addArrayVarWithInitializer(builder: var Builder, kind: VarKind = Local, name: string, elementType: Snippet, len: int, body: typed) =
|
||||
## adds an array variable declaration to the builder with the initializer built according to `body`
|
||||
builder.addVarHeader(kind)
|
||||
builder.add(elementType)
|
||||
builder.add(" ")
|
||||
builder.add(name)
|
||||
builder.add("[")
|
||||
builder.addInt(len)
|
||||
builder.add("] = ")
|
||||
body
|
||||
builder.add(";\n")
|
||||
|
||||
template addTypedef(builder: var Builder, name: string, typeBody: typed) =
|
||||
## adds a typedef declaration to the builder with name `name` and type as
|
||||
## built in `typeBody`
|
||||
@@ -63,41 +89,57 @@ template addTypedef(builder: var Builder, name: string, typeBody: typed) =
|
||||
builder.add(name)
|
||||
builder.add(";\n")
|
||||
|
||||
type StructInitializer = object
|
||||
## context for building struct initializers, i.e. `{ field1, field2 }`
|
||||
# XXX use in genBracedInit
|
||||
orderCompliant: bool
|
||||
## if true, fields will not be named, instead values are placed in order
|
||||
needsComma: bool
|
||||
type
|
||||
StructInitializerKind = enum
|
||||
siOrderedStruct ## struct constructor, but without named fields on C
|
||||
siNamedStruct ## struct constructor, with named fields i.e. C99 designated initializer
|
||||
siArray ## array constructor
|
||||
siWrapper ## wrapper for a single field, generates it verbatim
|
||||
|
||||
proc initStructInitializer(builder: var Builder, orderCompliant: bool): StructInitializer =
|
||||
## starts building a struct initializer, `orderCompliant = true` means
|
||||
## built fields must be ordered correctly
|
||||
doAssert orderCompliant, "named struct constructors unimplemented"
|
||||
result = StructInitializer(orderCompliant: true, needsComma: false)
|
||||
builder.add("{ ")
|
||||
StructInitializer = object
|
||||
## context for building struct initializers, i.e. `{ field1, field2 }`
|
||||
kind: StructInitializerKind
|
||||
## if true, fields will not be named, instead values are placed in order
|
||||
needsComma: bool
|
||||
|
||||
proc initStructInitializer(builder: var Builder, kind: StructInitializerKind): StructInitializer =
|
||||
## starts building a struct initializer, i.e. braced initializer list
|
||||
result = StructInitializer(kind: kind, needsComma: false)
|
||||
if kind != siWrapper:
|
||||
builder.add("{")
|
||||
|
||||
template addField(builder: var Builder, constr: var StructInitializer, name: string, valueBody: typed) =
|
||||
## adds a field to a struct initializer, with the value built in `valueBody`
|
||||
if constr.needsComma:
|
||||
assert constr.kind != siWrapper, "wrapper constructor cannot have multiple fields"
|
||||
builder.add(", ")
|
||||
else:
|
||||
constr.needsComma = true
|
||||
if constr.orderCompliant:
|
||||
case constr.kind
|
||||
of siArray, siWrapper:
|
||||
# no name, can just add value
|
||||
valueBody
|
||||
else:
|
||||
doAssert false, "named struct constructors unimplemented"
|
||||
of siOrderedStruct:
|
||||
# no name, can just add value on C
|
||||
assert name.len != 0, "name has to be given for struct initializer field"
|
||||
valueBody
|
||||
of siNamedStruct:
|
||||
assert name.len != 0, "name has to be given for struct initializer field"
|
||||
builder.add(".")
|
||||
builder.add(name)
|
||||
builder.add(" = ")
|
||||
valueBody
|
||||
|
||||
proc finishStructInitializer(builder: var Builder, constr: StructInitializer) =
|
||||
## finishes building a struct initializer
|
||||
builder.add(" }")
|
||||
if constr.kind != siWrapper:
|
||||
builder.add("}")
|
||||
|
||||
template addStructInitializer(builder: var Builder, constr: out StructInitializer, orderCompliant: bool, body: typed) =
|
||||
template addStructInitializer(builder: var Builder, constr: out StructInitializer, kind: StructInitializerKind, body: typed) =
|
||||
## builds a struct initializer, i.e. `{ field1, field2 }`
|
||||
## a `var StructInitializer` must be declared and passed as a parameter so
|
||||
## that it can be used with `addField`
|
||||
constr = builder.initStructInitializer(orderCompliant)
|
||||
constr = builder.initStructInitializer(kind)
|
||||
body
|
||||
builder.finishStructInitializer(constr)
|
||||
|
||||
|
||||
@@ -15,5 +15,11 @@ const
|
||||
proc procPtrType(conv: TCallingConvention, rettype: Snippet, name: string): Snippet =
|
||||
CallingConvToStr[conv] & "_PTR(" & rettype & ", " & name & ")"
|
||||
|
||||
proc cCast(typ, value: Snippet): Snippet =
|
||||
"((" & typ & ") " & value & ")"
|
||||
|
||||
proc cAddr(value: Snippet): Snippet =
|
||||
"&" & value
|
||||
|
||||
proc bitOr(a, b: Snippet): Snippet =
|
||||
a & " | " & b
|
||||
"(" & a & " | " & b & ")"
|
||||
|
||||
@@ -336,7 +336,7 @@ proc genArg(p: BProc, n: PNode, param: PSym; call: PNode; result: var Rope; need
|
||||
# variable. Thus, we create a temporary pointer variable instead.
|
||||
let needsIndirect = mapType(p.config, n[0].typ, mapTypeChooser(n[0]) == skParam) != ctArray
|
||||
if needsIndirect:
|
||||
n.typ = n.typ.exactReplica
|
||||
n.typ() = n.typ.exactReplica
|
||||
n.typ.flags.incl tfVarIsPtr
|
||||
a = initLocExprSingleUse(p, n)
|
||||
a = withTmpIfNeeded(p, a, needsTmp)
|
||||
|
||||
@@ -13,7 +13,7 @@ when defined(nimCompilerStacktraceHints):
|
||||
import std/stackframes
|
||||
|
||||
proc getNullValueAuxT(p: BProc; orig, t: PType; obj, constOrNil: PNode,
|
||||
result: var Rope; count: var int;
|
||||
result: var Builder; init: var StructInitializer;
|
||||
isConst: bool, info: TLineInfo)
|
||||
|
||||
# -------------------------- constant expressions ------------------------
|
||||
@@ -1626,7 +1626,7 @@ proc genSeqConstr(p: BProc, n: PNode, d: var TLoc) =
|
||||
proc genArrToSeq(p: BProc, n: PNode, d: var TLoc) =
|
||||
var elem, arr: TLoc
|
||||
if n[1].kind == nkBracket:
|
||||
n[1].typ = n.typ
|
||||
n[1].typ() = n.typ
|
||||
genSeqConstr(p, n[1], d)
|
||||
return
|
||||
if d.k == locNone:
|
||||
@@ -2044,7 +2044,7 @@ proc genInOp(p: BProc, e: PNode, d: var TLoc) =
|
||||
|
||||
proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||
const
|
||||
lookupOpr: array[mLeSet..mMinusSet, string] = [
|
||||
lookupOpr: array[mLeSet..mXorSet, string] = [
|
||||
"for ($1 = 0; $1 < $2; $1++) { $n" &
|
||||
" $3 = (($4[$1] & ~ $5[$1]) == 0);$n" &
|
||||
" if (!$3) break;}$n",
|
||||
@@ -2054,7 +2054,8 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||
"if ($3) $3 = (#nimCmpMem($4, $5, $2) != 0);$n",
|
||||
"&",
|
||||
"|",
|
||||
"& ~"]
|
||||
"& ~",
|
||||
"^"]
|
||||
var a, b: TLoc
|
||||
var i: TLoc
|
||||
var setType = skipTypes(e[1].typ, abstractVar)
|
||||
@@ -2085,6 +2086,7 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||
of mMulSet: binaryExpr(p, e, d, "($1 & $2)")
|
||||
of mPlusSet: binaryExpr(p, e, d, "($1 | $2)")
|
||||
of mMinusSet: binaryExpr(p, e, d, "($1 & ~ $2)")
|
||||
of mXorSet: binaryExpr(p, e, d, "($1 ^ $2)")
|
||||
of mInSet:
|
||||
genInOp(p, e, d)
|
||||
else: internalError(p.config, e.info, "genSetOp()")
|
||||
@@ -2112,7 +2114,7 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||
var a = initLocExpr(p, e[1])
|
||||
var b = initLocExpr(p, e[2])
|
||||
putIntoDest(p, d, e, ropecg(p.module, "(#nimCmpMem($1, $2, $3)==0)", [a.rdCharLoc, b.rdCharLoc, size]))
|
||||
of mMulSet, mPlusSet, mMinusSet:
|
||||
of mMulSet, mPlusSet, mMinusSet, mXorSet:
|
||||
# we inline the simple for loop for better code generation:
|
||||
i = getTemp(p, getSysType(p.module.g.graph, unknownLineInfo, tyInt)) # our counter
|
||||
a = initLocExpr(p, e[1])
|
||||
@@ -2321,7 +2323,7 @@ proc genWasMoved(p: BProc; n: PNode) =
|
||||
# [addrLoc(p.config, a), getTypeDesc(p.module, a.t)])
|
||||
|
||||
proc genMove(p: BProc; n: PNode; d: var TLoc) =
|
||||
var a: TLoc = initLocExpr(p, n[1].skipAddr)
|
||||
var a: TLoc = initLocExpr(p, n[1].skipAddr, {lfEnforceDeref})
|
||||
if n.len == 4:
|
||||
# generated by liftdestructors:
|
||||
var src: TLoc = initLocExpr(p, n[2])
|
||||
@@ -2548,7 +2550,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||
of mSetLengthStr: genSetLengthStr(p, e, d)
|
||||
of mSetLengthSeq: genSetLengthSeq(p, e, d)
|
||||
of mIncl, mExcl, mCard, mLtSet, mLeSet, mEqSet, mMulSet, mPlusSet, mMinusSet,
|
||||
mInSet:
|
||||
mInSet, mXorSet:
|
||||
genSetOp(p, e, d, op)
|
||||
of mNewString, mNewStringOfCap, mExit, mParseBiggestFloat:
|
||||
var opr = e[0].sym
|
||||
@@ -3077,7 +3079,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
|
||||
# addr ( deref ( x )) --> x
|
||||
var x = n[0][0]
|
||||
if n.typ.skipTypes(abstractVar).kind != tyOpenArray:
|
||||
x.typ = n.typ
|
||||
x.typ() = n.typ
|
||||
expr(p, x, d)
|
||||
return
|
||||
genAddr(p, n, d)
|
||||
@@ -3193,7 +3195,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
|
||||
of nkMixinStmt, nkBindStmt: discard
|
||||
else: internalError(p.config, n.info, "expr(" & $n.kind & "); unknown node kind")
|
||||
|
||||
proc getDefaultValue(p: BProc; typ: PType; info: TLineInfo; result: var Rope) =
|
||||
proc getDefaultValue(p: BProc; typ: PType; info: TLineInfo; result: var Builder) =
|
||||
var t = skipTypes(typ, abstractRange+{tyOwned}-{tyTypeDesc})
|
||||
case t.kind
|
||||
of tyBool: result.add rope"NIM_FALSE"
|
||||
@@ -3204,38 +3206,56 @@ proc getDefaultValue(p: BProc; typ: PType; info: TLineInfo; result: var Rope) =
|
||||
result.add rope"NIM_NIL"
|
||||
of tyString, tySequence:
|
||||
if optSeqDestructors in p.config.globalOptions:
|
||||
result.add "{0, NIM_NIL}"
|
||||
var seqInit: StructInitializer
|
||||
result.addStructInitializer(seqInit, kind = siOrderedStruct):
|
||||
result.addField(seqInit, name = "len"):
|
||||
result.add("0")
|
||||
result.addField(seqInit, name = "p"):
|
||||
result.add("NIM_NIL")
|
||||
else:
|
||||
result.add "NIM_NIL"
|
||||
of tyProc:
|
||||
if t.callConv != ccClosure:
|
||||
result.add "NIM_NIL"
|
||||
else:
|
||||
result.add "{NIM_NIL, NIM_NIL}"
|
||||
var closureInit: StructInitializer
|
||||
result.addStructInitializer(closureInit, kind = siOrderedStruct):
|
||||
result.addField(closureInit, name = "ClP_0"):
|
||||
result.add("NIM_NIL")
|
||||
result.addField(closureInit, name = "ClE_0"):
|
||||
result.add("NIM_NIL")
|
||||
of tyObject:
|
||||
var count = 0
|
||||
result.add "{"
|
||||
getNullValueAuxT(p, t, t, t.n, nil, result, count, true, info)
|
||||
result.add "}"
|
||||
var objInit: StructInitializer
|
||||
result.addStructInitializer(objInit, kind = siOrderedStruct):
|
||||
getNullValueAuxT(p, t, t, t.n, nil, result, objInit, true, info)
|
||||
of tyTuple:
|
||||
result.add "{"
|
||||
if p.vccAndC and t.isEmptyTupleType:
|
||||
result.add "0"
|
||||
for i, a in t.ikids:
|
||||
if i > 0: result.add ", "
|
||||
getDefaultValue(p, a, info, result)
|
||||
result.add "}"
|
||||
var tupleInit: StructInitializer
|
||||
result.addStructInitializer(tupleInit, kind = siOrderedStruct):
|
||||
if p.vccAndC and t.isEmptyTupleType:
|
||||
result.addField(tupleInit, name = "dummy"):
|
||||
result.add "0"
|
||||
for i, a in t.ikids:
|
||||
result.addField(tupleInit, name = "Field" & $i):
|
||||
getDefaultValue(p, a, info, result)
|
||||
of tyArray:
|
||||
result.add "{"
|
||||
for i in 0..<toInt(lengthOrd(p.config, t.indexType)):
|
||||
if i > 0: result.add ", "
|
||||
getDefaultValue(p, t.elementType, info, result)
|
||||
result.add "}"
|
||||
var arrInit: StructInitializer
|
||||
result.addStructInitializer(arrInit, kind = siArray):
|
||||
for i in 0..<toInt(lengthOrd(p.config, t.indexType)):
|
||||
result.addField(arrInit, name = ""):
|
||||
getDefaultValue(p, t.elementType, info, result)
|
||||
#result = rope"{}"
|
||||
of tyOpenArray, tyVarargs:
|
||||
result.add "{NIM_NIL, 0}"
|
||||
var openArrInit: StructInitializer
|
||||
result.addStructInitializer(openArrInit, kind = siOrderedStruct):
|
||||
result.addField(openArrInit, name = "Field0"):
|
||||
result.add("NIM_NIL")
|
||||
result.addField(openArrInit, name = "Field1"):
|
||||
result.add("0")
|
||||
of tySet:
|
||||
if mapSetType(p.config, t) == ctArray: result.add "{}"
|
||||
if mapSetType(p.config, t) == ctArray:
|
||||
var setInit: StructInitializer
|
||||
result.addStructInitializer(setInit, kind = siArray):
|
||||
discard
|
||||
else: result.add "0"
|
||||
else:
|
||||
globalError(p.config, info, "cannot create null element for: " & $t.kind)
|
||||
@@ -3246,16 +3266,18 @@ proc isEmptyCaseObjectBranch(n: PNode): bool =
|
||||
return true
|
||||
|
||||
proc getNullValueAux(p: BProc; t: PType; obj, constOrNil: PNode,
|
||||
result: var Rope; count: var int;
|
||||
result: var Builder; init: var StructInitializer;
|
||||
isConst: bool, info: TLineInfo) =
|
||||
case obj.kind
|
||||
of nkRecList:
|
||||
let isUnion = tfUnion in t.flags
|
||||
for it in obj.sons:
|
||||
getNullValueAux(p, t, it, constOrNil, result, count, isConst, info)
|
||||
getNullValueAux(p, t, it, constOrNil, result, init, isConst, info)
|
||||
if isUnion:
|
||||
# generate only 1 field for default value of union
|
||||
return
|
||||
of nkRecCase:
|
||||
getNullValueAux(p, t, obj[0], constOrNil, result, count, isConst, info)
|
||||
var res = ""
|
||||
if count > 0: res.add ", "
|
||||
getNullValueAux(p, t, obj[0], constOrNil, result, init, isConst, info)
|
||||
var branch = Zero
|
||||
if constOrNil != nil:
|
||||
## find kind value, default is zero if not specified
|
||||
@@ -3269,140 +3291,186 @@ proc getNullValueAux(p: BProc; t: PType; obj, constOrNil: PNode,
|
||||
break
|
||||
|
||||
let selectedBranch = caseObjDefaultBranch(obj, branch)
|
||||
res.add "{"
|
||||
var countB = 0
|
||||
let b = lastSon(obj[selectedBranch])
|
||||
# designated initilization is the only way to init non first element of unions
|
||||
# branches are allowed to have no members (b.len == 0), in this case they don't need initializer
|
||||
var fieldName: string = ""
|
||||
if b.kind == nkRecList and not isEmptyCaseObjectBranch(b):
|
||||
res.add "._" & mangleRecFieldName(p.module, obj[0].sym) & "_" & $selectedBranch & " = {"
|
||||
getNullValueAux(p, t, b, constOrNil, res, countB, isConst, info)
|
||||
res.add "}"
|
||||
fieldName = "_" & mangleRecFieldName(p.module, obj[0].sym) & "_" & $selectedBranch
|
||||
result.addField(init, name = "<anonymous union>"):
|
||||
# XXX figure out name for the union, see use of `addAnonUnion`
|
||||
var branchInit: StructInitializer
|
||||
result.addStructInitializer(branchInit, kind = siNamedStruct):
|
||||
result.addField(branchInit, name = fieldName):
|
||||
var branchObjInit: StructInitializer
|
||||
result.addStructInitializer(branchObjInit, kind = siOrderedStruct):
|
||||
getNullValueAux(p, t, b, constOrNil, result, branchObjInit, isConst, info)
|
||||
elif b.kind == nkSym:
|
||||
res.add "." & mangleRecFieldName(p.module, b.sym) & " = "
|
||||
getNullValueAux(p, t, b, constOrNil, res, countB, isConst, info)
|
||||
fieldName = mangleRecFieldName(p.module, b.sym)
|
||||
result.addField(init, name = "<anonymous union>"):
|
||||
# XXX figure out name for the union, see use of `addAnonUnion`
|
||||
var branchInit: StructInitializer
|
||||
result.addStructInitializer(branchInit, kind = siNamedStruct):
|
||||
result.addField(branchInit, name = fieldName):
|
||||
# we need to generate the default value of the single sym,
|
||||
# to do this create a dummy wrapper initializer and recurse
|
||||
var branchFieldInit: StructInitializer
|
||||
result.addStructInitializer(branchFieldInit, kind = siWrapper):
|
||||
getNullValueAux(p, t, b, constOrNil, result, branchFieldInit, isConst, info)
|
||||
else:
|
||||
# no fields, don't initialize
|
||||
return
|
||||
result.add res
|
||||
result.add "}"
|
||||
|
||||
of nkSym:
|
||||
if count > 0: result.add ", "
|
||||
inc count
|
||||
let field = obj.sym
|
||||
if constOrNil != nil:
|
||||
for i in 1..<constOrNil.len:
|
||||
if constOrNil[i].kind == nkExprColonExpr:
|
||||
assert constOrNil[i][0].kind == nkSym, "illformed object constr; the field is not a sym"
|
||||
if constOrNil[i][0].sym.name.id == field.name.id:
|
||||
genBracedInit(p, constOrNil[i][1], isConst, field.typ, result)
|
||||
return
|
||||
elif i == field.position:
|
||||
genBracedInit(p, constOrNil[i], isConst, field.typ, result)
|
||||
return
|
||||
# not found, produce default value:
|
||||
getDefaultValue(p, field.typ, info, result)
|
||||
let sname = mangleRecFieldName(p.module, field)
|
||||
result.addField(init, name = sname):
|
||||
block fieldInit:
|
||||
if constOrNil != nil:
|
||||
for i in 1..<constOrNil.len:
|
||||
if constOrNil[i].kind == nkExprColonExpr:
|
||||
assert constOrNil[i][0].kind == nkSym, "illformed object constr; the field is not a sym"
|
||||
if constOrNil[i][0].sym.name.id == field.name.id:
|
||||
genBracedInit(p, constOrNil[i][1], isConst, field.typ, result)
|
||||
break fieldInit
|
||||
elif i == field.position:
|
||||
genBracedInit(p, constOrNil[i], isConst, field.typ, result)
|
||||
break fieldInit
|
||||
# not found, produce default value:
|
||||
getDefaultValue(p, field.typ, info, result)
|
||||
else:
|
||||
localError(p.config, info, "cannot create null element for: " & $obj)
|
||||
|
||||
proc getNullValueAuxT(p: BProc; orig, t: PType; obj, constOrNil: PNode,
|
||||
result: var Rope; count: var int;
|
||||
result: var Builder; init: var StructInitializer;
|
||||
isConst: bool, info: TLineInfo) =
|
||||
var base = t.baseClass
|
||||
let oldRes = result
|
||||
let oldcount = count
|
||||
when false:
|
||||
let oldRes = result
|
||||
let oldcount = count
|
||||
if base != nil:
|
||||
result.add "{"
|
||||
base = skipTypes(base, skipPtrs)
|
||||
getNullValueAuxT(p, orig, base, base.n, constOrNil, result, count, isConst, info)
|
||||
result.add "}"
|
||||
result.addField(init, name = "Sup"):
|
||||
var baseInit: StructInitializer
|
||||
result.addStructInitializer(baseInit, kind = siOrderedStruct):
|
||||
getNullValueAuxT(p, orig, base, base.n, constOrNil, result, baseInit, isConst, info)
|
||||
elif not isObjLackingTypeField(t):
|
||||
if optTinyRtti in p.config.globalOptions:
|
||||
result.add genTypeInfoV2(p.module, orig, obj.info)
|
||||
else:
|
||||
result.add genTypeInfoV1(p.module, orig, obj.info)
|
||||
inc count
|
||||
getNullValueAux(p, t, obj, constOrNil, result, count, isConst, info)
|
||||
# do not emit '{}' as that is not valid C:
|
||||
if oldcount == count: result = oldRes
|
||||
result.addField(init, name = "m_type"):
|
||||
if optTinyRtti in p.config.globalOptions:
|
||||
result.add genTypeInfoV2(p.module, orig, obj.info)
|
||||
else:
|
||||
result.add genTypeInfoV1(p.module, orig, obj.info)
|
||||
getNullValueAux(p, t, obj, constOrNil, result, init, isConst, info)
|
||||
when false: # referring to Sup field, hopefully not a problem
|
||||
# do not emit '{}' as that is not valid C:
|
||||
if oldcount == count: result = oldRes
|
||||
|
||||
proc genConstObjConstr(p: BProc; n: PNode; isConst: bool; result: var Rope) =
|
||||
proc genConstObjConstr(p: BProc; n: PNode; isConst: bool; result: var Builder) =
|
||||
let t = n.typ.skipTypes(abstractInstOwned)
|
||||
var count = 0
|
||||
#if not isObjLackingTypeField(t) and not p.module.compileToCpp:
|
||||
# result.addf("{$1}", [genTypeInfo(p.module, t)])
|
||||
# inc count
|
||||
result.add "{"
|
||||
if t.kind == tyObject:
|
||||
getNullValueAuxT(p, t, t, t.n, n, result, count, isConst, n.info)
|
||||
result.add("}\n")
|
||||
var objInit: StructInitializer
|
||||
result.addStructInitializer(objInit, kind = siOrderedStruct):
|
||||
if t.kind == tyObject:
|
||||
getNullValueAuxT(p, t, t, t.n, n, result, objInit, isConst, n.info)
|
||||
|
||||
proc genConstSimpleList(p: BProc, n: PNode; isConst: bool; result: var Rope) =
|
||||
result.add "{"
|
||||
if p.vccAndC and n.len == 0 and n.typ.kind == tyArray:
|
||||
getDefaultValue(p, n.typ.elementType, n.info, result)
|
||||
for i in 0..<n.len:
|
||||
let it = n[i]
|
||||
if i > 0: result.add ",\n"
|
||||
if it.kind == nkExprColonExpr: genBracedInit(p, it[1], isConst, it[0].typ, result)
|
||||
else: genBracedInit(p, it, isConst, it.typ, result)
|
||||
result.add("}\n")
|
||||
|
||||
proc genConstTuple(p: BProc, n: PNode; isConst: bool; tup: PType; result: var Rope) =
|
||||
result.add "{"
|
||||
if p.vccAndC and n.len == 0:
|
||||
result.add "0"
|
||||
for i in 0..<n.len:
|
||||
let it = n[i]
|
||||
if i > 0: result.add ",\n"
|
||||
if it.kind == nkExprColonExpr: genBracedInit(p, it[1], isConst, tup[i], result)
|
||||
else: genBracedInit(p, it, isConst, tup[i], result)
|
||||
result.add("}\n")
|
||||
|
||||
proc genConstSeq(p: BProc, n: PNode, t: PType; isConst: bool; result: var Rope) =
|
||||
var data = "{{$1, $1 | NIM_STRLIT_FLAG}" % [n.len.rope]
|
||||
let base = t.skipTypes(abstractInst)[0]
|
||||
if n.len > 0:
|
||||
# array part needs extra curlies:
|
||||
data.add(", {")
|
||||
proc genConstSimpleList(p: BProc, n: PNode; isConst: bool; result: var Builder) =
|
||||
var arrInit: StructInitializer
|
||||
result.addStructInitializer(arrInit, kind = siArray):
|
||||
if p.vccAndC and n.len == 0 and n.typ.kind == tyArray:
|
||||
result.addField(arrInit, name = ""):
|
||||
getDefaultValue(p, n.typ.elementType, n.info, result)
|
||||
for i in 0..<n.len:
|
||||
if i > 0: data.addf(",$n", [])
|
||||
genBracedInit(p, n[i], isConst, base, data)
|
||||
data.add("}")
|
||||
data.add("}")
|
||||
let it = n[i]
|
||||
var ind, val: PNode
|
||||
if it.kind == nkExprColonExpr:
|
||||
ind = it[0]
|
||||
val = it[1]
|
||||
else:
|
||||
ind = it
|
||||
val = it
|
||||
result.addField(arrInit, name = ""):
|
||||
genBracedInit(p, val, isConst, ind.typ, result)
|
||||
|
||||
proc genConstTuple(p: BProc, n: PNode; isConst: bool; tup: PType; result: var Builder) =
|
||||
var tupleInit: StructInitializer
|
||||
result.addStructInitializer(tupleInit, kind = siOrderedStruct):
|
||||
if p.vccAndC and n.len == 0:
|
||||
result.addField(tupleInit, name = "dummy"):
|
||||
result.add("0")
|
||||
for i in 0..<n.len:
|
||||
var it = n[i]
|
||||
if it.kind == nkExprColonExpr:
|
||||
it = it[1]
|
||||
result.addField(tupleInit, name = "Field" & $i):
|
||||
genBracedInit(p, it, isConst, tup[i], result)
|
||||
|
||||
proc genConstSeq(p: BProc, n: PNode, t: PType; isConst: bool; result: var Builder) =
|
||||
let base = t.skipTypes(abstractInst)[0]
|
||||
let tmpName = getTempName(p.module)
|
||||
|
||||
appcg(p.module, cfsStrData,
|
||||
"static $5 struct {$n" &
|
||||
" #TGenericSeq Sup;$n" &
|
||||
" $1 data[$2];$n" &
|
||||
"} $3 = $4;$n", [
|
||||
getTypeDesc(p.module, base), n.len, tmpName, data,
|
||||
if isConst: "NIM_CONST" else: ""])
|
||||
var def = newBuilder("")
|
||||
def.addVarWithTypeAndInitializer(
|
||||
if isConst: Const else: Global,
|
||||
name = tmpName):
|
||||
def.addSimpleStruct(p.module, name = "", baseType = ""):
|
||||
def.addField(name = "sup", typ = cgsymValue(p.module, "TGenericSeq"))
|
||||
def.addArrayField(name = "data", elementType = getTypeDesc(p.module, base), len = n.len)
|
||||
do:
|
||||
var structInit: StructInitializer
|
||||
def.addStructInitializer(structInit, kind = siOrderedStruct):
|
||||
def.addField(structInit, name = "sup"):
|
||||
var supInit: StructInitializer
|
||||
def.addStructInitializer(supInit, kind = siOrderedStruct):
|
||||
def.addField(supInit, name = "len"):
|
||||
def.add(n.len.rope)
|
||||
def.addField(supInit, name = "reserved"):
|
||||
def.add(bitOr(rope(n.len), "NIM_STRLIT_FLAG"))
|
||||
if n.len > 0:
|
||||
def.addField(structInit, name = "data"):
|
||||
var arrInit: StructInitializer
|
||||
def.addStructInitializer(arrInit, kind = siArray):
|
||||
for i in 0..<n.len:
|
||||
def.addField(arrInit, name = ""):
|
||||
genBracedInit(p, n[i], isConst, base, def)
|
||||
p.module.s[cfsStrData].add def
|
||||
|
||||
result.add "(($1)&$2)" % [getTypeDesc(p.module, t), tmpName]
|
||||
result.add cCast(typ = getTypeDesc(p.module, t), value = cAddr(tmpName))
|
||||
|
||||
proc genConstSeqV2(p: BProc, n: PNode, t: PType; isConst: bool; result: var Rope) =
|
||||
proc genConstSeqV2(p: BProc, n: PNode, t: PType; isConst: bool; result: var Builder) =
|
||||
let base = t.skipTypes(abstractInst)[0]
|
||||
var data = rope""
|
||||
if n.len > 0:
|
||||
data.add(", {")
|
||||
for i in 0..<n.len:
|
||||
if i > 0: data.addf(",$n", [])
|
||||
genBracedInit(p, n[i], isConst, base, data)
|
||||
data.add("}")
|
||||
|
||||
let payload = getTempName(p.module)
|
||||
appcg(p.module, cfsStrData,
|
||||
"static $5 struct {$n" &
|
||||
" NI cap; $1 data[$2];$n" &
|
||||
"} $3 = {$2 | NIM_STRLIT_FLAG$4};$n", [
|
||||
getTypeDesc(p.module, base), n.len, payload, data,
|
||||
if isConst: "const" else: ""])
|
||||
result.add "{$1, ($2*)&$3}" % [rope(n.len), getSeqPayloadType(p.module, t), payload]
|
||||
|
||||
proc genBracedInit(p: BProc, n: PNode; isConst: bool; optionalType: PType; result: var Rope) =
|
||||
var def = newBuilder("")
|
||||
def.addVarWithTypeAndInitializer(
|
||||
if isConst: AlwaysConst else: Global,
|
||||
name = payload):
|
||||
def.addSimpleStruct(p.module, name = "", baseType = ""):
|
||||
def.addField(name = "cap", typ = "NI")
|
||||
def.addArrayField(name = "data", elementType = getTypeDesc(p.module, base), len = n.len)
|
||||
do:
|
||||
var structInit: StructInitializer
|
||||
def.addStructInitializer(structInit, kind = siOrderedStruct):
|
||||
def.addField(structInit, name = "cap"):
|
||||
def.add(bitOr(rope(n.len), "NIM_STRLIT_FLAG"))
|
||||
if n.len > 0:
|
||||
def.addField(structInit, name = "data"):
|
||||
var arrInit: StructInitializer
|
||||
def.addStructInitializer(arrInit, kind = siArray):
|
||||
for i in 0..<n.len:
|
||||
def.addField(arrInit, name = ""):
|
||||
genBracedInit(p, n[i], isConst, base, def)
|
||||
p.module.s[cfsStrData].add def
|
||||
|
||||
var resultInit: StructInitializer
|
||||
result.addStructInitializer(resultInit, kind = siOrderedStruct):
|
||||
result.addField(resultInit, name = "len"):
|
||||
result.add(rope(n.len))
|
||||
result.addField(resultInit, name = "p"):
|
||||
result.add cCast(typ = ptrType(getSeqPayloadType(p.module, t)), value = cAddr(payload))
|
||||
|
||||
proc genBracedInit(p: BProc, n: PNode; isConst: bool; optionalType: PType; result: var Builder) =
|
||||
case n.kind
|
||||
of nkHiddenStdConv, nkHiddenSubConv:
|
||||
genBracedInit(p, n[1], isConst, n.typ, result)
|
||||
@@ -3437,11 +3505,16 @@ proc genBracedInit(p: BProc, n: PNode; isConst: bool; optionalType: PType; resul
|
||||
# in VM closures are initialized with nkPar(nkNilLit, nkNilLit)
|
||||
# leading to duplicate code like this:
|
||||
# "{NIM_NIL,NIM_NIL}, {NIM_NIL,NIM_NIL}"
|
||||
if n[0].kind == nkNilLit:
|
||||
result.add "{NIM_NIL,NIM_NIL}"
|
||||
else:
|
||||
var d: TLoc = initLocExpr(p, n[0])
|
||||
result.add "{(($1) $2),NIM_NIL}" % [getClosureType(p.module, typ, clHalfWithEnv), rdLoc(d)]
|
||||
var closureInit: StructInitializer
|
||||
result.addStructInitializer(closureInit, kind = siOrderedStruct):
|
||||
result.addField(closureInit, name = "ClP_0"):
|
||||
if n[0].kind == nkNilLit:
|
||||
result.add("NIM_NIL")
|
||||
else:
|
||||
var d: TLoc = initLocExpr(p, n[0])
|
||||
result.add(cCast(typ = getClosureType(p.module, typ, clHalfWithEnv), value = rdLoc(d)))
|
||||
result.addField(closureInit, name = "ClE_0"):
|
||||
result.add("NIM_NIL")
|
||||
else:
|
||||
var d: TLoc = initLocExpr(p, n)
|
||||
result.add rdLoc(d)
|
||||
@@ -3453,17 +3526,21 @@ proc genBracedInit(p: BProc, n: PNode; isConst: bool; optionalType: PType; resul
|
||||
if n.kind != nkBracket:
|
||||
internalError(p.config, n.info, "const openArray expression is not an array construction")
|
||||
|
||||
var data = newRopeAppender()
|
||||
genConstSimpleList(p, n, isConst, data)
|
||||
|
||||
let payload = getTempName(p.module)
|
||||
let ctype = getTypeDesc(p.module, typ.elementType)
|
||||
let arrLen = n.len
|
||||
appcg(p.module, cfsStrData,
|
||||
"static $5 $1 $3[$2] = $4;$n", [
|
||||
ctype, arrLen, payload, data,
|
||||
if isConst: "const" else: ""])
|
||||
result.add "{($1*)&$2, $3}" % [ctype, payload, rope arrLen]
|
||||
var data = newBuilder("")
|
||||
data.addArrayVarWithInitializer(
|
||||
kind = if isConst: AlwaysConst else: Global,
|
||||
name = payload, elementType = ctype, len = arrLen):
|
||||
genConstSimpleList(p, n, isConst, data)
|
||||
p.module.s[cfsStrData].add(data)
|
||||
var openArrInit: StructInitializer
|
||||
result.addStructInitializer(openArrInit, kind = siOrderedStruct):
|
||||
result.addField(openArrInit, name = "Field0"):
|
||||
result.add(cCast(typ = ptrType(ctype), value = cAddr(payload)))
|
||||
result.addField(openArrInit, name = "Field1"):
|
||||
result.add(rope arrLen)
|
||||
|
||||
of tyObject:
|
||||
genConstObjConstr(p, n, isConst, result)
|
||||
|
||||
@@ -36,22 +36,37 @@ proc genStringLiteralDataOnlyV1(m: BModule, s: string; result: var Rope) =
|
||||
cgsym(m, "TGenericSeq")
|
||||
let tmp = getTempName(m)
|
||||
result.add tmp
|
||||
m.s[cfsStrData].addf("STRING_LITERAL($1, $2, $3);$n",
|
||||
[tmp, makeCString(s), rope(s.len)])
|
||||
var res = newBuilder("")
|
||||
res.addVarWithTypeAndInitializer(AlwaysConst, name = tmp):
|
||||
res.addSimpleStruct(m, name = "", baseType = ""):
|
||||
res.addField(name = "Sup", typ = "TGenericSeq")
|
||||
res.addArrayField(name = "data", elementType = "NIM_CHAR", len = s.len + 1)
|
||||
do:
|
||||
var strInit: StructInitializer
|
||||
res.addStructInitializer(strInit, kind = siOrderedStruct):
|
||||
res.addField(strInit, name = "Sup"):
|
||||
var seqInit: StructInitializer
|
||||
res.addStructInitializer(seqInit, kind = siOrderedStruct):
|
||||
res.addField(seqInit, name = "len"):
|
||||
res.add(rope(s.len))
|
||||
res.addField(seqInit, name = "reserved"):
|
||||
res.add(cCast("NI", bitOr(cCast("NU", rope(s.len)), "NIM_STRLIT_FLAG")))
|
||||
res.addField(strInit, name = "data"):
|
||||
res.add(makeCString(s))
|
||||
m.s[cfsStrData].add(res)
|
||||
|
||||
proc genStringLiteralV1(m: BModule; n: PNode; result: var Rope) =
|
||||
if s.isNil:
|
||||
appcg(m, result, "((#NimStringDesc*) NIM_NIL)", [])
|
||||
result.add(cCast(ptrType(cgsymValue(m, "NimStringDesc")), "NIM_NIL"))
|
||||
else:
|
||||
let id = nodeTableTestOrSet(m.dataCache, n, m.labels)
|
||||
var name: string = ""
|
||||
if id == m.labels:
|
||||
# string literal not found in the cache:
|
||||
appcg(m, result, "((#NimStringDesc*) &", [])
|
||||
genStringLiteralDataOnlyV1(m, n.strVal, result)
|
||||
result.add ")"
|
||||
genStringLiteralDataOnlyV1(m, n.strVal, name)
|
||||
else:
|
||||
appcg(m, result, "((#NimStringDesc*) &$1$2)",
|
||||
[m.tmpBase, id])
|
||||
name = m.tmpBase & $id
|
||||
result.add(cCast(ptrType(cgsymValue(m, "NimStringDesc")), cAddr(name)))
|
||||
|
||||
# ------ Version 2: destructor based strings and seqs -----------------------
|
||||
|
||||
@@ -65,7 +80,7 @@ proc genStringLiteralDataOnlyV2(m: BModule, s: string; result: Rope; isConst: bo
|
||||
res.addArrayField(name = "data", elementType = "NIM_CHAR", len = s.len + 1)
|
||||
do:
|
||||
var structInit: StructInitializer
|
||||
res.addStructInitializer(structInit, orderCompliant = true):
|
||||
res.addStructInitializer(structInit, kind = siOrderedStruct):
|
||||
res.addField(structInit, name = "cap"):
|
||||
res.add(bitOr(rope(s.len), "NIM_STRLIT_FLAG"))
|
||||
res.addField(structInit, name = "data"):
|
||||
@@ -74,22 +89,30 @@ proc genStringLiteralDataOnlyV2(m: BModule, s: string; result: Rope; isConst: bo
|
||||
|
||||
proc genStringLiteralV2(m: BModule; n: PNode; isConst: bool; result: var Rope) =
|
||||
let id = nodeTableTestOrSet(m.dataCache, n, m.labels)
|
||||
var litName: string
|
||||
if id == m.labels:
|
||||
let pureLit = getTempName(m)
|
||||
genStringLiteralDataOnlyV2(m, n.strVal, pureLit, isConst)
|
||||
let tmp = getTempName(m)
|
||||
result.add tmp
|
||||
cgsym(m, "NimStrPayload")
|
||||
cgsym(m, "NimStringV2")
|
||||
# string literal not found in the cache:
|
||||
m.s[cfsStrData].addf("static $4 NimStringV2 $1 = {$2, (NimStrPayload*)&$3};$n",
|
||||
[tmp, rope(n.strVal.len), pureLit, rope(if isConst: "const" else: "")])
|
||||
litName = getTempName(m)
|
||||
genStringLiteralDataOnlyV2(m, n.strVal, litName, isConst)
|
||||
else:
|
||||
let tmp = getTempName(m)
|
||||
result.add tmp
|
||||
m.s[cfsStrData].addf("static $4 NimStringV2 $1 = {$2, (NimStrPayload*)&$3};$n",
|
||||
[tmp, rope(n.strVal.len), m.tmpBase & rope(id),
|
||||
rope(if isConst: "const" else: "")])
|
||||
litName = m.tmpBase & $id
|
||||
let tmp = getTempName(m)
|
||||
result.add tmp
|
||||
var res = newBuilder("")
|
||||
res.addVarWithTypeAndInitializer(
|
||||
if isConst: AlwaysConst else: Global,
|
||||
name = tmp):
|
||||
res.add("NimStringV2")
|
||||
do:
|
||||
var strInit: StructInitializer
|
||||
res.addStructInitializer(strInit, kind = siOrderedStruct):
|
||||
res.addField(strInit, name = "len"):
|
||||
res.add(rope(n.strVal.len))
|
||||
res.addField(strInit, name = "p"):
|
||||
res.add(cCast(ptrType("NimStrPayload"), cAddr(litName)))
|
||||
m.s[cfsStrData].add(res)
|
||||
|
||||
proc genStringLiteralV2Const(m: BModule; n: PNode; isConst: bool; result: var Rope) =
|
||||
let id = nodeTableTestOrSet(m.dataCache, n, m.labels)
|
||||
@@ -102,7 +125,12 @@ proc genStringLiteralV2Const(m: BModule; n: PNode; isConst: bool; result: var Ro
|
||||
genStringLiteralDataOnlyV2(m, n.strVal, pureLit, isConst)
|
||||
else:
|
||||
pureLit = m.tmpBase & rope(id)
|
||||
result.addf "{$1, (NimStrPayload*)&$2}", [rope(n.strVal.len), pureLit]
|
||||
var strInit: StructInitializer
|
||||
result.addStructInitializer(strInit, kind = siOrderedStruct):
|
||||
result.addField(strInit, name = "len"):
|
||||
result.add(rope(n.strVal.len))
|
||||
result.addField(strInit, name = "p"):
|
||||
result.add(cCast(ptrType("NimStrPayload"), cAddr(pureLit)))
|
||||
|
||||
# ------ Version selector ---------------------------------------------------
|
||||
|
||||
@@ -118,7 +146,7 @@ proc genStringLiteralDataOnly(m: BModule; s: string; info: TLineInfo;
|
||||
localError(m.config, info, "cannot determine how to produce code for string literal")
|
||||
|
||||
proc genNilStringLiteral(m: BModule; info: TLineInfo; result: var Rope) =
|
||||
appcg(m, result, "((#NimStringDesc*) NIM_NIL)", [])
|
||||
result.add(cCast(ptrType(cgsymValue(m, "NimStringDesc")), "NIM_NIL"))
|
||||
|
||||
proc genStringLiteral(m: BModule; n: PNode; result: var Rope) =
|
||||
case detectStrVersion(m)
|
||||
|
||||
@@ -279,7 +279,7 @@ proc genGotoVar(p: BProc; value: PNode) =
|
||||
else:
|
||||
lineF(p, cpsStmts, "goto NIMSTATE_$#;$n", [value.intVal.rope])
|
||||
|
||||
proc genBracedInit(p: BProc, n: PNode; isConst: bool; optionalType: PType; result: var Rope)
|
||||
proc genBracedInit(p: BProc, n: PNode; isConst: bool; optionalType: PType; result: var Builder)
|
||||
|
||||
proc potentialValueInit(p: BProc; v: PSym; value: PNode; result: var Rope) =
|
||||
if lfDynamicLib in v.loc.flags or sfThread in v.flags or p.hcrOn:
|
||||
|
||||
@@ -340,7 +340,12 @@ proc getSimpleTypeDesc(m: BModule; typ: PType): Rope =
|
||||
of tyNil: result = typeNameOrLiteral(m, typ, "void*")
|
||||
of tyInt..tyUInt64:
|
||||
result = typeNameOrLiteral(m, typ, NumericalTypeToStr[typ.kind])
|
||||
of tyDistinct, tyRange, tyOrdinal: result = getSimpleTypeDesc(m, typ.skipModifier)
|
||||
of tyRange, tyOrdinal: result = getSimpleTypeDesc(m, typ.skipModifier)
|
||||
of tyDistinct:
|
||||
result = getSimpleTypeDesc(m, typ.skipModifier)
|
||||
if isImportedType(typ) and result != "":
|
||||
useHeader(m, typ.sym)
|
||||
result = typ.sym.loc.snippet
|
||||
of tyStatic:
|
||||
if typ.n != nil: result = getSimpleTypeDesc(m, skipModifier typ)
|
||||
else:
|
||||
@@ -716,6 +721,7 @@ proc genRecordFieldsAux(m: BModule; n: PNode,
|
||||
else: internalError(m.config, "genRecordFieldsAux(record case branch)")
|
||||
if unionBody.len != 0:
|
||||
result.addAnonUnion:
|
||||
# XXX this has to be a named field for NIFC
|
||||
result.add(unionBody)
|
||||
of nkSym:
|
||||
let field = n.sym
|
||||
@@ -860,7 +866,8 @@ proc getTypeDescAux(m: BModule; origTyp: PType, check: var IntSet; kind: TypeDes
|
||||
if t != origTyp and origTyp.sym != nil: useHeader(m, origTyp.sym)
|
||||
let sig = hashType(origTyp, m.config)
|
||||
|
||||
result = getTypePre(m, t, sig)
|
||||
# tyDistinct matters if it is an importc type
|
||||
result = getTypePre(m, origTyp.skipTypes(irrelevantForBackend-{tyOwned, tyDistinct}), sig)
|
||||
defer: # defer is the simplest in this case
|
||||
if isImportedType(t) and not m.typeABICache.containsOrIncl(sig):
|
||||
addAbiCheck(m, t, result)
|
||||
|
||||
@@ -97,7 +97,7 @@ proc t(a: TLoc): PType {.inline.} =
|
||||
|
||||
proc lodeTyp(t: PType): PNode =
|
||||
result = newNode(nkEmpty)
|
||||
result.typ = t
|
||||
result.typ() = t
|
||||
|
||||
proc isSimpleConst(typ: PType): bool =
|
||||
let t = skipTypes(typ, abstractVar)
|
||||
|
||||
@@ -55,7 +55,7 @@ proc methodCall*(n: PNode; conf: ConfigRef): PNode =
|
||||
# replace ordinary method by dispatcher method:
|
||||
let disp = getDispatcher(result[0].sym)
|
||||
if disp != nil:
|
||||
result[0].typ = disp.typ
|
||||
result[0].typ() = disp.typ
|
||||
result[0].sym = disp
|
||||
# change the arguments to up/downcasts to fit the dispatcher's parameters:
|
||||
for i in 1..<result.len:
|
||||
|
||||
@@ -161,10 +161,6 @@ type
|
||||
# is their finally. For finally it is parent finally. Otherwise -1
|
||||
idgen: IdGenerator
|
||||
varStates: Table[ItemId, int] # Used to detect if local variable belongs to multiple states
|
||||
stateVarSym: PSym # :state variable. nil if env already introduced by lambdalifting
|
||||
# remove if -d:nimOptIters is default, treating it as always nil
|
||||
nimOptItersEnabled: bool # tracks if -d:nimOptIters is enabled
|
||||
# should be default when issues are fixed, see #24094
|
||||
|
||||
const
|
||||
nkSkip = {nkEmpty..nkNilLit, nkTemplateDef, nkTypeSection, nkStaticStmt,
|
||||
@@ -174,11 +170,8 @@ const
|
||||
localRequiresLifting = -2
|
||||
|
||||
proc newStateAccess(ctx: var Ctx): PNode =
|
||||
if ctx.stateVarSym.isNil:
|
||||
result = rawIndirectAccess(newSymNode(getEnvParam(ctx.fn)),
|
||||
result = rawIndirectAccess(newSymNode(getEnvParam(ctx.fn)),
|
||||
getStateField(ctx.g, ctx.fn), ctx.fn.info)
|
||||
else:
|
||||
result = newSymNode(ctx.stateVarSym)
|
||||
|
||||
proc newStateAssgn(ctx: var Ctx, toValue: PNode): PNode =
|
||||
# Creates state assignment:
|
||||
@@ -196,22 +189,12 @@ proc newEnvVar(ctx: var Ctx, name: string, typ: PType): PSym =
|
||||
result.flags.incl sfNoInit
|
||||
assert(not typ.isNil, "Env var needs a type")
|
||||
|
||||
if not ctx.stateVarSym.isNil:
|
||||
# We haven't gone through labmda lifting yet, so just create a local var,
|
||||
# it will be lifted later
|
||||
if ctx.tempVars.isNil:
|
||||
ctx.tempVars = newNodeI(nkVarSection, ctx.fn.info)
|
||||
addVar(ctx.tempVars, newSymNode(result))
|
||||
else:
|
||||
let envParam = getEnvParam(ctx.fn)
|
||||
# let obj = envParam.typ.lastSon
|
||||
result = addUniqueField(envParam.typ.elementType, result, ctx.g.cache, ctx.idgen)
|
||||
let envParam = getEnvParam(ctx.fn)
|
||||
# let obj = envParam.typ.lastSon
|
||||
result = addUniqueField(envParam.typ.elementType, result, ctx.g.cache, ctx.idgen)
|
||||
|
||||
proc newEnvVarAccess(ctx: Ctx, s: PSym): PNode =
|
||||
if ctx.stateVarSym.isNil:
|
||||
result = rawIndirectAccess(newSymNode(getEnvParam(ctx.fn)), s, ctx.fn.info)
|
||||
else:
|
||||
result = newSymNode(s)
|
||||
result = rawIndirectAccess(newSymNode(getEnvParam(ctx.fn)), s, ctx.fn.info)
|
||||
|
||||
proc newTempVarAccess(ctx: Ctx, s: PSym): PNode =
|
||||
result = newSymNode(s, ctx.fn.info)
|
||||
@@ -263,20 +246,12 @@ proc newTempVarDef(ctx: Ctx, s: PSym, initialValue: PNode): PNode =
|
||||
v = ctx.g.emptyNode
|
||||
newTree(nkVarSection, newTree(nkIdentDefs, newSymNode(s), ctx.g.emptyNode, v))
|
||||
|
||||
proc newEnvVarAsgn(ctx: Ctx, s: PSym, v: PNode): PNode
|
||||
|
||||
proc newTempVar(ctx: var Ctx, typ: PType, parent: PNode, initialValue: PNode = nil): PSym =
|
||||
if ctx.nimOptItersEnabled:
|
||||
result = newSym(skVar, getIdent(ctx.g.cache, ":tmpSlLower" & $ctx.tempVarId), ctx.idgen, ctx.fn, ctx.fn.info)
|
||||
else:
|
||||
result = ctx.newEnvVar(":tmpSlLower" & $ctx.tempVarId, typ)
|
||||
result = newSym(skVar, getIdent(ctx.g.cache, ":tmpSlLower" & $ctx.tempVarId), ctx.idgen, ctx.fn, ctx.fn.info)
|
||||
inc ctx.tempVarId
|
||||
result.typ = typ
|
||||
assert(not typ.isNil, "Temp var needs a type")
|
||||
if ctx.nimOptItersEnabled:
|
||||
parent.add(ctx.newTempVarDef(result, initialValue))
|
||||
elif initialValue != nil:
|
||||
parent.add(ctx.newEnvVarAsgn(result, initialValue))
|
||||
parent.add(ctx.newTempVarDef(result, initialValue))
|
||||
|
||||
proc hasYields(n: PNode): bool =
|
||||
# TODO: This is very inefficient. It traverses the node, looking for nkYieldStmt.
|
||||
@@ -336,12 +311,12 @@ proc newNullifyCurExc(ctx: var Ctx, info: TLineInfo): PNode =
|
||||
let curExc = ctx.newCurExcAccess()
|
||||
curExc.info = info
|
||||
let nilnode = newNode(nkNilLit)
|
||||
nilnode.typ = curExc.typ
|
||||
nilnode.typ() = curExc.typ
|
||||
result = newTree(nkAsgn, curExc, nilnode)
|
||||
|
||||
proc newOr(g: ModuleGraph, a, b: PNode): PNode {.inline.} =
|
||||
result = newTree(nkCall, newSymNode(g.getSysMagic(a.info, "or", mOr)), a, b)
|
||||
result.typ = g.getSysType(a.info, tyBool)
|
||||
result.typ() = g.getSysType(a.info, tyBool)
|
||||
result.info = a.info
|
||||
|
||||
proc collectExceptState(ctx: var Ctx, n: PNode): PNode {.inline.} =
|
||||
@@ -359,7 +334,7 @@ proc collectExceptState(ctx: var Ctx, n: PNode): PNode {.inline.} =
|
||||
newSymNode(g.getSysMagic(c.info, "of", mOf)),
|
||||
g.callCodegenProc("getCurrentException"),
|
||||
c[i])
|
||||
nextCond.typ = ctx.g.getSysType(c.info, tyBool)
|
||||
nextCond.typ() = ctx.g.getSysType(c.info, tyBool)
|
||||
nextCond.info = c.info
|
||||
|
||||
if cond.isNil:
|
||||
@@ -455,24 +430,13 @@ proc newTempVarAsgn(ctx: Ctx, s: PSym, v: PNode): PNode =
|
||||
result = newTree(nkFastAsgn, ctx.newTempVarAccess(s), v)
|
||||
result.info = v.info
|
||||
|
||||
proc newEnvVarAsgn(ctx: Ctx, s: PSym, v: PNode): PNode =
|
||||
# unused with -d:nimOptIters
|
||||
if isEmptyType(v.typ):
|
||||
result = v
|
||||
else:
|
||||
result = newTree(nkFastAsgn, ctx.newEnvVarAccess(s), v)
|
||||
result.info = v.info
|
||||
|
||||
proc addExprAssgn(ctx: Ctx, output, input: PNode, sym: PSym) =
|
||||
var input = input
|
||||
if input.kind == nkStmtListExpr:
|
||||
let (st, res) = exprToStmtList(input)
|
||||
output.add(st)
|
||||
input = res
|
||||
if ctx.nimOptItersEnabled:
|
||||
output.add(ctx.newTempVarAsgn(sym, input))
|
||||
output.add(ctx.newTempVarAsgn(sym, res))
|
||||
else:
|
||||
output.add(ctx.newEnvVarAsgn(sym, input))
|
||||
output.add(ctx.newTempVarAsgn(sym, input))
|
||||
|
||||
proc convertExprBodyToAsgn(ctx: Ctx, exprBody: PNode, res: PSym): PNode =
|
||||
result = newNodeI(nkStmtList, exprBody.info)
|
||||
@@ -480,11 +444,11 @@ proc convertExprBodyToAsgn(ctx: Ctx, exprBody: PNode, res: PSym): PNode =
|
||||
|
||||
proc newNotCall(g: ModuleGraph; e: PNode): PNode =
|
||||
result = newTree(nkCall, newSymNode(g.getSysMagic(e.info, "not", mNot), e.info), e)
|
||||
result.typ = g.getSysType(e.info, tyBool)
|
||||
result.typ() = g.getSysType(e.info, tyBool)
|
||||
|
||||
proc boolLit(g: ModuleGraph; info: TLineInfo; value: bool): PNode =
|
||||
result = newIntLit(g, info, ord value)
|
||||
result.typ = getSysType(g, info, tyBool)
|
||||
result.typ() = getSysType(g, info, tyBool)
|
||||
|
||||
proc captureVar(c: var Ctx, s: PSym) =
|
||||
if c.varStates.getOrDefault(s.itemId) != localRequiresLifting:
|
||||
@@ -522,7 +486,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
|
||||
|
||||
result = newNodeI(nkStmtListExpr, n.info)
|
||||
if n.typ.isNil: internalError(ctx.g.config, "lowerStmtListExprs: constr typ.isNil")
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
|
||||
for i in 0..<n.len:
|
||||
case n[i].kind
|
||||
@@ -549,7 +513,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
|
||||
let isExpr = not isEmptyType(n.typ)
|
||||
if isExpr:
|
||||
result = newNodeI(nkStmtListExpr, n.info)
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
tmp = ctx.newTempVar(n.typ, result)
|
||||
else:
|
||||
result = newNodeI(nkStmtList, n.info)
|
||||
@@ -601,11 +565,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
|
||||
else:
|
||||
internalError(ctx.g.config, "lowerStmtListExpr(nkIf): " & $branch.kind)
|
||||
|
||||
if isExpr:
|
||||
if ctx.nimOptItersEnabled:
|
||||
result.add(ctx.newTempVarAccess(tmp))
|
||||
else:
|
||||
result.add(ctx.newEnvVarAccess(tmp))
|
||||
if isExpr: result.add(ctx.newTempVarAccess(tmp))
|
||||
|
||||
of nkTryStmt, nkHiddenTryStmt:
|
||||
var ns = false
|
||||
@@ -618,7 +578,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
|
||||
|
||||
if isExpr:
|
||||
result = newNodeI(nkStmtListExpr, n.info)
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
let tmp = ctx.newTempVar(n.typ, result)
|
||||
|
||||
n[0] = ctx.convertExprBodyToAsgn(n[0], tmp)
|
||||
@@ -635,10 +595,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
|
||||
else:
|
||||
internalError(ctx.g.config, "lowerStmtListExpr(nkTryStmt): " & $branch.kind)
|
||||
result.add(n)
|
||||
if ctx.nimOptItersEnabled:
|
||||
result.add(ctx.newTempVarAccess(tmp))
|
||||
else:
|
||||
result.add(ctx.newEnvVarAccess(tmp))
|
||||
result.add(ctx.newTempVarAccess(tmp))
|
||||
|
||||
of nkCaseStmt:
|
||||
var ns = false
|
||||
@@ -652,7 +609,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
|
||||
|
||||
if isExpr:
|
||||
result = newNodeI(nkStmtListExpr, n.info)
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
let tmp = ctx.newTempVar(n.typ, result)
|
||||
|
||||
if n[0].kind == nkStmtListExpr:
|
||||
@@ -670,10 +627,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
|
||||
else:
|
||||
internalError(ctx.g.config, "lowerStmtListExpr(nkCaseStmt): " & $branch.kind)
|
||||
result.add(n)
|
||||
if ctx.nimOptItersEnabled:
|
||||
result.add(ctx.newTempVarAccess(tmp))
|
||||
else:
|
||||
result.add(ctx.newEnvVarAccess(tmp))
|
||||
result.add(ctx.newTempVarAccess(tmp))
|
||||
elif n[0].kind == nkStmtListExpr:
|
||||
result = newNodeI(nkStmtList, n.info)
|
||||
let (st, ex) = exprToStmtList(n[0])
|
||||
@@ -692,7 +646,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
|
||||
|
||||
if isExpr:
|
||||
result = newNodeI(nkStmtListExpr, n.info)
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
else:
|
||||
result = newNodeI(nkStmtList, n.info)
|
||||
|
||||
@@ -706,11 +660,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
|
||||
let tmp = ctx.newTempVar(cond.typ, result, cond)
|
||||
# result.add(ctx.newTempVarAsgn(tmp, cond))
|
||||
|
||||
var check: PNode
|
||||
if ctx.nimOptItersEnabled:
|
||||
check = ctx.newTempVarAccess(tmp)
|
||||
else:
|
||||
check = ctx.newEnvVarAccess(tmp)
|
||||
var check = ctx.newTempVarAccess(tmp)
|
||||
if n[0].sym.magic == mOr:
|
||||
check = ctx.g.newNotCall(check)
|
||||
|
||||
@@ -720,18 +670,12 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
|
||||
let (st, ex) = exprToStmtList(cond)
|
||||
ifBody.add(st)
|
||||
cond = ex
|
||||
if ctx.nimOptItersEnabled:
|
||||
ifBody.add(ctx.newTempVarAsgn(tmp, cond))
|
||||
else:
|
||||
ifBody.add(ctx.newEnvVarAsgn(tmp, cond))
|
||||
ifBody.add(ctx.newTempVarAsgn(tmp, cond))
|
||||
|
||||
let ifBranch = newTree(nkElifBranch, check, ifBody)
|
||||
let ifNode = newTree(nkIfStmt, ifBranch)
|
||||
result.add(ifNode)
|
||||
if ctx.nimOptItersEnabled:
|
||||
result.add(ctx.newTempVarAccess(tmp))
|
||||
else:
|
||||
result.add(ctx.newEnvVarAccess(tmp))
|
||||
result.add(ctx.newTempVarAccess(tmp))
|
||||
else:
|
||||
for i in 0..<n.len:
|
||||
if n[i].kind == nkStmtListExpr:
|
||||
@@ -742,10 +686,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
|
||||
if n[i].kind in nkCallKinds: # XXX: This should better be some sort of side effect tracking
|
||||
let tmp = ctx.newTempVar(n[i].typ, result, n[i])
|
||||
# result.add(ctx.newTempVarAsgn(tmp, n[i]))
|
||||
if ctx.nimOptItersEnabled:
|
||||
n[i] = ctx.newTempVarAccess(tmp)
|
||||
else:
|
||||
n[i] = ctx.newEnvVarAccess(tmp)
|
||||
n[i] = ctx.newTempVarAccess(tmp)
|
||||
|
||||
result.add(n)
|
||||
|
||||
@@ -791,7 +732,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
|
||||
if ns:
|
||||
needsSplit = true
|
||||
result = newNodeI(nkStmtListExpr, n.info)
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
let (st, ex) = exprToStmtList(n[^1])
|
||||
result.add(st)
|
||||
n[^1] = ex
|
||||
@@ -861,7 +802,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
|
||||
if ns:
|
||||
needsSplit = true
|
||||
result = newNodeI(nkStmtListExpr, n.info)
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
let (st, ex) = exprToStmtList(n[0])
|
||||
result.add(st)
|
||||
n[0] = ex
|
||||
@@ -873,10 +814,10 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
|
||||
if ns:
|
||||
needsSplit = true
|
||||
result = newNodeI(nkStmtListExpr, n.info)
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
let (st, ex) = exprToStmtList(n[1])
|
||||
n.transitionSonsKind(nkBlockStmt)
|
||||
n.typ = nil
|
||||
n.typ() = nil
|
||||
n[1] = st
|
||||
result.add(n)
|
||||
result.add(ex)
|
||||
@@ -897,9 +838,9 @@ proc newEndFinallyNode(ctx: var Ctx, info: TLineInfo): PNode =
|
||||
# raise
|
||||
let curExc = ctx.newCurExcAccess()
|
||||
let nilnode = newNode(nkNilLit)
|
||||
nilnode.typ = curExc.typ
|
||||
nilnode.typ() = curExc.typ
|
||||
let cmp = newTree(nkCall, newSymNode(ctx.g.getSysMagic(info, "==", mEqRef), info), curExc, nilnode)
|
||||
cmp.typ = ctx.g.getSysType(info, tyBool)
|
||||
cmp.typ() = ctx.g.getSysType(info, tyBool)
|
||||
|
||||
let retStmt =
|
||||
if ctx.nearestFinally == 0:
|
||||
@@ -1244,11 +1185,11 @@ proc newArrayType(g: ModuleGraph; n: int, t: PType; idgen: IdGenerator; owner: P
|
||||
|
||||
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.idgen, 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)
|
||||
elem.typ = ctx.g.getSysType(ctx.fn.info, tyInt16)
|
||||
elem.typ() = ctx.g.getSysType(ctx.fn.info, tyInt16)
|
||||
result.add(elem)
|
||||
|
||||
proc newCatchBody(ctx: var Ctx, info: TLineInfo): PNode {.inline.} =
|
||||
@@ -1271,7 +1212,7 @@ proc newCatchBody(ctx: var Ctx, info: TLineInfo): PNode {.inline.} =
|
||||
let getNextState = newTree(nkBracketExpr,
|
||||
ctx.createExceptionTable(),
|
||||
ctx.newStateAccess())
|
||||
getNextState.typ = intTyp
|
||||
getNextState.typ() = intTyp
|
||||
|
||||
# :state = exceptionTable[:state]
|
||||
result.add(ctx.newStateAssgn(getNextState))
|
||||
@@ -1282,7 +1223,7 @@ proc newCatchBody(ctx: var Ctx, info: TLineInfo): PNode {.inline.} =
|
||||
ctx.g.getSysMagic(info, "==", mEqI).newSymNode(),
|
||||
ctx.newStateAccess(),
|
||||
newIntTypeNode(0, intTyp))
|
||||
cond.typ = boolTyp
|
||||
cond.typ() = boolTyp
|
||||
|
||||
let raiseStmt = newTree(nkRaiseStmt, ctx.g.emptyNode)
|
||||
let ifBranch = newTree(nkElifBranch, cond, raiseStmt)
|
||||
@@ -1295,7 +1236,7 @@ proc newCatchBody(ctx: var Ctx, info: TLineInfo): PNode {.inline.} =
|
||||
ctx.g.getSysMagic(info, "<", mLtI).newSymNode,
|
||||
newIntTypeNode(0, intTyp),
|
||||
ctx.newStateAccess())
|
||||
cond.typ = boolTyp
|
||||
cond.typ() = boolTyp
|
||||
|
||||
let asgn = newTree(nkAsgn, ctx.newUnrollFinallyAccess(info), cond)
|
||||
result.add(asgn)
|
||||
@@ -1306,12 +1247,12 @@ proc newCatchBody(ctx: var Ctx, info: TLineInfo): PNode {.inline.} =
|
||||
ctx.g.getSysMagic(info, "<", mLtI).newSymNode,
|
||||
ctx.newStateAccess(),
|
||||
newIntTypeNode(0, intTyp))
|
||||
cond.typ = boolTyp
|
||||
cond.typ() = boolTyp
|
||||
|
||||
let negateState = newTree(nkCall,
|
||||
ctx.g.getSysMagic(info, "-", mUnaryMinusI).newSymNode,
|
||||
ctx.newStateAccess())
|
||||
negateState.typ = intTyp
|
||||
negateState.typ() = intTyp
|
||||
|
||||
let ifBranch = newTree(nkElifBranch, cond, ctx.newStateAssgn(negateState))
|
||||
let ifStmt = newTree(nkIfStmt, ifBranch)
|
||||
@@ -1343,13 +1284,6 @@ proc wrapIntoStateLoop(ctx: var Ctx, n: PNode): PNode =
|
||||
result.info = n.info
|
||||
|
||||
let localVars = newNodeI(nkStmtList, n.info)
|
||||
if not ctx.stateVarSym.isNil:
|
||||
let varSect = newNodeI(nkVarSection, n.info)
|
||||
addVar(varSect, newSymNode(ctx.stateVarSym))
|
||||
localVars.add(varSect)
|
||||
|
||||
if not ctx.tempVars.isNil:
|
||||
localVars.add(ctx.tempVars)
|
||||
|
||||
let blockStmt = newNodeI(nkBlockStmt, n.info)
|
||||
blockStmt.add(newSymNode(ctx.stateLoopLabel))
|
||||
@@ -1552,21 +1486,11 @@ proc liftLocals(c: var Ctx, n: PNode): PNode =
|
||||
n[i] = liftLocals(c, n[i])
|
||||
|
||||
proc transformClosureIterator*(g: ModuleGraph; idgen: IdGenerator; fn: PSym, n: PNode): PNode =
|
||||
var ctx = Ctx(g: g, fn: fn, idgen: idgen,
|
||||
# should be default when issues are fixed, see #24094:
|
||||
nimOptItersEnabled: isDefined(g.config, "nimOptIters"))
|
||||
var ctx = Ctx(g: g, fn: fn, idgen: idgen)
|
||||
|
||||
if getEnvParam(fn).isNil:
|
||||
if ctx.nimOptItersEnabled:
|
||||
# The transformation should always happen after at least partial lambdalifting
|
||||
# is performed, so that the closure iter environment is always created upfront.
|
||||
doAssert(false, "Env param not created before iter transformation")
|
||||
else:
|
||||
# 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"), idgen, fn, fn.info)
|
||||
ctx.stateVarSym.typ = g.createClosureIterStateType(fn, idgen)
|
||||
# The transformation should always happen after at least partial lambdalifting
|
||||
# is performed, so that the closure iter environment is always created upfront.
|
||||
doAssert(getEnvParam(fn) != nil, "Env param not created before iter transformation")
|
||||
|
||||
ctx.stateLoopLabel = newSym(skLabel, getIdent(ctx.g.cache, ":stateLoop"), idgen, fn, fn.info)
|
||||
var pc = PreprocessContext(finallys: @[], config: g.config, idgen: idgen)
|
||||
@@ -1592,10 +1516,9 @@ proc transformClosureIterator*(g: ModuleGraph; idgen: IdGenerator; fn: PSym, n:
|
||||
let caseDispatcher = newTreeI(nkCaseStmt, n.info,
|
||||
ctx.newStateAccess())
|
||||
|
||||
if ctx.nimOptItersEnabled:
|
||||
# Lamdalifting will not touch our locals, it is our responsibility to lift those that
|
||||
# need it.
|
||||
detectCapturedVars(ctx)
|
||||
# Lamdalifting will not touch our locals, it is our responsibility to lift those that
|
||||
# need it.
|
||||
detectCapturedVars(ctx)
|
||||
|
||||
for s in ctx.states:
|
||||
let body = ctx.transformStateAssignments(s.body)
|
||||
@@ -1604,8 +1527,7 @@ proc transformClosureIterator*(g: ModuleGraph; idgen: IdGenerator; fn: PSym, n:
|
||||
caseDispatcher.add newTreeI(nkElse, n.info, newTreeI(nkReturnStmt, n.info, g.emptyNode))
|
||||
|
||||
result = wrapIntoStateLoop(ctx, caseDispatcher)
|
||||
if ctx.nimOptItersEnabled:
|
||||
result = liftLocals(ctx, result)
|
||||
result = liftLocals(ctx, result)
|
||||
|
||||
when false:
|
||||
echo "TRANSFORM TO STATES: "
|
||||
|
||||
@@ -169,3 +169,5 @@ proc initDefines*(symbols: StringTableRef) =
|
||||
defineSymbol("nimHasGenericsOpenSym2")
|
||||
defineSymbol("nimHasGenericsOpenSym3")
|
||||
defineSymbol("nimHasJsNoLambdaLifting")
|
||||
defineSymbol("nimHasDefaultFloatRoundtrip")
|
||||
defineSymbol("nimHasXorSet")
|
||||
|
||||
@@ -1320,7 +1320,7 @@ proc documentEffect(cache: IdentCache; n, x: PNode, effectType: TSpecialWord, id
|
||||
if t.startsWith("ref "): t = substr(t, 4)
|
||||
effects[i] = newIdentNode(getIdent(cache, t), n.info)
|
||||
# set the type so that the following analysis doesn't screw up:
|
||||
effects[i].typ = real[i].typ
|
||||
effects[i].typ() = real[i].typ
|
||||
|
||||
result = newTreeI(nkExprColonExpr, n.info,
|
||||
newIdentNode(getIdent(cache, $effectType), n.info), effects)
|
||||
|
||||
@@ -275,7 +275,7 @@ proc unpackObject(conf: ConfigRef, x: pointer, typ: PType, n: PNode): PNode =
|
||||
# the nkPar node:
|
||||
if n.isNil:
|
||||
result = newNode(nkTupleConstr)
|
||||
result.typ = typ
|
||||
result.typ() = typ
|
||||
if typ.n.isNil:
|
||||
internalError(conf, "cannot unpack unnamed tuple")
|
||||
unpackObjectAdd(conf, x, typ.n, result)
|
||||
@@ -298,7 +298,7 @@ proc unpackObject(conf: ConfigRef, x: pointer, typ: PType, n: PNode): PNode =
|
||||
proc unpackArray(conf: ConfigRef, x: pointer, typ: PType, n: PNode): PNode =
|
||||
if n.isNil:
|
||||
result = newNode(nkBracket)
|
||||
result.typ = typ
|
||||
result.typ() = typ
|
||||
newSeq(result.sons, lengthOrd(conf, typ).toInt)
|
||||
else:
|
||||
result = n
|
||||
@@ -319,7 +319,7 @@ proc unpack(conf: ConfigRef, x: pointer, typ: PType, n: PNode): PNode =
|
||||
template aw(k, v, field: untyped): untyped =
|
||||
if n.isNil:
|
||||
result = newNode(k)
|
||||
result.typ = typ
|
||||
result.typ() = typ
|
||||
else:
|
||||
# check we have the right field:
|
||||
result = n
|
||||
@@ -333,12 +333,12 @@ proc unpack(conf: ConfigRef, x: pointer, typ: PType, n: PNode): PNode =
|
||||
template setNil() =
|
||||
if n.isNil:
|
||||
result = newNode(nkNilLit)
|
||||
result.typ = typ
|
||||
result.typ() = typ
|
||||
else:
|
||||
reset n[]
|
||||
result = n
|
||||
result[] = TNode(kind: nkNilLit)
|
||||
result.typ = typ
|
||||
result.typ() = typ
|
||||
|
||||
template awi(kind, v: untyped): untyped = aw(kind, v, intVal)
|
||||
template awf(kind, v: untyped): untyped = aw(kind, v, floatVal)
|
||||
@@ -427,7 +427,7 @@ proc fficast*(conf: ConfigRef, x: PNode, destTyp: PType): PNode =
|
||||
# cast through a pointer needs a new inner object:
|
||||
let y = if x.kind == nkRefTy: newNodeI(nkRefTy, x.info, 1)
|
||||
else: x.copyTree
|
||||
y.typ = x.typ
|
||||
y.typ() = x.typ
|
||||
result = unpack(conf, a, destTyp, y)
|
||||
dealloc a
|
||||
|
||||
@@ -481,7 +481,7 @@ proc callForeignFunction*(conf: ConfigRef, fn: PNode, fntyp: PType,
|
||||
if aTyp.isNil:
|
||||
internalAssert conf, i+1 < fntyp.len
|
||||
aTyp = fntyp[i+1]
|
||||
args[i+start].typ = aTyp
|
||||
args[i+start].typ() = aTyp
|
||||
sig[i] = mapType(conf, aTyp)
|
||||
if sig[i].isNil: globalError(conf, info, "cannot map FFI type")
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) =
|
||||
if x == nil:
|
||||
x = copySym(s, c.idgen)
|
||||
# sem'check needs to set the owner properly later, see bug #9476
|
||||
x.owner = nil # c.genSymOwner
|
||||
setOwner(x, nil) # c.genSymOwner
|
||||
#if x.kind == skParam and x.owner.kind == skModule:
|
||||
# internalAssert c.config, false
|
||||
idTablePut(c.mapping, s, x)
|
||||
@@ -182,7 +182,7 @@ proc wrapInComesFrom*(info: TLineInfo; sym: PSym; res: PNode): PNode =
|
||||
d.add newSymNode(sym, info)
|
||||
result.add d
|
||||
result.add res
|
||||
result.typ = res.typ
|
||||
result.typ() = res.typ
|
||||
|
||||
proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym;
|
||||
conf: ConfigRef;
|
||||
|
||||
@@ -1104,7 +1104,7 @@ proc settype(n: PNode): PType =
|
||||
|
||||
proc buildOf(it, loc: PNode; o: Operators): PNode =
|
||||
var s = newNodeI(nkCurly, it.info, it.len-1)
|
||||
s.typ = settype(loc)
|
||||
s.typ() = settype(loc)
|
||||
for i in 0..<it.len-1: s[i] = it[i]
|
||||
result = newNodeI(nkCall, it.info, 3)
|
||||
result[0] = newSymNode(o.opContains)
|
||||
@@ -1170,7 +1170,7 @@ proc buildProperFieldCheck(access, check: PNode; o: Operators): PNode =
|
||||
# set field name to discriminator field name
|
||||
a[1] = check[2]
|
||||
# set discriminator field type: important for `neg`
|
||||
a.typ = check[2].typ
|
||||
a.typ() = check[2].typ
|
||||
result[2] = a
|
||||
# 'access.kind != nkDotExpr' can happen for object constructors
|
||||
# which we don't check yet
|
||||
|
||||
@@ -838,7 +838,7 @@ proc loadNodes*(c: var PackedDecoder; g: var PackedModuleGraph; thisModule: int;
|
||||
of nkSym:
|
||||
result.sym = loadSym(c, g, thisModule, PackedItemId(module: LitId(0), item: tree[n].soperand))
|
||||
if result.typ == nil:
|
||||
result.typ = result.sym.typ
|
||||
result.typ() = result.sym.typ
|
||||
of externIntLit:
|
||||
result.intVal = g[thisModule].fromDisk.numbers[n.litId]
|
||||
of nkStrLit..nkTripleStrLit:
|
||||
@@ -852,7 +852,7 @@ proc loadNodes*(c: var PackedDecoder; g: var PackedModuleGraph; thisModule: int;
|
||||
transitionNoneToSym(result)
|
||||
result.sym = loadSym(c, g, thisModule, PackedItemId(module: n1.litId, item: tree[n2].soperand))
|
||||
if result.typ == nil:
|
||||
result.typ = result.sym.typ
|
||||
result.typ() = result.sym.typ
|
||||
else:
|
||||
for n0 in sonsReadonly(tree, n):
|
||||
result.addAllowNil loadNodes(c, g, thisModule, tree, n0)
|
||||
@@ -942,7 +942,7 @@ proc symBodyFromPacked(c: var PackedDecoder; g: var PackedModuleGraph;
|
||||
result.guard = loadSym(c, g, si, s.guard)
|
||||
result.bitsize = s.bitsize
|
||||
result.alignment = s.alignment
|
||||
result.owner = loadSym(c, g, si, s.owner)
|
||||
setOwner(result, loadSym(c, g, si, s.owner))
|
||||
let externalName = g[si].fromDisk.strings[s.externalName]
|
||||
if externalName != "":
|
||||
result.loc.snippet = externalName
|
||||
@@ -998,7 +998,7 @@ proc typeHeaderFromPacked(c: var PackedDecoder; g: var PackedModuleGraph;
|
||||
proc typeBodyFromPacked(c: var PackedDecoder; g: var PackedModuleGraph;
|
||||
t: PackedType; si, item: int32; result: PType) =
|
||||
result.sym = loadSym(c, g, si, t.sym)
|
||||
result.owner = loadSym(c, g, si, t.owner)
|
||||
setOwner(result, loadSym(c, g, si, t.owner))
|
||||
when false:
|
||||
for op, item in pairs t.attachedOps:
|
||||
result.attachedOps[op] = loadSym(c, g, si, item)
|
||||
@@ -1062,7 +1062,7 @@ proc setupLookupTables(g: var PackedModuleGraph; conf: ConfigRef; cache: IdentCa
|
||||
name: getIdent(cache, splitFile(filename).name),
|
||||
info: newLineInfo(fileIdx, 1, 1),
|
||||
position: int(fileIdx))
|
||||
m.module.owner = getPackage(conf, cache, fileIdx)
|
||||
setOwner(m.module, getPackage(conf, cache, fileIdx))
|
||||
m.module.flags = m.fromDisk.moduleFlags
|
||||
|
||||
proc loadToReplayNodes(g: var PackedModuleGraph; conf: ConfigRef; cache: IdentCache;
|
||||
|
||||
@@ -332,7 +332,7 @@ proc genMarkCyclic(c: var Con; result, dest: PNode) =
|
||||
result.add callCodegenProc(c.graph, "nimMarkCyclic", dest.info, dest)
|
||||
else:
|
||||
let xenv = genBuiltin(c.graph, c.idgen, mAccessEnv, "accessEnv", dest)
|
||||
xenv.typ = getSysType(c.graph, dest.info, tyPointer)
|
||||
xenv.typ() = getSysType(c.graph, dest.info, tyPointer)
|
||||
result.add callCodegenProc(c.graph, "nimMarkCyclic", dest.info, xenv)
|
||||
|
||||
proc genCopyNoCheck(c: var Con; dest, ri: PNode; a: TTypeAttachedOp): PNode =
|
||||
@@ -408,7 +408,7 @@ proc genWasMoved(c: var Con, n: PNode): PNode =
|
||||
proc genDefaultCall(t: PType; c: Con; info: TLineInfo): PNode =
|
||||
result = newNodeI(nkCall, info)
|
||||
result.add(newSymNode(createMagic(c.graph, c.idgen, "default", mDefault)))
|
||||
result.typ = t
|
||||
result.typ() = t
|
||||
|
||||
proc destructiveMoveVar(n: PNode; c: var Con; s: var Scope): PNode =
|
||||
# generate: (let tmp = v; reset(v); tmp)
|
||||
@@ -822,9 +822,9 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode; tmpFlags = {sfSing
|
||||
n[1].typ.skipTypes(abstractInst-{tyOwned}).kind == tyOwned:
|
||||
# allow conversions from owned to unowned via this little hack:
|
||||
let nTyp = n[1].typ
|
||||
n[1].typ = n.typ
|
||||
n[1].typ() = n.typ
|
||||
result[1] = p(n[1], c, s, sinkArg)
|
||||
result[1].typ = nTyp
|
||||
result[1].typ() = nTyp
|
||||
else:
|
||||
result[1] = p(n[1], c, s, sinkArg)
|
||||
elif n.kind in {nkObjDownConv, nkObjUpConv}:
|
||||
@@ -1022,9 +1022,9 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode; tmpFlags = {sfSing
|
||||
n[1].typ.skipTypes(abstractInst-{tyOwned}).kind == tyOwned:
|
||||
# allow conversions from owned to unowned via this little hack:
|
||||
let nTyp = n[1].typ
|
||||
n[1].typ = n.typ
|
||||
n[1].typ() = n.typ
|
||||
result[1] = p(n[1], c, s, mode)
|
||||
result[1].typ = nTyp
|
||||
result[1].typ() = nTyp
|
||||
else:
|
||||
result[1] = p(n[1], c, s, mode)
|
||||
|
||||
|
||||
@@ -1592,7 +1592,7 @@ proc genAddr(p: PProc, n: PNode, r: var TCompRes) =
|
||||
if n.kind == nkHiddenAddr:
|
||||
x = n[0][0]
|
||||
if n.typ.skipTypes(abstractVar).kind != tyOpenArray:
|
||||
x.typ = n.typ
|
||||
x.typ() = n.typ
|
||||
gen(p, x, r)
|
||||
of nkHiddenAddr:
|
||||
gen(p, n[0], r)
|
||||
@@ -2458,6 +2458,7 @@ proc genMagic(p: PProc, n: PNode, r: var TCompRes) =
|
||||
of mMulSet: binaryExpr(p, n, r, "SetMul", "SetMul($1, $2)")
|
||||
of mPlusSet: binaryExpr(p, n, r, "SetPlus", "SetPlus($1, $2)")
|
||||
of mMinusSet: binaryExpr(p, n, r, "SetMinus", "SetMinus($1, $2)")
|
||||
of mXorSet: binaryExpr(p, n, r, "SetXor", "SetXor($1, $2)")
|
||||
of mIncl: binaryExpr(p, n, r, "", "$1[$2] = true")
|
||||
of mExcl: binaryExpr(p, n, r, "", "delete $1[$2]")
|
||||
of mInSet:
|
||||
|
||||
@@ -150,7 +150,7 @@ template isIterator*(owner: PSym): bool =
|
||||
|
||||
proc createEnvObj(g: ModuleGraph; idgen: IdGenerator; owner: PSym; info: TLineInfo): PType =
|
||||
result = createObj(g, idgen, owner, info, final=false)
|
||||
if owner.isIterator or not isDefined(g.config, "nimOptIters"):
|
||||
if owner.isIterator:
|
||||
rawAddField(result, createStateField(g, owner, idgen))
|
||||
|
||||
proc getClosureIterResult*(g: ModuleGraph; iter: PSym; idgen: IdGenerator): PSym =
|
||||
@@ -175,6 +175,7 @@ proc addHiddenParam(routine: PSym, param: PSym) =
|
||||
#echo "produced environment: ", param.id, " for ", routine.id
|
||||
|
||||
proc getEnvParam*(routine: PSym): PSym =
|
||||
if routine.ast.isNil: return nil
|
||||
let params = routine.ast[paramsPos]
|
||||
let hidden = lastSon(params)
|
||||
if hidden.kind == nkSym and hidden.sym.kind == skParam and hidden.sym.name.s == paramName:
|
||||
@@ -228,13 +229,6 @@ proc makeClosure*(g: ModuleGraph; idgen: IdGenerator; prc: PSym; env: PNode; inf
|
||||
if tfHasAsgn in result.typ.flags or optSeqDestructors in g.config.globalOptions:
|
||||
prc.flags.incl sfInjectDestructors
|
||||
|
||||
proc interestingIterVar(s: PSym): bool {.inline.} =
|
||||
# unused with -d:nimOptIters
|
||||
# XXX optimization: Only lift the variable if it lives across
|
||||
# yield/return boundaries! This can potentially speed up
|
||||
# closure iterators quite a bit.
|
||||
result = s.kind in {skResult, skVar, skLet, skTemp, skForVar} and sfGlobal notin s.flags
|
||||
|
||||
template liftingHarmful(conf: ConfigRef; owner: PSym): bool =
|
||||
## lambda lifting can be harmful for JS-like code generators.
|
||||
let isCompileTime = sfCompileTime in owner.flags or owner.kind == skMacro
|
||||
@@ -281,16 +275,6 @@ proc liftIterSym*(g: ModuleGraph; n: PNode; idgen: IdGenerator; owner: PSym): PN
|
||||
createTypeBoundOpsLL(g, env.typ, n.info, idgen, owner)
|
||||
result.add makeClosure(g, idgen, iter, env, n.info)
|
||||
|
||||
proc freshVarForClosureIter*(g: ModuleGraph; s: PSym; idgen: IdGenerator; owner: PSym): PNode =
|
||||
# unused with -d:nimOptIters
|
||||
let envParam = getHiddenParam(g, owner)
|
||||
let obj = envParam.typ.skipTypes({tyOwned, tyRef, tyPtr})
|
||||
let field = addField(obj, s, g.cache, idgen)
|
||||
|
||||
var access = newSymNode(envParam)
|
||||
assert obj.kind == tyObject
|
||||
result = rawIndirectAccess(access, field, s.info)
|
||||
|
||||
# ------------------ new stuff -------------------------------------------
|
||||
|
||||
proc markAsClosure(g: ModuleGraph; owner: PSym; n: PNode) =
|
||||
@@ -339,7 +323,7 @@ proc getEnvTypeForOwner(c: var DetectionPass; owner: PSym;
|
||||
result = c.ownerToType.getOrDefault(owner.id)
|
||||
if result.isNil:
|
||||
let env = getEnvParam(owner)
|
||||
if env.isNil or not owner.isIterator or not isDefined(c.graph.config, "nimOptIters"):
|
||||
if env.isNil or not owner.isIterator:
|
||||
result = newType(tyRef, c.idgen, owner)
|
||||
let obj = createEnvObj(c.graph, c.idgen, owner, info)
|
||||
rawAddSon(result, obj)
|
||||
@@ -436,6 +420,12 @@ proc addClosureParam(c: var DetectionPass; fn: PSym; info: TLineInfo) =
|
||||
localError(c.graph.config, fn.info, "internal error: inconsistent environment type")
|
||||
#echo "adding closure to ", fn.name.s
|
||||
|
||||
proc iterEnvHasUpField(g: ModuleGraph, iter: PSym): bool =
|
||||
let cp = getEnvParam(iter)
|
||||
doAssert(cp != nil, "Env param not present in iter")
|
||||
let upField = lookupInRecord(cp.typ.skipTypes({tyOwned, tyRef, tyPtr}).n, getIdent(g.cache, upName))
|
||||
upField != nil
|
||||
|
||||
proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
|
||||
case n.kind
|
||||
of nkSym:
|
||||
@@ -454,23 +444,12 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
|
||||
let body = transformBody(c.graph, c.idgen, s, {useCache})
|
||||
detectCapturedVars(body, s, c)
|
||||
let ow = s.skipGenericOwner
|
||||
let innerClosure = innerProc and s.typ.callConv == ccClosure and not s.isIterator
|
||||
let innerClosure = innerProc and s.typ.callConv == ccClosure and (not s.isIterator or iterEnvHasUpField(c.graph, s))
|
||||
let interested = interestingVar(s)
|
||||
if ow == owner:
|
||||
if owner.isIterator:
|
||||
c.somethingToDo = true
|
||||
addClosureParam(c, owner, n.info)
|
||||
if not isDefined(c.graph.config, "nimOptIters") and interestingIterVar(s):
|
||||
if not c.capturedVars.contains(s.id):
|
||||
if not c.inTypeOf: c.capturedVars.incl(s.id)
|
||||
let obj = getHiddenParam(c.graph, owner).typ.skipTypes({tyOwned, tyRef, tyPtr})
|
||||
#let obj = c.getEnvTypeForOwner(s.owner).skipTypes({tyOwned, tyRef, tyPtr})
|
||||
|
||||
if s.name.id == getIdent(c.graph.cache, ":state").id:
|
||||
obj.n[0].sym.flags.incl sfNoInit
|
||||
obj.n[0].sym.itemId = ItemId(module: s.itemId.module, item: -s.itemId.item)
|
||||
else:
|
||||
discard addField(obj, s, c.graph.cache, c.idgen)
|
||||
# direct or indirect dependency:
|
||||
elif innerClosure or interested:
|
||||
discard """
|
||||
@@ -630,7 +609,7 @@ proc rawClosureCreation(owner: PSym;
|
||||
let unowned = c.unownedEnvVars[owner.id]
|
||||
assert unowned != nil
|
||||
let env2 = copyTree(env)
|
||||
env2.typ = unowned.typ
|
||||
env2.typ() = unowned.typ
|
||||
result.add newAsgnStmt(unowned, env2, env.info)
|
||||
createTypeBoundOpsLL(d.graph, unowned.typ, env.info, d.idgen, owner)
|
||||
|
||||
@@ -670,16 +649,27 @@ proc finishClosureCreation(owner: PSym; d: var DetectionPass; c: LiftingPass;
|
||||
res.add newAsgnStmt(unowned, nilLit, info)
|
||||
createTypeBoundOpsLL(d.graph, unowned.typ, info, d.idgen, owner)
|
||||
|
||||
proc closureCreationForIter(iter: PNode;
|
||||
proc getUpForIter(g: ModuleGraph; owner, iterOwner: PSym, expectedUpTyp: PType): PNode =
|
||||
var p = getHiddenParam(g, owner)
|
||||
var res = p.newSymNode
|
||||
while res.typ.skipTypes({tyOwned, tyRef, tyPtr}) != expectedUpTyp:
|
||||
let upField = lookupInRecord(p.typ.skipTypes({tyOwned, tyRef, tyPtr}).n, getIdent(g.cache, upName))
|
||||
if upField == nil:
|
||||
return nil
|
||||
p = upField
|
||||
res = rawIndirectAccess(res, upField, p.info)
|
||||
res
|
||||
|
||||
proc closureCreationForIter(owner: PSym, iter: 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), d.idgen, owner, iter.info)
|
||||
let iterOwner = iter.sym.skipGenericOwner
|
||||
var v = newSym(skVar, getIdent(d.graph.cache, envName), d.idgen, iterOwner, 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)
|
||||
if iterOwner.isIterator:
|
||||
let it = getHiddenParam(d.graph, iterOwner)
|
||||
addUniqueField(it.typ.skipTypes({tyOwned, tyRef, tyPtr}), v, d.graph.cache, d.idgen)
|
||||
vnode = indirectAccess(newSymNode(it), v, v.info)
|
||||
else:
|
||||
@@ -688,12 +678,14 @@ proc closureCreationForIter(iter: PNode;
|
||||
addVar(vs, vnode)
|
||||
result.add(vs)
|
||||
result.add genCreateEnv(vnode)
|
||||
createTypeBoundOpsLL(d.graph, vnode.typ, iter.info, d.idgen, owner)
|
||||
createTypeBoundOpsLL(d.graph, vnode.typ, iter.info, d.idgen, iterOwner)
|
||||
|
||||
let upField = lookupInRecord(v.typ.skipTypes({tyOwned, tyRef, tyPtr}).n, getIdent(d.graph.cache, upName))
|
||||
if upField != nil:
|
||||
let u = setupEnvVar(owner, d, c, iter.info)
|
||||
if u.typ.skipTypes({tyOwned, tyRef, tyPtr}) == upField.typ.skipTypes({tyOwned, tyRef, tyPtr}):
|
||||
let expectedUpTyp = upField.typ.skipTypes({tyOwned, tyRef, tyPtr})
|
||||
let u = if iterOwner == owner: setupEnvVar(iterOwner, d, c, iter.info)
|
||||
else: getUpForIter(d.graph, owner, iterOwner, expectedUpTyp)
|
||||
if u != nil and u.typ.skipTypes({tyOwned, tyRef, tyPtr}) == expectedUpTyp:
|
||||
result.add(newAsgnStmt(rawIndirectAccess(vnode, upField, iter.info),
|
||||
u, iter.info))
|
||||
else:
|
||||
@@ -727,7 +719,7 @@ proc symToClosure(n: PNode; owner: PSym; d: var DetectionPass;
|
||||
let available = getHiddenParam(d.graph, owner)
|
||||
result = makeClosure(d.graph, d.idgen, s, available.newSymNode, n.info)
|
||||
elif s.isIterator:
|
||||
result = closureCreationForIter(n, d, c)
|
||||
result = closureCreationForIter(owner, n, d, c)
|
||||
elif s.skipGenericOwner == owner:
|
||||
# direct dependency, so use the outer's env variable:
|
||||
result = makeClosure(d.graph, d.idgen, s, setupEnvVar(owner, d, c, n.info), n.info)
|
||||
@@ -774,8 +766,6 @@ proc liftCapturedVars(n: PNode; owner: PSym; d: var DetectionPass;
|
||||
elif s.id in d.capturedVars:
|
||||
if s.owner != owner:
|
||||
result = accessViaEnvParam(d.graph, n, owner)
|
||||
elif owner.isIterator and not isDefined(d.graph.config, "nimOptIters") and interestingIterVar(s):
|
||||
result = accessViaEnvParam(d.graph, n, owner)
|
||||
else:
|
||||
result = accessViaEnvVar(n, owner, d, c)
|
||||
of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit, nkComesFrom,
|
||||
@@ -796,7 +786,7 @@ proc liftCapturedVars(n: PNode; owner: PSym; d: var DetectionPass;
|
||||
let oldInContainer = c.inContainer
|
||||
c.inContainer = 0
|
||||
let m = newSymNode(n[namePos].sym)
|
||||
m.typ = n.typ
|
||||
m.typ() = n.typ
|
||||
result = liftCapturedVars(m, owner, d, c)
|
||||
c.inContainer = oldInContainer
|
||||
of nkHiddenStdConv:
|
||||
@@ -893,7 +883,7 @@ proc liftLambdas*(g: ModuleGraph; fn: PSym, body: PNode; tooEarly: var bool;
|
||||
# ignore forward declaration:
|
||||
result = body
|
||||
tooEarly = true
|
||||
if fn.isIterator and isDefined(g.config, "nimOptIters"):
|
||||
if fn.isIterator:
|
||||
var d = initDetectionPass(g, fn, idgen)
|
||||
addClosureParam(d, fn, body.info)
|
||||
else:
|
||||
|
||||
@@ -49,7 +49,7 @@ proc at(a, i: PNode, elemType: PType): PNode =
|
||||
result = newNodeI(nkBracketExpr, a.info, 2)
|
||||
result[0] = a
|
||||
result[1] = i
|
||||
result.typ = elemType
|
||||
result.typ() = elemType
|
||||
|
||||
proc destructorOverridden(g: ModuleGraph; t: PType): bool =
|
||||
let op = getAttachedOp(g, t, attachedDestructor)
|
||||
@@ -68,7 +68,7 @@ proc dotField(x: PNode, f: PSym): PNode =
|
||||
else:
|
||||
result[0] = x
|
||||
result[1] = newSymNode(f, x.info)
|
||||
result.typ = f.typ
|
||||
result.typ() = f.typ
|
||||
|
||||
proc newAsgnStmt(le, ri: PNode): PNode =
|
||||
result = newNodeI(nkAsgn, le.info, 2)
|
||||
@@ -88,7 +88,7 @@ proc defaultOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
body.add newAsgnStmt(x, y)
|
||||
elif c.kind == attachedDestructor and c.addMemReset:
|
||||
let call = genBuiltin(c, mDefault, "default", x)
|
||||
call.typ = t
|
||||
call.typ() = t
|
||||
body.add newAsgnStmt(x, call)
|
||||
elif c.kind == attachedWasMoved:
|
||||
body.add genBuiltin(c, mWasMoved, "`=wasMoved`", x)
|
||||
@@ -105,7 +105,7 @@ proc genWhileLoop(c: var TLiftCtx; i, dest: PNode): PNode =
|
||||
result = newNodeI(nkWhileStmt, c.info, 2)
|
||||
let cmp = genBuiltin(c, mLtI, "<", i)
|
||||
cmp.add genLen(c.g, dest)
|
||||
cmp.typ = getSysType(c.g, c.info, tyBool)
|
||||
cmp.typ() = getSysType(c.g, c.info, tyBool)
|
||||
result[0] = cmp
|
||||
result[1] = newNodeI(nkStmtList, c.info)
|
||||
|
||||
@@ -127,10 +127,10 @@ proc genContainerOf(c: var TLiftCtx; objType: PType, field, x: PSym): PNode =
|
||||
dotExpr.add newSymNode(field)
|
||||
|
||||
let offsetOf = genBuiltin(c, mOffsetOf, "offsetof", dotExpr)
|
||||
offsetOf.typ = intType
|
||||
offsetOf.typ() = intType
|
||||
|
||||
let minusExpr = genBuiltin(c, mSubI, "-", castExpr1)
|
||||
minusExpr.typ = intType
|
||||
minusExpr.typ() = intType
|
||||
minusExpr.add offsetOf
|
||||
|
||||
let objPtr = makePtrType(objType.owner, objType, c.idgen)
|
||||
@@ -265,7 +265,7 @@ proc fillBodyObjT(c: var TLiftCtx; t: PType, body, x, y: PNode) =
|
||||
# because the wasMoved(dest) call would zero out src, if dest aliases src.
|
||||
var cond = newTree(nkCall, newSymNode(c.g.getSysMagic(c.info, "==", mEqRef)),
|
||||
newTreeIT(nkAddr, c.info, makePtrType(c.fn, x.typ, c.idgen), x), newTreeIT(nkAddr, c.info, makePtrType(c.fn, y.typ, c.idgen), y))
|
||||
cond.typ = getSysType(c.g, x.info, tyBool)
|
||||
cond.typ() = getSysType(c.g, x.info, tyBool)
|
||||
body.add genIf(c, cond, newTreeI(nkReturnStmt, c.info, newNodeI(nkEmpty, c.info)))
|
||||
var temp = newSym(skTemp, getIdent(c.g.cache, lowerings.genPrefix), c.idgen, c.fn, c.info)
|
||||
temp.typ = x.typ
|
||||
@@ -296,7 +296,7 @@ proc fillBodyObjT(c: var TLiftCtx; t: PType, body, x, y: PNode) =
|
||||
|
||||
proc boolLit*(g: ModuleGraph; info: TLineInfo; value: bool): PNode =
|
||||
result = newIntLit(g, info, ord value)
|
||||
result.typ = getSysType(g, info, tyBool)
|
||||
result.typ() = getSysType(g, info, tyBool)
|
||||
|
||||
proc getCycleParam(c: TLiftCtx): PNode =
|
||||
assert c.kind in {attachedAsgn, attachedDup}
|
||||
@@ -545,18 +545,18 @@ proc newSeqCall(c: var TLiftCtx; x, y: PNode): PNode =
|
||||
# don't call genAddr(c, x) here:
|
||||
result = genBuiltin(c, mNewSeq, "newSeq", x)
|
||||
let lenCall = genBuiltin(c, mLengthSeq, "len", y)
|
||||
lenCall.typ = getSysType(c.g, x.info, tyInt)
|
||||
lenCall.typ() = getSysType(c.g, x.info, tyInt)
|
||||
result.add lenCall
|
||||
|
||||
proc setLenStrCall(c: var TLiftCtx; x, y: PNode): PNode =
|
||||
let lenCall = genBuiltin(c, mLengthStr, "len", y)
|
||||
lenCall.typ = getSysType(c.g, x.info, tyInt)
|
||||
lenCall.typ() = getSysType(c.g, x.info, tyInt)
|
||||
result = genBuiltin(c, mSetLengthStr, "setLen", x) # genAddr(g, x))
|
||||
result.add lenCall
|
||||
|
||||
proc setLenSeqCall(c: var TLiftCtx; t: PType; x, y: PNode): PNode =
|
||||
let lenCall = genBuiltin(c, mLengthSeq, "len", y)
|
||||
lenCall.typ = getSysType(c.g, x.info, tyInt)
|
||||
lenCall.typ() = getSysType(c.g, x.info, tyInt)
|
||||
var op = getSysMagic(c.g, x.info, "setLen", mSetLengthSeq)
|
||||
op = instantiateGeneric(c, op, t, t)
|
||||
result = newTree(nkCall, newSymNode(op, x.info), x, lenCall)
|
||||
@@ -579,7 +579,7 @@ proc checkSelfAssignment(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
newTreeIT(nkAddr, c.info, makePtrType(c.fn, x.typ, c.idgen), x),
|
||||
newTreeIT(nkAddr, c.info, makePtrType(c.fn, y.typ, c.idgen), y)
|
||||
)
|
||||
cond.typ = getSysType(c.g, c.info, tyBool)
|
||||
cond.typ() = getSysType(c.g, c.info, tyBool)
|
||||
body.add genIf(c, cond, newTreeI(nkReturnStmt, c.info, newNodeI(nkEmpty, c.info)))
|
||||
|
||||
proc fillSeqOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
@@ -720,7 +720,7 @@ proc atomicRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
if isFinal(elemType):
|
||||
addDestructorCall(c, elemType, actions, genDeref(tmp, nkDerefExpr))
|
||||
var alignOf = genBuiltin(c, mAlignOf, "alignof", newNodeIT(nkType, c.info, elemType))
|
||||
alignOf.typ = getSysType(c.g, c.info, tyInt)
|
||||
alignOf.typ() = getSysType(c.g, c.info, tyInt)
|
||||
actions.add callCodegenProc(c.g, "nimRawDispose", c.info, tmp, alignOf)
|
||||
else:
|
||||
addDestructorCall(c, elemType, newNodeI(nkStmtList, c.info), genDeref(tmp, nkDerefExpr))
|
||||
@@ -730,7 +730,7 @@ proc atomicRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
if isCyclic:
|
||||
if isFinal(elemType):
|
||||
let typInfo = genBuiltin(c, mGetTypeInfoV2, "getTypeInfoV2", newNodeIT(nkType, x.info, elemType))
|
||||
typInfo.typ = getSysType(c.g, c.info, tyPointer)
|
||||
typInfo.typ() = getSysType(c.g, c.info, tyPointer)
|
||||
cond = callCodegenProc(c.g, "nimDecRefIsLastCyclicStatic", c.info, tmp, typInfo)
|
||||
else:
|
||||
cond = callCodegenProc(c.g, "nimDecRefIsLastCyclicDyn", c.info, tmp)
|
||||
@@ -738,7 +738,7 @@ proc atomicRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
cond = callCodegenProc(c.g, "nimDecRefIsLastDyn", c.info, x)
|
||||
else:
|
||||
cond = callCodegenProc(c.g, "nimDecRefIsLast", c.info, x)
|
||||
cond.typ = getSysType(c.g, x.info, tyBool)
|
||||
cond.typ() = getSysType(c.g, x.info, tyBool)
|
||||
|
||||
case c.kind
|
||||
of attachedSink:
|
||||
@@ -765,7 +765,7 @@ proc atomicRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
if isCyclic:
|
||||
if isFinal(elemType):
|
||||
let typInfo = genBuiltin(c, mGetTypeInfoV2, "getTypeInfoV2", newNodeIT(nkType, x.info, elemType))
|
||||
typInfo.typ = getSysType(c.g, c.info, tyPointer)
|
||||
typInfo.typ() = getSysType(c.g, c.info, tyPointer)
|
||||
body.add callCodegenProc(c.g, "nimTraceRef", c.info, genAddrOf(x, c.idgen), typInfo, y)
|
||||
else:
|
||||
# If the ref is polymorphic we have to account for this
|
||||
@@ -786,7 +786,7 @@ proc atomicClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
## Closures are really like refs except they always use a virtual destructor
|
||||
## and we need to do the refcounting only on the ref field which we call 'xenv':
|
||||
let xenv = genBuiltin(c, mAccessEnv, "accessEnv", x)
|
||||
xenv.typ = getSysType(c.g, c.info, tyPointer)
|
||||
xenv.typ() = getSysType(c.g, c.info, tyPointer)
|
||||
|
||||
let isCyclic = c.g.config.selectedGC == gcOrc
|
||||
let tmp =
|
||||
@@ -802,7 +802,7 @@ proc atomicClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
if isCyclic: "nimDecRefIsLastCyclicDyn"
|
||||
else: "nimDecRefIsLast"
|
||||
let cond = callCodegenProc(c.g, decRefProc, c.info, tmp)
|
||||
cond.typ = getSysType(c.g, x.info, tyBool)
|
||||
cond.typ() = getSysType(c.g, x.info, tyBool)
|
||||
|
||||
case c.kind
|
||||
of attachedSink:
|
||||
@@ -814,7 +814,7 @@ proc atomicClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
body.add newAsgnStmt(x, y)
|
||||
of attachedAsgn:
|
||||
let yenv = genBuiltin(c, mAccessEnv, "accessEnv", y)
|
||||
yenv.typ = getSysType(c.g, c.info, tyPointer)
|
||||
yenv.typ() = getSysType(c.g, c.info, tyPointer)
|
||||
if isCyclic:
|
||||
body.add genIf(c, yenv, callCodegenProc(c.g, "nimIncRefCyclic", c.info, yenv, getCycleParam(c)))
|
||||
body.add newAsgnStmt(x, y)
|
||||
@@ -826,7 +826,7 @@ proc atomicClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
body.add newAsgnStmt(x, y)
|
||||
of attachedDup:
|
||||
let yenv = genBuiltin(c, mAccessEnv, "accessEnv", y)
|
||||
yenv.typ = getSysType(c.g, c.info, tyPointer)
|
||||
yenv.typ() = getSysType(c.g, c.info, tyPointer)
|
||||
if isCyclic:
|
||||
body.add newAsgnStmt(x, y)
|
||||
body.add genIf(c, yenv, callCodegenProc(c.g, "nimIncRefCyclic", c.info, yenv, getCycleParam(c)))
|
||||
@@ -878,7 +878,7 @@ proc ownedRefOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
if isFinal(elemType):
|
||||
addDestructorCall(c, elemType, actions, genDeref(x, nkDerefExpr))
|
||||
var alignOf = genBuiltin(c, mAlignOf, "alignof", newNodeIT(nkType, c.info, elemType))
|
||||
alignOf.typ = getSysType(c.g, c.info, tyInt)
|
||||
alignOf.typ() = getSysType(c.g, c.info, tyInt)
|
||||
actions.add callCodegenProc(c.g, "nimRawDispose", c.info, x, alignOf)
|
||||
else:
|
||||
addDestructorCall(c, elemType, newNodeI(nkStmtList, c.info), genDeref(x, nkDerefExpr))
|
||||
@@ -901,14 +901,14 @@ proc closureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
# a big problem is that we don't know the environment's type here, so we
|
||||
# have to go through some indirection; we delegate this to the codegen:
|
||||
let call = newNodeI(nkCall, c.info, 2)
|
||||
call.typ = t
|
||||
call.typ() = t
|
||||
call[0] = newSymNode(createMagic(c.g, c.idgen, "deepCopy", mDeepCopy))
|
||||
call[1] = y
|
||||
body.add newAsgnStmt(x, call)
|
||||
elif (optOwnedRefs in c.g.config.globalOptions and
|
||||
optRefCheck in c.g.config.options) or c.g.config.selectedGC in {gcArc, gcAtomicArc, gcOrc}:
|
||||
let xx = genBuiltin(c, mAccessEnv, "accessEnv", x)
|
||||
xx.typ = getSysType(c.g, c.info, tyPointer)
|
||||
xx.typ() = getSysType(c.g, c.info, tyPointer)
|
||||
case c.kind
|
||||
of attachedSink:
|
||||
# we 'nil' y out afterwards so we *need* to take over its reference
|
||||
@@ -917,13 +917,13 @@ proc closureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
body.add newAsgnStmt(x, y)
|
||||
of attachedAsgn:
|
||||
let yy = genBuiltin(c, mAccessEnv, "accessEnv", y)
|
||||
yy.typ = getSysType(c.g, c.info, tyPointer)
|
||||
yy.typ() = getSysType(c.g, c.info, tyPointer)
|
||||
body.add genIf(c, yy, callCodegenProc(c.g, "nimIncRef", c.info, yy))
|
||||
body.add genIf(c, xx, callCodegenProc(c.g, "nimDecWeakRef", c.info, xx))
|
||||
body.add newAsgnStmt(x, y)
|
||||
of attachedDup:
|
||||
let yy = genBuiltin(c, mAccessEnv, "accessEnv", y)
|
||||
yy.typ = getSysType(c.g, c.info, tyPointer)
|
||||
yy.typ() = getSysType(c.g, c.info, tyPointer)
|
||||
body.add newAsgnStmt(x, y)
|
||||
body.add genIf(c, yy, callCodegenProc(c.g, "nimIncRef", c.info, yy))
|
||||
of attachedDestructor:
|
||||
@@ -938,7 +938,7 @@ proc closureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
|
||||
proc ownedClosureOp(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
let xx = genBuiltin(c, mAccessEnv, "accessEnv", x)
|
||||
xx.typ = getSysType(c.g, c.info, tyPointer)
|
||||
xx.typ() = getSysType(c.g, c.info, tyPointer)
|
||||
var actions = newNodeI(nkStmtList, c.info)
|
||||
#discard addDestructorCall(c, elemType, newNodeI(nkStmtList, c.info), genDeref(xx))
|
||||
actions.add callCodegenProc(c.g, "nimDestroyAndDispose", c.info, xx)
|
||||
@@ -1152,8 +1152,8 @@ proc symPrototype(g: ModuleGraph; typ: PType; owner: PSym; kind: TTypeAttachedOp
|
||||
proc genTypeFieldCopy(c: var TLiftCtx; t: PType; body, x, y: PNode) =
|
||||
let xx = genBuiltin(c, mAccessTypeField, "accessTypeField", x)
|
||||
let yy = genBuiltin(c, mAccessTypeField, "accessTypeField", y)
|
||||
xx.typ = getSysType(c.g, c.info, tyPointer)
|
||||
yy.typ = xx.typ
|
||||
xx.typ() = getSysType(c.g, c.info, tyPointer)
|
||||
yy.typ() = xx.typ
|
||||
body.add newAsgnStmt(xx, yy)
|
||||
|
||||
proc produceSym(g: ModuleGraph; c: PContext; typ: PType; kind: TTypeAttachedOp;
|
||||
|
||||
@@ -32,12 +32,12 @@ proc interestingVar(s: PSym): bool {.inline.} =
|
||||
proc lookupOrAdd(c: var Ctx; s: PSym; info: TLineInfo): PNode =
|
||||
let field = addUniqueField(c.objType, s, c.cache, c.idgen)
|
||||
var deref = newNodeI(nkHiddenDeref, info)
|
||||
deref.typ = c.objType
|
||||
deref.typ() = c.objType
|
||||
deref.add(newSymNode(c.partialParam, info))
|
||||
result = newNodeI(nkDotExpr, info)
|
||||
result.add(deref)
|
||||
result.add(newSymNode(field))
|
||||
result.typ = field.typ
|
||||
result.typ() = field.typ
|
||||
|
||||
proc liftLocals(n: PNode; i: int; c: var Ctx) =
|
||||
let it = n[i]
|
||||
|
||||
@@ -174,12 +174,12 @@ proc rawIndirectAccess*(a: PNode; field: PSym; info: TLineInfo): PNode =
|
||||
# returns a[].field as a node
|
||||
assert field.kind == skField
|
||||
var deref = newNodeI(nkHiddenDeref, info)
|
||||
deref.typ = a.typ.skipTypes(abstractInst)[0]
|
||||
deref.typ() = a.typ.skipTypes(abstractInst)[0]
|
||||
deref.add a
|
||||
result = newNodeI(nkDotExpr, info)
|
||||
result.add deref
|
||||
result.add newSymNode(field)
|
||||
result.typ = field.typ
|
||||
result.typ() = field.typ
|
||||
|
||||
proc rawDirectAccess*(obj, field: PSym): PNode =
|
||||
# returns a.field as a node
|
||||
@@ -187,7 +187,7 @@ proc rawDirectAccess*(obj, field: PSym): PNode =
|
||||
result = newNodeI(nkDotExpr, field.info)
|
||||
result.add newSymNode(obj)
|
||||
result.add newSymNode(field)
|
||||
result.typ = field.typ
|
||||
result.typ() = field.typ
|
||||
|
||||
proc lookupInRecord(n: PNode, id: ItemId): PSym =
|
||||
result = nil
|
||||
@@ -250,12 +250,12 @@ proc newDotExpr*(obj, b: PSym): PNode =
|
||||
assert field != nil, b.name.s
|
||||
result.add newSymNode(obj)
|
||||
result.add newSymNode(field)
|
||||
result.typ = field.typ
|
||||
result.typ() = field.typ
|
||||
|
||||
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).elementType
|
||||
deref.typ() = a.typ.skipTypes(abstractInst).elementType
|
||||
var t = deref.typ.skipTypes(abstractInst)
|
||||
var field: PSym
|
||||
while true:
|
||||
@@ -273,12 +273,12 @@ proc indirectAccess*(a: PNode, b: ItemId, info: TLineInfo): PNode =
|
||||
result = newNodeI(nkDotExpr, info)
|
||||
result.add deref
|
||||
result.add newSymNode(field)
|
||||
result.typ = field.typ
|
||||
result.typ() = field.typ
|
||||
|
||||
proc indirectAccess*(a: PNode, b: string, info: TLineInfo; cache: IdentCache): PNode =
|
||||
# returns a[].b as a node
|
||||
var deref = newNodeI(nkHiddenDeref, info)
|
||||
deref.typ = a.typ.skipTypes(abstractInst).elementType
|
||||
deref.typ() = a.typ.skipTypes(abstractInst).elementType
|
||||
var t = deref.typ.skipTypes(abstractInst)
|
||||
var field: PSym
|
||||
let bb = getIdent(cache, b)
|
||||
@@ -297,7 +297,7 @@ proc indirectAccess*(a: PNode, b: string, info: TLineInfo; cache: IdentCache): P
|
||||
result = newNodeI(nkDotExpr, info)
|
||||
result.add deref
|
||||
result.add newSymNode(field)
|
||||
result.typ = field.typ
|
||||
result.typ() = field.typ
|
||||
|
||||
proc getFieldFromObj*(t: PType; v: PSym): PSym =
|
||||
assert v.kind != skField
|
||||
@@ -320,7 +320,7 @@ proc indirectAccess*(a, b: PSym, info: TLineInfo): PNode =
|
||||
proc genAddrOf*(n: PNode; idgen: IdGenerator; typeKind = tyPtr): PNode =
|
||||
result = newNodeI(nkAddr, n.info, 1)
|
||||
result[0] = n
|
||||
result.typ = newType(typeKind, idgen, n.typ.owner)
|
||||
result.typ() = newType(typeKind, idgen, n.typ.owner)
|
||||
result.typ.rawAddSon(n.typ)
|
||||
|
||||
proc genDeref*(n: PNode; k = nkHiddenDeref): PNode =
|
||||
@@ -344,18 +344,18 @@ proc callCodegenProc*(g: ModuleGraph; name: string;
|
||||
if optionalArgs != nil:
|
||||
for i in 1..<optionalArgs.len-2:
|
||||
result.add optionalArgs[i]
|
||||
result.typ = sym.typ.returnType
|
||||
result.typ() = sym.typ.returnType
|
||||
|
||||
proc newIntLit*(g: ModuleGraph; info: TLineInfo; value: BiggestInt): PNode =
|
||||
result = nkIntLit.newIntNode(value)
|
||||
result.typ = getSysType(g, info, tyInt)
|
||||
result.typ() = getSysType(g, info, tyInt)
|
||||
|
||||
proc genHigh*(g: ModuleGraph; n: PNode): PNode =
|
||||
if skipTypes(n.typ, abstractVar).kind == tyArray:
|
||||
result = newIntLit(g, n.info, toInt64(lastOrd(g.config, skipTypes(n.typ, abstractVar))))
|
||||
else:
|
||||
result = newNodeI(nkCall, n.info, 2)
|
||||
result.typ = getSysType(g, n.info, tyInt)
|
||||
result.typ() = getSysType(g, n.info, tyInt)
|
||||
result[0] = newSymNode(getSysMagic(g, n.info, "high", mHigh))
|
||||
result[1] = n
|
||||
|
||||
@@ -364,7 +364,7 @@ proc genLen*(g: ModuleGraph; n: PNode): PNode =
|
||||
result = newIntLit(g, n.info, toInt64(lastOrd(g.config, skipTypes(n.typ, abstractVar)) + 1))
|
||||
else:
|
||||
result = newNodeI(nkCall, n.info, 2)
|
||||
result.typ = getSysType(g, n.info, tyInt)
|
||||
result.typ() = getSysType(g, n.info, tyInt)
|
||||
result[0] = newSymNode(getSysMagic(g, n.info, "len", mLengthSeq))
|
||||
result[1] = n
|
||||
|
||||
|
||||
@@ -166,4 +166,4 @@ proc makeAddr*(n: PNode; idgen: IdGenerator): PNode =
|
||||
result = n
|
||||
else:
|
||||
result = newTree(nkHiddenAddr, n)
|
||||
result.typ = makePtrType(n.typ, idgen)
|
||||
result.typ() = makePtrType(n.typ, idgen)
|
||||
|
||||
@@ -25,7 +25,7 @@ template getModuleIdent(graph: ModuleGraph, filename: AbsoluteFile): PIdent =
|
||||
|
||||
proc partialInitModule*(result: PSym; graph: ModuleGraph; fileIdx: FileIndex; filename: AbsoluteFile) =
|
||||
let packSym = getPackage(graph, fileIdx)
|
||||
result.owner = packSym
|
||||
setOwner(result, packSym)
|
||||
result.position = int fileIdx
|
||||
|
||||
proc newModule*(graph: ModuleGraph; fileIdx: FileIndex): PSym =
|
||||
|
||||
@@ -919,7 +919,7 @@ proc infix(ctx: NilCheckerContext, l: PNode, r: PNode, magic: TMagic): PNode =
|
||||
newSymNode(op, r.info),
|
||||
l,
|
||||
r)
|
||||
result.typ = newType(tyBool, ctx.idgen, nil)
|
||||
result.typ() = newType(tyBool, ctx.idgen, nil)
|
||||
|
||||
proc prefixNot(ctx: NilCheckerContext, node: PNode): PNode =
|
||||
var cache = newIdentCache()
|
||||
@@ -929,7 +929,7 @@ proc prefixNot(ctx: NilCheckerContext, node: PNode): PNode =
|
||||
result = nkPrefix.newTree(
|
||||
newSymNode(op, node.info),
|
||||
node)
|
||||
result.typ = newType(tyBool, ctx.idgen, nil)
|
||||
result.typ() = newType(tyBool, ctx.idgen, nil)
|
||||
|
||||
proc infixEq(ctx: NilCheckerContext, l: PNode, r: PNode): PNode =
|
||||
infix(ctx, l, r, mEqRef)
|
||||
|
||||
@@ -84,7 +84,7 @@ proc toTreeSet*(conf: ConfigRef; s: TBitSet, settype: PType, info: TLineInfo): P
|
||||
elemType = settype[0]
|
||||
first = firstOrd(conf, elemType).toInt64
|
||||
result = newNodeI(nkCurly, info)
|
||||
result.typ = settype
|
||||
result.typ() = settype
|
||||
result.info = info
|
||||
e = 0
|
||||
while e < s.len * ElemSize:
|
||||
@@ -101,7 +101,7 @@ proc toTreeSet*(conf: ConfigRef; s: TBitSet, settype: PType, info: TLineInfo): P
|
||||
result.add aa
|
||||
else:
|
||||
n = newNodeI(nkRange, info)
|
||||
n.typ = elemType
|
||||
n.typ() = elemType
|
||||
n.add aa
|
||||
let bb = newIntTypeNode(b + first, elemType)
|
||||
bb.info = info
|
||||
|
||||
@@ -722,12 +722,12 @@ proc processPragma(c: PContext, n: PNode, i: int) =
|
||||
proc pragmaRaisesOrTags(c: PContext, n: PNode) =
|
||||
proc processExc(c: PContext, x: PNode) =
|
||||
if c.hasUnresolvedArgs(c, x):
|
||||
x.typ = makeTypeFromExpr(c, x)
|
||||
x.typ() = makeTypeFromExpr(c, x)
|
||||
else:
|
||||
var t = skipTypes(c.semTypeNode(c, x, nil), skipPtrs)
|
||||
if t.kind notin {tyObject, tyOr}:
|
||||
localError(c.config, x.info, errGenerated, "invalid type for raises/tags list")
|
||||
x.typ = t
|
||||
x.typ() = t
|
||||
|
||||
if n.kind in nkPragmaCallKinds and n.len == 2:
|
||||
let it = n[1]
|
||||
|
||||
@@ -1311,10 +1311,11 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext, fromStmtList = false) =
|
||||
put(g, tkCustomLit, n[0].strVal)
|
||||
gsub(g, n, 1)
|
||||
else:
|
||||
gsub(g, n, 0)
|
||||
for i in 0..<n.len-1:
|
||||
gsub(g, n, i)
|
||||
put(g, tkDot, ".")
|
||||
assert n.len == 2, $n.len
|
||||
accentedName(g, n[1])
|
||||
if n.len > 1:
|
||||
accentedName(g, n[^1])
|
||||
of nkBind:
|
||||
putWithSpace(g, tkBind, "bind")
|
||||
gsub(g, n, 0)
|
||||
|
||||
@@ -102,7 +102,7 @@ proc fitNode(c: PContext, formal: PType, arg: PNode; info: TLineInfo): PNode =
|
||||
renderTree(arg, {renderNoComments}))
|
||||
# error correction:
|
||||
result = copyTree(arg)
|
||||
result.typ = formal
|
||||
result.typ() = formal
|
||||
elif arg.kind in nkSymChoices and formal.skipTypes(abstractInst).kind == tyEnum:
|
||||
# Pick the right 'sym' from the sym choice by looking at 'formal' type:
|
||||
result = nil
|
||||
@@ -116,7 +116,7 @@ proc fitNode(c: PContext, formal: PType, arg: PNode; info: TLineInfo): PNode =
|
||||
typeMismatch(c.config, info, formal, arg.typ, arg)
|
||||
# error correction:
|
||||
result = copyTree(arg)
|
||||
result.typ = formal
|
||||
result.typ() = formal
|
||||
else:
|
||||
result = fitNodePostMatch(c, formal, result)
|
||||
|
||||
@@ -256,7 +256,7 @@ proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym =
|
||||
# when there is a nested proc inside a template, semtmpl
|
||||
# will assign a wrong owner during the first pass over the
|
||||
# template; we must fix it here: see #909
|
||||
result.owner = getCurrOwner(c)
|
||||
setOwner(result, getCurrOwner(c))
|
||||
else:
|
||||
result = newSym(kind, considerQuotedIdent(c, n), c.idgen, getCurrOwner(c), n.info)
|
||||
if find(result.name.s, '`') >= 0:
|
||||
@@ -470,7 +470,7 @@ proc semAfterMacroCall(c: PContext, call, macroResult: PNode,
|
||||
renderTree(result, {renderNoComments}))
|
||||
result = newSymNode(errorSym(c, result))
|
||||
else:
|
||||
result.typ = makeTypeDesc(c, typ)
|
||||
result.typ() = makeTypeDesc(c, typ)
|
||||
#result = symNodeFromType(c, typ, n.info)
|
||||
else:
|
||||
if s.ast[genericParamsPos] != nil and retType.isMetaType:
|
||||
@@ -494,7 +494,7 @@ proc semAfterMacroCall(c: PContext, call, macroResult: PNode,
|
||||
if retType.kind == tyVoid:
|
||||
result = semStmt(c, result, flags)
|
||||
else:
|
||||
result = semExpr(c, result, flags, expectedType)
|
||||
result = semExpr(c, result, flags)
|
||||
result = fitNode(c, retType, result, result.info)
|
||||
#globalError(s.info, errInvalidParamKindX, typeToString(s.typ.returnType))
|
||||
dec(c.config.evalTemplateCounter)
|
||||
@@ -612,7 +612,7 @@ proc defaultFieldsForTuple(c: PContext, recNode: PNode, hasDefault: var bool, ch
|
||||
newNodeIT(nkType, recNode.info, asgnType)
|
||||
)
|
||||
asgnExpr.flags.incl nfSkipFieldChecking
|
||||
asgnExpr.typ = recNode.typ
|
||||
asgnExpr.typ() = recNode.typ
|
||||
result.add newTree(nkExprColonExpr, recNode, asgnExpr)
|
||||
else:
|
||||
raiseAssert "unreachable"
|
||||
@@ -634,7 +634,7 @@ proc defaultFieldsForTheUninitialized(c: PContext, recNode: PNode, checkDefault:
|
||||
if checkDefault: # don't add defaults when checking whether a case branch has default fields
|
||||
return
|
||||
defaultValue = newIntNode(nkIntLit#[c.graph]#, 0)
|
||||
defaultValue.typ = discriminator.typ
|
||||
defaultValue.typ() = discriminator.typ
|
||||
selectedBranch = recNode.pickCaseBranchIndex defaultValue
|
||||
defaultValue.flags.incl nfSkipFieldChecking
|
||||
result.add newTree(nkExprColonExpr, discriminator, defaultValue)
|
||||
@@ -647,7 +647,7 @@ proc defaultFieldsForTheUninitialized(c: PContext, recNode: PNode, checkDefault:
|
||||
elif recType.kind in {tyObject, tyArray, tyTuple}:
|
||||
let asgnExpr = defaultNodeField(c, recNode, recNode.typ, checkDefault)
|
||||
if asgnExpr != nil:
|
||||
asgnExpr.typ = recNode.typ
|
||||
asgnExpr.typ() = recNode.typ
|
||||
asgnExpr.flags.incl nfSkipFieldChecking
|
||||
result.add newTree(nkExprColonExpr, recNode, asgnExpr)
|
||||
else:
|
||||
@@ -660,7 +660,7 @@ proc defaultNodeField(c: PContext, a: PNode, aTyp: PType, checkDefault: bool): P
|
||||
let child = defaultFieldsForTheUninitialized(c, aTypSkip.n, checkDefault)
|
||||
if child.len > 0:
|
||||
var asgnExpr = newTree(nkObjConstr, newNodeIT(nkType, a.info, aTyp))
|
||||
asgnExpr.typ = aTyp
|
||||
asgnExpr.typ() = aTyp
|
||||
asgnExpr.sons.add child
|
||||
result = semExpr(c, asgnExpr)
|
||||
else:
|
||||
@@ -675,7 +675,7 @@ proc defaultNodeField(c: PContext, a: PNode, aTyp: PType, checkDefault: bool): P
|
||||
semExprWithType(c, child),
|
||||
node
|
||||
))
|
||||
result.typ = aTyp
|
||||
result.typ() = aTyp
|
||||
else:
|
||||
result = nil
|
||||
of tyTuple:
|
||||
@@ -684,7 +684,7 @@ proc defaultNodeField(c: PContext, a: PNode, aTyp: PType, checkDefault: bool): P
|
||||
let children = defaultFieldsForTuple(c, aTypSkip.n, hasDefault, checkDefault)
|
||||
if hasDefault and children.len > 0:
|
||||
result = newNodeI(nkTupleConstr, a.info)
|
||||
result.typ = aTyp
|
||||
result.typ() = aTyp
|
||||
result.sons.add children
|
||||
result = semExpr(c, result)
|
||||
else:
|
||||
|
||||
@@ -636,7 +636,7 @@ proc instGenericConvertersArg*(c: PContext, a: PNode, x: TCandidate) =
|
||||
if s.isGenericRoutineStrict:
|
||||
let finalCallee = generateInstance(c, s, x.bindings, a.info)
|
||||
a[0].sym = finalCallee
|
||||
a[0].typ = finalCallee.typ
|
||||
a[0].typ() = finalCallee.typ
|
||||
#a.typ = finalCallee.typ.returnType
|
||||
|
||||
proc instGenericConvertersSons*(c: PContext, n: PNode, x: TCandidate) =
|
||||
@@ -671,13 +671,13 @@ proc inferWithMetatype(c: PContext, formal: PType,
|
||||
# This almost exactly replicates the steps taken by the compiler during
|
||||
# param matching. It performs an embarrassing amount of back-and-forth
|
||||
# type jugling, but it's the price to pay for consistency and correctness
|
||||
result.typ = generateTypeInstance(c, m.bindings, arg.info,
|
||||
result.typ() = generateTypeInstance(c, m.bindings, arg.info,
|
||||
formal.skipTypes({tyCompositeTypeClass}))
|
||||
else:
|
||||
typeMismatch(c.config, arg.info, formal, arg.typ, arg)
|
||||
# error correction:
|
||||
result = copyTree(arg)
|
||||
result.typ = formal
|
||||
result.typ() = formal
|
||||
|
||||
proc updateDefaultParams(c: PContext, call: PNode) =
|
||||
# In generic procs, the default parameter may be unique for each
|
||||
@@ -700,7 +700,7 @@ proc updateDefaultParams(c: PContext, call: PNode) =
|
||||
pushInfoContext(c.config, call.info, call[0].sym.detailedInfo)
|
||||
typeMismatch(c.config, def.info, formal.typ, def.typ, formal.ast)
|
||||
popInfoContext(c.config)
|
||||
def.typ = errorType(c)
|
||||
def.typ() = errorType(c)
|
||||
call[i] = def
|
||||
|
||||
proc getCallLineInfo(n: PNode): TLineInfo =
|
||||
@@ -784,7 +784,7 @@ proc semResolvedCall(c: PContext, x: var TCandidate,
|
||||
result = x.call
|
||||
result[0] = newSymNode(finalCallee, getCallLineInfo(result[0]))
|
||||
if containsGenericType(result.typ):
|
||||
result.typ = newTypeS(tyError, c)
|
||||
result.typ() = newTypeS(tyError, c)
|
||||
incl result.typ.flags, tfCheckedForDestructor
|
||||
return
|
||||
let gp = finalCallee.ast[genericParamsPos]
|
||||
@@ -811,7 +811,7 @@ proc semResolvedCall(c: PContext, x: var TCandidate,
|
||||
# this node will be used in template substitution,
|
||||
# pretend this is an untyped node and let regular sem handle the type
|
||||
# to prevent problems where a generic parameter is treated as a value
|
||||
tn.typ = nil
|
||||
tn.typ() = nil
|
||||
x.call.add tn
|
||||
else:
|
||||
internalAssert c.config, false
|
||||
@@ -821,7 +821,7 @@ proc semResolvedCall(c: PContext, x: var TCandidate,
|
||||
markConvertersUsed(c, result)
|
||||
result[0] = newSymNode(finalCallee, getCallLineInfo(result[0]))
|
||||
if finalCallee.magic notin {mArrGet, mArrPut}:
|
||||
result.typ = finalCallee.typ.returnType
|
||||
result.typ() = finalCallee.typ.returnType
|
||||
updateDefaultParams(c, result)
|
||||
|
||||
proc canDeref(n: PNode): bool {.inline.} =
|
||||
@@ -830,7 +830,7 @@ proc canDeref(n: PNode): bool {.inline.} =
|
||||
|
||||
proc tryDeref(n: PNode): PNode =
|
||||
result = newNodeI(nkHiddenDeref, n.info)
|
||||
result.typ = n.typ.skipTypes(abstractInst)[0]
|
||||
result.typ() = n.typ.skipTypes(abstractInst)[0]
|
||||
result.add n
|
||||
|
||||
proc semOverloadedCall(c: PContext, n, nOrig: PNode,
|
||||
@@ -849,7 +849,7 @@ proc semOverloadedCall(c: PContext, n, nOrig: PNode,
|
||||
else:
|
||||
if c.inGenericContext > 0 and c.matchedConcept == nil:
|
||||
result = semGenericStmt(c, n)
|
||||
result.typ = makeTypeFromExpr(c, result.copyTree)
|
||||
result.typ() = makeTypeFromExpr(c, result.copyTree)
|
||||
elif efExplain notin flags:
|
||||
# repeat the overload resolution,
|
||||
# this time enabling all the diagnostic output (this should fail again)
|
||||
@@ -864,7 +864,7 @@ proc explicitGenericInstError(c: PContext; n: PNode): PNode =
|
||||
localError(c.config, getCallLineInfo(n), errCannotInstantiateX % renderTree(n))
|
||||
result = n
|
||||
|
||||
proc explicitGenericSym(c: PContext, n: PNode, s: PSym): PNode =
|
||||
proc explicitGenericSym(c: PContext, n: PNode, s: PSym, errors: var CandidateErrors, doError: bool): PNode =
|
||||
if s.kind in {skTemplate, skMacro}:
|
||||
internalError c.config, n.info, "cannot get explicitly instantiated symbol of " &
|
||||
(if s.kind == skTemplate: "template" else: "macro")
|
||||
@@ -874,6 +874,11 @@ proc explicitGenericSym(c: PContext, n: PNode, s: PSym): PNode =
|
||||
if m.state != csMatch:
|
||||
# state is csMatch only if *all* generic params were matched,
|
||||
# including implicit parameters
|
||||
if doError:
|
||||
errors.add(CandidateError(
|
||||
sym: s,
|
||||
firstMismatch: m.firstMismatch,
|
||||
diagnostics: m.diagnostics))
|
||||
return nil
|
||||
var newInst = generateInstance(c, s, m.bindings, n.info)
|
||||
newInst.typ.flags.excl tfUnresolved
|
||||
@@ -893,46 +898,43 @@ proc setGenericParams(c: PContext, n, expectedParams: PNode) =
|
||||
nil
|
||||
e = semExprWithType(c, n[i], expectedType = constraint)
|
||||
if e.typ == nil:
|
||||
n[i].typ = errorType(c)
|
||||
n[i].typ() = errorType(c)
|
||||
else:
|
||||
n[i].typ = e.typ.skipTypes({tyTypeDesc})
|
||||
n[i].typ() = e.typ.skipTypes({tyTypeDesc})
|
||||
|
||||
proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
|
||||
proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym, doError: bool): PNode =
|
||||
assert n.kind == nkBracketExpr
|
||||
setGenericParams(c, n, s.ast[genericParamsPos])
|
||||
var s = s
|
||||
var a = n[0]
|
||||
var errors: CandidateErrors = @[]
|
||||
if a.kind == nkSym:
|
||||
# common case; check the only candidate has the right
|
||||
# number of generic type parameters:
|
||||
if s.ast[genericParamsPos].safeLen != n.len-1:
|
||||
let expected = s.ast[genericParamsPos].safeLen
|
||||
localError(c.config, getCallLineInfo(n), errGenerated, "cannot instantiate: '" & renderTree(n) &
|
||||
"'; got " & $(n.len-1) & " typeof(s) but expected " & $expected)
|
||||
return n
|
||||
result = explicitGenericSym(c, n, s)
|
||||
if result == nil: result = explicitGenericInstError(c, n)
|
||||
result = explicitGenericSym(c, n, s, errors, doError)
|
||||
if doError and result == nil:
|
||||
notFoundError(c, n, errors)
|
||||
elif a.kind in {nkClosedSymChoice, nkOpenSymChoice}:
|
||||
# choose the generic proc with the proper number of type parameters.
|
||||
# XXX I think this could be improved by reusing sigmatch.paramTypesMatch.
|
||||
# It's good enough for now.
|
||||
result = newNodeI(a.kind, getCallLineInfo(n))
|
||||
for i in 0..<a.len:
|
||||
var candidate = a[i].sym
|
||||
if candidate.kind in {skProc, skMethod, skConverter,
|
||||
skFunc, skIterator}:
|
||||
# it suffices that the candidate has the proper number of generic
|
||||
# type parameters:
|
||||
if candidate.ast[genericParamsPos].safeLen == n.len-1:
|
||||
let x = explicitGenericSym(c, n, candidate)
|
||||
if x != nil: result.add(x)
|
||||
let x = explicitGenericSym(c, n, candidate, errors, doError)
|
||||
if x != nil: result.add(x)
|
||||
# get rid of nkClosedSymChoice if not ambiguous:
|
||||
if result.len == 1 and a.kind == nkClosedSymChoice:
|
||||
result = result[0]
|
||||
elif result.len == 0: result = explicitGenericInstError(c, n)
|
||||
# candidateCount != 1: return explicitGenericInstError(c, n)
|
||||
if result.len == 0:
|
||||
result = nil
|
||||
if doError:
|
||||
notFoundError(c, n, errors)
|
||||
else:
|
||||
result = explicitGenericInstError(c, n)
|
||||
# probably unreachable: we are trying to instantiate `a` which is not
|
||||
# a sym/symchoice
|
||||
if doError:
|
||||
result = explicitGenericInstError(c, n)
|
||||
else:
|
||||
result = nil
|
||||
|
||||
proc searchForBorrowProc(c: PContext, startScope: PScope, fn: PSym): tuple[s: PSym, state: TBorrowState] =
|
||||
# Searches for the fn in the symbol table. If the parameter lists are suitable
|
||||
|
||||
@@ -195,29 +195,29 @@ proc getIntLitType*(c: PContext; literal: PNode): PType =
|
||||
proc setIntLitType*(c: PContext; result: PNode) =
|
||||
let i = result.intVal
|
||||
case c.config.target.intSize
|
||||
of 8: result.typ = getIntLitType(c, result)
|
||||
of 8: result.typ() = getIntLitType(c, result)
|
||||
of 4:
|
||||
if i >= low(int32) and i <= high(int32):
|
||||
result.typ = getIntLitType(c, result)
|
||||
result.typ() = getIntLitType(c, result)
|
||||
else:
|
||||
result.typ = getSysType(c.graph, result.info, tyInt64)
|
||||
result.typ() = getSysType(c.graph, result.info, tyInt64)
|
||||
of 2:
|
||||
if i >= low(int16) and i <= high(int16):
|
||||
result.typ = getIntLitType(c, result)
|
||||
result.typ() = getIntLitType(c, result)
|
||||
elif i >= low(int32) and i <= high(int32):
|
||||
result.typ = getSysType(c.graph, result.info, tyInt32)
|
||||
result.typ() = getSysType(c.graph, result.info, tyInt32)
|
||||
else:
|
||||
result.typ = getSysType(c.graph, result.info, tyInt64)
|
||||
result.typ() = getSysType(c.graph, result.info, tyInt64)
|
||||
of 1:
|
||||
# 8 bit CPUs are insane ...
|
||||
if i >= low(int8) and i <= high(int8):
|
||||
result.typ = getIntLitType(c, result)
|
||||
result.typ() = getIntLitType(c, result)
|
||||
elif i >= low(int16) and i <= high(int16):
|
||||
result.typ = getSysType(c.graph, result.info, tyInt16)
|
||||
result.typ() = getSysType(c.graph, result.info, tyInt16)
|
||||
elif i >= low(int32) and i <= high(int32):
|
||||
result.typ = getSysType(c.graph, result.info, tyInt32)
|
||||
result.typ() = getSysType(c.graph, result.info, tyInt32)
|
||||
else:
|
||||
result.typ = getSysType(c.graph, result.info, tyInt64)
|
||||
result.typ() = getSysType(c.graph, result.info, tyInt64)
|
||||
else:
|
||||
internalError(c.config, result.info, "invalid int size")
|
||||
|
||||
@@ -449,7 +449,7 @@ when false:
|
||||
proc makeStaticExpr*(c: PContext, n: PNode): PNode =
|
||||
result = newNodeI(nkStaticExpr, n.info)
|
||||
result.sons = @[n]
|
||||
result.typ = if n.typ != nil and n.typ.kind == tyStatic: n.typ
|
||||
result.typ() = if n.typ != nil and n.typ.kind == tyStatic: n.typ
|
||||
else: newTypeS(tyStatic, c, n.typ)
|
||||
|
||||
proc makeAndType*(c: PContext, t1, t2: PType): PType =
|
||||
@@ -508,7 +508,7 @@ proc errorType*(c: PContext): PType =
|
||||
|
||||
proc errorNode*(c: PContext, n: PNode): PNode =
|
||||
result = newNodeI(nkEmpty, n.info)
|
||||
result.typ = errorType(c)
|
||||
result.typ() = errorType(c)
|
||||
|
||||
# These mimic localError
|
||||
template localErrorNode*(c: PContext, n: PNode, info: TLineInfo, msg: TMsgKind, arg: string): PNode =
|
||||
@@ -529,10 +529,11 @@ template localErrorNode*(c: PContext, n: PNode, arg: string): PNode =
|
||||
liMessage(c.config, n2.info, errGenerated, arg, doNothing, instLoc())
|
||||
errorNode(c, n2)
|
||||
|
||||
proc fillTypeS*(dest: PType, kind: TTypeKind, c: PContext) =
|
||||
dest.kind = kind
|
||||
dest.owner = getCurrOwner(c)
|
||||
dest.size = - 1
|
||||
when false:
|
||||
proc fillTypeS*(dest: PType, kind: TTypeKind, c: PContext) =
|
||||
dest.kind = kind
|
||||
dest.owner = getCurrOwner(c)
|
||||
dest.size = - 1
|
||||
|
||||
proc makeRangeType*(c: PContext; first, last: BiggestInt;
|
||||
info: TLineInfo; intType: PType = nil): PType =
|
||||
@@ -563,7 +564,7 @@ proc symFromType*(c: PContext; t: PType, info: TLineInfo): PSym =
|
||||
|
||||
proc symNodeFromType*(c: PContext, t: PType, info: TLineInfo): PNode =
|
||||
result = newSymNode(symFromType(c, t, info), info)
|
||||
result.typ = makeTypeDesc(c, t)
|
||||
result.typ() = makeTypeDesc(c, t)
|
||||
|
||||
proc markIndirect*(c: PContext, s: PSym) {.inline.} =
|
||||
if s.kind in {skProc, skFunc, skConverter, skMethod, skIterator}:
|
||||
|
||||
@@ -56,11 +56,11 @@ proc semOperand(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
if result.typ != nil:
|
||||
if result.typ.kind in {tyVar, tyLent}: result = newDeref(result)
|
||||
elif {efWantStmt, efAllowStmt} * flags != {}:
|
||||
result.typ = newTypeS(tyVoid, c)
|
||||
result.typ() = newTypeS(tyVoid, c)
|
||||
else:
|
||||
localError(c.config, n.info, errExprXHasNoType %
|
||||
renderTree(result, {renderNoComments}))
|
||||
result.typ = errorType(c)
|
||||
result.typ() = errorType(c)
|
||||
|
||||
proc semExprCheck(c: PContext, n: PNode, flags: TExprFlags, expectedType: PType = nil): PNode =
|
||||
rejectEmptyNode(n)
|
||||
@@ -82,14 +82,14 @@ proc semExprCheck(c: PContext, n: PNode, flags: TExprFlags, expectedType: PType
|
||||
proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: PType = nil): PNode =
|
||||
result = semExprCheck(c, n, flags-{efTypeAllowed}, expectedType)
|
||||
if result.typ == nil and efInTypeof in flags:
|
||||
result.typ = c.voidType
|
||||
result.typ() = c.voidType
|
||||
elif result.typ == nil or result.typ == c.enforceVoidContext:
|
||||
localError(c.config, n.info, errExprXHasNoType %
|
||||
renderTree(result, {renderNoComments}))
|
||||
result.typ = errorType(c)
|
||||
result.typ() = errorType(c)
|
||||
elif result.typ.kind == tyError:
|
||||
# associates the type error to the current owner
|
||||
result.typ = errorType(c)
|
||||
result.typ() = errorType(c)
|
||||
elif efTypeAllowed in flags and result.typ.kind == tyProc and
|
||||
hasUnresolvedParams(result, {}):
|
||||
# mirrored with semOperand but only on efTypeAllowed
|
||||
@@ -101,7 +101,7 @@ proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType
|
||||
else:
|
||||
errProcHasNoConcreteType % n.renderTree
|
||||
localError(c.config, n.info, err)
|
||||
result.typ = errorType(c)
|
||||
result.typ() = errorType(c)
|
||||
else:
|
||||
if result.typ.kind in {tyVar, tyLent}: result = newDeref(result)
|
||||
|
||||
@@ -110,7 +110,7 @@ proc semExprNoDeref(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
if result.typ == nil:
|
||||
localError(c.config, n.info, errExprXHasNoType %
|
||||
renderTree(result, {renderNoComments}))
|
||||
result.typ = errorType(c)
|
||||
result.typ() = errorType(c)
|
||||
|
||||
proc semSymGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
|
||||
result = symChoice(c, n, s, scClosed)
|
||||
@@ -194,7 +194,7 @@ proc semOpenSym(c: PContext, n: PNode, flags: TExprFlags, expectedType: PType,
|
||||
result = nil
|
||||
if not isSym:
|
||||
# set symchoice node type back to None
|
||||
n.typ = newTypeS(tyNone, c)
|
||||
n.typ() = newTypeS(tyNone, c)
|
||||
|
||||
proc semSymChoice(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: PType = nil): PNode =
|
||||
if n.kind == nkOpenSymChoice:
|
||||
@@ -216,7 +216,7 @@ proc semSymChoice(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: P
|
||||
err.add " " & candidate.owner.name.s & "." & candidate.name.s
|
||||
err.add ": " & typeToString(candidate.typ) & "\n"
|
||||
localError(c.config, n.info, err)
|
||||
n.typ = errorType(c)
|
||||
n.typ() = errorType(c)
|
||||
result = n
|
||||
if result.kind == nkSym:
|
||||
result = semSym(c, result, result.sym, flags)
|
||||
@@ -227,7 +227,7 @@ proc inlineConst(c: PContext, n: PNode, s: PSym): PNode {.inline.} =
|
||||
localError(c.config, n.info, "constant of type '" & typeToString(s.typ) & "' has no value")
|
||||
result = newSymNode(s)
|
||||
else:
|
||||
result.typ = s.typ
|
||||
result.typ() = s.typ
|
||||
result.info = n.info
|
||||
|
||||
type
|
||||
@@ -395,7 +395,7 @@ proc semConv(c: PContext, n: PNode; flags: TExprFlags = {}, expectedType: PType
|
||||
var evaluated = semStaticExpr(c, n[1], expectedType)
|
||||
if evaluated.kind == nkType or evaluated.typ.kind == tyTypeDesc:
|
||||
result = n
|
||||
result.typ = c.makeTypeDesc semStaticType(c, evaluated, nil)
|
||||
result.typ() = c.makeTypeDesc semStaticType(c, evaluated, nil)
|
||||
return
|
||||
elif targetType.base.kind == tyNone:
|
||||
return evaluated
|
||||
@@ -413,7 +413,7 @@ proc semConv(c: PContext, n: PNode; flags: TExprFlags = {}, expectedType: PType
|
||||
if targetType.kind == tyOwned:
|
||||
t.flags.incl tfHasOwned
|
||||
result = newNodeI(nkType, n.info)
|
||||
result.typ = makeTypeDesc(c, t)
|
||||
result.typ() = makeTypeDesc(c, t)
|
||||
return
|
||||
|
||||
result.add copyTree(n[0])
|
||||
@@ -429,10 +429,10 @@ proc semConv(c: PContext, n: PNode; flags: TExprFlags = {}, expectedType: PType
|
||||
if targetType.kind != tyGenericParam and targetType.isMetaType:
|
||||
let final = inferWithMetatype(c, targetType, op, true)
|
||||
result.add final
|
||||
result.typ = final.typ
|
||||
result.typ() = final.typ
|
||||
return
|
||||
|
||||
result.typ = targetType
|
||||
result.typ() = targetType
|
||||
# XXX op is overwritten later on, this is likely added too early
|
||||
# here or needs to be overwritten too then.
|
||||
result.add op
|
||||
@@ -440,7 +440,7 @@ proc semConv(c: PContext, n: PNode; flags: TExprFlags = {}, expectedType: PType
|
||||
if targetType.kind == tyGenericParam or
|
||||
(op.typ != nil and op.typ.kind == tyFromExpr and c.inGenericContext > 0):
|
||||
# expression is compiled early in a generic body
|
||||
result.typ = makeTypeFromExpr(c, copyTree(result))
|
||||
result.typ() = makeTypeFromExpr(c, copyTree(result))
|
||||
return result
|
||||
|
||||
if not isSymChoice(op):
|
||||
@@ -490,7 +490,7 @@ proc semCast(c: PContext, n: PNode): PNode =
|
||||
if not isCastable(c, targetType, castedExpr.typ, n.info):
|
||||
localError(c.config, n.info, "expression cannot be cast to '$1'" % $targetType)
|
||||
result = newNodeI(nkCast, n.info)
|
||||
result.typ = targetType
|
||||
result.typ() = targetType
|
||||
result.add copyTree(n[0])
|
||||
result.add castedExpr
|
||||
|
||||
@@ -504,18 +504,18 @@ proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode =
|
||||
var typ = skipTypes(n[1].typ, abstractVarRange + {tyTypeDesc, tyUserTypeClassInst})
|
||||
case typ.kind
|
||||
of tySequence, tyString, tyCstring, tyOpenArray, tyVarargs:
|
||||
n.typ = getSysType(c.graph, n.info, tyInt)
|
||||
n.typ() = getSysType(c.graph, n.info, tyInt)
|
||||
of tyArray:
|
||||
n.typ = typ.indexType
|
||||
n.typ() = typ.indexType
|
||||
if n.typ.kind == tyRange and emptyRange(n.typ.n[0], n.typ.n[1]): #Invalid range
|
||||
n.typ = getSysType(c.graph, n.info, tyInt)
|
||||
n.typ() = getSysType(c.graph, n.info, tyInt)
|
||||
of tyInt..tyInt64, tyChar, tyBool, tyEnum, tyUInt..tyUInt64, tyFloat..tyFloat64:
|
||||
n.typ = n[1].typ.skipTypes({tyTypeDesc})
|
||||
n.typ() = n[1].typ.skipTypes({tyTypeDesc})
|
||||
of tyGenericParam:
|
||||
# prepare this for resolving in semtypinst:
|
||||
# we must use copyTree here in order to avoid creating a cycle
|
||||
# that could easily turn into an infinite recursion in semtypinst
|
||||
n.typ = makeTypeFromExpr(c, n.copyTree)
|
||||
n.typ() = makeTypeFromExpr(c, n.copyTree)
|
||||
else:
|
||||
localError(c.config, n.info, "invalid argument for: " & opToStr[m])
|
||||
result = n
|
||||
@@ -531,7 +531,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 = newTypeS(tyStatic, c, n.typ)
|
||||
n.typ() = newTypeS(tyStatic, c, n.typ)
|
||||
n.typ.n = n # XXX: cycles like the one here look dangerous.
|
||||
# Consider using `n.copyTree`
|
||||
|
||||
@@ -581,7 +581,7 @@ proc isOpImpl(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
# `res = sameType(t1, t2)` would be wrong, e.g. for `int is (int|float)`
|
||||
|
||||
result = newIntNode(nkIntLit, ord(res))
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
|
||||
proc semIs(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
if n.len != 3 or n[2].kind == nkEmpty:
|
||||
@@ -590,7 +590,7 @@ proc semIs(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
|
||||
let boolType = getSysType(c.graph, n.info, tyBool)
|
||||
result = n
|
||||
n.typ = boolType
|
||||
n.typ() = boolType
|
||||
var liftLhs = true
|
||||
|
||||
n[1] = semExprWithType(c, n[1], {efDetermineType, efWantIterator})
|
||||
@@ -604,7 +604,7 @@ proc semIs(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
n[1] = evaluated
|
||||
else:
|
||||
result = newIntNode(nkIntLit, 0)
|
||||
result.typ = boolType
|
||||
result.typ() = boolType
|
||||
return
|
||||
elif t2.kind == tyTypeDesc and
|
||||
(t2.base.kind == tyNone or tfExplicit in t2.flags):
|
||||
@@ -634,7 +634,7 @@ proc semOpAux(c: PContext, n: PNode) =
|
||||
let info = a[0].info
|
||||
a[0] = newIdentNode(considerQuotedIdent(c, a[0], a), info)
|
||||
a[1] = semExprWithType(c, a[1], flags)
|
||||
a.typ = a[1].typ
|
||||
a.typ() = a[1].typ
|
||||
else:
|
||||
n[i] = semExprWithType(c, a, flags)
|
||||
|
||||
@@ -707,7 +707,7 @@ proc changeType(c: PContext; n: PNode, newType: PType, check: bool) =
|
||||
localError(c.config, n.info, "cannot convert '" & n.sym.name.s &
|
||||
"' to '" & typeNameAndDesc(newType) & "'")
|
||||
else: discard
|
||||
n.typ = newType
|
||||
n.typ() = newType
|
||||
|
||||
proc arrayConstrType(c: PContext, n: PNode): PType =
|
||||
var typ = newTypeS(tyArray, c)
|
||||
@@ -729,12 +729,12 @@ proc semArrayConstr(c: PContext, n: PNode, flags: TExprFlags; expectedType: PTyp
|
||||
var expectedElementType, expectedIndexType: PType = nil
|
||||
var expectedBase: PType = nil
|
||||
if constructType:
|
||||
result.typ = newTypeS(tyArray, c)
|
||||
result.typ() = newTypeS(tyArray, c)
|
||||
rawAddSon(result.typ, nil) # index type
|
||||
if expectedType != nil:
|
||||
expectedBase = expectedType.skipTypes(abstractRange-{tyDistinct})
|
||||
else:
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
expectedBase = n.typ.skipTypes(abstractRange) # include tyDistinct this time
|
||||
if expectedBase != nil:
|
||||
case expectedBase.kind
|
||||
@@ -1002,7 +1002,7 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode =
|
||||
if n[i].typ.isNil or n[i].typ.kind != tyStatic or
|
||||
tfUnresolved notin n[i].typ.flags:
|
||||
break maybeLabelAsStatic
|
||||
n.typ = newTypeS(tyStatic, c, n.typ)
|
||||
n.typ() = newTypeS(tyStatic, c, n.typ)
|
||||
n.typ.flags.incl tfUnresolved
|
||||
|
||||
# optimization pass: not necessary for correctness of the semantic pass
|
||||
@@ -1091,7 +1091,7 @@ proc semOverloadedCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode,
|
||||
if efWantIterable in flags:
|
||||
let typ = newTypeS(tyIterable, c)
|
||||
rawAddSon(typ, result.typ)
|
||||
result.typ = typ
|
||||
result.typ() = typ
|
||||
|
||||
proc resolveIndirectCall(c: PContext; n, nOrig: PNode;
|
||||
t: PType): TCandidate =
|
||||
@@ -1178,7 +1178,7 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags; expectedType: PType
|
||||
elif n0.typ.kind == tyFromExpr and c.inGenericContext > 0:
|
||||
# don't make assumptions, entire expression needs to be tyFromExpr
|
||||
result = semGenericStmt(c, n)
|
||||
result.typ = makeTypeFromExpr(c, result.copyTree)
|
||||
result.typ() = makeTypeFromExpr(c, result.copyTree)
|
||||
return
|
||||
else:
|
||||
n[0] = n0
|
||||
@@ -1436,7 +1436,7 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
|
||||
of tyStatic:
|
||||
if typ.n != nil:
|
||||
result = typ.n
|
||||
result.typ = typ.base
|
||||
result.typ() = typ.base
|
||||
else:
|
||||
result = newSymNode(s, n.info)
|
||||
else:
|
||||
@@ -1482,11 +1482,11 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
|
||||
onUse(n.info, s)
|
||||
if s.typ.kind == tyStatic:
|
||||
result = newSymNode(s, n.info)
|
||||
result.typ = s.typ
|
||||
result.typ() = s.typ
|
||||
elif s.ast != nil:
|
||||
result = semExpr(c, s.ast)
|
||||
else:
|
||||
n.typ = s.typ
|
||||
n.typ() = s.typ
|
||||
return n
|
||||
of skType:
|
||||
if n.kind != nkDotExpr: # dotExpr is already checked by builtinFieldAccess
|
||||
@@ -1495,7 +1495,7 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
|
||||
if s.typ.kind == tyStatic and s.typ.base.kind != tyNone and s.typ.n != nil:
|
||||
return s.typ.n
|
||||
result = newSymNode(s, n.info)
|
||||
result.typ = makeTypeDesc(c, s.typ)
|
||||
result.typ() = makeTypeDesc(c, s.typ)
|
||||
of skField:
|
||||
# old code, not sure if it's live code:
|
||||
markUsed(c, n.info, s)
|
||||
@@ -1521,7 +1521,7 @@ proc tryReadingGenericParam(c: PContext, n: PNode, i: PIdent, t: PType): PNode =
|
||||
if result == c.graph.emptyNode:
|
||||
if c.inGenericContext > 0:
|
||||
result = semGenericStmt(c, n)
|
||||
result.typ = makeTypeFromExpr(c, result.copyTree)
|
||||
result.typ() = makeTypeFromExpr(c, result.copyTree)
|
||||
else:
|
||||
result = nil
|
||||
of tyUserTypeClasses:
|
||||
@@ -1529,7 +1529,7 @@ proc tryReadingGenericParam(c: PContext, n: PNode, i: PIdent, t: PType): PNode =
|
||||
result = readTypeParameter(c, t, i, n.info)
|
||||
elif c.inGenericContext > 0:
|
||||
result = semGenericStmt(c, n)
|
||||
result.typ = makeTypeFromExpr(c, copyTree(result))
|
||||
result.typ() = makeTypeFromExpr(c, copyTree(result))
|
||||
else:
|
||||
result = nil
|
||||
of tyGenericBody, tyCompositeTypeClass:
|
||||
@@ -1538,12 +1538,12 @@ proc tryReadingGenericParam(c: PContext, n: PNode, i: PIdent, t: PType): PNode =
|
||||
if result != nil:
|
||||
# generic parameter exists, stop here but delay until instantiation
|
||||
result = semGenericStmt(c, n)
|
||||
result.typ = makeTypeFromExpr(c, copyTree(result))
|
||||
result.typ() = makeTypeFromExpr(c, copyTree(result))
|
||||
else:
|
||||
result = nil
|
||||
elif c.inGenericContext > 0 and t.containsUnresolvedType:
|
||||
result = semGenericStmt(c, n)
|
||||
result.typ = makeTypeFromExpr(c, copyTree(result))
|
||||
result.typ() = makeTypeFromExpr(c, copyTree(result))
|
||||
else:
|
||||
result = nil
|
||||
|
||||
@@ -1561,14 +1561,14 @@ proc tryReadingTypeField(c: PContext, n: PNode, i: PIdent, ty: PType): PNode =
|
||||
if f != nil:
|
||||
result = newSymNode(f)
|
||||
result.info = n.info
|
||||
result.typ = ty
|
||||
result.typ() = ty
|
||||
markUsed(c, n.info, f)
|
||||
onUse(n.info, f)
|
||||
of tyObject, tyTuple:
|
||||
if ty.n != nil and ty.n.kind == nkRecList:
|
||||
let field = lookupInRecord(ty.n, i)
|
||||
if field != nil:
|
||||
n.typ = makeTypeDesc(c, field.typ)
|
||||
n.typ() = makeTypeDesc(c, field.typ)
|
||||
result = n
|
||||
of tyGenericInst:
|
||||
result = tryReadingTypeField(c, n, i, ty.skipModifier)
|
||||
@@ -1615,7 +1615,7 @@ proc builtinFieldAccess(c: PContext; n: PNode; flags: var TExprFlags): PNode =
|
||||
# tyFromExpr, but when this happen in a macro this is not a built-in
|
||||
# field access and we leave the compiler to compile a normal call:
|
||||
if getCurrOwner(c).kind != skMacro:
|
||||
n.typ = makeTypeFromExpr(c, n.copyTree)
|
||||
n.typ() = makeTypeFromExpr(c, n.copyTree)
|
||||
flags.incl efCannotBeDotCall
|
||||
return n
|
||||
else:
|
||||
@@ -1655,12 +1655,12 @@ proc builtinFieldAccess(c: PContext; n: PNode; flags: var TExprFlags): PNode =
|
||||
n[0] = makeDeref(n[0])
|
||||
n[1] = newSymNode(f) # we now have the correct field
|
||||
n[1].info = info # preserve the original info
|
||||
n.typ = f.typ
|
||||
n.typ() = f.typ
|
||||
if check == nil:
|
||||
result = n
|
||||
else:
|
||||
check[0] = n
|
||||
check.typ = n.typ
|
||||
check.typ() = n.typ
|
||||
result = check
|
||||
elif ty.kind == tyTuple and ty.n != nil:
|
||||
f = getSymFromList(ty.n, i)
|
||||
@@ -1669,7 +1669,7 @@ proc builtinFieldAccess(c: PContext; n: PNode; flags: var TExprFlags): PNode =
|
||||
onUse(n[1].info, f)
|
||||
n[0] = makeDeref(n[0])
|
||||
n[1] = newSymNode(f)
|
||||
n.typ = f.typ
|
||||
n.typ() = f.typ
|
||||
result = n
|
||||
|
||||
# we didn't find any field, let's look for a generic param
|
||||
@@ -1718,33 +1718,21 @@ proc semDeref(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
result = n
|
||||
var t = skipTypes(n[0].typ, {tyGenericInst, tyVar, tyLent, tyAlias, tySink, tyOwned})
|
||||
case t.kind
|
||||
of tyRef, tyPtr: n.typ = t.elementType
|
||||
of tyRef, tyPtr: n.typ() = t.elementType
|
||||
of tyMetaTypes, tyFromExpr:
|
||||
n.typ = makeTypeFromExpr(c, n.copyTree)
|
||||
n.typ() = makeTypeFromExpr(c, n.copyTree)
|
||||
else: result = nil
|
||||
#GlobalError(n[0].info, errCircumNeedsPointer)
|
||||
|
||||
proc maybeInstantiateGeneric(c: PContext, n: PNode, s: PSym): PNode =
|
||||
## Instantiates generic if not lacking implicit generics,
|
||||
## otherwise returns n.
|
||||
let
|
||||
neededGenParams = s.ast[genericParamsPos].len
|
||||
heldGenParams = n.len - 1
|
||||
var implicitParams = 0
|
||||
for x in s.ast[genericParamsPos]:
|
||||
if tfImplicitTypeParam in x.typ.flags:
|
||||
inc implicitParams
|
||||
if heldGenParams != neededGenParams and implicitParams + heldGenParams == neededGenParams:
|
||||
# This is an implicit + explicit generic procedure without all args passed,
|
||||
# kicking back the sem'd symbol fixes #17212
|
||||
# Uncertain the hackiness of this solution.
|
||||
result = n
|
||||
else:
|
||||
result = explicitGenericInstantiation(c, n, s)
|
||||
if result == n:
|
||||
n[0] = copyTree(result[0])
|
||||
proc maybeInstantiateGeneric(c: PContext, n: PNode, s: PSym, doError: bool): PNode =
|
||||
## Attempts to instantiate generic proc symbol(s) with given parameters.
|
||||
## If instantiation causes errors; if `doError` is `true`, a type mismatch
|
||||
## error is given, otherwise `nil` is returned.
|
||||
result = explicitGenericInstantiation(c, n, s, doError)
|
||||
if result == n:
|
||||
n[0] = copyTree(result[0])
|
||||
|
||||
proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
proc semSubscript(c: PContext, n: PNode, flags: TExprFlags, afterOverloading = false): PNode =
|
||||
## returns nil if not a built-in subscript operator; also called for the
|
||||
## checking of assignments
|
||||
result = nil
|
||||
@@ -1765,10 +1753,10 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
if arr.kind == tyStatic:
|
||||
if arr.base.kind == tyNone:
|
||||
result = n
|
||||
result.typ = semStaticType(c, n[1], nil)
|
||||
result.typ() = semStaticType(c, n[1], nil)
|
||||
return
|
||||
elif arr.n != nil:
|
||||
return semSubscript(c, arr.n, flags)
|
||||
return semSubscript(c, arr.n, flags, afterOverloading)
|
||||
else:
|
||||
arr = arr.base
|
||||
|
||||
@@ -1787,18 +1775,18 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
if arg != nil:
|
||||
n[1] = arg
|
||||
result = n
|
||||
result.typ = elemType(arr)
|
||||
result.typ() = elemType(arr)
|
||||
# Other types have a bit more of leeway
|
||||
elif n[1].typ.skipTypes(abstractRange-{tyDistinct}).kind in
|
||||
{tyInt..tyInt64, tyUInt..tyUInt64}:
|
||||
result = n
|
||||
result.typ = elemType(arr)
|
||||
result.typ() = elemType(arr)
|
||||
of tyTypeDesc:
|
||||
# The result so far is a tyTypeDesc bound
|
||||
# a tyGenericBody. The line below will substitute
|
||||
# it with the instantiated type.
|
||||
result = n
|
||||
result.typ = makeTypeDesc(c, semTypeNode(c, n, nil))
|
||||
result.typ() = makeTypeDesc(c, semTypeNode(c, n, nil))
|
||||
#result = symNodeFromType(c, semTypeNode(c, n, nil), n.info)
|
||||
of tyTuple:
|
||||
if n.len != 2: return nil
|
||||
@@ -1808,7 +1796,7 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
if skipTypes(n[1].typ, {tyGenericInst, tyRange, tyOrdinal, tyAlias, tySink}).kind in
|
||||
{tyInt..tyInt64}:
|
||||
let idx = getOrdValue(n[1])
|
||||
if idx >= 0 and idx < arr.len: n.typ = arr[toInt(idx)]
|
||||
if idx >= 0 and idx < arr.len: n.typ() = arr[toInt(idx)]
|
||||
else:
|
||||
localError(c.config, n.info,
|
||||
"invalid index $1 in subscript for tuple of length $2" %
|
||||
@@ -1825,7 +1813,10 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
of skProc, skFunc, skMethod, skConverter, skIterator:
|
||||
# type parameters: partial generic specialization
|
||||
n[0] = semSymGenericInstantiation(c, n[0], s)
|
||||
result = maybeInstantiateGeneric(c, n, s)
|
||||
result = maybeInstantiateGeneric(c, n, s, doError = afterOverloading)
|
||||
if result != nil:
|
||||
# check newly created sym/symchoice
|
||||
result = semExpr(c, result, flags)
|
||||
of skMacro, skTemplate:
|
||||
if efInCall in flags:
|
||||
# We are processing macroOrTmpl[] in macroOrTmpl[](...) call.
|
||||
@@ -1900,7 +1891,7 @@ proc takeImplicitAddr(c: PContext, n: PNode; isLent: bool): PNode =
|
||||
localError(c.config, n.info, errExprHasNoAddress)
|
||||
result = newNodeIT(nkHiddenAddr, n.info, if n.typ.kind in {tyVar, tyLent}: n.typ else: makePtrType(c, n.typ))
|
||||
if n.typ.kind in {tyVar, tyLent}:
|
||||
n.typ = n.typ.elementType
|
||||
n.typ() = n.typ.elementType
|
||||
result.add(n)
|
||||
|
||||
proc asgnToResultVar(c: PContext, n, le, ri: PNode) {.inline.} =
|
||||
@@ -2068,7 +2059,7 @@ proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode =
|
||||
let lhs = n[0]
|
||||
let rhs = semExprWithType(c, n[1], {efTypeAllowed}, le)
|
||||
if lhs.kind == nkSym and lhs.sym.kind == skResult:
|
||||
n.typ = c.enforceVoidContext
|
||||
n.typ() = c.enforceVoidContext
|
||||
if c.p.owner.kind != skMacro and resultTypeIsInferrable(lhs.sym.typ):
|
||||
var rhsTyp = rhs.typ
|
||||
if rhsTyp.kind in tyUserTypeClasses and rhsTyp.isResolvedUserTypeClass:
|
||||
@@ -2079,7 +2070,7 @@ proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode =
|
||||
internalAssert c.config, c.p.resultSym != nil
|
||||
# Make sure the type is valid for the result variable
|
||||
typeAllowedCheck(c, n.info, rhsTyp, skResult)
|
||||
lhs.typ = rhsTyp
|
||||
lhs.typ() = rhsTyp
|
||||
c.p.resultSym.typ = rhsTyp
|
||||
c.p.owner.typ.setReturnType rhsTyp
|
||||
else:
|
||||
@@ -2127,7 +2118,7 @@ proc semProcBody(c: PContext, n: PNode; expectedType: PType = nil): PNode =
|
||||
if result.kind == nkNilLit:
|
||||
# or ImplicitlyDiscardable(result):
|
||||
# new semantic: 'result = x' triggers the void context
|
||||
result.typ = nil
|
||||
result.typ() = nil
|
||||
elif result.kind == nkStmtListExpr and result.typ.kind == tyNil:
|
||||
# to keep backwards compatibility bodies like:
|
||||
# nil
|
||||
@@ -2230,7 +2221,7 @@ proc semDefined(c: PContext, n: PNode): PNode =
|
||||
result = newIntNode(nkIntLit, 0)
|
||||
result.intVal = ord isDefined(c.config, considerQuotedIdentOrDot(c, n[1], n).s)
|
||||
result.info = n.info
|
||||
result.typ = getSysType(c.graph, n.info, tyBool)
|
||||
result.typ() = getSysType(c.graph, n.info, tyBool)
|
||||
|
||||
proc lookUpForDeclared(c: PContext, n: PNode, onlyCurrentScope: bool): PSym =
|
||||
case n.kind
|
||||
@@ -2268,7 +2259,7 @@ proc semDeclared(c: PContext, n: PNode, onlyCurrentScope: bool): PNode =
|
||||
result = newIntNode(nkIntLit, 0)
|
||||
result.intVal = ord lookUpForDeclared(c, n[1], onlyCurrentScope) != nil
|
||||
result.info = n.info
|
||||
result.typ = getSysType(c.graph, n.info, tyBool)
|
||||
result.typ() = getSysType(c.graph, n.info, tyBool)
|
||||
|
||||
proc expectMacroOrTemplateCall(c: PContext, n: PNode): PSym =
|
||||
## The argument to the proc should be nkCall(...) or similar
|
||||
@@ -2341,10 +2332,10 @@ proc semExpandToAst(c: PContext, n: PNode): PNode =
|
||||
localError(c.config, n.info, "getAst takes a call, but got " & n.renderTree)
|
||||
# Preserve the magic symbol in order to be handled in evals.nim
|
||||
internalAssert c.config, n[0].sym.magic == mExpandToAst
|
||||
#n.typ = getSysSym("NimNode").typ # expandedSym.getReturnType
|
||||
#n.typ() = getSysSym("NimNode").typ # expandedSym.getReturnType
|
||||
if n.kind == nkStmtList and n.len == 1: result = n[0]
|
||||
else: result = n
|
||||
result.typ = sysTypeFromName(c.graph, n.info, "NimNode")
|
||||
result.typ() = sysTypeFromName(c.graph, n.info, "NimNode")
|
||||
|
||||
proc semExpandToAst(c: PContext, n: PNode, magicSym: PSym,
|
||||
flags: TExprFlags = {}): PNode =
|
||||
@@ -2514,7 +2505,7 @@ proc semCompiles(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
|
||||
result = newIntNode(nkIntLit, ord(tryExpr(c, n[1], flags) != nil))
|
||||
result.info = n.info
|
||||
result.typ = getSysType(c.graph, n.info, tyBool)
|
||||
result.typ() = getSysType(c.graph, n.info, tyBool)
|
||||
|
||||
proc semShallowCopy(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||
if n.len == 3:
|
||||
@@ -2558,7 +2549,7 @@ proc semSizeof(c: PContext, n: PNode): PNode =
|
||||
else:
|
||||
n[1] = semExprWithType(c, n[1], {efDetermineType})
|
||||
#restoreOldStyleType(n[1])
|
||||
n.typ = getSysType(c.graph, n.info, tyInt)
|
||||
n.typ() = getSysType(c.graph, n.info, tyInt)
|
||||
result = foldSizeOf(c.config, n, n)
|
||||
|
||||
proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags; expectedType: PType = nil): PNode =
|
||||
@@ -2600,7 +2591,7 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags; expectedType: P
|
||||
markUsed(c, n.info, s)
|
||||
checkSonsLen(n, 2, c.config)
|
||||
result = newStrNodeT(renderTree(n[1], {renderNoComments}), n, c.graph)
|
||||
result.typ = getSysType(c.graph, n.info, tyString)
|
||||
result.typ() = getSysType(c.graph, n.info, tyString)
|
||||
of mParallel:
|
||||
markUsed(c, n.info, s)
|
||||
if parallel notin c.features:
|
||||
@@ -2626,9 +2617,9 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags; expectedType: P
|
||||
let typ = result[^1].typ
|
||||
if not typ.isEmptyType:
|
||||
if spawnResult(typ, c.inParallelStmt > 0) == srFlowVar:
|
||||
result.typ = createFlowVar(c, typ, n.info)
|
||||
result.typ() = createFlowVar(c, typ, n.info)
|
||||
else:
|
||||
result.typ = typ
|
||||
result.typ() = typ
|
||||
result.add instantiateCreateFlowVarCall(c, typ, n.info).newSymNode
|
||||
else:
|
||||
result.add c.graph.emptyNode
|
||||
@@ -2636,7 +2627,7 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags; expectedType: P
|
||||
markUsed(c, n.info, s)
|
||||
result = setMs(n, s)
|
||||
result[1] = semExpr(c, n[1])
|
||||
result.typ = n[1].typ
|
||||
result.typ() = n[1].typ
|
||||
of mPlugin:
|
||||
markUsed(c, n.info, s)
|
||||
# semDirectOp with conditional 'afterCallActions':
|
||||
@@ -2767,18 +2758,18 @@ proc semWhen(c: PContext, n: PNode, semCheck = true): PNode =
|
||||
else: illFormedAst(n, c.config)
|
||||
if cannotResolve:
|
||||
result = semGenericStmt(c, n)
|
||||
result.typ = makeTypeFromExpr(c, result.copyTree)
|
||||
result.typ() = makeTypeFromExpr(c, result.copyTree)
|
||||
return
|
||||
if result == nil:
|
||||
result = newNodeI(nkEmpty, n.info)
|
||||
if whenNimvm:
|
||||
result.typ = typ
|
||||
result.typ() = typ
|
||||
if n.len == 1:
|
||||
result.add(newTree(nkElse, newNode(nkStmtList)))
|
||||
|
||||
proc semSetConstr(c: PContext, n: PNode, expectedType: PType = nil): PNode =
|
||||
result = newNodeI(nkCurly, n.info)
|
||||
result.typ = newTypeS(tySet, c)
|
||||
result.typ() = newTypeS(tySet, c)
|
||||
result.typ.flags.incl tfIsConstructor
|
||||
var expectedElementType: PType = nil
|
||||
if expectedType != nil and (
|
||||
@@ -2804,7 +2795,7 @@ proc semSetConstr(c: PContext, n: PNode, expectedType: PType = nil): PNode =
|
||||
if doSetType:
|
||||
typ = skipTypes(n[i][1].typ,
|
||||
{tyGenericInst, tyVar, tyLent, tyOrdinal, tyAlias, tySink})
|
||||
n[i].typ = n[i][2].typ # range node needs type too
|
||||
n[i].typ() = n[i][2].typ # range node needs type too
|
||||
elif n[i].kind == nkRange:
|
||||
# already semchecked
|
||||
if doSetType:
|
||||
@@ -2919,7 +2910,7 @@ proc semTupleFieldsConstr(c: PContext, n: PNode, flags: TExprFlags; expectedType
|
||||
|
||||
if n[i][1].typ.kind == tyTypeDesc:
|
||||
localError(c.config, n[i][1].info, "typedesc not allowed as tuple field.")
|
||||
n[i][1].typ = errorType(c)
|
||||
n[i][1].typ() = errorType(c)
|
||||
|
||||
var f = newSymS(skField, n[i][0], c)
|
||||
f.typ = skipIntLit(n[i][1].typ.skipTypes({tySink}), c.idgen)
|
||||
@@ -2928,7 +2919,7 @@ proc semTupleFieldsConstr(c: PContext, n: PNode, flags: TExprFlags; expectedType
|
||||
typ.n.add newSymNode(f)
|
||||
n[i][0] = newSymNode(f)
|
||||
result.add n[i]
|
||||
result.typ = typ
|
||||
result.typ() = typ
|
||||
|
||||
proc semTuplePositionsConstr(c: PContext, n: PNode, flags: TExprFlags; expectedType: PType = nil): PNode =
|
||||
result = n # we don't modify n, but compute the type:
|
||||
@@ -2949,7 +2940,7 @@ proc semTuplePositionsConstr(c: PContext, n: PNode, flags: TExprFlags; expectedT
|
||||
# `const foo = if true: (0, nil) else: (1, new(int))`
|
||||
n[i] = fitNode(c, expectedElemType, n[i], n[i].info)
|
||||
addSonSkipIntLit(typ, n[i].typ.skipTypes({tySink}), c.idgen)
|
||||
result.typ = typ
|
||||
result.typ() = typ
|
||||
|
||||
include semobjconstr
|
||||
|
||||
@@ -2965,13 +2956,13 @@ proc semBlock(c: PContext, n: PNode; flags: TExprFlags; expectedType: PType = ni
|
||||
if sfGenSym notin labl.flags:
|
||||
addDecl(c, labl)
|
||||
elif labl.owner == nil:
|
||||
labl.owner = c.p.owner
|
||||
setOwner(labl, c.p.owner)
|
||||
n[0] = newSymNode(labl, n[0].info)
|
||||
suggestSym(c.graph, n[0].info, labl, c.graph.usageSym)
|
||||
styleCheckDef(c, labl)
|
||||
onDef(n[0].info, labl)
|
||||
n[1] = semExpr(c, n[1], flags, expectedType)
|
||||
n.typ = n[1].typ
|
||||
n.typ() = n[1].typ
|
||||
if isEmptyType(n.typ): n.transitionSonsKind(nkBlockStmt)
|
||||
else: n.transitionSonsKind(nkBlockExpr)
|
||||
closeScope(c)
|
||||
@@ -3049,7 +3040,7 @@ proc semTupleConstr(c: PContext, n: PNode, flags: TExprFlags; expectedType: PTyp
|
||||
if isTupleType: # expressions as ``(int, string)`` are reinterpret as type expressions
|
||||
result = n
|
||||
var typ = semTypeNode(c, n, nil).skipTypes({tyTypeDesc})
|
||||
result.typ = makeTypeDesc(c, typ)
|
||||
result.typ() = makeTypeDesc(c, typ)
|
||||
else:
|
||||
result = tupexp
|
||||
|
||||
@@ -3271,10 +3262,10 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: PType
|
||||
if expectedType != nil and (
|
||||
let expected = expectedType.skipTypes(abstractRange-{tyDistinct});
|
||||
expected.kind == typeKind):
|
||||
result.typ = expected
|
||||
result.typ() = expected
|
||||
changeType(c, result, expectedType, check=true)
|
||||
else:
|
||||
result.typ = getSysType(c.graph, n.info, typeKind)
|
||||
result.typ() = getSysType(c.graph, n.info, typeKind)
|
||||
|
||||
result = n
|
||||
when defined(nimsuggest):
|
||||
@@ -3309,7 +3300,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: PType
|
||||
# localError(c.config, n.info, errInstantiateXExplicitly, s.name.s)
|
||||
# "procs literals" are 'owned'
|
||||
if optOwnedRefs in c.config.globalOptions:
|
||||
result.typ = makeVarType(c, result.typ, tyOwned)
|
||||
result.typ() = makeVarType(c, result.typ, tyOwned)
|
||||
of skEnumField:
|
||||
result = enumFieldSymChoice(c, n, s, flags)
|
||||
else:
|
||||
@@ -3338,11 +3329,11 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: PType
|
||||
discard
|
||||
of nkNilLit:
|
||||
if result.typ == nil:
|
||||
result.typ = getNilType(c)
|
||||
result.typ() = getNilType(c)
|
||||
if expectedType != nil and expectedType.kind notin {tyUntyped, tyTyped}:
|
||||
var m = newCandidate(c, result.typ)
|
||||
if typeRel(m, expectedType, result.typ) >= isSubtype:
|
||||
result.typ = expectedType
|
||||
result.typ() = expectedType
|
||||
# or: result = fitNode(c, expectedType, result, n.info)
|
||||
of nkIntLit:
|
||||
if result.typ == nil:
|
||||
@@ -3370,10 +3361,10 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: PType
|
||||
if expectedType != nil and (
|
||||
let expected = expectedType.skipTypes(abstractRange-{tyDistinct});
|
||||
expected.kind in {tyFloat..tyFloat128}):
|
||||
result.typ = expected
|
||||
result.typ() = expected
|
||||
changeType(c, result, expectedType, check=true)
|
||||
else:
|
||||
result.typ = getSysType(c.graph, n.info, tyFloat64)
|
||||
result.typ() = getSysType(c.graph, n.info, tyFloat64)
|
||||
of nkFloat32Lit: directLiteral(tyFloat32)
|
||||
of nkFloat64Lit: directLiteral(tyFloat64)
|
||||
of nkFloat128Lit: directLiteral(tyFloat128)
|
||||
@@ -3382,9 +3373,9 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: PType
|
||||
if expectedType != nil and (
|
||||
let expected = expectedType.skipTypes(abstractRange-{tyDistinct});
|
||||
expected.kind in {tyString, tyCstring}):
|
||||
result.typ = expectedType
|
||||
result.typ() = expectedType
|
||||
else:
|
||||
result.typ = getSysType(c.graph, n.info, tyString)
|
||||
result.typ() = getSysType(c.graph, n.info, tyString)
|
||||
of nkCharLit: directLiteral(tyChar)
|
||||
of nkDotExpr:
|
||||
result = semFieldAccess(c, n, flags)
|
||||
@@ -3399,13 +3390,13 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType: PType
|
||||
let modifier = n.modifierTypeKindOfNode
|
||||
if modifier != tyNone:
|
||||
var baseType = semExpr(c, n[0]).typ.skipTypes({tyTypeDesc})
|
||||
result.typ = c.makeTypeDesc(newTypeS(modifier, c, baseType))
|
||||
result.typ() = c.makeTypeDesc(newTypeS(modifier, c, baseType))
|
||||
return
|
||||
var typ = semTypeNode(c, n, nil).skipTypes({tyTypeDesc})
|
||||
result.typ = makeTypeDesc(c, typ)
|
||||
result.typ() = makeTypeDesc(c, typ)
|
||||
of nkStmtListType:
|
||||
let typ = semTypeNode(c, n, nil)
|
||||
result.typ = makeTypeDesc(c, typ)
|
||||
result.typ() = makeTypeDesc(c, typ)
|
||||
of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit:
|
||||
# check if it is an expression macro:
|
||||
checkMinSonsLen(n, 1, c.config)
|
||||
|
||||
@@ -38,7 +38,7 @@ proc newIntNodeT*(intVal: Int128, n: PNode; idgen: IdGenerator; g: ModuleGraph):
|
||||
# original type was 'int', not a distinct int etc.
|
||||
if n.typ.kind == tyInt:
|
||||
# access cache for the int lit type
|
||||
result.typ = getIntLitTypeG(g, result, idgen)
|
||||
result.typ() = getIntLitTypeG(g, result, idgen)
|
||||
result.info = n.info
|
||||
|
||||
proc newFloatNodeT*(floatVal: BiggestFloat, n: PNode; g: ModuleGraph): PNode =
|
||||
@@ -46,12 +46,12 @@ proc newFloatNodeT*(floatVal: BiggestFloat, n: PNode; g: ModuleGraph): PNode =
|
||||
result = newFloatNode(nkFloat32Lit, floatVal)
|
||||
else:
|
||||
result = newFloatNode(nkFloatLit, floatVal)
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
result.info = n.info
|
||||
|
||||
proc newStrNodeT*(strVal: string, n: PNode; g: ModuleGraph): PNode =
|
||||
result = newStrNode(nkStrLit, strVal)
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
result.info = n.info
|
||||
|
||||
proc getConstExpr*(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode
|
||||
@@ -302,6 +302,9 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; idgen: IdGenerator; g: ModuleGraph): P
|
||||
of mMinusSet:
|
||||
result = nimsets.diffSets(g.config, a, b)
|
||||
result.info = n.info
|
||||
of mXorSet:
|
||||
result = nimsets.symdiffSets(g.config, a, b)
|
||||
result.info = n.info
|
||||
of mConStrStr: result = newStrNodeT(getStrOrChar(a) & getStrOrChar(b), n, g)
|
||||
of mInSet: result = newIntNodeT(toInt128(ord(inSet(a, b))), n, idgen, g)
|
||||
of mRepr:
|
||||
@@ -316,7 +319,7 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; idgen: IdGenerator; g: ModuleGraph): P
|
||||
of mEnumToStr: result = newStrNodeT(ordinalValToString(a, g), n, g)
|
||||
of mArrToSeq:
|
||||
result = copyTree(a)
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
of mCompileOption:
|
||||
result = newIntNodeT(toInt128(ord(commands.testCompileOption(g.config, a.getStr, n.info))), n, idgen, g)
|
||||
of mCompileOptionArg:
|
||||
@@ -411,7 +414,7 @@ proc foldConv(n, a: PNode; idgen: IdGenerator; g: ModuleGraph; check = false): P
|
||||
result = newIntNodeT(toInt128(a.getOrdValue != 0), n, idgen, g)
|
||||
of tyBool, tyEnum: # xxx shouldn't we disallow `tyEnum`?
|
||||
result = a
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
else:
|
||||
raiseAssert $srcTyp.kind
|
||||
of tyInt..tyInt64, tyUInt..tyUInt64:
|
||||
@@ -428,7 +431,7 @@ proc foldConv(n, a: PNode; idgen: IdGenerator; g: ModuleGraph; check = false): P
|
||||
result = newIntNodeT(val, n, idgen, g)
|
||||
else:
|
||||
result = a
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
if check and result.kind in {nkCharLit..nkUInt64Lit} and
|
||||
dstTyp.kind notin {tyUInt..tyUInt64}:
|
||||
rangeCheck(n, getInt(result), g)
|
||||
@@ -438,12 +441,12 @@ proc foldConv(n, a: PNode; idgen: IdGenerator; g: ModuleGraph; check = false): P
|
||||
result = newFloatNodeT(toFloat64(getOrdValue(a)), n, g)
|
||||
else:
|
||||
result = a
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
of tyOpenArray, tyVarargs, tyProc, tyPointer:
|
||||
result = nil
|
||||
else:
|
||||
result = a
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
|
||||
proc getArrayConstr(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode =
|
||||
if n.kind == nkBracket:
|
||||
@@ -514,10 +517,10 @@ proc foldConStrStr(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode
|
||||
proc newSymNodeTypeDesc*(s: PSym; idgen: IdGenerator; info: TLineInfo): PNode =
|
||||
result = newSymNode(s, info)
|
||||
if s.typ.kind != tyTypeDesc:
|
||||
result.typ = newType(tyTypeDesc, idgen, s.owner)
|
||||
result.typ() = newType(tyTypeDesc, idgen, s.owner)
|
||||
result.typ.addSonSkipIntLit(s.typ, idgen)
|
||||
else:
|
||||
result.typ = s.typ
|
||||
result.typ() = s.typ
|
||||
|
||||
proc foldDefine(m, s: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode =
|
||||
result = nil
|
||||
@@ -636,7 +639,7 @@ proc getConstExpr(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode
|
||||
if s.typ.kind == tyStatic:
|
||||
if s.typ.n != nil and tfUnresolved notin s.typ.flags:
|
||||
result = s.typ.n
|
||||
result.typ = s.typ.base
|
||||
result.typ() = s.typ.base
|
||||
elif s.typ.isIntLit:
|
||||
result = s.typ.n
|
||||
else:
|
||||
@@ -749,7 +752,7 @@ proc getConstExpr(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode
|
||||
if a == nil: return
|
||||
if leValueConv(n[1], a) and leValueConv(a, n[2]):
|
||||
result = a # a <= x and x <= b
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
elif n.typ.kind in {tyUInt..tyUInt64}:
|
||||
discard "don't check uints"
|
||||
else:
|
||||
@@ -760,7 +763,7 @@ proc getConstExpr(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode
|
||||
var a = getConstExpr(m, n[0], idgen, g)
|
||||
if a == nil: return
|
||||
result = a
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
|
||||
var a = getConstExpr(m, n[1], idgen, g)
|
||||
if a == nil: return
|
||||
@@ -777,7 +780,7 @@ proc getConstExpr(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode
|
||||
not (n.typ.kind == tyProc and a.typ.kind == tyProc):
|
||||
# we allow compile-time 'cast' for pointer types:
|
||||
result = a
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
of nkBracketExpr: result = foldArrayAccess(m, n, idgen, g)
|
||||
of nkDotExpr: result = foldFieldAccess(m, n, idgen, g)
|
||||
of nkCheckedFieldExpr:
|
||||
|
||||
@@ -78,10 +78,10 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym,
|
||||
if result.kind == nkSym:
|
||||
result = newOpenSym(result)
|
||||
else:
|
||||
result.typ = nil
|
||||
result.typ() = nil
|
||||
else:
|
||||
result.flags.incl nfDisabledOpenSym
|
||||
result.typ = nil
|
||||
result.typ() = nil
|
||||
case s.kind
|
||||
of skUnknown:
|
||||
# Introduced in this pass! Leave it as an identifier.
|
||||
@@ -116,7 +116,7 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym,
|
||||
result = newOpenSym(result)
|
||||
else:
|
||||
result.flags.incl nfDisabledOpenSym
|
||||
result.typ = nil
|
||||
result.typ() = nil
|
||||
else:
|
||||
result = n
|
||||
else:
|
||||
@@ -126,7 +126,7 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym,
|
||||
result = newOpenSym(result)
|
||||
else:
|
||||
result.flags.incl nfDisabledOpenSym
|
||||
result.typ = nil
|
||||
result.typ() = nil
|
||||
onUse(n.info, s)
|
||||
of skParam:
|
||||
result = n
|
||||
@@ -145,7 +145,7 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym,
|
||||
result = newOpenSym(result)
|
||||
else:
|
||||
result.flags.incl nfDisabledOpenSym
|
||||
result.typ = nil
|
||||
result.typ() = nil
|
||||
elif c.inGenericContext > 0 and withinConcept notin flags:
|
||||
# don't leave generic param as identifier node in generic type,
|
||||
# sigmatch will try to instantiate generic type AST without all params
|
||||
@@ -157,7 +157,7 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym,
|
||||
result = newOpenSym(result)
|
||||
else:
|
||||
result.flags.incl nfDisabledOpenSym
|
||||
result.typ = nil
|
||||
result.typ() = nil
|
||||
else:
|
||||
result = n
|
||||
onUse(n.info, s)
|
||||
@@ -168,7 +168,7 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym,
|
||||
result = newOpenSym(result)
|
||||
else:
|
||||
result.flags.incl nfDisabledOpenSym
|
||||
result.typ = nil
|
||||
result.typ() = nil
|
||||
onUse(n.info, s)
|
||||
|
||||
proc lookup(c: PContext, n: PNode, flags: TSemGenericFlags,
|
||||
|
||||
@@ -111,7 +111,7 @@ proc freshGenSyms(c: PContext; n: PNode, owner, orig: PSym, symMap: var SymMappi
|
||||
elif s.owner == nil or s.owner.kind == skPackage:
|
||||
#echo "copied this ", s.name.s
|
||||
x = copySym(s, c.idgen)
|
||||
x.owner = owner
|
||||
setOwner(x, owner)
|
||||
idTablePut(symMap, s, x)
|
||||
n.sym = x
|
||||
else:
|
||||
@@ -273,7 +273,7 @@ proc instantiateProcType(c: PContext, pt: LayeredIdTable,
|
||||
internalAssert c.config, originalParams[i].kind == nkSym
|
||||
let oldParam = originalParams[i].sym
|
||||
let param = copySym(oldParam, c.idgen)
|
||||
param.owner = prc
|
||||
setOwner(param, prc)
|
||||
param.typ = result[i]
|
||||
|
||||
# The default value is instantiated and fitted against the final
|
||||
@@ -302,7 +302,7 @@ proc instantiateProcType(c: PContext, pt: LayeredIdTable,
|
||||
# the only way the default value might be inserted).
|
||||
param.ast = errorNode(c, def)
|
||||
# we know the node is empty, we need the actual type for error message
|
||||
param.ast.typ = def.typ
|
||||
param.ast.typ() = def.typ
|
||||
else:
|
||||
param.ast = fitNodePostMatch(c, typeToFit, converted)
|
||||
param.typ = result[i]
|
||||
@@ -395,9 +395,9 @@ proc generateInstance(c: PContext, fn: PSym, pt: LayeredIdTable,
|
||||
let passc = getLocalPassC(c, producer)
|
||||
if passc != "": #pass the local compiler options to the consumer module too
|
||||
extccomp.addLocalCompileOption(c.config, passc, toFullPathConsiderDirty(c.config, c.module.info.fileIndex))
|
||||
result.owner = c.module
|
||||
setOwner(result, c.module)
|
||||
else:
|
||||
result.owner = fn
|
||||
setOwner(result, fn)
|
||||
result.ast = n
|
||||
pushOwner(c, result)
|
||||
|
||||
|
||||
@@ -50,8 +50,8 @@ proc annotateType*(n: PNode, t: PType; conf: ConfigRef) =
|
||||
case n.kind
|
||||
of nkObjConstr:
|
||||
let x = t.skipTypes(abstractPtrs)
|
||||
n.typ = t
|
||||
n[0].typ = t
|
||||
n.typ() = t
|
||||
n[0].typ() = t
|
||||
for i in 1..<n.len:
|
||||
var j = i-1
|
||||
let field = x.ithField(j)
|
||||
@@ -62,12 +62,12 @@ proc annotateType*(n: PNode, t: PType; conf: ConfigRef) =
|
||||
annotateType(n[i][1], field.typ, conf)
|
||||
of nkPar, nkTupleConstr:
|
||||
if x.kind == tyTuple:
|
||||
n.typ = t
|
||||
n.typ() = t
|
||||
for i in 0..<n.len:
|
||||
if i >= x.kidsLen: globalError conf, n.info, "invalid field at index " & $i
|
||||
else: annotateType(n[i], x[i], conf)
|
||||
elif x.kind == tyProc and x.callConv == ccClosure:
|
||||
n.typ = t
|
||||
n.typ() = t
|
||||
elif x.kind == tyOpenArray: # `opcSlice` transforms slices into tuples
|
||||
if n.kind == nkTupleConstr:
|
||||
let
|
||||
@@ -88,39 +88,39 @@ proc annotateType*(n: PNode, t: PType; conf: ConfigRef) =
|
||||
globalError(conf, n.info, "Incorrectly generated tuple constr")
|
||||
n[] = bracketExpr[]
|
||||
|
||||
n.typ = t
|
||||
n.typ() = t
|
||||
else:
|
||||
globalError(conf, n.info, "() must have a tuple type")
|
||||
of nkBracket:
|
||||
if x.kind in {tyArray, tySequence, tyOpenArray}:
|
||||
n.typ = t
|
||||
n.typ() = t
|
||||
for m in n: annotateType(m, x.elemType, conf)
|
||||
else:
|
||||
globalError(conf, n.info, "[] must have some form of array type")
|
||||
of nkCurly:
|
||||
if x.kind in {tySet}:
|
||||
n.typ = t
|
||||
n.typ() = t
|
||||
for m in n: annotateType(m, x.elemType, conf)
|
||||
else:
|
||||
globalError(conf, n.info, "{} must have the set type")
|
||||
of nkFloatLit..nkFloat128Lit:
|
||||
if x.kind in {tyFloat..tyFloat128}:
|
||||
n.typ = t
|
||||
n.typ() = t
|
||||
else:
|
||||
globalError(conf, n.info, "float literal must have some float type")
|
||||
of nkCharLit..nkUInt64Lit:
|
||||
if x.kind in {tyInt..tyUInt64, tyBool, tyChar, tyEnum}:
|
||||
n.typ = t
|
||||
n.typ() = t
|
||||
else:
|
||||
globalError(conf, n.info, "integer literal must have some int type")
|
||||
of nkStrLit..nkTripleStrLit:
|
||||
if x.kind in {tyString, tyCstring}:
|
||||
n.typ = t
|
||||
n.typ() = t
|
||||
else:
|
||||
globalError(conf, n.info, "string literal must be of some string type")
|
||||
of nkNilLit:
|
||||
if x.kind in NilableTypes+{tyString, tySequence}:
|
||||
n.typ = t
|
||||
n.typ() = t
|
||||
else:
|
||||
globalError(conf, n.info, "nil literal must be of some pointer type")
|
||||
else: discard
|
||||
|
||||
@@ -18,7 +18,7 @@ proc addDefaultFieldForNew(c: PContext, n: PNode): PNode =
|
||||
let typ = result[1].typ # new(x)
|
||||
if typ.skipTypes({tyGenericInst, tyAlias, tySink}).kind == tyRef and typ.skipTypes({tyGenericInst, tyAlias, tySink})[0].kind == tyObject:
|
||||
var asgnExpr = newTree(nkObjConstr, newNodeIT(nkType, result[1].info, typ))
|
||||
asgnExpr.typ = typ
|
||||
asgnExpr.typ() = typ
|
||||
var t = typ.skipTypes({tyGenericInst, tyAlias, tySink})[0]
|
||||
while true:
|
||||
asgnExpr.sons.add defaultFieldsForTheUninitialized(c, t.n, false)
|
||||
@@ -38,7 +38,7 @@ proc semAddr(c: PContext; n: PNode): PNode =
|
||||
if isAssignable(c, x) notin {arLValue, arLocalLValue, arAddressableConst, arLentValue}:
|
||||
localError(c.config, n.info, errExprHasNoAddress)
|
||||
result.add x
|
||||
result.typ = makePtrType(c, x.typ)
|
||||
result.typ() = makePtrType(c, x.typ)
|
||||
|
||||
proc semTypeOf(c: PContext; n: PNode): PNode =
|
||||
var m = BiggestInt 1 # typeOfIter
|
||||
@@ -55,18 +55,18 @@ proc semTypeOf(c: PContext; n: PNode): PNode =
|
||||
result.add typExpr
|
||||
if typExpr.typ.kind == tyFromExpr:
|
||||
typExpr.typ.flags.incl tfNonConstExpr
|
||||
result.typ = makeTypeDesc(c, typExpr.typ)
|
||||
result.typ() = makeTypeDesc(c, typExpr.typ)
|
||||
|
||||
type
|
||||
SemAsgnMode = enum asgnNormal, noOverloadedSubscript, noOverloadedAsgn
|
||||
|
||||
proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode
|
||||
proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode
|
||||
proc semSubscript(c: PContext, n: PNode, flags: TExprFlags, afterOverloading = false): PNode
|
||||
|
||||
proc semArrGet(c: PContext; n: PNode; flags: TExprFlags): PNode =
|
||||
result = newNodeI(nkBracketExpr, n.info)
|
||||
for i in 1..<n.len: result.add(n[i])
|
||||
result = semSubscript(c, result, flags)
|
||||
result = semSubscript(c, result, flags, afterOverloading = true)
|
||||
if result.isNil:
|
||||
let x = copyTree(n)
|
||||
x[0] = newIdentNode(getIdent(c.cache, "[]"), n.info)
|
||||
@@ -76,12 +76,23 @@ proc semArrGet(c: PContext; n: PNode; flags: TExprFlags): PNode =
|
||||
if a.typ != nil and a.typ.kind in {tyGenericParam, tyFromExpr}:
|
||||
# expression is compiled early in a generic body
|
||||
result = semGenericStmt(c, x)
|
||||
result.typ = makeTypeFromExpr(c, copyTree(result))
|
||||
result.typ() = makeTypeFromExpr(c, copyTree(result))
|
||||
result.typ.flags.incl tfNonConstExpr
|
||||
return
|
||||
bracketNotFoundError(c, x, flags)
|
||||
#localError(c.config, n.info, "could not resolve: " & $n)
|
||||
result = errorNode(c, n)
|
||||
let s = # extract sym from first arg
|
||||
if n.len > 1:
|
||||
if n[1].kind == nkSym: n[1].sym
|
||||
elif n[1].kind in nkSymChoices + {nkOpenSym} and n[1].len != 0:
|
||||
n[1][0].sym
|
||||
else: nil
|
||||
else: nil
|
||||
if s != nil and s.kind in routineKinds:
|
||||
# this is a failed generic instantiation
|
||||
# semSubscript should already error but this is better for cascading errors
|
||||
result = explicitGenericInstError(c, n)
|
||||
else:
|
||||
bracketNotFoundError(c, x, flags)
|
||||
result = errorNode(c, n)
|
||||
|
||||
proc semArrPut(c: PContext; n: PNode; flags: TExprFlags): PNode =
|
||||
# rewrite `[]=`(a, i, x) back to ``a[i] = x``.
|
||||
@@ -189,15 +200,15 @@ proc evalTypeTrait(c: PContext; traitCall: PNode, operand: PType, context: PSym)
|
||||
let preferStr = traitCall[2].strVal
|
||||
prefer = parseEnum[TPreferedDesc](preferStr)
|
||||
result = newStrNode(nkStrLit, operand.typeToString(prefer))
|
||||
result.typ = getSysType(c.graph, traitCall[1].info, tyString)
|
||||
result.typ() = getSysType(c.graph, traitCall[1].info, tyString)
|
||||
result.info = traitCall.info
|
||||
of "name", "$":
|
||||
result = newStrNode(nkStrLit, operand.typeToString(preferTypeName))
|
||||
result.typ = getSysType(c.graph, traitCall[1].info, tyString)
|
||||
result.typ() = getSysType(c.graph, traitCall[1].info, tyString)
|
||||
result.info = traitCall.info
|
||||
of "arity":
|
||||
result = newIntNode(nkIntLit, operand.len - ord(operand.kind==tyProc))
|
||||
result.typ = newType(tyInt, c.idgen, context)
|
||||
result.typ() = newType(tyInt, c.idgen, context)
|
||||
result.info = traitCall.info
|
||||
of "genericHead":
|
||||
var arg = operand
|
||||
@@ -267,7 +278,7 @@ proc semOrd(c: PContext, n: PNode): PNode =
|
||||
discard
|
||||
else:
|
||||
localError(c.config, n.info, errOrdinalTypeExpected % typeToString(parType, preferDesc))
|
||||
result.typ = errorType(c)
|
||||
result.typ() = errorType(c)
|
||||
|
||||
proc semBindSym(c: PContext, n: PNode): PNode =
|
||||
result = copyNode(n)
|
||||
@@ -383,7 +394,7 @@ proc semOf(c: PContext, n: PNode): PNode =
|
||||
message(c.config, n.info, hintConditionAlwaysTrue, renderTree(n))
|
||||
result = newIntNode(nkIntLit, 1)
|
||||
result.info = n.info
|
||||
result.typ = getSysType(c.graph, n.info, tyBool)
|
||||
result.typ() = getSysType(c.graph, n.info, tyBool)
|
||||
return result
|
||||
elif diff == high(int):
|
||||
if commonSuperclass(a, b) == nil:
|
||||
@@ -392,10 +403,10 @@ proc semOf(c: PContext, n: PNode): PNode =
|
||||
message(c.config, n.info, hintConditionAlwaysFalse, renderTree(n))
|
||||
result = newIntNode(nkIntLit, 0)
|
||||
result.info = n.info
|
||||
result.typ = getSysType(c.graph, n.info, tyBool)
|
||||
result.typ() = getSysType(c.graph, n.info, tyBool)
|
||||
else:
|
||||
localError(c.config, n.info, "'of' takes 2 arguments")
|
||||
n.typ = getSysType(c.graph, n.info, tyBool)
|
||||
n.typ() = getSysType(c.graph, n.info, tyBool)
|
||||
result = n
|
||||
|
||||
proc semUnown(c: PContext; n: PNode): PNode =
|
||||
@@ -430,9 +441,9 @@ proc semUnown(c: PContext; n: PNode): PNode =
|
||||
result = t
|
||||
|
||||
result = copyTree(n[1])
|
||||
result.typ = unownedType(c, result.typ)
|
||||
result.typ() = unownedType(c, result.typ)
|
||||
# little hack for injectdestructors.nim (see bug #11350):
|
||||
#result[0].typ = nil
|
||||
#result[0].typ() = nil
|
||||
|
||||
proc turnFinalizerIntoDestructor(c: PContext; orig: PSym; info: TLineInfo): PSym =
|
||||
# We need to do 2 things: Replace n.typ which is a 'ref T' by a 'var T' type.
|
||||
@@ -442,7 +453,7 @@ proc turnFinalizerIntoDestructor(c: PContext; orig: PSym; info: TLineInfo): PSym
|
||||
proc transform(c: PContext; n: PNode; old, fresh: PType; oldParam, newParam: PSym): PNode =
|
||||
result = shallowCopy(n)
|
||||
if sameTypeOrNil(n.typ, old):
|
||||
result.typ = fresh
|
||||
result.typ() = fresh
|
||||
if n.kind == nkSym and n.sym == oldParam:
|
||||
result.sym = newParam
|
||||
for i in 0 ..< safeLen(n):
|
||||
@@ -453,7 +464,7 @@ proc turnFinalizerIntoDestructor(c: PContext; orig: PSym; info: TLineInfo): PSym
|
||||
result = copySym(orig, c.idgen)
|
||||
result.info = info
|
||||
result.flags.incl sfFromGeneric
|
||||
result.owner = orig
|
||||
setOwner(result, orig)
|
||||
let origParamType = orig.typ.firstParamType
|
||||
let newParamType = makeVarType(result, origParamType.skipTypes(abstractPtrs), c.idgen)
|
||||
let oldParam = orig.typ.n[1].sym
|
||||
@@ -524,10 +535,10 @@ proc semNewFinalize(c: PContext; n: PNode): PNode =
|
||||
discard "already turned this one into a finalizer"
|
||||
else:
|
||||
if fin.instantiatedFrom != nil and fin.instantiatedFrom != fin.owner: #undo move
|
||||
fin.owner = fin.instantiatedFrom
|
||||
setOwner(fin, fin.instantiatedFrom)
|
||||
let wrapperSym = newSym(skProc, getIdent(c.graph.cache, fin.name.s & "FinalizerWrapper"), c.idgen, fin.owner, fin.info)
|
||||
let selfSymNode = newSymNode(copySym(fin.ast[paramsPos][1][0].sym, c.idgen))
|
||||
selfSymNode.typ = fin.typ.firstParamType
|
||||
selfSymNode.typ() = fin.typ.firstParamType
|
||||
wrapperSym.flags.incl sfUsed
|
||||
|
||||
let wrapper = c.semExpr(c, newProcNode(nkProcDef, fin.info, body = newTree(nkCall, newSymNode(fin), selfSymNode),
|
||||
@@ -539,13 +550,13 @@ proc semNewFinalize(c: PContext; n: PNode): PNode =
|
||||
genericParams = fin.ast[genericParamsPos], pragmas = fin.ast[pragmasPos], exceptions = fin.ast[miscPos]), {})
|
||||
|
||||
var transFormedSym = turnFinalizerIntoDestructor(c, wrapperSym, wrapper.info)
|
||||
transFormedSym.owner = fin
|
||||
setOwner(transFormedSym, fin)
|
||||
if c.config.backend == backendCpp or sfCompileToCpp in c.module.flags:
|
||||
let origParamType = transFormedSym.ast[bodyPos][1].typ
|
||||
let selfSymbolType = makePtrType(c, origParamType.skipTypes(abstractPtrs))
|
||||
let selfPtr = newNodeI(nkHiddenAddr, transFormedSym.ast[bodyPos][1].info)
|
||||
selfPtr.add transFormedSym.ast[bodyPos][1]
|
||||
selfPtr.typ = selfSymbolType
|
||||
selfPtr.typ() = selfSymbolType
|
||||
transFormedSym.ast[bodyPos][1] = c.semExpr(c, selfPtr)
|
||||
# TODO: suppress var destructor warnings; if newFinalizer is not
|
||||
# TODO: deprecated, try to implement plain T destructor
|
||||
@@ -601,7 +612,7 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
|
||||
of mTypeTrait: result = semTypeTraits(c, n)
|
||||
of mAstToStr:
|
||||
result = newStrNodeT(renderTree(n[1], {renderNoComments}), n, c.graph)
|
||||
result.typ = getSysType(c.graph, n.info, tyString)
|
||||
result.typ() = getSysType(c.graph, n.info, tyString)
|
||||
of mInstantiationInfo: result = semInstantiationInfo(c, n)
|
||||
of mOrd: result = semOrd(c, n)
|
||||
of mOf: result = semOf(c, n)
|
||||
@@ -614,7 +625,7 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
|
||||
result = semDynamicBindSym(c, n)
|
||||
of mProcCall:
|
||||
result = n
|
||||
result.typ = n[1].typ
|
||||
result.typ() = n[1].typ
|
||||
of mDotDot:
|
||||
result = n
|
||||
of mPlugin:
|
||||
@@ -657,7 +668,7 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
|
||||
result[0] = newSymNode(op)
|
||||
if op.typ.len == 3:
|
||||
let boolLit = newIntLit(c.graph, n.info, 1)
|
||||
boolLit.typ = getSysType(c.graph, n.info, tyBool)
|
||||
boolLit.typ() = getSysType(c.graph, n.info, tyBool)
|
||||
result.add boolLit
|
||||
of mWasMoved:
|
||||
result = n
|
||||
@@ -699,7 +710,7 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
|
||||
result = n
|
||||
if result.typ != nil and expectedType != nil and result.typ.kind == tySequence and
|
||||
expectedType.kind == tySequence and result.typ.elementType.kind == tyEmpty:
|
||||
result.typ = expectedType # type inference for empty sequence # bug #21377
|
||||
result.typ() = expectedType # type inference for empty sequence # bug #21377
|
||||
of mEnsureMove:
|
||||
result = n
|
||||
if n[1].kind in {nkStmtListExpr, nkBlockExpr,
|
||||
|
||||
@@ -188,7 +188,7 @@ proc collectOrAddMissingCaseFields(c: PContext, branchNode: PNode,
|
||||
newNodeIT(nkType, constrCtx.initExpr.info, asgnType)
|
||||
)
|
||||
asgnExpr.flags.incl nfSkipFieldChecking
|
||||
asgnExpr.typ = recTyp
|
||||
asgnExpr.typ() = recTyp
|
||||
defaults.add newTree(nkExprColonExpr, newSymNode(sym), asgnExpr)
|
||||
|
||||
proc collectBranchFields(c: PContext, n: PNode, discriminatorVal: PNode,
|
||||
@@ -475,7 +475,7 @@ proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags; expectedType: PType
|
||||
if t.kind == tyRef:
|
||||
t = skipTypes(t.elementType, {tyGenericInst, tyAlias, tySink, tyOwned})
|
||||
if optOwnedRefs in c.config.globalOptions:
|
||||
result.typ = makeVarType(c, result.typ, tyOwned)
|
||||
result.typ() = makeVarType(c, result.typ, tyOwned)
|
||||
# we have to watch out, there are also 'owned proc' types that can be used
|
||||
# multiple times as long as they don't have closures.
|
||||
result.typ.flags.incl tfHasOwned
|
||||
|
||||
@@ -407,9 +407,9 @@ proc transformSlices(g: ModuleGraph; idgen: IdGenerator; n: PNode): PNode =
|
||||
result = copyNode(n)
|
||||
var typ = newType(tyOpenArray, idgen, result.typ.owner)
|
||||
typ.add result.typ.elementType
|
||||
result.typ = typ
|
||||
result.typ() = typ
|
||||
let opSlice = newSymNode(createMagic(g, idgen, "slice", mSlice))
|
||||
opSlice.typ = getSysType(g, n.info, tyInt)
|
||||
opSlice.typ() = getSysType(g, n.info, tyInt)
|
||||
result.add opSlice
|
||||
result.add n[1]
|
||||
let slice = n[2].skipStmtList
|
||||
|
||||
@@ -193,7 +193,7 @@ proc guardDotAccess(a: PEffects; n: PNode) =
|
||||
let dot = newNodeI(nkDotExpr, n.info, 2)
|
||||
dot[0] = n[0]
|
||||
dot[1] = newSymNode(g)
|
||||
dot.typ = g.typ
|
||||
dot.typ() = g.typ
|
||||
for L in a.locked:
|
||||
#if a.guards.sameSubexprs(dot, L): return
|
||||
if guards.sameTree(dot, L): return
|
||||
@@ -411,7 +411,7 @@ proc throws(tracked, n, orig: PNode) =
|
||||
if n.typ == nil or n.typ.kind != tyError:
|
||||
if orig != nil:
|
||||
let x = copyTree(orig)
|
||||
x.typ = n.typ
|
||||
x.typ() = n.typ
|
||||
tracked.add x
|
||||
else:
|
||||
tracked.add n
|
||||
@@ -426,12 +426,12 @@ proc excType(g: ModuleGraph; n: PNode): PType =
|
||||
|
||||
proc createRaise(g: ModuleGraph; n: PNode): PNode =
|
||||
result = newNode(nkType)
|
||||
result.typ = getEbase(g, n.info)
|
||||
result.typ() = getEbase(g, n.info)
|
||||
if not n.isNil: result.info = n.info
|
||||
|
||||
proc createTag(g: ModuleGraph; n: PNode): PNode =
|
||||
result = newNode(nkType)
|
||||
result.typ = g.sysTypeFromName(n.info, "RootEffect")
|
||||
result.typ() = g.sysTypeFromName(n.info, "RootEffect")
|
||||
if not n.isNil: result.info = n.info
|
||||
|
||||
proc addRaiseEffect(a: PEffects, e, comesFrom: PNode) =
|
||||
@@ -1210,7 +1210,7 @@ proc track(tracked: PEffects, n: PNode) =
|
||||
if n.sym.typ != nil and tfHasAsgn in n.sym.typ.flags:
|
||||
tracked.owner.flags.incl sfInjectDestructors
|
||||
# bug #15038: ensure consistency
|
||||
if n.typ == nil or (not hasDestructor(n.typ) and sameType(n.typ, n.sym.typ)): n.typ = n.sym.typ
|
||||
if n.typ == nil or (not hasDestructor(n.typ) and sameType(n.typ, n.sym.typ)): n.typ() = n.sym.typ
|
||||
of nkHiddenAddr, nkAddr:
|
||||
if n[0].kind == nkSym and isLocalSym(tracked, n[0].sym) and
|
||||
n.typ.kind notin {tyVar, tyLent}:
|
||||
|
||||
@@ -112,11 +112,11 @@ proc semWhile(c: PContext, n: PNode; flags: TExprFlags): PNode =
|
||||
dec(c.p.nestedLoopCounter)
|
||||
closeScope(c)
|
||||
if n[1].typ == c.enforceVoidContext:
|
||||
result.typ = c.enforceVoidContext
|
||||
result.typ() = c.enforceVoidContext
|
||||
elif efInTypeof in flags:
|
||||
result.typ = n[1].typ
|
||||
result.typ() = n[1].typ
|
||||
elif implicitlyDiscardable(n[1]):
|
||||
result[1].typ = c.enforceVoidContext
|
||||
result[1].typ() = c.enforceVoidContext
|
||||
|
||||
proc semProc(c: PContext, n: PNode): PNode
|
||||
|
||||
@@ -275,7 +275,7 @@ proc fixNilType(c: PContext; n: PNode) =
|
||||
elif n.kind in {nkStmtList, nkStmtListExpr}:
|
||||
n.transitionSonsKind(nkStmtList)
|
||||
for it in n: fixNilType(c, it)
|
||||
n.typ = nil
|
||||
n.typ() = nil
|
||||
|
||||
proc discardCheck(c: PContext, result: PNode, flags: TExprFlags) =
|
||||
if c.matchedConcept != nil or efInTypeof in flags: return
|
||||
@@ -331,14 +331,14 @@ proc semIf(c: PContext, n: PNode; flags: TExprFlags; expectedType: PType = nil):
|
||||
for it in n: discardCheck(c, it.lastSon, flags)
|
||||
result.transitionSonsKind(nkIfStmt)
|
||||
# propagate any enforced VoidContext:
|
||||
if typ == c.enforceVoidContext: result.typ = c.enforceVoidContext
|
||||
if typ == c.enforceVoidContext: result.typ() = c.enforceVoidContext
|
||||
else:
|
||||
for it in n:
|
||||
let j = it.len-1
|
||||
if not endsInNoReturn(it[j]):
|
||||
it[j] = fitNode(c, typ, it[j], it[j].info)
|
||||
result.transitionSonsKind(nkIfExpr)
|
||||
result.typ = typ
|
||||
result.typ() = typ
|
||||
|
||||
proc semTry(c: PContext, n: PNode; flags: TExprFlags; expectedType: PType = nil): PNode =
|
||||
var check = initIntSet()
|
||||
@@ -438,7 +438,7 @@ proc semTry(c: PContext, n: PNode; flags: TExprFlags; expectedType: PType = nil)
|
||||
discardCheck(c, n[0], flags)
|
||||
for i in 1..<n.len: discardCheck(c, n[i].lastSon, flags)
|
||||
if typ == c.enforceVoidContext:
|
||||
result.typ = c.enforceVoidContext
|
||||
result.typ() = c.enforceVoidContext
|
||||
else:
|
||||
if n.lastSon.kind == nkFinally: discardCheck(c, n.lastSon.lastSon, flags)
|
||||
if not endsInNoReturn(n[0]):
|
||||
@@ -448,7 +448,7 @@ proc semTry(c: PContext, n: PNode; flags: TExprFlags; expectedType: PType = nil)
|
||||
let j = it.len-1
|
||||
if not endsInNoReturn(it[j]):
|
||||
it[j] = fitNode(c, typ, it[j], it[j].info)
|
||||
result.typ = typ
|
||||
result.typ() = typ
|
||||
|
||||
proc fitRemoveHiddenConv(c: PContext, typ: PType, n: PNode): PNode =
|
||||
result = fitNode(c, typ, n, n.info)
|
||||
@@ -457,7 +457,7 @@ proc fitRemoveHiddenConv(c: PContext, typ: PType, n: PNode): PNode =
|
||||
if r1.kind in {nkCharLit..nkUInt64Lit} and typ.skipTypes(abstractRange).kind in {tyFloat..tyFloat128}:
|
||||
result = newFloatNode(nkFloatLit, BiggestFloat r1.intVal)
|
||||
result.info = n.info
|
||||
result.typ = typ
|
||||
result.typ() = typ
|
||||
if not floatRangeCheck(result.floatVal, typ):
|
||||
localError(c.config, n.info, errFloatToString % [$result.floatVal, typeToString(typ)])
|
||||
elif r1.kind == nkSym and typ.skipTypes(abstractRange).kind == tyCstring:
|
||||
@@ -605,7 +605,7 @@ proc fillPartialObject(c: PContext; n: PNode; typ: PType) =
|
||||
obj.n.add newSymNode(field)
|
||||
n[0] = makeDeref x
|
||||
n[1] = newSymNode(field)
|
||||
n.typ = field.typ
|
||||
n.typ() = field.typ
|
||||
else:
|
||||
localError(c.config, n.info, "implicit object field construction " &
|
||||
"requires a .partial object, but got " & typeToString(obj))
|
||||
@@ -908,7 +908,7 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
|
||||
if sfGenSym notin v.flags:
|
||||
if not isDiscardUnderscore(v): addInterfaceDecl(c, v)
|
||||
else:
|
||||
if v.owner == nil: v.owner = c.p.owner
|
||||
if v.owner == nil: setOwner(v, c.p.owner)
|
||||
when oKeepVariableNames:
|
||||
if c.inUnrolledContext > 0: v.flags.incl(sfShadowed)
|
||||
else:
|
||||
@@ -1026,7 +1026,7 @@ proc semConst(c: PContext, n: PNode): PNode =
|
||||
when defined(nimsuggest):
|
||||
v.hasUserSpecifiedType = hasUserSpecifiedType
|
||||
if sfGenSym notin v.flags: addInterfaceDecl(c, v)
|
||||
elif v.owner == nil: v.owner = getCurrOwner(c)
|
||||
elif v.owner == nil: setOwner(v, getCurrOwner(c))
|
||||
styleCheckDef(c, v)
|
||||
onDef(a[j].info, v)
|
||||
|
||||
@@ -1097,7 +1097,7 @@ proc semForVars(c: PContext, n: PNode; flags: TExprFlags): PNode =
|
||||
v.typ = iter[i]
|
||||
n[0][i] = newSymNode(v)
|
||||
if sfGenSym notin v.flags and not isDiscardUnderscore(v): addDecl(c, v)
|
||||
elif v.owner == nil: v.owner = getCurrOwner(c)
|
||||
elif v.owner == nil: setOwner(v, getCurrOwner(c))
|
||||
else:
|
||||
var v = symForVar(c, n[0])
|
||||
if getCurrOwner(c).kind == skModule: incl(v.flags, sfGlobal)
|
||||
@@ -1107,7 +1107,7 @@ proc semForVars(c: PContext, n: PNode; flags: TExprFlags): PNode =
|
||||
v.typ = iterBase
|
||||
n[0] = newSymNode(v)
|
||||
if sfGenSym notin v.flags and not isDiscardUnderscore(v): addDecl(c, v)
|
||||
elif v.owner == nil: v.owner = getCurrOwner(c)
|
||||
elif v.owner == nil: setOwner(v, getCurrOwner(c))
|
||||
else:
|
||||
localError(c.config, n.info, errWrongNumberOfVariables)
|
||||
elif n.len-2 != iterAfterVarLent.len:
|
||||
@@ -1141,7 +1141,7 @@ proc semForVars(c: PContext, n: PNode; flags: TExprFlags): PNode =
|
||||
v.typ = iter[i][j]
|
||||
n[i][j] = newSymNode(v)
|
||||
if not isDiscardUnderscore(v): addDecl(c, v)
|
||||
elif v.owner == nil: v.owner = getCurrOwner(c)
|
||||
elif v.owner == nil: setOwner(v, getCurrOwner(c))
|
||||
else:
|
||||
var v = symForVar(c, n[i])
|
||||
if getCurrOwner(c).kind == skModule: incl(v.flags, sfGlobal)
|
||||
@@ -1156,7 +1156,7 @@ proc semForVars(c: PContext, n: PNode; flags: TExprFlags): PNode =
|
||||
n[i] = newSymNode(v)
|
||||
if sfGenSym notin v.flags:
|
||||
if not isDiscardUnderscore(v): addDecl(c, v)
|
||||
elif v.owner == nil: v.owner = getCurrOwner(c)
|
||||
elif v.owner == nil: setOwner(v, getCurrOwner(c))
|
||||
inc(c.p.nestedLoopCounter)
|
||||
let oldBreakInLoop = c.p.breakInLoop
|
||||
c.p.breakInLoop = true
|
||||
@@ -1291,9 +1291,9 @@ proc semFor(c: PContext, n: PNode; flags: TExprFlags): PNode =
|
||||
result = semForVars(c, n, flags)
|
||||
# propagate any enforced VoidContext:
|
||||
if n[^1].typ == c.enforceVoidContext:
|
||||
result.typ = c.enforceVoidContext
|
||||
result.typ() = c.enforceVoidContext
|
||||
elif efInTypeof in flags:
|
||||
result.typ = result.lastSon.typ
|
||||
result.typ() = result.lastSon.typ
|
||||
closeScope(c)
|
||||
|
||||
proc semCase(c: PContext, n: PNode; flags: TExprFlags; expectedType: PType = nil): PNode =
|
||||
@@ -1373,14 +1373,14 @@ proc semCase(c: PContext, n: PNode; flags: TExprFlags; expectedType: PType = nil
|
||||
for i in 1..<n.len: discardCheck(c, n[i].lastSon, flags)
|
||||
# propagate any enforced VoidContext:
|
||||
if typ == c.enforceVoidContext:
|
||||
result.typ = c.enforceVoidContext
|
||||
result.typ() = c.enforceVoidContext
|
||||
else:
|
||||
for i in 1..<n.len:
|
||||
var it = n[i]
|
||||
let j = it.len-1
|
||||
if not endsInNoReturn(it[j]):
|
||||
it[j] = fitNode(c, typ, it[j], it[j].info)
|
||||
result.typ = typ
|
||||
result.typ() = typ
|
||||
|
||||
proc semRaise(c: PContext, n: PNode): PNode =
|
||||
result = n
|
||||
@@ -1475,7 +1475,7 @@ proc typeDefLeftSidePass(c: PContext, typeSection: PNode, i: int) =
|
||||
s = typsym
|
||||
# add it here, so that recursive types are possible:
|
||||
if sfGenSym notin s.flags: addInterfaceDecl(c, s)
|
||||
elif s.owner == nil: s.owner = getCurrOwner(c)
|
||||
elif s.owner == nil: setOwner(s, getCurrOwner(c))
|
||||
|
||||
if name.kind == nkPragmaExpr:
|
||||
if name[0].kind == nkPostfix:
|
||||
@@ -1975,7 +1975,7 @@ proc semInferredLambda(c: PContext, pt: LayeredIdTable, n: PNode): PNode =
|
||||
let original = n[namePos].sym
|
||||
let s = original #copySym(original, false)
|
||||
#incl(s.flags, sfFromGeneric)
|
||||
#s.owner = original
|
||||
#s.owner() = original
|
||||
|
||||
n = replaceTypesInBody(c, pt, n, original)
|
||||
result = n
|
||||
@@ -1990,7 +1990,7 @@ proc semInferredLambda(c: PContext, pt: LayeredIdTable, n: PNode): PNode =
|
||||
tyFromExpr}+tyTypeClasses:
|
||||
localError(c.config, params[i].info, "cannot infer type of parameter: " &
|
||||
params[i].sym.name.s)
|
||||
#params[i].sym.owner = s
|
||||
#params[i].sym.owner() = s
|
||||
openScope(c)
|
||||
pushOwner(c, s)
|
||||
addParams(c, params, skProc)
|
||||
@@ -2002,7 +2002,7 @@ proc semInferredLambda(c: PContext, pt: LayeredIdTable, n: PNode): PNode =
|
||||
popOwner(c)
|
||||
closeScope(c)
|
||||
if optOwnedRefs in c.config.globalOptions and result.typ != nil:
|
||||
result.typ = makeVarType(c, result.typ, tyOwned)
|
||||
result.typ() = makeVarType(c, result.typ, tyOwned)
|
||||
# alternative variant (not quite working):
|
||||
# var prc = arg[0].sym
|
||||
# let inferred = c.semGenerateInstance(c, prc, m.bindings, arg.info)
|
||||
@@ -2362,7 +2362,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||
n[namePos] = newSymNode(s)
|
||||
of nkSym:
|
||||
s = n[namePos].sym
|
||||
s.owner = c.getCurrOwner
|
||||
setOwner(s, c.getCurrOwner)
|
||||
else:
|
||||
# Highlighting needs to be done early so the position for
|
||||
# name isn't changed (see taccent_highlight). We don't want to check if this is the
|
||||
@@ -2608,9 +2608,9 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||
c.patterns.add(s)
|
||||
if isAnon:
|
||||
n.transitionSonsKind(nkLambda)
|
||||
result.typ = s.typ
|
||||
result.typ() = s.typ
|
||||
if optOwnedRefs in c.config.globalOptions:
|
||||
result.typ = makeVarType(c, result.typ, tyOwned)
|
||||
result.typ() = makeVarType(c, result.typ, tyOwned)
|
||||
elif isTopLevel(c) and s.kind != skIterator and s.typ.callConv == ccClosure:
|
||||
localError(c.config, s.info, "'.closure' calling convention for top level routines is invalid")
|
||||
|
||||
@@ -2629,7 +2629,7 @@ proc semIterator(c: PContext, n: PNode): PNode =
|
||||
# gensym'ed iterator?
|
||||
if n[namePos].kind == nkSym:
|
||||
# gensym'ed iterators might need to become closure iterators:
|
||||
n[namePos].sym.owner = getCurrOwner(c)
|
||||
setOwner(n[namePos].sym, getCurrOwner(c))
|
||||
n[namePos].sym.transitionRoutineSymKind(skIterator)
|
||||
result = semProcAux(c, n, skIterator, iteratorPragmas)
|
||||
# bug #7093: if after a macro transformation we don't have an
|
||||
@@ -2650,7 +2650,7 @@ proc semIterator(c: PContext, n: PNode): PNode =
|
||||
if n[bodyPos].kind == nkEmpty and s.magic == mNone and c.inConceptDecl == 0:
|
||||
localError(c.config, n.info, errImplOfXexpected % s.name.s)
|
||||
if optOwnedRefs in c.config.globalOptions and result.typ != nil:
|
||||
result.typ = makeVarType(c, result.typ, tyOwned)
|
||||
result.typ() = makeVarType(c, result.typ, tyOwned)
|
||||
result.typ.callConv = ccClosure
|
||||
|
||||
proc semProc(c: PContext, n: PNode): PNode =
|
||||
@@ -2781,7 +2781,7 @@ proc semPragmaBlock(c: PContext, n: PNode; expectedType: PType = nil): PNode =
|
||||
n[1] = semExpr(c, n[1], expectedType = expectedType)
|
||||
dec c.inUncheckedAssignSection, inUncheckedAssignSection
|
||||
result = n
|
||||
result.typ = n[1].typ
|
||||
result.typ() = n[1].typ
|
||||
for i in 0..<pragmaList.len:
|
||||
case whichPragma(pragmaList[i])
|
||||
of wLine: setInfoRecursive(result, pragmaList[i].info)
|
||||
@@ -2866,14 +2866,14 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags, expectedType: PType =
|
||||
else: discard
|
||||
if n[i].typ == c.enforceVoidContext: #or usesResult(n[i]):
|
||||
voidContext = true
|
||||
n.typ = c.enforceVoidContext
|
||||
n.typ() = c.enforceVoidContext
|
||||
if i == last and (n.len == 1 or ({efWantValue, efInTypeof} * flags != {})):
|
||||
n.typ = n[i].typ
|
||||
n.typ() = n[i].typ
|
||||
if not isEmptyType(n.typ): n.transitionSonsKind(nkStmtListExpr)
|
||||
elif i != last or voidContext:
|
||||
discardCheck(c, n[i], flags)
|
||||
else:
|
||||
n.typ = n[i].typ
|
||||
n.typ() = n[i].typ
|
||||
if not isEmptyType(n.typ): n.transitionSonsKind(nkStmtListExpr)
|
||||
var m = n[i]
|
||||
while m.kind in {nkStmtListExpr, nkStmtList} and m.len > 0: # from templates
|
||||
|
||||
@@ -237,10 +237,10 @@ proc semTemplSymbol(c: var TemplCtx, n: PNode, s: PSym; isField, isAmbiguous: bo
|
||||
if result.kind == nkSym:
|
||||
result = newOpenSym(result)
|
||||
else:
|
||||
result.typ = nil
|
||||
result.typ() = nil
|
||||
else:
|
||||
result.flags.incl nfDisabledOpenSym
|
||||
result.typ = nil
|
||||
result.typ() = nil
|
||||
of skGenericParam:
|
||||
if isField and sfGenSym in s.flags: result = n
|
||||
else:
|
||||
@@ -250,7 +250,7 @@ proc semTemplSymbol(c: var TemplCtx, n: PNode, s: PSym; isField, isAmbiguous: bo
|
||||
result = newOpenSym(result)
|
||||
else:
|
||||
result.flags.incl nfDisabledOpenSym
|
||||
result.typ = nil
|
||||
result.typ() = nil
|
||||
of skParam:
|
||||
result = n
|
||||
of skType:
|
||||
@@ -268,10 +268,10 @@ proc semTemplSymbol(c: var TemplCtx, n: PNode, s: PSym; isField, isAmbiguous: bo
|
||||
if result.kind == nkSym:
|
||||
result = newOpenSym(result)
|
||||
else:
|
||||
result.typ = nil
|
||||
result.typ() = nil
|
||||
else:
|
||||
result.flags.incl nfDisabledOpenSym
|
||||
result.typ = nil
|
||||
result.typ() = nil
|
||||
else:
|
||||
if isField and sfGenSym in s.flags: result = n
|
||||
else:
|
||||
@@ -281,7 +281,7 @@ proc semTemplSymbol(c: var TemplCtx, n: PNode, s: PSym; isField, isAmbiguous: bo
|
||||
result = newOpenSym(result)
|
||||
else:
|
||||
result.flags.incl nfDisabledOpenSym
|
||||
result.typ = nil
|
||||
result.typ() = nil
|
||||
# Issue #12832
|
||||
when defined(nimsuggest):
|
||||
suggestSym(c.c.graph, n.info, s, c.c.graph.usageSym, false)
|
||||
|
||||
@@ -480,7 +480,7 @@ proc firstRange(config: ConfigRef, t: PType): PNode =
|
||||
result = newFloatNode(nkFloatLit, firstFloat(t))
|
||||
else:
|
||||
result = newIntNode(nkIntLit, firstOrd(config, t))
|
||||
result.typ = t
|
||||
result.typ() = t
|
||||
|
||||
proc semTuple(c: PContext, n: PNode, prev: PType): PType =
|
||||
var typ: PType
|
||||
@@ -1096,7 +1096,7 @@ proc addParamOrResult(c: PContext, param: PSym, kind: TSymKind) =
|
||||
if sfGenSym in param.flags:
|
||||
# bug #XXX, fix the gensym'ed parameters owner:
|
||||
if param.owner == nil:
|
||||
param.owner = getCurrOwner(c)
|
||||
setOwner(param, getCurrOwner(c))
|
||||
else: addDecl(c, param)
|
||||
|
||||
template shouldHaveMeta(t) =
|
||||
@@ -1381,7 +1381,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
|
||||
elif hasUnresolvedArgs(c, def):
|
||||
# template default value depends on other parameter
|
||||
# don't do any typechecking
|
||||
def.typ = makeTypeFromExpr(c, def.copyTree)
|
||||
def.typ() = makeTypeFromExpr(c, def.copyTree)
|
||||
break determineType
|
||||
elif typ != nil and typ.kind == tyTyped:
|
||||
canBeVoid = true
|
||||
@@ -1519,7 +1519,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
|
||||
# XXX This rather hacky way keeps 'tflatmap' compiling:
|
||||
if tfHasMeta notin oldFlags:
|
||||
result.flags.excl tfHasMeta
|
||||
result.n.typ = r
|
||||
result.n.typ() = r
|
||||
|
||||
if isCurrentlyGeneric():
|
||||
for n in genericParams:
|
||||
@@ -1536,8 +1536,8 @@ proc semStmtListType(c: PContext, n: PNode, prev: PType): PType =
|
||||
n[i] = semStmt(c, n[i], {})
|
||||
if n.len > 0:
|
||||
result = semTypeNode(c, n[^1], prev)
|
||||
n.typ = result
|
||||
n[^1].typ = result
|
||||
n.typ() = result
|
||||
n[^1].typ() = result
|
||||
else:
|
||||
result = nil
|
||||
|
||||
@@ -1550,15 +1550,15 @@ proc semBlockType(c: PContext, n: PNode, prev: PType): PType =
|
||||
if n[0].kind notin {nkEmpty, nkSym}:
|
||||
addDecl(c, newSymS(skLabel, n[0], c))
|
||||
result = semStmtListType(c, n[1], prev)
|
||||
n[1].typ = result
|
||||
n.typ = result
|
||||
n[1].typ() = result
|
||||
n.typ() = result
|
||||
closeScope(c)
|
||||
c.p.breakInLoop = oldBreakInLoop
|
||||
dec(c.p.nestedBlockCounter)
|
||||
|
||||
proc semGenericParamInInvocation(c: PContext, n: PNode): PType =
|
||||
result = semTypeNode(c, n, nil)
|
||||
n.typ = makeTypeDesc(c, result)
|
||||
n.typ() = makeTypeDesc(c, result)
|
||||
|
||||
proc trySemObjectTypeForInheritedGenericInst(c: PContext, n: PNode, t: PType): bool =
|
||||
var
|
||||
@@ -1970,7 +1970,7 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
|
||||
n.transitionNoneToSym()
|
||||
n.sym = result
|
||||
n.info = oldInfo
|
||||
n.typ = result.typ
|
||||
n.typ() = result.typ
|
||||
else:
|
||||
localError(c.config, n.info, "identifier expected")
|
||||
result = errorSym(c, n)
|
||||
@@ -2269,7 +2269,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||
when false:
|
||||
localError(c.config, n.info, "type expected, but got: " & renderTree(n))
|
||||
result = newOrPrevType(tyError, prev, c)
|
||||
n.typ = result
|
||||
n.typ() = result
|
||||
dec c.inTypeContext
|
||||
|
||||
proc setMagicType(conf: ConfigRef; m: PSym, kind: TTypeKind, size: int) =
|
||||
@@ -2416,7 +2416,7 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
|
||||
else:
|
||||
# the following line fixes ``TV2*[T:SomeNumber=TR] = array[0..1, T]``
|
||||
# from manyloc/named_argument_bug/triengine:
|
||||
def.typ = def.typ.skipTypes({tyTypeDesc})
|
||||
def.typ() = def.typ.skipTypes({tyTypeDesc})
|
||||
if not containsGenericType(def.typ):
|
||||
def = fitNode(c, typ, def, def.info)
|
||||
|
||||
|
||||
@@ -110,7 +110,7 @@ proc prepareNode*(cl: var TReplTypeVars, n: PNode): PNode =
|
||||
return if tfUnresolved in t.flags: prepareNode(cl, t.n)
|
||||
else: t.n
|
||||
result = copyNode(n)
|
||||
result.typ = t
|
||||
result.typ() = t
|
||||
if result.kind == nkSym:
|
||||
result.sym =
|
||||
if n.typ != nil and n.typ == n.sym.typ:
|
||||
@@ -264,7 +264,7 @@ proc replaceTypeVarsN(cl: var TReplTypeVars, n: PNode; start=0; expectedType: PT
|
||||
if n.typ.kind == tyFromExpr:
|
||||
# type of node should not be evaluated as a static value
|
||||
n.typ.flags.incl tfNonConstExpr
|
||||
result.typ = replaceTypeVarsT(cl, n.typ)
|
||||
result.typ() = replaceTypeVarsT(cl, n.typ)
|
||||
checkMetaInvariants(cl, result.typ)
|
||||
case n.kind
|
||||
of nkNone..pred(nkSym), succ(nkSym)..nkNilLit:
|
||||
@@ -358,7 +358,7 @@ proc replaceTypeVarsS(cl: var TReplTypeVars, s: PSym, t: PType): PSym =
|
||||
result = copySym(s, cl.c.idgen)
|
||||
incl(result.flags, sfFromGeneric)
|
||||
#idTablePut(cl.symMap, s, result)
|
||||
result.owner = s.owner
|
||||
setOwner(result, s.owner)
|
||||
result.typ = t
|
||||
if result.kind != skType:
|
||||
result.ast = replaceTypeVarsN(cl, s.ast)
|
||||
@@ -696,7 +696,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
|
||||
if not cl.allowMetaTypes and result.n != nil and
|
||||
result.base.kind != tyNone:
|
||||
result.n = cl.c.semConstExpr(cl.c, result.n)
|
||||
result.n.typ = result.base
|
||||
result.n.typ() = result.base
|
||||
|
||||
of tyGenericInst, tyUserTypeClassInst:
|
||||
bailout()
|
||||
|
||||
@@ -200,6 +200,9 @@ proc matchGenericParams*(m: var TCandidate, binding: PNode, callee: PSym) =
|
||||
elif tfImplicitTypeParam in paramSym.typ.flags:
|
||||
# not a mismatch, but can't create sym
|
||||
m.state = csEmpty
|
||||
m.firstMismatch.kind = kMissingGenericParam
|
||||
m.firstMismatch.arg = i + 1
|
||||
m.firstMismatch.formal = paramSym
|
||||
return
|
||||
else:
|
||||
m.state = csNoMatch
|
||||
@@ -444,11 +447,11 @@ template describeArgImpl(c: PContext, n: PNode, i: int, startIdx = 1; prefer = p
|
||||
arg = c.semTryExpr(c, n[i][1])
|
||||
if arg == nil:
|
||||
arg = n[i][1]
|
||||
arg.typ = newTypeS(tyUntyped, c)
|
||||
arg.typ() = newTypeS(tyUntyped, c)
|
||||
else:
|
||||
if arg.typ == nil:
|
||||
arg.typ = newTypeS(tyVoid, c)
|
||||
n[i].typ = arg.typ
|
||||
arg.typ() = newTypeS(tyVoid, c)
|
||||
n[i].typ() = arg.typ
|
||||
n[i][1] = arg
|
||||
else:
|
||||
if arg.typ.isNil and arg.kind notin {nkStmtList, nkDo, nkElse,
|
||||
@@ -457,10 +460,10 @@ template describeArgImpl(c: PContext, n: PNode, i: int, startIdx = 1; prefer = p
|
||||
arg = c.semTryExpr(c, n[i])
|
||||
if arg == nil:
|
||||
arg = n[i]
|
||||
arg.typ = newTypeS(tyUntyped, c)
|
||||
arg.typ() = newTypeS(tyUntyped, c)
|
||||
else:
|
||||
if arg.typ == nil:
|
||||
arg.typ = newTypeS(tyVoid, c)
|
||||
arg.typ() = newTypeS(tyVoid, c)
|
||||
n[i] = arg
|
||||
if arg.typ != nil and arg.typ.kind == tyError: return
|
||||
result.add argTypeToString(arg, prefer)
|
||||
@@ -2167,16 +2170,16 @@ proc implicitConv(kind: TNodeKind, f: PType, arg: PNode, m: TCandidate,
|
||||
result = newNodeI(kind, arg.info)
|
||||
if containsGenericType(f):
|
||||
if not m.matchedErrorType:
|
||||
result.typ = getInstantiatedType(c, arg, m, f).skipTypes({tySink})
|
||||
result.typ() = getInstantiatedType(c, arg, m, f).skipTypes({tySink})
|
||||
else:
|
||||
result.typ = errorType(c)
|
||||
result.typ() = errorType(c)
|
||||
else:
|
||||
result.typ = f.skipTypes({tySink})
|
||||
result.typ() = f.skipTypes({tySink})
|
||||
# keep varness
|
||||
if arg.typ != nil and arg.typ.kind == tyVar:
|
||||
result.typ = toVar(result.typ, tyVar, c.idgen)
|
||||
result.typ() = toVar(result.typ, tyVar, c.idgen)
|
||||
else:
|
||||
result.typ = result.typ.skipTypes({tyVar})
|
||||
result.typ() = result.typ.skipTypes({tyVar})
|
||||
|
||||
if result.typ == nil: internalError(c.graph.config, arg.info, "implicitConv")
|
||||
result.add c.graph.emptyNode
|
||||
@@ -2204,13 +2207,13 @@ proc convertLiteral(kind: TNodeKind, c: PContext, m: TCandidate; n: PNode, newTy
|
||||
result.add x
|
||||
else:
|
||||
result.addConsiderNil convertLiteral(kind, c, m, n[i], elemType(newType))
|
||||
result.typ = newType
|
||||
result.typ() = newType
|
||||
return
|
||||
of nkBracket:
|
||||
result = copyNode(n)
|
||||
for i in 0..<n.len:
|
||||
result.addConsiderNil convertLiteral(kind, c, m, n[i], elemType(newType))
|
||||
result.typ = newType
|
||||
result.typ() = newType
|
||||
return
|
||||
of nkPar, nkTupleConstr:
|
||||
let tup = newType.skipTypes({tyGenericInst, tyAlias, tySink, tyDistinct})
|
||||
@@ -2234,7 +2237,7 @@ proc convertLiteral(kind: TNodeKind, c: PContext, m: TCandidate; n: PNode, newTy
|
||||
else:
|
||||
for i in 0..<n.len:
|
||||
result.addConsiderNil convertLiteral(kind, c, m, n[i], tup[i])
|
||||
result.typ = newType
|
||||
result.typ() = newType
|
||||
return
|
||||
of nkCharLit..nkUInt64Lit:
|
||||
if n.kind != nkUInt64Lit and not sameTypeOrNil(n.typ, newType) and isOrdinalType(newType):
|
||||
@@ -2242,14 +2245,14 @@ proc convertLiteral(kind: TNodeKind, c: PContext, m: TCandidate; n: PNode, newTy
|
||||
if value < firstOrd(c.config, newType) or value > lastOrd(c.config, newType):
|
||||
return nil
|
||||
result = copyNode(n)
|
||||
result.typ = newType
|
||||
result.typ() = newType
|
||||
return
|
||||
of nkFloatLit..nkFloat64Lit:
|
||||
if newType.skipTypes(abstractVarRange-{tyTypeDesc}).kind == tyFloat:
|
||||
if not floatRangeCheck(n.floatVal, newType):
|
||||
return nil
|
||||
result = copyNode(n)
|
||||
result.typ = newType
|
||||
result.typ() = newType
|
||||
return
|
||||
of nkSym:
|
||||
if n.sym.kind == skEnumField and not sameTypeOrNil(n.sym.typ, newType) and isOrdinalType(newType):
|
||||
@@ -2257,7 +2260,7 @@ proc convertLiteral(kind: TNodeKind, c: PContext, m: TCandidate; n: PNode, newTy
|
||||
if value < firstOrd(c.config, newType) or value > lastOrd(c.config, newType):
|
||||
return nil
|
||||
result = copyNode(n)
|
||||
result.typ = newType
|
||||
result.typ() = newType
|
||||
return
|
||||
else: discard
|
||||
return implicitConv(kind, newType, n, m, c)
|
||||
@@ -2303,7 +2306,7 @@ proc userConvMatch(c: PContext, m: var TCandidate, f, a: PType,
|
||||
incl(c.converters[i].flags, sfUsed)
|
||||
markOwnerModuleAsUsed(c, c.converters[i])
|
||||
var s = newSymNode(c.converters[i])
|
||||
s.typ = c.converters[i].typ
|
||||
s.typ() = c.converters[i].typ
|
||||
s.info = arg.info
|
||||
result = newNodeIT(nkHiddenCallConv, arg.info, dest)
|
||||
result.add s
|
||||
@@ -2356,7 +2359,7 @@ proc localConvMatch(c: PContext, m: var TCandidate, f, a: PType,
|
||||
if result.kind == nkCall: result.transitionSonsKind(nkHiddenCallConv)
|
||||
inc(m.convMatches)
|
||||
if r == isGeneric:
|
||||
result.typ = getInstantiatedType(c, arg, m, base(f))
|
||||
result.typ() = getInstantiatedType(c, arg, m, base(f))
|
||||
m.baseTypeMatch = true
|
||||
|
||||
proc incMatches(m: var TCandidate; r: TTypeRelation; convMatch = 1) =
|
||||
@@ -2412,7 +2415,7 @@ proc paramTypesMatchAux(m: var TCandidate, f, a: PType,
|
||||
let typ = newTypeS(tyStatic, c, son = evaluated.typ)
|
||||
typ.n = evaluated
|
||||
arg = copyTree(arg) # fix #12864
|
||||
arg.typ = typ
|
||||
arg.typ() = typ
|
||||
a = typ
|
||||
else:
|
||||
if m.callee.kind == tyGenericBody:
|
||||
@@ -2531,7 +2534,7 @@ proc paramTypesMatchAux(m: var TCandidate, f, a: PType,
|
||||
# doesn't work: `proc foo[T](): array[T, int] = ...; foo[3]()` (see #23204)
|
||||
(arg.typ.isIntLit and not m.isNoCall):
|
||||
result = arg.copyTree
|
||||
result.typ = getInstantiatedType(c, arg, m, f).skipTypes({tySink})
|
||||
result.typ() = getInstantiatedType(c, arg, m, f).skipTypes({tySink})
|
||||
else:
|
||||
result = arg
|
||||
of isBothMetaConvertible:
|
||||
@@ -2587,7 +2590,7 @@ proc paramTypesMatchAux(m: var TCandidate, f, a: PType,
|
||||
of isGeneric:
|
||||
inc(m.convMatches)
|
||||
result = copyTree(arg)
|
||||
result.typ = getInstantiatedType(c, arg, m, base(f))
|
||||
result.typ() = getInstantiatedType(c, arg, m, base(f))
|
||||
m.baseTypeMatch = true
|
||||
of isFromIntLit:
|
||||
inc(m.intConvMatches, 256)
|
||||
@@ -2613,7 +2616,7 @@ proc staticAwareTypeRel(m: var TCandidate, f: PType, arg: var PNode): TTypeRelat
|
||||
# The ast of the type does not point to the symbol.
|
||||
# Without this we will never resolve a `static proc` with overloads
|
||||
let copiedNode = copyNode(arg)
|
||||
copiedNode.typ = exactReplica(copiedNode.typ)
|
||||
copiedNode.typ() = exactReplica(copiedNode.typ)
|
||||
copiedNode.typ.n = arg
|
||||
arg = copiedNode
|
||||
typeRel(m, f, arg.typ)
|
||||
@@ -2878,7 +2881,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode, m: var TCandidate, marker: var Int
|
||||
m.baseTypeMatch = false
|
||||
m.typedescMatched = false
|
||||
n[a][1] = prepareOperand(c, formal.typ, n[a][1])
|
||||
n[a].typ = n[a][1].typ
|
||||
n[a].typ() = n[a][1].typ
|
||||
arg = paramTypesMatch(m, formal.typ, n[a].typ,
|
||||
n[a][1], n[a][1])
|
||||
m.firstMismatch.kind = kTypeMismatch
|
||||
@@ -3052,7 +3055,7 @@ proc matches*(c: PContext, n, nOrig: PNode, m: var TCandidate) =
|
||||
if m.calleeSym != nil: m.calleeSym.detailedInfo else: "")
|
||||
typeMismatch(c.config, formal.ast.info, formal.typ, formal.ast.typ, formal.ast)
|
||||
popInfoContext(c.config)
|
||||
formal.ast.typ = errorType(c)
|
||||
formal.ast.typ() = errorType(c)
|
||||
if nfDefaultRefsParam in formal.ast.flags:
|
||||
m.call.flags.incl nfDefaultRefsParam
|
||||
var defaultValue = copyTree(formal.ast)
|
||||
|
||||
@@ -477,7 +477,7 @@ template foldSizeOf*(conf: ConfigRef; n: PNode; fallback: PNode): PNode =
|
||||
if size >= 0:
|
||||
let res = newIntNode(nkIntLit, size)
|
||||
res.info = node.info
|
||||
res.typ = node.typ
|
||||
res.typ() = node.typ
|
||||
res
|
||||
else:
|
||||
fallback
|
||||
@@ -491,7 +491,7 @@ template foldAlignOf*(conf: ConfigRef; n: PNode; fallback: PNode): PNode =
|
||||
if align >= 0:
|
||||
let res = newIntNode(nkIntLit, align)
|
||||
res.info = node.info
|
||||
res.typ = node.typ
|
||||
res.typ() = node.typ
|
||||
res
|
||||
else:
|
||||
fallback
|
||||
@@ -519,7 +519,7 @@ template foldOffsetOf*(conf: ConfigRef; n: PNode; fallback: PNode): PNode =
|
||||
if offset >= 0:
|
||||
let tmp = newIntNode(nkIntLit, offset)
|
||||
tmp.info = node.info
|
||||
tmp.typ = node.typ
|
||||
tmp.typ() = node.typ
|
||||
tmp
|
||||
else:
|
||||
fallback
|
||||
|
||||
@@ -16,7 +16,7 @@ from trees import getMagic, getRoot
|
||||
proc callProc(a: PNode): PNode =
|
||||
result = newNodeI(nkCall, a.info)
|
||||
result.add a
|
||||
result.typ = a.typ.returnType
|
||||
result.typ() = a.typ.returnType
|
||||
|
||||
# we have 4 cases to consider:
|
||||
# - a void proc --> nothing to do
|
||||
@@ -117,7 +117,7 @@ proc castToVoidPointer(g: ModuleGraph, n: PNode, fvField: PNode): PNode =
|
||||
result = newNodeI(nkCast, fvField.info)
|
||||
result.add newNodeI(nkEmpty, fvField.info)
|
||||
result.add fvField
|
||||
result.typ = ptrType
|
||||
result.typ() = ptrType
|
||||
|
||||
proc createWrapperProc(g: ModuleGraph; f: PNode; threadParam, argsParam: PSym;
|
||||
varSection, varInit, call, barrier, fv: PNode;
|
||||
@@ -200,7 +200,7 @@ 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, idgen, objType.owner)
|
||||
result.typ() = newType(tyPtr, idgen, objType.owner)
|
||||
result.typ.rawAddSon(objType)
|
||||
|
||||
template checkMagicProcs(g: ModuleGraph, n: PNode, formal: PNode) =
|
||||
@@ -266,9 +266,9 @@ proc setupArgsForParallelism(g: ModuleGraph; n: PNode; objType: PType;
|
||||
if argType.kind in {tyVarargs, tyOpenArray}:
|
||||
# important special case: we always create a zero-copy slice:
|
||||
let slice = newNodeI(nkCall, n.info, 4)
|
||||
slice.typ = n.typ
|
||||
slice.typ() = n.typ
|
||||
slice[0] = newSymNode(createMagic(g, idgen, "slice", mSlice))
|
||||
slice[0].typ = getSysType(g, n.info, tyInt) # fake type
|
||||
slice[0].typ() = getSysType(g, n.info, tyInt) # fake type
|
||||
var fieldB = newSym(skField, tmpName, idgen, objType.owner, n.info, g.config.options)
|
||||
fieldB.typ = getSysType(g, n.info, tyInt)
|
||||
discard objType.addField(fieldB, g.cache, idgen)
|
||||
|
||||
@@ -56,7 +56,6 @@ type
|
||||
contSyms, breakSyms: seq[PSym] # to transform 'continue' and 'break'
|
||||
deferDetected, tooEarly: bool
|
||||
isIntroducingNewLocalVars: bool # true if we are in `introducingNewLocalVars` (don't transform yields)
|
||||
inAddr: bool
|
||||
flags: TransformFlags
|
||||
graph: ModuleGraph
|
||||
idgen: IdGenerator
|
||||
@@ -98,17 +97,14 @@ proc newTemp(c: PTransf, typ: PType, info: TLineInfo): PNode =
|
||||
r.typ = typ #skipTypes(typ, {tyGenericInst, tyAlias, tySink})
|
||||
incl(r.flags, sfFromGeneric)
|
||||
let owner = getCurrOwner(c)
|
||||
if owner.isIterator and not c.tooEarly and not isDefined(c.graph.config, "nimOptIters"):
|
||||
result = freshVarForClosureIter(c.graph, r, c.idgen, owner)
|
||||
else:
|
||||
result = newSymNode(r)
|
||||
result = newSymNode(r)
|
||||
|
||||
proc transform(c: PTransf, n: PNode): PNode
|
||||
proc transform(c: PTransf, n: PNode, noConstFold = false): PNode
|
||||
|
||||
proc transformSons(c: PTransf, n: PNode): PNode =
|
||||
proc transformSons(c: PTransf, n: PNode, noConstFold = false): PNode =
|
||||
result = newTransNode(n)
|
||||
for i in 0..<n.len:
|
||||
result[i] = transform(c, n[i])
|
||||
result[i] = transform(c, n[i], noConstFold)
|
||||
|
||||
proc newAsgnStmt(c: PTransf, kind: TNodeKind, le: PNode, ri: PNode; isFirstWrite: bool): PNode =
|
||||
result = newTransNode(kind, ri.info, 2)
|
||||
@@ -177,13 +173,10 @@ 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 and not isDefined(c.graph.config, "nimOptIters"):
|
||||
result = freshVarForClosureIter(c.graph, v, c.idgen, owner)
|
||||
else:
|
||||
var newVar = copySym(v, c.idgen)
|
||||
incl(newVar.flags, sfFromGeneric)
|
||||
newVar.owner = owner
|
||||
result = newSymNode(newVar)
|
||||
var newVar = copySym(v, c.idgen)
|
||||
incl(newVar.flags, sfFromGeneric)
|
||||
setOwner(newVar, owner)
|
||||
result = newSymNode(newVar)
|
||||
|
||||
proc transformVarSection(c: PTransf, v: PNode): PNode =
|
||||
result = newTransNode(v)
|
||||
@@ -363,7 +356,7 @@ proc transformAsgn(c: PTransf, n: PNode): PNode =
|
||||
# given tuple type
|
||||
newTupleConstr[i] = def[0]
|
||||
|
||||
newTupleConstr.typ = rhs.typ
|
||||
newTupleConstr.typ() = rhs.typ
|
||||
|
||||
let asgnNode = newTransNode(nkAsgn, n.info, 2)
|
||||
asgnNode[0] = transform(c, n[0])
|
||||
@@ -481,8 +474,8 @@ proc transformYield(c: PTransf, n: PNode): PNode =
|
||||
result.add(introduceNewLocalVars(c, c.transCon.forLoopBody))
|
||||
c.isIntroducingNewLocalVars = false
|
||||
|
||||
proc transformAddrDeref(c: PTransf, n: PNode, kinds: TNodeKinds): PNode =
|
||||
result = transformSons(c, n)
|
||||
proc transformAddrDeref(c: PTransf, n: PNode, kinds: TNodeKinds, isAddr = false): PNode =
|
||||
result = transformSons(c, n, noConstFold = isAddr)
|
||||
# inlining of 'var openarray' iterators; bug #19977
|
||||
if n.typ.kind != tyOpenArray and (c.graph.config.backend == backendCpp or sfCompileToCpp in c.module.flags): return
|
||||
var n = result
|
||||
@@ -494,9 +487,9 @@ proc transformAddrDeref(c: PTransf, n: PNode, kinds: TNodeKinds): PNode =
|
||||
n[0][0] = m[0]
|
||||
result = n[0]
|
||||
if n.typ.skipTypes(abstractVar).kind != tyOpenArray:
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
elif n.typ.skipTypes(abstractInst).kind in {tyVar}:
|
||||
result.typ = toVar(result.typ, n.typ.skipTypes(abstractInst).kind, c.idgen)
|
||||
result.typ() = toVar(result.typ, n.typ.skipTypes(abstractInst).kind, c.idgen)
|
||||
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
|
||||
var m = n[0][1]
|
||||
if m.kind in kinds:
|
||||
@@ -504,9 +497,9 @@ proc transformAddrDeref(c: PTransf, n: PNode, kinds: TNodeKinds): PNode =
|
||||
n[0][1] = m[0]
|
||||
result = n[0]
|
||||
if n.typ.skipTypes(abstractVar).kind != tyOpenArray:
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
elif n.typ.skipTypes(abstractInst).kind in {tyVar}:
|
||||
result.typ = toVar(result.typ, n.typ.skipTypes(abstractInst).kind, c.idgen)
|
||||
result.typ() = toVar(result.typ, n.typ.skipTypes(abstractInst).kind, c.idgen)
|
||||
else:
|
||||
if n[0].kind in kinds and
|
||||
not (n[0][0].kind == nkSym and n[0][0].sym.kind == skForVar and
|
||||
@@ -520,7 +513,7 @@ proc transformAddrDeref(c: PTransf, n: PNode, kinds: TNodeKinds): PNode =
|
||||
# addr ( deref ( x )) --> x
|
||||
result = n[0][0]
|
||||
if n.typ.skipTypes(abstractVar).kind != tyOpenArray:
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
|
||||
proc generateThunk(c: PTransf; prc: PNode, dest: PType): PNode =
|
||||
## Converts 'prc' into '(thunk, nil)' so that it's compatible with
|
||||
@@ -579,7 +572,7 @@ proc transformConv(c: PTransf, n: PNode): PNode =
|
||||
else:
|
||||
result = transform(c, n[1])
|
||||
#result = transformSons(c, n)
|
||||
result.typ = takeType(n.typ, n[1].typ, c.graph, c.idgen)
|
||||
result.typ() = takeType(n.typ, n[1].typ, c.graph, c.idgen)
|
||||
#echo n.info, " came here and produced ", typeToString(result.typ),
|
||||
# " from ", typeToString(n.typ), " and ", typeToString(n[1].typ)
|
||||
of tyCstring:
|
||||
@@ -607,7 +600,7 @@ proc transformConv(c: PTransf, n: PNode): PNode =
|
||||
result[0] = transform(c, n[1])
|
||||
else:
|
||||
result = transform(c, n[1])
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
else:
|
||||
result = transformSons(c, n)
|
||||
of tyObject:
|
||||
@@ -620,7 +613,7 @@ proc transformConv(c: PTransf, n: PNode): PNode =
|
||||
result[0] = transform(c, n[1])
|
||||
else:
|
||||
result = transform(c, n[1])
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
of tyGenericParam, tyOrdinal:
|
||||
result = transform(c, n[1])
|
||||
# happens sometimes for generated assignments, etc.
|
||||
@@ -840,7 +833,7 @@ proc transformCase(c: PTransf, n: PNode): PNode =
|
||||
# as an expr
|
||||
let kind = if n.typ != nil: nkIfExpr else: nkIfStmt
|
||||
ifs = newTransNode(kind, it.info, 0)
|
||||
ifs.typ = n.typ
|
||||
ifs.typ() = n.typ
|
||||
ifs.add(e)
|
||||
of nkElse:
|
||||
if ifs == nil: result.add(e)
|
||||
@@ -948,7 +941,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(c.idgen)
|
||||
convNode.typ() = excTypeNode.typ.toRef(c.idgen)
|
||||
# -> let exc = ...
|
||||
let identDefs = newTransNode(nkIdentDefs, n[1].info, 3)
|
||||
identDefs[0] = n[0][2]
|
||||
@@ -1005,12 +998,12 @@ proc transformDerefBlock(c: PTransf, n: PNode): PNode =
|
||||
# We transform (block: x)[] to (block: x[])
|
||||
let e0 = n[0]
|
||||
result = shallowCopy(e0)
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
for i in 0 ..< e0.len - 1:
|
||||
result[i] = e0[i]
|
||||
result[e0.len-1] = newTreeIT(nkHiddenDeref, n.info, n.typ, e0[e0.len-1])
|
||||
|
||||
proc transform(c: PTransf, n: PNode): PNode =
|
||||
proc transform(c: PTransf, n: PNode, noConstFold = false): PNode =
|
||||
when false:
|
||||
var oldDeferAnchor: PNode
|
||||
if n.kind in {nkElifBranch, nkOfBranch, nkExceptBranch, nkElifExpr,
|
||||
@@ -1077,12 +1070,9 @@ proc transform(c: PTransf, n: PNode): PNode =
|
||||
of nkCallKinds:
|
||||
result = transformCall(c, n)
|
||||
of nkHiddenAddr:
|
||||
result = transformAddrDeref(c, n, {nkHiddenDeref})
|
||||
result = transformAddrDeref(c, n, {nkHiddenDeref}, isAddr = true)
|
||||
of nkAddr:
|
||||
let oldInAddr = c.inAddr
|
||||
c.inAddr = true
|
||||
result = transformAddrDeref(c, n, {nkDerefExpr, nkHiddenDeref})
|
||||
c.inAddr = oldInAddr
|
||||
result = transformAddrDeref(c, n, {nkDerefExpr, nkHiddenDeref}, isAddr = true)
|
||||
of nkDerefExpr:
|
||||
result = transformAddrDeref(c, n, {nkAddr, nkHiddenAddr})
|
||||
of nkHiddenDeref:
|
||||
@@ -1162,7 +1152,7 @@ proc transform(c: PTransf, n: PNode): PNode =
|
||||
let exprIsPointerCast = n.kind in {nkCast, nkConv, nkHiddenStdConv} and
|
||||
n.typ != nil and
|
||||
n.typ.kind == tyPointer
|
||||
if not exprIsPointerCast and not c.inAddr:
|
||||
if not exprIsPointerCast and not noConstFold:
|
||||
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):
|
||||
@@ -1212,7 +1202,7 @@ proc liftDeferAux(n: PNode) =
|
||||
tryStmt.add deferPart
|
||||
n[i] = tryStmt
|
||||
n.sons.setLen(i+1)
|
||||
n.typ = tryStmt.typ
|
||||
n.typ() = tryStmt.typ
|
||||
goOn = true
|
||||
break
|
||||
for i in 0..n.safeLen-1:
|
||||
|
||||
@@ -1685,7 +1685,7 @@ proc skipHidden*(n: PNode): PNode =
|
||||
|
||||
proc skipConvTakeType*(n: PNode): PNode =
|
||||
result = n.skipConv
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
|
||||
proc isEmptyContainer*(t: PType): bool =
|
||||
case t.kind
|
||||
@@ -1725,7 +1725,7 @@ proc skipHiddenSubConv*(n: PNode; g: ModuleGraph; idgen: IdGenerator): PNode =
|
||||
result = n
|
||||
else:
|
||||
result = copyTree(result)
|
||||
result.typ = dest
|
||||
result.typ() = dest
|
||||
else:
|
||||
result = n
|
||||
|
||||
|
||||
@@ -202,7 +202,7 @@ proc copyValue(src: PNode): PNode =
|
||||
return src
|
||||
result = newNode(src.kind)
|
||||
result.info = src.info
|
||||
result.typ = src.typ
|
||||
result.typ() = src.typ
|
||||
result.flags = src.flags * PersistentNodeFlags
|
||||
result.comment = src.comment
|
||||
when defined(useNodeIds):
|
||||
@@ -1276,6 +1276,11 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||
createSet(regs[ra])
|
||||
move(regs[ra].node.sons,
|
||||
nimsets.diffSets(c.config, regs[rb].node, regs[rc].node).sons)
|
||||
of opcXorSet:
|
||||
decodeBC(rkNode)
|
||||
createSet(regs[ra])
|
||||
move(regs[ra].node.sons,
|
||||
nimsets.symdiffSets(c.config, regs[rb].node, regs[rc].node).sons)
|
||||
of opcConcatStr:
|
||||
decodeBC(rkNode)
|
||||
createStr regs[ra]
|
||||
@@ -1532,10 +1537,10 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||
# Set the `name` field of the exception
|
||||
var exceptionNameNode = newStrNode(nkStrLit, c.currentExceptionA.typ.sym.name.s)
|
||||
if c.currentExceptionA[2].kind == nkExprColonExpr:
|
||||
exceptionNameNode.typ = c.currentExceptionA[2][1].typ
|
||||
exceptionNameNode.typ() = c.currentExceptionA[2][1].typ
|
||||
c.currentExceptionA[2][1] = exceptionNameNode
|
||||
else:
|
||||
exceptionNameNode.typ = c.currentExceptionA[2].typ
|
||||
exceptionNameNode.typ() = c.currentExceptionA[2].typ
|
||||
c.currentExceptionA[2] = exceptionNameNode
|
||||
c.exceptionInstr = pc
|
||||
|
||||
@@ -1577,7 +1582,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||
let instr2 = c.code[pc]
|
||||
let count = regs[instr2.regA].intVal.int
|
||||
regs[ra].node = newNodeI(nkBracket, c.debug[pc])
|
||||
regs[ra].node.typ = typ
|
||||
regs[ra].node.typ() = typ
|
||||
newSeq(regs[ra].node.sons, count)
|
||||
for i in 0..<count:
|
||||
regs[ra].node[i] = getNullValue(c, typ.elementType, c.debug[pc], c.config)
|
||||
@@ -1992,7 +1997,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||
else:
|
||||
internalAssert c.config, false
|
||||
regs[ra].node.info = n.info
|
||||
regs[ra].node.typ = n.typ
|
||||
regs[ra].node.typ() = n.typ
|
||||
of opcNCopyLineInfo:
|
||||
decodeB(rkNode)
|
||||
regs[ra].node.info = regs[rb].node.info
|
||||
@@ -2072,7 +2077,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
||||
ensureKind(rkNode)
|
||||
regs[ra].node = temp
|
||||
regs[ra].node.info = c.debug[pc]
|
||||
regs[ra].node.typ = typ
|
||||
regs[ra].node.typ() = typ
|
||||
of opcConv:
|
||||
let rb = instr.regB
|
||||
inc pc
|
||||
@@ -2332,9 +2337,17 @@ proc execProc*(c: PCtx; sym: PSym; args: openArray[PNode]): PNode =
|
||||
localError(c.config, sym.info,
|
||||
"NimScript: attempt to call non-routine: " & sym.name.s)
|
||||
|
||||
proc errorNode(idgen: IdGenerator; owner: PSym, n: PNode): PNode =
|
||||
result = newNodeI(nkEmpty, n.info)
|
||||
result.typ() = newType(tyError, idgen, owner)
|
||||
result.typ.flags.incl tfCheckedForDestructor
|
||||
|
||||
proc evalStmt*(c: PCtx, n: PNode) =
|
||||
let n = transformExpr(c.graph, c.idgen, c.module, n)
|
||||
let start = genStmt(c, n)
|
||||
if c.cannotEval:
|
||||
c.cannotEval = false
|
||||
return
|
||||
# execute new instructions; this redundant opcEof check saves us lots
|
||||
# of allocations in 'execute':
|
||||
if c.code[start].opcode != opcEof:
|
||||
@@ -2345,7 +2358,10 @@ proc evalExpr*(c: PCtx, n: PNode): PNode =
|
||||
# `nim --eval:"expr"` might've used it at some point for idetools; could
|
||||
# be revived for nimsuggest
|
||||
let n = transformExpr(c.graph, c.idgen, c.module, n)
|
||||
c.cannotEval = false
|
||||
let start = genExpr(c, n)
|
||||
if c.cannotEval:
|
||||
return errorNode(c.idgen, c.module, n)
|
||||
assert c.code[start].opcode != opcEof
|
||||
result = execute(c, start)
|
||||
|
||||
@@ -2398,7 +2414,10 @@ proc evalConstExprAux(module: PSym; idgen: IdGenerator;
|
||||
var c = PCtx g.vm
|
||||
let oldMode = c.mode
|
||||
c.mode = mode
|
||||
c.cannotEval = false
|
||||
let start = genExpr(c, n, requiresValue = mode!=emStaticStmt)
|
||||
if c.cannotEval:
|
||||
return errorNode(idgen, prc, n)
|
||||
if c.code[start].opcode == opcEof: return newNodeI(nkEmpty, n.info)
|
||||
assert c.code[start].opcode != opcEof
|
||||
when debugEchoCode: c.echoCode start
|
||||
@@ -2455,7 +2474,7 @@ proc setupMacroParam(x: PNode, typ: PType): TFullReg =
|
||||
var n = x
|
||||
if n.kind in {nkHiddenSubConv, nkHiddenStdConv}: n = n[1]
|
||||
n.flags.incl nfIsRef
|
||||
n.typ = x.typ
|
||||
n.typ() = x.typ
|
||||
result = TFullReg(kind: rkNode, node: n)
|
||||
|
||||
iterator genericParamsInMacroCall*(macroSym: PSym, call: PNode): (PSym, PNode) =
|
||||
@@ -2469,11 +2488,6 @@ iterator genericParamsInMacroCall*(macroSym: PSym, call: PNode): (PSym, PNode) =
|
||||
# to prevent endless recursion in macro instantiation
|
||||
const evalMacroLimit = 1000
|
||||
|
||||
#proc errorNode(idgen: IdGenerator; owner: PSym, n: PNode): PNode =
|
||||
# result = newNodeI(nkEmpty, n.info)
|
||||
# result.typ = newType(tyError, idgen, owner)
|
||||
# result.typ.flags.incl tfCheckedForDestructor
|
||||
|
||||
proc evalMacroCall*(module: PSym; idgen: IdGenerator; g: ModuleGraph; templInstCounter: ref int;
|
||||
n, nOrig: PNode, sym: PSym): PNode =
|
||||
#if g.config.errorCounter > 0: return errorNode(idgen, module, n)
|
||||
@@ -2497,7 +2511,10 @@ proc evalMacroCall*(module: PSym; idgen: IdGenerator; g: ModuleGraph; templInstC
|
||||
c.comesFromHeuristic.line = 0'u16
|
||||
c.callsite = nOrig
|
||||
c.templInstCounter = templInstCounter
|
||||
c.cannotEval = false
|
||||
let start = genProc(c, sym)
|
||||
if c.cannotEval:
|
||||
return errorNode(idgen, module, n)
|
||||
|
||||
var tos = PStackFrame(prc: sym, comesFrom: 0, next: nil)
|
||||
let maxSlots = sym.offset
|
||||
|
||||
@@ -100,7 +100,7 @@ type
|
||||
opcEqRef, opcEqNimNode, opcSameNodeType,
|
||||
opcXor, opcNot, opcUnaryMinusInt, opcUnaryMinusFloat, opcBitnotInt,
|
||||
opcEqStr, opcEqCString, opcLeStr, opcLtStr, opcEqSet, opcLeSet, opcLtSet,
|
||||
opcMulSet, opcPlusSet, opcMinusSet, opcConcatStr,
|
||||
opcMulSet, opcPlusSet, opcMinusSet, opcXorSet, opcConcatStr,
|
||||
opcContainsSet, opcRepr, opcSetLenStr, opcSetLenSeq,
|
||||
opcIsNil, opcOf, opcIs,
|
||||
opcParseFloat, opcConv, opcCast,
|
||||
@@ -270,6 +270,7 @@ type
|
||||
templInstCounter*: ref int # gives every template instantiation a unique ID, needed here for getAst
|
||||
vmstateDiff*: seq[(PSym, PNode)] # we remember the "diff" to global state here (feature for IC)
|
||||
procToCodePos*: Table[int, int]
|
||||
cannotEval*: bool
|
||||
|
||||
PStackFrame* = ref TStackFrame
|
||||
TStackFrame* {.acyclic.} = object
|
||||
|
||||
@@ -35,7 +35,7 @@ proc atomicTypeX(cache: IdentCache; name: string; m: TMagic; t: PType; info: TLi
|
||||
sym.magic = m
|
||||
sym.typ = t
|
||||
result = newSymNode(sym)
|
||||
result.typ = t
|
||||
result.typ() = t
|
||||
|
||||
proc atomicTypeX(s: PSym; info: TLineInfo): PNode =
|
||||
result = newSymNode(s)
|
||||
@@ -52,7 +52,7 @@ proc mapTypeToBracketX(cache: IdentCache; name: string; m: TMagic; t: PType; inf
|
||||
for a in t.kids:
|
||||
if a == nil:
|
||||
let voidt = atomicTypeX(cache, "void", mVoid, t, info, idgen)
|
||||
voidt.typ = newType(tyVoid, idgen, t.owner)
|
||||
voidt.typ() = newType(tyVoid, idgen, t.owner)
|
||||
result.add voidt
|
||||
else:
|
||||
result.add mapTypeToAstX(cache, a, info, idgen, inst)
|
||||
@@ -136,7 +136,7 @@ proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo;
|
||||
if allowRecursion:
|
||||
result = mapTypeToAstR(t.skipModifier, info)
|
||||
# keep original type info for getType calls on the output node:
|
||||
result.typ = t
|
||||
result.typ() = t
|
||||
else:
|
||||
result = newNodeX(nkBracketExpr)
|
||||
#result.add mapTypeToAst(t.last, info)
|
||||
@@ -146,7 +146,7 @@ proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo;
|
||||
else:
|
||||
result = mapTypeToAstX(cache, t.skipModifier, info, idgen, inst, allowRecursion)
|
||||
# keep original type info for getType calls on the output node:
|
||||
result.typ = t
|
||||
result.typ() = t
|
||||
of tyGenericBody:
|
||||
if inst:
|
||||
result = mapTypeToAstR(t.typeBodyImpl, info)
|
||||
|
||||
@@ -1212,6 +1212,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}, m: TMag
|
||||
of mMulSet: genBinarySet(c, n, dest, opcMulSet)
|
||||
of mPlusSet: genBinarySet(c, n, dest, opcPlusSet)
|
||||
of mMinusSet: genBinarySet(c, n, dest, opcMinusSet)
|
||||
of mXorSet: genBinarySet(c, n, dest, opcXorSet)
|
||||
of mConStrStr: genVarargsABC(c, n, dest, opcConcatStr)
|
||||
of mInSet: genBinarySet(c, n, dest, opcContainsSet)
|
||||
of mRepr: genUnaryABC(c, n, dest, opcRepr)
|
||||
@@ -1473,9 +1474,9 @@ proc canElimAddr(n: PNode; idgen: IdGenerator): PNode =
|
||||
result = copyNode(n[0])
|
||||
result.add m[0]
|
||||
if n.typ.skipTypes(abstractVar).kind != tyOpenArray:
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
elif n.typ.skipTypes(abstractInst).kind in {tyVar}:
|
||||
result.typ = toVar(result.typ, n.typ.skipTypes(abstractInst).kind, idgen)
|
||||
result.typ() = toVar(result.typ, n.typ.skipTypes(abstractInst).kind, idgen)
|
||||
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
|
||||
var m = n[0][1]
|
||||
if m.kind in {nkDerefExpr, nkHiddenDeref}:
|
||||
@@ -1484,9 +1485,9 @@ proc canElimAddr(n: PNode; idgen: IdGenerator): PNode =
|
||||
result.add n[0][0]
|
||||
result.add m[0]
|
||||
if n.typ.skipTypes(abstractVar).kind != tyOpenArray:
|
||||
result.typ = n.typ
|
||||
result.typ() = n.typ
|
||||
elif n.typ.skipTypes(abstractInst).kind in {tyVar}:
|
||||
result.typ = toVar(result.typ, n.typ.skipTypes(abstractInst).kind, idgen)
|
||||
result.typ() = toVar(result.typ, n.typ.skipTypes(abstractInst).kind, idgen)
|
||||
else:
|
||||
if n[0].kind in {nkDerefExpr, nkHiddenDeref}:
|
||||
# addr ( deref ( x )) --> x
|
||||
@@ -1545,6 +1546,7 @@ template cannotEval(c: PCtx; n: PNode) =
|
||||
if c.config.cmd == cmdCheck:
|
||||
localError(c.config, n.info, "cannot evaluate at compile time: " &
|
||||
n.renderTree)
|
||||
c.cannotEval = true
|
||||
return
|
||||
globalError(c.config, n.info, "cannot evaluate at compile time: " &
|
||||
n.renderTree)
|
||||
@@ -1678,7 +1680,7 @@ proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
|
||||
|
||||
proc genTypeLit(c: PCtx; t: PType; dest: var TDest) =
|
||||
var n = newNode(nkType)
|
||||
n.typ = t
|
||||
n.typ() = t
|
||||
genLit(c, n, dest)
|
||||
|
||||
proc isEmptyBody(n: PNode): bool =
|
||||
@@ -1847,7 +1849,7 @@ proc genCheckedObjAccessAux(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags
|
||||
let fieldName = $accessExpr[1]
|
||||
let msg = genFieldDefect(c.config, fieldName, disc.sym)
|
||||
let strLit = newStrNode(msg, accessExpr[1].info)
|
||||
strLit.typ = strType
|
||||
strLit.typ() = strType
|
||||
c.genLit(strLit, msgReg)
|
||||
c.gABC(n, opcInvalidField, msgReg, discVal)
|
||||
c.freeTemp(discVal)
|
||||
|
||||
@@ -33,13 +33,13 @@ proc dispatch(x: Base, params: ...) =
|
||||
dispatchObject,
|
||||
newIntNode(nkIntLit, index)
|
||||
)
|
||||
getVTableCall.typ = base.typ
|
||||
getVTableCall.typ() = base.typ
|
||||
var vTableCall = newNodeIT(nkCall, base.info, base.typ.returnType)
|
||||
var castNode = newTree(nkCast,
|
||||
newNodeIT(nkType, base.info, base.typ),
|
||||
getVTableCall)
|
||||
|
||||
castNode.typ = base.typ
|
||||
castNode.typ() = base.typ
|
||||
vTableCall.add castNode
|
||||
for col in 1..<paramLen:
|
||||
let param = base.typ.n[col].sym
|
||||
|
||||
@@ -2241,6 +2241,10 @@ Nim supports these `calling conventions`:idx:\:
|
||||
only a hint for the compiler: it may completely ignore it, and
|
||||
it may inline procedures that are not marked as `inline`.
|
||||
|
||||
`noinline`:idx:
|
||||
: The backend compiler may inline procedures that are not marked as `inline`.
|
||||
The noinline convention prevents it.
|
||||
|
||||
`fastcall`:idx:
|
||||
: Fastcall means different things to different C compilers. One gets whatever
|
||||
the C `__fastcall` means.
|
||||
@@ -8646,6 +8650,14 @@ pragma should be used in addition to the `exportc` pragma. See
|
||||
[Dynlib pragma for export].
|
||||
|
||||
|
||||
Exportcpp pragma
|
||||
----------------
|
||||
The `exportcpp` pragma works like the `exportc` pragma but it requires the `cpp` backend.
|
||||
When compiled with the `cpp` backend, the `exportc` pragma adds `export "C"` to
|
||||
the declaration in the generated code so that it can be called from both C and
|
||||
C++ code. `exportcpp` pragma doesn't add `export "C"`.
|
||||
|
||||
|
||||
Extern pragma
|
||||
-------------
|
||||
Like `exportc` or `importc`, the `extern` pragma affects name
|
||||
|
||||
@@ -1182,6 +1182,9 @@ at runtime by 0, the second by 1, and so on. For example:
|
||||
|
||||
var x = south # `x` is of type `Direction`; its value is `south`
|
||||
echo x # prints "south"
|
||||
|
||||
if x == Direction.south:
|
||||
echo "It's south!"
|
||||
```
|
||||
|
||||
All the comparison operators can be used with enumeration types.
|
||||
|
||||
@@ -469,12 +469,6 @@ typedef char* NCSTRING;
|
||||
|
||||
#define NIM_STRLIT_FLAG ((NU)(1) << ((NIM_INTBITS) - 2)) /* This has to be the same as system.strlitFlag! */
|
||||
|
||||
#define STRING_LITERAL(name, str, length) \
|
||||
static const struct { \
|
||||
TGenericSeq Sup; \
|
||||
NIM_CHAR data[(length) + 1]; \
|
||||
} name = {{length, (NI) ((NU)length | NIM_STRLIT_FLAG)}, str}
|
||||
|
||||
/* declared size of a sequence/variable length array: */
|
||||
#if defined(__cplusplus) && defined(__clang__)
|
||||
# define SEQ_DECL_SIZE 1
|
||||
|
||||
@@ -75,3 +75,31 @@ func `[]=`*[T](t: var set[T], key: T, val: bool) {.inline.} =
|
||||
s[a3] = true
|
||||
assert s == {a2, a3}
|
||||
if val: t.incl key else: t.excl key
|
||||
|
||||
when defined(nimHasXorSet):
|
||||
func symmetricDifference*[T](x, y: set[T]): set[T] {.magic: "XorSet".} =
|
||||
## This operator computes the symmetric difference of two sets,
|
||||
## equivalent to but more efficient than `x + y - x * y` or
|
||||
## `(x - y) + (y - x)`.
|
||||
runnableExamples:
|
||||
assert symmetricDifference({1, 2, 3}, {2, 3, 4}) == {1, 4}
|
||||
else:
|
||||
func symmetricDifference*[T](x, y: set[T]): set[T] {.inline.} =
|
||||
result = x + y - (x * y)
|
||||
|
||||
proc `-+-`*[T](x, y: set[T]): set[T] {.inline.} =
|
||||
## Operator alias for `symmetricDifference`.
|
||||
runnableExamples:
|
||||
assert {1, 2, 3} -+- {2, 3, 4} == {1, 4}
|
||||
result = symmetricDifference(x, y)
|
||||
|
||||
proc toggle*[T](x: var set[T], y: set[T]) {.inline.} =
|
||||
## Toggles the existence of each value of `y` in `x`.
|
||||
## If any element in `y` is also in `x`, it is excluded from `x`;
|
||||
## otherwise it is included.
|
||||
## Equivalent to `x = symmetricDifference(x, y)`.
|
||||
runnableExamples:
|
||||
var x = {1, 2, 3}
|
||||
x.toggle({2, 3, 4})
|
||||
assert x == {1, 4}
|
||||
x = symmetricDifference(x, y)
|
||||
|
||||
@@ -337,6 +337,18 @@ proc SetMinus(a, b: int): int {.compilerproc, asmNoStackFrame.} =
|
||||
return result;
|
||||
""".}
|
||||
|
||||
proc SetXor(a, b: int): int {.compilerproc, asmNoStackFrame.} =
|
||||
{.emit: """
|
||||
var result = {};
|
||||
for (var elem in `a`) {
|
||||
if (!`b`[elem]) { result[elem] = true; }
|
||||
}
|
||||
for (var elem in `b`) {
|
||||
if (!`a`[elem]) { result[elem] = true; }
|
||||
}
|
||||
return result;
|
||||
""".}
|
||||
|
||||
proc cmpStrings(a, b: string): int {.asmNoStackFrame, compilerproc.} =
|
||||
{.emit: """
|
||||
if (`a` == `b`) return 0;
|
||||
|
||||
@@ -9,6 +9,7 @@ is in separate files:
|
||||
* `assertions <assertions.html>`_
|
||||
* `dollars <dollars.html>`_
|
||||
* `ctypes <ctypes.html>`_
|
||||
* `repr_v2 <repr_v2.html>`_
|
||||
|
||||
|
||||
Here is a short overview of the most commonly used functions from the
|
||||
|
||||
@@ -449,7 +449,7 @@ proc testNimblePackages(r: var TResults; cat: Category; packageFilter: string) =
|
||||
if pkg.allowFailure:
|
||||
inc r.passed
|
||||
inc r.failedButAllowed
|
||||
addResult(r, test, targetC, "", "", cmd & "\n" & outp, reFailed, allowFailure = pkg.allowFailure)
|
||||
r.finishTest(test, targetC, "", "", cmd & "\n" & outp, reFailed, allowFailure = pkg.allowFailure)
|
||||
continue
|
||||
outp
|
||||
|
||||
@@ -465,21 +465,21 @@ proc testNimblePackages(r: var TResults; cat: Category; packageFilter: string) =
|
||||
discard tryCommand(cmds[i], maxRetries = 3)
|
||||
discard tryCommand(cmds[^1], reFailed = reBuildFailed)
|
||||
inc r.passed
|
||||
r.addResult(test, targetC, "", "", "", reSuccess, allowFailure = pkg.allowFailure)
|
||||
r.finishTest(test, targetC, "", "", "", reSuccess, allowFailure = pkg.allowFailure)
|
||||
|
||||
errors = r.total - r.passed
|
||||
if errors == 0:
|
||||
r.addResult(packageFileTest, targetC, "", "", "", reSuccess)
|
||||
r.finishTest(packageFileTest, targetC, "", "", "", reSuccess)
|
||||
else:
|
||||
r.addResult(packageFileTest, targetC, "", "", "", reBuildFailed)
|
||||
r.finishTest(packageFileTest, targetC, "", "", "", reBuildFailed)
|
||||
|
||||
except JsonParsingError:
|
||||
errors = 1
|
||||
r.addResult(packageFileTest, targetC, "", "", "Invalid package file", reBuildFailed)
|
||||
r.finishTest(packageFileTest, targetC, "", "", "Invalid package file", reBuildFailed)
|
||||
raise
|
||||
except ValueError:
|
||||
errors = 1
|
||||
r.addResult(packageFileTest, targetC, "", "", "Unknown package", reBuildFailed)
|
||||
r.finishTest(packageFileTest, targetC, "", "", "Unknown package", reBuildFailed)
|
||||
raise # bug #18805
|
||||
finally:
|
||||
if errors == 0: removeDir(packagesDir)
|
||||
@@ -568,6 +568,7 @@ proc isJoinableSpec(spec: TSpec): bool =
|
||||
spec.err != reDisabled and
|
||||
not spec.unjoinable and
|
||||
spec.exitCode == 0 and
|
||||
spec.retries == 0 and
|
||||
spec.input.len == 0 and
|
||||
spec.nimout.len == 0 and
|
||||
spec.nimoutFull == false and
|
||||
|
||||
@@ -61,7 +61,7 @@ pkg "constantine", "nimble make_lib"
|
||||
pkg "cowstrings", "nim c -r tests/tcowstrings.nim"
|
||||
pkg "criterion"
|
||||
pkg "dashing", "nim c tests/functional.nim"
|
||||
pkg "datamancer", url = "https://github.com/nim-lang/Datamancer"
|
||||
pkg "datamancer"
|
||||
pkg "delaunay"
|
||||
pkg "docopt"
|
||||
pkg "dotenv"
|
||||
|
||||
@@ -56,6 +56,7 @@ type
|
||||
reJoined, # test is disabled because it was joined into the megatest
|
||||
reSuccess # test was successful
|
||||
reInvalidSpec # test had problems to parse the spec
|
||||
reRetry # test is being retried
|
||||
|
||||
TTarget* = enum
|
||||
targetC = "c"
|
||||
@@ -102,6 +103,7 @@ type
|
||||
# but don't rely on much precision
|
||||
inlineErrors*: seq[InlineError] # line information to error message
|
||||
debugInfo*: string # debug info to give more context
|
||||
retries*: int # number of retry attempts after the test fails
|
||||
|
||||
proc getCmd*(s: TSpec): string =
|
||||
if s.cmd.len == 0:
|
||||
@@ -477,6 +479,8 @@ proc parseSpec*(filename: string): TSpec =
|
||||
result.timeout = parseFloat(e.value)
|
||||
except ValueError:
|
||||
result.parseErrors.addLine "cannot interpret as a float: ", e.value
|
||||
of "retries":
|
||||
discard parseInt(e.value, result.retries)
|
||||
of "targets", "target":
|
||||
try:
|
||||
result.targets.incl parseTargets(e.value)
|
||||
|
||||
@@ -275,16 +275,13 @@ proc testName(test: TTest, target: TTarget, extraOptions: string, allowFailure:
|
||||
name.strip()
|
||||
|
||||
proc addResult(r: var TResults, test: TTest, target: TTarget,
|
||||
extraOptions, expected, given: string, successOrig: TResultEnum,
|
||||
extraOptions, expected, given: string, success: TResultEnum, duration: float,
|
||||
allowFailure = false, givenSpec: ptr TSpec = nil) =
|
||||
# instead of `ptr TSpec` we could also use `Option[TSpec]`; passing `givenSpec` makes it easier to get what we need
|
||||
# instead of having to pass individual fields, or abusing existing ones like expected vs given.
|
||||
# test.name is easier to find than test.name.extractFilename
|
||||
# A bit hacky but simple and works with tests/testament/tshould_not_work.nim
|
||||
let name = testName(test, target, extraOptions, allowFailure)
|
||||
let duration = epochTime() - test.startTime
|
||||
let success = if test.spec.timeout > 0.0 and duration > test.spec.timeout: reTimeout
|
||||
else: successOrig
|
||||
|
||||
let durationStr = duration.formatFloat(ffDecimal, precision = 2).align(5)
|
||||
if backendLogging:
|
||||
@@ -345,6 +342,33 @@ proc addResult(r: var TResults, test: TTest, target: TTarget,
|
||||
discard waitForExit(p)
|
||||
close(p)
|
||||
|
||||
proc finishTest(r: var TResults, test: TTest, target: TTarget,
|
||||
extraOptions, expected, given: string, successOrig: TResultEnum,
|
||||
allowFailure = false, givenSpec: ptr TSpec = nil) =
|
||||
## calculates duration of test, reports result
|
||||
## `retries` option in the test is ignored
|
||||
let duration = epochTime() - test.startTime
|
||||
let success = if test.spec.timeout > 0.0 and duration > test.spec.timeout: reTimeout
|
||||
else: successOrig
|
||||
addResult(r, test, target, extraOptions, expected, given, success, duration, allowFailure, givenSpec)
|
||||
|
||||
proc finishTestRetryable(r: var TResults, test: TTest, target: TTarget,
|
||||
extraOptions, expected, given: string, successOrig: TResultEnum,
|
||||
allowFailure = false, givenSpec: ptr TSpec = nil): bool =
|
||||
## if test failed and has remaining retries, return `true`,
|
||||
## otherwise calculate duration and report result
|
||||
##
|
||||
## warning: if `true` is returned, then the result is not reported,
|
||||
## it has to be retried or `finishTest` should be called instead
|
||||
result = false
|
||||
let duration = epochTime() - test.startTime
|
||||
let success = if test.spec.timeout > 0.0 and duration > test.spec.timeout: reTimeout
|
||||
else: successOrig
|
||||
if test.spec.retries > 0 and success notin {reSuccess, reDisabled, reJoined, reInvalidSpec}:
|
||||
return true
|
||||
else:
|
||||
addResult(r, test, target, extraOptions, expected, given, success, duration, allowFailure, givenSpec)
|
||||
|
||||
proc toString(inlineError: InlineError, filename: string): string =
|
||||
result.add "$file($line, $col) $kind: $msg" % [
|
||||
"file", filename,
|
||||
@@ -373,23 +397,24 @@ proc nimoutCheck(expected, given: TSpec): bool =
|
||||
result = false
|
||||
|
||||
proc cmpMsgs(r: var TResults, expected, given: TSpec, test: TTest,
|
||||
target: TTarget, extraOptions: string) =
|
||||
target: TTarget, extraOptions: string): bool =
|
||||
# result has to be checked for retry
|
||||
if not checkForInlineErrors(expected, given) or
|
||||
(not expected.nimoutFull and not nimoutCheck(expected, given)):
|
||||
r.addResult(test, target, extraOptions, expected.nimout & inlineErrorsMsgs(expected), given.nimout, reMsgsDiffer)
|
||||
result = r.finishTestRetryable(test, target, extraOptions, expected.nimout & inlineErrorsMsgs(expected), given.nimout, reMsgsDiffer)
|
||||
elif strip(expected.msg) notin strip(given.msg):
|
||||
r.addResult(test, target, extraOptions, expected.msg, given.msg, reMsgsDiffer)
|
||||
result = r.finishTestRetryable(test, target, extraOptions, expected.msg, given.msg, reMsgsDiffer)
|
||||
elif not nimoutCheck(expected, given):
|
||||
r.addResult(test, target, extraOptions, expected.nimout, given.nimout, reMsgsDiffer)
|
||||
result = r.finishTestRetryable(test, target, extraOptions, expected.nimout, given.nimout, reMsgsDiffer)
|
||||
elif extractFilename(expected.file) != extractFilename(given.file) and
|
||||
"internal error:" notin expected.msg:
|
||||
r.addResult(test, target, extraOptions, expected.file, given.file, reFilesDiffer)
|
||||
result = r.finishTestRetryable(test, target, extraOptions, expected.file, given.file, reFilesDiffer)
|
||||
elif expected.line != given.line and expected.line != 0 or
|
||||
expected.column != given.column and expected.column != 0:
|
||||
r.addResult(test, target, extraOptions, $expected.line & ':' & $expected.column,
|
||||
result = r.finishTestRetryable(test, target, extraOptions, $expected.line & ':' & $expected.column,
|
||||
$given.line & ':' & $given.column, reLinesDiffer)
|
||||
else:
|
||||
r.addResult(test, target, extraOptions, expected.msg, given.msg, reSuccess)
|
||||
result = r.finishTestRetryable(test, target, extraOptions, expected.msg, given.msg, reSuccess)
|
||||
inc(r.passed)
|
||||
|
||||
proc generatedFile(test: TTest, target: TTarget): string =
|
||||
@@ -428,7 +453,8 @@ proc codegenCheck(test: TTest, target: TTarget, spec: TSpec, expectedMsg: var st
|
||||
echo getCurrentExceptionMsg()
|
||||
|
||||
proc compilerOutputTests(test: TTest, target: TTarget, extraOptions: string,
|
||||
given: var TSpec, expected: TSpec; r: var TResults) =
|
||||
given: var TSpec, expected: TSpec; r: var TResults): bool =
|
||||
# result has to be checked for retry
|
||||
var expectedmsg: string = ""
|
||||
var givenmsg: string = ""
|
||||
if given.err == reSuccess:
|
||||
@@ -443,7 +469,7 @@ proc compilerOutputTests(test: TTest, target: TTarget, extraOptions: string,
|
||||
else:
|
||||
givenmsg = "$ " & given.cmd & '\n' & given.nimout
|
||||
if given.err == reSuccess: inc(r.passed)
|
||||
r.addResult(test, target, extraOptions, expectedmsg, givenmsg, given.err)
|
||||
result = r.finishTestRetryable(test, target, extraOptions, expectedmsg, givenmsg, given.err)
|
||||
|
||||
proc getTestSpecTarget(): TTarget =
|
||||
if getEnv("NIM_COMPILE_TO_CPP", "false") == "true":
|
||||
@@ -459,31 +485,39 @@ proc equalModuloLastNewline(a, b: string): bool =
|
||||
|
||||
proc testSpecHelper(r: var TResults, test: var TTest, expected: TSpec,
|
||||
target: TTarget, extraOptions: string, nimcache: string) =
|
||||
test.startTime = epochTime()
|
||||
template maybeRetry(x: bool) =
|
||||
# if `x` is true, retries the test
|
||||
if x:
|
||||
test.spec.err = reRetry
|
||||
dec test.spec.retries
|
||||
testSpecHelper(r, test, expected, target, extraOptions, nimcache)
|
||||
return
|
||||
if test.spec.err != reRetry:
|
||||
test.startTime = epochTime()
|
||||
if testName(test, target, extraOptions, false) in skips:
|
||||
test.spec.err = reDisabled
|
||||
|
||||
if test.spec.err in {reDisabled, reJoined}:
|
||||
r.addResult(test, target, extraOptions, "", "", test.spec.err)
|
||||
r.finishTest(test, target, extraOptions, "", "", test.spec.err)
|
||||
inc(r.skipped)
|
||||
return
|
||||
var given = callNimCompiler(expected.getCmd, test.name, test.options, nimcache, target, extraOptions)
|
||||
case expected.action
|
||||
of actionCompile:
|
||||
compilerOutputTests(test, target, extraOptions, given, expected, r)
|
||||
maybeRetry compilerOutputTests(test, target, extraOptions, given, expected, r)
|
||||
of actionRun:
|
||||
if given.err != reSuccess:
|
||||
r.addResult(test, target, extraOptions, "", "$ " & given.cmd & '\n' & given.nimout, given.err, givenSpec = given.addr)
|
||||
maybeRetry r.finishTestRetryable(test, target, extraOptions, "", "$ " & given.cmd & '\n' & given.nimout, given.err, givenSpec = given.addr)
|
||||
else:
|
||||
let isJsTarget = target == targetJS
|
||||
var exeFile = changeFileExt(test.name, if isJsTarget: "js" else: ExeExt)
|
||||
if not fileExists(exeFile):
|
||||
r.addResult(test, target, extraOptions, expected.output,
|
||||
maybeRetry r.finishTestRetryable(test, target, extraOptions, expected.output,
|
||||
"executable not found: " & exeFile, reExeNotFound)
|
||||
else:
|
||||
let nodejs = if isJsTarget: findNodeJs() else: ""
|
||||
if isJsTarget and nodejs == "":
|
||||
r.addResult(test, target, extraOptions, expected.output, "nodejs binary not in PATH",
|
||||
maybeRetry r.finishTestRetryable(test, target, extraOptions, expected.output, "nodejs binary not in PATH",
|
||||
reExeNotFound)
|
||||
else:
|
||||
var exeCmd: string
|
||||
@@ -515,19 +549,19 @@ proc testSpecHelper(r: var TResults, test: var TTest, expected: TSpec,
|
||||
buf
|
||||
if exitCode != expected.exitCode:
|
||||
given.err = reExitcodesDiffer
|
||||
r.addResult(test, target, extraOptions, "exitcode: " & $expected.exitCode,
|
||||
maybeRetry r.finishTestRetryable(test, target, extraOptions, "exitcode: " & $expected.exitCode,
|
||||
"exitcode: " & $exitCode & "\n\nOutput:\n" &
|
||||
bufB, reExitcodesDiffer)
|
||||
elif (expected.outputCheck == ocEqual and not expected.output.equalModuloLastNewline(bufB)) or
|
||||
(expected.outputCheck == ocSubstr and expected.output notin bufB):
|
||||
given.err = reOutputsDiffer
|
||||
r.addResult(test, target, extraOptions, expected.output, bufB, reOutputsDiffer)
|
||||
compilerOutputTests(test, target, extraOptions, given, expected, r)
|
||||
maybeRetry r.finishTestRetryable(test, target, extraOptions, expected.output, bufB, reOutputsDiffer)
|
||||
maybeRetry compilerOutputTests(test, target, extraOptions, given, expected, r)
|
||||
of actionReject:
|
||||
# Make sure its the compiler rejecting and not the system (e.g. segfault)
|
||||
cmpMsgs(r, expected, given, test, target, extraOptions)
|
||||
maybeRetry cmpMsgs(r, expected, given, test, target, extraOptions)
|
||||
if given.exitCode != QuitFailure:
|
||||
r.addResult(test, target, extraOptions, "exitcode: " & $QuitFailure,
|
||||
maybeRetry r.finishTestRetryable(test, target, extraOptions, "exitcode: " & $QuitFailure,
|
||||
"exitcode: " & $given.exitCode & "\n\nOutput:\n" &
|
||||
given.nimout, reExitcodesDiffer)
|
||||
|
||||
@@ -552,7 +586,7 @@ proc targetHelper(r: var TResults, test: TTest, expected: TSpec, extraOptions: s
|
||||
for target in expected.targets:
|
||||
inc(r.total)
|
||||
if target notin gTargets:
|
||||
r.addResult(test, target, extraOptions, "", "", reDisabled)
|
||||
r.finishTest(test, target, extraOptions, "", "", reDisabled)
|
||||
inc(r.skipped)
|
||||
elif simulate:
|
||||
inc count
|
||||
@@ -567,7 +601,7 @@ proc testSpec(r: var TResults, test: TTest, targets: set[TTarget] = {}) =
|
||||
var expected = test.spec
|
||||
if expected.parseErrors.len > 0:
|
||||
# targetC is a lie, but a parameter is required
|
||||
r.addResult(test, targetC, "", "", expected.parseErrors, reInvalidSpec)
|
||||
r.finishTest(test, targetC, "", "", expected.parseErrors, reInvalidSpec)
|
||||
inc(r.total)
|
||||
return
|
||||
|
||||
|
||||
20
testament/tests/shouldfail/tnotenoughretries.nim
Normal file
20
testament/tests/shouldfail/tnotenoughretries.nim
Normal file
@@ -0,0 +1,20 @@
|
||||
discard """
|
||||
retries: 1
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
const tempFile = "tnotenoughretries_temp"
|
||||
|
||||
if not fileExists(tempFile):
|
||||
writeFile(tempFile, "abc")
|
||||
quit(1)
|
||||
else:
|
||||
let content = readFile(tempFile)
|
||||
if content == "abc":
|
||||
writeFile(tempFile, "def")
|
||||
quit(1)
|
||||
else:
|
||||
# success
|
||||
removeFile(tempFile)
|
||||
discard
|
||||
13
tests/ccgbugs/t19585.nim
Normal file
13
tests/ccgbugs/t19585.nim
Normal file
@@ -0,0 +1,13 @@
|
||||
discard """
|
||||
targets: "c cpp"
|
||||
"""
|
||||
|
||||
# bug #19585
|
||||
|
||||
type
|
||||
X* {.exportc.} = object
|
||||
v: int
|
||||
|
||||
{.emit:"""
|
||||
X x = { 1234 };
|
||||
""".}
|
||||
13
tests/ccgbugs/timportc_distinct.nim
Normal file
13
tests/ccgbugs/timportc_distinct.nim
Normal file
@@ -0,0 +1,13 @@
|
||||
discard """
|
||||
ccodecheck: "time_t"
|
||||
joinable: false
|
||||
"""
|
||||
|
||||
type
|
||||
Time* {.importc: "time_t", header: "<time.h>".} = distinct clong
|
||||
|
||||
proc foo =
|
||||
var s: Time = default(Time)
|
||||
discard s
|
||||
|
||||
foo()
|
||||
32
tests/ccgbugs/tunioninit.nim
Normal file
32
tests/ccgbugs/tunioninit.nim
Normal file
@@ -0,0 +1,32 @@
|
||||
# issue #20653
|
||||
|
||||
type
|
||||
EmptySeq* {.bycopy.} = object
|
||||
|
||||
ChoiceWithEmptySeq_d* {.bycopy.} = object
|
||||
a*: bool
|
||||
|
||||
INNER_C_UNION* {.bycopy, union.} = object
|
||||
a*: char
|
||||
b*: EmptySeq
|
||||
c*: byte
|
||||
d*: ChoiceWithEmptySeq_d
|
||||
|
||||
ChoiceWithEmptySeq_selection* = enum
|
||||
ChoiceWithEmptySeq_NONE,
|
||||
ChoiceWithEmptySeq_a_PRESENT,
|
||||
ChoiceWithEmptySeq_b_PRESENT,
|
||||
ChoiceWithEmptySeq_c_PRESENT,
|
||||
ChoiceWithEmptySeq_d_PRESENT
|
||||
|
||||
ChoiceWithEmptySeq* {.bycopy.} = object
|
||||
kind*: ChoiceWithEmptySeq_selection
|
||||
u*: INNER_C_UNION
|
||||
|
||||
Og_Context* {.bycopy.} = object
|
||||
state*: int
|
||||
init_done*: bool
|
||||
ch*: ChoiceWithEmptySeq
|
||||
em*: EmptySeq
|
||||
|
||||
var context* : Og_Context = Og_Context(init_done: false)
|
||||
@@ -16,3 +16,16 @@ block:
|
||||
doAssert s == 2
|
||||
|
||||
foo()
|
||||
|
||||
import std/deques
|
||||
|
||||
block: # bug #24319
|
||||
var queue = initDeque[array[32, byte]]()
|
||||
for i in 0 ..< 5:
|
||||
let element: array[32, byte] = [
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 1,
|
||||
]
|
||||
queue.addLast(element)
|
||||
|
||||
doAssert queue.popLast[^1] == byte(1)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
discard """
|
||||
cmd: '''nim c --newruntime $file'''
|
||||
errormsg: "'=copy' is not available for type <owned Button>; requires a copy because it's not the last read of ':envAlt.b1'; routine: main"
|
||||
errormsg: "'=copy' is not available for type <owned Button>; requires a copy because it's not the last read of ':envAlt.b0'; routine: main"
|
||||
line: 48
|
||||
"""
|
||||
|
||||
|
||||
10
tests/errmsgs/t24258.nim
Normal file
10
tests/errmsgs/t24258.nim
Normal file
@@ -0,0 +1,10 @@
|
||||
discard """
|
||||
cmd: "nim check $file"
|
||||
errormsg: "illformed AST: [22]43.len"
|
||||
joinable: false
|
||||
"""
|
||||
|
||||
template encodeList*(args: varargs[untyped]): seq[byte] =
|
||||
@[byte args.len]
|
||||
|
||||
let x = encodeList([22], 43)
|
||||
@@ -1,3 +1,7 @@
|
||||
discard """
|
||||
retries: 2
|
||||
"""
|
||||
|
||||
# -*- nim -*-
|
||||
|
||||
import os, strutils
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
discard """
|
||||
outputsub: "true"
|
||||
disabled: "32bit"
|
||||
retries: 2
|
||||
"""
|
||||
|
||||
type
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
discard """
|
||||
retries: 2
|
||||
"""
|
||||
|
||||
# Program to detect bug #1796 reliably
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
discard """
|
||||
outputsub: "no leak: "
|
||||
retries: 2
|
||||
"""
|
||||
|
||||
type
|
||||
|
||||
@@ -6,6 +6,7 @@ Hello from thread
|
||||
Hello from thread
|
||||
'''
|
||||
cmd: "nim $target --hints:on --threads:on --tlsEmulation:off $options $file"
|
||||
retries: 2
|
||||
"""
|
||||
# Copied from stdlib
|
||||
import strutils
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
discard """
|
||||
outputsub: "Success!"
|
||||
retries: 2
|
||||
"""
|
||||
|
||||
# This is adapted from a benchmark written by John Ellis and Pete Kovac
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
discard """
|
||||
outputsub: "77\n77"
|
||||
retries: 2
|
||||
"""
|
||||
|
||||
## Check how GC/Alloc works in Emscripten
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
discard """
|
||||
outputsub: "no leak: "
|
||||
retries: 2
|
||||
"""
|
||||
|
||||
when defined(GC_setMaxPause):
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
discard """
|
||||
outputsub: "no leak: "
|
||||
retries: 2
|
||||
"""
|
||||
|
||||
when defined(GC_setMaxPause):
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
discard """
|
||||
outputsub: "no leak: "
|
||||
retries: 2
|
||||
"""
|
||||
|
||||
when defined(GC_setMaxPause):
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
discard """
|
||||
outputsub: "no leak: "
|
||||
retries: 2
|
||||
"""
|
||||
|
||||
type
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
discard """
|
||||
output: "success"
|
||||
retries: 2
|
||||
"""
|
||||
|
||||
import os, times
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
discard """
|
||||
outputsub: "finished"
|
||||
retries: 2
|
||||
"""
|
||||
|
||||
# Test the garbage collector.
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
discard """
|
||||
retries: 2
|
||||
"""
|
||||
|
||||
import std/[cgi, strtabs]
|
||||
|
||||
proc handleRequest(query: string): StringTableRef =
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
discard """
|
||||
outputsub: "no leak: "
|
||||
retries: 2
|
||||
"""
|
||||
|
||||
type
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
discard """
|
||||
outputsub: "no leak: "
|
||||
retries: 2
|
||||
"""
|
||||
|
||||
type
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
discard """
|
||||
joinable: false
|
||||
retries: 2
|
||||
"""
|
||||
|
||||
import std/asyncdispatch
|
||||
|
||||
@@ -8,6 +8,7 @@ Performing Loop Recognition
|
||||
Another 3 iterations...
|
||||
...
|
||||
Found 1 loops (including artificial root node) (3)'''
|
||||
retries: 2
|
||||
"""
|
||||
|
||||
# bug #3184
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
discard """
|
||||
output: '''Success'''
|
||||
retries: 2
|
||||
"""
|
||||
|
||||
# bug #3793
|
||||
|
||||
@@ -3,6 +3,7 @@ discard """
|
||||
10000000
|
||||
10000000
|
||||
10000000'''
|
||||
retries: 2
|
||||
"""
|
||||
|
||||
# bug #17085
|
||||
|
||||
@@ -4,6 +4,7 @@ discard """
|
||||
finalized
|
||||
finalized
|
||||
'''
|
||||
retries: 2
|
||||
"""
|
||||
|
||||
proc finish(o: RootRef) =
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
discard """
|
||||
output: "true"
|
||||
retries: 2
|
||||
"""
|
||||
|
||||
import intsets
|
||||
|
||||
@@ -2,10 +2,17 @@ discard """
|
||||
cmd: "nim check $options --hints:off $file"
|
||||
action: "reject"
|
||||
nimout:'''
|
||||
tpointerprocs.nim(15, 11) Error: 'foo' doesn't have a concrete type, due to unspecified generic parameters.
|
||||
tpointerprocs.nim(27, 11) Error: cannot instantiate: 'foo[int]'; got 1 typeof(s) but expected 2
|
||||
tpointerprocs.nim(27, 14) Error: expression 'foo[int]' has no type (or is ambiguous)
|
||||
tpointerprocs.nim(28, 11) Error: expression 'bar' has no type (or is ambiguous)
|
||||
tpointerprocs.nim(22, 11) Error: 'foo' doesn't have a concrete type, due to unspecified generic parameters.
|
||||
tpointerprocs.nim(34, 14) Error: type mismatch: got <int>
|
||||
but expected one of:
|
||||
proc foo(x: int | float; y: int or string): float
|
||||
first type mismatch at position: 2 in generic parameters
|
||||
missing generic parameter: y:type
|
||||
|
||||
expression: foo[int]
|
||||
tpointerprocs.nim(34, 14) Error: cannot instantiate: 'foo[int]'
|
||||
tpointerprocs.nim(34, 14) Error: expression 'foo[int]' has no type (or is ambiguous)
|
||||
tpointerprocs.nim(35, 11) Error: expression 'bar' has no type (or is ambiguous)
|
||||
'''
|
||||
"""
|
||||
|
||||
@@ -25,4 +32,4 @@ block:
|
||||
proc foo(x: int | float, y: int or string): float = result = 1.0
|
||||
let
|
||||
bar = foo[int]
|
||||
baz = bar
|
||||
baz = bar
|
||||
|
||||
32
tests/iter/tfoldedaddr.nim
Normal file
32
tests/iter/tfoldedaddr.nim
Normal file
@@ -0,0 +1,32 @@
|
||||
discard """
|
||||
output: '''
|
||||
23
|
||||
23
|
||||
23
|
||||
23
|
||||
23
|
||||
23
|
||||
'''
|
||||
"""
|
||||
|
||||
block: # issue #24305
|
||||
iterator demo(a: openArray[int]): int =
|
||||
for k in countUp(a[0], 19):
|
||||
yield 23
|
||||
|
||||
for k in demo(@[17]):
|
||||
echo k
|
||||
|
||||
block: # issue #24305 with array
|
||||
iterator demo(a: array[1, int]): int =
|
||||
for k in countUp(a[0], 19):
|
||||
yield 23
|
||||
|
||||
for k in demo([17]):
|
||||
echo k
|
||||
|
||||
block: # related regression
|
||||
proc main =
|
||||
let a = [0, 1, 2]
|
||||
let x = addr a[low(a)]
|
||||
main()
|
||||
139
tests/iter/tnestedclosures.nim
Normal file
139
tests/iter/tnestedclosures.nim
Normal file
@@ -0,0 +1,139 @@
|
||||
discard """
|
||||
targets: "c"
|
||||
output: '''
|
||||
Test 1:
|
||||
12
|
||||
Test 2:
|
||||
23
|
||||
23
|
||||
Test 3:
|
||||
34
|
||||
34
|
||||
Test 4:
|
||||
45
|
||||
45
|
||||
50
|
||||
50
|
||||
Test 5:
|
||||
45
|
||||
123
|
||||
47
|
||||
50
|
||||
Test 6:
|
||||
<hi>
|
||||
Test 7:
|
||||
0
|
||||
1
|
||||
2
|
||||
'''
|
||||
"""
|
||||
|
||||
block: #24094
|
||||
echo "Test 1:"
|
||||
proc foo() =
|
||||
let x = 12
|
||||
iterator bar2(): int {.closure.} =
|
||||
yield x
|
||||
proc bar() =
|
||||
let z = bar2
|
||||
for y in z(): # just doing bar2() gives param not in env: x
|
||||
echo y
|
||||
bar()
|
||||
|
||||
foo()
|
||||
|
||||
block: #24094
|
||||
echo "Test 2:"
|
||||
iterator foo(): int {.closure.} =
|
||||
let x = 23
|
||||
iterator bar2(): int {.closure.} =
|
||||
yield x
|
||||
proc bar() =
|
||||
let z = bar2
|
||||
for y in z():
|
||||
echo y
|
||||
bar()
|
||||
yield x
|
||||
|
||||
for x in foo(): echo x
|
||||
|
||||
block: #24094
|
||||
echo "Test 3:"
|
||||
iterator foo(): int {.closure.} =
|
||||
let x = 34
|
||||
proc bar() =
|
||||
echo x
|
||||
iterator bar2(): int {.closure.} =
|
||||
bar()
|
||||
yield x
|
||||
for y in bar2():
|
||||
yield y
|
||||
|
||||
for x in foo(): echo x
|
||||
|
||||
block:
|
||||
echo "Test 4:"
|
||||
proc foo() =
|
||||
var x = 45
|
||||
iterator bar2(): int {.closure.} =
|
||||
yield x
|
||||
yield x + 3
|
||||
|
||||
let b1 = bar2
|
||||
let b2 = bar2
|
||||
echo b1()
|
||||
echo b2()
|
||||
x = 47
|
||||
echo b1()
|
||||
echo b2()
|
||||
foo()
|
||||
|
||||
block:
|
||||
echo "Test 5:"
|
||||
proc foo() =
|
||||
var x = 45
|
||||
iterator bar2(): int {.closure.} =
|
||||
yield x
|
||||
yield x + 3
|
||||
|
||||
proc bar() =
|
||||
var y = 123
|
||||
iterator bar3(): int {.closure.} =
|
||||
yield x
|
||||
yield y
|
||||
let b3 = bar3
|
||||
for z in b3():
|
||||
echo z
|
||||
x = 47
|
||||
let b2 = bar2
|
||||
for z in b2():
|
||||
echo z
|
||||
bar()
|
||||
foo()
|
||||
|
||||
block: #19154
|
||||
echo "Test 6:"
|
||||
proc test(s: string): proc(): iterator(): string =
|
||||
iterator it(): string = yield s
|
||||
proc f(): iterator(): string = it
|
||||
return f
|
||||
|
||||
let it = test("hi")()
|
||||
for s in it():
|
||||
echo "<", s, ">"
|
||||
|
||||
block: #3824
|
||||
echo "Test 7:"
|
||||
proc main =
|
||||
iterator factory(): int {.closure.} =
|
||||
iterator bar(): int {.closure.} =
|
||||
yield 0
|
||||
yield 1
|
||||
yield 2
|
||||
|
||||
for x in bar(): yield x
|
||||
|
||||
for x in factory():
|
||||
echo x
|
||||
|
||||
main()
|
||||
@@ -1,5 +1,5 @@
|
||||
discard """
|
||||
matrix: "; --experimental:strictdefs; -d:nimOptIters"
|
||||
matrix: "; --experimental:strictdefs"
|
||||
targets: "c cpp"
|
||||
"""
|
||||
|
||||
@@ -505,7 +505,7 @@ block: # void iterator
|
||||
discard
|
||||
var a = it
|
||||
|
||||
if defined(nimOptIters): # Locals present in only 1 state should be on the stack
|
||||
block: # Locals present in only 1 state should be on the stack
|
||||
proc checkOnStack(a: pointer, shouldBeOnStack: bool) =
|
||||
# Quick and dirty way to check if a points to stack
|
||||
var dummy = 0
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user