This commit is contained in:
blueloveTH 2024-07-30 18:12:22 +08:00
parent db0acc854c
commit 67ae21d18d
8 changed files with 46 additions and 46 deletions

View File

@ -1,9 +1,9 @@
#!/bin/bash #!/bin/bash
# Check if clang++ is installed # Check if clang is installed
if ! type -P clang++ >/dev/null 2>&1; then if ! type -P clang >/dev/null 2>&1; then
echo "clang++ is required and not installed. Kindly install it." echo "clang is required and not installed. Kindly install it."
echo "Run: sudo apt-get install libc++-dev libc++abi-dev clang" echo "Run: sudo apt-get install clang"
exit 1 exit 1
fi fi
@ -18,13 +18,11 @@ if [ $? -ne 0 ]; then
exit 1 exit 1
fi fi
SRC_C=$(find src/ -name "*.c") SRC=$(find src/ -name "*.c")
SRC_CPP=$(find src/ -name "*.cpp")
SRC="$SRC_C $SRC_CPP"
echo "> Compiling and linking source files... " echo "> Compiling and linking source files... "
FLAGS="-std=c++17 -O1 -stdlib=libc++ -frtti -Wfatal-errors -Iinclude" FLAGS="-std=c11 -O1 -Wfatal-errors -Iinclude"
if [[ "$OSTYPE" == "darwin"* ]]; then if [[ "$OSTYPE" == "darwin"* ]]; then
LIB_EXTENSION=".dylib" LIB_EXTENSION=".dylib"
@ -35,12 +33,12 @@ else
LINK_FLAGS="-Wl,-rpath=." LINK_FLAGS="-Wl,-rpath=."
fi fi
clang++ $FLAGS -o libpocketpy$LIB_EXTENSION $SRC -fPIC -shared clang $FLAGS -o libpocketpy$LIB_EXTENSION $SRC -fPIC -shared
# compile main.cpp and link to libpocketpy.so # compile main.cpp and link to libpocketpy.so
echo "> Compiling main.cpp and linking to libpocketpy$LIB_EXTENSION..." echo "> Compiling main.c and linking to libpocketpy$LIB_EXTENSION..."
clang++ $FLAGS -o main -O1 src2/main.cpp -L. -lpocketpy $LINK_FLAGS clang $FLAGS -o main -O1 src2/main.c -L. -lpocketpy $LINK_FLAGS
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
echo "Build completed. Type \"./main\" to enter REPL." echo "Build completed. Type \"./main\" to enter REPL."

View File

@ -93,6 +93,8 @@ int pk_arrayequal(py_TValue* lhs, int lhs_length, py_TValue* rhs, int rhs_length
bool pk_arrayiter(py_Ref val); bool pk_arrayiter(py_Ref val);
bool pk_arraycontains(py_Ref self, py_Ref val); bool pk_arraycontains(py_Ref self, py_Ref val);
bool pk_pushmethod(py_StackRef self, py_Name name);
/// Assumes [a, b] are on the stack, performs a binary op. /// Assumes [a, b] are on the stack, performs a binary op.
/// The result is stored in `self->last_retval`. /// The result is stored in `self->last_retval`.
/// The stack remains unchanged. /// The stack remains unchanged.

View File

@ -178,17 +178,12 @@ bool py_deldict(py_Ref self, py_Name name);
py_ObjectRef py_getslot(py_Ref self, int i); py_ObjectRef py_getslot(py_Ref self, int i);
void py_setslot(py_Ref self, int i, py_Ref val); void py_setslot(py_Ref self, int i, py_Ref val);
py_TmpRef py_getupvalue(py_StackRef argv);
void py_setupvalue(py_StackRef argv, py_Ref val);
/// Gets the attribute of the object. /// Gets the attribute of the object.
bool py_getattr(py_Ref self, py_Name name); bool py_getattr(py_Ref self, py_Name name);
/// Sets the attribute of the object. /// Sets the attribute of the object.
bool py_setattr(py_Ref self, py_Name name, py_Ref val); bool py_setattr(py_Ref self, py_Name name, py_Ref val);
/// Deletes the attribute of the object. /// Deletes the attribute of the object.
bool py_delattr(py_Ref self, py_Name name); bool py_delattr(py_Ref self, py_Name name);
/// Gets the unbound method of the object.
bool py_getunboundmethod(py_Ref self, py_Name name, py_Ref out, py_Ref out_self);
bool py_getitem(py_Ref self, py_Ref key); bool py_getitem(py_Ref self, py_Ref key);
bool py_setitem(py_Ref self, py_Ref key, py_Ref val); bool py_setitem(py_Ref self, py_Ref key, py_Ref val);
@ -231,6 +226,11 @@ void py_pop();
void py_shrink(int n); void py_shrink(int n);
/// Get a temporary variable from the stack and returns the reference to it. /// Get a temporary variable from the stack and returns the reference to it.
py_StackRef py_pushtmp(); py_StackRef py_pushtmp();
/// Gets the unbound method of the object.
/// Assumes the object is located at the top of the stack.
/// If returns true: [self] -> [unbound, self]
/// If returns false: [self] -> [self] (no change)
bool py_pushmethod(py_Name name);
/************* Modules *************/ /************* Modules *************/
py_TmpRef py_newmodule(const char* name, const char* package); py_TmpRef py_newmodule(const char* name, const char* package);

View File

@ -251,12 +251,9 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
goto __ERROR; goto __ERROR;
} }
case OP_LOAD_METHOD: { case OP_LOAD_METHOD: {
// [self] // [self] -> [unbound, self]
bool ok = py_getunboundmethod(TOP(), byte.arg, TOP(), SP()); bool ok = py_pushmethod(byte.arg);
if(ok) { if(!ok) {
// [unbound, self]
SP()++;
} else {
// fallback to getattr // fallback to getattr
if(py_getattr(TOP(), byte.arg)) { if(py_getattr(TOP(), byte.arg)) {
py_assign(TOP(), py_retval()); py_assign(TOP(), py_retval());
@ -912,8 +909,8 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
pk_print_stack(self, frame, (Bytecode){}); pk_print_stack(self, frame, (Bytecode){});
py_BaseException__set_lineno(&self->curr_exception, Frame__lineno(frame), frame->co); py_BaseException__set_lineno(&self->curr_exception, Frame__lineno(frame), frame->co);
__ERROR_RE_RAISE: __ERROR_RE_RAISE:
do {} while(0);
printf("error.op: %s, line: %d\n", pk_opname(byte.op), Frame__lineno(frame)); //printf("error.op: %s, line: %d\n", pk_opname(byte.op), Frame__lineno(frame));
int lineno = py_BaseException__get_lineno(&self->curr_exception, frame->co); int lineno = py_BaseException__get_lineno(&self->curr_exception, frame->co);
py_BaseException__stpush(&self->curr_exception, py_BaseException__stpush(&self->curr_exception,
frame->co->src, frame->co->src,

View File

@ -478,7 +478,7 @@ pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t argc, uint16_t kwargc, bo
} }
// handle `__call__` overload // handle `__call__` overload
if(py_getunboundmethod(p0, __call__, p0, p0 + 1)) { if(pk_pushmethod(p0, __call__)) {
// [__call__, self, args..., kwargs...] // [__call__, self, args..., kwargs...]
return pk_VM__vectorcall(self, argc, kwargc, opcall); return pk_VM__vectorcall(self, argc, kwargc, opcall);
} }
@ -557,7 +557,7 @@ void pk_ManagedHeap__mark(pk_ManagedHeap* self) {
} }
void pk_print_stack(pk_VM* self, Frame* frame, Bytecode byte) { void pk_print_stack(pk_VM* self, Frame* frame, Bytecode byte) {
// return; return;
if(frame == NULL) return; if(frame == NULL) return;
py_TValue* sp = self->stack.sp; py_TValue* sp = self->stack.sp;

View File

@ -132,19 +132,17 @@ static bool _py_builtins__next(int argc, py_Ref argv) {
static bool _py_builtins__sorted(int argc, py_Ref argv) { static bool _py_builtins__sorted(int argc, py_Ref argv) {
PY_CHECK_ARGC(3); PY_CHECK_ARGC(3);
// convert _0 to list object // convert _0 to list object
if(!py_tpcall(tp_list, 1, argv)) return false; if(!py_tpcall(tp_list, 1, py_arg(0))) return false;
py_Ref retval = py_pushtmp(); py_push(py_retval()); // duptop
py_Ref sort = py_pushtmp(); py_push(py_retval()); // [| <list>]
py_Ref self = py_pushtmp(); bool ok = py_pushmethod(py_name("sort")); // [| list.sort, <list>]
py_Ref key = py_pushtmp();
py_Ref reverse = py_pushtmp();
*self = *retval = *py_retval();
bool ok = py_getunboundmethod(self, py_name("sort"), sort, self);
if(!ok) return false; if(!ok) return false;
*key = argv[1]; py_push(py_arg(1)); // [| list.sort, <list>, key]
*reverse = argv[2]; py_push(py_arg(2)); // [| list.sort, <list>, key, reverse]
if(!py_vectorcall(2, 0)) return false; ok = py_vectorcall(2, 0); // [| ]
*py_retval() = *retval; if(!ok) return false;
py_assign(py_retval(), py_peek(-1));
py_pop();
return true; return true;
} }

View File

@ -129,7 +129,7 @@ void py_printexc() {
char* py_formatexc() { char* py_formatexc() {
pk_VM* vm = pk_current_vm; pk_VM* vm = pk_current_vm;
if(py_isnil(&vm->curr_exception)) { return NULL; } if(py_isnil(&vm->curr_exception)) return NULL;
c11_sbuf ss; c11_sbuf ss;
c11_sbuf__ctor(&ss); c11_sbuf__ctor(&ss);

View File

@ -230,7 +230,11 @@ bool py_vectorcall(uint16_t argc, uint16_t kwargc) {
py_Ref py_retval() { return &pk_current_vm->last_retval; } py_Ref py_retval() { return &pk_current_vm->last_retval; }
bool py_getunboundmethod(py_Ref self, py_Name name, py_Ref out, py_Ref out_self) { bool py_pushmethod(py_Name name){
return pk_pushmethod(py_peek(-1), name);
}
bool pk_pushmethod(py_StackRef self, py_Name name) {
// NOTE: `out` and `out_self` may overlap with `self` // NOTE: `out` and `out_self` may overlap with `self`
py_Type type; py_Type type;
// handle super() proxy // handle super() proxy
@ -243,22 +247,23 @@ bool py_getunboundmethod(py_Ref self, py_Name name, py_Ref out, py_Ref out_self)
py_Ref cls_var = py_tpfindname(type, name); py_Ref cls_var = py_tpfindname(type, name);
if(cls_var != NULL) { if(cls_var != NULL) {
pk_current_vm->stack.sp++;
switch(cls_var->type) { switch(cls_var->type) {
case tp_function: case tp_function:
case tp_nativefunc: { case tp_nativefunc: {
py_TValue self_bak = *self; py_TValue self_bak = *self;
// `out` may overlap with `self`. If we assign `out`, `self` may be corrupted. // `out` may overlap with `self`. If we assign `out`, `self` may be corrupted.
*out = *cls_var; self[0] = *cls_var;
*out_self = self_bak; self[1] = self_bak;
break; break;
} }
case tp_staticmethod: case tp_staticmethod:
*out = *py_getslot(cls_var, 0); self[0] = *py_getslot(cls_var, 0);
py_newnil(out_self); self[1] = *py_NIL;
break; break;
case tp_classmethod: case tp_classmethod:
*out = *py_getslot(cls_var, 0); self[0] = *py_getslot(cls_var, 0);
*out_self = c11__getitem(pk_TypeInfo, &pk_current_vm->types, type).self; self[1] = c11__getitem(pk_TypeInfo, &pk_current_vm->types, type).self;
break; break;
default: c11__unreachedable(); default: c11__unreachedable();
} }