mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-24 21:40:16 +00:00
up
This commit is contained in:
parent
a6b4671711
commit
ebe3193327
@ -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;
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
14
src/expr.h
14
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;
|
||||
}
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user