mirror of
https://github.com/nim-lang/Nim.git
synced 2026-08-31 19:03:42 +00:00
Compare commits
7 Commits
pr_oi
...
pr_when_ty
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fbec8cd8d6 | ||
|
|
f4cd77c318 | ||
|
|
5059bb40e5 | ||
|
|
790df938d7 | ||
|
|
7867200135 | ||
|
|
d05e936732 | ||
|
|
2a8e4dd977 |
@@ -341,9 +341,9 @@ proc genCppParamsForCtor(p: BProc; call: PNode; didGenTemp: var bool): Snippet =
|
||||
call[i][0]
|
||||
else:
|
||||
call[i]
|
||||
if not param.typ.isCompileTimeOnly and (param.kind != nkBracketExpr or param.typ.kind in
|
||||
if param.kind != nkBracketExpr or param.typ.kind in
|
||||
{tyRef, tyPtr, tyUncheckedArray, tyArray, tyOpenArray,
|
||||
tyVarargs, tySequence, tyString, tyCstring, tyTuple}):
|
||||
tyVarargs, tySequence, tyString, tyCstring, tyTuple}:
|
||||
let tempLoc = initLocExprSingleUse(p, param)
|
||||
didGenTemp = didGenTemp or tempLoc.k == locTemp
|
||||
genOtherArg(p, call, i, typ, res, argBuilder)
|
||||
|
||||
@@ -454,6 +454,26 @@ proc resetSemFlag(n: PNode) =
|
||||
for i in 0..<n.safeLen:
|
||||
resetSemFlag(n[i])
|
||||
|
||||
proc normalizeTypedescMacroResult(c: PContext, n: PNode): PNode =
|
||||
result = n
|
||||
if result.kind == nkStmtList:
|
||||
result.transitionSonsKind(nkStmtListType)
|
||||
|
||||
const maxTypedescMacroNormalizationPasses = 32
|
||||
# Resolve surviving compile-time branches so later passes don't walk
|
||||
# unevaluated type AST for a typedesc expression.
|
||||
for _ in 0..<maxTypedescMacroNormalizationPasses:
|
||||
if result.kind == nkWhenStmt:
|
||||
result = semWhen(c, result, false)
|
||||
if result.kind == nkStmtList:
|
||||
result.transitionSonsKind(nkStmtListType)
|
||||
elif result.kind == nkStmtListType and result.len > 0 and result[^1].kind == nkWhenStmt:
|
||||
result[^1] = semWhen(c, result[^1], false)
|
||||
if result[^1].kind == nkStmtList:
|
||||
result[^1].transitionSonsKind(nkStmtListType)
|
||||
else:
|
||||
break
|
||||
|
||||
proc semAfterMacroCall(c: PContext, call, macroResult: PNode,
|
||||
s: PSym, flags: TExprFlags; expectedType: PType = nil): PNode =
|
||||
## Semantically check the output of a macro.
|
||||
@@ -484,7 +504,7 @@ proc semAfterMacroCall(c: PContext, call, macroResult: PNode,
|
||||
# More restrictive version.
|
||||
result = semExprWithType(c, result, flags, expectedType)
|
||||
of tyTypeDesc:
|
||||
if result.kind == nkStmtList: result.transitionSonsKind(nkStmtListType)
|
||||
result = normalizeTypedescMacroResult(c, result)
|
||||
var typ = semTypeNode(c, result, nil)
|
||||
if typ == nil:
|
||||
localError(c.config, result.info, "expression has no type: " &
|
||||
@@ -492,7 +512,7 @@ proc semAfterMacroCall(c: PContext, call, macroResult: PNode,
|
||||
result = newSymNode(errorSym(c, result))
|
||||
else:
|
||||
result.typ = makeTypeDesc(c, typ)
|
||||
#result = symNodeFromType(c, typ, n.info)
|
||||
#result = symNodeFromType(c, typ, n.info)
|
||||
else:
|
||||
if s.ast[genericParamsPos] != nil and retType.isMetaType:
|
||||
# The return type may depend on the Macro arguments
|
||||
|
||||
@@ -90,20 +90,11 @@ proc getCurrOwner(c: PTransf): PSym =
|
||||
if c.transCon != nil: result = c.transCon.owner
|
||||
else: result = c.module
|
||||
|
||||
proc freshOwnedSym(c: PTransf; s, owner: PSym): PNode =
|
||||
# We need to copy the symbol here because we might need to change its owner and
|
||||
# we don't want to mess with the original symbol which might be used in other places.
|
||||
# This can happen for example for iterators which are transformed multiple times when
|
||||
# they are used in different contexts.
|
||||
var fresh = copySym(s, c.idgen)
|
||||
incl(fresh.flagsImpl, sfFromGeneric)
|
||||
setOwner(fresh, owner)
|
||||
result = newSymNode(fresh)
|
||||
|
||||
proc newTemp(c: PTransf, typ: PType, info: TLineInfo): PNode =
|
||||
let r = newSym(skTemp, getIdent(c.graph.cache, genPrefix), c.idgen, getCurrOwner(c), info)
|
||||
r.typ = typ #skipTypes(typ, {tyGenericInst, tyAlias, tySink})
|
||||
incl(r.flagsImpl, sfFromGeneric)
|
||||
let owner = getCurrOwner(c)
|
||||
result = newSymNode(r)
|
||||
|
||||
proc transform(c: PTransf, n: PNode, noConstFold = false): PNode
|
||||
@@ -194,39 +185,11 @@ proc transformSym(c: PTransf, n: PNode): PNode =
|
||||
result = transformSymAux(c, n)
|
||||
|
||||
proc freshVar(c: PTransf; v: PSym): PNode =
|
||||
result = freshOwnedSym(c, v, getCurrOwner(c))
|
||||
|
||||
proc introduceNewRoutineHeaderSyms(c: PTransf; n: PNode; oldOwner, newOwner: PSym) =
|
||||
# We need to introduce new symbols for the parameters and result of a routine when
|
||||
# we copy it for inlining or closure generation.
|
||||
# Otherwise, we would have multiple nodes referring to the same parameter symbols which
|
||||
# can lead to problems when we need to change the owner of these symbols.
|
||||
case n.kind
|
||||
of nkSym:
|
||||
if n.sym.owner == oldOwner:
|
||||
c.transCon.mapping[n.sym.itemId] = freshOwnedSym(c, n.sym, newOwner)
|
||||
of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit:
|
||||
discard
|
||||
else:
|
||||
for i in 0..<n.len:
|
||||
introduceNewRoutineHeaderSyms(c, n[i], oldOwner, newOwner)
|
||||
|
||||
proc copyRoutineTypeHeader(c: PTransf; oldProc, newProc: PSym) =
|
||||
# We need to copy the routine type header to ensure that
|
||||
# modifications to the newProc do not affect the oldProc.
|
||||
if oldProc.typ != nil and oldProc.typ.kind == tyProc and oldProc.typ.n != nil:
|
||||
newProc.typ = copyType(oldProc.typ, c.idgen, newProc)
|
||||
newProc.typ.n = newNodeI(oldProc.typ.n.kind, oldProc.typ.n.info)
|
||||
if oldProc.typ.n.len > 0:
|
||||
newProc.typ.n.add copyNode(oldProc.typ.n[0])
|
||||
for i in 1..<oldProc.typ.n.len:
|
||||
let oldParam = oldProc.typ.n[i].sym
|
||||
var newParam = getOrDefault(c.transCon.mapping, oldParam.itemId)
|
||||
if newParam == nil:
|
||||
newParam = freshOwnedSym(c, oldParam, newProc)
|
||||
c.transCon.mapping[oldParam.itemId] = newParam
|
||||
doAssert newParam.kind == nkSym
|
||||
newProc.typ.addParam newParam.sym
|
||||
let owner = getCurrOwner(c)
|
||||
var newVar = copySym(v, c.idgen)
|
||||
incl(newVar.flagsImpl, sfFromGeneric)
|
||||
setOwner(newVar, owner)
|
||||
result = newSymNode(newVar)
|
||||
|
||||
proc transformVarSection(c: PTransf, v: PNode): PNode =
|
||||
result = newTransNode(v)
|
||||
@@ -375,13 +338,8 @@ proc introduceNewLocalVars(c: PTransf, n: PNode): PNode =
|
||||
return n
|
||||
of nkLambdaKinds, nkProcDef, nkFuncDef, nkMethodDef, nkConverterDef: # todo optimize nosideeffects?
|
||||
result = newTransNode(n)
|
||||
let oldProc = n[namePos].sym
|
||||
let x = freshOwnedSym(c, oldProc, oldProc.owner)
|
||||
c.transCon.mapping[oldProc.itemId] = x
|
||||
introduceNewRoutineHeaderSyms(c, n[paramsPos], oldProc, x.sym)
|
||||
if resultPos < n.len and n[resultPos] != nil:
|
||||
introduceNewRoutineHeaderSyms(c, n[resultPos], oldProc, x.sym)
|
||||
copyRoutineTypeHeader(c, oldProc, x.sym)
|
||||
let x = newSymNode(copySym(n[namePos].sym, c.idgen))
|
||||
c.transCon.mapping[n[namePos].sym.itemId] = x
|
||||
result[namePos] = x # we have to copy proc definitions for iters
|
||||
for i in 1..<n.len:
|
||||
result[i] = introduceNewLocalVars(c, n[i])
|
||||
|
||||
@@ -465,24 +465,4 @@ block: # bug #25724
|
||||
else: yield 1
|
||||
for w in c():
|
||||
let n = w
|
||||
(proc() = discard n)()
|
||||
|
||||
block:
|
||||
iterator c(): int =
|
||||
yield 1
|
||||
yield 1
|
||||
|
||||
for w in c():
|
||||
proc p(s: int) =
|
||||
let sap = s
|
||||
p(0)
|
||||
|
||||
block: # bug #25725
|
||||
iterator c(): int =
|
||||
when nimvm: yield 0
|
||||
else: yield 1
|
||||
for w in c():
|
||||
let n = w
|
||||
proc p(s: int) =
|
||||
let s = s; discard n
|
||||
p(0)
|
||||
(proc() = discard n)()
|
||||
@@ -45,3 +45,12 @@ elif compiles(nonexistent):
|
||||
else:
|
||||
output("whenElse")
|
||||
|
||||
|
||||
template test(): typedesc =
|
||||
when true:
|
||||
int
|
||||
else:
|
||||
bool
|
||||
|
||||
const c = default(test())
|
||||
echo c
|
||||
|
||||
Reference in New Issue
Block a user