mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 03:20:18 +00:00
some fix
This commit is contained in:
parent
37db7bc29b
commit
c01a77d4b4
20
src/ceval.h
20
src/ceval.h
@ -165,6 +165,16 @@ __NEXT_STEP:;
|
||||
TARGET(STORE_FAST)
|
||||
frame->_locals[byte.arg] = POPX();
|
||||
DISPATCH();
|
||||
TARGET(STORE_NAME) {
|
||||
StrName name(byte.arg);
|
||||
PyObject* val = POPX();
|
||||
if(frame->_locals.is_valid()){
|
||||
bool ok = frame->_locals.try_set(name, val);
|
||||
if(!ok) vm->NameError(name);
|
||||
}else{
|
||||
frame->f_globals().set(name, val);
|
||||
}
|
||||
} DISPATCH();
|
||||
TARGET(STORE_GLOBAL) {
|
||||
StrName name(byte.arg);
|
||||
frame->f_globals().set(name, POPX());
|
||||
@ -188,6 +198,16 @@ __NEXT_STEP:;
|
||||
if(val == nullptr) vm->NameError(co->varnames[byte.arg]);
|
||||
frame->_locals[byte.arg] = nullptr;
|
||||
} DISPATCH();
|
||||
TARGET(DELETE_NAME) {
|
||||
StrName name(byte.arg);
|
||||
if(frame->_locals.is_valid()){
|
||||
if(!frame->_locals.contains(name)) vm->NameError(name);
|
||||
frame->_locals.erase(name);
|
||||
}else{
|
||||
if(!frame->f_globals().contains(name)) vm->NameError(name);
|
||||
frame->f_globals().erase(name);
|
||||
}
|
||||
} DISPATCH();
|
||||
TARGET(DELETE_GLOBAL) {
|
||||
StrName name(byte.arg);
|
||||
if(frame->f_globals().contains(name)){
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
namespace pkpy{
|
||||
|
||||
enum NameScope { NAME_LOCAL, NAME_GLOBAL };
|
||||
enum NameScope { NAME_LOCAL, NAME_GLOBAL, NAME_GLOBAL_UNKNOWN };
|
||||
|
||||
enum Opcode {
|
||||
#define OPCODE(name) OP_##name,
|
||||
|
@ -21,6 +21,7 @@ class Compiler {
|
||||
std::unique_ptr<Lexer> lexer;
|
||||
stack<CodeEmitContext> contexts;
|
||||
VM* vm;
|
||||
bool unknown_global_scope; // for eval/exec() call
|
||||
bool used;
|
||||
// for parsing token stream
|
||||
int i = 0;
|
||||
@ -37,7 +38,11 @@ class Compiler {
|
||||
|
||||
CodeEmitContext* ctx() { return &contexts.top(); }
|
||||
CompileMode mode() const{ return lexer->src->mode; }
|
||||
NameScope name_scope() const { return contexts.size()>1 ? NAME_LOCAL : NAME_GLOBAL; }
|
||||
NameScope name_scope() const {
|
||||
auto s = contexts.size()>1 ? NAME_LOCAL : NAME_GLOBAL;
|
||||
if(unknown_global_scope && s == NAME_GLOBAL) s = NAME_GLOBAL_UNKNOWN;
|
||||
return s;
|
||||
}
|
||||
|
||||
CodeObject_ push_global_context(){
|
||||
CodeObject_ co = make_sp<CodeObject>(lexer->src, lexer->src->filename);
|
||||
@ -977,9 +982,10 @@ __SUBSCR_END:
|
||||
void IndentationError(Str msg){ lexer->throw_err("IndentationError", msg, err().line, err().start); }
|
||||
|
||||
public:
|
||||
Compiler(VM* vm, const Str& source, const Str& filename, CompileMode mode){
|
||||
Compiler(VM* vm, const Str& source, const Str& filename, CompileMode mode, bool unknown_global_scope=false){
|
||||
this->vm = vm;
|
||||
this->used = false;
|
||||
this->unknown_global_scope = unknown_global_scope;
|
||||
this->lexer = std::make_unique<Lexer>(
|
||||
make_sp<SourceData>(source, filename, mode)
|
||||
);
|
||||
|
@ -136,6 +136,8 @@ struct NameExpr: Expr{
|
||||
ctx->emit(OP_LOAD_FAST, index, line);
|
||||
}else{
|
||||
Opcode op = ctx->level <= 1 ? OP_LOAD_GLOBAL : OP_LOAD_NONLOCAL;
|
||||
// we cannot determine the scope when calling exec()/eval()
|
||||
if(scope == NAME_GLOBAL_UNKNOWN) op = OP_LOAD_NAME;
|
||||
ctx->emit(op, StrName(name).index, line);
|
||||
}
|
||||
}
|
||||
@ -148,6 +150,9 @@ struct NameExpr: Expr{
|
||||
case NAME_GLOBAL:
|
||||
ctx->emit(OP_DELETE_GLOBAL, StrName(name).index, line);
|
||||
break;
|
||||
case NAME_GLOBAL_UNKNOWN:
|
||||
ctx->emit(OP_DELETE_NAME, StrName(name).index, line);
|
||||
break;
|
||||
default: FATAL_ERROR(); break;
|
||||
}
|
||||
return true;
|
||||
@ -166,6 +171,9 @@ struct NameExpr: Expr{
|
||||
case NAME_GLOBAL:
|
||||
ctx->emit(OP_STORE_GLOBAL, StrName(name).index, line);
|
||||
break;
|
||||
case NAME_GLOBAL_UNKNOWN:
|
||||
ctx->emit(OP_STORE_NAME, StrName(name).index, line);
|
||||
break;
|
||||
default: FATAL_ERROR(); break;
|
||||
}
|
||||
return true;
|
||||
|
12
src/frame.h
12
src/frame.h
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "codeobject.h"
|
||||
#include "common.h"
|
||||
#include "memory.h"
|
||||
#include "vector.h"
|
||||
|
||||
@ -35,6 +36,17 @@ struct FastLocals{
|
||||
return a[index];
|
||||
}
|
||||
|
||||
bool contains(StrName name){
|
||||
return varnames_inv->contains(name);
|
||||
}
|
||||
|
||||
void erase(StrName name){
|
||||
if(!is_valid()) return;
|
||||
int index = varnames_inv->try_get(name);
|
||||
if(index == -1) FATAL_ERROR();
|
||||
a[index] = nullptr;
|
||||
}
|
||||
|
||||
bool try_set(StrName name, PyObject* value){
|
||||
if(!is_valid()) return false;
|
||||
int index = varnames_inv->try_get(name);
|
||||
|
@ -27,11 +27,13 @@ OPCODE(LOAD_METHOD)
|
||||
OPCODE(LOAD_SUBSCR)
|
||||
|
||||
OPCODE(STORE_FAST)
|
||||
OPCODE(STORE_NAME)
|
||||
OPCODE(STORE_GLOBAL)
|
||||
OPCODE(STORE_ATTR)
|
||||
OPCODE(STORE_SUBSCR)
|
||||
|
||||
OPCODE(DELETE_FAST)
|
||||
OPCODE(DELETE_NAME)
|
||||
OPCODE(DELETE_GLOBAL)
|
||||
OPCODE(DELETE_ATTR)
|
||||
OPCODE(DELETE_SUBSCR)
|
||||
|
@ -11,8 +11,8 @@
|
||||
|
||||
namespace pkpy {
|
||||
|
||||
inline CodeObject_ VM::compile(Str source, Str filename, CompileMode mode) {
|
||||
Compiler compiler(this, source, filename, mode);
|
||||
inline CodeObject_ VM::compile(Str source, Str filename, CompileMode mode, bool unknown_global_scope) {
|
||||
Compiler compiler(this, source, filename, mode, unknown_global_scope);
|
||||
try{
|
||||
return compiler.compile();
|
||||
}catch(Exception& e){
|
||||
@ -97,13 +97,13 @@ inline void init_builtins(VM* _vm) {
|
||||
});
|
||||
|
||||
_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, true);
|
||||
FrameId frame = vm->top_frame();
|
||||
return vm->_exec(code.get(), frame->_module, frame->_locals, nullptr);
|
||||
});
|
||||
|
||||
_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, true);
|
||||
FrameId frame = vm->top_frame();
|
||||
vm->_exec(code.get(), frame->_module, frame->_locals, nullptr);
|
||||
return vm->None;
|
||||
|
2
src/vm.h
2
src/vm.h
@ -333,7 +333,7 @@ public:
|
||||
_lazy_modules.clear();
|
||||
}
|
||||
|
||||
CodeObject_ compile(Str source, Str filename, CompileMode mode);
|
||||
CodeObject_ compile(Str source, Str filename, CompileMode mode, bool unknown_global_scope=false);
|
||||
PyObject* num_negated(PyObject* obj);
|
||||
f64 num_to_float(PyObject* obj);
|
||||
bool asBool(PyObject* obj);
|
||||
|
@ -1,33 +1,32 @@
|
||||
assert eval('1+1') == 2
|
||||
assert eval('[1,2,3]') == [1,2,3]
|
||||
|
||||
# some bugs here
|
||||
# def f(x):
|
||||
# return eval('x')
|
||||
def f(x):
|
||||
return eval('x')
|
||||
|
||||
# assert f(1) == 1
|
||||
assert f(1) == 1
|
||||
|
||||
|
||||
# a = 0
|
||||
# assert eval('a') == 0
|
||||
a = 0
|
||||
assert eval('a') == 0
|
||||
|
||||
# exec('a = 1')
|
||||
# assert a == 1
|
||||
exec('a = 1')
|
||||
assert a == 1
|
||||
|
||||
# def f(x):
|
||||
# exec('a = x')
|
||||
# return a
|
||||
def f(a):
|
||||
exec('a = 3')
|
||||
return a
|
||||
|
||||
# assert f(2) == 2
|
||||
assert f(2) == 3
|
||||
|
||||
# exec(
|
||||
# "exec('a = eval(\"3 + 5\")')"
|
||||
# )
|
||||
# assert a == 8
|
||||
exec(
|
||||
"exec('a = eval(\"3 + 5\")')"
|
||||
)
|
||||
assert a == 8
|
||||
|
||||
# def f():
|
||||
# b = 1
|
||||
# exec(
|
||||
# "exec('b = eval(\"3 + 5\")')"
|
||||
# )
|
||||
# assert b == 8
|
||||
def f():
|
||||
b = 1
|
||||
exec(
|
||||
"exec('b = eval(\"3 + 5\")')"
|
||||
)
|
||||
assert b == 8
|
Loading…
x
Reference in New Issue
Block a user