mirror of
https://github.com/pocketpy/pocketpy
synced 2025-11-07 04:00:17 +00:00
Compare commits
No commits in common. "3786abccdd406f2ee7895f722aa3325699e1435a" and "a1a7609ec09aaab3e083867ae776e06295996a84" have entirely different histories.
3786abccdd
...
a1a7609ec0
@ -20,11 +20,3 @@
|
||||
#define equal(a, b) (c11_sv__cmp((a), (b)) == 0)
|
||||
#include "pocketpy/xmacros/smallmap.h"
|
||||
#undef SMALLMAP_T__HEADER
|
||||
|
||||
|
||||
#define SMALLMAP_T__HEADER
|
||||
#define K void*
|
||||
#define V int
|
||||
#define NAME c11_smallmap_p2i
|
||||
#include "pocketpy/xmacros/smallmap.h"
|
||||
#undef SMALLMAP_T__HEADER
|
||||
|
||||
@ -1,21 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "pocketpy/pocketpy.h"
|
||||
|
||||
#include "pocketpy/common/utils.h"
|
||||
#include "pocketpy/common/sstream.h"
|
||||
#include "pocketpy/interpreter/vm.h"
|
||||
|
||||
typedef struct c11_array2d {
|
||||
py_TValue* data; // slots
|
||||
int n_cols;
|
||||
int n_rows;
|
||||
int numel;
|
||||
} c11_array2d;
|
||||
|
||||
typedef struct c11_array2d_iterator {
|
||||
c11_array2d* array;
|
||||
int index;
|
||||
} c11_array2d_iterator;
|
||||
|
||||
c11_array2d* py_newarray2d(py_OutRef out, int n_cols, int n_rows);
|
||||
@ -610,20 +610,12 @@ PK_API int py_dict_getitem(py_Ref self, py_Ref key) PY_RAISE PY_RETURN;
|
||||
PK_API bool py_dict_setitem(py_Ref self, py_Ref key, py_Ref val) PY_RAISE;
|
||||
/// -1: error, 0: not found, 1: found (and deleted)
|
||||
PK_API int py_dict_delitem(py_Ref self, py_Ref key) PY_RAISE;
|
||||
|
||||
/// -1: error, 0: not found, 1: found
|
||||
PK_API int py_dict_getitem_by_str(py_Ref self, const char* key) PY_RAISE PY_RETURN;
|
||||
/// -1: error, 0: not found, 1: found
|
||||
PK_API int py_dict_getitem_by_int(py_Ref self, py_i64 key) PY_RAISE PY_RETURN;
|
||||
/// true: success, false: error
|
||||
PK_API bool py_dict_setitem_by_str(py_Ref self, const char* key, py_Ref val) PY_RAISE;
|
||||
/// true: success, false: error
|
||||
PK_API bool py_dict_setitem_by_int(py_Ref self, py_i64 key, py_Ref val) PY_RAISE;
|
||||
/// -1: error, 0: not found, 1: found (and deleted)
|
||||
PK_API int py_dict_delitem_by_str(py_Ref self, const char* key) PY_RAISE;
|
||||
/// -1: error, 0: not found, 1: found (and deleted)
|
||||
PK_API int py_dict_delitem_by_int(py_Ref self, py_i64 key) PY_RAISE;
|
||||
|
||||
/// true: success, false: error
|
||||
PK_API bool
|
||||
py_dict_apply(py_Ref self, bool (*f)(py_Ref key, py_Ref val, void* ctx), void* ctx) PY_RAISE;
|
||||
|
||||
@ -35,7 +35,7 @@ class deque(Generic[T]):
|
||||
_capacity: int
|
||||
|
||||
def __init__(self, iterable: Iterable[T] = None):
|
||||
self._data = [None] * 8 # type: ignore
|
||||
self._data = [None] * 8 # initial capacity
|
||||
self._head = 0
|
||||
self._tail = 0
|
||||
self._capacity = len(self._data)
|
||||
@ -98,7 +98,7 @@ class deque(Generic[T]):
|
||||
def clear(self):
|
||||
i = self._head
|
||||
while i != self._tail:
|
||||
self._data[i] = None # type: ignore
|
||||
self._data[i] = None
|
||||
i = (i + 1) % self._capacity
|
||||
self._head = 0
|
||||
self._tail = 0
|
||||
|
||||
@ -9,12 +9,12 @@ class timedelta:
|
||||
def __repr__(self):
|
||||
return f"datetime.timedelta(days={self.days}, seconds={self.seconds})"
|
||||
|
||||
def __eq__(self, other) -> bool:
|
||||
def __eq__(self, other: 'timedelta') -> bool:
|
||||
if not isinstance(other, timedelta):
|
||||
return NotImplemented
|
||||
return (self.days, self.seconds) == (other.days, other.seconds)
|
||||
|
||||
def __ne__(self, other) -> bool:
|
||||
def __ne__(self, other: 'timedelta') -> bool:
|
||||
if not isinstance(other, timedelta):
|
||||
return NotImplemented
|
||||
return (self.days, self.seconds) != (other.days, other.seconds)
|
||||
@ -40,10 +40,10 @@ class date:
|
||||
return op(self.month, other.month)
|
||||
return op(self.day, other.day)
|
||||
|
||||
def __eq__(self, other) -> bool:
|
||||
def __eq__(self, other: 'date') -> bool:
|
||||
return self.__cmp(other, operator.eq)
|
||||
|
||||
def __ne__(self, other) -> bool:
|
||||
def __ne__(self, other: 'date') -> bool:
|
||||
return self.__cmp(other, operator.ne)
|
||||
|
||||
def __lt__(self, other: 'date') -> bool:
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -16,11 +16,3 @@
|
||||
#define equal(a, b) (c11_sv__cmp((a), (b)) == 0)
|
||||
#include "pocketpy/xmacros/smallmap.h"
|
||||
#undef SMALLMAP_T__SOURCE
|
||||
|
||||
|
||||
#define SMALLMAP_T__SOURCE
|
||||
#define K void*
|
||||
#define V int
|
||||
#define NAME c11_smallmap_p2i
|
||||
#include "pocketpy/xmacros/smallmap.h"
|
||||
#undef SMALLMAP_T__SOURCE
|
||||
|
||||
@ -1,4 +1,20 @@
|
||||
#include "pocketpy/interpreter/array2d.h"
|
||||
#include "pocketpy/pocketpy.h"
|
||||
|
||||
#include "pocketpy/common/utils.h"
|
||||
#include "pocketpy/common/sstream.h"
|
||||
#include "pocketpy/interpreter/vm.h"
|
||||
|
||||
typedef struct c11_array2d {
|
||||
py_TValue* data; // slots
|
||||
int n_cols;
|
||||
int n_rows;
|
||||
int numel;
|
||||
} c11_array2d;
|
||||
|
||||
typedef struct c11_array2d_iterator {
|
||||
c11_array2d* array;
|
||||
int index;
|
||||
} c11_array2d_iterator;
|
||||
|
||||
static bool py_array2d_is_valid(c11_array2d* self, int col, int row) {
|
||||
return col >= 0 && col < self->n_cols && row >= 0 && row < self->n_rows;
|
||||
@ -12,7 +28,7 @@ static void py_array2d__set(c11_array2d* self, int col, int row, py_Ref value) {
|
||||
self->data[row * self->n_cols + col] = *value;
|
||||
}
|
||||
|
||||
c11_array2d* py_newarray2d(py_OutRef out, int n_cols, int n_rows) {
|
||||
static c11_array2d* py_array2d(py_OutRef out, int n_cols, int n_rows) {
|
||||
int numel = n_cols * n_rows;
|
||||
c11_array2d* ud = py_newobject(out, tp_array2d, numel, sizeof(c11_array2d));
|
||||
ud->data = py_getslot(out, 0);
|
||||
@ -33,7 +49,7 @@ static bool array2d__new__(int argc, py_Ref argv) {
|
||||
int n_rows = argv[2]._i64;
|
||||
int numel = n_cols * n_rows;
|
||||
if(n_cols <= 0 || n_rows <= 0) return ValueError("array2d() expected positive dimensions");
|
||||
c11_array2d* ud = py_newarray2d(py_pushtmp(), n_cols, n_rows);
|
||||
c11_array2d* ud = py_array2d(py_pushtmp(), n_cols, n_rows);
|
||||
// setup initial values
|
||||
if(py_callable(default_)) {
|
||||
for(int j = 0; j < n_rows; j++) {
|
||||
@ -175,7 +191,7 @@ static bool array2d_any(int argc, py_Ref argv) {
|
||||
static bool array2d__eq__(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
c11_array2d* self = py_touserdata(argv);
|
||||
c11_array2d* res = py_newarray2d(py_pushtmp(), self->n_cols, self->n_rows);
|
||||
c11_array2d* res = py_array2d(py_pushtmp(), self->n_cols, self->n_rows);
|
||||
if(py_istype(py_arg(1), tp_array2d)) {
|
||||
c11_array2d* other = py_touserdata(py_arg(1));
|
||||
if(!_array2d_check_same_shape(self, other)) return false;
|
||||
@ -252,7 +268,7 @@ static bool array2d_map(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
c11_array2d* self = py_touserdata(argv);
|
||||
py_Ref f = py_arg(1);
|
||||
c11_array2d* res = py_newarray2d(py_pushtmp(), self->n_cols, self->n_rows);
|
||||
c11_array2d* res = py_array2d(py_pushtmp(), self->n_cols, self->n_rows);
|
||||
for(int i = 0; i < self->numel; i++) {
|
||||
bool ok = py_call(f, 1, self->data + i);
|
||||
if(!ok) return false;
|
||||
@ -267,7 +283,7 @@ static bool array2d_copy(int argc, py_Ref argv) {
|
||||
// def copy(self) -> 'array2d': ...
|
||||
PY_CHECK_ARGC(1);
|
||||
c11_array2d* self = py_touserdata(argv);
|
||||
c11_array2d* res = py_newarray2d(py_retval(), self->n_cols, self->n_rows);
|
||||
c11_array2d* res = py_array2d(py_retval(), self->n_cols, self->n_rows);
|
||||
memcpy(res->data, self->data, self->numel * sizeof(py_TValue));
|
||||
return true;
|
||||
}
|
||||
@ -340,7 +356,7 @@ static bool array2d_fromlist_STATIC(int argc, py_Ref argv) {
|
||||
return ValueError("fromlist() expected a list of lists with the same length");
|
||||
}
|
||||
}
|
||||
c11_array2d* res = py_newarray2d(py_retval(), n_cols, n_rows);
|
||||
c11_array2d* res = py_array2d(py_retval(), n_cols, n_rows);
|
||||
for(int j = 0; j < n_rows; j++) {
|
||||
py_Ref row_j = py_list_getitem(argv, j);
|
||||
for(int i = 0; i < n_cols; i++) {
|
||||
@ -436,7 +452,7 @@ static bool array2d_get_bounding_rect(int argc, py_Ref argv) {
|
||||
static bool array2d_count_neighbors(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(3);
|
||||
c11_array2d* self = py_touserdata(argv);
|
||||
c11_array2d* res = py_newarray2d(py_pushtmp(), self->n_cols, self->n_rows);
|
||||
c11_array2d* res = py_array2d(py_pushtmp(), self->n_cols, self->n_rows);
|
||||
py_Ref value = py_arg(1);
|
||||
const char* neighborhood = py_tostr(py_arg(2));
|
||||
|
||||
@ -540,7 +556,7 @@ static bool array2d__getitem__(int argc, py_Ref argv) {
|
||||
return _array2d_IndexError(self, col, row);
|
||||
} else if(py_istype(x, tp_slice) && py_istype(y, tp_slice)) {
|
||||
HANDLE_SLICE();
|
||||
c11_array2d* res = py_newarray2d(py_retval(), slice_width, slice_height);
|
||||
c11_array2d* res = py_array2d(py_retval(), slice_width, slice_height);
|
||||
for(int j = start_row; j < stop_row; j++) {
|
||||
for(int i = start_col; i < stop_col; i++) {
|
||||
py_array2d__set(res, i - start_col, j - start_row, py_array2d__get(self, i, j));
|
||||
@ -644,7 +660,7 @@ static bool array2d_convolve(int argc, py_Ref argv) {
|
||||
int ksize_half = ksize / 2;
|
||||
if(!_array2d_check_all_type(self, tp_int)) return false;
|
||||
if(!_array2d_check_all_type(kernel, tp_int)) return false;
|
||||
c11_array2d* res = py_newarray2d(py_pushtmp(), self->n_cols, self->n_rows);
|
||||
c11_array2d* res = py_array2d(py_pushtmp(), self->n_cols, self->n_rows);
|
||||
for(int j = 0; j < self->n_rows; j++) {
|
||||
for(int i = 0; i < self->n_cols; i++) {
|
||||
py_i64 sum = 0;
|
||||
|
||||
@ -3,16 +3,12 @@
|
||||
|
||||
#include "pocketpy/common/utils.h"
|
||||
#include "pocketpy/common/sstream.h"
|
||||
#include "pocketpy/interpreter/array2d.h"
|
||||
#include "pocketpy/interpreter/vm.h"
|
||||
#include <stdint.h>
|
||||
|
||||
typedef enum {
|
||||
// clang-format off
|
||||
PKL_MEMO_GET,
|
||||
PKL_MEMO_SET,
|
||||
PKL_NONE, PKL_ELLIPSIS,
|
||||
PKL_INT_0, PKL_INT_1, PKL_INT_2, PKL_INT_3, PKL_INT_4, PKL_INT_5, PKL_INT_6, PKL_INT_7,
|
||||
PKL_INT_8, PKL_INT_9, PKL_INT_10, PKL_INT_11, PKL_INT_12, PKL_INT_13, PKL_INT_14, PKL_INT_15,
|
||||
PKL_NONE,
|
||||
PKL_INT8, PKL_INT16, PKL_INT32, PKL_INT64,
|
||||
PKL_FLOAT32, PKL_FLOAT64,
|
||||
PKL_TRUE, PKL_FALSE,
|
||||
@ -23,39 +19,24 @@ typedef enum {
|
||||
PKL_VEC2, PKL_VEC3,
|
||||
PKL_VEC2I, PKL_VEC3I,
|
||||
PKL_TYPE,
|
||||
PKL_ARRAY2D,
|
||||
PKL_EOF,
|
||||
// clang-format on
|
||||
} PickleOp;
|
||||
|
||||
typedef struct {
|
||||
c11_smallmap_p2i memo;
|
||||
c11_vector /*T=char*/ codes;
|
||||
} PickleObject;
|
||||
|
||||
typedef struct {
|
||||
uint16_t memo_length;
|
||||
} PickleObjectHeader;
|
||||
static void PickleObject__ctor(PickleObject* self) { c11_vector__ctor(&self->codes, sizeof(char)); }
|
||||
|
||||
static void PickleObject__ctor(PickleObject* self) {
|
||||
c11_smallmap_p2i__ctor(&self->memo);
|
||||
c11_vector__ctor(&self->codes, sizeof(char));
|
||||
}
|
||||
static void PickleObject__dtor(PickleObject* self) { c11_vector__dtor(&self->codes); }
|
||||
|
||||
static void PickleObject__dtor(PickleObject* self) {
|
||||
c11_smallmap_p2i__dtor(&self->memo);
|
||||
c11_vector__dtor(&self->codes);
|
||||
}
|
||||
|
||||
static bool PickleObject__py_submit(PickleObject* self, py_OutRef out) {
|
||||
unsigned char* data = self->codes.data;
|
||||
PickleObjectHeader* p =
|
||||
(PickleObjectHeader*)py_newbytes(out, sizeof(PickleObjectHeader) + self->codes.length);
|
||||
if(self->memo.length >= UINT16_MAX) c11__abort("PickleObject__py_submit(): memo overflow");
|
||||
p->memo_length = (uint16_t)self->memo.length;
|
||||
memcpy(p + 1, data, self->codes.length);
|
||||
PickleObject__dtor(self);
|
||||
return true;
|
||||
static void PickleObject__py_submit(PickleObject* self, py_OutRef out) {
|
||||
int size;
|
||||
unsigned char* data = c11_vector__submit(&self->codes, &size);
|
||||
unsigned char* out_data = py_newbytes(out, size);
|
||||
memcpy(out_data, data, size);
|
||||
free(data);
|
||||
}
|
||||
|
||||
static void PickleObject__write_bytes(PickleObject* buf, const void* data, int size) {
|
||||
@ -67,10 +48,6 @@ static void pkl__emit_op(PickleObject* buf, PickleOp op) {
|
||||
}
|
||||
|
||||
static void pkl__emit_int(PickleObject* buf, py_i64 val) {
|
||||
if(val >= 0 && val <= 15) {
|
||||
pkl__emit_op(buf, PKL_INT_0 + val);
|
||||
return;
|
||||
}
|
||||
if((int8_t)val == val) {
|
||||
pkl__emit_op(buf, PKL_INT8);
|
||||
PickleObject__write_bytes(buf, &val, 1);
|
||||
@ -96,24 +73,6 @@ static py_i64 pkl__read_int(const unsigned char** p) {
|
||||
PickleOp op = (PickleOp) * *p;
|
||||
(*p)++;
|
||||
switch(op) {
|
||||
// clang-format off
|
||||
case PKL_INT_0: return 0;
|
||||
case PKL_INT_1: return 1;
|
||||
case PKL_INT_2: return 2;
|
||||
case PKL_INT_3: return 3;
|
||||
case PKL_INT_4: return 4;
|
||||
case PKL_INT_5: return 5;
|
||||
case PKL_INT_6: return 6;
|
||||
case PKL_INT_7: return 7;
|
||||
case PKL_INT_8: return 8;
|
||||
case PKL_INT_9: return 9;
|
||||
case PKL_INT_10: return 10;
|
||||
case PKL_INT_11: return 11;
|
||||
case PKL_INT_12: return 12;
|
||||
case PKL_INT_13: return 13;
|
||||
case PKL_INT_14: return 14;
|
||||
case PKL_INT_15: return 15;
|
||||
// clang-format on
|
||||
case PKL_INT8: {
|
||||
int8_t val;
|
||||
UNALIGNED_READ(&val, *p);
|
||||
@ -185,28 +144,15 @@ static bool pickle__write_dict_kv(py_Ref k, py_Ref v, void* ctx) {
|
||||
}
|
||||
|
||||
static bool pickle__write_object(PickleObject* buf, py_TValue* obj) {
|
||||
if(obj->is_ptr) {
|
||||
void* memo_key = obj->_obj;
|
||||
int index = c11_smallmap_p2i__get(&buf->memo, memo_key, -1);
|
||||
if(index != -1) {
|
||||
pkl__emit_op(buf, PKL_MEMO_GET);
|
||||
pkl__emit_int(buf, index);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
switch(obj->type) {
|
||||
case tp_NoneType: {
|
||||
pkl__emit_op(buf, PKL_NONE);
|
||||
break;
|
||||
}
|
||||
case tp_ellipsis: {
|
||||
pkl__emit_op(buf, PKL_ELLIPSIS);
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
case tp_int: {
|
||||
py_i64 val = obj->_i64;
|
||||
pkl__emit_int(buf, val);
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
case tp_float: {
|
||||
py_f64 val = obj->_f64;
|
||||
@ -218,19 +164,19 @@ static bool pickle__write_object(PickleObject* buf, py_TValue* obj) {
|
||||
pkl__emit_op(buf, PKL_FLOAT64);
|
||||
PickleObject__write_bytes(buf, &val, 8);
|
||||
}
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
case tp_bool: {
|
||||
bool val = obj->_bool;
|
||||
pkl__emit_op(buf, val ? PKL_TRUE : PKL_FALSE);
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
case tp_str: {
|
||||
pkl__emit_op(buf, PKL_STRING);
|
||||
c11_sv sv = py_tosv(obj);
|
||||
pkl__emit_int(buf, sv.size);
|
||||
PickleObject__write_bytes(buf, sv.data, sv.size);
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
case tp_bytes: {
|
||||
pkl__emit_op(buf, PKL_BYTES);
|
||||
@ -238,44 +184,39 @@ static bool pickle__write_object(PickleObject* buf, py_TValue* obj) {
|
||||
unsigned char* data = py_tobytes(obj, &size);
|
||||
pkl__emit_int(buf, size);
|
||||
PickleObject__write_bytes(buf, data, size);
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
case tp_list: {
|
||||
bool ok = pickle__write_array(buf, PKL_BUILD_LIST, py_list_data(obj), py_list_len(obj));
|
||||
if(!ok) return false;
|
||||
break;
|
||||
return pickle__write_array(buf, PKL_BUILD_LIST, py_list_data(obj), py_list_len(obj));
|
||||
}
|
||||
case tp_tuple: {
|
||||
bool ok =
|
||||
pickle__write_array(buf, PKL_BUILD_TUPLE, py_tuple_data(obj), py_tuple_len(obj));
|
||||
if(!ok) return false;
|
||||
break;
|
||||
return pickle__write_array(buf, PKL_BUILD_TUPLE, py_tuple_data(obj), py_tuple_len(obj));
|
||||
}
|
||||
case tp_dict: {
|
||||
bool ok = py_dict_apply(obj, pickle__write_dict_kv, (void*)buf);
|
||||
if(!ok) return false;
|
||||
pkl__emit_op(buf, PKL_BUILD_DICT);
|
||||
pkl__emit_int(buf, py_dict_len(obj));
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
case tp_vec2: {
|
||||
c11_vec2 val = py_tovec2(obj);
|
||||
pkl__emit_op(buf, PKL_VEC2);
|
||||
PickleObject__write_bytes(buf, &val, sizeof(c11_vec2));
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
case tp_vec3: {
|
||||
c11_vec3 val = py_tovec3(obj);
|
||||
pkl__emit_op(buf, PKL_VEC3);
|
||||
PickleObject__write_bytes(buf, &val, sizeof(c11_vec3));
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
case tp_vec2i: {
|
||||
c11_vec2i val = py_tovec2i(obj);
|
||||
pkl__emit_op(buf, PKL_VEC2I);
|
||||
pkl__emit_int(buf, val.x);
|
||||
pkl__emit_int(buf, val.y);
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
case tp_vec3i: {
|
||||
c11_vec3i val = py_tovec3i(obj);
|
||||
@ -283,7 +224,7 @@ static bool pickle__write_object(PickleObject* buf, py_TValue* obj) {
|
||||
pkl__emit_int(buf, val.x);
|
||||
pkl__emit_int(buf, val.y);
|
||||
pkl__emit_int(buf, val.z);
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
case tp_type: {
|
||||
pkl__emit_op(buf, PKL_TYPE);
|
||||
@ -298,32 +239,10 @@ static bool pickle__write_object(PickleObject* buf, py_TValue* obj) {
|
||||
// include '\0'
|
||||
PickleObject__write_bytes(buf, path->data, path->size + 1);
|
||||
c11_string__delete(path);
|
||||
break;
|
||||
}
|
||||
case tp_array2d: {
|
||||
c11_array2d* arr = py_touserdata(obj);
|
||||
for(int i = 0; i < arr->numel; i++) {
|
||||
if(arr->data[i].is_ptr)
|
||||
return TypeError(
|
||||
"'array2d' object is not picklable because it contains heap-allocated objects");
|
||||
}
|
||||
pkl__emit_op(buf, PKL_ARRAY2D);
|
||||
pkl__emit_int(buf, arr->n_cols);
|
||||
pkl__emit_int(buf, arr->n_rows);
|
||||
// TODO: fix type index which is not stable
|
||||
PickleObject__write_bytes(buf, arr->data, arr->numel * sizeof(py_TValue));
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
default: return TypeError("'%t' object is not picklable", obj->type);
|
||||
}
|
||||
if(obj->is_ptr) {
|
||||
void* memo_key = obj->_obj;
|
||||
int index = buf->memo.length;
|
||||
c11_smallmap_p2i__set(&buf->memo, memo_key, index);
|
||||
pkl__emit_op(buf, PKL_MEMO_SET);
|
||||
pkl__emit_int(buf, index);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool py_pickle_dumps(py_Ref val) {
|
||||
@ -335,48 +254,21 @@ bool py_pickle_dumps(py_Ref val) {
|
||||
return false;
|
||||
}
|
||||
pkl__emit_op(&buf, PKL_EOF);
|
||||
return PickleObject__py_submit(&buf, py_retval());
|
||||
PickleObject__py_submit(&buf, py_retval());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool py_pickle_loads(const unsigned char* data, int size) {
|
||||
PickleObjectHeader* header = (PickleObjectHeader*)data;
|
||||
const unsigned char* p = (const unsigned char*)(header + 1);
|
||||
py_StackRef p0 = py_peek(0);
|
||||
py_StackRef memo = py_pushtmp();
|
||||
py_newtuple(memo, header->memo_length);
|
||||
const unsigned char* p = data;
|
||||
while(true) {
|
||||
PickleOp op = (PickleOp)*p;
|
||||
p++;
|
||||
switch(op) {
|
||||
case PKL_MEMO_GET: {
|
||||
int index = pkl__read_int(&p);
|
||||
py_Ref val = py_tuple_getitem(memo, index);
|
||||
assert(!py_isnil(val));
|
||||
py_push(val);
|
||||
break;
|
||||
}
|
||||
case PKL_MEMO_SET: {
|
||||
int index = pkl__read_int(&p);
|
||||
py_tuple_setitem(memo, index, py_peek(-1));
|
||||
break;
|
||||
}
|
||||
case PKL_NONE: {
|
||||
py_pushnone();
|
||||
break;
|
||||
}
|
||||
case PKL_ELLIPSIS: {
|
||||
py_newellipsis(py_pushtmp());
|
||||
break;
|
||||
}
|
||||
// clang-format off
|
||||
case PKL_INT_0: case PKL_INT_1: case PKL_INT_2: case PKL_INT_3:
|
||||
case PKL_INT_4: case PKL_INT_5: case PKL_INT_6: case PKL_INT_7:
|
||||
case PKL_INT_8: case PKL_INT_9: case PKL_INT_10: case PKL_INT_11:
|
||||
case PKL_INT_12: case PKL_INT_13: case PKL_INT_14: case PKL_INT_15: {
|
||||
py_newint(py_pushtmp(), op - PKL_INT_0);
|
||||
break;
|
||||
}
|
||||
// clang-format on
|
||||
case PKL_INT8: {
|
||||
int8_t val;
|
||||
UNALIGNED_READ(&val, p);
|
||||
@ -518,20 +410,10 @@ bool py_pickle_loads(const unsigned char* data, int size) {
|
||||
py_push(py_tpobject(t));
|
||||
break;
|
||||
}
|
||||
case PKL_ARRAY2D: {
|
||||
int n_cols = pkl__read_int(&p);
|
||||
int n_rows = pkl__read_int(&p);
|
||||
c11_array2d* arr = py_newarray2d(py_pushtmp(), n_cols, n_rows);
|
||||
int total_size = arr->numel * sizeof(py_TValue);
|
||||
memcpy(arr->data, p, total_size);
|
||||
p += total_size;
|
||||
break;
|
||||
}
|
||||
case PKL_EOF: {
|
||||
// [memo, obj]
|
||||
if(py_peek(0) - p0 != 2) return ValueError("invalid pickle data");
|
||||
py_assign(py_retval(), py_peek(-1));
|
||||
py_shrink(2);
|
||||
if(py_peek(0) - p0 != 1) { return ValueError("invalid pickle data"); }
|
||||
py_assign(py_retval(), p0);
|
||||
py_pop();
|
||||
return true;
|
||||
}
|
||||
default: c11__unreachable();
|
||||
|
||||
@ -316,10 +316,7 @@ static bool builtins_print(int argc, py_Ref argv) {
|
||||
c11_sbuf__ctor(&buf);
|
||||
for(int i = 0; i < length; i++) {
|
||||
if(i > 0) c11_sbuf__write_sv(&buf, sep);
|
||||
if(!py_str(&args[i])) {
|
||||
c11_sbuf__dtor(&buf);
|
||||
return false;
|
||||
}
|
||||
if(!py_str(&args[i])) return false;
|
||||
c11_sbuf__write_sv(&buf, py_tosv(py_retval()));
|
||||
}
|
||||
c11_sbuf__write_sv(&buf, end);
|
||||
|
||||
@ -632,24 +632,6 @@ int py_dict_delitem_by_str(py_Ref self, const char* key) {
|
||||
return res;
|
||||
}
|
||||
|
||||
int py_dict_getitem_by_int(py_Ref self, py_i64 key) {
|
||||
py_TValue tmp;
|
||||
py_newint(&tmp, key);
|
||||
return py_dict_getitem(self, &tmp);
|
||||
}
|
||||
|
||||
bool py_dict_setitem_by_int(py_Ref self, py_i64 key, py_Ref val) {
|
||||
py_TValue tmp;
|
||||
py_newint(&tmp, key);
|
||||
return py_dict_setitem(self, &tmp, val);
|
||||
}
|
||||
|
||||
int py_dict_delitem_by_int(py_Ref self, py_i64 key) {
|
||||
py_TValue tmp;
|
||||
py_newint(&tmp, key);
|
||||
return py_dict_delitem(self, &tmp);
|
||||
}
|
||||
|
||||
int py_dict_len(py_Ref self) {
|
||||
assert(py_isdict(self));
|
||||
Dict* ud = py_touserdata(self);
|
||||
|
||||
@ -7,10 +7,8 @@ def test(data): # type: ignore
|
||||
o = pkl.loads(b)
|
||||
print(o)
|
||||
assert data == o
|
||||
return o
|
||||
|
||||
test(None) # PKL_NONE
|
||||
test(...) # PKL_ELLIPSIS
|
||||
test(1) # PKL_INT8
|
||||
test(277) # PKL_INT16
|
||||
test(-66666) # PKL_INT32
|
||||
@ -31,20 +29,6 @@ test(vec3i(1, 2, 3)) # PKL_VEC3I
|
||||
|
||||
test(vec3i) # PKL_TYPE
|
||||
|
||||
print('-'*50)
|
||||
from array2d import array2d
|
||||
a = array2d[int].fromlist([
|
||||
[1, 2, 3],
|
||||
[4, 5, 6]
|
||||
])
|
||||
a_encoded = pkl.dumps(a)
|
||||
print(a_encoded)
|
||||
a_decoded = pkl.loads(a_encoded)
|
||||
assert isinstance(a_decoded, array2d)
|
||||
assert a_decoded.width == 3 and a_decoded.height == 2
|
||||
assert (a == a_decoded).all()
|
||||
print(a_decoded)
|
||||
|
||||
test([1, 2, 3]) # PKL_LIST
|
||||
test((1, 2, 3)) # PKL_TUPLE
|
||||
test({1: 2, 3: 4}) # PKL_DICT
|
||||
@ -55,23 +39,6 @@ test([1, '2', 3.0, True])
|
||||
test([1, '2', True, {'key': 4}])
|
||||
test([1, '2', 3.0, True, {'k1': 4, 'k2': [b'xxxx']}])
|
||||
|
||||
# test memo
|
||||
a = [1, 2, 3, 4, 5, 6, 745]
|
||||
b = [a] * 10
|
||||
c = test(b)
|
||||
assert b == c
|
||||
assert b is not c
|
||||
assert c[0] is c[1] and c[1] is c[2]
|
||||
|
||||
s1 = 'hello'
|
||||
s2 = 'world'
|
||||
a = [s1, s2] * 10
|
||||
b = test(a)
|
||||
assert b == a
|
||||
assert b is not a
|
||||
assert b[0] is b[2]
|
||||
assert b[1] is b[3]
|
||||
|
||||
exit()
|
||||
|
||||
from pickle import dumps, loads, _wrap, _unwrap
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user