Compare commits

..

No commits in common. "1e17b494034d365332e36986035923fad38bd80b" and "f95b76520783066ed0341f748749be47da88d80b" have entirely different histories.

9 changed files with 27 additions and 155 deletions

View File

@ -1,5 +1,4 @@
#include "pocketpy.h"
#include <stdio.h>
#define CUTE_PNG_IMPLEMENTATION
#include "cute_png.h"
@ -10,7 +9,7 @@ static bool cute_png_loads(int argc, py_Ref argv) {
int size;
unsigned char* data = py_tobytes(argv, &size);
cp_image_t image = cp_load_png_mem(data, size);
if(image.pix == NULL) return ValueError("cp_load_png_mem() failed");
if(image.pix == NULL) return ValueError("cute_png: %s", cp_error_reason);
py_newarray2d(py_retval(), image.w, image.h);
for(int y = 0; y < image.h; y++) {
for(int x = 0; x < image.w; x++) {
@ -74,19 +73,7 @@ static bool cute_png_Image__from_bytes_STATIC(int argc, py_Ref argv) {
int size;
unsigned char* data = py_tobytes(argv, &size);
cp_image_t image = cp_load_png_mem(data, size);
if(image.pix == NULL) return ValueError("cp_load_png_mem() failed");
cp_image_t* ud =
py_newobject(py_retval(), py_gettype("cute_png", py_name("Image")), 0, sizeof(cp_image_t));
*ud = image;
return true;
}
static bool cute_png_Image__from_file_STATIC(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
PY_CHECK_ARG_TYPE(0, tp_str);
const char* path = py_tostr(argv);
cp_image_t image = cp_load_png(path);
if(image.pix == NULL) return ValueError("cp_load_png() failed");
if(image.pix == NULL) return ValueError("cute_png: %s", cp_error_reason);
cp_image_t* ud =
py_newobject(py_retval(), py_gettype("cute_png", py_name("Image")), 0, sizeof(cp_image_t));
*ud = image;
@ -160,41 +147,10 @@ static bool cute_png_Image__clear(int argc, py_Ref argv) {
return true;
}
static bool cute_png_Image__to_png_bytes(int argc, py_Ref argv) {
static bool cute_png_Image__to_rgb565_bytes(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
cp_image_t* image = py_touserdata(argv);
cp_saved_png_t saved_image = cp_save_png_to_memory(image);
assert(saved_image.data != NULL);
unsigned char* data = py_newbytes(py_retval(), saved_image.size);
memcpy(data, saved_image.data, saved_image.size);
CUTE_PNG_FREE(saved_image.data);
return true;
}
static bool cute_png_Image__to_png_file(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
PY_CHECK_ARG_TYPE(1, tp_str);
cp_image_t* image = py_touserdata(argv);
const char* path = py_tostr(py_arg(1));
FILE* fp = fopen(path, "wb");
if(fp == NULL) return OSError("cannot open file '%s' for writing", path);
cp_saved_png_t saved_image = cp_save_png_to_memory(image);
assert(saved_image.data != NULL);
size_t size = fwrite(saved_image.data, saved_image.size, 1, fp);
CUTE_PNG_FREE(saved_image.data);
fclose(fp);
py_newint(py_retval(), size);
return true;
}
static bool cute_png_Image__to_rgb565_file(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
PY_CHECK_ARG_TYPE(1, tp_str);
cp_image_t* image = py_touserdata(argv);
const char* path = py_tostr(py_arg(1));
FILE* fp = fopen(path, "wb");
if(fp == NULL) return OSError("cannot open file '%s' for writing", path);
size_t size = 0;
unsigned char* data = py_newbytes(py_retval(), image->w * image->h * 2);
for(int y = 0; y < image->h; y++) {
for(int x = 0; x < image->w; x++) {
size_t idx = y * image->w + x;
@ -204,15 +160,21 @@ static bool cute_png_Image__to_rgb565_file(int argc, py_Ref argv) {
uint16_t b = (pixel.b >> 3) & 0x1F;
uint16_t rgb565 = (r << 11) | (g << 5) | b;
// use little-endian
size_t delta = fwrite(&rgb565, 1, 2, fp);
size += delta;
if(delta != 2) {
py_newint(py_retval(), size);
return true;
}
data[idx * 2 + 0] = rgb565 & 0xFF;
data[idx * 2 + 1] = (rgb565 >> 8) & 0xFF;
}
}
py_newint(py_retval(), size);
return true;
}
static bool cute_png_Image__to_png_bytes(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
cp_image_t* image = py_touserdata(argv);
cp_saved_png_t saved_image = cp_save_png_to_memory(image);
assert(saved_image.data != NULL);
unsigned char* data = py_newbytes(py_retval(), saved_image.size);
memcpy(data, saved_image.data, saved_image.size);
CUTE_PNG_FREE(saved_image.data);
return true;
}
@ -226,7 +188,6 @@ void pk__add_module_cute_png() {
py_bindmethod(tp_image, "__new__", cute_png_Image__new__);
py_bindstaticmethod(tp_image, "from_bytes", cute_png_Image__from_bytes_STATIC);
py_bindstaticmethod(tp_image, "from_file", cute_png_Image__from_file_STATIC);
py_bindproperty(tp_image, "width", cute_png_Image__width, NULL);
py_bindproperty(tp_image, "height", cute_png_Image__height, NULL);
@ -235,7 +196,6 @@ void pk__add_module_cute_png() {
py_bindmethod(tp_image, "getpixel", cute_png_Image__getpixel);
py_bindmethod(tp_image, "clear", cute_png_Image__clear);
py_bindmethod(tp_image, "to_rgb565_bytes", cute_png_Image__to_rgb565_bytes);
py_bindmethod(tp_image, "to_png_bytes", cute_png_Image__to_png_bytes);
py_bindmethod(tp_image, "to_png_file", cute_png_Image__to_png_file);
py_bindmethod(tp_image, "to_rgb565_file", cute_png_Image__to_rgb565_file);
}

View File

@ -2,7 +2,6 @@
#include "pocketpy/common/vector.h"
#include "pocketpy/objects/base.h"
#include <stdio.h>
typedef struct {
uint64_t hash;
@ -23,9 +22,3 @@ typedef c11_vector List;
void c11_chunked_array2d__mark(void* ud, c11_vector* p_stack);
void function__gc_mark(void* ud, c11_vector* p_stack);
typedef struct {
FILE* file; // cute_png will cast the whole userdata to FILE**
const char* path;
const char* mode;
} io_FileIO;

View File

@ -11,17 +11,13 @@ class Image:
@staticmethod
def from_bytes(data: bytes) -> "Image": ...
@staticmethod
def from_file(path: str) -> "Image": ...
def setpixel(self, x: int, y: int, color: color32) -> None: ...
def getpixel(self, x: int, y: int) -> color32: ...
def clear(self, color: color32) -> None: ...
def to_rgb565_bytes(self) -> bytes: ...
def to_png_bytes(self) -> bytes: ...
def to_png_file(self, path: str) -> int: ...
def to_rgb565_file(self, path: str) -> int: ...
def loads(data: bytes) -> array2d[color32]: ...
def dumps(image: array2d[color32]) -> bytes: ...

View File

@ -1,17 +0,0 @@
class FileIO:
def __new__(cls, file: str, mode: str) -> "FileIO": ...
def __enter__(self) -> "FileIO": ...
def __exit__(self) -> None: ...
def read(self, size: int | None = None) -> bytes: ...
def write(self, data: bytes) -> int: ...
def close(self) -> None: ...
def tell(self) -> int: ...
def seek(self, offset: int, whence: int) -> None: ...
def flush(self) -> None: ...
SEEK_SET: int
SEEK_CUR: int
SEEK_END: int

View File

@ -580,7 +580,6 @@ FrameResult VM__vectorcall(VM* self, uint16_t argc, uint16_t kwargc, bool opcall
// [cls, NULL, args..., kwargs...]
py_Ref new_f = py_tpfindmagic(py_totype(p0), __new__);
assert(new_f && py_isnil(p0 + 1));
bool is_default_new = new_f->type == tp_nativefunc && new_f->_cfunc == pk__object_new;
// prepare a copy of args and kwargs
int span = self->stack.sp - argv;
@ -604,13 +603,6 @@ FrameResult VM__vectorcall(VM* self, uint16_t argc, uint16_t kwargc, bool opcall
// [__init__, self, args..., kwargs...]
if(VM__vectorcall(self, argc, kwargc, false) == RES_ERROR) return RES_ERROR;
*py_retval() = p0[1]; // restore the new instance
} else {
if(is_default_new) {
if(argc != 0 || kwargc != 0) {
TypeError("%t() takes no arguments", py_totype(p0));
return RES_ERROR;
}
}
}
// reset the stack
self->stack.sp = p0;

View File

@ -1,6 +1,5 @@
#include "pocketpy/objects/base.h"
#include "pocketpy/pocketpy.h"
#include "pocketpy/interpreter/types.h"
#include "pocketpy/interpreter/vm.h"
#if PK_ENABLE_OS
@ -102,6 +101,12 @@ void pk__add_module_os() {
py_newdict(py_emplacedict(mod, py_name("environ")));
}
typedef struct {
const char* path;
const char* mode;
FILE* file;
} io_FileIO;
static bool io_FileIO__new__(int argc, py_Ref argv) {
// __new__(cls, file, mode)
PY_CHECK_ARGC(3);
@ -208,14 +213,6 @@ static bool io_FileIO_write(int argc, py_Ref argv) {
return true;
}
static bool io_FileIO_flush(int argc, py_Ref argv) {
PY_CHECK_ARGC(1);
io_FileIO* ud = py_touserdata(py_arg(0));
fflush(ud->file);
py_newnone(py_retval());
return true;
}
void pk__add_module_io() {
py_Ref mod = py_newmodule("io");
@ -229,7 +226,6 @@ void pk__add_module_io() {
py_bindmethod(FileIO, "close", io_FileIO_close);
py_bindmethod(FileIO, "tell", io_FileIO_tell);
py_bindmethod(FileIO, "seek", io_FileIO_seek);
py_bindmethod(FileIO, "flush", io_FileIO_flush);
py_newint(py_emplacedict(mod, py_name("SEEK_SET")), SEEK_SET);
py_newint(py_emplacedict(mod, py_name("SEEK_CUR")), SEEK_CUR);

View File

@ -167,26 +167,8 @@ static bool list__setitem__(int argc, py_Ref argv) {
static bool list__delitem__(int argc, py_Ref argv) {
PY_CHECK_ARGC(2);
List* self = py_touserdata(py_arg(0));
if(py_istype(py_arg(1), tp_slice)) {
int start, stop, step;
bool ok = pk__parse_int_slice(py_arg(1), self->length, &start, &stop, &step);
if(!ok) return false;
if(step != 1) return ValueError("slice step must be 1 for deletion");
int n = stop - start;
if(n > 0) {
py_TValue* p = self->data;
for(int i = stop; i < self->length; i++) {
p[start + i - stop] = p[i];
}
self->length -= n;
}
py_newnone(py_retval());
return true;
}
PY_CHECK_ARG_TYPE(1, tp_int);
List* self = py_touserdata(py_arg(0));
int index = py_toint(py_arg(1));
if(!pk__normalize_index(&index, self->length)) return false;
c11_vector__erase(py_TValue, self, index);

View File

@ -160,16 +160,6 @@ b = [(1, 2), (3, 3), (5, 1)]
b.sort(key=lambda x:x[1])
assert b == [(5, 1), (1, 2), (3,3)]
# test del slice
a = [1, 2, 3, 4]
b = a.copy(); del b[:2]; assert b == [3, 4]
b = a.copy(); del b[1:3]; assert b == [1, 4]
b = a.copy(); del b[2:]; assert b == [1, 2]
b = a.copy(); del b[:-1]; assert b == [4]
b = a.copy(); del b[-1:]; assert b == [1, 2, 3]
b = a.copy(); del b[:]; assert b == []
assert a == [1, 2, 3, 4]
# test cyclic reference
# a = []
# a.append(0)

View File

@ -135,24 +135,4 @@ assert MyClass.b == 1
assert MyClass.c == 2
assert MyClass.d == 3
assert MyClass(1, 2).m == 1
class E: pass
try:
E(1,2,3)
exit(1)
except TypeError:
pass
class E1:
def __new__(cls, a, b):
o = object.__new__(cls)
o.a = a
o.b = b
return o
def sum(self):
return self.a + self.b
e1 = E1(3,4)
assert e1.sum() == 7
assert MyClass(1, 2).m == 1