mirror of
https://github.com/pocketpy/pocketpy
synced 2025-12-06 18:20:17 +00:00
up
This commit is contained in:
parent
3cafab9029
commit
baf7ad6b50
@ -18,6 +18,9 @@ __NEXT_STEP:;
|
|||||||
//heap._auto_collect(this);
|
//heap._auto_collect(this);
|
||||||
|
|
||||||
const Bytecode& byte = frame->next_bytecode();
|
const Bytecode& byte = frame->next_bytecode();
|
||||||
|
|
||||||
|
// std::cout << frame->stack_info() << " " << OP_NAMES[byte.op] << std::endl;
|
||||||
|
|
||||||
switch (byte.op)
|
switch (byte.op)
|
||||||
{
|
{
|
||||||
case OP_NO_OP: DISPATCH();
|
case OP_NO_OP: DISPATCH();
|
||||||
@ -296,7 +299,7 @@ __NEXT_STEP:;
|
|||||||
}
|
}
|
||||||
CodeObject_ code = compile(source, name.str(), EXEC_MODE);
|
CodeObject_ code = compile(source, name.str(), EXEC_MODE);
|
||||||
PyObject* new_mod = new_module(name);
|
PyObject* new_mod = new_module(name);
|
||||||
_exec(code, new_mod);
|
_exec(code, new_mod, builtins);
|
||||||
new_mod->attr()._try_perfect_rehash();
|
new_mod->attr()._try_perfect_rehash();
|
||||||
}
|
}
|
||||||
frame->push(ext_mod);
|
frame->push(ext_mod);
|
||||||
|
|||||||
@ -57,7 +57,7 @@ struct CodeObject {
|
|||||||
std::vector<Bytecode> codes;
|
std::vector<Bytecode> codes;
|
||||||
List consts;
|
List consts;
|
||||||
std::vector<StrName> names;
|
std::vector<StrName> names;
|
||||||
std::set<StrName> global_names;
|
std::set<Str> global_names;
|
||||||
std::vector<CodeBlock> blocks = { CodeBlock{NO_BLOCK, -1} };
|
std::vector<CodeBlock> blocks = { CodeBlock{NO_BLOCK, -1} };
|
||||||
std::map<StrName, int> labels;
|
std::map<StrName, int> labels;
|
||||||
std::vector<FuncDecl_> func_decls;
|
std::vector<FuncDecl_> func_decls;
|
||||||
|
|||||||
11
src/common.h
11
src/common.h
@ -28,16 +28,19 @@
|
|||||||
#include <variant>
|
#include <variant>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
#define PK_VERSION "0.9.6"
|
#define PK_VERSION "0.9.7"
|
||||||
|
|
||||||
// debug macros
|
// debug macros
|
||||||
#define DEBUG_NO_BUILTIN_MODULES 1
|
#define DEBUG_NO_BUILTIN_MODULES 0
|
||||||
#define DEBUG_MODE 1
|
#define DEBUG_EXTRA_CHECK 1
|
||||||
|
#define DEBUG_DIS_REPL 0
|
||||||
|
#define DEBUG_DIS_REPL_MIN 1
|
||||||
|
#define DEBUG_FULL_EXCEPTION 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
|
||||||
#else
|
#else
|
||||||
#define PK_ENABLE_FILEIO 1
|
#define PK_ENABLE_FILEIO (1-DEBUG_NO_BUILTIN_MODULES)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__EMSCRIPTEN__) || defined(__arm__) || defined(__i386__)
|
#if defined(__EMSCRIPTEN__) || defined(__arm__) || defined(__i386__)
|
||||||
|
|||||||
161
src/compiler.h
161
src/compiler.h
@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "codeobject.h"
|
||||||
|
#include "common.h"
|
||||||
#include "expr.h"
|
#include "expr.h"
|
||||||
|
|
||||||
namespace pkpy{
|
namespace pkpy{
|
||||||
@ -152,6 +154,17 @@ class Compiler {
|
|||||||
parse_expression(PREC_TUPLE, push_stack);
|
parse_expression(PREC_TUPLE, push_stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// special case for `for loop` and `comp`
|
||||||
|
Expr_ EXPR_VARS(){
|
||||||
|
std::vector<Expr_> items;
|
||||||
|
do {
|
||||||
|
consume(TK("@id"));
|
||||||
|
items.push_back(make_expr<NameExpr>(prev().str(), name_scope()));
|
||||||
|
} while(match(TK(",")));
|
||||||
|
if(items.size()==1) return std::move(items[0]);
|
||||||
|
return make_expr<TupleExpr>(std::move(items));
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T, typename... Args>
|
template <typename T, typename... Args>
|
||||||
std::unique_ptr<T> make_expr(Args&&... args) {
|
std::unique_ptr<T> make_expr(Args&&... args) {
|
||||||
std::unique_ptr<T> expr = std::make_unique<T>(std::forward<Args>(args)...);
|
std::unique_ptr<T> expr = std::make_unique<T>(std::forward<Args>(args)...);
|
||||||
@ -269,10 +282,9 @@ class Compiler {
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
void _consume_comp(Expr_ expr){
|
void _consume_comp(Expr_ expr){
|
||||||
static_assert(std::is_base_of<CompExpr, T>::value);
|
static_assert(std::is_base_of<CompExpr, T>::value);
|
||||||
std::unique_ptr<CompExpr> ce = std::make_unique<T>();
|
std::unique_ptr<CompExpr> ce = make_expr<T>();
|
||||||
ce->expr = std::move(expr);
|
ce->expr = std::move(expr);
|
||||||
EXPR_TUPLE(); // must be a lvalue
|
ce->vars = EXPR_VARS();
|
||||||
ce->vars = ctx()->s_expr.popx();
|
|
||||||
consume(TK("in"));
|
consume(TK("in"));
|
||||||
EXPR();
|
EXPR();
|
||||||
ce->iter = ctx()->s_expr.popx();
|
ce->iter = ctx()->s_expr.popx();
|
||||||
@ -374,7 +386,12 @@ class Compiler {
|
|||||||
|
|
||||||
// PASS
|
// PASS
|
||||||
void exprName(){
|
void exprName(){
|
||||||
ctx()->s_expr.push(make_expr<NameExpr>(prev().str(), name_scope()));
|
Str name = prev().str();
|
||||||
|
NameScope scope = name_scope();
|
||||||
|
if(ctx()->co->global_names.count(name)){
|
||||||
|
scope = NAME_GLOBAL;
|
||||||
|
}
|
||||||
|
ctx()->s_expr.push(make_expr<NameExpr>(name, scope));
|
||||||
}
|
}
|
||||||
|
|
||||||
// PASS
|
// PASS
|
||||||
@ -389,26 +406,65 @@ class Compiler {
|
|||||||
void exprSubscr() {
|
void exprSubscr() {
|
||||||
auto e = make_expr<SubscrExpr>();
|
auto e = make_expr<SubscrExpr>();
|
||||||
e->a = ctx()->s_expr.popx();
|
e->a = ctx()->s_expr.popx();
|
||||||
std::vector<Expr_> items;
|
auto slice = make_expr<SliceExpr>();
|
||||||
do {
|
bool is_slice = false;
|
||||||
EXPR_TUPLE();
|
// a[<0> <state:1> : state<3> : state<5>]
|
||||||
items.push_back(ctx()->s_expr.popx());
|
int state = 0;
|
||||||
} while(match(TK(":")));
|
do{
|
||||||
consume(TK("]"));
|
switch(state){
|
||||||
switch(items.size()){
|
case 0:
|
||||||
case 1:
|
if(match(TK(":"))){
|
||||||
e->b = std::move(items[0]);
|
is_slice=true;
|
||||||
break;
|
state=2;
|
||||||
case 2: case 3: {
|
break;
|
||||||
auto slice = make_expr<SliceExpr>();
|
}
|
||||||
slice->start = std::move(items[0]);
|
if(match(TK("]"))) SyntaxError();
|
||||||
slice->stop = std::move(items[1]);
|
EXPR_TUPLE();
|
||||||
if(items.size()==3){
|
slice->start = ctx()->s_expr.popx();
|
||||||
slice->step = std::move(items[2]);
|
state=1;
|
||||||
}
|
break;
|
||||||
e->b = std::move(slice);
|
case 1:
|
||||||
} break;
|
if(match(TK(":"))){
|
||||||
default: SyntaxError(); break;
|
is_slice=true;
|
||||||
|
state=2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(match(TK("]"))) goto __SUBSCR_END;
|
||||||
|
SyntaxError("expected ':' or ']'");
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if(match(TK(":"))){
|
||||||
|
state=4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(match(TK("]"))) goto __SUBSCR_END;
|
||||||
|
EXPR_TUPLE();
|
||||||
|
slice->stop = ctx()->s_expr.popx();
|
||||||
|
state=3;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
if(match(TK(":"))){
|
||||||
|
state=4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(match(TK("]"))) goto __SUBSCR_END;
|
||||||
|
SyntaxError("expected ':' or ']'");
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
if(match(TK("]"))) goto __SUBSCR_END;
|
||||||
|
EXPR_TUPLE();
|
||||||
|
slice->step = ctx()->s_expr.popx();
|
||||||
|
state=5;
|
||||||
|
break;
|
||||||
|
case 5: consume(TK("]")); goto __SUBSCR_END;
|
||||||
|
}
|
||||||
|
}while(true);
|
||||||
|
__SUBSCR_END:
|
||||||
|
if(is_slice){
|
||||||
|
e->b = std::move(slice);
|
||||||
|
}else{
|
||||||
|
if(state != 1) UNREACHABLE();
|
||||||
|
e->b = std::move(slice->start);
|
||||||
}
|
}
|
||||||
ctx()->s_expr.push(std::move(e));
|
ctx()->s_expr.push(std::move(e));
|
||||||
}
|
}
|
||||||
@ -535,8 +591,7 @@ class Compiler {
|
|||||||
|
|
||||||
// PASS
|
// PASS
|
||||||
void compile_for_loop() {
|
void compile_for_loop() {
|
||||||
EXPR_TUPLE();
|
Expr_ vars = EXPR_VARS();
|
||||||
Expr_ vars = ctx()->s_expr.popx();
|
|
||||||
consume(TK("in"));
|
consume(TK("in"));
|
||||||
EXPR(false);
|
EXPR(false);
|
||||||
ctx()->emit(OP_GET_ITER, BC_NOARG, BC_KEEPLINE);
|
ctx()->emit(OP_GET_ITER, BC_NOARG, BC_KEEPLINE);
|
||||||
@ -550,31 +605,32 @@ class Compiler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void compile_try_except() {
|
void compile_try_except() {
|
||||||
// ctx()->enter_block(TRY_EXCEPT);
|
ctx()->enter_block(TRY_EXCEPT);
|
||||||
// ctx()->emit(OP_TRY_BLOCK_ENTER, BC_NOARG, prev().line);
|
ctx()->emit(OP_TRY_BLOCK_ENTER, BC_NOARG, prev().line);
|
||||||
// compile_block_body();
|
compile_block_body();
|
||||||
// ctx()->emit(OP_TRY_BLOCK_EXIT, BC_NOARG, BC_KEEPLINE);
|
ctx()->emit(OP_TRY_BLOCK_EXIT, BC_NOARG, BC_KEEPLINE);
|
||||||
// std::vector<int> patches = {
|
std::vector<int> patches = {
|
||||||
// ctx()->emit(OP_JUMP_ABSOLUTE, BC_NOARG, BC_KEEPLINE)
|
ctx()->emit(OP_JUMP_ABSOLUTE, BC_NOARG, BC_KEEPLINE)
|
||||||
// };
|
};
|
||||||
// ctx()->exit_block();
|
ctx()->exit_block();
|
||||||
|
do {
|
||||||
// do {
|
consume(TK("except"));
|
||||||
// consume(TK("except"));
|
if(match(TK("@id"))){
|
||||||
// if(match(TK("@id"))){
|
int namei = ctx()->add_name(prev().str());
|
||||||
// int name_idx = ctx()->add_name(prev().str(), NAME_SPECIAL);
|
ctx()->emit(OP_EXCEPTION_MATCH, namei, prev().line);
|
||||||
// emit(OP_EXCEPTION_MATCH, name_idx);
|
}else{
|
||||||
// }else{
|
ctx()->emit(OP_LOAD_TRUE, BC_NOARG, BC_KEEPLINE);
|
||||||
// emit(OP_LOAD_TRUE);
|
}
|
||||||
// }
|
int patch = ctx()->emit(OP_POP_JUMP_IF_FALSE, BC_NOARG, BC_KEEPLINE);
|
||||||
// int patch = emit(OP_POP_JUMP_IF_FALSE);
|
// pop the exception on match
|
||||||
// emit(OP_POP_TOP); // pop the exception on match
|
ctx()->emit(OP_POP_TOP, BC_NOARG, BC_KEEPLINE);
|
||||||
// compile_block_body();
|
compile_block_body();
|
||||||
// patches.push_back(emit(OP_JUMP_ABSOLUTE));
|
patches.push_back(ctx()->emit(OP_JUMP_ABSOLUTE, BC_NOARG, BC_KEEPLINE));
|
||||||
// patch_jump(patch);
|
ctx()->patch_jump(patch);
|
||||||
// }while(curr().type == TK("except"));
|
}while(curr().type == TK("except"));
|
||||||
// emit(OP_RE_RAISE); // no match, re-raise
|
// no match, re-raise
|
||||||
// for (int patch : patches) patch_jump(patch);
|
ctx()->emit(OP_RE_RAISE, BC_NOARG, BC_KEEPLINE);
|
||||||
|
for (int patch : patches) ctx()->patch_jump(patch);
|
||||||
}
|
}
|
||||||
|
|
||||||
void compile_decorated(){
|
void compile_decorated(){
|
||||||
@ -611,7 +667,7 @@ class Compiler {
|
|||||||
break;
|
break;
|
||||||
default: return false;
|
default: return false;
|
||||||
}
|
}
|
||||||
std::cout << ctx()->_log_s_expr() << std::endl;
|
// std::cout << ctx()->_log_s_expr() << std::endl;
|
||||||
Expr_ rhs = ctx()->s_expr.popx();
|
Expr_ rhs = ctx()->s_expr.popx();
|
||||||
|
|
||||||
if(lhs_p->is_starred() || rhs->is_starred()){
|
if(lhs_p->is_starred() || rhs->is_starred()){
|
||||||
@ -785,7 +841,6 @@ class Compiler {
|
|||||||
if(enable_type_hints && match(TK(":"))) consume(TK("@id"));
|
if(enable_type_hints && match(TK(":"))) consume(TK("@id"));
|
||||||
|
|
||||||
if(state == 0 && curr().type == TK("=")) state = 2;
|
if(state == 0 && curr().type == TK("=")) state = 2;
|
||||||
|
|
||||||
switch (state)
|
switch (state)
|
||||||
{
|
{
|
||||||
case 0: decl->args.push_back(name); break;
|
case 0: decl->args.push_back(name); break;
|
||||||
|
|||||||
@ -357,8 +357,8 @@ struct DictItemExpr: Expr{
|
|||||||
std::vector<const Expr*> children() const override { return {key.get(), value.get()}; }
|
std::vector<const Expr*> children() const override { return {key.get(), value.get()}; }
|
||||||
|
|
||||||
void emit(CodeEmitContext* ctx) override {
|
void emit(CodeEmitContext* ctx) override {
|
||||||
key->emit(ctx);
|
|
||||||
value->emit(ctx);
|
value->emit(ctx);
|
||||||
|
key->emit(ctx); // reverse order
|
||||||
ctx->emit(OP_BUILD_TUPLE, 2, line);
|
ctx->emit(OP_BUILD_TUPLE, 2, line);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -462,9 +462,11 @@ struct CompExpr: Expr{
|
|||||||
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);
|
||||||
|
expr->emit(ctx);
|
||||||
ctx->emit(op1(), BC_NOARG, BC_KEEPLINE);
|
ctx->emit(op1(), BC_NOARG, BC_KEEPLINE);
|
||||||
ctx->patch_jump(patch);
|
ctx->patch_jump(patch);
|
||||||
}else{
|
}else{
|
||||||
|
expr->emit(ctx);
|
||||||
ctx->emit(op1(), BC_NOARG, BC_KEEPLINE);
|
ctx->emit(op1(), BC_NOARG, BC_KEEPLINE);
|
||||||
}
|
}
|
||||||
ctx->emit(OP_LOOP_CONTINUE, BC_NOARG, BC_KEEPLINE);
|
ctx->emit(OP_LOOP_CONTINUE, BC_NOARG, BC_KEEPLINE);
|
||||||
|
|||||||
49
src/frame.h
49
src/frame.h
@ -14,6 +14,7 @@ struct Frame {
|
|||||||
const CodeObject* co;
|
const CodeObject* co;
|
||||||
PyObject* _module;
|
PyObject* _module;
|
||||||
NameDict_ _locals;
|
NameDict_ _locals;
|
||||||
|
NameDict_ _closure;
|
||||||
const uint64_t id;
|
const uint64_t id;
|
||||||
std::vector<std::pair<int, std::vector<PyObject*>>> s_try_block;
|
std::vector<std::pair<int, std::vector<PyObject*>>> s_try_block;
|
||||||
const NameDict* names[5]; // name resolution array, zero terminated
|
const NameDict* names[5]; // name resolution array, zero terminated
|
||||||
@ -21,14 +22,16 @@ struct Frame {
|
|||||||
NameDict& f_locals() noexcept { return *_locals; }
|
NameDict& f_locals() noexcept { return *_locals; }
|
||||||
NameDict& f_globals() noexcept { return _module->attr(); }
|
NameDict& f_globals() noexcept { return _module->attr(); }
|
||||||
|
|
||||||
Frame(const CodeObject_& co, PyObject* _module, NameDict_ _locals=nullptr, NameDict_ _closure=nullptr)
|
Frame(const CodeObject_& co, PyObject* _module, PyObject* builtins, NameDict_ _locals=nullptr, NameDict_ _closure=nullptr)
|
||||||
: co(co.get()), _module(_module), _locals(_locals), id(kFrameGlobalId++) {
|
: co(co.get()), _module(_module), _locals(_locals), _closure(_closure), id(kFrameGlobalId++) {
|
||||||
memset(names, 0, sizeof(names));
|
memset(names, 0, sizeof(names));
|
||||||
int i = 0;
|
int i = 0;
|
||||||
if(_locals != nullptr) names[i++] = _locals.get();
|
if(_locals != nullptr) names[i++] = _locals.get();
|
||||||
if(_closure != nullptr) names[i++] = _closure.get();
|
if(_closure != nullptr) names[i++] = _closure.get();
|
||||||
names[i++] = &_module->attr();
|
names[i++] = &_module->attr(); // borrowed reference
|
||||||
// names[i++] = builtins
|
if(builtins != nullptr){
|
||||||
|
names[i++] = &builtins->attr(); // borrowed reference
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const Bytecode& next_bytecode() {
|
const Bytecode& next_bytecode() {
|
||||||
@ -41,26 +44,26 @@ struct Frame {
|
|||||||
return co->src->snapshot(line);
|
return co->src->snapshot(line);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Str stack_info(){
|
Str stack_info(){
|
||||||
// StrStream ss;
|
StrStream ss;
|
||||||
// ss << "[";
|
ss << "[";
|
||||||
// for(int i=0; i<_data.size(); i++){
|
for(int i=0; i<_data.size(); i++){
|
||||||
// ss << OBJ_TP_NAME(_data[i]);
|
ss << (i64)_data[i];
|
||||||
// if(i != _data.size()-1) ss << ", ";
|
if(i != _data.size()-1) ss << ", ";
|
||||||
// }
|
}
|
||||||
// ss << "]";
|
ss << "]";
|
||||||
// return ss.str();
|
return ss.str();
|
||||||
// }
|
}
|
||||||
|
|
||||||
void pop(){
|
void pop(){
|
||||||
#if DEBUG_MODE
|
#if DEBUG_EXTRA_CHECK
|
||||||
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_MODE
|
#if DEBUG_EXTRA_CHECK
|
||||||
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 +72,21 @@ struct Frame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
PyObject*& top(){
|
PyObject*& top(){
|
||||||
#if DEBUG_MODE
|
#if DEBUG_EXTRA_CHECK
|
||||||
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_MODE
|
#if DEBUG_EXTRA_CHECK
|
||||||
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_MODE
|
#if DEBUG_EXTRA_CHECK
|
||||||
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];
|
||||||
@ -152,12 +155,8 @@ struct Frame {
|
|||||||
void _mark() const {
|
void _mark() const {
|
||||||
for(PyObject* obj : _data) OBJ_MARK(obj);
|
for(PyObject* obj : _data) OBJ_MARK(obj);
|
||||||
OBJ_MARK(_module);
|
OBJ_MARK(_module);
|
||||||
|
_locals->_mark();
|
||||||
int i = 0; // names[0] is ensured to be non-null
|
_closure->_mark();
|
||||||
do{
|
|
||||||
names[i++]->_mark();
|
|
||||||
}while(names[i] != nullptr);
|
|
||||||
|
|
||||||
for(auto& p : s_try_block){
|
for(auto& p : s_try_block){
|
||||||
for(PyObject* obj : p.second) OBJ_MARK(obj);
|
for(PyObject* obj : p.second) OBJ_MARK(obj);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,7 +15,9 @@ inline CodeObject_ VM::compile(Str source, Str filename, CompileMode mode) {
|
|||||||
try{
|
try{
|
||||||
return compiler.compile();
|
return compiler.compile();
|
||||||
}catch(Exception& e){
|
}catch(Exception& e){
|
||||||
// std::cout << e.summary() << std::endl;
|
#if DEBUG_FULL_EXCEPTION
|
||||||
|
std::cerr << e.summary() << std::endl;
|
||||||
|
#endif
|
||||||
_error(e);
|
_error(e);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -93,12 +95,12 @@ inline void init_builtins(VM* _vm) {
|
|||||||
|
|
||||||
_vm->bind_builtin_func<1>("eval", [](VM* vm, Args& args) {
|
_vm->bind_builtin_func<1>("eval", [](VM* vm, Args& args) {
|
||||||
CodeObject_ code = vm->compile(CAST(Str&, args[0]), "<eval>", EVAL_MODE);
|
CodeObject_ code = vm->compile(CAST(Str&, args[0]), "<eval>", EVAL_MODE);
|
||||||
return vm->_exec(code, vm->top_frame()->_module, vm->top_frame()->_locals);
|
return vm->_exec(code, vm->top_frame()->_module, vm->builtins, vm->top_frame()->_locals);
|
||||||
});
|
});
|
||||||
|
|
||||||
_vm->bind_builtin_func<1>("exec", [](VM* vm, Args& args) {
|
_vm->bind_builtin_func<1>("exec", [](VM* vm, Args& args) {
|
||||||
CodeObject_ code = vm->compile(CAST(Str&, args[0]), "<exec>", EXEC_MODE);
|
CodeObject_ code = vm->compile(CAST(Str&, args[0]), "<exec>", EXEC_MODE);
|
||||||
vm->_exec(code, vm->top_frame()->_module, vm->top_frame()->_locals);
|
vm->_exec(code, vm->top_frame()->_module, vm->builtins, vm->top_frame()->_locals);
|
||||||
return vm->None;
|
return vm->None;
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -597,7 +599,7 @@ inline void add_module_json(VM* vm){
|
|||||||
vm->bind_func<1>(mod, "loads", [](VM* vm, Args& args) {
|
vm->bind_func<1>(mod, "loads", [](VM* vm, Args& args) {
|
||||||
const Str& expr = CAST(Str&, args[0]);
|
const Str& expr = CAST(Str&, args[0]);
|
||||||
CodeObject_ code = vm->compile(expr, "<json>", JSON_MODE);
|
CodeObject_ code = vm->compile(expr, "<json>", JSON_MODE);
|
||||||
return vm->_exec(code, vm->top_frame()->_module, vm->top_frame()->_locals);
|
return vm->_exec(code, vm->top_frame()->_module, vm->builtins, vm->top_frame()->_locals);
|
||||||
});
|
});
|
||||||
|
|
||||||
vm->bind_func<1>(mod, "dumps", CPP_LAMBDA(vm->call(args[0], __json__, no_arg())));
|
vm->bind_func<1>(mod, "dumps", CPP_LAMBDA(vm->call(args[0], __json__, no_arg())));
|
||||||
@ -750,7 +752,7 @@ inline void add_module_random(VM* vm){
|
|||||||
PyObject* mod = vm->new_module("random");
|
PyObject* mod = vm->new_module("random");
|
||||||
Random::register_class(vm, mod);
|
Random::register_class(vm, mod);
|
||||||
CodeObject_ code = vm->compile(kPythonLibs["random"], "random.py", EXEC_MODE);
|
CodeObject_ code = vm->compile(kPythonLibs["random"], "random.py", EXEC_MODE);
|
||||||
vm->_exec(code, mod);
|
vm->_exec(code, mod, vm->builtins);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void add_module_gc(VM* vm){
|
inline void add_module_gc(VM* vm){
|
||||||
@ -778,11 +780,11 @@ inline void VM::post_init(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
CodeObject_ code = compile(kPythonLibs["builtins"], "<builtins>", EXEC_MODE);
|
CodeObject_ code = compile(kPythonLibs["builtins"], "<builtins>", EXEC_MODE);
|
||||||
this->_exec(code, this->builtins);
|
this->_exec(code, this->builtins, nullptr);
|
||||||
code = compile(kPythonLibs["_dict"], "<builtins>", EXEC_MODE);
|
code = compile(kPythonLibs["_dict"], "<builtins>", EXEC_MODE);
|
||||||
this->_exec(code, this->builtins);
|
this->_exec(code, this->builtins, nullptr);
|
||||||
code = compile(kPythonLibs["_set"], "<builtins>", EXEC_MODE);
|
code = compile(kPythonLibs["_set"], "<builtins>", EXEC_MODE);
|
||||||
this->_exec(code, this->builtins);
|
this->_exec(code, this->builtins, nullptr);
|
||||||
|
|
||||||
// property is defined in builtins.py so we need to add it after builtins is loaded
|
// property is defined in builtins.py so we need to add it after builtins is loaded
|
||||||
_t(tp_object)->attr().set(__class__, property(CPP_LAMBDA(vm->_t(args[0]))));
|
_t(tp_object)->attr().set(__class__, property(CPP_LAMBDA(vm->_t(args[0]))));
|
||||||
|
|||||||
19
src/vm.h
19
src/vm.h
@ -93,7 +93,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
Frame* top_frame() const {
|
Frame* top_frame() const {
|
||||||
#if DEBUG_MODE
|
#if DEBUG_EXTRA_CHECK
|
||||||
if(callstack.empty()) UNREACHABLE();
|
if(callstack.empty()) UNREACHABLE();
|
||||||
#endif
|
#endif
|
||||||
return callstack.top().get();
|
return callstack.top().get();
|
||||||
@ -166,13 +166,15 @@ 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 DEBUG_DIS_REPL
|
||||||
if(_module == _main) std::cout << disassemble(code) << '\n';
|
if(_module == _main) std::cout << disassemble(code) << '\n';
|
||||||
return _exec(code, _module);
|
#endif
|
||||||
|
return _exec(code, _module, builtins);
|
||||||
}catch (const Exception& e){
|
}catch (const Exception& e){
|
||||||
*_stderr << e.summary() << '\n';
|
*_stderr << e.summary() << '\n';
|
||||||
|
|
||||||
}
|
}
|
||||||
#if !DEBUG_MODE
|
#if !DEBUG_FULL_EXCEPTION
|
||||||
catch (const std::exception& e) {
|
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';
|
||||||
@ -607,11 +609,12 @@ inline Str VM::disassemble(CodeObject_ co){
|
|||||||
argStr += " (" + BITWISE_SPECIAL_METHODS[byte.arg].str() + ")";
|
argStr += " (" + BITWISE_SPECIAL_METHODS[byte.arg].str() + ")";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ss << argStr;
|
ss << pad(argStr, 40); // may overflow
|
||||||
// ss << pad(argStr, 20); // may overflow
|
ss << co->blocks[byte.block].type;
|
||||||
// ss << co->blocks[byte.block].to_string();
|
|
||||||
if(i != co->codes.size() - 1) ss << '\n';
|
if(i != co->codes.size() - 1) ss << '\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !DEBUG_DIS_REPL_MIN
|
||||||
StrStream consts;
|
StrStream consts;
|
||||||
consts << "co_consts: ";
|
consts << "co_consts: ";
|
||||||
consts << CAST(Str, asRepr(VAR(co->consts)));
|
consts << CAST(Str, asRepr(VAR(co->consts)));
|
||||||
@ -624,7 +627,7 @@ inline Str VM::disassemble(CodeObject_ co){
|
|||||||
}
|
}
|
||||||
names << CAST(Str, asRepr(VAR(list)));
|
names << CAST(Str, asRepr(VAR(list)));
|
||||||
ss << '\n' << consts.str() << '\n' << names.str();
|
ss << '\n' << consts.str() << '\n' << names.str();
|
||||||
|
#endif
|
||||||
for(auto& decl: co->func_decls){
|
for(auto& decl: co->func_decls){
|
||||||
ss << "\n\n" << "Disassembly of " << decl->name.str() << ":\n";
|
ss << "\n\n" << "Disassembly of " << decl->name.str() << ":\n";
|
||||||
ss << disassemble(decl->code);
|
ss << disassemble(decl->code);
|
||||||
@ -753,7 +756,7 @@ inline PyObject* VM::call(PyObject* callable, Args args, const Args& kwargs, boo
|
|||||||
locals->set(key, kwargs[i+1]);
|
locals->set(key, kwargs[i+1]);
|
||||||
}
|
}
|
||||||
PyObject* _module = fn._module != nullptr ? fn._module : top_frame()->_module;
|
PyObject* _module = fn._module != nullptr ? fn._module : top_frame()->_module;
|
||||||
auto _frame = _new_frame(fn.decl->code, _module, locals, fn._closure);
|
auto _frame = _new_frame(fn.decl->code, _module, builtins, locals, fn._closure);
|
||||||
if(fn.decl->code->is_generator) return PyIter(Generator(this, std::move(_frame)));
|
if(fn.decl->code->is_generator) return PyIter(Generator(this, std::move(_frame)));
|
||||||
callstack.push(std::move(_frame));
|
callstack.push(std::move(_frame));
|
||||||
if(opCall) return _py_op_call;
|
if(opCall) return _py_op_call;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user