mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-21 20:10:17 +00:00
impl listcomp(with if)
This commit is contained in:
parent
bb651906c3
commit
f2e589a5a3
@ -55,10 +55,11 @@ struct CodeObject {
|
|||||||
return co_consts.size() - 1;
|
return co_consts.size() - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void __copyToEnd(int start, int end){
|
void __moveToEnd(int start, int end){
|
||||||
auto _start = co_code.begin() + start;
|
auto _start = co_code.begin() + start;
|
||||||
auto _end = co_code.begin() + end;
|
auto _end = co_code.begin() + end;
|
||||||
co_code.insert(co_code.end(), _start, _end);
|
co_code.insert(co_code.end(), _start, _end);
|
||||||
|
for(int i=start; i<end; i++) co_code[i].op = OP_NO_OP;
|
||||||
}
|
}
|
||||||
|
|
||||||
_Str toString(){
|
_Str toString(){
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
class Compiler;
|
class Compiler;
|
||||||
|
|
||||||
typedef void (Compiler::*GrammarFn)();
|
typedef void (Compiler::*GrammarFn)();
|
||||||
typedef std::function<void(Compiler*)> CompilerAction;
|
typedef void (Compiler::*CompilerAction)();
|
||||||
|
|
||||||
struct GrammarRule{
|
struct GrammarRule{
|
||||||
GrammarFn prefix;
|
GrammarFn prefix;
|
||||||
@ -450,12 +450,33 @@ __LISTCOMP:
|
|||||||
getCode()->co_code[_patch].op = OP_JUMP_ABSOLUTE;
|
getCode()->co_code[_patch].op = OP_JUMP_ABSOLUTE;
|
||||||
getCode()->co_code[_patch].arg = _body_end;
|
getCode()->co_code[_patch].arg = _body_end;
|
||||||
emitCode(OP_BUILD_LIST, 0);
|
emitCode(OP_BUILD_LIST, 0);
|
||||||
__compileForLoop([=](Compiler* compiler){
|
EXPR_FOR_VARS();consume(TK("in"));EXPR_TUPLE();
|
||||||
// [list, iter]
|
matchNewLines();
|
||||||
getCode()->__copyToEnd(_body_start, _body_end);
|
|
||||||
// [list, iter, value]
|
int _skipPatch = emitCode(OP_JUMP_ABSOLUTE);
|
||||||
|
int _cond_start = getCode()->co_code.size();
|
||||||
|
if(match(TK("if"))) EXPR_TUPLE();
|
||||||
|
int _cond_end = getCode()->co_code.size();
|
||||||
|
patchJump(_skipPatch);
|
||||||
|
|
||||||
|
emitCode(OP_GET_ITER);
|
||||||
|
Loop& loop = enterLoop(true);
|
||||||
|
int patch = emitCode(OP_FOR_ITER);
|
||||||
|
|
||||||
|
if(_cond_end != _cond_start) { // there is an if condition
|
||||||
|
getCode()->__moveToEnd(_cond_start, _cond_end);
|
||||||
|
int ifpatch = emitCode(OP_POP_JUMP_IF_FALSE);
|
||||||
|
getCode()->__moveToEnd(_body_start, _body_end);
|
||||||
emitCode(OP_LIST_APPEND);
|
emitCode(OP_LIST_APPEND);
|
||||||
});
|
patchJump(ifpatch);
|
||||||
|
}else{
|
||||||
|
getCode()->__moveToEnd(_body_start, _body_end);
|
||||||
|
emitCode(OP_LIST_APPEND);
|
||||||
|
}
|
||||||
|
|
||||||
|
emitCode(OP_JUMP_ABSOLUTE, loop.start); keepOpcodeLine();
|
||||||
|
patchJump(patch);
|
||||||
|
exitLoop();
|
||||||
consume(TK("]"));
|
consume(TK("]"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -547,7 +568,7 @@ __LISTCOMP:
|
|||||||
return getCode()->co_code.size() - 1;
|
return getCode()->co_code.size() - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void patchJump(int addr_index) {
|
inline void patchJump(int addr_index) {
|
||||||
int target = getCode()->co_code.size();
|
int target = getCode()->co_code.size();
|
||||||
getCode()->co_code[addr_index].arg = target;
|
getCode()->co_code[addr_index].arg = target;
|
||||||
}
|
}
|
||||||
@ -563,7 +584,7 @@ __LISTCOMP:
|
|||||||
}
|
}
|
||||||
consume(TK("@indent"));
|
consume(TK("@indent"));
|
||||||
while (peek() != TK("@dedent")) {
|
while (peek() != TK("@dedent")) {
|
||||||
action(this);
|
(this->*action)();
|
||||||
matchNewLines();
|
matchNewLines();
|
||||||
}
|
}
|
||||||
consume(TK("@dedent"));
|
consume(TK("@dedent"));
|
||||||
@ -652,19 +673,21 @@ __LISTCOMP:
|
|||||||
exitLoop();
|
exitLoop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void __compileForLoop(CompilerAction action) {
|
void EXPR_FOR_VARS(){
|
||||||
int size = 0;
|
int size = 0;
|
||||||
do {
|
do {
|
||||||
consume(TK("@id"));
|
consume(TK("@id"));
|
||||||
exprName(); size++;
|
exprName(); size++;
|
||||||
} while (match(TK(",")));
|
} while (match(TK(",")));
|
||||||
if(size > 1) emitCode(OP_BUILD_SMART_TUPLE, size);
|
if(size > 1) emitCode(OP_BUILD_SMART_TUPLE, size);
|
||||||
consume(TK("in"));
|
}
|
||||||
EXPR_TUPLE();
|
|
||||||
emitCode(OP_GET_ITER); // [ptr, list] -> iter
|
void compileForLoop() {
|
||||||
|
EXPR_FOR_VARS();consume(TK("in"));EXPR_TUPLE();
|
||||||
|
emitCode(OP_GET_ITER);
|
||||||
Loop& loop = enterLoop(true);
|
Loop& loop = enterLoop(true);
|
||||||
int patch = emitCode(OP_FOR_ITER);
|
int patch = emitCode(OP_FOR_ITER);
|
||||||
action(this);
|
compileBlockBody();
|
||||||
emitCode(OP_JUMP_ABSOLUTE, loop.start); keepOpcodeLine();
|
emitCode(OP_JUMP_ABSOLUTE, loop.start); keepOpcodeLine();
|
||||||
patchJump(patch);
|
patchJump(patch);
|
||||||
exitLoop();
|
exitLoop();
|
||||||
@ -698,7 +721,7 @@ __LISTCOMP:
|
|||||||
} else if (match(TK("while"))) {
|
} else if (match(TK("while"))) {
|
||||||
compileWhileLoop();
|
compileWhileLoop();
|
||||||
} else if (match(TK("for"))) {
|
} else if (match(TK("for"))) {
|
||||||
__compileForLoop(&Compiler::compileBlockBody);
|
compileForLoop();
|
||||||
} else if(match(TK("assert"))){
|
} else if(match(TK("assert"))){
|
||||||
EXPR();
|
EXPR();
|
||||||
emitCode(OP_ASSERT);
|
emitCode(OP_ASSERT);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user