mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-13 14:53:46 +00:00
tuple unpacking works in a non-var/let context
This commit is contained in:
@@ -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 :-(
|
||||
|
||||
@@ -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
|
||||
|
||||
32
tests/tuples/tunpack_asgn.nim
Normal file
32
tests/tuples/tunpack_asgn.nim
Normal 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
|
||||
2
todo.txt
2
todo.txt
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user