Support chained 'for's in generator expressions
This commit is contained in:
parent
0f6b74ff5b
commit
35b4032de3
@ -2252,23 +2252,8 @@ static void singleInner(ssize_t indLoopCounter) {
|
|||||||
expression();
|
expression();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Parser a generator expression.
|
|
||||||
*
|
|
||||||
* This is essentially the same as a comprehension body, but
|
|
||||||
* without the added loop index or wrapping function call.
|
|
||||||
*
|
|
||||||
* After every inner expression, we yield.
|
|
||||||
*/
|
|
||||||
static void generatorExpression(KrkScanner scannerBefore, Parser parserBefore) {
|
|
||||||
parser.previous = syntheticToken("<genexpr>");
|
|
||||||
Compiler subcompiler;
|
|
||||||
initCompiler(&subcompiler, TYPE_FUNCTION);
|
|
||||||
subcompiler.function->chunk.filename = subcompiler.enclosing->function->chunk.filename;
|
|
||||||
subcompiler.function->isGenerator = 1;
|
|
||||||
|
|
||||||
beginScope();
|
|
||||||
|
|
||||||
|
static void generatorInner(KrkScanner scannerBefore, Parser parserBefore) {
|
||||||
ssize_t loopInd = current->localCount;
|
ssize_t loopInd = current->localCount;
|
||||||
ssize_t varCount = 0;
|
ssize_t varCount = 0;
|
||||||
do {
|
do {
|
||||||
@ -2320,21 +2305,43 @@ static void generatorExpression(KrkScanner scannerBefore, Parser parserBefore) {
|
|||||||
emitByte(OP_POP); /* Pop condition */
|
emitByte(OP_POP); /* Pop condition */
|
||||||
}
|
}
|
||||||
|
|
||||||
KrkScanner scannerAfter = krk_tellScanner();
|
|
||||||
Parser parserAfter = parser;
|
|
||||||
krk_rewindScanner(scannerBefore);
|
|
||||||
parser = parserBefore;
|
|
||||||
|
|
||||||
beginScope();
|
beginScope();
|
||||||
expression();
|
if (match(TOKEN_FOR)) {
|
||||||
emitByte(OP_YIELD);
|
generatorInner(scannerBefore, parserBefore);
|
||||||
|
} else {
|
||||||
|
KrkScanner scannerAfter = krk_tellScanner();
|
||||||
|
Parser parserAfter = parser;
|
||||||
|
krk_rewindScanner(scannerBefore);
|
||||||
|
parser = parserBefore;
|
||||||
|
expression();
|
||||||
|
emitByte(OP_YIELD);
|
||||||
|
krk_rewindScanner(scannerAfter);
|
||||||
|
parser = parserAfter;
|
||||||
|
}
|
||||||
endScope();
|
endScope();
|
||||||
|
|
||||||
krk_rewindScanner(scannerAfter);
|
|
||||||
parser = parserAfter;
|
|
||||||
|
|
||||||
emitLoop(loopStart);
|
emitLoop(loopStart);
|
||||||
patchJump(exitJump);
|
patchJump(exitJump);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Parser a generator expression.
|
||||||
|
*
|
||||||
|
* This is essentially the same as a comprehension body, but
|
||||||
|
* without the added loop index or wrapping function call.
|
||||||
|
*
|
||||||
|
* After every inner expression, we yield.
|
||||||
|
*/
|
||||||
|
static void generatorExpression(KrkScanner scannerBefore, Parser parserBefore) {
|
||||||
|
parser.previous = syntheticToken("<genexpr>");
|
||||||
|
Compiler subcompiler;
|
||||||
|
initCompiler(&subcompiler, TYPE_FUNCTION);
|
||||||
|
subcompiler.function->chunk.filename = subcompiler.enclosing->function->chunk.filename;
|
||||||
|
subcompiler.function->isGenerator = 1;
|
||||||
|
|
||||||
|
beginScope();
|
||||||
|
generatorInner(scannerBefore, parserBefore);
|
||||||
|
endScope();
|
||||||
|
|
||||||
KrkFunction *subfunction = endCompiler();
|
KrkFunction *subfunction = endCompiler();
|
||||||
size_t indFunc = krk_addConstant(currentChunk(), OBJECT_VAL(subfunction));
|
size_t indFunc = krk_addConstant(currentChunk(), OBJECT_VAL(subfunction));
|
||||||
|
@ -19,3 +19,5 @@ try:
|
|||||||
except SyntaxError as e:
|
except SyntaxError as e:
|
||||||
print('parenthesized' in str(e))
|
print('parenthesized' in str(e))
|
||||||
|
|
||||||
|
let matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]]
|
||||||
|
print(list(entry for row in matrix for entry in row))
|
||||||
|
@ -3,3 +3,4 @@
|
|||||||
True
|
True
|
||||||
285
|
285
|
||||||
True
|
True
|
||||||
|
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
|
||||||
|
Loading…
Reference in New Issue
Block a user