This commit is contained in:
Araq 2020-07-07 23:10:00 +02:00 • committed by Andreas Rumpf
commit b17e1efc67
2 changed files with 34 additions and 18 deletions

View file

@ -91,17 +91,23 @@ proc optimize(s: var Scope) =
filterNil(wasMoved) filterNil(wasMoved)
filterNil(final) filterNil(final)
proc toTree(s: var Scope; ret: PNode; onlyCareAboutVars = false): PNode = type
ToTreeFlag = enum
onlyCareAboutVars,
producesValue
proc toTree(s: var Scope; ret: PNode; flags: set[ToTreeFlag]): PNode =
if not s.needsTry: optimize(s) if not s.needsTry: optimize(s)
assert ret != nil assert ret != nil
if s.vars.len == 0 and s.final.len == 0 and s.wasMoved.len == 0: if s.vars.len == 0 and s.final.len == 0 and s.wasMoved.len == 0:
# trivial, nothing was done: # trivial, nothing was done:
result = ret result = ret
else: else:
if isEmptyType(ret.typ): let isExpr = producesValue in flags and not isEmptyType(ret.typ)
result = newNodeI(nkStmtList, ret.info) if isExpr:
else:
result = newNodeIT(nkStmtListExpr, ret.info, ret.typ) result = newNodeIT(nkStmtListExpr, ret.info, ret.typ)
else:
result = newNodeI(nkStmtList, ret.info)
if s.vars.len > 0: if s.vars.len > 0:
let varSection = newNodeI(nkVarSection, ret.info) let varSection = newNodeI(nkVarSection, ret.info)
@ -109,7 +115,7 @@ proc toTree(s: var Scope; ret: PNode; onlyCareAboutVars = false): PNode =
varSection.add newTree(nkIdentDefs, newSymNode(tmp), newNodeI(nkEmpty, ret.info), varSection.add newTree(nkIdentDefs, newSymNode(tmp), newNodeI(nkEmpty, ret.info),
newNodeI(nkEmpty, ret.info)) newNodeI(nkEmpty, ret.info))
result.add varSection result.add varSection
if onlyCareAboutVars: if onlyCareAboutVars in flags:
result.add ret result.add ret
s.vars.setLen 0 s.vars.setLen 0
elif s.needsTry: elif s.needsTry:
@ -117,8 +123,11 @@ proc toTree(s: var Scope; ret: PNode; onlyCareAboutVars = false): PNode =
for m in s.wasMoved: finSection.add m for m in s.wasMoved: finSection.add m
for i in countdown(s.final.high, 0): finSection.add s.final[i] for i in countdown(s.final.high, 0): finSection.add s.final[i]
result.add newTryFinally(ret, finSection) result.add newTryFinally(ret, finSection)
elif isExpr:
for m in s.wasMoved: result.add m
for i in countdown(s.final.high, 0): result.add s.final[i]
result.add ret
else: else:
#assert isEmptyType(ret.typ)
result.add ret result.add ret
for m in s.wasMoved: result.add m for m in s.wasMoved: result.add m
for i in countdown(s.final.high, 0): result.add s.final[i] for i in countdown(s.final.high, 0): result.add s.final[i]
@ -593,22 +602,25 @@ proc pVarTopLevel(v: PNode; c: var Con; s: var Scope; ri, res: PNode) =
elif ri.kind != nkEmpty: elif ri.kind != nkEmpty:
res.add moveOrCopy(v, ri, c, s, isDecl = true) res.add moveOrCopy(v, ri, c, s, isDecl = true)
template handleNestedTempl(n: untyped, processCall: untyped) = template handleNestedTempl(n, processCall: untyped; alwaysStmt: bool) =
template maybeVoid(child, s): untyped = template maybeVoid(child, s): untyped =
if isEmptyType(child.typ): p(child, c, s, normal) if isEmptyType(child.typ): p(child, c, s, normal)
else: processCall(child, s) else: processCall(child, s)
let treeFlags = if not isEmptyType(n.typ) and not alwaysStmt: {producesValue} else: {}
case n.kind case n.kind
of nkStmtList, nkStmtListExpr: of nkStmtList, nkStmtListExpr:
# a statement list does not open a new scope # a statement list does not open a new scope
if n.len == 0: return n if n.len == 0: return n
result = copyNode(n) result = copyNode(n)
if alwaysStmt: result.typ = nil
for i in 0..<n.len-1: for i in 0..<n.len-1:
result.add p(n[i], c, s, normal) result.add p(n[i], c, s, normal)
result.add maybeVoid(n[^1], s) result.add maybeVoid(n[^1], s)
of nkCaseStmt: of nkCaseStmt:
result = copyNode(n) result = copyNode(n)
if alwaysStmt: result.typ = nil
result.add p(n[0], c, s, normal) result.add p(n[0], c, s, normal)
for i in 1..<n.len: for i in 1..<n.len:
let it = n[i] let it = n[i]
@ -619,7 +631,7 @@ template handleNestedTempl(n: untyped, processCall: untyped) =
branch[j] = copyTree(it[j]) branch[j] = copyTree(it[j])
var ofScope = nestedScope(s) var ofScope = nestedScope(s)
let ofResult = maybeVoid(it[^1], ofScope) let ofResult = maybeVoid(it[^1], ofScope)
branch[^1] = toTree(ofScope, ofResult) branch[^1] = toTree(ofScope, ofResult, treeFlags)
result.add branch result.add branch
rememberParent(s, ofScope) rememberParent(s, ofScope)
@ -629,20 +641,22 @@ template handleNestedTempl(n: untyped, processCall: untyped) =
result.add p(n[0], c, s, normal) result.add p(n[0], c, s, normal)
var bodyScope = nestedScope(s) var bodyScope = nestedScope(s)
let bodyResult = p(n[1], c, bodyScope, normal) let bodyResult = p(n[1], c, bodyScope, normal)
result.add toTree(bodyScope, bodyResult) result.add toTree(bodyScope, bodyResult, treeFlags)
rememberParent(s, bodyScope) rememberParent(s, bodyScope)
dec c.inLoop dec c.inLoop
of nkBlockStmt, nkBlockExpr: of nkBlockStmt, nkBlockExpr:
result = copyNode(n) result = copyNode(n)
if alwaysStmt: result.typ = nil
result.add n[0] result.add n[0]
var bodyScope = nestedScope(s) var bodyScope = nestedScope(s)
let bodyResult = processCall(n[1], bodyScope) let bodyResult = processCall(n[1], bodyScope)
result.add toTree(bodyScope, bodyResult) result.add toTree(bodyScope, bodyResult, treeFlags)
rememberParent(s, bodyScope) rememberParent(s, bodyScope)
of nkIfStmt, nkIfExpr: of nkIfStmt, nkIfExpr:
result = copyNode(n) result = copyNode(n)
if alwaysStmt: result.typ = nil
for i in 0..<n.len: for i in 0..<n.len:
let it = n[i] let it = n[i]
var branch = shallowCopy(it) var branch = shallowCopy(it)
@ -650,19 +664,20 @@ template handleNestedTempl(n: untyped, processCall: untyped) =
branchScope.parent = nil branchScope.parent = nil
if it.kind in {nkElifBranch, nkElifExpr}: if it.kind in {nkElifBranch, nkElifExpr}:
let cond = p(it[0], c, branchScope, normal) let cond = p(it[0], c, branchScope, normal)
branch[0] = toTree(branchScope, cond, onlyCareAboutVars = true) branch[0] = toTree(branchScope, cond, {producesValue, onlyCareAboutVars})
branchScope.parent = addr(s) branchScope.parent = addr(s)
var branchResult = processCall(it[^1], branchScope) var branchResult = processCall(it[^1], branchScope)
branch[^1] = toTree(branchScope, branchResult) branch[^1] = toTree(branchScope, branchResult, treeFlags)
result.add branch result.add branch
rememberParent(s, branchScope) rememberParent(s, branchScope)
of nkTryStmt: of nkTryStmt:
result = copyNode(n) result = copyNode(n)
if alwaysStmt: result.typ = nil
var tryScope = nestedScope(s) var tryScope = nestedScope(s)
var tryResult = maybeVoid(n[0], tryScope) var tryResult = maybeVoid(n[0], tryScope)
result.add toTree(tryScope, tryResult) result.add toTree(tryScope, tryResult, treeFlags)
rememberParent(s, tryScope) rememberParent(s, tryScope)
for i in 1..<n.len: for i in 1..<n.len:
@ -671,12 +686,13 @@ template handleNestedTempl(n: untyped, processCall: untyped) =
var branchScope = nestedScope(s) var branchScope = nestedScope(s)
var branchResult = if it.kind == nkFinally: p(it[^1], c, branchScope, normal) var branchResult = if it.kind == nkFinally: p(it[^1], c, branchScope, normal)
else: processCall(it[^1], branchScope) else: processCall(it[^1], branchScope)
branch[^1] = toTree(branchScope, branchResult) branch[^1] = toTree(branchScope, branchResult, treeFlags)
result.add branch result.add branch
rememberParent(s, branchScope) rememberParent(s, branchScope)
of nkWhen: # This should be a "when nimvm" node. of nkWhen: # This should be a "when nimvm" node.
result = copyTree(n) result = copyTree(n)
if alwaysStmt: result.typ = nil
result[1][0] = processCall(n[1][0], s) result[1][0] = processCall(n[1][0], s)
else: assert(false) else: assert(false)
@ -708,7 +724,7 @@ proc p(n: PNode; c: var Con; s: var Scope; mode: ProcessMode): PNode =
if n.kind in {nkStmtList, nkStmtListExpr, nkBlockStmt, nkBlockExpr, nkIfStmt, if n.kind in {nkStmtList, nkStmtListExpr, nkBlockStmt, nkBlockExpr, nkIfStmt,
nkIfExpr, nkCaseStmt, nkWhen, nkWhileStmt, nkTryStmt}: nkIfExpr, nkCaseStmt, nkWhen, nkWhileStmt, nkTryStmt}:
template process(child, s): untyped = p(child, c, s, mode) template process(child, s): untyped = p(child, c, s, mode)
handleNestedTempl(n, process) handleNestedTempl(n, process, false)
elif mode == sinkArg: elif mode == sinkArg:
if n.containsConstSeq: if n.containsConstSeq:
# const sequences are not mutable and so we need to pass a copy to the # const sequences are not mutable and so we need to pass a copy to the
@ -994,7 +1010,7 @@ proc moveOrCopy(dest, ri: PNode; c: var Con; s: var Scope, isDecl = false): PNod
result = genSink(c, s, dest, p(ri, c, s, sinkArg), isDecl) result = genSink(c, s, dest, p(ri, c, s, sinkArg), isDecl)
of nkStmtListExpr, nkBlockExpr, nkIfExpr, nkCaseStmt: of nkStmtListExpr, nkBlockExpr, nkIfExpr, nkCaseStmt:
template process(child, s): untyped = moveOrCopy(dest, child, c, s, isDecl) template process(child, s): untyped = moveOrCopy(dest, child, c, s, isDecl)
handleNestedTempl(ri, process) handleNestedTempl(ri, process, true)
of nkRaiseStmt: of nkRaiseStmt:
result = pRaiseStmt(ri, c, s) result = pRaiseStmt(ri, c, s)
else: else:
@ -1071,7 +1087,7 @@ proc injectDestructorCalls*(g: ModuleGraph; owner: PSym; n: PNode): PNode =
scope.final.add genDestroy(c, params[i]) scope.final.add genDestroy(c, params[i])
#if optNimV2 in c.graph.config.globalOptions: #if optNimV2 in c.graph.config.globalOptions:
# injectDefaultCalls(n, c) # injectDefaultCalls(n, c)
result = toTree(scope, body) result = toTree(scope, body, {})
dbg: dbg:
echo ">---------transformed-to--------->" echo ">---------transformed-to--------->"
echo renderTree(result, {renderIds}) echo renderTree(result, {renderIds})

View file

@ -113,7 +113,7 @@ proc myfunc2(x, y: int): tuple[a: MySeqNonCopyable, b:int, c:MySeqNonCopyable] =
var cc = newMySeq(y, 5.0) var cc = newMySeq(y, 5.0)
(a: case x: (a: case x:
of 1: of 1:
let (z1, z2) = myfunc(x,y) let (z1, z2) = myfunc(x, y)
z2 z2
elif x > 5: raise newException(ValueError, "new error") elif x > 5: raise newException(ValueError, "new error")
else: newMySeq(x, 1.0), else: newMySeq(x, 1.0),