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; 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(){ _Str toString(){
_StrStream ss; _StrStream ss;
int prev_line = -1; int prev_line = -1;
@ -95,7 +101,7 @@ struct CodeObject {
class Frame { class Frame {
private: private:
std::stack<PyVar> s_data; std::vector<PyVar> s_data;
int ip = 0; int ip = 0;
public: public:
StlDict* f_globals; StlDict* f_globals;
@ -124,8 +130,8 @@ public:
} }
inline PyVar __pop(){ inline PyVar __pop(){
PyVar v = s_data.top(); PyVar v = s_data.back();
s_data.pop(); s_data.pop_back();
return v; return v;
} }
@ -136,11 +142,15 @@ public:
} }
inline PyVar topValue(VM* vm){ 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){ inline void push(PyVar v){
s_data.push(v); s_data.push_back(v);
} }
inline void jumpTo(int i){ inline void jumpTo(int i){

View File

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

View File

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

View File

@ -162,6 +162,7 @@ public:
switch (byte.op) 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_CONST: frame->push(frame->code->co_consts[byte.arg]); break;
case OP_LOAD_NAME_PTR: { case OP_LOAD_NAME_PTR: {
frame->push(PyPointer(frame->code->co_names[byte.arg])); frame->push(PyPointer(frame->code->co_names[byte.arg]));
@ -220,6 +221,11 @@ public:
case OP_LOAD_EVAL_FN: { case OP_LOAD_EVAL_FN: {
frame->push(builtins->attribs["eval"]); frame->push(builtins->attribs["eval"]);
} break; } 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: case OP_STORE_FUNCTION:
{ {
PyVar obj = frame->popValue(this); PyVar obj = frame->popValue(this);