Prechádzať zdrojové kódy

add `io` module and `open`

blueloveTH 1 rok pred
rodič
commit
3eeaeaa65d

+ 3 - 10
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

+ 2 - 0
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();

+ 1 - 0
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();

+ 75 - 5
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 <errno.h>
 
 #if PY_SYS_PLATFORM == 0
 #include <direct.h>
@@ -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")));
-}
+}
+
+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));
+}