mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 11:30:18 +00:00
...
This commit is contained in:
parent
db0acc854c
commit
67ae21d18d
20
build.sh
20
build.sh
@ -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."
|
||||||
|
@ -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.
|
||||||
|
@ -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);
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user