Compare commits

...

7 Commits

Author SHA1 Message Date
blueloveTH
87bf0c9e7c ... 2024-08-09 13:40:02 +08:00
blueloveTH
a96173fd6a ... 2024-08-09 13:11:56 +08:00
blueloveTH
d8f2808462 ... 2024-08-09 12:54:29 +08:00
blueloveTH
3e99f46273 fix gc issues 2024-08-09 12:28:20 +08:00
blueloveTH
3caca62f2c ... 2024-08-09 11:46:10 +08:00
blueloveTH
2eb3eabcc2 add json module 2024-08-09 11:40:20 +08:00
blueloveTH
3fbbd9fb67 ... 2024-08-09 11:04:30 +08:00
23 changed files with 336 additions and 118 deletions

View File

@ -64,3 +64,5 @@ int Frame__exit_block(Frame* self, ValueStack*, int);
UnwindTarget* Frame__find_unwind_target(Frame* self, int iblock);
void Frame__set_unwind_target(Frame* self, py_TValue* sp);
void Frame__gc_mark(Frame* self);

View File

@ -5,3 +5,5 @@ void pk__add_module_os();
void pk__add_module_math();
void pk__add_module_dis();
void pk__add_module_random();
void pk__add_module_json();
void pk__add_module_gc();

View File

@ -21,6 +21,7 @@ typedef struct py_TypeInfo {
c11_vector /*T=py_Name*/ annotated_fields;
void (*on_end_subclass)(struct py_TypeInfo*); // backdoor for enum module
void (*gc_mark)(void* ud);
/* Magic Slots */
py_TValue magic[64];
@ -61,8 +62,9 @@ void VM__pop_frame(VM* self);
bool pk__parse_int_slice(py_Ref slice, int length, int* start, int* stop, int* step);
bool pk__normalize_index(int* index, int length);
void pk_list__mark(void* ud, void (*marker)(py_TValue*));
void pk_dict__mark(void* ud, void (*marker)(py_TValue*));
void pk__mark_value(py_TValue*);
void pk__mark_namedict(NameDict*);
void pk__tp_set_marker(py_Type type, void (*gc_mark)(void*));
bool pk_wrapper__self(int argc, py_Ref argv);
bool pk_wrapper__NotImplementedError(int argc, py_Ref argv);

View File

@ -209,15 +209,16 @@ py_GlobalRef py_tpfindmagic(py_Type, py_Name name);
/// Search the name from the given type to the base type.
/// Return `NULL` if not found.
py_GlobalRef py_tpfindname(py_Type, py_Name name);
/// Get the magic method from the given type only.
/// The returned reference is always valid. However, its value may be `nil`.
py_GlobalRef py_tpgetmagic(py_Type type, py_Name name);
/// Get the type object of the given type.
py_GlobalRef py_tpobject(py_Type type);
/// Get the type name.
const char* py_tpname(py_Type type);
/// Call a type to create a new instance.
bool py_tpcall(py_Type type, int argc, py_Ref argv) PY_RAISE;
/// Get the magic method from the given type only.
/// The returned reference is always valid. However, its value may be `nil`.
py_GlobalRef py_tpmagic(py_Type type, py_Name name);
/// Check if the object is an instance of the given type.
/// Raise `TypeError` if the check fails.
@ -287,7 +288,7 @@ void py_bindfunc(py_Ref obj, const char* name, py_CFunction f);
/// @param setter setter function. Use `NULL` if not needed.
void py_bindproperty(py_Type type, const char* name, py_CFunction getter, py_CFunction setter);
#define py_bindmagic(type, __magic__, f) py_newnativefunc(py_tpmagic((type), __magic__), (f))
#define py_bindmagic(type, __magic__, f) py_newnativefunc(py_tpgetmagic((type), __magic__), (f))
#define PY_CHECK_ARGC(n) \
if(argc != n) return TypeError("expected %d arguments, got %d", n, argc)
@ -454,6 +455,8 @@ bool py_str(py_Ref val) PY_RAISE;
bool py_repr(py_Ref val) PY_RAISE;
/// Python equivalent to `len(val)`.
bool py_len(py_Ref val) PY_RAISE;
/// Python equivalent to `json.dumps(val)`.
bool py_json(py_Ref val) PY_RAISE;
/************* Unchecked Functions *************/

View File

@ -1,5 +1,4 @@
import json
from c import struct
import builtins
_BASIC_TYPES = [int, float, str, bool, type(None)]
@ -142,7 +141,8 @@ class _Unpickler:
# generic object
cls = _find_class(o[0])
if getattr(cls, '__struct__', False):
# if getattr(cls, '__struct__', False):
if False:
inst = cls.fromstruct(struct.fromhex(o[1]))
self.tag(index, inst)
return inst

File diff suppressed because one or more lines are too long

View File

@ -909,6 +909,13 @@ FrameResult VM__run_top_frame(VM* self) {
base = py_totype(TOP());
}
POP();
py_TypeInfo* base_ti = c11__at(py_TypeInfo, &self->types, base);
if(base_ti->is_sealed){
TypeError("type '%t' is not an acceptable base type", base);
goto __ERROR;
}
py_Type type =
pk_newtype(py_name2str(name), base, frame->module, NULL, true, false);
PUSH(py_tpobject(type));
@ -1027,7 +1034,7 @@ FrameResult VM__run_top_frame(VM* self) {
py_TValue* tmp = c11__at(py_TValue, &frame->co->consts, byte.arg);
const char* string = py_tostr(tmp);
// TODO: optimize this
if(!py_exec(string, "<eval>", EVAL_MODE, frame->module)) goto __ERROR;
if(!py_exec(string, "<f-string>", EVAL_MODE, frame->module)) goto __ERROR;
PUSH(py_retval());
DISPATCH();
}

View File

@ -1,4 +1,5 @@
#include "pocketpy/interpreter/frame.h"
#include "pocketpy/interpreter/vm.h"
#include "pocketpy/objects/codeobject.h"
#include "pocketpy/objects/object.h"
#include "pocketpy/pocketpy.h"
@ -133,6 +134,11 @@ void Frame__set_unwind_target(Frame* self, py_TValue* sp) {
}
}
void Frame__gc_mark(Frame *self){
pk__mark_value(self->module);
CodeObject__gc_mark(self->co);
}
py_TValue* Frame__f_closure_try_get(Frame* self, py_Name name) {
if(!self->has_function) return NULL;
Function* ud = py_touserdata(self->p0);

View File

@ -71,9 +71,16 @@ static bool generator__next__(int argc, py_Ref argv) {
}
}
static void generator__gc_mark(void* ud){
Generator* gen = ud;
if(gen->frame) Frame__gc_mark(gen->frame);
}
py_Type pk_generator__register() {
py_Type type = pk_newtype("generator", tp_object, NULL, (py_Dtor)Generator__dtor, false, true);
pk__tp_set_marker(type, generator__gc_mark);
py_bindmagic(type, __iter__, pk_wrapper__self);
py_bindmagic(type, __next__, generator__next__);
return type;

View File

@ -197,6 +197,8 @@ void VM__ctor(VM* self) {
pk__add_module_math();
pk__add_module_dis();
pk__add_module_random();
pk__add_module_json();
pk__add_module_gc();
// add python builtins
do {
@ -311,8 +313,12 @@ py_Type pk_newtype(const char* name,
c11_vector* types = &pk_current_vm->types;
py_Type index = types->count;
py_TypeInfo* ti = c11_vector__emplace(types);
py_TypeInfo* base_ti = base ? c11__at(py_TypeInfo, types, base) : NULL;
if(base_ti && base_ti->is_sealed){
c11__abort("type '%s' is not an acceptable base type", py_name2str(base_ti->name));
}
py_TypeInfo__ctor(ti, py_name(name), index, base, module ? *module : *py_NIL);
if(!dtor && base) { dtor = c11__at(py_TypeInfo, types, base)->dtor; }
if(!dtor && base) dtor = base_ti->dtor;
ti->dtor = dtor;
ti->is_python = is_python;
ti->is_sealed = is_sealed;
@ -533,10 +539,23 @@ void PyObject__delete(PyObject* self) {
static void mark_object(PyObject* obj);
static void mark_value(py_TValue* val) {
void pk__mark_value(py_TValue* val) {
if(val->is_ptr) mark_object(val->_obj);
}
void pk__mark_namedict(NameDict* dict) {
for(int i = 0; i < dict->count; i++) {
NameDict_KV* kv = c11__at(NameDict_KV, dict, i);
pk__mark_value(&kv->value);
}
}
void pk__tp_set_marker(py_Type type, void (*gc_mark)(void*)) {
py_TypeInfo* ti = c11__at(py_TypeInfo, &pk_current_vm->types, type);
assert(ti->gc_mark == NULL);
ti->gc_mark = gc_mark;
}
static void mark_object(PyObject* obj) {
if(obj->gc_marked) return;
obj->gc_marked = true;
@ -544,24 +563,19 @@ static void mark_object(PyObject* obj) {
if(obj->slots > 0) {
py_TValue* p = PyObject__slots(obj);
for(int i = 0; i < obj->slots; i++)
mark_value(p + i);
return;
}
if(obj->slots == -1) {
pk__mark_value(p + i);
} else if(obj->slots == -1) {
NameDict* dict = PyObject__dict(obj);
for(int j = 0; j < dict->count; j++) {
NameDict_KV* kv = c11__at(NameDict_KV, dict, j);
mark_value(&kv->value);
}
return;
pk__mark_namedict(dict);
}
if(obj->type == tp_list) {
pk_list__mark(PyObject__userdata(obj), mark_value);
} else if(obj->type == tp_dict) {
pk_dict__mark(PyObject__userdata(obj), mark_value);
}
py_TypeInfo* types = c11__at(py_TypeInfo, &pk_current_vm->types, obj->type);
if(types->gc_mark) { types->gc_mark(PyObject__userdata(obj)); }
}
void CodeObject__gc_mark(const CodeObject* self) {
c11__foreach(py_TValue, &self->consts, i) { pk__mark_value(i); }
c11__foreach(FuncDecl_, &self->func_decls, i) { CodeObject__gc_mark(&(*i)->code); }
}
void ManagedHeap__mark(ManagedHeap* self) {
@ -573,17 +587,17 @@ void ManagedHeap__mark(ManagedHeap* self) {
}
// mark value stack
for(py_TValue* p = vm->stack.begin; p != vm->stack.end; p++) {
mark_value(p);
pk__mark_value(p);
}
// mark frame
for(Frame* frame = vm->top_frame; frame; frame = frame->f_back) {
mark_value(frame->module);
Frame__gc_mark(frame);
}
// mark vm's registers
mark_value(&vm->last_retval);
mark_value(&vm->curr_exception);
pk__mark_value(&vm->last_retval);
pk__mark_value(&vm->curr_exception);
for(int i = 0; i < c11__count_array(vm->reg); i++) {
mark_value(&vm->reg[i]);
pk__mark_value(&vm->reg[i]);
}
}

19
src/modules/gc.c Normal file
View File

@ -0,0 +1,19 @@
#include "pocketpy/pocketpy.h"
#include "pocketpy/common/utils.h"
#include "pocketpy/objects/object.h"
#include "pocketpy/common/sstream.h"
#include "pocketpy/interpreter/vm.h"
static bool gc_collect(int argc, py_Ref argv){
ManagedHeap* heap = &pk_current_vm->heap;
int res = ManagedHeap__collect(heap);
py_newint(py_retval(), res);
return true;
}
void pk__add_module_gc() {
py_Ref mod = py_newmodule("gc");
py_bindfunc(mod, "collect", gc_collect);
}

111
src/modules/json.c Normal file
View File

@ -0,0 +1,111 @@
#include "pocketpy/pocketpy.h"
#include "pocketpy/common/utils.h"
#include "pocketpy/objects/object.h"
#include "pocketpy/common/sstream.h"
#include "pocketpy/interpreter/vm.h"
#include <math.h>
static bool json_loads(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
PY_CHECK_ARG_TYPE(0, tp_str);
const char* source = py_tostr(argv);
py_TmpRef mod = py_getmodule("json");
return py_exec(source, "<json>", EVAL_MODE, mod);
}
static bool json_dumps(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
return py_json(argv);
}
void pk__add_module_json() {
py_Ref mod = py_newmodule("json");
py_setdict(mod, py_name("null"), py_None);
py_setdict(mod, py_name("true"), py_True);
py_setdict(mod, py_name("false"), py_False);
py_bindfunc(mod, "loads", json_loads);
py_bindfunc(mod, "dumps", json_dumps);
}
static bool json__write_object(c11_sbuf* buf, py_TValue* obj);
static bool json__write_array(c11_sbuf* buf, py_TValue* arr, int length) {
c11_sbuf__write_char(buf, '[');
for(int i = 0; i < length; i++) {
if(i != 0) c11_sbuf__write_cstr(buf, ", ");
bool ok = json__write_object(buf, arr + i);
if(!ok) return false;
}
c11_sbuf__write_char(buf, ']');
return true;
}
typedef struct {
c11_sbuf* buf;
bool first;
} json__write_dict_kv_ctx;
static bool json__write_dict_kv(py_Ref k, py_Ref v, void* ctx_) {
json__write_dict_kv_ctx* ctx = ctx_;
if(!ctx->first) c11_sbuf__write_cstr(ctx->buf, ", ");
ctx->first = false;
if(!py_isstr(k)) return TypeError("keys must be strings");
c11_sbuf__write_quoted(ctx->buf, py_tosv(k), '"');
c11_sbuf__write_char(ctx->buf, ':');
return json__write_object(ctx->buf, v);
}
static bool json__write_object(c11_sbuf* buf, py_TValue* obj) {
switch(obj->type) {
case tp_NoneType: c11_sbuf__write_cstr(buf, "null"); return true;
case tp_int: c11_sbuf__write_int(buf, obj->_i64); return true;
case tp_float: {
if(isnan(obj->_f64)) {
c11_sbuf__write_cstr(buf, "NaN");
} else if(isinf(obj->_f64)) {
c11_sbuf__write_cstr(buf, obj->_f64 < 0 ? "-Infinity" : "Infinity");
} else {
c11_sbuf__write_f64(buf, obj->_f64, -1);
}
return true;
}
case tp_bool: {
c11_sbuf__write_cstr(buf, py_tobool(obj) ? "true" : "false");
return true;
}
case tp_str: {
c11_sbuf__write_quoted(buf, py_tosv(obj), '"');
return true;
}
case tp_list: {
return json__write_array(buf, py_list_data(obj), py_list_len(obj));
}
case tp_tuple: {
return json__write_array(buf, py_tuple_data(obj), py_tuple_len(obj));
}
case tp_dict: {
c11_sbuf__write_char(buf, '{');
json__write_dict_kv_ctx ctx = {.buf = buf, .first = true};
bool ok = py_dict_apply(obj, json__write_dict_kv, &ctx);
if(!ok) return false;
c11_sbuf__write_char(buf, '}');
return true;
}
default: return TypeError("'%t' object is not JSON serializable", obj->type);
}
}
bool py_json(py_Ref val) {
c11_sbuf buf;
c11_sbuf__ctor(&buf);
bool ok = json__write_object(&buf, val);
if(!ok){
c11_sbuf__dtor(&buf);
return false;
}
c11_sbuf__py_submit(&buf, py_retval());
return true;
}

View File

@ -5,7 +5,7 @@
#include "pocketpy/common/sstream.h"
#include "pocketpy/interpreter/vm.h"
static bool _py_pkpy__next(int argc, py_Ref argv) {
static bool pkpy_next(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
int res = py_next(argv);
if(res == -1) return false;
@ -17,5 +17,5 @@ static bool _py_pkpy__next(int argc, py_Ref argv) {
void pk__add_module_pkpy() {
py_Ref mod = py_newmodule("pkpy");
py_bindfunc(mod, "next", _py_pkpy__next);
py_bindfunc(mod, "next", pkpy_next);
}

View File

@ -1,5 +1,6 @@
#include "pocketpy/objects/codeobject.h"
#include "pocketpy/common/utils.h"
#include "pocketpy/pocketpy.h"
#include <stdint.h>
void Bytecode__set_signed_arg(Bytecode* self, int arg) {

74
src/public/exec.c Normal file
View File

@ -0,0 +1,74 @@
#include "pocketpy/objects/codeobject.h"
#include "pocketpy/objects/sourcedata.h"
#include "pocketpy/pocketpy.h"
#include "pocketpy/common/utils.h"
#include "pocketpy/common/sstream.h"
#include "pocketpy/objects/object.h"
#include "pocketpy/interpreter/vm.h"
#include "pocketpy/compiler/compiler.h"
typedef struct {
const char* source;
const char* filename;
int mode;
int is_dynamic;
} py_ExecKey;
static int py_ExecKey__cmp(const py_ExecKey* a, const py_ExecKey* b) {
return memcmp(a, b, sizeof(py_ExecKey));
}
static void py_ExecKey__ctor(py_ExecKey* key, const char* source, const char* filename,
enum py_CompileMode mode, bool is_dynamic) {
key->source = source;
key->filename = filename;
key->mode = mode;
key->is_dynamic = is_dynamic;
}
static bool _py_exec(const char* source,
const char* filename,
enum py_CompileMode mode,
py_Ref module,
bool is_dynamic) {
VM* vm = pk_current_vm;
// py_ExecKey cache_key;
// py_ExecKey__ctor(&cache_key, source, filename, mode, is_dynamic);
CodeObject co;
SourceData_ src = SourceData__rcnew(source, filename, mode, is_dynamic);
Error* err = pk_compile(src, &co);
if(err) {
py_exception(tp_SyntaxError, err->msg);
py_BaseException__stpush(&vm->curr_exception, src, err->lineno, NULL);
PK_DECREF(src);
free(err);
return false;
}
if(!module) module = &vm->main;
py_StackRef sp = vm->stack.sp;
if(is_dynamic) {
// [globals, locals]
sp -= 2;
}
Frame* frame = Frame__new(&co, module, sp, sp, false, is_dynamic);
VM__push_frame(vm, frame);
FrameResult res = VM__run_top_frame(vm);
CodeObject__dtor(&co);
PK_DECREF(src);
if(res == RES_ERROR) return false;
if(res == RES_RETURN) return true;
c11__unreachedable();
}
bool py_exec(const char* source, const char* filename, enum py_CompileMode mode, py_Ref module) {
return _py_exec(source, filename, mode, module, false);
}
bool py_execdyn(const char* source, const char* filename, enum py_CompileMode mode, py_Ref module) {
return _py_exec(source, filename, mode, module, true);
}

View File

@ -7,8 +7,6 @@
#include "pocketpy/objects/object.h"
#include "pocketpy/interpreter/vm.h"
#include "pocketpy/compiler/compiler.h"
#include <stdbool.h>
#include <stdint.h>
VM* pk_current_vm;
@ -78,50 +76,6 @@ const char* pk_opname(Opcode op) {
return OP_NAMES[op];
}
static bool _py_exec(const char* source,
const char* filename,
enum py_CompileMode mode,
py_Ref module,
bool is_dynamic) {
VM* vm = pk_current_vm;
CodeObject co;
SourceData_ src = SourceData__rcnew(source, filename, mode, is_dynamic);
Error* err = pk_compile(src, &co);
if(err) {
py_exception(tp_SyntaxError, err->msg);
py_BaseException__stpush(&vm->curr_exception, src, err->lineno, NULL);
PK_DECREF(src);
free(err);
return false;
}
if(!module) module = &vm->main;
py_StackRef sp = vm->stack.sp;
if(is_dynamic) {
// [globals, locals]
sp -= 2;
}
Frame* frame = Frame__new(&co, module, sp, sp, false, is_dynamic);
VM__push_frame(vm, frame);
FrameResult res = VM__run_top_frame(vm);
CodeObject__dtor(&co);
PK_DECREF(src);
if(res == RES_ERROR) return false;
if(res == RES_RETURN) return true;
c11__unreachedable();
}
bool py_exec(const char* source, const char* filename, enum py_CompileMode mode, py_Ref module) {
return _py_exec(source, filename, mode, module, false);
}
bool py_execdyn(const char* source, const char* filename, enum py_CompileMode mode, py_Ref module) {
return _py_exec(source, filename, mode, module, true);
}
bool py_call(py_Ref f, int argc, py_Ref argv) {
if(f->type == tp_nativefunc) {
return py_callcfunc(f->_cfunc, argc, argv);
@ -220,7 +174,7 @@ py_Ref py_tpfindname(py_Type t, py_Name name) {
return NULL;
}
py_Ref py_tpmagic(py_Type type, py_Name name) {
py_Ref py_tpgetmagic(py_Type type, py_Name name) {
assert(py_ismagicname(name));
VM* vm = pk_current_vm;
return &c11__at(py_TypeInfo, &vm->types, type)->magic[name];

View File

@ -1,3 +1,4 @@
#include "pocketpy/objects/codeobject.h"
#include "pocketpy/pocketpy.h"
#include "pocketpy/common/utils.h"
@ -386,6 +387,7 @@ static bool builtins_ord(int argc, py_Ref argv) {
}
static bool builtins_globals(int argc, py_Ref argv) {
PY_CHECK_ARGC(0);
Frame* frame = pk_current_vm->top_frame;
if(frame->is_dynamic) {
py_assign(py_retval(), &frame->p0[0]);
@ -396,6 +398,7 @@ static bool builtins_globals(int argc, py_Ref argv) {
}
static bool builtins_locals(int argc, py_Ref argv) {
PY_CHECK_ARGC(0);
Frame* frame = pk_current_vm->top_frame;
if(frame->is_dynamic) {
py_assign(py_retval(), &frame->p0[1]);
@ -501,7 +504,6 @@ static bool function__closure__getter(int argc, py_Ref argv) {
Function* ud = py_touserdata(argv);
if(!ud->closure) {
py_newnone(py_retval());
return true;
}
py_Ref r0 = py_pushtmp();
py_Ref retval = py_pushtmp();
@ -520,10 +522,18 @@ static bool function__closure__getter(int argc, py_Ref argv) {
return true;
}
static void function__gc_mark(void* ud) {
Function* func = ud;
if(func->closure) pk__mark_namedict(func->closure);
CodeObject__gc_mark(&func->decl->code);
}
py_Type pk_function__register() {
py_Type type =
pk_newtype("function", tp_object, NULL, (void (*)(void*))Function__dtor, false, true);
pk__tp_set_marker(type, function__gc_mark);
py_bindproperty(type, "__closure__", function__closure__getter, NULL);
return type;
}

View File

@ -433,9 +433,21 @@ static bool dict_values(int argc, py_Ref argv) {
return true;
}
static void dict__gc_mark(void* ud) {
Dict* self = ud;
for(int i = 0; i < self->entries.count; i++) {
DictEntry* entry = c11__at(DictEntry, &self->entries, i);
if(py_isnil(&entry->key)) continue;
pk__mark_value(&entry->key);
pk__mark_value(&entry->val);
}
}
py_Type pk_dict__register() {
py_Type type = pk_newtype("dict", tp_object, NULL, (void (*)(void*))Dict__dtor, false, false);
pk__tp_set_marker(type, dict__gc_mark);
py_bindmagic(type, __new__, dict__new__);
py_bindmagic(type, __init__, dict__init__);
py_bindmagic(type, __getitem__, dict__getitem__);
@ -532,13 +544,3 @@ bool py_dict_apply(py_Ref self, bool (*f)(py_Ref, py_Ref, void*), void* ctx) {
}
return true;
}
void pk_dict__mark(void* ud, void (*marker)(py_TValue*)) {
Dict* self = ud;
for(int i = 0; i < self->entries.count; i++) {
DictEntry* entry = c11__at(DictEntry, &self->entries, i);
if(py_isnil(&entry->key)) continue;
marker(&entry->key);
marker(&entry->val);
}
}

View File

@ -106,7 +106,7 @@ py_Type pk_BaseException__register() {
}
py_Type pk_Exception__register() {
py_Type type = pk_newtype("Exception", tp_BaseException, NULL, NULL, false, true);
py_Type type = pk_newtype("Exception", tp_BaseException, NULL, NULL, false, false);
return type;
}

View File

@ -44,7 +44,7 @@ int py_list_len(py_Ref self) {
return userdata->count;
}
void py_list_swap(py_Ref self, int i, int j){
void py_list_swap(py_Ref self, int i, int j) {
py_TValue* data = py_list_data(self);
py_TValue tmp = data[i];
data[i] = data[j];
@ -408,10 +408,19 @@ static bool list__contains__(int argc, py_Ref argv) {
return pk_arraycontains(py_arg(0), py_arg(1));
}
static void list__gc_mark(void* ud) {
List* self = ud;
for(int i = 0; i < self->count; i++) {
pk__mark_value(c11__at(py_TValue, self, i));
}
}
py_Type pk_list__register() {
py_Type type =
pk_newtype("list", tp_object, NULL, (void (*)(void*))c11_vector__dtor, false, true);
pk__tp_set_marker(type, list__gc_mark);
py_bindmagic(type, __len__, list__len__);
py_bindmagic(type, __eq__, list__eq__);
py_bindmagic(type, __ne__, list__ne__);
@ -443,10 +452,3 @@ py_Type pk_list__register() {
py_setdict(py_tpobject(type), __hash__, py_None);
return type;
}
void pk_list__mark(void* ud, void (*marker)(py_TValue*)) {
List* self = ud;
for(int i = 0; i < self->count; i++) {
marker(c11__at(py_TValue, self, i));
}
}

View File

@ -46,9 +46,9 @@ static bool object__repr__(int argc, py_Ref argv) {
static bool object__dict__getter(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
if(argv->is_ptr && argv->_obj->slots == -1){
if(argv->is_ptr && argv->_obj->slots == -1) {
pk_mappingproxy__namedict(py_retval(), argv);
}else{
} else {
py_newnone(py_retval());
}
return true;
@ -74,9 +74,9 @@ static bool type__base__getter(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
py_Type type = py_totype(argv);
py_TypeInfo* ti = c11__at(py_TypeInfo, &pk_current_vm->types, type);
if(ti->base){
if(ti->base) {
py_assign(py_retval(), py_tpobject(ti->base));
}else{
} else {
py_newnone(py_retval());
}
return true;
@ -90,6 +90,11 @@ static bool type__name__getter(int argc, py_Ref argv) {
return true;
}
static bool type__getitem__(int argc, py_Ref argv) {
py_assign(py_retval(), argv);
return true;
}
void pk_object__register() {
// TODO: use staticmethod
py_bindmagic(tp_object, __new__, object__new__);
@ -102,6 +107,7 @@ void pk_object__register() {
py_bindmagic(tp_type, __repr__, type__repr__);
py_bindmagic(tp_type, __new__, type__new__);
py_bindmagic(tp_type, __getitem__, type__getitem__);
py_bindproperty(tp_type, "__base__", type__base__getter, NULL);
py_bindproperty(tp_type, "__name__", type__name__getter, NULL);

View File

@ -14,7 +14,7 @@ py_Ref py_getdict(py_Ref self, py_Name name) {
return NameDict__try_get(PyObject__dict(self->_obj), name);
} else {
py_Type* ud = py_touserdata(self);
py_Ref slot = py_tpmagic(*ud, name);
py_Ref slot = py_tpgetmagic(*ud, name);
return py_isnil(slot) ? NULL : slot;
}
}
@ -25,7 +25,7 @@ void py_setdict(py_Ref self, py_Name name, py_Ref val) {
NameDict__set(PyObject__dict(self->_obj), name, *val);
} else {
py_Type* ud = py_touserdata(self);
*py_tpmagic(*ud, name) = *val;
*py_tpgetmagic(*ud, name) = *val;
}
}
@ -41,7 +41,7 @@ bool py_deldict(py_Ref self, py_Name name) {
} else {
py_Type* ud = py_touserdata(self);
py_newnil(py_tpmagic(*ud, name));
py_newnil(py_tpgetmagic(*ud, name));
return true;
}
}

View File

@ -14,11 +14,7 @@ a = {
'h': False
}
try:
import cjson as json
print('[INFO] cjson is used')
except ImportError:
import json
import json
assert json.loads("1") == 1
assert json.loads('"1"') == "1"
@ -29,7 +25,7 @@ assert json.loads("true") == True
assert json.loads("false") == False
assert json.loads("{}") == {}
assert json.loads(b"false") == False
# assert json.loads(b"false") == False
_j = json.dumps(a)
_a = json.loads(_j)