blueloveTH 2 лет назад
Родитель
Сommit
ebe3193327
3 измененных файлов с 54 добавлено и 44 удалено
  1. 1 0
      src/codeobject.h
  2. 41 42
      src/compiler.h
  3. 12 2
      src/expr.h

+ 1 - 0
src/codeobject.h

@@ -61,6 +61,7 @@ struct CodeObject {
     std::vector<CodeBlock> blocks = { CodeBlock{NO_BLOCK, -1} };
     std::map<StrName, int> labels;
 
+    // may be.. just use a large NameDict?
     uint32_t perfect_locals_capacity = 2;
     uint32_t perfect_hash_seed = 0;
 

+ 41 - 42
src/compiler.h

@@ -1,13 +1,6 @@
 #pragma once
 
-#include "codeobject.h"
-#include "common.h"
-#include "lexer.h"
-#include "error.h"
-#include "ceval.h"
 #include "expr.h"
-#include "obj.h"
-#include "str.h"
 
 namespace pkpy{
 
@@ -21,9 +14,9 @@ struct PrattRule{
 };
 
 class Compiler {
+    inline static PrattRule rules[kTokenCount];
     std::unique_ptr<Lexer> lexer;
     stack<CodeEmitContext> contexts;
-    std::map<TokenIndex, PrattRule> rules;
     VM* vm;
     bool used;
     // for parsing token stream
@@ -33,7 +26,6 @@ class Compiler {
     const Token& prev() { return tokens.at(i-1); }
     const Token& curr() { return tokens.at(i); }
     const Token& next() { return tokens.at(i+1); }
-    const Token& peek(int offset) { return tokens.at(i+offset); }
     void advance() { i++; }
 
     CodeEmitContext* ctx() { return &contexts.top(); }
@@ -49,7 +41,7 @@ class Compiler {
 
     void pop_context(){
         if(!ctx()->s_expr.empty()) UNREACHABLE();
-        // if last instruction is not return, add a default return None
+        // if the last op does not return, add a default return None
         if(ctx()->co->codes.back().op != OP_RETURN_VALUE){
             ctx()->emit(OP_LOAD_NONE, BC_NOARG, BC_KEEPLINE);
             ctx()->emit(OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE);
@@ -58,14 +50,7 @@ class Compiler {
         contexts.pop();
     }
 
-public:
-    Compiler(VM* vm, const char* source, Str filename, CompileMode mode){
-        this->vm = vm;
-        this->used = false;
-        this->lexer = std::make_unique<Lexer>(
-            make_sp<SourceData>(source, filename, mode)
-        );
-
+    static void init_pratt_rules(){
 // http://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/
 #define METHOD(name) &Compiler::name
 #define NO_INFIX nullptr, PREC_NONE
@@ -112,22 +97,8 @@ public:
         rules[TK("@fstr")] =    { METHOD(exprFString),   NO_INFIX };
 #undef METHOD
 #undef NO_INFIX
-
-        // rules[TK("=")] =        { nullptr,               METHOD(exprAssign),         PREC_ASSIGNMENT };
-        // rules[TK("+=")] =       { nullptr,               METHOD(exprInplaceAssign),  PREC_ASSIGNMENT };
-        // rules[TK("-=")] =       { nullptr,               METHOD(exprInplaceAssign),  PREC_ASSIGNMENT };
-        // rules[TK("*=")] =       { nullptr,               METHOD(exprInplaceAssign),  PREC_ASSIGNMENT };
-        // rules[TK("/=")] =       { nullptr,               METHOD(exprInplaceAssign),  PREC_ASSIGNMENT };
-        // rules[TK("//=")] =      { nullptr,               METHOD(exprInplaceAssign),  PREC_ASSIGNMENT };
-        // rules[TK("%=")] =       { nullptr,               METHOD(exprInplaceAssign),  PREC_ASSIGNMENT };
-        // rules[TK("&=")] =       { nullptr,               METHOD(exprInplaceAssign),  PREC_ASSIGNMENT };
-        // rules[TK("|=")] =       { nullptr,               METHOD(exprInplaceAssign),  PREC_ASSIGNMENT };
-        // rules[TK("^=")] =       { nullptr,               METHOD(exprInplaceAssign),  PREC_ASSIGNMENT };
-        // rules[TK(">>=")] =      { nullptr,               METHOD(exprInplaceAssign),  PREC_ASSIGNMENT };
-        // rules[TK("<<=")] =      { nullptr,               METHOD(exprInplaceAssign),  PREC_ASSIGNMENT };
     }
 
-private:
     bool match(TokenIndex expected) {
         if (curr().type != expected) return false;
         advance();
@@ -206,7 +177,7 @@ private:
             consume(TK(":"));
         }
         e->func.code = push_context(lexer->src, "<lambda>");
-        EXPR(true); // https://github.com/blueloveTH/pocketpy/issues/37
+        EXPR(false); // https://github.com/blueloveTH/pocketpy/issues/37
         ctx()->emit(OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE);
         pop_context();
         ctx()->s_expr.push(std::move(e));
@@ -464,8 +435,8 @@ private:
     Str _compile_import() {
         consume(TK("@id"));
         Str name = prev().str();
-        int index = ctx()->add_name(name, NAME_SPECIAL);
-        ctx()->emit(OP_IMPORT_NAME, index, peek(-2).line);
+        int index = ctx()->add_name(name);
+        ctx()->emit(OP_IMPORT_NAME, index, prev().line);
         return name;
     }
 
@@ -525,8 +496,9 @@ private:
         if(!push_stack) ctx()->emit_expr();
     }
 
+    // PASS
     void compile_if_stmt() {
-        EXPR(true);   // condition
+        EXPR(false);   // condition
         int patch = ctx()->emit(OP_POP_JUMP_IF_FALSE, BC_NOARG, prev().line);
         compile_block_body();
         if (match(TK("elif"))) {
@@ -544,9 +516,10 @@ private:
         }
     }
 
+    // PASS
     void compile_while_loop() {
         ctx()->enter_block(WHILE_LOOP);
-        EXPR(true);   // condition
+        EXPR(false);   // condition
         int patch = ctx()->emit(OP_POP_JUMP_IF_FALSE, BC_NOARG, prev().line);
         compile_block_body();
         ctx()->emit(OP_LOOP_CONTINUE, BC_NOARG, BC_KEEPLINE);
@@ -556,12 +529,17 @@ private:
 
     void compile_for_loop() {
         EXPR_TUPLE();
-        ctx()->emit_lvalue();
+        Expr_ vars = ctx()->s_expr.popx();
         consume(TK("in"));
-        EXPR(true);
+        EXPR(false);
         ctx()->emit(OP_GET_ITER, BC_NOARG, BC_KEEPLINE);
         ctx()->enter_block(FOR_LOOP);
         ctx()->emit(OP_FOR_ITER, BC_NOARG, BC_KEEPLINE);
+        // set variables and handle implicit unpack
+        bool ok = vars->emit_store(ctx());
+        // this error occurs in `vars` instead of this line
+        // but...nevermind
+        if(!ok) SyntaxError();
         compile_block_body();
         ctx()->emit(OP_LOOP_CONTINUE, BC_NOARG, BC_KEEPLINE);
         ctx()->exit_block();
@@ -596,7 +574,7 @@ private:
     }
 
     void compile_decorated(){
-        EXPR(true);
+        EXPR(false);
         if(!match_newlines(mode()==REPL_MODE)) SyntaxError();
         ctx()->emit(OP_SETUP_DECORATOR, BC_NOARG, prev().line);
         consume(TK("def"));
@@ -680,7 +658,7 @@ private:
                 consume(TK("@id"));
                 int dummy_t = ctx()->add_name(prev().str(), NAME_SPECIAL);
                 if(match(TK("(")) && !match(TK(")"))){
-                    EXPR(true); consume(TK(")"));
+                    EXPR(false); consume(TK(")"));
                 }else{
                     ctx()->emit(OP_LOAD_NONE, BC_NOARG, BC_KEEPLINE);
                 }
@@ -697,7 +675,7 @@ private:
             case TK("with"): {
                 // TODO: reimpl this
                 UNREACHABLE();
-                // EXPR(true);
+                // EXPR(false);
                 // consume(TK("as"));
                 // consume(TK("@id"));
                 // int index = ctx()->add_name(prev().str(), name_scope());
@@ -859,6 +837,27 @@ private:
     void IndentationError(Str msg){ lexer->throw_err("IndentationError", msg, curr().line, curr().start); }
 
 public:
+    Compiler(VM* vm, const char* source, Str filename, CompileMode mode){
+        this->vm = vm;
+        this->used = false;
+        this->lexer = std::make_unique<Lexer>(
+            make_sp<SourceData>(source, filename, mode)
+        );
+        if(rules.empty()) init_pratt_rules();
+        // rules[TK("=")] =        { nullptr,               METHOD(exprAssign),         PREC_ASSIGNMENT };
+        // rules[TK("+=")] =       { nullptr,               METHOD(exprInplaceAssign),  PREC_ASSIGNMENT };
+        // rules[TK("-=")] =       { nullptr,               METHOD(exprInplaceAssign),  PREC_ASSIGNMENT };
+        // rules[TK("*=")] =       { nullptr,               METHOD(exprInplaceAssign),  PREC_ASSIGNMENT };
+        // rules[TK("/=")] =       { nullptr,               METHOD(exprInplaceAssign),  PREC_ASSIGNMENT };
+        // rules[TK("//=")] =      { nullptr,               METHOD(exprInplaceAssign),  PREC_ASSIGNMENT };
+        // rules[TK("%=")] =       { nullptr,               METHOD(exprInplaceAssign),  PREC_ASSIGNMENT };
+        // rules[TK("&=")] =       { nullptr,               METHOD(exprInplaceAssign),  PREC_ASSIGNMENT };
+        // rules[TK("|=")] =       { nullptr,               METHOD(exprInplaceAssign),  PREC_ASSIGNMENT };
+        // rules[TK("^=")] =       { nullptr,               METHOD(exprInplaceAssign),  PREC_ASSIGNMENT };
+        // rules[TK(">>=")] =      { nullptr,               METHOD(exprInplaceAssign),  PREC_ASSIGNMENT };
+        // rules[TK("<<=")] =      { nullptr,               METHOD(exprInplaceAssign),  PREC_ASSIGNMENT };
+    }
+
     CodeObject_ compile(){
         if(used) UNREACHABLE();
         used = true;

+ 12 - 2
src/expr.h

@@ -6,7 +6,6 @@
 #include "error.h"
 #include "ceval.h"
 
-
 namespace pkpy{
 
 struct CodeEmitContext;
@@ -369,7 +368,18 @@ struct TupleExpr: SequenceExpr{
     Opcode opcode() const override { return OP_BUILD_TUPLE; }
 
     bool emit_store(CodeEmitContext* ctx) override {
-        // ...
+        // assume TOS is an iterable
+        // unpack it and emit several OP_STORE
+        // https://docs.python.org/3/library/dis.html#opcode-UNPACK_SEQUENCE
+        // https://docs.python.org/3/library/dis.html#opcode-UNPACK_EX
+        return true;
+    }
+
+    bool emit_del(CodeEmitContext* ctx) override{
+        for(auto& e: items){
+            bool ok = e->emit_del(ctx);
+            if(!ok) return false;
+        }
         return true;
     }
 };