mirror of
https://github.com/pocketpy/pocketpy
synced 2025-12-07 02:30:17 +00:00
support @property.setter
This commit is contained in:
parent
e8ad5b5784
commit
e124f635c1
@ -23,7 +23,7 @@
|
|||||||
#include <bitset>
|
#include <bitset>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
|
||||||
#define PK_VERSION "1.2.9"
|
#define PK_VERSION "1.3.0"
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "export.h"
|
#include "export.h"
|
||||||
|
|||||||
@ -23,6 +23,7 @@ OPCODE(LOAD_NAME)
|
|||||||
OPCODE(LOAD_NONLOCAL)
|
OPCODE(LOAD_NONLOCAL)
|
||||||
OPCODE(LOAD_GLOBAL)
|
OPCODE(LOAD_GLOBAL)
|
||||||
OPCODE(LOAD_ATTR)
|
OPCODE(LOAD_ATTR)
|
||||||
|
OPCODE(LOAD_CLASS_GLOBAL)
|
||||||
OPCODE(LOAD_METHOD)
|
OPCODE(LOAD_METHOD)
|
||||||
OPCODE(LOAD_SUBSCR)
|
OPCODE(LOAD_SUBSCR)
|
||||||
|
|
||||||
|
|||||||
@ -133,7 +133,8 @@ public:
|
|||||||
PyObject* StopIteration;
|
PyObject* StopIteration;
|
||||||
PyObject* _main; // __main__ module
|
PyObject* _main; // __main__ module
|
||||||
|
|
||||||
PyObject* _last_exception;
|
PyObject* _last_exception; // last exception
|
||||||
|
PyObject* _curr_class; // current class being defined
|
||||||
|
|
||||||
#if PK_ENABLE_CEVAL_CALLBACK
|
#if PK_ENABLE_CEVAL_CALLBACK
|
||||||
void (*_ceval_on_step)(VM*, Frame*, Bytecode bc) = nullptr;
|
void (*_ceval_on_step)(VM*, Frame*, Bytecode bc) = nullptr;
|
||||||
|
|||||||
@ -182,10 +182,22 @@ __NEXT_STEP:;
|
|||||||
_0 = vm->builtins->attr().try_get_likely_found(_name);
|
_0 = vm->builtins->attr().try_get_likely_found(_name);
|
||||||
if(_0 != nullptr) { PUSH(_0); DISPATCH(); }
|
if(_0 != nullptr) { PUSH(_0); DISPATCH(); }
|
||||||
vm->NameError(_name);
|
vm->NameError(_name);
|
||||||
}DISPATCH();
|
} DISPATCH();
|
||||||
TARGET(LOAD_ATTR)
|
TARGET(LOAD_ATTR){
|
||||||
TOP() = getattr(TOP(), StrName(byte.arg));
|
TOP() = getattr(TOP(), StrName(byte.arg));
|
||||||
DISPATCH();
|
} DISPATCH();
|
||||||
|
TARGET(LOAD_CLASS_GLOBAL){
|
||||||
|
PK_ASSERT(_curr_class != nullptr);
|
||||||
|
StrName _name(byte.arg);
|
||||||
|
PyObject* _0 = getattr(_curr_class, _name, false);
|
||||||
|
if(_0 != nullptr) { PUSH(_0); DISPATCH(); }
|
||||||
|
// load global if attribute not found
|
||||||
|
_0 = frame->f_globals().try_get_likely_found(_name);
|
||||||
|
if(_0 != nullptr) { PUSH(_0); DISPATCH(); }
|
||||||
|
_0 = vm->builtins->attr().try_get_likely_found(_name);
|
||||||
|
if(_0 != nullptr) { PUSH(_0); DISPATCH(); }
|
||||||
|
vm->NameError(_name);
|
||||||
|
} DISPATCH();
|
||||||
TARGET(LOAD_METHOD){
|
TARGET(LOAD_METHOD){
|
||||||
PyObject* _0;
|
PyObject* _0;
|
||||||
TOP() = get_unbound_method(TOP(), StrName(byte.arg), &_0, true, true);
|
TOP() = get_unbound_method(TOP(), StrName(byte.arg), &_0, true, true);
|
||||||
@ -723,15 +735,18 @@ __NEXT_STEP:;
|
|||||||
PyObject* _0 = POPX(); // super
|
PyObject* _0 = POPX(); // super
|
||||||
if(_0 == None) _0 = _t(tp_object);
|
if(_0 == None) _0 = _t(tp_object);
|
||||||
check_non_tagged_type(_0, tp_type);
|
check_non_tagged_type(_0, tp_type);
|
||||||
PyObject* _1 = new_type_object(frame->_module, _name, PK_OBJ_GET(Type, _0));
|
_curr_class = new_type_object(frame->_module, _name, PK_OBJ_GET(Type, _0));
|
||||||
PUSH(_1);
|
} DISPATCH();
|
||||||
|
TARGET(END_CLASS) {
|
||||||
|
PK_ASSERT(_curr_class != nullptr);
|
||||||
|
_curr_class = nullptr;
|
||||||
} DISPATCH();
|
} DISPATCH();
|
||||||
TARGET(END_CLASS) POP(); DISPATCH();
|
|
||||||
TARGET(STORE_CLASS_ATTR){
|
TARGET(STORE_CLASS_ATTR){
|
||||||
|
PK_ASSERT(_curr_class != nullptr);
|
||||||
StrName _name(byte.arg);
|
StrName _name(byte.arg);
|
||||||
PyObject* _0 = POPX();
|
PyObject* _0 = POPX();
|
||||||
if(is_non_tagged_type(_0, tp_function)){
|
if(is_non_tagged_type(_0, tp_function)){
|
||||||
PK_OBJ_GET(Function, _0)._class = TOP();
|
PK_OBJ_GET(Function, _0)._class = _curr_class;
|
||||||
}
|
}
|
||||||
TOP()->attr().set(_name, _0);
|
TOP()->attr().set(_name, _0);
|
||||||
} DISPATCH();
|
} DISPATCH();
|
||||||
@ -793,8 +808,8 @@ __NEXT_STEP:;
|
|||||||
} DISPATCH();
|
} DISPATCH();
|
||||||
|
|
||||||
#if !PK_ENABLE_COMPUTED_GOTO
|
#if !PK_ENABLE_COMPUTED_GOTO
|
||||||
static_assert(OP_DEC_GLOBAL == 106);
|
static_assert(OP_DEC_GLOBAL == 107);
|
||||||
case 107: case 108: case 109: case 110: case 111: case 112: case 113: case 114: case 115: case 116: case 117: case 118: case 119: case 120: case 121: case 122: case 123: case 124: case 125: case 126: case 127: case 128: case 129: case 130: case 131: case 132: case 133: case 134: case 135: case 136: case 137: case 138: case 139: case 140: case 141: case 142: case 143: case 144: case 145: case 146: case 147: case 148: case 149: case 150: case 151: case 152: case 153: case 154: case 155: case 156: case 157: case 158: case 159: case 160: case 161: case 162: case 163: case 164: case 165: case 166: case 167: case 168: case 169: case 170: case 171: case 172: case 173: case 174: case 175: case 176: case 177: case 178: case 179: case 180: case 181: case 182: case 183: case 184: case 185: case 186: case 187: case 188: case 189: case 190: case 191: case 192: case 193: case 194: case 195: case 196: case 197: case 198: case 199: case 200: case 201: case 202: case 203: case 204: case 205: case 206: case 207: case 208: case 209: case 210: case 211: case 212: case 213: case 214: case 215: case 216: case 217: case 218: case 219: case 220: case 221: case 222: case 223: case 224: case 225: case 226: case 227: case 228: case 229: case 230: case 231: case 232: case 233: case 234: case 235: case 236: case 237: case 238: case 239: case 240: case 241: case 242: case 243: case 244: case 245: case 246: case 247: case 248: case 249: case 250: case 251: case 252: case 253: case 254: case 255: FATAL_ERROR(); break;
|
case 108: case 109: case 110: case 111: case 112: case 113: case 114: case 115: case 116: case 117: case 118: case 119: case 120: case 121: case 122: case 123: case 124: case 125: case 126: case 127: case 128: case 129: case 130: case 131: case 132: case 133: case 134: case 135: case 136: case 137: case 138: case 139: case 140: case 141: case 142: case 143: case 144: case 145: case 146: case 147: case 148: case 149: case 150: case 151: case 152: case 153: case 154: case 155: case 156: case 157: case 158: case 159: case 160: case 161: case 162: case 163: case 164: case 165: case 166: case 167: case 168: case 169: case 170: case 171: case 172: case 173: case 174: case 175: case 176: case 177: case 178: case 179: case 180: case 181: case 182: case 183: case 184: case 185: case 186: case 187: case 188: case 189: case 190: case 191: case 192: case 193: case 194: case 195: case 196: case 197: case 198: case 199: case 200: case 201: case 202: case 203: case 204: case 205: case 206: case 207: case 208: case 209: case 210: case 211: case 212: case 213: case 214: case 215: case 216: case 217: case 218: case 219: case 220: case 221: case 222: case 223: case 224: case 225: case 226: case 227: case 228: case 229: case 230: case 231: case 232: case 233: case 234: case 235: case 236: case 237: case 238: case 239: case 240: case 241: case 242: case 243: case 244: case 245: case 246: case 247: case 248: case 249: case 250: case 251: case 252: case 253: case 254: case 255: FATAL_ERROR(); break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
11
src/expr.cpp
11
src/expr.cpp
@ -127,8 +127,15 @@ namespace pkpy{
|
|||||||
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(ctx->is_compiling_class && scope == NAME_GLOBAL){
|
||||||
if(scope == NAME_GLOBAL_UNKNOWN) op = OP_LOAD_NAME;
|
// if we are compiling a class, we should use OP_LOAD_ATTR_GLOBAL instead of OP_LOAD_GLOBAL
|
||||||
|
// this supports @property.setter
|
||||||
|
op = OP_LOAD_CLASS_GLOBAL;
|
||||||
|
// exec()/eval() won't work with OP_LOAD_ATTR_GLOBAL in class body
|
||||||
|
}else{
|
||||||
|
// 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1653,6 +1653,12 @@ void add_module_gc(VM* vm){
|
|||||||
void VM::post_init(){
|
void VM::post_init(){
|
||||||
init_builtins(this);
|
init_builtins(this);
|
||||||
|
|
||||||
|
bind_method<1>("property", "setter", [](VM* vm, ArgsView args) {
|
||||||
|
Property& self = _CAST(Property&, args[0]);
|
||||||
|
self.setter = args[1];
|
||||||
|
return args[0];
|
||||||
|
});
|
||||||
|
|
||||||
// type
|
// type
|
||||||
bind__getitem__(tp_type, [](VM* vm, PyObject* self, PyObject* _){
|
bind__getitem__(tp_type, [](VM* vm, PyObject* self, PyObject* _){
|
||||||
PK_UNUSED(_);
|
PK_UNUSED(_);
|
||||||
|
|||||||
@ -1192,6 +1192,7 @@ void ManagedHeap::mark() {
|
|||||||
for(PyObject* obj: vm->s_data) PK_OBJ_MARK(obj);
|
for(PyObject* obj: vm->s_data) PK_OBJ_MARK(obj);
|
||||||
if(_gc_marker_ex) _gc_marker_ex(vm);
|
if(_gc_marker_ex) _gc_marker_ex(vm);
|
||||||
if(vm->_last_exception) PK_OBJ_MARK(vm->_last_exception);
|
if(vm->_last_exception) PK_OBJ_MARK(vm->_last_exception);
|
||||||
|
if(vm->_curr_class) PK_OBJ_MARK(vm->_curr_class);
|
||||||
if(vm->_c.error != nullptr) PK_OBJ_MARK(vm->_c.error);
|
if(vm->_c.error != nullptr) PK_OBJ_MARK(vm->_c.error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -109,3 +109,13 @@ class B(A):
|
|||||||
# assert B.a == 1 ...bug here
|
# assert B.a == 1 ...bug here
|
||||||
assert B.b == 3
|
assert B.b == 3
|
||||||
assert B.c == 4
|
assert B.c == 4
|
||||||
|
|
||||||
|
class A:
|
||||||
|
x = 1
|
||||||
|
x = x + 1
|
||||||
|
y = 1
|
||||||
|
z = x + y
|
||||||
|
|
||||||
|
assert A.x == 2
|
||||||
|
assert A.y == 1
|
||||||
|
assert A.z == 3
|
||||||
|
|||||||
@ -810,12 +810,29 @@ try:
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
class Vector2:
|
||||||
|
def __init__(self) -> None:
|
||||||
|
self._x = 0
|
||||||
|
|
||||||
|
@property
|
||||||
|
def x(self):
|
||||||
|
return self._x
|
||||||
|
|
||||||
|
@x.setter
|
||||||
|
def x(self, val):
|
||||||
|
self._x = val
|
||||||
|
|
||||||
|
v = Vector2()
|
||||||
|
assert v.x == 0
|
||||||
|
v.x = 10
|
||||||
|
assert v.x == 10
|
||||||
|
|
||||||
# /************ module timeit ************/
|
# /************ module timeit ************/
|
||||||
import timeit
|
import timeit
|
||||||
|
|
||||||
def aaa():
|
def aaa():
|
||||||
for i in range(100):
|
for i in range(10):
|
||||||
for j in range(100):
|
for j in range(10):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
assert type(timeit.timeit(aaa, 2)) is float
|
assert type(timeit.timeit(aaa, 2)) is float
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user