This commit is contained in:
blueloveTH 2023-04-03 22:21:09 +08:00
parent 190d2a0589
commit e4e43826fe
10 changed files with 148 additions and 135 deletions

View File

@ -2,8 +2,6 @@
#include "common.h" #include "common.h"
#include "vm.h" #include "vm.h"
#include <type_traits>
#include <vector>
namespace pkpy { namespace pkpy {

View File

@ -26,12 +26,13 @@
#include <random> #include <random>
#include <initializer_list> #include <initializer_list>
#include <variant> #include <variant>
#include <type_traits>
#define PK_VERSION "0.9.6" #define PK_VERSION "0.9.6"
// debug macros // debug macros
#define DEBUG_NO_BUILTIN_MODULES 0 #define DEBUG_NO_BUILTIN_MODULES 1
#define DEBUG_EXTRA_CHECK 1 #define DEBUG_MODE 1
#if (defined(__ANDROID__) && __ANDROID_API__ <= 22) || defined(__EMSCRIPTEN__) #if (defined(__ANDROID__) && __ANDROID_API__ <= 22) || defined(__EMSCRIPTEN__)
#define PK_ENABLE_FILEIO 0 #define PK_ENABLE_FILEIO 0

View File

@ -26,7 +26,7 @@ class Compiler {
const Token& prev() { return tokens.at(i-1); } const Token& prev() { return tokens.at(i-1); }
const Token& curr() { return tokens.at(i); } const Token& curr() { return tokens.at(i); }
const Token& next() { return tokens.at(i+1); } const Token& next() { return tokens.at(i+1); }
void advance() { i++; } void advance(int delta=1) { i += delta; }
CodeEmitContext* ctx() { return &contexts.top(); } CodeEmitContext* ctx() { return &contexts.top(); }
CompileMode mode() const{ return lexer->src->mode; } CompileMode mode() const{ return lexer->src->mode; }
@ -42,7 +42,7 @@ class Compiler {
void pop_context(){ void pop_context(){
if(!ctx()->s_expr.empty()) UNREACHABLE(); if(!ctx()->s_expr.empty()) UNREACHABLE();
// if the last op does 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){ if(ctx()->co->codes.empty() || ctx()->co->codes.back().op != OP_RETURN_VALUE){
ctx()->emit(OP_LOAD_NONE, BC_NOARG, BC_KEEPLINE); ctx()->emit(OP_LOAD_NONE, BC_NOARG, BC_KEEPLINE);
ctx()->emit(OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE); ctx()->emit(OP_RETURN_VALUE, BC_NOARG, BC_KEEPLINE);
} }
@ -185,12 +185,14 @@ class Compiler {
// PASS // PASS
void exprTuple(){ void exprTuple(){
auto e = make_expr<TupleExpr>(); std::vector<Expr_> items;
do { do {
EXPR(); // NOTE: "1," will fail, "1,2" will be ok EXPR(); // NOTE: "1," will fail, "1,2" will be ok
e->items.push_back(ctx()->s_expr.popx()); items.push_back(ctx()->s_expr.popx());
} while(match(TK(","))); } while(match(TK(",")));
ctx()->s_expr.push(std::move(e)); ctx()->s_expr.push(make_expr<TupleExpr>(
std::move(items)
));
} }
// PASS // PASS
@ -577,7 +579,7 @@ class Compiler {
EXPR(false); EXPR(false);
// TODO: support multiple decorator // TODO: support multiple decorator
// use a while loop to consume '@' // use a while loop to consume '@'
if(!match_newlines(mode()==REPL_MODE)) SyntaxError(); if(!match_newlines_repl()) SyntaxError();
ctx()->emit(OP_SETUP_DECORATOR, BC_NOARG, prev().line); ctx()->emit(OP_SETUP_DECORATOR, BC_NOARG, prev().line);
consume(TK("def")); consume(TK("def"));
compile_function(); compile_function();
@ -585,11 +587,9 @@ class Compiler {
bool try_compile_assignment(){ bool try_compile_assignment(){
Expr* lhs_p = ctx()->s_expr.top().get(); Expr* lhs_p = ctx()->s_expr.top().get();
bool inplace;
switch (curr().type) { switch (curr().type) {
case TK("+="): case TK("-="): case TK("*="): case TK("/="): case TK("//="): case TK("%="): case TK("+="): case TK("-="): case TK("*="): case TK("/="): case TK("//="): case TK("%="):
case TK("<<="): case TK(">>="): case TK("&="): case TK("|="): case TK("^="): { case TK("<<="): case TK(">>="): case TK("&="): case TK("|="): case TK("^="): {
inplace = true;
advance(); advance();
auto e = make_expr<BinaryExpr>(); auto e = make_expr<BinaryExpr>();
e->op = prev().type - 1; // -1 to remove = e->op = prev().type - 1; // -1 to remove =
@ -599,7 +599,6 @@ class Compiler {
ctx()->s_expr.push(std::move(e)); ctx()->s_expr.push(std::move(e));
} break; } break;
case TK("="): case TK("="):
inplace = false;
advance(); advance();
EXPR_TUPLE(); EXPR_TUPLE();
break; break;
@ -625,7 +624,7 @@ class Compiler {
ctx()->emit(OP_LOOP_CONTINUE, BC_NOARG, kw_line); ctx()->emit(OP_LOOP_CONTINUE, BC_NOARG, kw_line);
consume_end_stmt(); consume_end_stmt();
break; break;
case TK("yield"): case TK("yield"):
if (contexts.size() <= 1) SyntaxError("'yield' outside function"); if (contexts.size() <= 1) SyntaxError("'yield' outside function");
EXPR_TUPLE(true); EXPR_TUPLE(true);
// if yield present, mark the function as generator // if yield present, mark the function as generator
@ -634,7 +633,7 @@ class Compiler {
consume_end_stmt(); consume_end_stmt();
break; break;
case TK("return"): case TK("return"):
if (contexts.size() <= 1) SyntaxError("'ret urn' outside function"); if (contexts.size() <= 1) SyntaxError("'return' outside function");
if(match_end_stmt()){ if(match_end_stmt()){
ctx()->emit(OP_LOAD_NONE, BC_NOARG, kw_line); ctx()->emit(OP_LOAD_NONE, BC_NOARG, kw_line);
}else{ }else{
@ -717,6 +716,7 @@ class Compiler {
/*************************************************/ /*************************************************/
// handle dangling expression or assignment // handle dangling expression or assignment
default: { default: {
advance(-1); // do revert since we have pre-called advance() at the beginning
EXPR_TUPLE(); EXPR_TUPLE();
if(!try_compile_assignment()){ if(!try_compile_assignment()){
ctx()->emit_expr(); ctx()->emit_expr();
@ -791,7 +791,6 @@ class Compiler {
void compile_function(){ void compile_function(){
// TODO: bug, if there are multiple decorators, will cause error // TODO: bug, if there are multiple decorators, will cause error
bool has_decorator = !co()->codes.empty() && co()->codes.back().op == OP_SETUP_DECORATOR;
Function func; Function func;
StrName obj_name; StrName obj_name;
consume(TK("@id")); consume(TK("@id"));
@ -812,38 +811,38 @@ class Compiler {
func.code = push_context(lexer->src, func.name.str()); func.code = push_context(lexer->src, func.name.str());
compile_block_body(); compile_block_body();
pop_context(); pop_context();
emit(OP_LOAD_FUNCTION, co()->add_const(VAR(func))); ctx()->emit(OP_LOAD_FUNCTION, ctx()->add_const(VAR(func)), prev().line);
if(name_scope() == NAME_LOCAL) emit(OP_SETUP_CLOSURE); if(name_scope() == NAME_LOCAL) ctx()->emit(OP_SETUP_CLOSURE, BC_NOARG, prev().line);
if(!ctx()->is_compiling_class){ if(!ctx()->is_compiling_class){
if(obj_name.empty()){ if(obj_name.empty()){
if(has_decorator) emit(OP_CALL, 1); auto e = make_expr<NameExpr>(func.name, name_scope());
emit(OP_STORE_NAME, co()->add_name(func.name, name_scope())); e->emit_store(ctx());
} else { } else {
if(has_decorator) SyntaxError("decorator is not supported here"); ctx()->emit(OP_LOAD_NAME, ctx()->add_name(obj_name), prev().line);
emit(OP_LOAD_NAME, co()->add_name(obj_name, name_scope())); int index = ctx()->add_name(func.name);
int index = co()->add_name(func.name, NAME_ATTR); ctx()->emit(OP_STORE_ATTR, index, prev().line);
emit(OP_BUILD_ATTR_REF, index);
emit(OP_ROT_TWO);
emit(OP_STORE_REF);
} }
}else{ }else{
if(has_decorator) emit(OP_CALL, 1); ctx()->emit(OP_STORE_CLASS_ATTR, ctx()->add_name(func.name), BC_KEEPLINE);
emit(OP_STORE_CLASS_ATTR, co()->add_name(func.name, name_scope()));
} }
} }
PyObject* read_literal(){ PyObject* read_literal(){
if(match(TK("-"))){ advance();
consume(TK("@num")); switch(prev().type){
PyObject* val = get_value(prev()); case TK("-"): {
return vm->num_negated(val); consume(TK("@num"));
PyObject* val = LiteralExpr(prev().value).to_object(ctx());
return vm->num_negated(val);
}
case TK("@num"): return LiteralExpr(prev().value).to_object(ctx());
case TK("@str"): return LiteralExpr(prev().value).to_object(ctx());
case TK("True"): return VAR(true);
case TK("False"): return VAR(false);
case TK("None"): return vm->None;
case TK("..."): return vm->Ellipsis;
default: break;
} }
if(match(TK("@num"))) return get_value(prev());
if(match(TK("@str"))) return get_value(prev());
if(match(TK("True"))) return VAR(true);
if(match(TK("False"))) return VAR(false);
if(match(TK("None"))) return vm->None;
if(match(TK("..."))) return vm->Ellipsis;
return nullptr; return nullptr;
} }
@ -858,7 +857,8 @@ public:
this->lexer = std::make_unique<Lexer>( this->lexer = std::make_unique<Lexer>(
make_sp<SourceData>(source, filename, mode) make_sp<SourceData>(source, filename, mode)
); );
if(rules.empty()) init_pratt_rules(); // TODO: check if already initialized
init_pratt_rules();
} }
CodeObject_ compile(){ CodeObject_ compile(){
@ -883,7 +883,7 @@ public:
return code; return code;
}else if(mode()==JSON_MODE){ }else if(mode()==JSON_MODE){
PyObject* value = read_literal(); PyObject* value = read_literal();
if(value != nullptr) emit(OP_LOAD_CONST, code->add_const(value)); if(value != nullptr) ctx()->emit(OP_LOAD_CONST, ctx()->add_const(value), prev().line);
else if(match(TK("{"))) exprMap(); else if(match(TK("{"))) exprMap();
else if(match(TK("["))) exprList(); else if(match(TK("["))) exprList();
else SyntaxError("expect a JSON object or array"); else SyntaxError("expect a JSON object or array");

View File

@ -31,12 +31,7 @@ struct CodeEmitContext{
CodeObject_ co; CodeObject_ co;
VM* vm; VM* vm;
stack<Expr_> s_expr; stack<Expr_> s_expr;
CodeEmitContext(VM* vm, CodeObject_ co): co(co) {} CodeEmitContext(VM* vm, CodeObject_ co): co(co) {}
CodeEmitContext(const CodeEmitContext&) = delete;
CodeEmitContext& operator=(const CodeEmitContext&) = delete;
CodeEmitContext(CodeEmitContext&&) = delete;
CodeEmitContext& operator=(CodeEmitContext&&) = delete;
int curr_block_i = 0; int curr_block_i = 0;
bool is_compiling_class = false; bool is_compiling_class = false;
@ -101,12 +96,11 @@ struct CodeEmitContext{
// PASS // PASS
struct NameExpr: Expr{ struct NameExpr: Expr{
Str name; StrName name;
NameScope scope; NameScope scope;
NameExpr(const Str& name, NameScope scope): name(name), scope(scope) {} NameExpr(StrName name, NameScope scope): name(name), scope(scope) {}
NameExpr(Str&& name, NameScope scope): name(std::move(name)), scope(scope) {}
Str str() const override { return "$" + name; } Str str() const override { return "$" + name.str(); }
void emit(CodeEmitContext* ctx) override { void emit(CodeEmitContext* ctx) override {
int index = ctx->add_name(name); int index = ctx->add_name(name);
@ -246,7 +240,7 @@ struct LiteralExpr: Expr{
UNREACHABLE(); UNREACHABLE();
} }
void emit(CodeEmitContext* ctx) override { PyObject* to_object(CodeEmitContext* ctx){
VM* vm = ctx->vm; VM* vm = ctx->vm;
PyObject* obj = nullptr; PyObject* obj = nullptr;
if(std::holds_alternative<i64>(value)){ if(std::holds_alternative<i64>(value)){
@ -258,6 +252,11 @@ struct LiteralExpr: Expr{
if(std::holds_alternative<Str>(value)){ if(std::holds_alternative<Str>(value)){
obj = VAR(std::get<Str>(value)); obj = VAR(std::get<Str>(value));
} }
return obj;
}
void emit(CodeEmitContext* ctx) override {
PyObject* obj = to_object(ctx);
if(obj == nullptr) UNREACHABLE(); if(obj == nullptr) UNREACHABLE();
int index = ctx->add_const(obj); int index = ctx->add_const(obj);
ctx->emit(OP_LOAD_CONST, index, line); ctx->emit(OP_LOAD_CONST, index, line);
@ -287,7 +286,7 @@ struct NegatedExpr: Expr{
obj = VAR(std::get<f64>(lit->value)); obj = VAR(std::get<f64>(lit->value));
} }
if(obj != nullptr){ if(obj != nullptr){
ctx->emit(OP_LOAD_CONST, ctx()->add_const(obj), line); ctx->emit(OP_LOAD_CONST, ctx->add_const(obj), line);
return; return;
} }
} }
@ -362,21 +361,25 @@ struct SequenceExpr: Expr{
}; };
struct ListExpr: SequenceExpr{ struct ListExpr: SequenceExpr{
using SequenceExpr::SequenceExpr;
Str str() const override { return "list()"; } Str str() const override { return "list()"; }
Opcode opcode() const override { return OP_BUILD_LIST; } Opcode opcode() const override { return OP_BUILD_LIST; }
}; };
struct DictExpr: SequenceExpr{ struct DictExpr: SequenceExpr{
using SequenceExpr::SequenceExpr;
Str str() const override { return "dict()"; } Str str() const override { return "dict()"; }
Opcode opcode() const override { return OP_BUILD_MAP; } Opcode opcode() const override { return OP_BUILD_DICT; }
}; };
struct SetExpr: SequenceExpr{ struct SetExpr: SequenceExpr{
using SequenceExpr::SequenceExpr;
Str str() const override { return "set()"; } Str str() const override { return "set()"; }
Opcode opcode() const override { return OP_BUILD_SET; } Opcode opcode() const override { return OP_BUILD_SET; }
}; };
struct TupleExpr: SequenceExpr{ struct TupleExpr: SequenceExpr{
using SequenceExpr::SequenceExpr;
Str str() const override { return "tuple()"; } Str str() const override { return "tuple()"; }
Opcode opcode() const override { return OP_BUILD_TUPLE; } Opcode opcode() const override { return OP_BUILD_TUPLE; }
@ -432,7 +435,8 @@ struct CompExpr: Expr{
ctx->enter_block(FOR_LOOP); ctx->enter_block(FOR_LOOP);
ctx->emit(OP_FOR_ITER, BC_NOARG, BC_KEEPLINE); ctx->emit(OP_FOR_ITER, BC_NOARG, BC_KEEPLINE);
bool ok = vars->emit_store(ctx); bool ok = vars->emit_store(ctx);
if(!ok) SyntaxError(); // this error occurs in `vars` instead of this line, but...nevermind // this error occurs in `vars` instead of this line, but...nevermind
if(!ok) UNREACHABLE(); // TODO: raise a SyntaxError instead
if(cond){ if(cond){
cond->emit(ctx); cond->emit(ctx);
int patch = ctx->emit(OP_POP_JUMP_IF_FALSE, BC_NOARG, BC_KEEPLINE); int patch = ctx->emit(OP_POP_JUMP_IF_FALSE, BC_NOARG, BC_KEEPLINE);
@ -449,16 +453,19 @@ struct CompExpr: Expr{
struct ListCompExpr: CompExpr{ struct ListCompExpr: CompExpr{
Opcode op0() override { return OP_BUILD_LIST; } Opcode op0() override { return OP_BUILD_LIST; }
Opcode op1() override { return OP_LIST_APPEND; } Opcode op1() override { return OP_LIST_APPEND; }
Str str() const override { return "listcomp()"; }
}; };
struct DictCompExpr: CompExpr{ struct DictCompExpr: CompExpr{
Opcode op0() override { return OP_BUILD_DI CT; } Opcode op0() override { return OP_BUILD_DICT; }
Opcode op1() override { return OP_DICT_ADD; } Opcode op1() override { return OP_DICT_ADD; }
Str str() const override { return "dictcomp()"; }
}; };
struct SetCompExpr: CompExpr{ struct SetCompExpr: CompExpr{
Opcode op0() override { return OP_BUILD_SET; } Opcode op0() override { return OP_BUILD_SET; }
Opcode op1() override { return OP_SET_ADD; } Opcode op1() override { return OP_SET_ADD; }
Str str() const override { return "setcomp()"; }
}; };
struct LambdaExpr: Expr{ struct LambdaExpr: Expr{

View File

@ -53,14 +53,14 @@ struct Frame {
// } // }
void pop(){ void pop(){
#if DEBUG_EXTRA_CHECK #if DEBUG_MODE
if(_data.empty()) throw std::runtime_error("_data.empty() is true"); if(_data.empty()) throw std::runtime_error("_data.empty() is true");
#endif #endif
_data.pop_back(); _data.pop_back();
} }
PyObject* popx(){ PyObject* popx(){
#if DEBUG_EXTRA_CHECK #if DEBUG_MODE
if(_data.empty()) throw std::runtime_error("_data.empty() is true"); if(_data.empty()) throw std::runtime_error("_data.empty() is true");
#endif #endif
PyObject* ret = _data.back(); PyObject* ret = _data.back();
@ -69,21 +69,21 @@ struct Frame {
} }
PyObject*& top(){ PyObject*& top(){
#if DEBUG_EXTRA_CHECK #if DEBUG_MODE
if(_data.empty()) throw std::runtime_error("_data.empty() is true"); if(_data.empty()) throw std::runtime_error("_data.empty() is true");
#endif #endif
return _data.back(); return _data.back();
} }
PyObject*& top_1(){ PyObject*& top_1(){
#if DEBUG_EXTRA_CHECK #if DEBUG_MODE
if(_data.size() < 2) throw std::runtime_error("_data.size() < 2"); if(_data.size() < 2) throw std::runtime_error("_data.size() < 2");
#endif #endif
return _data[_data.size()-2]; return _data[_data.size()-2];
} }
PyObject*& top_2(){ PyObject*& top_2(){
#if DEBUG_EXTRA_CHECK #if DEBUG_MODE
if(_data.size() < 3) throw std::runtime_error("_data.size() < 3"); if(_data.size() < 3) throw std::runtime_error("_data.size() < 3");
#endif #endif
return _data[_data.size()-3]; return _data[_data.size()-3];
@ -115,7 +115,7 @@ struct Frame {
} }
int _exit_block(int i){ int _exit_block(int i){
if(co->blocks[i].type == FOR_LOOP) _pop(); if(co->blocks[i].type == FOR_LOOP) pop();
else if(co->blocks[i].type == TRY_EXCEPT) on_try_block_exit(); else if(co->blocks[i].type == TRY_EXCEPT) on_try_block_exit();
return co->blocks[i].parent; return co->blocks[i].parent;
} }

View File

@ -26,8 +26,8 @@ public:
template <typename T> template <typename T>
class ArrayIter : public BaseIter { class ArrayIter : public BaseIter {
int index;
PyObject* ref; PyObject* ref;
int index;
public: public:
ArrayIter(VM* vm, PyObject* ref) : BaseIter(vm), ref(ref), index(0) {} ArrayIter(VM* vm, PyObject* ref) : BaseIter(vm), ref(ref), index(0) {}
@ -43,10 +43,10 @@ public:
}; };
class StringIter : public BaseIter { class StringIter : public BaseIter {
int index = 0;
PyObject* ref; PyObject* ref;
int index;
public: public:
StringIter(VM* vm, PyObject* ref) : BaseIter(vm), ref(ref) {} StringIter(VM* vm, PyObject* ref) : BaseIter(vm), ref(ref), index(0) {}
PyObject* next() override{ PyObject* next() override{
Str* str = &OBJ_GET(Str, ref); Str* str = &OBJ_GET(Str, ref);

View File

@ -1,7 +1,6 @@
#pragma once #pragma once
#include "common.h" #include "common.h"
#include <type_traits>
namespace pkpy{ namespace pkpy{

View File

@ -3,7 +3,6 @@
#include "common.h" #include "common.h"
#include "namedict.h" #include "namedict.h"
#include "tuplelist.h" #include "tuplelist.h"
#include <type_traits>
namespace pkpy { namespace pkpy {
@ -142,9 +141,14 @@ struct Py_ : PyObject {
}; };
#define OBJ_GET(T, obj) (((Py_<T>*)(obj))->_value) #define OBJ_GET(T, obj) (((Py_<T>*)(obj))->_value)
#define OBJ_NAME(obj) OBJ_GET(Str, vm->getattr(obj, __name__))
#define OBJ_MARK(obj) if(!is_tagged(obj)) obj->_mark() #define OBJ_MARK(obj) if(!is_tagged(obj)) obj->_mark()
#if DEBUG_NO_BUILTIN_MODULES
#define OBJ_NAME(obj) Str("<?>")
#else
#define OBJ_NAME(obj) OBJ_GET(Str, vm->getattr(obj, __name__))
#endif
const int kTpIntIndex = 2; const int kTpIntIndex = 2;
const int kTpFloatIndex = 3; const int kTpFloatIndex = 3;

View File

@ -542,7 +542,7 @@ inline void init_builtins(VM* _vm) {
}); });
/************ PyBool ************/ /************ PyBool ************/
_vm->bind_static_method<1>("bool", "__new__", CPP_LAMBDA(vm->asBool(args[0]))); _vm->bind_static_method<1>("bool", "__new__", CPP_LAMBDA(VAR(vm->asBool(args[0]))));
_vm->bind_method<0>("bool", "__repr__", [](VM* vm, Args& args) { _vm->bind_method<0>("bool", "__repr__", [](VM* vm, Args& args) {
bool val = CAST(bool, args[0]); bool val = CAST(bool, args[0]);

140
src/vm.h
View File

@ -93,7 +93,7 @@ public:
} }
Frame* top_frame() const { Frame* top_frame() const {
#if DEBUG_EXTRA_CHECK #if DEBUG_MODE
if(callstack.empty()) UNREACHABLE(); if(callstack.empty()) UNREACHABLE();
#endif #endif
return callstack.top().get(); return callstack.top().get();
@ -166,14 +166,18 @@ public:
if(_module == nullptr) _module = _main; if(_module == nullptr) _module = _main;
try { try {
CodeObject_ code = compile(source, filename, mode); CodeObject_ code = compile(source, filename, mode);
// if(_module == _main) std::cout << disassemble(code) << '\n'; if(_module == _main) std::cout << disassemble(code) << '\n';
return _exec(code, _module); return _exec(code, _module);
}catch (const Exception& e){ }catch (const Exception& e){
*_stderr << e.summary() << '\n'; *_stderr << e.summary() << '\n';
}catch (const std::exception& e) {
}
#if !DEBUG_MODE
catch (const std::exception& e) {
*_stderr << "An std::exception occurred! It could be a bug.\n"; *_stderr << "An std::exception occurred! It could be a bug.\n";
*_stderr << e.what() << '\n'; *_stderr << e.what() << '\n';
} }
#endif
callstack = {}; callstack = {};
return nullptr; return nullptr;
} }
@ -289,6 +293,7 @@ public:
void NameError(StrName name){ _error("NameError", "name " + name.str().escape(true) + " is not defined"); } void NameError(StrName name){ _error("NameError", "name " + name.str().escape(true) + " is not defined"); }
void AttributeError(PyObject* obj, StrName name){ void AttributeError(PyObject* obj, StrName name){
// OBJ_NAME calls getattr, which may lead to a infinite recursion
_error("AttributeError", "type " + OBJ_NAME(_t(obj)).escape(true) + " has no attribute " + name.str().escape(true)); _error("AttributeError", "type " + OBJ_NAME(_t(obj)).escape(true) + " has no attribute " + name.str().escape(true));
} }
@ -551,74 +556,73 @@ inline PyObject* VM::new_module(StrName name) {
} }
inline Str VM::disassemble(CodeObject_ co){ inline Str VM::disassemble(CodeObject_ co){
return ""; auto pad = [](const Str& s, const int n){
// auto pad = [](const Str& s, const int n){ if(s.size() >= n) return s.substr(0, n);
// if(s.size() >= n) return s.substr(0, n); return s + std::string(n - s.size(), ' ');
// return s + std::string(n - s.size(), ' '); };
// };
// std::vector<int> jumpTargets; std::vector<int> jumpTargets;
// for(auto byte : co->codes){ for(auto byte : co->codes){
// if(byte.op == OP_JUMP_ABSOLUTE || byte.op == OP_POP_JUMP_IF_FALSE){ if(byte.op == OP_JUMP_ABSOLUTE || byte.op == OP_POP_JUMP_IF_FALSE){
// jumpTargets.push_back(byte.arg); jumpTargets.push_back(byte.arg);
// } }
// } }
// StrStream ss; StrStream ss;
// ss << std::string(54, '-') << '\n'; ss << std::string(54, '-') << '\n';
// ss << co->name << ":\n"; ss << co->name << ":\n";
// int prev_line = -1; int prev_line = -1;
// for(int i=0; i<co->codes.size(); i++){ for(int i=0; i<co->codes.size(); i++){
// const Bytecode& byte = co->codes[i]; const Bytecode& byte = co->codes[i];
// if(byte.op == OP_NO_OP) continue; if(byte.op == OP_NO_OP) continue;
// Str line = std::to_string(byte.line); Str line = std::to_string(byte.line);
// if(byte.line == prev_line) line = ""; if(byte.line == prev_line) line = "";
// else{ else{
// if(prev_line != -1) ss << "\n"; if(prev_line != -1) ss << "\n";
// prev_line = byte.line; prev_line = byte.line;
// } }
// std::string pointer; std::string pointer;
// if(std::find(jumpTargets.begin(), jumpTargets.end(), i) != jumpTargets.end()){ if(std::find(jumpTargets.begin(), jumpTargets.end(), i) != jumpTargets.end()){
// pointer = "-> "; pointer = "-> ";
// }else{ }else{
// pointer = " "; pointer = " ";
// } }
// ss << pad(line, 8) << pointer << pad(std::to_string(i), 3); ss << pad(line, 8) << pointer << pad(std::to_string(i), 3);
// ss << " " << pad(OP_NAMES[byte.op], 20) << " "; ss << " " << pad(OP_NAMES[byte.op], 20) << " ";
// // ss << pad(byte.arg == -1 ? "" : std::to_string(byte.arg), 5); // ss << pad(byte.arg == -1 ? "" : std::to_string(byte.arg), 5);
// std::string argStr = byte.arg == -1 ? "" : std::to_string(byte.arg); std::string argStr = byte.arg == -1 ? "" : std::to_string(byte.arg);
// if(byte.op == OP_LOAD_CONST){ if(byte.op == OP_LOAD_CONST){
// argStr += " (" + CAST(Str, asRepr(co->consts[byte.arg])) + ")"; argStr += " (" + CAST(Str, asRepr(co->consts[byte.arg])) + ")";
// } }
// if(byte.op == OP_LOAD_NAME_REF || byte.op == OP_LOAD_NAME || byte.op == OP_RAISE || byte.op == OP_STORE_NAME){ if(byte.op == OP_LOAD_NAME || byte.op == OP_STORE_LOCAL || byte.op == OP_STORE_GLOBAL){
// argStr += " (" + co->names[byte.arg].first.str().escape(true) + ")"; argStr += " (" + co->names[byte.arg].str().escape(true) + ")";
// } }
// ss << argStr; ss << argStr;
// // ss << pad(argStr, 20); // may overflow // ss << pad(argStr, 20); // may overflow
// // ss << co->blocks[byte.block].to_string(); // ss << co->blocks[byte.block].to_string();
// if(i != co->codes.size() - 1) ss << '\n'; if(i != co->codes.size() - 1) ss << '\n';
// } }
// StrStream consts; StrStream consts;
// consts << "co_consts: "; consts << "co_consts: ";
// consts << CAST(Str, asRepr(VAR(co->consts))); consts << CAST(Str, asRepr(VAR(co->consts)));
// StrStream names; StrStream names;
// names << "co_names: "; names << "co_names: ";
// List list; List list;
// for(int i=0; i<co->names.size(); i++){ for(int i=0; i<co->names.size(); i++){
// list.push_back(VAR(co->names[i].first.str())); list.push_back(VAR(co->names[i].str()));
// } }
// names << CAST(Str, asRepr(VAR(list))); names << CAST(Str, asRepr(VAR(list)));
// ss << '\n' << consts.str() << '\n' << names.str() << '\n'; ss << '\n' << consts.str() << '\n' << names.str() << '\n';
// for(int i=0; i<co->consts.size(); i++){ for(int i=0; i<co->consts.size(); i++){
// PyObject* obj = co->consts[i]; PyObject* obj = co->consts[i];
// if(is_type(obj, tp_function)){ if(is_type(obj, tp_function)){
// const auto& f = CAST(Function&, obj); const auto& f = CAST(Function&, obj);
// ss << disassemble(f.code); ss << disassemble(f.code);
// } }
// } }
// return Str(ss.str()); return Str(ss.str());
} }
inline void VM::init_builtin_types(){ inline void VM::init_builtin_types(){
@ -877,7 +881,7 @@ inline PyObject* VM::_exec(){
}catch(HandledException& e){ }catch(HandledException& e){
continue; continue;
}catch(UnhandledException& e){ }catch(UnhandledException& e){
PyObject* obj = frame->pop(); PyObject* obj = frame->popx();
Exception& _e = CAST(Exception&, obj); Exception& _e = CAST(Exception&, obj);
_e.st_push(frame->snapshot()); _e.st_push(frame->snapshot());
callstack.pop(); callstack.pop();