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