mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-21 12:00:18 +00:00
some fix
This commit is contained in:
parent
8ae999ecdf
commit
facd1c0ce6
@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "pocketpy/objects/codeobject.h"
|
||||||
#include "pocketpy/pocketpy.h"
|
#include "pocketpy/pocketpy.h"
|
||||||
#include "pocketpy/interpreter/gc.h"
|
#include "pocketpy/interpreter/gc.h"
|
||||||
#include "pocketpy/interpreter/frame.h"
|
#include "pocketpy/interpreter/frame.h"
|
||||||
@ -70,8 +71,6 @@ void pk_VM__dtor(pk_VM* self);
|
|||||||
void pk_VM__push_frame(pk_VM* self, Frame* frame);
|
void pk_VM__push_frame(pk_VM* self, Frame* frame);
|
||||||
void pk_VM__pop_frame(pk_VM* self);
|
void pk_VM__pop_frame(pk_VM* self);
|
||||||
|
|
||||||
void pk_VM__init_builtins(pk_VM* self);
|
|
||||||
|
|
||||||
typedef enum pk_FrameResult {
|
typedef enum pk_FrameResult {
|
||||||
RES_RETURN,
|
RES_RETURN,
|
||||||
RES_CALL,
|
RES_CALL,
|
||||||
@ -89,7 +88,10 @@ py_Type pk_VM__new_type(pk_VM* self,
|
|||||||
|
|
||||||
pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t argc, uint16_t kwargc, bool opcall);
|
pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t argc, uint16_t kwargc, bool opcall);
|
||||||
|
|
||||||
|
const char* pk_opname(Opcode op);
|
||||||
|
|
||||||
// type registration
|
// type registration
|
||||||
|
void pk_number__register();
|
||||||
py_Type pk_str__register();
|
py_Type pk_str__register();
|
||||||
py_Type pk_bytes__register();
|
py_Type pk_bytes__register();
|
||||||
py_Type pk_list__register();
|
py_Type pk_list__register();
|
||||||
|
@ -117,7 +117,7 @@ bool py_issubclass(py_Type derived, py_Type base);
|
|||||||
/************* References *************/
|
/************* References *************/
|
||||||
#define py_offset(p, i) (py_Ref)((char*)p + ((i) << 4))
|
#define py_offset(p, i) (py_Ref)((char*)p + ((i) << 4))
|
||||||
|
|
||||||
#define TypeError(x) false
|
#define TypeError(...) false
|
||||||
#define py_arg(i) py_offset(argv, i)
|
#define py_arg(i) py_offset(argv, i)
|
||||||
#define py_checkargc(n) \
|
#define py_checkargc(n) \
|
||||||
if(argc != n) return TypeError()
|
if(argc != n) return TypeError()
|
||||||
|
@ -89,6 +89,9 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
|||||||
__NEXT_STEP:
|
__NEXT_STEP:
|
||||||
byte = *frame->ip;
|
byte = *frame->ip;
|
||||||
|
|
||||||
|
// log
|
||||||
|
printf("byte.op: %s, line: %d\n", pk_opname(byte.op), Frame__lineno(frame));
|
||||||
|
|
||||||
switch((Opcode)byte.op) {
|
switch((Opcode)byte.op) {
|
||||||
case OP_NO_OP: DISPATCH();
|
case OP_NO_OP: DISPATCH();
|
||||||
/*****************************************/
|
/*****************************************/
|
||||||
@ -614,6 +617,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
|||||||
case OP_CALL: {
|
case OP_CALL: {
|
||||||
pk_ManagedHeap__collect_if_needed(&self->heap);
|
pk_ManagedHeap__collect_if_needed(&self->heap);
|
||||||
vectorcall_opcall(byte.arg & 0xFF, byte.arg >> 8);
|
vectorcall_opcall(byte.arg & 0xFF, byte.arg >> 8);
|
||||||
|
DISPATCH();
|
||||||
}
|
}
|
||||||
case OP_CALL_VARGS: {
|
case OP_CALL_VARGS: {
|
||||||
assert(false);
|
assert(false);
|
||||||
@ -667,7 +671,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
|||||||
__ERROR:
|
__ERROR:
|
||||||
// 1. Exception can be handled inside the current frame
|
// 1. Exception can be handled inside the current frame
|
||||||
// 2. Exception need to be propagated to the upper frame
|
// 2. Exception need to be propagated to the upper frame
|
||||||
printf("byte.op: %d, line: %d\n", byte.op, Frame__lineno(frame));
|
printf("error.op: %s, line: %d\n", pk_opname(byte.op), Frame__lineno(frame));
|
||||||
assert(false);
|
assert(false);
|
||||||
return RES_ERROR;
|
return RES_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -342,7 +342,7 @@ static bool _py_float__new__(int argc, py_Ref argv) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pk_VM__init_builtins(pk_VM* self) {
|
void pk_number__register() {
|
||||||
/****** tp_int & tp_float ******/
|
/****** tp_int & tp_float ******/
|
||||||
py_bindmagic(tp_int, __add__, _py_int__add__);
|
py_bindmagic(tp_int, __add__, _py_int__add__);
|
||||||
py_bindmagic(tp_float, __add__, _py_float__add__);
|
py_bindmagic(tp_float, __add__, _py_float__add__);
|
||||||
|
@ -41,6 +41,7 @@ void pk_TypeInfo__ctor(pk_TypeInfo* self,
|
|||||||
// create type object with __dict__
|
// create type object with __dict__
|
||||||
pk_ManagedHeap* heap = &pk_current_vm->heap;
|
pk_ManagedHeap* heap = &pk_current_vm->heap;
|
||||||
PyObject* typeobj = pk_ManagedHeap__new(heap, tp_type, -1, sizeof(py_Type));
|
PyObject* typeobj = pk_ManagedHeap__new(heap, tp_type, -1, sizeof(py_Type));
|
||||||
|
*(py_Type*)PyObject__userdata(typeobj) = index;
|
||||||
self->self = (py_TValue){
|
self->self = (py_TValue){
|
||||||
.type = typeobj->type,
|
.type = typeobj->type,
|
||||||
.is_ptr = true,
|
.is_ptr = true,
|
||||||
@ -55,6 +56,13 @@ void pk_TypeInfo__ctor(pk_TypeInfo* self,
|
|||||||
|
|
||||||
void pk_TypeInfo__dtor(pk_TypeInfo* self) { c11_vector__dtor(&self->annotated_fields); }
|
void pk_TypeInfo__dtor(pk_TypeInfo* self) { c11_vector__dtor(&self->annotated_fields); }
|
||||||
|
|
||||||
|
static bool _py_object__new__(int argc, py_Ref argv) {
|
||||||
|
assert(argc >= 1);
|
||||||
|
py_Type cls = argv[0].type;
|
||||||
|
py_newobject(py_retval(), cls, 0, 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void pk_VM__ctor(pk_VM* self) {
|
void pk_VM__ctor(pk_VM* self) {
|
||||||
self->top_frame = NULL;
|
self->top_frame = NULL;
|
||||||
|
|
||||||
@ -158,7 +166,10 @@ void pk_VM__ctor(pk_VM* self) {
|
|||||||
py_setdict(&self->builtins, py_name("NotImplemented"), &tmp);
|
py_setdict(&self->builtins, py_name("NotImplemented"), &tmp);
|
||||||
|
|
||||||
/* Do Buildin Bindings*/
|
/* Do Buildin Bindings*/
|
||||||
pk_VM__init_builtins(self);
|
pk_number__register();
|
||||||
|
// object.__new__
|
||||||
|
py_bindmagic(tp_object, __new__, _py_object__new__);
|
||||||
|
|
||||||
self->main = *py_newmodule("__main__", NULL);
|
self->main = *py_newmodule("__main__", NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,7 +312,8 @@ pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t ARGC, uint16_t KWARGC, bo
|
|||||||
// if(f.argc != -1) {
|
// if(f.argc != -1) {
|
||||||
// if(KWARGC != 0)
|
// if(KWARGC != 0)
|
||||||
// TypeError(
|
// TypeError(
|
||||||
// "old-style native_func does not accept keyword arguments. If you want to skip this check, specify `argc` to -1");
|
// "old-style native_func does not accept keyword arguments. If you want to
|
||||||
|
// skip this check, specify `argc` to -1");
|
||||||
// if(args.size() != f.argc) {
|
// if(args.size() != f.argc) {
|
||||||
// vm->TypeError(_S("expected ", f.argc, " arguments, got ", args.size()));
|
// vm->TypeError(_S("expected ", f.argc, " arguments, got ", args.size()));
|
||||||
// }
|
// }
|
||||||
@ -314,58 +326,52 @@ pk_FrameResult pk_VM__vectorcall(pk_VM* self, uint16_t ARGC, uint16_t KWARGC, bo
|
|||||||
return RES_RETURN;
|
return RES_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
if(p0->type == tp_type) {
|
if(p0->type == tp_type) {
|
||||||
// [type, NULL, args..., kwargs...]
|
// [cls, NULL, args..., kwargs...]
|
||||||
PyVar new_f = *find_name_in_mro(PK_OBJ_GET(Type, callable), __new__);
|
py_Ref new_f = py_tpfindmagic(py_totype(p0), __new__);
|
||||||
PyVar obj;
|
assert(new_f && py_isnull(p0 + 1));
|
||||||
assert(new_f && (!p0[1]));
|
|
||||||
if(PyVar__IS_OP(&new_f, &__cached_object_new)) {
|
|
||||||
// fast path for object.__new__
|
|
||||||
obj = vm->new_object<DummyInstance>(PK_OBJ_GET(Type, callable));
|
|
||||||
} else {
|
|
||||||
PUSH(new_f);
|
|
||||||
PUSH(PY_NULL);
|
|
||||||
PUSH(callable); // cls
|
|
||||||
for(PyVar o: args)
|
|
||||||
PUSH(o);
|
|
||||||
for(PyVar o: kwargs)
|
|
||||||
PUSH(o);
|
|
||||||
// if obj is not an instance of `cls`, the behavior is undefined
|
|
||||||
obj = vectorcall(ARGC + 1, KWARGC);
|
|
||||||
}
|
|
||||||
|
|
||||||
// __init__
|
// prepare a copy of args and kwargs
|
||||||
PyVar self;
|
int span = self->stack.sp - argv;
|
||||||
callable = get_unbound_method(obj, __init__, &self, false);
|
*self->stack.sp++ = *new_f; // push __new__
|
||||||
if(callable) {
|
*self->stack.sp++ = *p0; // push cls
|
||||||
callable_t = _tp(callable);
|
memcpy(self->stack.sp, argv, span * sizeof(py_TValue));
|
||||||
// replace `NULL` with `self`
|
self->stack.sp += span;
|
||||||
p1[-(ARGC + 2)] = callable;
|
|
||||||
p1[-(ARGC + 1)] = self;
|
// [new_f, cls, args..., kwargs...]
|
||||||
// [init_f, self, args..., kwargs...]
|
pk_FrameResult res = pk_VM__vectorcall(self, ARGC, KWARGC, false);
|
||||||
vectorcall(ARGC, KWARGC);
|
if(res == RES_ERROR) return RES_ERROR;
|
||||||
// We just discard the return value of `__init__`
|
assert(res == RES_RETURN);
|
||||||
// in cpython it raises a TypeError if the return value is not None
|
// by recursively using vectorcall, args and kwargs are consumed
|
||||||
|
// [cls, NULL, args..., kwargs...]
|
||||||
|
|
||||||
|
// try __init__
|
||||||
|
// NOTE: previous we use `get_unbound_method` but here we just use `tpfindmagic`
|
||||||
|
py_Ref init_f = py_tpfindmagic(py_totype(p0), __init__);
|
||||||
|
if(init_f) {
|
||||||
|
// do an inplace patch
|
||||||
|
*p0 = *init_f; // __init__
|
||||||
|
p0[1] = self->last_retval; // self
|
||||||
|
// [__init__, self, args..., kwargs...]
|
||||||
|
pk_FrameResult res = pk_VM__vectorcall(self, ARGC, KWARGC, false);
|
||||||
|
if(res == RES_ERROR) return RES_ERROR;
|
||||||
|
assert(res == RES_RETURN);
|
||||||
} else {
|
} else {
|
||||||
// manually reset the stack
|
// manually reset the stack
|
||||||
s_data.reset(p0);
|
self->stack.sp = p0;
|
||||||
}
|
}
|
||||||
return obj;
|
return RES_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle `__call__` overload
|
// handle `__call__` overload
|
||||||
PyVar self;
|
if(py_getunboundmethod(p0, __call__, false, p0, p0 + 1)) {
|
||||||
PyVar call_f = get_unbound_method(callable, __call__, &self, false);
|
// [__call__, self, args..., kwargs...]
|
||||||
if(self) {
|
pk_FrameResult res = pk_VM__vectorcall(self, ARGC, KWARGC, false);
|
||||||
p1[-(ARGC + 2)] = call_f;
|
if(res == RES_ERROR) return RES_ERROR;
|
||||||
p1[-(ARGC + 1)] = self;
|
assert(res == RES_RETURN);
|
||||||
// [call_f, self, args..., kwargs...]
|
|
||||||
return vectorcall(ARGC, KWARGC, op_call);
|
|
||||||
}
|
}
|
||||||
TypeError(_type_name(vm, callable_t).escape() + " object is not callable");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
TypeError("'%t' object is not callable", p0->type);
|
||||||
PK_UNREACHABLE();
|
PK_UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#include "pocketpy/objects/codeobject.h"
|
||||||
#include "pocketpy/objects/sourcedata.h"
|
#include "pocketpy/objects/sourcedata.h"
|
||||||
#include "pocketpy/pocketpy.h"
|
#include "pocketpy/pocketpy.h"
|
||||||
|
|
||||||
@ -25,13 +26,16 @@ void py_finalize() {
|
|||||||
pk_MemoryPools__finalize();
|
pk_MemoryPools__finalize();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void disassemble(CodeObject* co) {
|
const char* pk_opname(Opcode op){
|
||||||
const static char* OP_NAMES[] = {
|
const static char* OP_NAMES[] = {
|
||||||
#define OPCODE(name) #name,
|
#define OPCODE(name) #name,
|
||||||
#include "pocketpy/xmacros/opcodes.h"
|
#include "pocketpy/xmacros/opcodes.h"
|
||||||
#undef OPCODE
|
#undef OPCODE
|
||||||
};
|
};
|
||||||
|
return OP_NAMES[op];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void disassemble(CodeObject* co) {
|
||||||
c11_vector /*T=int*/ jumpTargets;
|
c11_vector /*T=int*/ jumpTargets;
|
||||||
c11_vector__ctor(&jumpTargets, sizeof(int));
|
c11_vector__ctor(&jumpTargets, sizeof(int));
|
||||||
for(int i = 0; i < co->codes.count; i++) {
|
for(int i = 0; i < co->codes.count; i++) {
|
||||||
@ -71,9 +75,9 @@ static void disassemble(CodeObject* co) {
|
|||||||
snprintf(buf, sizeof(buf), "%-8s%-3s%-3d ", line, pointer, i);
|
snprintf(buf, sizeof(buf), "%-8s%-3s%-3d ", line, pointer, i);
|
||||||
c11_sbuf__write_cstr(&ss, buf);
|
c11_sbuf__write_cstr(&ss, buf);
|
||||||
|
|
||||||
c11_sbuf__write_cstr(&ss, OP_NAMES[byte.op]);
|
c11_sbuf__write_cstr(&ss, pk_opname(byte.op));
|
||||||
c11_sbuf__write_char(&ss, ex.is_virtual ? '*' : ' ');
|
c11_sbuf__write_char(&ss, ex.is_virtual ? '*' : ' ');
|
||||||
int padding = 24 - strlen(OP_NAMES[byte.op]);
|
int padding = 24 - strlen(pk_opname(byte.op));
|
||||||
for(int j = 0; j < padding; j++)
|
for(int j = 0; j < padding; j++)
|
||||||
c11_sbuf__write_char(&ss, ' ');
|
c11_sbuf__write_char(&ss, ' ');
|
||||||
|
|
||||||
@ -196,7 +200,7 @@ bool py_getunboundmethod(const py_Ref self,
|
|||||||
bool fallback,
|
bool fallback,
|
||||||
py_Ref out,
|
py_Ref out,
|
||||||
py_Ref out_self) {
|
py_Ref out_self) {
|
||||||
return -1;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pk_TypeInfo* pk_tpinfo(const py_Ref self) {
|
pk_TypeInfo* pk_tpinfo(const py_Ref self) {
|
||||||
@ -205,6 +209,7 @@ pk_TypeInfo* pk_tpinfo(const py_Ref self) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
py_Ref py_tpfindmagic(py_Type t, py_Name name) {
|
py_Ref py_tpfindmagic(py_Type t, py_Name name) {
|
||||||
|
assert(t);
|
||||||
assert(py_ismagicname(name));
|
assert(py_ismagicname(name));
|
||||||
pk_TypeInfo* types = (pk_TypeInfo*)pk_current_vm->types.data;
|
pk_TypeInfo* types = (pk_TypeInfo*)pk_current_vm->types.data;
|
||||||
do {
|
do {
|
||||||
|
104
tests/00_tmp.py
Normal file
104
tests/00_tmp.py
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
# test int literals
|
||||||
|
assert 0xffff == 65535
|
||||||
|
assert 0xAAFFFF == 11206655
|
||||||
|
assert 0x7fffffff == 2147483647
|
||||||
|
assert -0xffff == -65535
|
||||||
|
assert -0xAAFFFF == -11206655
|
||||||
|
assert -0x7fffffff == -2147483647
|
||||||
|
# test 64-bit
|
||||||
|
assert 2**60-1 + 546 - 0xfffffffffffff == 1148417904979477026
|
||||||
|
|
||||||
|
# test oct literals
|
||||||
|
assert 0o1234 == 668
|
||||||
|
assert 0o17777777777 == 2147483647
|
||||||
|
assert -0o1234 == -668
|
||||||
|
assert -0o17777777777 == -2147483647
|
||||||
|
|
||||||
|
# test binary literals
|
||||||
|
assert 0b10010 == 18
|
||||||
|
assert -0b10010 == -18
|
||||||
|
assert 0b11111111111111111111111111111111 == 4294967295
|
||||||
|
assert -0b11111 == -31
|
||||||
|
|
||||||
|
# test == != >= <= < >
|
||||||
|
assert -1 == -1
|
||||||
|
assert -1 != 1
|
||||||
|
assert -1 >= -1
|
||||||
|
assert -1 <= -1
|
||||||
|
assert -1 < 1
|
||||||
|
assert -1 > -2
|
||||||
|
|
||||||
|
# test + - * % ** //
|
||||||
|
assert -1 + 1 == 0
|
||||||
|
assert -1 - 1 == -2
|
||||||
|
assert 4 * -1 == -4
|
||||||
|
assert 5 % 2 == 1
|
||||||
|
assert 2 ** 3 == 8
|
||||||
|
assert 4 // 2 == 2
|
||||||
|
assert 5 // 2 == 2
|
||||||
|
|
||||||
|
# test += -= *= //=
|
||||||
|
x = 3
|
||||||
|
x += 1
|
||||||
|
assert x == 4
|
||||||
|
x -= 1
|
||||||
|
assert x == 3
|
||||||
|
x *= 2
|
||||||
|
assert x == 6
|
||||||
|
x //= 2
|
||||||
|
assert x == 3
|
||||||
|
|
||||||
|
# test bit_length
|
||||||
|
assert (1).bit_length() == 1
|
||||||
|
assert (2).bit_length() == 2
|
||||||
|
assert (3).bit_length() == 2
|
||||||
|
|
||||||
|
assert (-1).bit_length() == 1
|
||||||
|
assert (-2).bit_length() == 2
|
||||||
|
assert (-3).bit_length() == 2
|
||||||
|
|
||||||
|
assert (123123123123123).bit_length() == 47
|
||||||
|
assert (-3123123123).bit_length() == 32
|
||||||
|
|
||||||
|
# test int()
|
||||||
|
assert int() == 0
|
||||||
|
assert int(True) == 1
|
||||||
|
assert int(False) == 0
|
||||||
|
|
||||||
|
assert int(1) == 1
|
||||||
|
assert int(1.0) == 1
|
||||||
|
assert int(1.1) == 1
|
||||||
|
assert int(1.9) == 1
|
||||||
|
assert int(-1.9) == -1
|
||||||
|
assert int(1.5) == 1
|
||||||
|
assert int(-1.5) == -1
|
||||||
|
assert int("123") == 123
|
||||||
|
|
||||||
|
assert int("0x123", 16) == 291
|
||||||
|
assert int("0o123", 8) == 83
|
||||||
|
assert int("-0x123", 16) == -291
|
||||||
|
assert int("-0o123", 8) == -83
|
||||||
|
assert int("-123") == -123
|
||||||
|
assert int("+123") == 123
|
||||||
|
|
||||||
|
# test >> << & | ^
|
||||||
|
assert 12 >> 1 == 6
|
||||||
|
assert 12 << 1 == 24
|
||||||
|
assert 12 & 1 == 0
|
||||||
|
assert 12 | 1 == 13
|
||||||
|
assert 12 ^ 1 == 13
|
||||||
|
|
||||||
|
# test high precision int pow
|
||||||
|
assert 7**21 == 558545864083284007
|
||||||
|
assert 2**60 == 1152921504606846976
|
||||||
|
assert -2**60 == -1152921504606846976
|
||||||
|
assert 4**13 == 67108864
|
||||||
|
assert (-4)**13 == -67108864
|
||||||
|
|
||||||
|
assert ~3 == -4
|
||||||
|
assert ~-3 == 2
|
||||||
|
assert ~0 == -1
|
||||||
|
|
||||||
|
# test __str__, __repr__
|
||||||
|
assert str(1) == '1'
|
||||||
|
assert repr(1) == '1'
|
@ -48,10 +48,6 @@ assert x == 6
|
|||||||
x //= 2
|
x //= 2
|
||||||
assert x == 3
|
assert x == 3
|
||||||
|
|
||||||
# test __str__, __repr__
|
|
||||||
assert str(1) == '1'
|
|
||||||
assert repr(1) == '1'
|
|
||||||
|
|
||||||
# test bit_length
|
# test bit_length
|
||||||
assert (1).bit_length() == 1
|
assert (1).bit_length() == 1
|
||||||
assert (2).bit_length() == 2
|
assert (2).bit_length() == 2
|
||||||
@ -103,6 +99,10 @@ assert ~3 == -4
|
|||||||
assert ~-3 == 2
|
assert ~-3 == 2
|
||||||
assert ~0 == -1
|
assert ~0 == -1
|
||||||
|
|
||||||
|
# test __str__, __repr__
|
||||||
|
assert str(1) == '1'
|
||||||
|
assert repr(1) == '1'
|
||||||
|
|
||||||
try:
|
try:
|
||||||
1 // 0
|
1 // 0
|
||||||
exit(1)
|
exit(1)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user