mirror of
https://github.com/pocketpy/pocketpy
synced 2026-03-21 20:50:16 +00:00
Compare commits
5 Commits
7d274490b6
...
628ae07f0d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
628ae07f0d | ||
|
|
440acd82f8 | ||
|
|
1d567445ed | ||
|
|
427d2293e0 | ||
|
|
c048ec9faf |
@ -51,7 +51,7 @@ typedef struct c11_chunked_array2d {
|
|||||||
c11_chunked_array2d_chunks_KV last_visited;
|
c11_chunked_array2d_chunks_KV last_visited;
|
||||||
|
|
||||||
py_TValue default_T;
|
py_TValue default_T;
|
||||||
py_TValue context_builder;
|
bool auto_add_chunk;
|
||||||
} c11_chunked_array2d;
|
} c11_chunked_array2d;
|
||||||
|
|
||||||
py_Ref c11_chunked_array2d__get(c11_chunked_array2d* self, int col, int row);
|
py_Ref c11_chunked_array2d__get(c11_chunked_array2d* self, int col, int row);
|
||||||
|
|||||||
@ -21,6 +21,7 @@ typedef struct py_TValue {
|
|||||||
c11_vec2i _vec2i;
|
c11_vec2i _vec2i;
|
||||||
c11_vec3 _vec3;
|
c11_vec3 _vec3;
|
||||||
c11_vec3i _vec3i;
|
c11_vec3i _vec3i;
|
||||||
|
c11_vec4i _vec4i;
|
||||||
c11_color32 _color32;
|
c11_color32 _color32;
|
||||||
void* _ptr;
|
void* _ptr;
|
||||||
char _chars[16];
|
char _chars[16];
|
||||||
|
|||||||
@ -775,12 +775,14 @@ PK_API void py_newvec2(py_OutRef out, c11_vec2);
|
|||||||
PK_API void py_newvec3(py_OutRef out, c11_vec3);
|
PK_API void py_newvec3(py_OutRef out, c11_vec3);
|
||||||
PK_API void py_newvec2i(py_OutRef out, c11_vec2i);
|
PK_API void py_newvec2i(py_OutRef out, c11_vec2i);
|
||||||
PK_API void py_newvec3i(py_OutRef out, c11_vec3i);
|
PK_API void py_newvec3i(py_OutRef out, c11_vec3i);
|
||||||
|
PK_API void py_newvec4i(py_OutRef out, c11_vec4i);
|
||||||
PK_API void py_newcolor32(py_OutRef out, c11_color32);
|
PK_API void py_newcolor32(py_OutRef out, c11_color32);
|
||||||
PK_API c11_mat3x3* py_newmat3x3(py_OutRef out);
|
PK_API c11_mat3x3* py_newmat3x3(py_OutRef out);
|
||||||
PK_API c11_vec2 py_tovec2(py_Ref self);
|
PK_API c11_vec2 py_tovec2(py_Ref self);
|
||||||
PK_API c11_vec3 py_tovec3(py_Ref self);
|
PK_API c11_vec3 py_tovec3(py_Ref self);
|
||||||
PK_API c11_vec2i py_tovec2i(py_Ref self);
|
PK_API c11_vec2i py_tovec2i(py_Ref self);
|
||||||
PK_API c11_vec3i py_tovec3i(py_Ref self);
|
PK_API c11_vec3i py_tovec3i(py_Ref self);
|
||||||
|
PK_API c11_vec4i py_tovec4i(py_Ref self);
|
||||||
PK_API c11_mat3x3* py_tomat3x3(py_Ref self);
|
PK_API c11_mat3x3* py_tomat3x3(py_Ref self);
|
||||||
PK_API c11_color32 py_tocolor32(py_Ref self);
|
PK_API c11_color32 py_tocolor32(py_Ref self);
|
||||||
|
|
||||||
@ -901,6 +903,7 @@ enum py_PredefinedType {
|
|||||||
tp_vec3,
|
tp_vec3,
|
||||||
tp_vec2i,
|
tp_vec2i,
|
||||||
tp_vec3i,
|
tp_vec3i,
|
||||||
|
tp_vec4i,
|
||||||
tp_mat3x3,
|
tp_mat3x3,
|
||||||
tp_color32,
|
tp_color32,
|
||||||
/* array2d */
|
/* array2d */
|
||||||
|
|||||||
@ -13,6 +13,11 @@ typedef union c11_vec3i {
|
|||||||
int data[3];
|
int data[3];
|
||||||
} c11_vec3i;
|
} c11_vec3i;
|
||||||
|
|
||||||
|
typedef union c11_vec4i {
|
||||||
|
struct { int x, y, z, w; };
|
||||||
|
int data[4];
|
||||||
|
} c11_vec4i;
|
||||||
|
|
||||||
typedef union c11_vec2 {
|
typedef union c11_vec2 {
|
||||||
struct { float x, y; };
|
struct { float x, y; };
|
||||||
float data[2];
|
float data[2];
|
||||||
|
|||||||
@ -136,19 +136,14 @@ class chunked_array2d[T, TContext]:
|
|||||||
cls,
|
cls,
|
||||||
chunk_size: int,
|
chunk_size: int,
|
||||||
default: T | None = None,
|
default: T | None = None,
|
||||||
context_builder: Callable[[vec2i], TContext] | None = None,
|
auto_add_chunk: bool = True,
|
||||||
): ...
|
): ...
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def chunk_size(self) -> int: ...
|
def chunk_size(self) -> int: ...
|
||||||
@property
|
|
||||||
def default(self) -> T: ...
|
|
||||||
@property
|
|
||||||
def context_builder(self) -> Callable[[vec2i], TContext] | None: ...
|
|
||||||
|
|
||||||
def __getitem__(self, index: vec2i) -> T: ...
|
def __getitem__(self, index: vec2i) -> T: ...
|
||||||
def __setitem__(self, index: vec2i, value: T): ...
|
def __setitem__(self, index: vec2i, value: T): ...
|
||||||
def __delitem__(self, index: vec2i): ...
|
|
||||||
def __iter__(self) -> Iterator[tuple[vec2i, TContext]]: ...
|
def __iter__(self) -> Iterator[tuple[vec2i, TContext]]: ...
|
||||||
def __len__(self) -> int: ...
|
def __len__(self) -> int: ...
|
||||||
|
|
||||||
@ -158,7 +153,7 @@ class chunked_array2d[T, TContext]:
|
|||||||
def world_to_chunk(self, world_pos: vec2i) -> tuple[vec2i, vec2i]:
|
def world_to_chunk(self, world_pos: vec2i) -> tuple[vec2i, vec2i]:
|
||||||
"""Converts world position to chunk position and local position."""
|
"""Converts world position to chunk position and local position."""
|
||||||
|
|
||||||
def add_chunk(self, chunk_pos: vec2i) -> TContext: ...
|
def add_chunk(self, chunk_pos: vec2i, context: TContext | None) -> None: ...
|
||||||
def remove_chunk(self, chunk_pos: vec2i) -> bool: ...
|
def remove_chunk(self, chunk_pos: vec2i) -> bool: ...
|
||||||
def move_chunk(self, src_chunk_pos: vec2i, dst_chunk_pos: vec2i) -> bool: ...
|
def move_chunk(self, src_chunk_pos: vec2i, dst_chunk_pos: vec2i) -> bool: ...
|
||||||
def get_context(self, chunk_pos: vec2i) -> TContext | None: ...
|
def get_context(self, chunk_pos: vec2i) -> TContext | None: ...
|
||||||
|
|||||||
@ -157,6 +157,23 @@ class vec3i(_vecI['vec3i']):
|
|||||||
|
|
||||||
def __init__(self, x: int, y: int, z: int) -> None: ...
|
def __init__(self, x: int, y: int, z: int) -> None: ...
|
||||||
|
|
||||||
|
class vec4i(_vecI['vec4i']):
|
||||||
|
@property
|
||||||
|
def x(self) -> int: ...
|
||||||
|
@property
|
||||||
|
def y(self) -> int: ...
|
||||||
|
@property
|
||||||
|
def z(self) -> int: ...
|
||||||
|
@property
|
||||||
|
def w(self) -> int: ...
|
||||||
|
|
||||||
|
def with_x(self, x: int) -> vec4i: ...
|
||||||
|
def with_y(self, y: int) -> vec4i: ...
|
||||||
|
def with_z(self, z: int) -> vec4i: ...
|
||||||
|
def with_w(self, w: int) -> vec4i: ...
|
||||||
|
|
||||||
|
def __init__(self, x: int, y: int, z: int, w: int) -> None: ...
|
||||||
|
|
||||||
|
|
||||||
class vec3(_vecF['vec3']):
|
class vec3(_vecF['vec3']):
|
||||||
@property
|
@property
|
||||||
|
|||||||
@ -2801,6 +2801,8 @@ static Error* compile_stmt(Compiler* self) {
|
|||||||
case TK_WITH: {
|
case TK_WITH: {
|
||||||
check(EXPR(self)); // [ <expr> ]
|
check(EXPR(self)); // [ <expr> ]
|
||||||
Ctx__s_emit_top(ctx());
|
Ctx__s_emit_top(ctx());
|
||||||
|
// Save context manager for later __exit__ call
|
||||||
|
Ctx__emit_(ctx(), OP_DUP_TOP, BC_NOARG, prev()->line);
|
||||||
Ctx__enter_block(ctx(), CodeBlockType_WITH);
|
Ctx__enter_block(ctx(), CodeBlockType_WITH);
|
||||||
NameExpr* as_name = NULL;
|
NameExpr* as_name = NULL;
|
||||||
if(match(TK_AS)) {
|
if(match(TK_AS)) {
|
||||||
@ -2809,17 +2811,33 @@ static Error* compile_stmt(Compiler* self) {
|
|||||||
as_name = NameExpr__new(prev()->line, name, name_scope(self));
|
as_name = NameExpr__new(prev()->line, name, name_scope(self));
|
||||||
}
|
}
|
||||||
Ctx__emit_(ctx(), OP_WITH_ENTER, BC_NOARG, prev()->line);
|
Ctx__emit_(ctx(), OP_WITH_ENTER, BC_NOARG, prev()->line);
|
||||||
// [ <expr> <expr>.__enter__() ]
|
|
||||||
if(as_name) {
|
if(as_name) {
|
||||||
bool ok = vtemit_store((Expr*)as_name, ctx());
|
bool ok = vtemit_store((Expr*)as_name, ctx());
|
||||||
vtdelete((Expr*)as_name);
|
vtdelete((Expr*)as_name);
|
||||||
if(!ok) return SyntaxError(self, "invalid syntax");
|
if(!ok) return SyntaxError(self, "invalid syntax");
|
||||||
} else {
|
} else {
|
||||||
// discard `__enter__()`'s return value
|
|
||||||
Ctx__emit_(ctx(), OP_POP_TOP, BC_NOARG, BC_KEEPLINE);
|
Ctx__emit_(ctx(), OP_POP_TOP, BC_NOARG, BC_KEEPLINE);
|
||||||
}
|
}
|
||||||
|
// Wrap body in try-except to ensure __exit__ is called even on exception
|
||||||
|
Ctx__enter_block(ctx(), CodeBlockType_TRY);
|
||||||
|
Ctx__emit_(ctx(), OP_BEGIN_TRY, BC_NOARG, prev()->line);
|
||||||
check(compile_block_body(self));
|
check(compile_block_body(self));
|
||||||
|
Ctx__emit_(ctx(), OP_END_TRY, BC_NOARG, BC_KEEPLINE);
|
||||||
|
// Normal exit: call __exit__(None, None, None)
|
||||||
|
Ctx__emit_(ctx(), OP_LOAD_NONE, BC_NOARG, prev()->line);
|
||||||
|
Ctx__emit_(ctx(), OP_LOAD_NONE, BC_NOARG, prev()->line);
|
||||||
|
Ctx__emit_(ctx(), OP_LOAD_NONE, BC_NOARG, prev()->line);
|
||||||
Ctx__emit_(ctx(), OP_WITH_EXIT, BC_NOARG, prev()->line);
|
Ctx__emit_(ctx(), OP_WITH_EXIT, BC_NOARG, prev()->line);
|
||||||
|
int jump_patch = Ctx__emit_(ctx(), OP_JUMP_FORWARD, BC_NOARG, BC_KEEPLINE);
|
||||||
|
Ctx__exit_block(ctx());
|
||||||
|
// Exception handler: call __exit__ with exception info, then re-raise
|
||||||
|
Ctx__emit_(ctx(), OP_PUSH_EXCEPTION, BC_NOARG, BC_KEEPLINE);
|
||||||
|
Ctx__emit_(ctx(), OP_LOAD_NONE, BC_NOARG, BC_KEEPLINE); // exc_type
|
||||||
|
Ctx__emit_(ctx(), OP_ROT_TWO, BC_NOARG, BC_KEEPLINE); // reorder: [cm, None, exc]
|
||||||
|
Ctx__emit_(ctx(), OP_LOAD_NONE, BC_NOARG, BC_KEEPLINE); // exc_tb
|
||||||
|
Ctx__emit_(ctx(), OP_WITH_EXIT, BC_NOARG, prev()->line);
|
||||||
|
Ctx__emit_(ctx(), OP_RE_RAISE, BC_NOARG, BC_KEEPLINE);
|
||||||
|
Ctx__patch_jump(ctx(), jump_patch);
|
||||||
Ctx__exit_block(ctx());
|
Ctx__exit_block(ctx());
|
||||||
} break;
|
} break;
|
||||||
/*************************************************/
|
/*************************************************/
|
||||||
|
|||||||
@ -1122,14 +1122,35 @@ __NEXT_STEP:
|
|||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
case OP_WITH_EXIT: {
|
case OP_WITH_EXIT: {
|
||||||
// [expr]
|
// Stack: [cm, exc_type, exc_val, exc_tb]
|
||||||
py_push(TOP());
|
// Call cm.__exit__(exc_type, exc_val, exc_tb)
|
||||||
|
py_Ref exc_tb = TOP();
|
||||||
|
py_Ref exc_val = SECOND();
|
||||||
|
py_Ref exc_type = THIRD();
|
||||||
|
py_Ref cm = FOURTH();
|
||||||
|
|
||||||
|
// Save all values from stack
|
||||||
|
py_TValue saved_cm = *cm;
|
||||||
|
py_TValue saved_exc_type = *exc_type;
|
||||||
|
py_TValue saved_exc_val = *exc_val;
|
||||||
|
py_TValue saved_exc_tb = *exc_tb;
|
||||||
|
self->stack.sp -= 4;
|
||||||
|
|
||||||
|
// Push cm and get __exit__ method
|
||||||
|
py_push(&saved_cm);
|
||||||
if(!py_pushmethod(__exit__)) {
|
if(!py_pushmethod(__exit__)) {
|
||||||
TypeError("'%t' object does not support the context manager protocol", TOP()->type);
|
TypeError("'%t' object does not support the context manager protocol", saved_cm.type);
|
||||||
goto __ERROR;
|
goto __ERROR;
|
||||||
}
|
}
|
||||||
if(!py_vectorcall(0, 0)) goto __ERROR;
|
|
||||||
POP();
|
// Push arguments: exc_type, exc_val, exc_tb
|
||||||
|
PUSH(&saved_exc_type);
|
||||||
|
PUSH(&saved_exc_val);
|
||||||
|
PUSH(&saved_exc_tb);
|
||||||
|
|
||||||
|
// Call __exit__(exc_type, exc_val, exc_tb)
|
||||||
|
if(!py_vectorcall(3, 0)) goto __ERROR;
|
||||||
|
py_pop(); // discard return value
|
||||||
DISPATCH();
|
DISPATCH();
|
||||||
}
|
}
|
||||||
///////////
|
///////////
|
||||||
|
|||||||
@ -1002,28 +1002,23 @@ static void register_array2d_view(py_Ref mod) {
|
|||||||
#include "pocketpy/xmacros/smallmap.h"
|
#include "pocketpy/xmacros/smallmap.h"
|
||||||
#undef SMALLMAP_T__SOURCE
|
#undef SMALLMAP_T__SOURCE
|
||||||
|
|
||||||
static py_TValue* c11_chunked_array2d__new_chunk(c11_chunked_array2d* self, c11_vec2i pos) {
|
static py_TValue* c11_chunked_array2d__new_chunk(c11_chunked_array2d* self, c11_vec2i pos, py_Ref context) {
|
||||||
#ifndef NDEBUG
|
|
||||||
bool exists = c11_chunked_array2d_chunks__contains(&self->chunks, pos);
|
bool exists = c11_chunked_array2d_chunks__contains(&self->chunks, pos);
|
||||||
assert(!exists);
|
if(exists) {
|
||||||
#endif
|
ValueError("chunk already exists at pos (%d, %d)", pos.x, pos.y);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
int chunk_numel = self->chunk_size * self->chunk_size + 1;
|
int chunk_numel = self->chunk_size * self->chunk_size + 1;
|
||||||
py_TValue* data = PK_MALLOC(sizeof(py_TValue) * chunk_numel);
|
py_TValue* data = PK_MALLOC(sizeof(py_TValue) * chunk_numel);
|
||||||
if(!py_isnone(&self->context_builder)) {
|
data[0] = *context;
|
||||||
py_newvec2i(&data[0], pos);
|
|
||||||
bool ok = py_call(&self->context_builder, 1, &data[0]);
|
|
||||||
if(!ok) {
|
|
||||||
PK_FREE(data);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
data[0] = *py_retval();
|
|
||||||
} else {
|
|
||||||
data[0] = *py_None();
|
|
||||||
}
|
|
||||||
memset(&data[1], 0, sizeof(py_TValue) * (chunk_numel - 1));
|
memset(&data[1], 0, sizeof(py_TValue) * (chunk_numel - 1));
|
||||||
c11_chunked_array2d_chunks__set(&self->chunks, pos, data);
|
c11_chunked_array2d_chunks__set(&self->chunks, pos, data);
|
||||||
self->last_visited.key = pos;
|
self->last_visited.key = pos;
|
||||||
self->last_visited.value = data;
|
self->last_visited.value = data;
|
||||||
|
// init data with default value
|
||||||
|
for(int i = 1; i < chunk_numel; i++) {
|
||||||
|
data[i] = self->default_T;
|
||||||
|
}
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1077,37 +1072,34 @@ static py_TValue* c11_chunked_array2d__parse_col_row(c11_chunked_array2d* self,
|
|||||||
py_Ref c11_chunked_array2d__get(c11_chunked_array2d* self, int col, int row) {
|
py_Ref c11_chunked_array2d__get(c11_chunked_array2d* self, int col, int row) {
|
||||||
c11_vec2i chunk_pos, local_pos;
|
c11_vec2i chunk_pos, local_pos;
|
||||||
py_TValue* data = c11_chunked_array2d__parse_col_row(self, col, row, &chunk_pos, &local_pos);
|
py_TValue* data = c11_chunked_array2d__parse_col_row(self, col, row, &chunk_pos, &local_pos);
|
||||||
if(data == NULL) return &self->default_T;
|
if(data == NULL) return NULL;
|
||||||
py_Ref retval = &data[1 + local_pos.y * self->chunk_size + local_pos.x];
|
return &data[1 + local_pos.y * self->chunk_size + local_pos.x];
|
||||||
if(py_isnil(retval)) return &self->default_T;
|
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool c11_chunked_array2d__set(c11_chunked_array2d* self, int col, int row, py_Ref value) {
|
bool c11_chunked_array2d__set(c11_chunked_array2d* self, int col, int row, py_Ref value) {
|
||||||
c11_vec2i chunk_pos, local_pos;
|
c11_vec2i chunk_pos, local_pos;
|
||||||
py_TValue* data = c11_chunked_array2d__parse_col_row(self, col, row, &chunk_pos, &local_pos);
|
py_TValue* data = c11_chunked_array2d__parse_col_row(self, col, row, &chunk_pos, &local_pos);
|
||||||
if(data == NULL) {
|
if(data == NULL) {
|
||||||
data = c11_chunked_array2d__new_chunk(self, chunk_pos);
|
if(self->auto_add_chunk) {
|
||||||
if(data == NULL) return false;
|
data = c11_chunked_array2d__new_chunk(self, chunk_pos, py_None());
|
||||||
|
if(data == NULL) return false;
|
||||||
|
} else {
|
||||||
|
return IndexError("(%d, %d) is out of bounds and !auto_add_chunk", col, row);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
data[1 + local_pos.y * self->chunk_size + local_pos.x] = *value;
|
data[1 + local_pos.y * self->chunk_size + local_pos.x] = *value;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void c11_chunked_array2d__del(c11_chunked_array2d* self, int col, int row) {
|
|
||||||
c11_vec2i chunk_pos, local_pos;
|
|
||||||
py_TValue* data = c11_chunked_array2d__parse_col_row(self, col, row, &chunk_pos, &local_pos);
|
|
||||||
if(data != NULL) data[1 + local_pos.y * self->chunk_size + local_pos.x] = *py_NIL();
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool chunked_array2d__new__(int argc, py_Ref argv) {
|
static bool chunked_array2d__new__(int argc, py_Ref argv) {
|
||||||
PY_CHECK_ARGC(4);
|
PY_CHECK_ARGC(4);
|
||||||
PY_CHECK_ARG_TYPE(1, tp_int);
|
PY_CHECK_ARG_TYPE(1, tp_int);
|
||||||
|
PY_CHECK_ARG_TYPE(3, tp_bool);
|
||||||
py_Type cls = py_totype(argv);
|
py_Type cls = py_totype(argv);
|
||||||
c11_chunked_array2d* self = py_newobject(py_retval(), cls, 0, sizeof(c11_chunked_array2d));
|
c11_chunked_array2d* self = py_newobject(py_retval(), cls, 0, sizeof(c11_chunked_array2d));
|
||||||
int chunk_size = py_toint(&argv[1]);
|
int chunk_size = py_toint(&argv[1]);
|
||||||
self->default_T = argv[2];
|
self->default_T = argv[2];
|
||||||
self->context_builder = argv[3];
|
self->auto_add_chunk = py_tobool(&argv[3]);
|
||||||
c11_chunked_array2d_chunks__ctor(&self->chunks);
|
c11_chunked_array2d_chunks__ctor(&self->chunks);
|
||||||
self->chunk_size = chunk_size;
|
self->chunk_size = chunk_size;
|
||||||
switch(chunk_size) {
|
switch(chunk_size) {
|
||||||
@ -1137,26 +1129,13 @@ static bool chunked_array2d_chunk_size(int argc, py_Ref argv) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool chunked_array2d_default(int argc, py_Ref argv) {
|
|
||||||
PY_CHECK_ARGC(1);
|
|
||||||
c11_chunked_array2d* self = py_touserdata(argv);
|
|
||||||
py_assign(py_retval(), &self->default_T);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool chunked_array2d_context_builder(int argc, py_Ref argv) {
|
|
||||||
PY_CHECK_ARGC(1);
|
|
||||||
c11_chunked_array2d* self = py_touserdata(argv);
|
|
||||||
py_assign(py_retval(), &self->context_builder);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool chunked_array2d__getitem__(int argc, py_Ref argv) {
|
static bool chunked_array2d__getitem__(int argc, py_Ref argv) {
|
||||||
PY_CHECK_ARGC(2);
|
PY_CHECK_ARGC(2);
|
||||||
PY_CHECK_ARG_TYPE(1, tp_vec2i);
|
PY_CHECK_ARG_TYPE(1, tp_vec2i);
|
||||||
c11_chunked_array2d* self = py_touserdata(argv);
|
c11_chunked_array2d* self = py_touserdata(argv);
|
||||||
c11_vec2i pos = py_tovec2i(&argv[1]);
|
c11_vec2i pos = py_tovec2i(&argv[1]);
|
||||||
py_Ref res = c11_chunked_array2d__get(self, pos.x, pos.y);
|
py_Ref res = c11_chunked_array2d__get(self, pos.x, pos.y);
|
||||||
|
if(res == NULL) return IndexError("(%d, %d) is out of bounds", pos.x, pos.y);
|
||||||
py_assign(py_retval(), res);
|
py_assign(py_retval(), res);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1172,16 +1151,6 @@ static bool chunked_array2d__setitem__(int argc, py_Ref argv) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool chunked_array2d__delitem__(int argc, py_Ref argv) {
|
|
||||||
PY_CHECK_ARGC(2);
|
|
||||||
PY_CHECK_ARG_TYPE(1, tp_vec2i);
|
|
||||||
c11_chunked_array2d* self = py_touserdata(argv);
|
|
||||||
c11_vec2i pos = py_tovec2i(&argv[1]);
|
|
||||||
c11_chunked_array2d__del(self, pos.x, pos.y);
|
|
||||||
py_newnone(py_retval());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool chunked_array2d__iter__(int argc, py_Ref argv) {
|
static bool chunked_array2d__iter__(int argc, py_Ref argv) {
|
||||||
PY_CHECK_ARGC(1);
|
PY_CHECK_ARGC(1);
|
||||||
c11_chunked_array2d* self = py_touserdata(argv);
|
c11_chunked_array2d* self = py_touserdata(argv);
|
||||||
@ -1258,13 +1227,13 @@ static bool chunked_array2d_world_to_chunk(int argc, py_Ref argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool chunked_array2d_add_chunk(int argc, py_Ref argv) {
|
static bool chunked_array2d_add_chunk(int argc, py_Ref argv) {
|
||||||
PY_CHECK_ARGC(2);
|
PY_CHECK_ARGC(3);
|
||||||
PY_CHECK_ARG_TYPE(1, tp_vec2i);
|
PY_CHECK_ARG_TYPE(1, tp_vec2i);
|
||||||
c11_chunked_array2d* self = py_touserdata(argv);
|
c11_chunked_array2d* self = py_touserdata(argv);
|
||||||
c11_vec2i pos = py_tovec2i(&argv[1]);
|
c11_vec2i pos = py_tovec2i(&argv[1]);
|
||||||
py_TValue* data = c11_chunked_array2d__new_chunk(self, pos);
|
py_TValue* data = c11_chunked_array2d__new_chunk(self, pos, &argv[2]);
|
||||||
if(data == NULL) return false;
|
if(data == NULL) return false;
|
||||||
py_assign(py_retval(), &data[0]); // context
|
py_newnone(py_retval());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1313,7 +1282,7 @@ static bool chunked_array2d_get_context(int argc, py_Ref argv) {
|
|||||||
c11_vec2i pos = py_tovec2i(&argv[1]);
|
c11_vec2i pos = py_tovec2i(&argv[1]);
|
||||||
py_TValue* data = c11_chunked_array2d_chunks__get(&self->chunks, pos, NULL);
|
py_TValue* data = c11_chunked_array2d_chunks__get(&self->chunks, pos, NULL);
|
||||||
if(data == NULL) {
|
if(data == NULL) {
|
||||||
py_newnone(py_retval());
|
return IndexError("no chunk found at (%d, %d)", pos.x, pos.y);
|
||||||
} else {
|
} else {
|
||||||
py_assign(py_retval(), &data[0]);
|
py_assign(py_retval(), &data[0]);
|
||||||
}
|
}
|
||||||
@ -1328,7 +1297,6 @@ void c11_chunked_array2d__dtor(c11_chunked_array2d* self) {
|
|||||||
void c11_chunked_array2d__mark(void* ud, c11_vector* p_stack) {
|
void c11_chunked_array2d__mark(void* ud, c11_vector* p_stack) {
|
||||||
c11_chunked_array2d* self = ud;
|
c11_chunked_array2d* self = ud;
|
||||||
pk__mark_value(&self->default_T);
|
pk__mark_value(&self->default_T);
|
||||||
pk__mark_value(&self->context_builder);
|
|
||||||
int chunk_numel = self->chunk_size * self->chunk_size + 1;
|
int chunk_numel = self->chunk_size * self->chunk_size + 1;
|
||||||
for(int i = 0; i < self->chunks.length; i++) {
|
for(int i = 0; i < self->chunks.length; i++) {
|
||||||
py_TValue* data = c11__getitem(c11_chunked_array2d_chunks_KV, &self->chunks, i).value;
|
py_TValue* data = c11__getitem(c11_chunked_array2d_chunks_KV, &self->chunks, i).value;
|
||||||
@ -1408,16 +1376,13 @@ static void register_chunked_array2d(py_Ref mod) {
|
|||||||
assert(type == tp_chunked_array2d);
|
assert(type == tp_chunked_array2d);
|
||||||
|
|
||||||
py_bind(py_tpobject(type),
|
py_bind(py_tpobject(type),
|
||||||
"__new__(cls, chunk_size, default=None, context_builder=None)",
|
"__new__(cls, chunk_size, default=None, auto_add_chunk=True)",
|
||||||
chunked_array2d__new__);
|
chunked_array2d__new__);
|
||||||
|
|
||||||
py_bindproperty(type, "chunk_size", chunked_array2d_chunk_size, NULL);
|
py_bindproperty(type, "chunk_size", chunked_array2d_chunk_size, NULL);
|
||||||
py_bindproperty(type, "default", chunked_array2d_default, NULL);
|
|
||||||
py_bindproperty(type, "context_builder", chunked_array2d_context_builder, NULL);
|
|
||||||
|
|
||||||
py_bindmagic(type, __getitem__, chunked_array2d__getitem__);
|
py_bindmagic(type, __getitem__, chunked_array2d__getitem__);
|
||||||
py_bindmagic(type, __setitem__, chunked_array2d__setitem__);
|
py_bindmagic(type, __setitem__, chunked_array2d__setitem__);
|
||||||
py_bindmagic(type, __delitem__, chunked_array2d__delitem__);
|
|
||||||
py_bindmagic(type, __iter__, chunked_array2d__iter__);
|
py_bindmagic(type, __iter__, chunked_array2d__iter__);
|
||||||
py_bindmagic(type, __len__, chunked_array2d__len__);
|
py_bindmagic(type, __len__, chunked_array2d__len__);
|
||||||
|
|
||||||
|
|||||||
@ -77,6 +77,17 @@ c11_vec3i py_tovec3i(py_Ref self) {
|
|||||||
return self->_vec3i;
|
return self->_vec3i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void py_newvec4i(py_OutRef out, c11_vec4i v) {
|
||||||
|
out->type = tp_vec4i;
|
||||||
|
out->is_ptr = false;
|
||||||
|
out->_vec4i = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
c11_vec4i py_tovec4i(py_Ref self) {
|
||||||
|
assert(self->type == tp_vec4i);
|
||||||
|
return self->_vec4i;
|
||||||
|
}
|
||||||
|
|
||||||
c11_mat3x3* py_newmat3x3(py_OutRef out) {
|
c11_mat3x3* py_newmat3x3(py_OutRef out) {
|
||||||
return py_newobject(out, tp_mat3x3, 0, sizeof(c11_mat3x3));
|
return py_newobject(out, tp_mat3x3, 0, sizeof(c11_mat3x3));
|
||||||
}
|
}
|
||||||
@ -310,6 +321,7 @@ DEF_VECTOR_OPS(3)
|
|||||||
|
|
||||||
DEF_VECTOR_INT_OPS(2)
|
DEF_VECTOR_INT_OPS(2)
|
||||||
DEF_VECTOR_INT_OPS(3)
|
DEF_VECTOR_INT_OPS(3)
|
||||||
|
DEF_VECTOR_INT_OPS(4)
|
||||||
|
|
||||||
static bool vec2i__hash__(int argc, py_Ref argv) {
|
static bool vec2i__hash__(int argc, py_Ref argv) {
|
||||||
PY_CHECK_ARGC(1);
|
PY_CHECK_ARGC(1);
|
||||||
@ -332,6 +344,18 @@ static bool vec3i__hash__(int argc, py_Ref argv) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool vec4i__hash__(int argc, py_Ref argv) {
|
||||||
|
PY_CHECK_ARGC(1);
|
||||||
|
c11_vec4i v = py_tovec4i(argv);
|
||||||
|
uint64_t x_part = (uint32_t)v.x & 0xFFFF;
|
||||||
|
uint64_t y_part = (uint32_t)v.y & 0xFFFF;
|
||||||
|
uint64_t z_part = (uint32_t)v.z & 0xFFFF;
|
||||||
|
uint64_t w_part = (uint32_t)v.w & 0xFFFF;
|
||||||
|
uint64_t hash = (x_part << 48) | (y_part << 32) | (z_part << 16) | w_part;
|
||||||
|
py_newint(py_retval(), (py_i64)hash);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool vec2__repr__(int argc, py_Ref argv) {
|
static bool vec2__repr__(int argc, py_Ref argv) {
|
||||||
PY_CHECK_ARGC(1);
|
PY_CHECK_ARGC(1);
|
||||||
char buf[64];
|
char buf[64];
|
||||||
@ -799,6 +823,21 @@ DEFINE_VEC_FIELD(vec3i, int, py_i64, x)
|
|||||||
DEFINE_VEC_FIELD(vec3i, int, py_i64, y)
|
DEFINE_VEC_FIELD(vec3i, int, py_i64, y)
|
||||||
DEFINE_VEC_FIELD(vec3i, int, py_i64, z)
|
DEFINE_VEC_FIELD(vec3i, int, py_i64, z)
|
||||||
|
|
||||||
|
/* vec4i */
|
||||||
|
static bool vec4i__repr__(int argc, py_Ref argv) {
|
||||||
|
PY_CHECK_ARGC(1);
|
||||||
|
c11_vec4i data = py_tovec4i(argv);
|
||||||
|
char buf[64];
|
||||||
|
int size = snprintf(buf, 64, "vec4i(%d, %d, %d, %d)", data.x, data.y, data.z, data.w);
|
||||||
|
py_newstrv(py_retval(), (c11_sv){buf, size});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_VEC_FIELD(vec4i, int, py_i64, x)
|
||||||
|
DEFINE_VEC_FIELD(vec4i, int, py_i64, y)
|
||||||
|
DEFINE_VEC_FIELD(vec4i, int, py_i64, z)
|
||||||
|
DEFINE_VEC_FIELD(vec4i, int, py_i64, w)
|
||||||
|
|
||||||
/* vec3 */
|
/* vec3 */
|
||||||
static bool vec3__repr__(int argc, py_Ref argv) {
|
static bool vec3__repr__(int argc, py_Ref argv) {
|
||||||
PY_CHECK_ARGC(1);
|
PY_CHECK_ARGC(1);
|
||||||
@ -1113,6 +1152,7 @@ void pk__add_module_vmath() {
|
|||||||
py_Type vec3 = pk_newtype("vec3", tp_object, mod, NULL, false, true);
|
py_Type vec3 = pk_newtype("vec3", tp_object, mod, NULL, false, true);
|
||||||
py_Type vec2i = pk_newtype("vec2i", tp_object, mod, NULL, false, true);
|
py_Type vec2i = pk_newtype("vec2i", tp_object, mod, NULL, false, true);
|
||||||
py_Type vec3i = pk_newtype("vec3i", tp_object, mod, NULL, false, true);
|
py_Type vec3i = pk_newtype("vec3i", tp_object, mod, NULL, false, true);
|
||||||
|
py_Type vec4i = pk_newtype("vec4i", tp_object, mod, NULL, false, true);
|
||||||
py_Type mat3x3 = pk_newtype("mat3x3", tp_object, mod, NULL, false, true);
|
py_Type mat3x3 = pk_newtype("mat3x3", tp_object, mod, NULL, false, true);
|
||||||
py_Type color32 = pk_newtype("color32", tp_object, mod, NULL, false, true);
|
py_Type color32 = pk_newtype("color32", tp_object, mod, NULL, false, true);
|
||||||
|
|
||||||
@ -1120,15 +1160,17 @@ void pk__add_module_vmath() {
|
|||||||
py_setdict(mod, py_name("vec3"), py_tpobject(vec3));
|
py_setdict(mod, py_name("vec3"), py_tpobject(vec3));
|
||||||
py_setdict(mod, py_name("vec2i"), py_tpobject(vec2i));
|
py_setdict(mod, py_name("vec2i"), py_tpobject(vec2i));
|
||||||
py_setdict(mod, py_name("vec3i"), py_tpobject(vec3i));
|
py_setdict(mod, py_name("vec3i"), py_tpobject(vec3i));
|
||||||
|
py_setdict(mod, py_name("vec4i"), py_tpobject(vec4i));
|
||||||
py_setdict(mod, py_name("mat3x3"), py_tpobject(mat3x3));
|
py_setdict(mod, py_name("mat3x3"), py_tpobject(mat3x3));
|
||||||
py_setdict(mod, py_name("color32"), py_tpobject(color32));
|
py_setdict(mod, py_name("color32"), py_tpobject(color32));
|
||||||
|
|
||||||
assert(vec2 == tp_vec2);
|
c11__rtassert(vec2 == tp_vec2);
|
||||||
assert(vec3 == tp_vec3);
|
c11__rtassert(vec3 == tp_vec3);
|
||||||
assert(vec2i == tp_vec2i);
|
c11__rtassert(vec2i == tp_vec2i);
|
||||||
assert(vec3i == tp_vec3i);
|
c11__rtassert(vec3i == tp_vec3i);
|
||||||
assert(mat3x3 == tp_mat3x3);
|
c11__rtassert(vec4i == tp_vec4i);
|
||||||
assert(color32 == tp_color32);
|
c11__rtassert(mat3x3 == tp_mat3x3);
|
||||||
|
c11__rtassert(color32 == tp_color32);
|
||||||
|
|
||||||
/* vec2 */
|
/* vec2 */
|
||||||
py_bindmagic(vec2, __new__, vec2__new__);
|
py_bindmagic(vec2, __new__, vec2__new__);
|
||||||
@ -1240,6 +1282,35 @@ void pk__add_module_vmath() {
|
|||||||
{1, 1, 1}
|
{1, 1, 1}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/* vec4i */
|
||||||
|
py_bindmagic(vec4i, __new__, vec4i__new__);
|
||||||
|
py_bindmagic(vec4i, __repr__, vec4i__repr__);
|
||||||
|
py_bindmagic(vec4i, __add__, vec4i__add__);
|
||||||
|
py_bindmagic(vec4i, __sub__, vec4i__sub__);
|
||||||
|
py_bindmagic(vec4i, __mul__, vec4i__mul__);
|
||||||
|
py_bindmagic(vec4i, __floordiv__, vec4i__floordiv__);
|
||||||
|
py_bindmagic(vec4i, __eq__, vec4i__eq__);
|
||||||
|
py_bindmagic(vec4i, __ne__, vec4i__ne__);
|
||||||
|
py_bindmagic(vec4i, __hash__, vec4i__hash__);
|
||||||
|
py_bindproperty(vec4i, "x", vec4i__x, NULL);
|
||||||
|
py_bindproperty(vec4i, "y", vec4i__y, NULL);
|
||||||
|
py_bindproperty(vec4i, "z", vec4i__z, NULL);
|
||||||
|
py_bindproperty(vec4i, "w", vec4i__w, NULL);
|
||||||
|
py_bindmethod(vec4i, "with_x", vec4i__with_x);
|
||||||
|
py_bindmethod(vec4i, "with_y", vec4i__with_y);
|
||||||
|
py_bindmethod(vec4i, "with_z", vec4i__with_z);
|
||||||
|
py_bindmethod(vec4i, "with_w", vec4i__with_w);
|
||||||
|
py_bindmethod(vec4i, "dot", vec4i_dot);
|
||||||
|
|
||||||
|
py_newvec4i(_const(vec4i, "ZERO"),
|
||||||
|
(c11_vec4i){
|
||||||
|
{0, 0, 0, 0}
|
||||||
|
});
|
||||||
|
py_newvec4i(_const(vec4i, "ONE"),
|
||||||
|
(c11_vec4i){
|
||||||
|
{1, 1, 1, 1}
|
||||||
|
});
|
||||||
|
|
||||||
/* vec3 */
|
/* vec3 */
|
||||||
py_bindmagic(vec3, __new__, vec3__new__);
|
py_bindmagic(vec3, __new__, vec3__new__);
|
||||||
py_bindmagic(vec3, __add__, vec3__add__);
|
py_bindmagic(vec3, __add__, vec3__add__);
|
||||||
|
|||||||
@ -27,4 +27,29 @@ assert path == ['enter', 'in', 'exit']
|
|||||||
|
|
||||||
path.clear()
|
path.clear()
|
||||||
|
|
||||||
|
# Test that __exit__ is called even when an exception occurs
|
||||||
|
class B:
|
||||||
|
def __init__(self):
|
||||||
|
self.path = []
|
||||||
|
|
||||||
|
def __enter__(self):
|
||||||
|
path.append('enter')
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||||
|
path.append('exit')
|
||||||
|
if exc_type is not None:
|
||||||
|
path.append('exception')
|
||||||
|
return False # propagate exception
|
||||||
|
|
||||||
|
try:
|
||||||
|
with B():
|
||||||
|
path.append('before_raise')
|
||||||
|
raise ValueError('test')
|
||||||
|
path.append('after_raise') # should not be reached
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
assert path == ['enter', 'before_raise', 'exit', 'exception'], f"Expected ['enter', 'before_raise', 'exit', 'exception'], got {path}"
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -93,15 +93,6 @@ assert data.view() == array2d.fromlist([
|
|||||||
assert data.view()[vec2i(1,1)-data.view().origin] == data[vec2i(1,1)]
|
assert data.view()[vec2i(1,1)-data.view().origin] == data[vec2i(1,1)]
|
||||||
assert data.view()[vec2i(3,3)-data.view().origin] == data[vec2i(3,3)]
|
assert data.view()[vec2i(3,3)-data.view().origin] == data[vec2i(3,3)]
|
||||||
|
|
||||||
# ====chunked_array2d__delitem__
|
|
||||||
data = chunked_array2d(4)
|
|
||||||
for i in range(10):
|
|
||||||
for j in range(10):
|
|
||||||
data[vec2i(i,j)] = 10
|
|
||||||
|
|
||||||
del data[vec2i(0,0)]
|
|
||||||
assert data[vec2i(0,0)] == data.default
|
|
||||||
|
|
||||||
# ====chunked_array2d__len__
|
# ====chunked_array2d__len__
|
||||||
data = chunked_array2d(4)
|
data = chunked_array2d(4)
|
||||||
for i in range(10):
|
for i in range(10):
|
||||||
|
|||||||
@ -2,66 +2,18 @@ import array2d
|
|||||||
from vmath import vec2i
|
from vmath import vec2i
|
||||||
|
|
||||||
|
|
||||||
def on_builder(a:vec2i):
|
|
||||||
return str(a)
|
|
||||||
pass
|
|
||||||
|
|
||||||
default = 0
|
default = 0
|
||||||
a = array2d.chunked_array2d(16, default,on_builder)
|
a = array2d.chunked_array2d(16, default, auto_add_chunk=False)
|
||||||
assert a.chunk_size == 16
|
assert a.chunk_size == 16
|
||||||
|
|
||||||
|
a.add_chunk(vec2i(1, 1), 5.0)
|
||||||
a[vec2i(16, 16)] = 16
|
a[vec2i(16, 16)] = 16
|
||||||
a[vec2i(15, 16)] = 15
|
a[vec2i(17, 16)] = 15
|
||||||
assert a[vec2i(16, 16)] == 16
|
assert a[vec2i(16, 16)] == 16
|
||||||
assert a[vec2i(15, 16)] == 15
|
assert a[vec2i(17, 16)] == 15
|
||||||
assert a[vec2i(16, 15)] == default
|
assert a[vec2i(17, 20)] == default
|
||||||
|
|
||||||
a1,a2=a.world_to_chunk(vec2i(15,16))
|
a1, _ = a.world_to_chunk(vec2i(16, 16))
|
||||||
|
|
||||||
assert a.remove_chunk(a1)== True
|
assert a.get_context(vec2i(1,1)) == 5.0
|
||||||
assert a[vec2i(15, 16)] == default
|
assert a.remove_chunk(a1)
|
||||||
|
|
||||||
assert a.get_context(vec2i(1,1))==on_builder(vec2i(1,1))
|
|
||||||
|
|
||||||
assert a.view().tolist()==[
|
|
||||||
[16 if i==0 and j==0 else 0 for j in range(16)] for i in range(16)
|
|
||||||
]
|
|
||||||
assert a.view_rect(vec2i(15,15),4,4).tolist()==[
|
|
||||||
[0,0,0,0],
|
|
||||||
[0,16,0,0],
|
|
||||||
[0,0,0,0],
|
|
||||||
[0,0,0,0]
|
|
||||||
]
|
|
||||||
a[vec2i(15, 16)] = 15
|
|
||||||
assert a.view_chunk(a1).tolist()==[
|
|
||||||
[15 if i==0 and j==15 else 0 for j in range(16)] for i in range(16)
|
|
||||||
]
|
|
||||||
a.clear()
|
|
||||||
|
|
||||||
assert a[vec2i(16, 16)] == default
|
|
||||||
assert a[vec2i(15, 16)] == default
|
|
||||||
assert a[vec2i(16, 15)] == default
|
|
||||||
|
|
||||||
from typing import Any
|
|
||||||
|
|
||||||
a = array2d.chunked_array2d[int, Any](4, default=0, context_builder=lambda x: 1)
|
|
||||||
assert a.chunk_size == 4
|
|
||||||
|
|
||||||
assert a.add_chunk(vec2i(0, 1)) == 1
|
|
||||||
assert a.get_context(vec2i(0, 1)) == 1
|
|
||||||
|
|
||||||
assert a.move_chunk(vec2i(2, 1), vec2i(1, 1)) == False
|
|
||||||
assert a.move_chunk(vec2i(0, 1), vec2i(1, 1)) == True
|
|
||||||
|
|
||||||
assert a.get_context(vec2i(1, 1)) == 1
|
|
||||||
assert a.get_context(vec2i(0, 1)) == None
|
|
||||||
|
|
||||||
b = a.copy()
|
|
||||||
assert a is not b
|
|
||||||
assert a.chunk_size == b.chunk_size
|
|
||||||
assert a.default == b.default
|
|
||||||
assert a.context_builder == b.context_builder
|
|
||||||
assert (a.view() == b.view()).all()
|
|
||||||
|
|
||||||
for pos, ctx in a:
|
|
||||||
assert b.get_context(pos) == ctx
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user