mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-28 17:04:41 +00:00
@@ -211,8 +211,7 @@ type
|
||||
nkDistinctTy, # distinct type
|
||||
nkProcTy, # proc type
|
||||
nkIteratorTy, # iterator type
|
||||
nkSharedTy, # 'shared T'
|
||||
# we use 'nkPostFix' for the 'not nil' addition
|
||||
nkSinkAsgn, # '=sink(x, y)'
|
||||
nkEnumTy, # enum body
|
||||
nkEnumFieldDef, # `ident = expr` in an enumeration
|
||||
nkArgList, # argument list
|
||||
|
||||
@@ -335,7 +335,7 @@ proc getPotentialWrites(n: PNode; mutate: bool; result: var seq[PNode]) =
|
||||
of nkLiterals, nkIdent, nkFormalParams: discard
|
||||
of nkSym:
|
||||
if mutate: result.add n
|
||||
of nkAsgn, nkFastAsgn:
|
||||
of nkAsgn, nkFastAsgn, nkSinkAsgn:
|
||||
getPotentialWrites(n[0], true, result)
|
||||
getPotentialWrites(n[1], mutate, result)
|
||||
of nkAddr, nkHiddenAddr:
|
||||
|
||||
@@ -3086,7 +3086,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
|
||||
cow(p, n[1])
|
||||
if nfPreventCg notin n.flags:
|
||||
genAsgn(p, n, fastAsgn=false)
|
||||
of nkFastAsgn:
|
||||
of nkFastAsgn, nkSinkAsgn:
|
||||
cow(p, n[1])
|
||||
if nfPreventCg notin n.flags:
|
||||
# transf is overly aggressive with 'nkFastAsgn', so we work around here.
|
||||
|
||||
@@ -926,7 +926,7 @@ proc easyResultAsgn(n: PNode): PNode =
|
||||
var i = 0
|
||||
while i < n.len and n[i].kind in harmless: inc i
|
||||
if i < n.len: result = easyResultAsgn(n[i])
|
||||
of nkAsgn, nkFastAsgn:
|
||||
of nkAsgn, nkFastAsgn, nkSinkAsgn:
|
||||
if n[0].kind == nkSym and n[0].sym.kind == skResult and not containsResult(n[1]):
|
||||
incl n.flags, nfPreventCg
|
||||
return n[1]
|
||||
@@ -968,7 +968,7 @@ proc allPathsAsgnResult(n: PNode): InitResultEnum =
|
||||
for it in n:
|
||||
result = allPathsAsgnResult(it)
|
||||
if result != Unknown: return result
|
||||
of nkAsgn, nkFastAsgn:
|
||||
of nkAsgn, nkFastAsgn, nkSinkAsgn:
|
||||
if n[0].kind == nkSym and n[0].sym.kind == skResult:
|
||||
if not containsResult(n[1]): result = InitSkippable
|
||||
else: result = InitRequired
|
||||
|
||||
@@ -718,7 +718,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
|
||||
n[^1] = ex
|
||||
result.add(n)
|
||||
|
||||
of nkAsgn, nkFastAsgn:
|
||||
of nkAsgn, nkFastAsgn, nkSinkAsgn:
|
||||
var ns = false
|
||||
for i in 0..<n.len:
|
||||
n[i] = ctx.lowerStmtListExprs(n[i], ns)
|
||||
@@ -868,7 +868,7 @@ proc transformReturnsInTry(ctx: var Ctx, n: PNode): PNode =
|
||||
if n[0].kind != nkEmpty:
|
||||
let asgnTmpResult = newNodeI(nkAsgn, n.info)
|
||||
asgnTmpResult.add(ctx.newTmpResultAccess())
|
||||
let x = if n[0].kind in {nkAsgn, nkFastAsgn}: n[0][1] else: n[0]
|
||||
let x = if n[0].kind in {nkAsgn, nkFastAsgn, nkSinkAsgn}: n[0][1] else: n[0]
|
||||
asgnTmpResult.add(x)
|
||||
result.add(asgnTmpResult)
|
||||
|
||||
|
||||
@@ -433,7 +433,7 @@ proc gen(c: var Con; n: PNode) =
|
||||
else:
|
||||
genCall(c, n)
|
||||
of nkCharLit..nkNilLit: discard
|
||||
of nkAsgn, nkFastAsgn:
|
||||
of nkAsgn, nkFastAsgn, nkSinkAsgn:
|
||||
gen(c, n[1])
|
||||
|
||||
if n[0].kind in PathKinds0:
|
||||
|
||||
@@ -400,7 +400,7 @@ proc genRecCommentAux(d: PDoc, n: PNode): PRstNode =
|
||||
result = genComment(d, n)
|
||||
if result == nil:
|
||||
if n.kind in {nkStmtList, nkStmtListExpr, nkTypeDef, nkConstDef,
|
||||
nkObjectTy, nkRefTy, nkPtrTy, nkAsgn, nkFastAsgn, nkHiddenStdConv}:
|
||||
nkObjectTy, nkRefTy, nkPtrTy, nkAsgn, nkFastAsgn, nkSinkAsgn, nkHiddenStdConv}:
|
||||
# notin {nkEmpty..nkNilLit, nkEnumTy, nkTupleTy}:
|
||||
for i in 0..<n.len:
|
||||
result = genRecCommentAux(d, n[i])
|
||||
@@ -1551,7 +1551,7 @@ proc genSection(d: PDoc, kind: TSymKind, groupedToc = false) =
|
||||
else:
|
||||
# Just have the link
|
||||
d.toc[kind] = getConfigVar(d.conf, "doc.section.toc_item") % sectionValues
|
||||
|
||||
|
||||
proc relLink(outDir: AbsoluteDir, destFile: AbsoluteFile, linkto: RelativeFile): string =
|
||||
$relativeTo(outDir / linkto, destFile.splitFile().dir, '/')
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ proc hlo(c: PContext, n: PNode): PNode =
|
||||
# already processed (special cases in semstmts.nim)
|
||||
result = n
|
||||
else:
|
||||
if n.kind in {nkFastAsgn, nkAsgn, nkIdentDefs, nkVarTuple} and
|
||||
if n.kind in {nkFastAsgn, nkAsgn, nkSinkAsgn, nkIdentDefs, nkVarTuple} and
|
||||
n[0].kind == nkSym and
|
||||
{sfGlobal, sfPure} * n[0].sym.flags == {sfGlobal, sfPure}:
|
||||
# do not optimize 'var g {.global} = re(...)' again!
|
||||
|
||||
@@ -78,7 +78,12 @@ proc nestedScope(parent: var Scope; body: PNode): Scope =
|
||||
Scope(vars: @[], locals: @[], wasMoved: @[], final: @[], body: body, needsTry: false, parent: addr(parent))
|
||||
|
||||
proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode; tmpFlags = {sfSingleUsedTemp}): PNode
|
||||
proc moveOrCopy(dest, ri: PNode; c: var Con; s: var Scope; isDecl = false): PNode
|
||||
|
||||
type
|
||||
MoveOrCopyFlag = enum
|
||||
IsDecl, IsExplicitSink
|
||||
|
||||
proc moveOrCopy(dest, ri: PNode; c: var Con; s: var Scope; flags: set[MoveOrCopyFlag] = {}): PNode
|
||||
|
||||
when false:
|
||||
var
|
||||
@@ -243,8 +248,8 @@ proc canBeMoved(c: Con; t: PType): bool {.inline.} =
|
||||
proc isNoInit(dest: PNode): bool {.inline.} =
|
||||
result = dest.kind == nkSym and sfNoInit in dest.sym.flags
|
||||
|
||||
proc genSink(c: var Con; dest, ri: PNode, isDecl = false): PNode =
|
||||
if (c.inLoopCond == 0 and (isUnpackedTuple(dest) or isDecl or
|
||||
proc genSink(c: var Con; dest, ri: PNode; flags: set[MoveOrCopyFlag] = {}): PNode =
|
||||
if (c.inLoopCond == 0 and (isUnpackedTuple(dest) or IsDecl in flags or
|
||||
(isAnalysableFieldAccess(dest, c.owner) and isFirstWrite(dest, c)))) or
|
||||
isNoInit(dest):
|
||||
# optimize sink call into a bitwise memcopy
|
||||
@@ -296,17 +301,21 @@ proc genMarkCyclic(c: var Con; result, dest: PNode) =
|
||||
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): PNode =
|
||||
proc genCopyNoCheck(c: var Con; dest, ri: PNode; a: TTypeAttachedOp): PNode =
|
||||
let t = dest.typ.skipTypes({tyGenericInst, tyAlias, tySink})
|
||||
result = c.genOp(t, attachedAsgn, dest, ri)
|
||||
result = c.genOp(t, a, dest, ri)
|
||||
assert ri.typ != nil
|
||||
|
||||
proc genCopy(c: var Con; dest, ri: PNode): PNode =
|
||||
proc genCopy(c: var Con; dest, ri: PNode; flags: set[MoveOrCopyFlag]): PNode =
|
||||
let t = dest.typ
|
||||
if tfHasOwned in t.flags and ri.kind != nkNilLit:
|
||||
# try to improve the error message here:
|
||||
c.checkForErrorPragma(t, ri, "=copy")
|
||||
result = c.genCopyNoCheck(dest, ri)
|
||||
if IsExplicitSink in flags:
|
||||
c.checkForErrorPragma(t, ri, "=sink")
|
||||
else:
|
||||
c.checkForErrorPragma(t, ri, "=copy")
|
||||
let a = if IsExplicitSink in flags: attachedSink else: attachedAsgn
|
||||
result = c.genCopyNoCheck(dest, ri, a)
|
||||
assert ri.typ != nil
|
||||
|
||||
proc genDiscriminantAsgn(c: var Con; s: var Scope; n: PNode): PNode =
|
||||
@@ -391,7 +400,7 @@ proc passCopyToSink(n: PNode; c: var Con; s: var Scope): PNode =
|
||||
let tmp = c.getTemp(s, n.typ, n.info)
|
||||
if hasDestructor(c, n.typ):
|
||||
result.add c.genWasMoved(tmp)
|
||||
var m = c.genCopy(tmp, n)
|
||||
var m = c.genCopy(tmp, n, {})
|
||||
m.add p(n, c, s, normal)
|
||||
c.finishCopy(m, n, isFromSink = true)
|
||||
result.add m
|
||||
@@ -436,7 +445,7 @@ proc ensureDestruction(arg, orig: PNode; c: var Con; s: var Scope): PNode =
|
||||
# This was already done in the sink parameter handling logic.
|
||||
result = newNodeIT(nkStmtListExpr, arg.info, arg.typ)
|
||||
let tmp = c.getTemp(s, arg.typ, arg.info)
|
||||
result.add c.genSink(tmp, arg, isDecl = true)
|
||||
result.add c.genSink(tmp, arg, {IsDecl})
|
||||
result.add tmp
|
||||
s.final.add c.genDestroy(tmp)
|
||||
else:
|
||||
@@ -518,7 +527,7 @@ template processScopeExpr(c: var Con; s: var Scope; ret: PNode, processCall: unt
|
||||
tmp.sym.flags = tmpFlags
|
||||
let cpy = if hasDestructor(c, ret.typ):
|
||||
s.parent[].final.add c.genDestroy(tmp)
|
||||
moveOrCopy(tmp, ret, c, s, isDecl = true)
|
||||
moveOrCopy(tmp, ret, c, s, {IsDecl})
|
||||
else:
|
||||
newTree(nkFastAsgn, tmp, p(ret, c, s, normal))
|
||||
|
||||
@@ -654,7 +663,7 @@ proc pRaiseStmt(n: PNode, c: var Con; s: var Scope): PNode =
|
||||
result.add call
|
||||
else:
|
||||
let tmp = c.getTemp(s, n[0].typ, n.info)
|
||||
var m = c.genCopyNoCheck(tmp, n[0])
|
||||
var m = c.genCopyNoCheck(tmp, n[0], attachedAsgn)
|
||||
m.add p(n[0], c, s, normal)
|
||||
c.finishCopy(m, n[0], isFromSink = false)
|
||||
result = newTree(nkStmtList, c.genWasMoved(tmp), m)
|
||||
@@ -818,9 +827,9 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode; tmpFlags = {sfSing
|
||||
s.locals.add v.sym
|
||||
pVarTopLevel(v, c, s, result)
|
||||
if ri.kind != nkEmpty:
|
||||
result.add moveOrCopy(v, ri, c, s, isDecl = v.kind == nkSym)
|
||||
result.add moveOrCopy(v, ri, c, s, if v.kind == nkSym: {IsDecl} else: {})
|
||||
elif ri.kind == nkEmpty and c.inLoop > 0:
|
||||
result.add moveOrCopy(v, genDefaultCall(v.typ, c, v.info), c, s, isDecl = v.kind == nkSym)
|
||||
result.add moveOrCopy(v, genDefaultCall(v.typ, c, v.info), c, s, if v.kind == nkSym: {IsDecl} else: {})
|
||||
else: # keep the var but transform 'ri':
|
||||
var v = copyNode(n)
|
||||
var itCopy = copyNode(it)
|
||||
@@ -833,12 +842,13 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode; tmpFlags = {sfSing
|
||||
itCopy.add p(it[^1], c, s, normal, tmpFlags = flags)
|
||||
v.add itCopy
|
||||
result.add v
|
||||
of nkAsgn, nkFastAsgn:
|
||||
of nkAsgn, nkFastAsgn, nkSinkAsgn:
|
||||
if hasDestructor(c, n[0].typ) and n[1].kind notin {nkProcDef, nkDo, nkLambda}:
|
||||
if n[0].kind in {nkDotExpr, nkCheckedFieldExpr}:
|
||||
cycleCheck(n, c)
|
||||
assert n[1].kind notin {nkAsgn, nkFastAsgn}
|
||||
result = moveOrCopy(p(n[0], c, s, mode), n[1], c, s)
|
||||
assert n[1].kind notin {nkAsgn, nkFastAsgn, nkSinkAsgn}
|
||||
let flags = if n.kind == nkSinkAsgn: {IsExplicitSink} else: {}
|
||||
result = moveOrCopy(p(n[0], c, s, mode), n[1], c, s, flags)
|
||||
elif isDiscriminantField(n[0]):
|
||||
result = c.genDiscriminantAsgn(s, n)
|
||||
else:
|
||||
@@ -963,7 +973,7 @@ proc sameLocation*(a, b: PNode): bool =
|
||||
of nkHiddenStdConv, nkHiddenSubConv: sameLocation(a[1], b)
|
||||
else: false
|
||||
|
||||
proc genFieldAccessSideEffects(c: var Con; dest, ri: PNode, isDecl: bool): PNode =
|
||||
proc genFieldAccessSideEffects(c: var Con; dest, ri: PNode; flags: set[MoveOrCopyFlag] = {}): PNode =
|
||||
# with side effects
|
||||
var temp = newSym(skLet, getIdent(c.graph.cache, "bracketTmp"), nextSymId c.idgen, c.owner, ri[1].info)
|
||||
temp.typ = ri[1].typ
|
||||
@@ -980,17 +990,17 @@ proc genFieldAccessSideEffects(c: var Con; dest, ri: PNode, isDecl: bool): PNode
|
||||
newAccess.add ri[0]
|
||||
newAccess.add tempAsNode
|
||||
|
||||
var snk = c.genSink(dest, newAccess, isDecl)
|
||||
var snk = c.genSink(dest, newAccess, flags)
|
||||
result = newTree(nkStmtList, v, snk, c.genWasMoved(newAccess))
|
||||
|
||||
proc moveOrCopy(dest, ri: PNode; c: var Con; s: var Scope, isDecl = false): PNode =
|
||||
proc moveOrCopy(dest, ri: PNode; c: var Con; s: var Scope, flags: set[MoveOrCopyFlag] = {}): PNode =
|
||||
if sameLocation(dest, ri):
|
||||
# rule (self-assignment-removal):
|
||||
result = newNodeI(nkEmpty, dest.info)
|
||||
elif isCursor(dest):
|
||||
case ri.kind:
|
||||
of nkStmtListExpr, nkBlockExpr, nkIfExpr, nkCaseStmt, nkTryStmt:
|
||||
template process(child, s): untyped = moveOrCopy(dest, child, c, s, isDecl)
|
||||
template process(child, s): untyped = moveOrCopy(dest, child, c, s, flags)
|
||||
# We know the result will be a stmt so we use that fact to optimize
|
||||
handleNestedTempl(ri, process, willProduceStmt = true)
|
||||
else:
|
||||
@@ -998,53 +1008,53 @@ proc moveOrCopy(dest, ri: PNode; c: var Con; s: var Scope, isDecl = false): PNod
|
||||
else:
|
||||
case ri.kind
|
||||
of nkCallKinds:
|
||||
result = c.genSink(dest, p(ri, c, s, consumed), isDecl)
|
||||
result = c.genSink(dest, p(ri, c, s, consumed), flags)
|
||||
of nkBracketExpr:
|
||||
if isUnpackedTuple(ri[0]):
|
||||
# unpacking of tuple: take over the elements
|
||||
result = c.genSink(dest, p(ri, c, s, consumed), isDecl)
|
||||
result = c.genSink(dest, p(ri, c, s, consumed), flags)
|
||||
elif isAnalysableFieldAccess(ri, c.owner) and isLastRead(ri, c, s):
|
||||
if aliases(dest, ri) == no:
|
||||
# Rule 3: `=sink`(x, z); wasMoved(z)
|
||||
if isAtom(ri[1]):
|
||||
var snk = c.genSink(dest, ri, isDecl)
|
||||
var snk = c.genSink(dest, ri, flags)
|
||||
result = newTree(nkStmtList, snk, c.genWasMoved(ri))
|
||||
else:
|
||||
result = genFieldAccessSideEffects(c, dest, ri, isDecl)
|
||||
result = genFieldAccessSideEffects(c, dest, ri, flags)
|
||||
else:
|
||||
result = c.genSink(dest, destructiveMoveVar(ri, c, s), isDecl)
|
||||
result = c.genSink(dest, destructiveMoveVar(ri, c, s), flags)
|
||||
else:
|
||||
result = c.genCopy(dest, ri)
|
||||
result = c.genCopy(dest, ri, flags)
|
||||
result.add p(ri, c, s, consumed)
|
||||
c.finishCopy(result, dest, isFromSink = false)
|
||||
of nkBracket:
|
||||
# array constructor
|
||||
if ri.len > 0 and isDangerousSeq(ri.typ):
|
||||
result = c.genCopy(dest, ri)
|
||||
result = c.genCopy(dest, ri, flags)
|
||||
result.add p(ri, c, s, consumed)
|
||||
c.finishCopy(result, dest, isFromSink = false)
|
||||
else:
|
||||
result = c.genSink(dest, p(ri, c, s, consumed), isDecl)
|
||||
result = c.genSink(dest, p(ri, c, s, consumed), flags)
|
||||
of nkObjConstr, nkTupleConstr, nkClosure, nkCharLit..nkNilLit:
|
||||
result = c.genSink(dest, p(ri, c, s, consumed), isDecl)
|
||||
result = c.genSink(dest, p(ri, c, s, consumed), flags)
|
||||
of nkSym:
|
||||
if isSinkParam(ri.sym) and isLastRead(ri, c, s):
|
||||
# Rule 3: `=sink`(x, z); wasMoved(z)
|
||||
let snk = c.genSink(dest, ri, isDecl)
|
||||
let snk = c.genSink(dest, ri, flags)
|
||||
result = newTree(nkStmtList, snk, c.genWasMoved(ri))
|
||||
elif ri.sym.kind != skParam and ri.sym.owner == c.owner and
|
||||
isLastRead(ri, c, s) and canBeMoved(c, dest.typ) and not isCursor(ri):
|
||||
# Rule 3: `=sink`(x, z); wasMoved(z)
|
||||
let snk = c.genSink(dest, ri, isDecl)
|
||||
let snk = c.genSink(dest, ri, flags)
|
||||
result = newTree(nkStmtList, snk, c.genWasMoved(ri))
|
||||
else:
|
||||
result = c.genCopy(dest, ri)
|
||||
result = c.genCopy(dest, ri, flags)
|
||||
result.add p(ri, c, s, consumed)
|
||||
c.finishCopy(result, dest, isFromSink = false)
|
||||
of nkHiddenSubConv, nkHiddenStdConv, nkConv, nkObjDownConv, nkObjUpConv, nkCast:
|
||||
result = c.genSink(dest, p(ri, c, s, sinkArg), isDecl)
|
||||
result = c.genSink(dest, p(ri, c, s, sinkArg), flags)
|
||||
of nkStmtListExpr, nkBlockExpr, nkIfExpr, nkCaseStmt, nkTryStmt:
|
||||
template process(child, s): untyped = moveOrCopy(dest, child, c, s, isDecl)
|
||||
template process(child, s): untyped = moveOrCopy(dest, child, c, s, flags)
|
||||
# We know the result will be a stmt so we use that fact to optimize
|
||||
handleNestedTempl(ri, process, willProduceStmt = true)
|
||||
of nkRaiseStmt:
|
||||
@@ -1053,10 +1063,10 @@ proc moveOrCopy(dest, ri: PNode; c: var Con; s: var Scope, isDecl = false): PNod
|
||||
if isAnalysableFieldAccess(ri, c.owner) and isLastRead(ri, c, s) and
|
||||
canBeMoved(c, dest.typ):
|
||||
# Rule 3: `=sink`(x, z); wasMoved(z)
|
||||
let snk = c.genSink(dest, ri, isDecl)
|
||||
let snk = c.genSink(dest, ri, flags)
|
||||
result = newTree(nkStmtList, snk, c.genWasMoved(ri))
|
||||
else:
|
||||
result = c.genCopy(dest, ri)
|
||||
result = c.genCopy(dest, ri, flags)
|
||||
result.add p(ri, c, s, consumed)
|
||||
c.finishCopy(result, dest, isFromSink = false)
|
||||
|
||||
|
||||
@@ -2711,7 +2711,7 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
|
||||
of nkReturnStmt: genReturnStmt(p, n)
|
||||
of nkBreakStmt: genBreakStmt(p, n)
|
||||
of nkAsgn: genAsgn(p, n)
|
||||
of nkFastAsgn: genFastAsgn(p, n)
|
||||
of nkFastAsgn, nkSinkAsgn: genFastAsgn(p, n)
|
||||
of nkDiscardStmt:
|
||||
if n[0].kind != nkEmpty:
|
||||
genLineDir(p, n)
|
||||
|
||||
@@ -782,7 +782,7 @@ proc liftCapturedVars(n: PNode; owner: PSym; d: var DetectionPass;
|
||||
n[1] = liftCapturedVars(n[1], owner, d, c)
|
||||
if n[1].kind == nkClosure: result = n[1]
|
||||
of nkReturnStmt:
|
||||
if n[0].kind in {nkAsgn, nkFastAsgn}:
|
||||
if n[0].kind in {nkAsgn, nkFastAsgn, nkSinkAsgn}:
|
||||
# we have a `result = result` expression produced by the closure
|
||||
# transform, let's not touch the LHS in order to make the lifting pass
|
||||
# correct when `result` is lifted
|
||||
|
||||
@@ -1242,7 +1242,7 @@ proc check(n: PNode, ctx: NilCheckerContext, map: NilMap): Check =
|
||||
result = check(n.sons[0], ctx, map)
|
||||
of nkIfStmt, nkIfExpr:
|
||||
result = checkIf(n, ctx, map)
|
||||
of nkAsgn:
|
||||
of nkAsgn, nkFastAsgn, nkSinkAsgn:
|
||||
result = checkAsgn(n[0], n[1], ctx, map)
|
||||
of nkVarSection:
|
||||
result.map = map
|
||||
|
||||
@@ -154,7 +154,7 @@ proc analyse(c: var Con; b: var BasicBlock; n: PNode) =
|
||||
nkTypeOfExpr, nkMixinStmt, nkBindStmt:
|
||||
discard "do not follow the construct"
|
||||
|
||||
of nkAsgn, nkFastAsgn:
|
||||
of nkAsgn, nkFastAsgn, nkSinkAsgn:
|
||||
# reverse order, see remark for `=sink`:
|
||||
analyse(c, b, n[1])
|
||||
analyse(c, b, n[0])
|
||||
|
||||
@@ -44,7 +44,7 @@ proc canonKind(n: PNode): TNodeKind =
|
||||
case result
|
||||
of nkCallKinds: result = nkCall
|
||||
of nkStrLit..nkTripleStrLit: result = nkStrLit
|
||||
of nkFastAsgn: result = nkAsgn
|
||||
of nkFastAsgn, nkSinkAsgn: result = nkAsgn
|
||||
else: discard
|
||||
|
||||
proc sameKinds(a, b: PNode): bool {.inline.} =
|
||||
|
||||
@@ -518,7 +518,7 @@ proc lsub(g: TSrcGen; n: PNode): int =
|
||||
of nkOfInherit: result = lsub(g, n[0]) + len("of_")
|
||||
of nkProcTy: result = lsons(g, n) + len("proc_")
|
||||
of nkIteratorTy: result = lsons(g, n) + len("iterator_")
|
||||
of nkSharedTy: result = lsons(g, n) + len("shared_")
|
||||
of nkSinkAsgn: result = lsons(g, n) + len("`=sink`(, )")
|
||||
of nkEnumTy:
|
||||
if n.len > 0:
|
||||
result = lsub(g, n[0]) + lcomma(g, n, 1) + len("enum_")
|
||||
@@ -1170,6 +1170,11 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext, fromStmtList = false) =
|
||||
put(g, tkSpaces, Space)
|
||||
putWithSpace(g, tkEquals, "=")
|
||||
gsub(g, n, 1)
|
||||
of nkSinkAsgn:
|
||||
put(g, tkSymbol, "`=sink`")
|
||||
put(g, tkParLe, "(")
|
||||
gcomma(g, n)
|
||||
put(g, tkParRi, ")")
|
||||
of nkChckRangeF:
|
||||
put(g, tkSymbol, "chckRangeF")
|
||||
put(g, tkParLe, "(")
|
||||
|
||||
@@ -306,7 +306,7 @@ proc semGenericStmt(c: PContext, n: PNode,
|
||||
result.add newIdentNode(getIdent(c.cache, "[]"), n.info)
|
||||
for i in 0..<n.len: result.add(n[i])
|
||||
result = semGenericStmt(c, result, flags, ctx)
|
||||
of nkAsgn, nkFastAsgn:
|
||||
of nkAsgn, nkFastAsgn, nkSinkAsgn:
|
||||
checkSonsLen(n, 2, c.config)
|
||||
let a = n[0]
|
||||
let b = n[1]
|
||||
|
||||
@@ -78,8 +78,8 @@ proc semArrPut(c: PContext; n: PNode; flags: TExprFlags): PNode =
|
||||
result[1] = n.lastSon
|
||||
result = semAsgn(c, result, noOverloadedSubscript)
|
||||
|
||||
proc semAsgnOpr(c: PContext; n: PNode): PNode =
|
||||
result = newNodeI(nkAsgn, n.info, 2)
|
||||
proc semAsgnOpr(c: PContext; n: PNode; k: TNodeKind): PNode =
|
||||
result = newNodeI(k, n.info, 2)
|
||||
result[0] = n[1]
|
||||
result[1] = n[2]
|
||||
result = semAsgn(c, result, noOverloadedAsgn)
|
||||
@@ -553,7 +553,9 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
|
||||
result = semArrPut(c, n, flags)
|
||||
of mAsgn:
|
||||
if n[0].sym.name.s == "=":
|
||||
result = semAsgnOpr(c, n)
|
||||
result = semAsgnOpr(c, n, nkAsgn)
|
||||
elif n[0].sym.name.s == "=sink":
|
||||
result = semAsgnOpr(c, n, nkSinkAsgn)
|
||||
else:
|
||||
result = semShallowCopy(c, n, flags)
|
||||
of mIsPartOf: result = semIsPartOf(c, n, flags)
|
||||
|
||||
@@ -323,7 +323,7 @@ proc analyseIf(c: var AnalysisCtx; n: PNode) =
|
||||
|
||||
proc analyse(c: var AnalysisCtx; n: PNode) =
|
||||
case n.kind
|
||||
of nkAsgn, nkFastAsgn:
|
||||
of nkAsgn, nkFastAsgn, nkSinkAsgn:
|
||||
let y = n[1].skipConv
|
||||
if n[0].isSingleAssignable and y.isLocal:
|
||||
let slot = c.getSlot(y.sym)
|
||||
@@ -442,7 +442,7 @@ proc transformSpawn(g: ModuleGraph; idgen: IdGenerator; owner: PSym; n, barrier:
|
||||
else:
|
||||
it[^1] = wrapProcForSpawn(g, idgen, owner, m, b.typ, barrier, nil)
|
||||
if result.isNil: result = n
|
||||
of nkAsgn, nkFastAsgn:
|
||||
of nkAsgn, nkFastAsgn, nkSinkAsgn:
|
||||
let b = n[1]
|
||||
if getMagic(b) == mSpawn and (let t = b[1][0].typ[0];
|
||||
spawnResult(t, true) == srByVar):
|
||||
|
||||
@@ -1053,7 +1053,7 @@ proc track(tracked: PEffects, n: PNode) =
|
||||
checkFieldAccess(tracked.guards, n, tracked.config)
|
||||
of nkTryStmt: trackTryStmt(tracked, n)
|
||||
of nkPragma: trackPragmaStmt(tracked, n)
|
||||
of nkAsgn, nkFastAsgn:
|
||||
of nkAsgn, nkFastAsgn, nkSinkAsgn:
|
||||
track(tracked, n[1])
|
||||
initVar(tracked, n[0], volatileCheck=true)
|
||||
invalidateFacts(tracked.guards, n[0])
|
||||
|
||||
@@ -511,7 +511,7 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
|
||||
result.add newIdentNode(getIdent(c.c.cache, "{}"), n.info)
|
||||
for i in 0..<n.len: result.add(n[i])
|
||||
result = semTemplBodySons(c, result)
|
||||
of nkAsgn, nkFastAsgn:
|
||||
of nkAsgn, nkFastAsgn, nkSinkAsgn:
|
||||
checkSonsLen(n, 2, c.c.config)
|
||||
let a = n[0]
|
||||
let b = n[1]
|
||||
|
||||
@@ -53,7 +53,7 @@ proc findDocComment(n: PNode): PNode =
|
||||
if result != nil: return
|
||||
if n.len > 1:
|
||||
result = findDocComment(n[1])
|
||||
elif n.kind in {nkAsgn, nkFastAsgn} and n.len == 2:
|
||||
elif n.kind in {nkAsgn, nkFastAsgn, nkSinkAsgn} and n.len == 2:
|
||||
result = findDocComment(n[1])
|
||||
|
||||
proc extractDocComment(g: ModuleGraph; s: PSym): string =
|
||||
|
||||
@@ -686,7 +686,7 @@ proc traverse(c: var Partitions; n: PNode) =
|
||||
for i in 0..<child.len-2:
|
||||
#registerVariable(c, child[i])
|
||||
deps(c, child[i], last)
|
||||
of nkAsgn, nkFastAsgn:
|
||||
of nkAsgn, nkFastAsgn, nkSinkAsgn:
|
||||
traverse(c, n[0])
|
||||
inc c.inAsgnSource
|
||||
traverse(c, n[1])
|
||||
@@ -779,7 +779,7 @@ proc traverse(c: var Partitions; n: PNode) =
|
||||
|
||||
if n.kind == nkWhileStmt:
|
||||
traverse(c, n[0])
|
||||
# variables in while condition has longer alive time than local variables
|
||||
# variables in while condition has longer alive time than local variables
|
||||
# in the while loop body
|
||||
else:
|
||||
for child in n: traverse(c, child)
|
||||
@@ -811,7 +811,7 @@ proc computeLiveRanges(c: var Partitions; n: PNode) =
|
||||
registerVariable(c, child[i])
|
||||
#deps(c, child[i], last)
|
||||
|
||||
of nkAsgn, nkFastAsgn:
|
||||
of nkAsgn, nkFastAsgn, nkSinkAsgn:
|
||||
computeLiveRanges(c, n[0])
|
||||
computeLiveRanges(c, n[1])
|
||||
if n[0].kind == nkSym:
|
||||
@@ -871,7 +871,7 @@ proc computeLiveRanges(c: var Partitions; n: PNode) =
|
||||
|
||||
if n.kind == nkWhileStmt:
|
||||
computeLiveRanges(c, n[0])
|
||||
# variables in while condition has longer alive time than local variables
|
||||
# variables in while condition has longer alive time than local variables
|
||||
# in the while loop body
|
||||
of nkElifBranch, nkElifExpr, nkElse, nkOfBranch:
|
||||
inc c.inConditional
|
||||
|
||||
@@ -2045,7 +2045,7 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
|
||||
of nkNilLit:
|
||||
if not n.typ.isEmptyType: genLit(c, getNullValue(n.typ, n.info, c.config), dest)
|
||||
else: unused(c, n, dest)
|
||||
of nkAsgn, nkFastAsgn:
|
||||
of nkAsgn, nkFastAsgn, nkSinkAsgn:
|
||||
unused(c, n, dest)
|
||||
genAsgn(c, n[0], n[1], n.kind == nkAsgn)
|
||||
of nkDotExpr: genObjAccess(c, n, dest, flags)
|
||||
|
||||
@@ -79,7 +79,7 @@ type
|
||||
nnkDistinctTy,
|
||||
nnkProcTy,
|
||||
nnkIteratorTy, # iterator type
|
||||
nnkSharedTy, # 'shared T'
|
||||
nnkSinkAsgn,
|
||||
nnkEnumTy,
|
||||
nnkEnumFieldDef,
|
||||
nnkArgList, nnkPattern
|
||||
@@ -127,6 +127,7 @@ type
|
||||
|
||||
const
|
||||
nnkMutableTy* {.deprecated.} = nnkOutTy
|
||||
nnkSharedTy* {.deprecated.} = nnkSinkAsgn
|
||||
|
||||
type
|
||||
NimIdent* {.deprecated.} = object of RootObj
|
||||
|
||||
29
tests/arc/texplicit_sink.nim
Normal file
29
tests/arc/texplicit_sink.nim
Normal file
@@ -0,0 +1,29 @@
|
||||
discard """
|
||||
output: '''de'''
|
||||
cmd: '''nim c --mm:arc --expandArc:main $file'''
|
||||
nimout: '''--expandArc: main
|
||||
|
||||
var
|
||||
a
|
||||
b_cursor
|
||||
try:
|
||||
a = f "abc"
|
||||
b_cursor = "de"
|
||||
`=sink`(a, b_cursor)
|
||||
echo [a]
|
||||
finally:
|
||||
`=destroy`(a)
|
||||
-- end of expandArc ------------------------'''
|
||||
"""
|
||||
|
||||
# bug #20572
|
||||
|
||||
proc f(s: string): string = s
|
||||
|
||||
proc main =
|
||||
var a = f "abc"
|
||||
var b = "de"
|
||||
`=sink`(a, b)
|
||||
echo a
|
||||
|
||||
main()
|
||||
Reference in New Issue
Block a user