This commit is contained in:
blueloveTH 2023-04-05 16:24:56 +08:00
parent 9077da4d6c
commit 66e6a6b559
4 changed files with 53 additions and 5 deletions

View File

@ -309,6 +309,20 @@ __NEXT_STEP:;
} }
}; DISPATCH(); }; DISPATCH();
/*****************************************/ /*****************************************/
case OP_UNPACK_SEQUENCE: {
// asIter or iter->next may run bytecode
// accidential gc may happen
// lock the gc via RAII
auto _lock = heap.gc_scope_lock();
PyObject* obj = asIter(frame->popx());
BaseIter* iter = PyIter_AS_C(obj);
for(int i=0; i<byte.arg; i++){
PyObject* item = iter->next();
if(item == nullptr) ValueError("not enough values to unpack");
frame->push(item);
}
if(iter->next() != nullptr) ValueError("too many values to unpack");
}; DISPATCH();
/*****************************************/ /*****************************************/
// case OP_SETUP_DECORATOR: DISPATCH(); // case OP_SETUP_DECORATOR: DISPATCH();
// case OP_BEGIN_CLASS: { // case OP_BEGIN_CLASS: {

View File

@ -40,7 +40,9 @@ class Compiler {
} }
void pop_context(){ void pop_context(){
if(!ctx()->s_expr.empty()) UNREACHABLE(); if(!ctx()->s_expr.empty()){
throw std::runtime_error("!ctx()->s_expr.empty()\n" + ctx()->_log_s_expr());
}
// 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.empty() || 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);
@ -184,6 +186,7 @@ class Compiler {
// PASS // PASS
void exprTuple(){ void exprTuple(){
std::vector<Expr_> items; std::vector<Expr_> items;
items.push_back(ctx()->s_expr.popx());
do { do {
EXPR(); // NOTE: "1," will fail, "1,2" will be ok EXPR(); // NOTE: "1," will fail, "1,2" will be ok
items.push_back(ctx()->s_expr.popx()); items.push_back(ctx()->s_expr.popx());
@ -385,6 +388,7 @@ class Compiler {
// PASS // PASS
void exprSubscr() { void exprSubscr() {
auto e = make_expr<SubscrExpr>(); auto e = make_expr<SubscrExpr>();
e->a = ctx()->s_expr.popx();
std::vector<Expr_> items; std::vector<Expr_> items;
do { do {
EXPR_TUPLE(); EXPR_TUPLE();
@ -605,6 +609,7 @@ class Compiler {
break; break;
default: return false; default: return false;
} }
std::cout << ctx()->_log_s_expr() << std::endl;
Expr_ rhs = ctx()->s_expr.popx(); Expr_ rhs = ctx()->s_expr.popx();
rhs->emit(ctx()); rhs->emit(ctx());
bool ok = lhs_p->emit_store(ctx()); bool ok = lhs_p->emit_store(ctx());

View File

@ -5,6 +5,7 @@
#include "lexer.h" #include "lexer.h"
#include "error.h" #include "error.h"
#include "ceval.h" #include "ceval.h"
#include "str.h"
namespace pkpy{ namespace pkpy{
@ -55,11 +56,19 @@ struct CodeEmitContext{
// clear the expression stack and generate bytecode // clear the expression stack and generate bytecode
void emit_expr(){ void emit_expr(){
if(s_expr.size() != 1) UNREACHABLE(); if(s_expr.size() != 1){
throw std::runtime_error("s_expr.size() != 1\n" + _log_s_expr());
}
Expr_ expr = s_expr.popx(); Expr_ expr = s_expr.popx();
expr->emit(this); expr->emit(this);
} }
Str _log_s_expr(){
StrStream ss;
for(auto& e: s_expr.data()) ss << e->str() << " ";
return ss.str();
}
int emit(Opcode opcode, int arg, int line) { int emit(Opcode opcode, int arg, int line) {
co->codes.push_back( co->codes.push_back(
Bytecode{(uint16_t)opcode, (uint16_t)curr_block_i, arg, line} Bytecode{(uint16_t)opcode, (uint16_t)curr_block_i, arg, line}
@ -411,8 +420,9 @@ struct TupleExpr: SequenceExpr{
if(starred_i != items.size()-1) return false; if(starred_i != items.size()-1) return false;
ctx->emit(OP_UNPACK_EX, items.size()-1, line); ctx->emit(OP_UNPACK_EX, items.size()-1, line);
} }
for(auto& e: items){ // do reverse emit
bool ok = e->emit_store(ctx); for(int i=items.size()-1; i>=0; i--){
bool ok = items[i]->emit_store(ctx);
if(!ok) return false; if(!ok) return false;
} }
return true; return true;

View File

@ -47,6 +47,23 @@ struct ManagedHeap{
int gc_threshold = kMinGCThreshold; int gc_threshold = kMinGCThreshold;
int gc_counter = 0; int gc_counter = 0;
/********************/
int _gc_lock_counter = 0;
struct ScopeLock{
ManagedHeap* heap;
ScopeLock(ManagedHeap* heap): heap(heap){
heap->_gc_lock_counter++;
}
~ScopeLock(){
heap->_gc_lock_counter--;
}
};
ScopeLock gc_scope_lock(){
return ScopeLock(this);
}
/********************/
template<typename T> template<typename T>
PyObject* gcnew(Type type, T&& val){ PyObject* gcnew(Type type, T&& val){
PyObject* obj = new Py_<std::decay_t<T>>(type, std::forward<T>(val)); PyObject* obj = new Py_<std::decay_t<T>>(type, std::forward<T>(val));
@ -98,6 +115,7 @@ struct ManagedHeap{
void _delete_hook(VM* vm, PyObject* obj); void _delete_hook(VM* vm, PyObject* obj);
void _auto_collect(VM* vm){ void _auto_collect(VM* vm){
if(_gc_lock_counter > 0) return;
if(gc_counter < gc_threshold) return; if(gc_counter < gc_threshold) return;
gc_counter = 0; gc_counter = 0;
collect(vm); collect(vm);
@ -106,6 +124,7 @@ struct ManagedHeap{
} }
int collect(VM* vm){ int collect(VM* vm){
if(_gc_lock_counter > 0) UNREACHABLE();
mark(vm); mark(vm);
int freed = sweep(vm); int freed = sweep(vm);
return freed; return freed;