tuple unpacking works in a non-var/let context

This commit is contained in:
Araq
2015-08-21 12:31:55 +02:00
parent 2733c508ef
commit bfd2fd67f9
5 changed files with 69 additions and 2 deletions

View File

@@ -63,6 +63,32 @@ proc lowerTupleUnpacking*(n: PNode; owner: PSym): PNode =
if n.sons[i].kind == nkSym: v.addVar(n.sons[i])
result.add newAsgnStmt(n.sons[i], newTupleAccess(tempAsNode, i))
proc newTupleAccessRaw*(tup: PNode, i: int): PNode =
result = newNodeI(nkBracketExpr, tup.info)
addSon(result, copyTree(tup))
var lit = newNodeI(nkIntLit, tup.info)
lit.intVal = i
addSon(result, lit)
proc lowerTupleUnpackingForAsgn*(n: PNode; owner: PSym): PNode =
let value = n.lastSon
result = newNodeI(nkStmtList, n.info)
var temp = newSym(skTemp, getIdent(genPrefix), owner, value.info)
var v = newNodeI(nkLetSection, value.info)
let tempAsNode = newIdentNode(getIdent(genPrefix & $temp.id), value.info)
var vpart = newNodeI(nkIdentDefs, tempAsNode.info, 3)
vpart.sons[0] = tempAsNode
vpart.sons[1] = ast.emptyNode
vpart.sons[2] = value
addSon(v, vpart)
result.add(v)
let lhs = n.sons[0]
for i in 0 .. lhs.len-1:
result.add newAsgnStmt(lhs.sons[i], newTupleAccessRaw(tempAsNode, i))
proc lowerSwap*(n: PNode; owner: PSym): PNode =
result = newNodeI(nkStmtList, n.info)
# note: cannot use 'skTemp' here cause we really need the copy for the VM :-(

View File

@@ -1282,6 +1282,14 @@ proc semAsgn(c: PContext, n: PNode): PNode =
result = buildOverloadedSubscripts(n.sons[0], getIdent"{}=")
add(result, n[1])
return semExprNoType(c, result)
of nkPar:
if a.len >= 2:
# unfortunately we need to rewrite ``(x, y) = foo()`` already here so
# that overloading of the assignment operator still works. Usually we
# prefer to do these rewritings in transf.nim:
return semStmt(c, lowerTupleUnpackingForAsgn(n, c.p.owner))
else:
a = semExprWithType(c, a, {efLValue})
else:
a = semExprWithType(c, a, {efLValue})
n.sons[0] = a

View File

@@ -0,0 +1,32 @@
discard """
output: '''2 4
4
2 0'''
"""
proc foobar(): (int, int) = (2, 4)
# test within a proc:
proc pp(x: var int) =
var y: int
(y, x) = foobar()
template pt(x) =
var y: int
(x, y) = foobar()
# test within a generic:
proc pg[T](x, y: var T) =
pt(x)
# test as a top level statement:
var x, y, a, b: int
(x, y) = fooBar()
echo x, " ", y
pp(a)
echo a
pg(a, b)
echo a, " ", b

View File

@@ -1,8 +1,6 @@
version 0.11.4
==============
- make tuple unpacking work in a non-var/let context
- document special cased varargs[untyped] and varargs[typed]
- The remaining bugs of the lambda lifting pass that is responsible to enable

View File

@@ -72,6 +72,9 @@ News
- Added ``macros.getImpl`` that can be used to access the implementation of
a routine or a constant. This allows for example for user-defined inlining
of function calls.
- Tuple unpacking finally works in a non-var/let context: ``(x, y) == f()``
is allowed. Note that this doesn't declare ``x`` and ``y`` variables, for
this ``let (x, y) == f()`` still needs to be used.
Bugfixes