From fbb67f73d14f4330ca911b4be84d2da08afcf5c3 Mon Sep 17 00:00:00 2001 From: Clyybber Date: Mon, 28 Oct 2019 16:58:59 +0100 Subject: [PATCH] Handle result variable --- compiler/transf.nim | 495 ++++++++++++++++++++++---------------------- 1 file changed, 246 insertions(+), 249 deletions(-) diff --git a/compiler/transf.nim b/compiler/transf.nim index 83cdd629e670e..33d176e8e46a9 100644 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -30,15 +30,14 @@ proc transformBody*(g: ModuleGraph, prc: PSym, cache = true; import closureiters, lambdalifting -type - PTransNode* = distinct PNode +type PTransCon = ref TTransCon TTransCon{.final.} = object # part of TContext; stackable mapping: TIdNodeTable # mapping from symbols to nodes owner: PSym # current owner forStmt: PNode # current for stmt - forLoopBody: PTransNode # transformed for loop body + forLoopBody: PNode # transformed for loop body yieldStmts: int # we count the number of yield statements, # because we need to introduce new variables # if we encounter the 2nd yield statement @@ -48,45 +47,28 @@ type module: PSym transCon: PTransCon # top of a TransCon stack inlining: int # > 0 if we are in inlining context (copy vars) - nestedProcs: int # > 0 if we are in a nested proc + genResult: bool # XXX contSyms, breakSyms: seq[PSym] # to transform 'continue' and 'break' deferDetected, tooEarly, needsDestroyPass, noDestructors: bool graph: ModuleGraph PTransf = ref TTransfContext -proc newTransNode(a: PNode): PTransNode {.inline.} = - result = PTransNode(shallowCopy(a)) +proc newTransNode(a: PNode): PNode {.inline.} = + result = shallowCopy(a) proc newTransNode(kind: TNodeKind, info: TLineInfo, - sons: int): PTransNode {.inline.} = + sons: int): PNode {.inline.} = var x = newNodeI(kind, info) newSeq(x.sons, sons) - result = x.PTransNode + result = x proc newTransNode(kind: TNodeKind, n: PNode, - sons: int): PTransNode {.inline.} = + sons: int): PNode {.inline.} = var x = newNodeIT(kind, n.info, n.typ) newSeq(x.sons, sons) x.typ = n.typ # x.flags = n.flags - result = x.PTransNode - -proc add(a, b: PTransNode) {.inline.} = addSon(PNode(a), PNode(b)) -proc len(a: PTransNode): int {.inline.} = len(a.PNode) - -proc `[]=`(a: PTransNode, i: int, x: PTransNode) {.inline.} = - var n = PNode(a) - n.sons[i] = PNode(x) - -proc `[]=`(a: PTransNode, i: BackwardsIndex, x: PTransNode) {.inline.} = - `[]=`(a, a.len - i.int, x) - -proc `[]`(a: PTransNode, i: int): PTransNode {.inline.} = - var n = PNode(a) - result = n.sons[i].PTransNode - -proc `[]`(a: PTransNode, i: BackwardsIndex): PTransNode {.inline.} = - `[]`(a, a.len - i.int) + result = x proc newTransCon(owner: PSym): PTransCon = assert owner != nil @@ -116,16 +98,16 @@ proc newTemp(c: PTransf, typ: PType, info: TLineInfo): PNode = else: result = newSymNode(r) -proc transform(c: PTransf, n: PNode): PTransNode +proc transform(c: PTransf, n: PNode): PNode -proc transformSons(c: PTransf, n: PNode): PTransNode = +proc transformSons(c: PTransf, n: PNode): PNode = result = newTransNode(n) for i in 0 ..< len(n): - result[i] = transform(c, n.sons[i]) + result[i] = transform(c, n[i]) -proc newAsgnStmt(c: PTransf, kind: TNodeKind, le: PNode, ri: PTransNode): PTransNode = - result = newTransNode(kind, PNode(ri).info, 2) - result[0] = PTransNode(le) +proc newAsgnStmt(c: PTransf, kind: TNodeKind, le: PNode, ri: PNode): PNode = + result = newTransNode(kind, ri.info, 2) + result[0] = le result[1] = ri proc transformSymAux(c: PTransf, n: PNode): PNode = @@ -162,8 +144,8 @@ proc transformSymAux(c: PTransf, n: PNode): PNode = tc = tc.next result = b -proc transformSym(c: PTransf, n: PNode): PTransNode = - result = PTransNode(transformSymAux(c, n)) +proc transformSym(c: PTransf, n: PNode): PNode = + result = transformSymAux(c, n) proc freshVar(c: PTransf; v: PSym): PNode = let owner = getCurrOwner(c) @@ -175,25 +157,25 @@ proc freshVar(c: PTransf; v: PSym): PNode = newVar.owner = owner result = newSymNode(newVar) -proc transformVarSection(c: PTransf, v: PNode): PTransNode = +proc transformVarSection(c: PTransf, v: PNode): PNode = result = newTransNode(v) for i in 0 ..< len(v): - var it = v.sons[i] + var it = v[i] if it.kind == nkCommentStmt: - result[i] = PTransNode(it) + result[i] = it elif it.kind == nkIdentDefs: - if it.sons[0].kind == nkSym: + if it[0].kind == nkSym: internalAssert(c.graph.config, it.len == 3) - let x = freshVar(c, it.sons[0].sym) - idNodeTablePut(c.transCon.mapping, it.sons[0].sym, x) + let x = freshVar(c, it[0].sym) + idNodeTablePut(c.transCon.mapping, it[0].sym, x) var defs = newTransNode(nkIdentDefs, it.info, 3) if importantComments(c.graph.config): # keep documentation information: - PNode(defs).comment = it.comment - defs[0] = x.PTransNode - defs[1] = it.sons[1].PTransNode - defs[2] = transform(c, it.sons[2]) - if x.kind == nkSym: x.sym.ast = defs[2].PNode + defs.comment = it.comment + defs[0] = x + defs[1] = it[1] + defs[2] = transform(c, it[2]) + if x.kind == nkSym: x.sym.ast = defs[2] result[i] = defs else: # has been transformed into 'param.x' for closure iterators, so just @@ -206,31 +188,31 @@ proc transformVarSection(c: PTransf, v: PNode): PTransNode = var defs = newTransNode(it.kind, it.info, L) for j in 0 .. L-3: if it[j].kind == nkSym: - let x = freshVar(c, it.sons[j].sym) - idNodeTablePut(c.transCon.mapping, it.sons[j].sym, x) - defs[j] = x.PTransNode + let x = freshVar(c, it[j].sym) + idNodeTablePut(c.transCon.mapping, it[j].sym, x) + defs[j] = x else: defs[j] = transform(c, it[j]) - assert(it.sons[L-2].kind == nkEmpty) - defs[L-2] = newNodeI(nkEmpty, it.info).PTransNode - defs[L-1] = transform(c, it.sons[L-1]) + assert(it[L-2].kind == nkEmpty) + defs[L-2] = newNodeI(nkEmpty, it.info) + defs[L-1] = transform(c, it[L-1]) result[i] = defs -proc transformConstSection(c: PTransf, v: PNode): PTransNode = - result = PTransNode(v) +proc transformConstSection(c: PTransf, v: PNode): PNode = + result = v when false: result = newTransNode(v) for i in 0 ..< len(v): - var it = v.sons[i] + var it = v[i] if it.kind == nkCommentStmt: - result[i] = PTransNode(it) + result[i] = it else: if it.kind != nkConstDef: internalError(c.graph.config, it.info, "transformConstSection") - if it.sons[0].kind != nkSym: - debug it.sons[0] + if it[0].kind != nkSym: + debug it[0] internalError(c.graph.config, it.info, "transformConstSection") - result[i] = PTransNode(it) + result[i] = it proc hasContinue(n: PNode): bool = case n.kind @@ -238,29 +220,29 @@ proc hasContinue(n: PNode): bool = of nkContinueStmt: result = true else: for i in 0 ..< len(n): - if hasContinue(n.sons[i]): return true + if hasContinue(n[i]): return true proc newLabel(c: PTransf, n: PNode): PSym = result = newSym(skLabel, nil, getCurrOwner(c), n.info) result.name = getIdent(c.graph.cache, genPrefix & $result.id) -proc transformBlock(c: PTransf, n: PNode): PTransNode = +proc transformBlock(c: PTransf, n: PNode): PNode = var labl: PSym if c.inlining > 0: labl = newLabel(c, n[0]) idNodeTablePut(c.transCon.mapping, n[0].sym, newSymNode(labl)) else: labl = - if n.sons[0].kind != nkEmpty: - n.sons[0].sym # already named block? -> Push symbol on the stack + if n[0].kind != nkEmpty: + n[0].sym # already named block? -> Push symbol on the stack else: newLabel(c, n) c.breakSyms.add(labl) result = transformSons(c, n) discard c.breakSyms.pop - result[0] = newSymNode(labl).PTransNode + result[0] = newSymNode(labl) -proc transformLoopBody(c: PTransf, n: PNode): PTransNode = +proc transformLoopBody(c: PTransf, n: PNode): PNode = # What if it contains "continue" and "break"? "break" needs # an explicit label too, but not the same! @@ -272,41 +254,41 @@ proc transformLoopBody(c: PTransf, n: PNode): PTransNode = c.contSyms.add(labl) result = newTransNode(nkBlockStmt, n.info, 2) - result[0] = newSymNode(labl).PTransNode + result[0] = newSymNode(labl) result[1] = transform(c, n) discard c.contSyms.pop() else: result = transform(c, n) -proc transformWhile(c: PTransf; n: PNode): PTransNode = +proc transformWhile(c: PTransf; n: PNode): PNode = if c.inlining > 0: result = transformSons(c, n) else: let labl = newLabel(c, n) c.breakSyms.add(labl) result = newTransNode(nkBlockStmt, n.info, 2) - result[0] = newSymNode(labl).PTransNode + result[0] = newSymNode(labl) var body = newTransNode(n) for i in 0..n.len-2: - body[i] = transform(c, n.sons[i]) - body[n.len-1] = transformLoopBody(c, n.sons[n.len-1]) + body[i] = transform(c, n[i]) + body[n.len-1] = transformLoopBody(c, n[n.len-1]) result[1] = body discard c.breakSyms.pop -proc transformBreak(c: PTransf, n: PNode): PTransNode = +proc transformBreak(c: PTransf, n: PNode): PNode = result = transformSons(c, n) - if n.sons[0].kind == nkEmpty and c.breakSyms.len > 0: + if n[0].kind == nkEmpty and c.breakSyms.len > 0: let labl = c.breakSyms[c.breakSyms.high] - result[0] = newSymNode(labl).PTransNode + result[0] = newSymNode(labl) -proc introduceNewLocalVars(c: PTransf, n: PNode): PTransNode = +proc introduceNewLocalVars(c: PTransf, n: PNode): PNode = case n.kind of nkSym: result = transformSym(c, n) of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit: # nothing to be done for leaves: - result = PTransNode(n) + result = n of nkVarSection, nkLetSection: result = transformVarSection(c, n) of nkClosure: @@ -315,14 +297,14 @@ proc introduceNewLocalVars(c: PTransf, n: PNode): PTransNode = # (bug #2604). We need to patch this environment here too: let a = n[1] if a.kind == nkSym: - n.sons[1] = transformSymAux(c, a) - return PTransNode(n) + n[1] = transformSymAux(c, a) + return n else: result = newTransNode(n) for i in 0 ..< len(n): - result[i] = introduceNewLocalVars(c, n.sons[i]) + result[i] = introduceNewLocalVars(c, n[i]) -proc transformAsgn(c: PTransf, n: PNode): PTransNode = +proc transformAsgn(c: PTransf, n: PNode): PNode = let rhs = n[1] if rhs.kind != nkTupleConstr: @@ -336,15 +318,15 @@ proc transformAsgn(c: PTransf, n: PNode): PTransNode = for i, field in rhs: let val = if field.kind == nkExprColonExpr: field[1] else: field let def = newTransNode(nkIdentDefs, field.info, 3) - def[0] = PTransNode(newTemp(c, val.typ, field.info)) - def[1] = PTransNode(newNodeI(nkEmpty, field.info)) + def[0] = newTemp(c, val.typ, field.info) + def[1] = newNodeI(nkEmpty, field.info) def[2] = transform(c, val) letSection[i] = def # NOTE: We assume the constructor fields are in the correct order for the # given tuple type newTupleConstr[i] = def[0] - PNode(newTupleConstr).typ = rhs.typ + newTupleConstr.typ = rhs.typ let asgnNode = newTransNode(nkAsgn, n.info, 2) asgnNode[0] = transform(c, n[0]) @@ -354,8 +336,8 @@ proc transformAsgn(c: PTransf, n: PNode): PTransNode = result[0] = letSection result[1] = asgnNode -proc transformYield(c: PTransf, n: PNode): PTransNode = - proc asgnTo(lhs: PNode, rhs: PTransNode): PTransNode = +proc transformYield(c: PTransf, n: PNode): PNode = + proc asgnTo(lhs: PNode, rhs: PNode): PNode = # Choose the right assignment instruction according to the given ``lhs`` # node since it may not be a nkSym (a stack-allocated skForVar) but a # nkDotExpr (a heap-allocated slot into the envP block) @@ -368,7 +350,7 @@ proc transformYield(c: PTransf, n: PNode): PTransNode = else: internalAssert c.graph.config, false result = newTransNode(nkStmtList, n.info, 0) - var e = n.sons[0] + var e = n[0] # c.transCon.forStmt.len == 3 means that there is one for loop variable # and thus no tuple unpacking: if e.typ.isNil: return result # can happen in nimsuggest for unknown reasons @@ -376,32 +358,32 @@ proc transformYield(c: PTransf, n: PNode): PTransNode = e = skipConv(e) if e.kind in {nkPar, nkTupleConstr}: for i in 0 ..< len(e): - var v = e.sons[i] - if v.kind == nkExprColonExpr: v = v.sons[1] + var v = e[i] + if v.kind == nkExprColonExpr: v = v[1] if c.transCon.forStmt[i].kind == nkVarTuple: for j in 0 ..< len(c.transCon.forStmt[i])-1: let lhs = c.transCon.forStmt[i][j] let rhs = transform(c, newTupleAccess(c.graph, v, j)) add(result, asgnTo(lhs, rhs)) else: - let lhs = c.transCon.forStmt.sons[i] + let lhs = c.transCon.forStmt[i] let rhs = transform(c, v) add(result, asgnTo(lhs, rhs)) else: # Unpack the tuple into the loop variables # XXX: BUG: what if `n` is an expression with side-effects? for i in 0 .. len(c.transCon.forStmt) - 3: - let lhs = c.transCon.forStmt.sons[i] + let lhs = c.transCon.forStmt[i] let rhs = transform(c, newTupleAccess(c.graph, e, i)) add(result, asgnTo(lhs, rhs)) else: - if c.transCon.forStmt.sons[0].kind == nkVarTuple: + if c.transCon.forStmt[0].kind == nkVarTuple: for i in 0 ..< len(c.transCon.forStmt[0])-1: let lhs = c.transCon.forStmt[0][i] let rhs = transform(c, newTupleAccess(c.graph, e, i)) add(result, asgnTo(lhs, rhs)) else: - let lhs = c.transCon.forStmt.sons[0] + let lhs = c.transCon.forStmt[0] let rhs = transform(c, e) add(result, asgnTo(lhs, rhs)) @@ -411,44 +393,44 @@ proc transformYield(c: PTransf, n: PNode): PTransNode = add(result, c.transCon.forLoopBody) else: # we need to introduce new local variables: - add(result, introduceNewLocalVars(c, c.transCon.forLoopBody.PNode)) + add(result, introduceNewLocalVars(c, c.transCon.forLoopBody)) if result.len > 0: - var changeNode = PNode(result[0]) + var changeNode = result[0] changeNode.info = c.transCon.forStmt.info for i, child in changeNode: child.info = changeNode.info -proc transformAddrDeref(c: PTransf, n: PNode, a, b: TNodeKind): PTransNode = +proc transformAddrDeref(c: PTransf, n: PNode, a, b: TNodeKind): PNode = result = transformSons(c, n) if c.graph.config.cmd == cmdCompileToCpp or sfCompileToCpp in c.module.flags: return - var n = result.PNode - case n.sons[0].kind + var n = result + case n[0].kind of nkObjUpConv, nkObjDownConv, nkChckRange, nkChckRangeF, nkChckRange64: - var m = n.sons[0].sons[0] + var m = n[0][0] if m.kind == a or m.kind == b: # addr ( nkConv ( deref ( x ) ) ) --> nkConv(x) - n.sons[0].sons[0] = m.sons[0] - result = PTransNode(n.sons[0]) + n[0][0] = m[0] + result = n[0] if n.typ.skipTypes(abstractVar).kind != tyOpenArray: - PNode(result).typ = n.typ + result.typ = n.typ elif n.typ.skipTypes(abstractInst).kind in {tyVar}: - PNode(result).typ = toVar(PNode(result).typ) + result.typ = toVar(result.typ) of nkHiddenStdConv, nkHiddenSubConv, nkConv: - var m = n.sons[0].sons[1] + var m = n[0][1] if m.kind == a or m.kind == b: # addr ( nkConv ( deref ( x ) ) ) --> nkConv(x) - n.sons[0].sons[1] = m.sons[0] - result = PTransNode(n.sons[0]) + n[0][1] = m[0] + result = n[0] if n.typ.skipTypes(abstractVar).kind != tyOpenArray: - PNode(result).typ = n.typ + result.typ = n.typ elif n.typ.skipTypes(abstractInst).kind in {tyVar}: - PNode(result).typ = toVar(PNode(result).typ) + result.typ = toVar(result.typ) else: - if n.sons[0].kind == a or n.sons[0].kind == b: + if n[0].kind == a or n[0].kind == b: # addr ( deref ( x )) --> x - result = PTransNode(n.sons[0].sons[0]) + result = n[0][0] if n.typ.skipTypes(abstractVar).kind != tyOpenArray: - PNode(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 @@ -466,18 +448,18 @@ proc generateThunk(c: PTransf; prc: PNode, dest: PType): PNode = result.add(conv) result.add(newNodeIT(nkNilLit, prc.info, getSysType(c.graph, prc.info, tyNil))) -proc transformConv(c: PTransf, n: PNode): PTransNode = +proc transformConv(c: PTransf, n: PNode): PNode = # numeric types need range checks: var dest = skipTypes(n.typ, abstractVarRange) - var source = skipTypes(n.sons[1].typ, abstractVarRange) + var source = skipTypes(n[1].typ, abstractVarRange) case dest.kind of tyInt..tyInt64, tyEnum, tyChar, tyBool, tyUInt8..tyUInt32: # we don't include uint and uint64 here as these are no ordinal types ;-) if not isOrdinalType(source): # float -> int conversions. ugh. result = transformSons(c, n) - elif firstOrd(c.graph.config, n.typ) <= firstOrd(c.graph.config, n.sons[1].typ) and - lastOrd(c.graph.config, n.sons[1].typ) <= lastOrd(c.graph.config, n.typ): + elif firstOrd(c.graph.config, n.typ) <= firstOrd(c.graph.config, n[1].typ) and + lastOrd(c.graph.config, n[1].typ) <= lastOrd(c.graph.config, n.typ): # BUGFIX: simply leave n as it is; we need a nkConv node, # but no range check: result = transformSons(c, n) @@ -488,34 +470,34 @@ proc transformConv(c: PTransf, n: PNode): PTransNode = else: result = newTransNode(nkChckRange, n, 3) dest = skipTypes(n.typ, abstractVar) - result[0] = transform(c, n.sons[1]) - result[1] = newIntTypeNode(firstOrd(c.graph.config, dest), dest).PTransNode - result[2] = newIntTypeNode(lastOrd(c.graph.config, dest), dest).PTransNode + result[0] = transform(c, n[1]) + result[1] = newIntTypeNode(firstOrd(c.graph.config, dest), dest) + result[2] = newIntTypeNode(lastOrd(c.graph.config, dest), dest) of tyFloat..tyFloat128: # XXX int64 -> float conversion? if skipTypes(n.typ, abstractVar).kind == tyRange: result = newTransNode(nkChckRangeF, n, 3) dest = skipTypes(n.typ, abstractVar) - result[0] = transform(c, n.sons[1]) - result[1] = copyTree(dest.n.sons[0]).PTransNode - result[2] = copyTree(dest.n.sons[1]).PTransNode + result[0] = transform(c, n[1]) + result[1] = copyTree(dest.n[0]) + result[2] = copyTree(dest.n[1]) else: result = transformSons(c, n) of tyOpenArray, tyVarargs: - result = transform(c, n.sons[1]) - PNode(result).typ = takeType(n.typ, n.sons[1].typ) - #echo n.info, " came here and produced ", typeToString(PNode(result).typ), - # " from ", typeToString(n.typ), " and ", typeToString(n.sons[1].typ) + result = transform(c, n[1]) + result.typ = takeType(n.typ, n[1].typ) + #echo n.info, " came here and produced ", typeToString(result.typ), + # " from ", typeToString(n.typ), " and ", typeToString(n[1].typ) of tyCString: if source.kind == tyString: result = newTransNode(nkStringToCString, n, 1) - result[0] = transform(c, n.sons[1]) + result[0] = transform(c, n[1]) else: result = transformSons(c, n) of tyString: if source.kind == tyCString: result = newTransNode(nkCStringToString, n, 1) - result[0] = transform(c, n.sons[1]) + result[0] = transform(c, n[1]) else: result = transformSons(c, n) of tyRef, tyPtr: @@ -525,31 +507,31 @@ proc transformConv(c: PTransf, n: PNode): PTransNode = var diff = inheritanceDiff(dest, source) if diff < 0: result = newTransNode(nkObjUpConv, n, 1) - result[0] = transform(c, n.sons[1]) + result[0] = transform(c, n[1]) elif diff > 0 and diff != high(int): result = newTransNode(nkObjDownConv, n, 1) - result[0] = transform(c, n.sons[1]) + result[0] = transform(c, n[1]) else: - result = transform(c, n.sons[1]) + result = transform(c, n[1]) else: result = transformSons(c, n) of tyObject: var diff = inheritanceDiff(dest, source) if diff < 0: result = newTransNode(nkObjUpConv, n, 1) - result[0] = transform(c, n.sons[1]) + result[0] = transform(c, n[1]) elif diff > 0 and diff != high(int): result = newTransNode(nkObjDownConv, n, 1) - result[0] = transform(c, n.sons[1]) + result[0] = transform(c, n[1]) else: - result = transform(c, n.sons[1]) + result = transform(c, n[1]) of tyGenericParam, tyOrdinal: - result = transform(c, n.sons[1]) + result = transform(c, n[1]) # happens sometimes for generated assignments, etc. of tyProc: result = transformSons(c, n) if dest.callConv == ccClosure and source.callConv == ccDefault: - result = generateThunk(c, result[1].PNode, dest).PTransNode + result = generateThunk(c, result[1], dest) else: result = transformSons(c, n) @@ -577,7 +559,7 @@ proc putArgInto(arg: PNode, formal: PType): TPutArgInto = of nkPar, nkTupleConstr, nkCurly, nkBracket: result = paFastAsgn for i in 0 ..< len(arg): - if putArgInto(arg.sons[i], formal) != paDirectMapping: return + if putArgInto(arg[i], formal) != paDirectMapping: return result = paDirectMapping else: if skipTypes(formal, abstractInst).kind in {tyVar, tyLent}: result = paVarAsgn @@ -585,35 +567,35 @@ proc putArgInto(arg: PNode, formal: PType): TPutArgInto = proc findWrongOwners(c: PTransf, n: PNode) = if n.kind == nkVarSection: - let x = n.sons[0].sons[0] + let x = n[0][0] if x.kind == nkSym and x.sym.owner != getCurrOwner(c): internalError(c.graph.config, x.info, "bah " & x.sym.name.s & " " & x.sym.owner.name.s & " " & getCurrOwner(c).name.s) else: - for i in 0 ..< safeLen(n): findWrongOwners(c, n.sons[i]) + for i in 0 ..< safeLen(n): findWrongOwners(c, n[i]) -proc transformFor(c: PTransf, n: PNode): PTransNode = +proc transformFor(c: PTransf, n: PNode): PNode = # generate access statements for the parameters (unless they are constant) # put mapping from formal parameters to actual parameters if n.kind != nkForStmt: internalError(c.graph.config, n.info, "transformFor") var length = len(n) - var call = n.sons[length - 2] + var call = n[length - 2] let labl = newLabel(c, n) result = newTransNode(nkBlockStmt, n.info, 2) - result[0] = newSymNode(labl).PTransNode + result[0] = newSymNode(labl) if call.typ.isNil: # see bug #3051 - result[1] = newNode(nkEmpty).PTransNode + result[1] = newNode(nkEmpty) return result c.breakSyms.add(labl) - if call.kind notin nkCallKinds or call.sons[0].kind != nkSym or - call.sons[0].typ.callConv == ccClosure: - result[1] = n.PTransNode + if call.kind notin nkCallKinds or call[0].kind != nkSym or + call[0].typ.callConv == ccClosure: + result[1] = n result[1][^1] = transformLoopBody(c, n[^1]) result[1][^2] = transform(c, n[^2]) - result[1] = lambdalifting.liftForLoop(c.graph, result[1].PNode, getCurrOwner(c)).PTransNode + result[1] = lambdalifting.liftForLoop(c.graph, result[1], getCurrOwner(c)) discard c.breakSyms.pop return result @@ -621,7 +603,7 @@ proc transformFor(c: PTransf, n: PNode): PTransNode = var stmtList = newTransNode(nkStmtList, n.info, 0) result[1] = stmtList - var loopBody = transformLoopBody(c, n.sons[length-1]) + var loopBody = transformLoopBody(c, n[length-1]) discard c.breakSyms.pop @@ -631,12 +613,12 @@ proc transformFor(c: PTransf, n: PNode): PTransNode = for j in 0 ..< len(n[i])-1: addVar(v, copyTree(n[i][j])) # declare new vars else: - addVar(v, copyTree(n.sons[i])) # declare new vars - add(stmtList, v.PTransNode) + addVar(v, copyTree(n[i])) # declare new vars + add(stmtList, v) # Bugfix: inlined locals belong to the invoking routine, not to the invoked # iterator! - let iter = call.sons[0].sym + let iter = call[0].sym var newC = newTransCon(getCurrOwner(c)) newC.forStmt = n newC.forLoopBody = loopBody @@ -645,11 +627,11 @@ proc transformFor(c: PTransf, n: PNode): PTransNode = # generate access statements for the parameters (unless they are constant) pushTransCon(c, newC) for i in 1 ..< len(call): - var arg = transform(c, call.sons[i]).PNode + var arg = transform(c, call[i]) let ff = skipTypes(iter.typ, abstractInst) # can happen for 'nim check': if i >= ff.n.len: return result - var formal = ff.n.sons[i].sym + var formal = ff.n[i].sym let pa = putArgInto(arg, formal.typ) case pa of paDirectMapping: @@ -665,7 +647,7 @@ proc transformFor(c: PTransf, n: PNode): PTransNode = # generate a temporary and produce an assignment statement: var temp = newTemp(c, t, formal.info) addVar(v, temp) - add(stmtList, newAsgnStmt(c, nkFastAsgn, temp, arg.PTransNode)) + add(stmtList, newAsgnStmt(c, nkFastAsgn, temp, arg)) idNodeTablePut(newC.mapping, formal, temp) of paVarAsgn: assert(skipTypes(formal.typ, abstractInst).kind == tyVar) @@ -673,10 +655,10 @@ proc transformFor(c: PTransf, n: PNode): PTransNode = # XXX BUG still not correct if the arg has a side effect! of paComplexOpenarray: let typ = newType(tySequence, formal.owner) - addSonSkipIntLit(typ, formal.typ.sons[0]) + addSonSkipIntLit(typ, formal.typ[0]) var temp = newTemp(c, typ, formal.info) addVar(v, temp) - add(stmtList, newAsgnStmt(c, nkFastAsgn, temp, arg.PTransNode)) + add(stmtList, newAsgnStmt(c, nkFastAsgn, temp, arg)) idNodeTablePut(newC.mapping, formal, temp) let body = transformBody(c.graph, iter, true, c.noDestructors) @@ -687,64 +669,64 @@ proc transformFor(c: PTransf, n: PNode): PTransNode = dec(c.inlining) popInfoContext(c.graph.config) popTransCon(c) - # echo "transformed: ", stmtList.PNode.renderTree + # echo "transformed: ", stmtList.renderTree -proc transformCase(c: PTransf, n: PNode): PTransNode = +proc transformCase(c: PTransf, n: PNode): PNode = # removes `elif` branches of a case stmt # adds ``else: nil`` if needed for the code generator result = newTransNode(nkCaseStmt, n, 0) - var ifs = PTransNode(nil) + var ifs: PNode = nil for i in 0 .. len(n)-1: - var it = n.sons[i] + var it = n[i] var e = transform(c, it) case it.kind of nkElifBranch: - if ifs.PNode == nil: + if ifs == nil: # Generate the right node depending on whether `n` is used as a stmt or # as an expr let kind = if n.typ != nil: nkIfExpr else: nkIfStmt ifs = newTransNode(kind, it.info, 0) - ifs.PNode.typ = n.typ + ifs.typ = n.typ ifs.add(e) of nkElse: - if ifs.PNode == nil: result.add(e) + if ifs == nil: result.add(e) else: ifs.add(e) else: result.add(e) - if ifs.PNode != nil: + if ifs != nil: var elseBranch = newTransNode(nkElse, n.info, 1) elseBranch[0] = ifs result.add(elseBranch) - elif result.PNode.lastSon.kind != nkElse and not ( - skipTypes(n.sons[0].typ, abstractVarRange).kind in + elif result.lastSon.kind != nkElse and not ( + skipTypes(n[0].typ, abstractVarRange).kind in {tyInt..tyInt64, tyChar, tyEnum, tyUInt..tyUInt64}): # fix a stupid code gen bug by normalizing: var elseBranch = newTransNode(nkElse, n.info, 1) elseBranch[0] = newTransNode(nkNilLit, n.info, 0) add(result, elseBranch) -proc transformArrayAccess(c: PTransf, n: PNode): PTransNode = +proc transformArrayAccess(c: PTransf, n: PNode): PNode = # XXX this is really bad; transf should use a proper AST visitor - if n.sons[0].kind == nkSym and n.sons[0].sym.kind == skType: - result = n.PTransNode + if n[0].kind == nkSym and n[0].sym.kind == skType: + result = n else: result = newTransNode(n) for i in 0 ..< n.len: - result[i] = transform(c, skipConv(n.sons[i])) + result[i] = transform(c, skipConv(n[i])) proc getMergeOp(n: PNode): PSym = case n.kind of nkCall, nkHiddenCallConv, nkCommand, nkInfix, nkPrefix, nkPostfix, nkCallStrLit: - if n.sons[0].kind == nkSym and n.sons[0].sym.magic == mConStrStr: - result = n.sons[0].sym + if n[0].kind == nkSym and n[0].sym.magic == mConStrStr: + result = n[0].sym else: discard proc flattenTreeAux(d, a: PNode, op: PSym) = let op2 = getMergeOp(a) if op2 != nil and (op2.id == op.id or op.magic != mNone and op2.magic == op.magic): - for i in 1 ..< len(a): flattenTreeAux(d, a.sons[i], op) + for i in 1 ..< len(a): flattenTreeAux(d, a[i], op) else: addSon(d, copyTree(a)) @@ -752,71 +734,71 @@ proc flattenTree(root: PNode): PNode = let op = getMergeOp(root) if op != nil: result = copyNode(root) - addSon(result, copyTree(root.sons[0])) + addSon(result, copyTree(root[0])) flattenTreeAux(result, root, op) else: result = root -proc transformCall(c: PTransf, n: PNode): PTransNode = +proc transformCall(c: PTransf, n: PNode): PNode = var n = flattenTree(n) let op = getMergeOp(n) let magic = getMagic(n) if op != nil and op.magic != mNone and n.len >= 3: result = newTransNode(nkCall, n, 0) - add(result, transform(c, n.sons[0])) + add(result, transform(c, n[0])) var j = 1 while j < len(n): - var a = transform(c, n.sons[j]).PNode + var a = transform(c, n[j]) inc(j) if isConstExpr(a): while (j < len(n)): - let b = transform(c, n.sons[j]).PNode + let b = transform(c, n[j]) if not isConstExpr(b): break a = evalOp(op.magic, n, a, b, nil, c.graph) inc(j) - add(result, a.PTransNode) + add(result, a) if len(result) == 2: result = result[1] elif magic == mAddr: result = newTransNode(nkAddr, n, 1) - result[0] = n[1].PTransNode - result = transformAddrDeref(c, result.PNode, nkDerefExpr, nkHiddenDeref) + result[0] = n[1] + result = transformAddrDeref(c, result, nkDerefExpr, nkHiddenDeref) elif magic in {mNBindSym, mTypeOf, mRunnableExamples}: # for bindSym(myconst) we MUST NOT perform constant folding: - result = n.PTransNode + result = n elif magic == mProcCall: # but do not change to its dispatcher: result = transformSons(c, n[1]) elif magic == mStrToStr: result = transform(c, n[1]) else: - let s = transformSons(c, n).PNode + let s = transformSons(c, n) # bugfix: check after 'transformSons' if it's still a method call: # use the dispatcher for the call: - if s.sons[0].kind == nkSym and s.sons[0].sym.kind == skMethod: + if s[0].kind == nkSym and s[0].sym.kind == skMethod: when false: - let t = lastSon(s.sons[0].sym.ast) + let t = lastSon(s[0].sym.ast) if t.kind != nkSym or sfDispatcher notin t.sym.flags: - methodDef(s.sons[0].sym, false) - result = methodCall(s, c.graph.config).PTransNode + methodDef(s[0].sym, false) + result = methodCall(s, c.graph.config) else: - result = s.PTransNode + result = s -proc transformExceptBranch(c: PTransf, n: PNode): PTransNode = +proc transformExceptBranch(c: PTransf, n: PNode): PNode = if n[0].isInfixAs() and not isImportedException(n[0][1].typ, c.graph.config): let excTypeNode = n[0][1] let actions = newTransNode(nkStmtListExpr, n[1], 2) # Generating `let exc = (excType)(getCurrentException())` # -> getCurrentException() - let excCall = PTransNode(callCodegenProc(c.graph, "getCurrentException")) + let excCall = callCodegenProc(c.graph, "getCurrentException") # -> (excType) let convNode = newTransNode(nkHiddenSubConv, n[1].info, 2) - convNode[0] = PTransNode(newNodeI(nkEmpty, n.info)) + convNode[0] = newNodeI(nkEmpty, n.info) convNode[1] = excCall - PNode(convNode).typ = excTypeNode.typ.toRef() + convNode.typ = excTypeNode.typ.toRef() # -> let exc = ... let identDefs = newTransNode(nkIdentDefs, n[1].info, 3) - identDefs[0] = PTransNode(n[0][2]) - identDefs[1] = PTransNode(newNodeI(nkEmpty, n.info)) + identDefs[0] = n[0][2] + identDefs[1] = newNodeI(nkEmpty, n.info) identDefs[2] = convNode let letSection = newTransNode(nkLetSection, n[1].info, 1) @@ -842,20 +824,20 @@ proc dontInlineConstant(orig, cnst: PNode): bool {.inline.} = proc commonOptimizations*(g: ModuleGraph; c: PSym, n: PNode): PNode = result = n for i in 0 ..< n.safeLen: - result.sons[i] = commonOptimizations(g, c, n.sons[i]) + result[i] = commonOptimizations(g, c, n[i]) var op = getMergeOp(n) if (op != nil) and (op.magic != mNone) and (len(n) >= 3): result = newNodeIT(nkCall, n.info, n.typ) - add(result, n.sons[0]) + add(result, n[0]) var args = newNode(nkArgList) flattenTreeAux(args, n, op) var j = 0 while j < len(args): - var a = args.sons[j] + var a = args[j] inc(j) if isConstExpr(a): while j < len(args): - let b = args.sons[j] + let b = args[j] if not isConstExpr(b): break a = evalOp(op.magic, result, a, b, nil, g) inc(j) @@ -936,7 +918,14 @@ proc initDefaultFields(obj, typNode: PNode, dontOverwrite: seq[PSym] = @[]): PNo else: return newNode(nkEmpty) else: assert(false) -proc transform(c: PTransf, n: PNode): PTransNode = +proc containsResult(n: PNode): bool = + if n.kind == nkSym and n.sym.kind == skResult: + result = true + else: + for i in 0.. 0: # we need to copy the variables for multiple yield statements: @@ -1064,39 +1060,38 @@ proc transform(c: PTransf, n: PNode): PTransNode = of nkAsgn: result = transformAsgn(c, n) of nkIdentDefs, nkConstDef: - result = PTransNode(n) + result = n result[0] = transform(c, n[0]) # Skip the second son since it only contains an unsemanticized copy of the # variable type used by docgen result[2] = transform(c, n[2]) # XXX comment handling really sucks: if importantComments(c.graph.config): - PNode(result).comment = n.comment + result.comment = n.comment of nkClosure: # it can happen that for-loop-inlining produced a fresh # set of variables, including some computed environment # (bug #2604). We need to patch this environment here too: let a = n[1] if a.kind == nkSym: - n.sons[1] = transformSymAux(c, a) - return PTransNode(n) + n[1] = transformSymAux(c, a) + return n of nkExceptBranch: result = transformExceptBranch(c, n) of nkObjConstr: - var res = newNodeIT(nkStmtListExpr, n.info, n.typ) + result = newNodeIT(nkStmtListExpr, n.info, n.typ) let sym = newSym(skTemp, getIdent(c.graph.cache, ":tmpO"), c.transCon.owner, n.info) sym.typ = n.typ let obj = newSymNode(sym) - res.add newTree(nkVarSection, newTree(nkIdentDefs, obj, newNode(nkEmpty), n)) + result.add newTree(nkVarSection, newTree(nkIdentDefs, obj, newNode(nkEmpty), n)) var providedFields: seq[PSym] for i in 1..