Add tuple unpacking and 'if' conditions to list comprehensions
This commit is contained in:
parent
fc05327c42
commit
070b4bc356
33
compiler.c
33
compiler.c
@ -1610,13 +1610,17 @@ static void list(int canAssign) {
|
|||||||
|
|
||||||
/* x in... */
|
/* x in... */
|
||||||
ssize_t loopInd = current->localCount;
|
ssize_t loopInd = current->localCount;
|
||||||
varDeclaration();
|
ssize_t varCount = 0;
|
||||||
defineVariable(loopInd);
|
do {
|
||||||
|
varDeclaration();
|
||||||
|
defineVariable(loopInd);
|
||||||
|
varCount++;
|
||||||
|
} while (match(TOKEN_COMMA));
|
||||||
|
|
||||||
consume(TOKEN_IN, "Only iterator loops (for ... in ...) are allowed in list comprehensions.");
|
consume(TOKEN_IN, "Only iterator loops (for ... in ...) are allowed in list comprehensions.");
|
||||||
|
|
||||||
beginScope();
|
beginScope();
|
||||||
expression();
|
parsePrecedence(PREC_OR); /* Otherwise we can get trapped on a ternary */
|
||||||
endScope();
|
endScope();
|
||||||
|
|
||||||
/* iterable... */
|
/* iterable... */
|
||||||
@ -1649,10 +1653,29 @@ static void list(int canAssign) {
|
|||||||
* and there's no feasible way they can return themselves without
|
* and there's no feasible way they can return themselves without
|
||||||
* our intended sentinel meaning, right? Surely? */
|
* our intended sentinel meaning, right? Surely? */
|
||||||
EMIT_CONSTANT_OP(OP_GET_LOCAL, indLoopIter);
|
EMIT_CONSTANT_OP(OP_GET_LOCAL, indLoopIter);
|
||||||
emitBytes(OP_EQUAL, OP_NOT);
|
emitByte(OP_EQUAL);
|
||||||
int exitJump = emitJump(OP_JUMP_IF_FALSE);
|
int exitJump = emitJump(OP_JUMP_IF_TRUE);
|
||||||
emitByte(OP_POP);
|
emitByte(OP_POP);
|
||||||
|
|
||||||
|
/* Unpack tuple */
|
||||||
|
if (varCount > 1) {
|
||||||
|
EMIT_CONSTANT_OP(OP_GET_LOCAL, loopInd);
|
||||||
|
EMIT_CONSTANT_OP(OP_UNPACK_TUPLE, varCount);
|
||||||
|
for (ssize_t i = loopInd + varCount - 1; i >= loopInd; i--) {
|
||||||
|
EMIT_CONSTANT_OP(OP_SET_LOCAL, i);
|
||||||
|
emitByte(OP_POP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match(TOKEN_IF)) {
|
||||||
|
parsePrecedence(PREC_OR);
|
||||||
|
int acceptJump = emitJump(OP_JUMP_IF_TRUE);
|
||||||
|
emitByte(OP_POP); /* Pop condition */
|
||||||
|
emitLoop(loopStart);
|
||||||
|
patchJump(acceptJump);
|
||||||
|
emitByte(OP_POP); /* Pop condition */
|
||||||
|
}
|
||||||
|
|
||||||
/* Now we can rewind the scanner to have it parse the original
|
/* Now we can rewind the scanner to have it parse the original
|
||||||
* expression that uses our iterated values! */
|
* expression that uses our iterated values! */
|
||||||
KrkScanner scannerAfter = krk_tellScanner();
|
KrkScanner scannerAfter = krk_tellScanner();
|
||||||
|
@ -29,3 +29,12 @@ for i in {'a': 1, 2: 'b'}.items():
|
|||||||
print(i)
|
print(i)
|
||||||
# ('a', 1)
|
# ('a', 1)
|
||||||
# (2, 'b')
|
# (2, 'b')
|
||||||
|
|
||||||
|
print(['{}: {}'.format(repr(k),repr(v)) for k, v in {1: 2, 3: 4}.items()])
|
||||||
|
# ['1: 2', '3: 4']
|
||||||
|
|
||||||
|
print([x for x,y in [(1,2),(3,4),(5,6)] if x + y > 3])
|
||||||
|
# [3, 5]
|
||||||
|
|
||||||
|
print(', '.join(['{}: {}'.format(repr(k),repr(v)) for k, v in {1: 2, '3': 4, 5: 'six', 'seven': 8}.items() if isinstance(k,str)]))
|
||||||
|
# '3': 4, 'seven': 8
|
||||||
|
@ -9,3 +9,6 @@ a 1
|
|||||||
2 b
|
2 b
|
||||||
('a', 1)
|
('a', 1)
|
||||||
(2, 'b')
|
(2, 'b')
|
||||||
|
['1: 2', '3: 4']
|
||||||
|
[3, 5]
|
||||||
|
'3': 4, 'seven': 8
|
||||||
|
Loading…
Reference in New Issue
Block a user