From 3eeaeaa65d1ca1a4a581a6d7b327ee33cafcad89 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Mon, 16 Dec 2024 20:40:04 +0800 Subject: [PATCH] add `io` module and `open` --- benchmarks/ldtk_json.py | 13 +---- include/pocketpy/interpreter/modules.h | 2 + src/interpreter/vm.c | 1 + src/modules/os.c | 80 ++++++++++++++++++++++++-- 4 files changed, 81 insertions(+), 15 deletions(-) diff --git a/benchmarks/ldtk_json.py b/benchmarks/ldtk_json.py index 1c9f82ee..5f2523b6 100644 --- a/benchmarks/ldtk_json.py +++ b/benchmarks/ldtk_json.py @@ -1,5 +1,4 @@ -exit(0) - +import os os.chdir('benchmarks') import json @@ -8,8 +7,8 @@ _2489KB = 'WorldMap_GridVania_layout.ldtk' _1093KB = 'WorldMap_Free_layout.ldtk' _339KB = 'Typical_2D_platformer_example.ldtk' -with open(f'res/{_2489KB}', 'r') as f: - json_content = f.read() +with open(f'res/{_2489KB}', 'rb') as f: + json_content = f.read().decode() data: dict = json.loads(json_content) assert isinstance(data, dict) @@ -19,9 +18,3 @@ dumped: str = json.dumps(data) loaded: dict = json.loads(dumped) assert len(data) == len(loaded) assert data == loaded - -#### very very slow!! DO NOT RUN IT -# import pickle -# data_pickled: bytes = pickle.dumps(data) -# assert isinstance(data_pickled, bytes) -# assert pickle.loads(data_pickled) == data \ No newline at end of file diff --git a/include/pocketpy/interpreter/modules.h b/include/pocketpy/interpreter/modules.h index 28cf10ab..fc578af5 100644 --- a/include/pocketpy/interpreter/modules.h +++ b/include/pocketpy/interpreter/modules.h @@ -2,6 +2,8 @@ void pk__add_module_os(); void pk__add_module_sys(); +void pk__add_module_io(); + void pk__add_module_math(); void pk__add_module_dis(); void pk__add_module_random(); diff --git a/src/interpreter/vm.c b/src/interpreter/vm.c index 138e3557..3a513d47 100644 --- a/src/interpreter/vm.c +++ b/src/interpreter/vm.c @@ -206,6 +206,7 @@ void VM__ctor(VM* self) { // add modules pk__add_module_os(); pk__add_module_sys(); + pk__add_module_io(); pk__add_module_math(); pk__add_module_dis(); pk__add_module_random(); diff --git a/src/modules/os.c b/src/modules/os.c index ccc013f3..747b9f87 100644 --- a/src/modules/os.c +++ b/src/modules/os.c @@ -1,9 +1,7 @@ +#include "pocketpy/objects/base.h" #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 #if PY_SYS_PLATFORM == 0 #include @@ -68,4 +66,76 @@ void pk__add_module_sys() { py_newstr(py_emplacedict(mod, py_name("platform")), PY_SYS_PLATFORM_STRING); py_newstr(py_emplacedict(mod, py_name("version")), PK_VERSION); py_newlist(py_emplacedict(mod, py_name("argv"))); -} \ No newline at end of file +} + +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); + PY_CHECK_ARG_TYPE(1, tp_str); + PY_CHECK_ARG_TYPE(2, tp_str); + py_Type cls = py_totype(argv); + io_FileIO* ud = py_newobject(py_retval(), cls, 0, sizeof(io_FileIO)); + ud->path = py_tostr(py_arg(1)); + ud->mode = py_tostr(py_arg(2)); + ud->file = fopen(ud->path, ud->mode); + if(ud->file == NULL) { + const char* msg = strerror(errno); + return IOError("[Errno %d] %s: %s", errno, msg, ud->path); + } + return true; +} + +static bool io_FileIO__enter__(int argc, py_Ref argv) { + py_assign(py_retval(), py_arg(0)); + return true; +} + +static bool io_FileIO__exit__(int argc, py_Ref argv) { + io_FileIO* ud = py_touserdata(py_arg(0)); + if(ud->file != NULL) { + fclose(ud->file); + ud->file = NULL; + } + return true; +} + +static bool io_FileIO_read(int argc, py_Ref argv) { + PY_CHECK_ARGC(1); + io_FileIO* ud = py_touserdata(py_arg(0)); + fseek(ud->file, 0, SEEK_END); + int filesize = ftell(ud->file); + fseek(ud->file, 0, SEEK_SET); + unsigned char* data = py_newbytes(py_retval(), filesize); + fread(data, 1, filesize, ud->file); + return true; +} + +static bool io_FileIO_write(int argc, py_Ref argv) { + PY_CHECK_ARGC(2); + PY_CHECK_ARG_TYPE(1, tp_bytes); + io_FileIO* ud = py_touserdata(py_arg(0)); + int filesize; + unsigned char* data = py_tobytes(py_arg(1), &filesize); + fwrite(data, 1, filesize, ud->file); + return true; +} + +void pk__add_module_io() { + py_Ref mod = py_newmodule("io"); + + py_Type FileIO = pk_newtype("FileIO", tp_object, mod, NULL, false, true); + + py_bindmagic(FileIO, __new__, io_FileIO__new__); + py_bindmagic(FileIO, __enter__, io_FileIO__enter__); + py_bindmagic(FileIO, __exit__, io_FileIO__exit__); + py_bindmethod(FileIO, "read", io_FileIO_read); + py_bindmethod(FileIO, "write", io_FileIO_write); + + py_setdict(&pk_current_vm->builtins, py_name("open"), py_tpobject(FileIO)); +}