mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-19 19:10:17 +00:00
...
This commit is contained in:
parent
8e1e29ddd6
commit
3c87bf8630
BIN
backup/vfs.zip
Normal file
BIN
backup/vfs.zip
Normal file
Binary file not shown.
@ -5,6 +5,8 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
const char* load_kPythonLib(const char* name);
|
||||
|
||||
extern const char kPythonLibs__enum[];
|
||||
extern const char kPythonLibs__long[];
|
||||
extern const char kPythonLibs__set[];
|
||||
|
@ -1,44 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "pocketpy/common/vector.h"
|
||||
#include "pocketpy/common/str.h"
|
||||
#include "pocketpy/pocketpy.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct VfsEntry {
|
||||
bool is_file;
|
||||
|
||||
union {
|
||||
struct {
|
||||
int size;
|
||||
unsigned char* data;
|
||||
} _file;
|
||||
|
||||
c11_vector _dir;
|
||||
};
|
||||
} VfsEntry;
|
||||
|
||||
#define SMALLMAP_T__HEADER
|
||||
#define K c11_sv
|
||||
#define V VfsEntry
|
||||
#define NAME VfsDir
|
||||
#define less(a, b) (c11_sv__cmp((a), (b)) < 0)
|
||||
#define equal(a, b) (c11_sv__cmp((a), (b)) == 0)
|
||||
#include "pocketpy/xmacros/smallmap.h"
|
||||
#undef SMALLMAP_T__HEADER
|
||||
|
||||
typedef struct Vfs {
|
||||
VfsEntry root;
|
||||
} Vfs;
|
||||
|
||||
void Vfs__ctor(Vfs* self);
|
||||
void Vfs__dtor(Vfs* self);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -4,7 +4,6 @@
|
||||
#include "pocketpy/pocketpy.h"
|
||||
#include "pocketpy/interpreter/gc.h"
|
||||
#include "pocketpy/interpreter/frame.h"
|
||||
#include "pocketpy/interpreter/vfs.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -40,7 +39,7 @@ typedef struct pk_VM {
|
||||
py_TValue main; // __main__ module
|
||||
|
||||
void (*ceval_on_step)(Frame*, Bytecode);
|
||||
unsigned char* (*import_file)(const char*, int*);
|
||||
char* (*import_file)(const char*);
|
||||
void (*print)(const char*);
|
||||
|
||||
py_TValue last_retval;
|
||||
@ -49,7 +48,6 @@ typedef struct pk_VM {
|
||||
|
||||
py_TValue reg[8]; // users' registers
|
||||
|
||||
Vfs __vfs;
|
||||
py_TValue* __curr_class;
|
||||
FuncDecl_ __dynamic_func_decl;
|
||||
py_TValue __vectorcall_buffer[PK_MAX_CO_VARNAMES];
|
||||
|
@ -360,11 +360,6 @@ bool py_dict__contains(py_Ref self, py_Ref key);
|
||||
int py_dict__len(py_Ref self);
|
||||
bool py_dict__apply(py_Ref self, bool (*f)(py_Ref key, py_Ref val, void* ctx), void* ctx);
|
||||
|
||||
/************* Virtual File System *************/
|
||||
unsigned char* py_vfsread(const char* path, int* size);
|
||||
bool py_vfswrite(const char* path, unsigned char* data, int size);
|
||||
char** py_vfslist(const char* path, int* length);
|
||||
|
||||
/************* Others *************/
|
||||
int py_replinput(char* buf);
|
||||
|
||||
|
14
prebuild.py
14
prebuild.py
@ -31,6 +31,8 @@ with open("include/pocketpy/common/_generated.h", "wt", encoding='utf-8', newlin
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
const char* load_kPythonLib(const char* name);
|
||||
|
||||
'''
|
||||
for key in sorted(sources.keys()):
|
||||
value = sources[key]
|
||||
@ -45,9 +47,19 @@ extern "C" {
|
||||
with open("src/common/_generated.c", "wt", encoding='utf-8', newline='\n') as f:
|
||||
data = '''// generated by prebuild.py
|
||||
#include "pocketpy/common/_generated.h"
|
||||
|
||||
#include <string.h>
|
||||
'''
|
||||
for key in sorted(sources.keys()):
|
||||
value = sources[key]
|
||||
data += f'const char kPythonLibs_{key}[] = {value};\n'
|
||||
f.write(data)
|
||||
|
||||
f.write("\n")
|
||||
f.write("const char* load_kPythonLib(const char* name) {\n")
|
||||
for key in sorted(sources.keys()):
|
||||
if key.startswith('_'):
|
||||
continue
|
||||
f.write(f' if (strcmp(name, "{key}") == 0) return kPythonLibs_{key};\n')
|
||||
f.write(" return NULL;\n")
|
||||
f.write("}\n")
|
||||
|
||||
|
File diff suppressed because one or more lines are too long
@ -1,131 +0,0 @@
|
||||
#include "pocketpy/interpreter/vfs.h"
|
||||
#include "pocketpy/interpreter/vm.h"
|
||||
|
||||
#define SMALLMAP_T__SOURCE
|
||||
#define K c11_sv
|
||||
#define V VfsEntry
|
||||
#define NAME VfsDir
|
||||
#define less(a, b) (c11_sv__cmp((a), (b)) < 0)
|
||||
#define equal(a, b) (c11_sv__cmp((a), (b)) == 0)
|
||||
#include "pocketpy/xmacros/smallmap.h"
|
||||
#undef SMALLMAP_T__SOURCE
|
||||
|
||||
static VfsEntry* Vfs__get(const char* path) {
|
||||
c11_vector /*T=c11_sv*/ cpnts = c11_sv__split((c11_sv){path, strlen(path)}, '/');
|
||||
|
||||
VfsEntry* root = &pk_current_vm->__vfs.root;
|
||||
for(int i = 0; i < cpnts.count; i++) {
|
||||
c11_sv cpnt = c11__getitem(c11_sv, &cpnts, i);
|
||||
VfsEntry* entry = VfsDir__try_get(&root->_dir, cpnt);
|
||||
if(entry == NULL) {
|
||||
c11_vector__dtor(&cpnts);
|
||||
return NULL;
|
||||
}
|
||||
if(entry->is_file) {
|
||||
VfsEntry* retval = i == cpnts.count - 1 ? entry : NULL;
|
||||
c11_vector__dtor(&cpnts);
|
||||
return retval;
|
||||
} else {
|
||||
root = entry;
|
||||
}
|
||||
}
|
||||
c11_vector__dtor(&cpnts);
|
||||
return root;
|
||||
}
|
||||
|
||||
static void VfsDir__delete_recursively(VfsDir* self) {
|
||||
for(int i = 0; i < self->count; i++) {
|
||||
VfsDir_KV* kv = c11__at(VfsDir_KV, self, i);
|
||||
free((char*)kv->key.data);
|
||||
if(kv->value.is_file) {
|
||||
free(kv->value._file.data);
|
||||
} else {
|
||||
VfsDir__delete_recursively(&kv->value._dir);
|
||||
}
|
||||
}
|
||||
VfsDir__dtor(self);
|
||||
}
|
||||
|
||||
void Vfs__ctor(Vfs* self) {
|
||||
self->root.is_file = false;
|
||||
VfsDir__ctor(&self->root._dir);
|
||||
}
|
||||
|
||||
void Vfs__dtor(Vfs* self) { VfsDir__delete_recursively(&self->root._dir); }
|
||||
|
||||
unsigned char* py_vfsread(const char* path, int* size) {
|
||||
VfsEntry* entry = Vfs__get(path);
|
||||
if(entry == NULL || !entry->is_file) return NULL;
|
||||
*size = entry->_file.size;
|
||||
unsigned char* retval = malloc(*size);
|
||||
memcpy(retval, entry->_file.data, *size);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void VfsDir__dupset(VfsDir* self, c11_sv key, VfsEntry value) {
|
||||
char* p = malloc(key.size);
|
||||
memcpy(p, key.data, key.size);
|
||||
VfsDir__set(self, (c11_sv){p, key.size}, value);
|
||||
}
|
||||
|
||||
bool py_vfswrite(const char* path, unsigned char* data, int size) {
|
||||
c11_vector /*T=c11_sv*/ cpnts = c11_sv__split((c11_sv){path, strlen(path)}, '/');
|
||||
VfsEntry* root = &pk_current_vm->__vfs.root;
|
||||
for(int i = 0; i < cpnts.count; i++) {
|
||||
c11_sv cpnt = c11__getitem(c11_sv, &cpnts, i);
|
||||
VfsEntry* entry = VfsDir__try_get(&root->_dir, cpnt);
|
||||
if(entry == NULL) {
|
||||
if(i == cpnts.count - 1) {
|
||||
// create file
|
||||
VfsEntry entry = {
|
||||
.is_file = true,
|
||||
._file.size = size,
|
||||
._file.data = data,
|
||||
};
|
||||
VfsDir__dupset(&root->_dir, cpnt, entry);
|
||||
c11_vector__dtor(&cpnts);
|
||||
return true;
|
||||
} else {
|
||||
// create missing directory
|
||||
VfsEntry entry = {
|
||||
.is_file = false,
|
||||
};
|
||||
VfsDir__ctor(&entry._dir);
|
||||
VfsDir__dupset(&root->_dir, cpnt, entry);
|
||||
}
|
||||
} else {
|
||||
if(i == cpnts.count - 1) {
|
||||
if(!entry->is_file) break;
|
||||
// update file
|
||||
free(entry->_file.data);
|
||||
entry->_file.size = size;
|
||||
entry->_file.data = data;
|
||||
c11_vector__dtor(&cpnts);
|
||||
return true;
|
||||
} else {
|
||||
if(entry->is_file) break;
|
||||
root = entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
c11_vector__dtor(&cpnts);
|
||||
return false;
|
||||
}
|
||||
|
||||
char** py_vfslist(const char* path, int* length) {
|
||||
VfsEntry* entry = Vfs__get(path);
|
||||
if(entry == NULL || entry->is_file) return NULL;
|
||||
*length = 0;
|
||||
char** ret = malloc(sizeof(char*) * entry->_dir.count);
|
||||
for(int i = 0; i < entry->_dir.count; i++) {
|
||||
VfsDir_KV* child = c11__at(VfsDir_KV, &entry->_dir, i);
|
||||
if(child->value.is_file) {
|
||||
int size = child->key.size;
|
||||
ret[i] = malloc(size + 1);
|
||||
memcpy(ret[i], child->key.data, size);
|
||||
ret[i][size] = '\0';
|
||||
(*length)++;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
@ -6,7 +6,7 @@
|
||||
#include "pocketpy/common/_generated.h"
|
||||
#include "pocketpy/pocketpy.h"
|
||||
|
||||
static unsigned char* pk_default_import_file(const char* path, int* size) { return NULL; }
|
||||
static char* pk_default_import_file(const char* path) { return NULL; }
|
||||
|
||||
static void pk_default_print(const char* data) { printf("%s", data); }
|
||||
|
||||
@ -36,13 +36,6 @@ static void pk_TypeInfo__ctor(pk_TypeInfo* self,
|
||||
|
||||
static void pk_TypeInfo__dtor(pk_TypeInfo* self) { c11_vector__dtor(&self->annotated_fields); }
|
||||
|
||||
static void save_site_package_to_vfs(const char* name, const char* source) {
|
||||
char buf[512];
|
||||
snprintf(buf, sizeof(buf), "site-packages/%s", name);
|
||||
bool ok = py_vfswrite(buf, (unsigned char*)source, strlen(source) + 1);
|
||||
if(!ok) c11__abort("failed to save '%s' to vfs", name);
|
||||
}
|
||||
|
||||
void pk_VM__ctor(pk_VM* self) {
|
||||
self->top_frame = NULL;
|
||||
|
||||
@ -60,7 +53,6 @@ void pk_VM__ctor(pk_VM* self) {
|
||||
self->curr_exception = *py_NIL;
|
||||
self->is_stopiteration = false;
|
||||
|
||||
Vfs__ctor(&self->__vfs);
|
||||
self->__curr_class = NULL;
|
||||
self->__dynamic_func_decl = NULL;
|
||||
|
||||
@ -184,19 +176,6 @@ void pk_VM__ctor(pk_VM* self) {
|
||||
pk__add_module_pkpy();
|
||||
|
||||
self->main = *py_newmodule("__main__");
|
||||
|
||||
save_site_package_to_vfs("bisect.py", kPythonLibs_bisect);
|
||||
save_site_package_to_vfs("cmath.py", kPythonLibs_cmath);
|
||||
save_site_package_to_vfs("collections.py", kPythonLibs_collections);
|
||||
save_site_package_to_vfs("colorsys.py", kPythonLibs_colorsys);
|
||||
save_site_package_to_vfs("datetime.py", kPythonLibs_datetime);
|
||||
save_site_package_to_vfs("functools.py", kPythonLibs_functools);
|
||||
save_site_package_to_vfs("heapq.py", kPythonLibs_heapq);
|
||||
save_site_package_to_vfs("itertools.py", kPythonLibs_itertools);
|
||||
save_site_package_to_vfs("operator.py", kPythonLibs_operator);
|
||||
save_site_package_to_vfs("pickle.py", kPythonLibs_pickle);
|
||||
save_site_package_to_vfs("this.py", kPythonLibs_this);
|
||||
save_site_package_to_vfs("typing.py", kPythonLibs_typing);
|
||||
}
|
||||
|
||||
void pk_VM__dtor(pk_VM* self) {
|
||||
@ -209,7 +188,6 @@ void pk_VM__dtor(pk_VM* self) {
|
||||
c11__foreach(pk_TypeInfo, &self->types, ti) pk_TypeInfo__dtor(ti);
|
||||
c11_vector__dtor(&self->types);
|
||||
ValueStack__clear(&self->stack);
|
||||
Vfs__dtor(&self->__vfs);
|
||||
}
|
||||
|
||||
void pk_VM__push_frame(pk_VM* self, Frame* frame) {
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "pocketpy/objects/object.h"
|
||||
#include "pocketpy/common/sstream.h"
|
||||
#include "pocketpy/interpreter/vm.h"
|
||||
#include "pocketpy/common/_generated.h"
|
||||
|
||||
py_Ref py_getmodule(const char* path) {
|
||||
pk_VM* vm = pk_current_vm;
|
||||
@ -60,7 +61,8 @@ bool py_import(const char* path_cstr) {
|
||||
// try relative import
|
||||
py_Ref package = py_getdict(&vm->top_frame->module, __package__);
|
||||
c11_sv package_sv = py_tosv(package);
|
||||
if(package_sv.size == 0) return ImportError("relative import %q with no known parent package", path);
|
||||
if(package_sv.size == 0)
|
||||
return ImportError("relative import %q with no known parent package", path);
|
||||
c11_string* new_path = c11_string__new3("%v.%v", package_sv, path);
|
||||
bool ok = py_import(new_path->data);
|
||||
c11_string__delete(new_path);
|
||||
@ -85,25 +87,23 @@ bool py_import(const char* path_cstr) {
|
||||
|
||||
// try import
|
||||
c11_string* slashed_path = c11_sv__replace(path, '.', PK_PLATFORM_SEP);
|
||||
c11_string* filename = c11_string__new3("%s.py", slashed_path->data);
|
||||
|
||||
c11_string* filename = c11_string__new3("site-packages/%s.py", slashed_path->data);
|
||||
int size;
|
||||
unsigned char* data = py_vfsread(filename->data, &size);
|
||||
if(data != NULL) goto __SUCCESS;
|
||||
|
||||
c11_string__delete(filename);
|
||||
filename = c11_string__new3("site-packages/%s/__init__.py", slashed_path->data);
|
||||
data = py_vfsread(filename->data, &size);
|
||||
if(data != NULL) goto __SUCCESS;
|
||||
bool need_free = true;
|
||||
const char* data = load_kPythonLib(path_cstr);
|
||||
if(data != NULL) {
|
||||
need_free = false;
|
||||
goto __SUCCESS;
|
||||
}
|
||||
|
||||
c11_string__delete(filename);
|
||||
filename = c11_string__new3("%s.py", slashed_path->data);
|
||||
data = vm->import_file(slashed_path->data, &size);
|
||||
data = vm->import_file(slashed_path->data);
|
||||
if(data != NULL) goto __SUCCESS;
|
||||
|
||||
c11_string__delete(filename);
|
||||
filename = c11_string__new3("%s/__init__.py", slashed_path->data);
|
||||
data = vm->import_file(slashed_path->data, &size);
|
||||
data = vm->import_file(slashed_path->data);
|
||||
if(data != NULL) goto __SUCCESS;
|
||||
|
||||
c11_string__delete(filename);
|
||||
@ -121,7 +121,7 @@ __SUCCESS:
|
||||
|
||||
c11_string__delete(filename);
|
||||
c11_string__delete(slashed_path);
|
||||
free(data);
|
||||
if(need_free) free((void*)data);
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user