add listcomp support

This commit is contained in:
blueloveTH 2022-11-08 20:13:52 +08:00
parent 5761d0b69c
commit bb651906c3
4 changed files with 58 additions and 15 deletions

View File

@ -55,6 +55,12 @@ struct CodeObject {
return co_consts.size() - 1;
}
void __copyToEnd(int start, int end){
auto _start = co_code.begin() + start;
auto _end = co_code.begin() + end;
co_code.insert(co_code.end(), _start, _end);
}
_Str toString(){
_StrStream ss;
int prev_line = -1;
@ -95,7 +101,7 @@ struct CodeObject {
class Frame {
private:
std::stack<PyVar> s_data;
std::vector<PyVar> s_data;
int ip = 0;
public:
StlDict* f_globals;
@ -124,8 +130,8 @@ public:
}
inline PyVar __pop(){
PyVar v = s_data.top();
s_data.pop();
PyVar v = s_data.back();
s_data.pop_back();
return v;
}
@ -136,11 +142,15 @@ public:
}
inline PyVar topValue(VM* vm){
return __deref_pointer(vm, s_data.top());
return __deref_pointer(vm, s_data.back());
}
inline PyVar topNValue(VM* vm, int n=-1){
return __deref_pointer(vm, s_data[s_data.size() + n]);
}
inline void push(PyVar v){
s_data.push(v);
s_data.push_back(v);
}
inline void jumpTo(int i){

View File

@ -11,7 +11,7 @@
class Compiler;
typedef void (Compiler::*GrammarFn)();
typedef void (Compiler::*CompilerAction)();
typedef std::function<void(Compiler*)> CompilerAction;
struct GrammarRule{
GrammarFn prefix;
@ -430,8 +430,33 @@ public:
}
void exprList() {
ExprCommaSplitArgs("]");
int _patch = emitCode(OP_NO_OP);
int _body_start = getCode()->co_code.size();
int ARGC = 0;
do {
matchNewLines();
if (peek() == TK("]")) break;
EXPR(); ARGC++;
matchNewLines();
if(ARGC == 1 && match(TK("for"))) goto __LISTCOMP;
} while (match(TK(",")));
matchNewLines();
consume(TK("]"));
emitCode(OP_BUILD_LIST, ARGC);
return;
__LISTCOMP:
int _body_end = getCode()->co_code.size();
getCode()->co_code[_patch].op = OP_JUMP_ABSOLUTE;
getCode()->co_code[_patch].arg = _body_end;
emitCode(OP_BUILD_LIST, 0);
__compileForLoop([=](Compiler* compiler){
// [list, iter]
getCode()->__copyToEnd(_body_start, _body_end);
// [list, iter, value]
emitCode(OP_LIST_APPEND);
});
consume(TK("]"));
}
void exprMap() {
@ -538,7 +563,7 @@ public:
}
consume(TK("@indent"));
while (peek() != TK("@dedent")) {
(this->*action)();
action(this);
matchNewLines();
}
consume(TK("@dedent"));
@ -617,7 +642,7 @@ public:
loops.pop();
}
void compileWhileStatement() {
void compileWhileLoop() {
Loop& loop = enterLoop(false);
EXPR_TUPLE();
int patch = emitCode(OP_POP_JUMP_IF_FALSE);
@ -627,12 +652,11 @@ public:
exitLoop();
}
void compileForStatement() {
void __compileForLoop(CompilerAction action) {
int size = 0;
do {
consume(TK("@id"));
exprName(); // push a name ptr into stack
size++;
exprName(); size++;
} while (match(TK(",")));
if(size > 1) emitCode(OP_BUILD_SMART_TUPLE, size);
consume(TK("in"));
@ -640,7 +664,7 @@ public:
emitCode(OP_GET_ITER); // [ptr, list] -> iter
Loop& loop = enterLoop(true);
int patch = emitCode(OP_FOR_ITER);
compileBlockBody();
action(this);
emitCode(OP_JUMP_ABSOLUTE, loop.start); keepOpcodeLine();
patchJump(patch);
exitLoop();
@ -672,9 +696,9 @@ public:
} else if (match(TK("if"))) {
compileIfStatement();
} else if (match(TK("while"))) {
compileWhileStatement();
compileWhileLoop();
} else if (match(TK("for"))) {
compileForStatement();
__compileForLoop(&Compiler::compileBlockBody);
} else if(match(TK("assert"))){
EXPR();
emitCode(OP_ASSERT);

View File

@ -1,5 +1,6 @@
#ifdef OPCODE
OPCODE(NO_OP)
OPCODE(LOAD_CONST)
OPCODE(IMPORT_NAME)
OPCODE(PRINT_EXPR)
@ -21,6 +22,8 @@ OPCODE(BUILD_LIST)
OPCODE(BUILD_MAP)
OPCODE(BUILD_SLICE)
OPCODE(LIST_APPEND)
OPCODE(GET_ITER)
OPCODE(FOR_ITER)

View File

@ -162,6 +162,7 @@ public:
switch (byte.op)
{
case OP_NO_OP: break; // do nothing
case OP_LOAD_CONST: frame->push(frame->code->co_consts[byte.arg]); break;
case OP_LOAD_NAME_PTR: {
frame->push(PyPointer(frame->code->co_names[byte.arg]));
@ -220,6 +221,11 @@ public:
case OP_LOAD_EVAL_FN: {
frame->push(builtins->attribs["eval"]);
} break;
case OP_LIST_APPEND: {
PyVar obj = frame->popValue(this);
PyVar list = frame->topNValue(this, -2);
fastCall(list, "append", {list, obj});
} break;
case OP_STORE_FUNCTION:
{
PyVar obj = frame->popValue(this);