mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 19:40:18 +00:00
...
This commit is contained in:
parent
b1a8c6db8e
commit
ea9dabdf99
@ -10,7 +10,7 @@
|
||||
|
||||
// Whether to compile os-related modules or not
|
||||
#ifndef PK_ENABLE_OS // can be overridden by cmake
|
||||
#define PK_ENABLE_OS 0
|
||||
#define PK_ENABLE_OS 1
|
||||
#endif
|
||||
|
||||
// Enable `line_profiler` module and `breakpoint()` function
|
||||
|
@ -49,6 +49,8 @@ int c11_sv__index(c11_sv self, char c);
|
||||
int c11_sv__rindex(c11_sv self, char c);
|
||||
int c11_sv__index2(c11_sv self, c11_sv sub, int start);
|
||||
int c11_sv__count(c11_sv self, c11_sv sub);
|
||||
bool c11_sv__startswith(c11_sv self, c11_sv prefix);
|
||||
bool c11_sv__endswith(c11_sv self, c11_sv suffix);
|
||||
|
||||
c11_string* c11_sv__replace(c11_sv self, char old, char new_);
|
||||
c11_string* c11_sv__replace2(c11_sv self, c11_sv old, c11_sv new_);
|
||||
|
13
include/pocketpy/interpreter/modules.h
Normal file
13
include/pocketpy/interpreter/modules.h
Normal file
@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void pk__add_module_pkpy();
|
||||
void pk__add_module_os();
|
||||
void pk__add_module_math();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -4,6 +4,7 @@
|
||||
#include "pocketpy/pocketpy.h"
|
||||
#include "pocketpy/interpreter/gc.h"
|
||||
#include "pocketpy/interpreter/frame.h"
|
||||
#include "pocketpy/interpreter/modules.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -124,8 +125,6 @@ py_Type pk_Exception__register();
|
||||
|
||||
py_TValue pk_builtins__register();
|
||||
|
||||
void pk__add_module_pkpy();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -7,6 +7,10 @@
|
||||
#include "pocketpy/common/config.h"
|
||||
#include "pocketpy/common/export.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/************* Public Types *************/
|
||||
typedef struct py_TValue py_TValue;
|
||||
typedef uint16_t py_Name;
|
||||
@ -121,7 +125,7 @@ void* py_newobject(py_Ref out, py_Type type, int slots, int udsize);
|
||||
/************* Type Cast *************/
|
||||
py_i64 py_toint(py_Ref);
|
||||
py_f64 py_tofloat(py_Ref);
|
||||
bool py_castfloat(py_Ref, py_f64* out);
|
||||
bool py_castfloat(py_Ref, py_f64* out) PY_RAISE;
|
||||
bool py_tobool(py_Ref);
|
||||
py_Type py_totype(py_Ref);
|
||||
const char* py_tostr(py_Ref);
|
||||
@ -186,6 +190,7 @@ py_GlobalRef py_retval();
|
||||
py_ObjectRef py_getdict(py_Ref self, py_Name name);
|
||||
void py_setdict(py_Ref self, py_Name name, py_Ref val);
|
||||
bool py_deldict(py_Ref self, py_Name name);
|
||||
py_ObjectRef py_emplacedict(py_Ref self, py_Name name);
|
||||
|
||||
/// Get the reference of the i-th slot of the object.
|
||||
/// The object must have slots and `i` must be in range.
|
||||
@ -264,7 +269,8 @@ py_TmpRef py_getmodule(const char* path);
|
||||
|
||||
/// Import a module.
|
||||
/// The result will be set to `py_retval()`.
|
||||
bool py_import(const char* path) PY_RAISE;
|
||||
/// -1: error, 0: not found, 1: success
|
||||
int py_import(const char* path) PY_RAISE;
|
||||
|
||||
/************* Errors *************/
|
||||
/// Raise an exception by name and message. Always returns false.
|
||||
@ -280,6 +286,8 @@ bool py_checkexc();
|
||||
/// Clear the current exception.
|
||||
void py_clearexc(py_StackRef p0);
|
||||
|
||||
#define IOError(...) py_exception("IOError", __VA_ARGS__)
|
||||
#define OSError(...) py_exception("OSError", __VA_ARGS__)
|
||||
#define NameError(n) py_exception("NameError", "name '%n' is not defined", (n))
|
||||
#define TypeError(...) py_exception("TypeError", __VA_ARGS__)
|
||||
#define RuntimeError(...) py_exception("RuntimeError", __VA_ARGS__)
|
||||
|
@ -56,7 +56,6 @@ MAGIC_METHOD(__exit__)
|
||||
MAGIC_METHOD(__name__)
|
||||
MAGIC_METHOD(__all__)
|
||||
MAGIC_METHOD(__package__)
|
||||
MAGIC_METHOD(__module_is_pending__)
|
||||
MAGIC_METHOD(__path__)
|
||||
MAGIC_METHOD(__class__)
|
||||
MAGIC_METHOD(__abs__)
|
||||
|
@ -165,6 +165,16 @@ int c11_sv__count(c11_sv self, c11_sv sub) {
|
||||
return cnt;
|
||||
}
|
||||
|
||||
bool c11_sv__startswith(c11_sv self, c11_sv prefix) {
|
||||
if(prefix.size > self.size) return false;
|
||||
return memcmp(self.data, prefix.data, prefix.size) == 0;
|
||||
}
|
||||
|
||||
bool c11_sv__endswith(c11_sv self, c11_sv suffix) {
|
||||
if(suffix.size > self.size) return false;
|
||||
return memcmp(self.data + self.size - suffix.size, suffix.data, suffix.size) == 0;
|
||||
}
|
||||
|
||||
c11_vector /* T=c11_sv */ c11_sv__split(c11_sv self, char sep) {
|
||||
c11_vector retval;
|
||||
c11_vector__ctor(&retval, sizeof(c11_sv));
|
||||
|
@ -257,6 +257,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
||||
// fallback to getattr
|
||||
if(py_getattr(TOP(), byte.arg)) {
|
||||
py_assign(TOP(), py_retval());
|
||||
py_newnil(SP()++);
|
||||
} else {
|
||||
goto __ERROR;
|
||||
}
|
||||
@ -757,8 +758,13 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
|
||||
////////
|
||||
case OP_IMPORT_PATH: {
|
||||
py_Ref path_object = c11__at(py_TValue, &frame->co->consts, byte.arg);
|
||||
bool ok = py_import(py_tostr(path_object));
|
||||
if(!ok) goto __ERROR;
|
||||
const char* path = py_tostr(path_object);
|
||||
int res = py_import(path);
|
||||
if(res == -1) goto __ERROR;
|
||||
if(res == 0) {
|
||||
ImportError("module '%s' not found", path);
|
||||
goto __ERROR;
|
||||
}
|
||||
PUSH(py_retval());
|
||||
DISPATCH();
|
||||
}
|
||||
|
@ -6,7 +6,22 @@
|
||||
#include "pocketpy/common/_generated.h"
|
||||
#include "pocketpy/pocketpy.h"
|
||||
|
||||
static char* pk_default_import_file(const char* path) { return NULL; }
|
||||
static char* pk_default_import_file(const char* path) {
|
||||
#if PK_ENABLE_OS
|
||||
FILE* f = fopen(path, "rb");
|
||||
if(f == NULL) return NULL;
|
||||
fseek(f, 0, SEEK_END);
|
||||
long size = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
char* buffer = malloc(size + 1);
|
||||
fread(buffer, 1, size, f);
|
||||
buffer[size] = 0;
|
||||
fclose(f);
|
||||
return buffer;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void pk_default_print(const char* data) { printf("%s", data); }
|
||||
|
||||
@ -147,6 +162,7 @@ void pk_VM__ctor(pk_VM* self) {
|
||||
const char** builtin_exceptions = (const char*[]){
|
||||
"StackOverflowError",
|
||||
"IOError",
|
||||
"OSError",
|
||||
"NotImplementedError",
|
||||
"TypeError",
|
||||
"IndexError",
|
||||
@ -174,6 +190,8 @@ void pk_VM__ctor(pk_VM* self) {
|
||||
|
||||
// add modules
|
||||
pk__add_module_pkpy();
|
||||
pk__add_module_os();
|
||||
pk__add_module_math();
|
||||
|
||||
self->main = *py_newmodule("__main__");
|
||||
}
|
||||
@ -559,7 +577,7 @@ void pk_ManagedHeap__mark(pk_ManagedHeap* self) {
|
||||
}
|
||||
|
||||
void pk_print_stack(pk_VM* self, Frame* frame, Bytecode byte) {
|
||||
// return;
|
||||
return;
|
||||
if(frame == NULL) return;
|
||||
|
||||
py_TValue* sp = self->stack.sp;
|
||||
@ -594,6 +612,11 @@ void pk_print_stack(pk_VM* self, Frame* frame, Bytecode byte) {
|
||||
pk_sprintf(&buf, "%q", py_tosv(p));
|
||||
break;
|
||||
}
|
||||
case tp_module: {
|
||||
py_Ref path = py_getdict(p, __path__);
|
||||
pk_sprintf(&buf, "<module '%v'>", py_tosv(path));
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
pk_sprintf(&buf, "(%t)", p->type);
|
||||
break;
|
||||
|
202
src/modules/math.c
Normal file
202
src/modules/math.c
Normal file
@ -0,0 +1,202 @@
|
||||
#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 <math.h>
|
||||
|
||||
#define ONE_ARG_FUNC(name, func) \
|
||||
static bool math_##name(int argc, py_Ref argv) { \
|
||||
PY_CHECK_ARGC(1); \
|
||||
double x; \
|
||||
if(!py_castfloat(py_arg(0), &x)) return false; \
|
||||
py_newfloat(py_retval(), func(x)); \
|
||||
return true; \
|
||||
}
|
||||
|
||||
#define TWO_ARG_FUNC(name, func) \
|
||||
static bool math_##name(int argc, py_Ref argv) { \
|
||||
PY_CHECK_ARGC(2); \
|
||||
double x, y; \
|
||||
if(!py_castfloat(py_arg(0), &x)) return false; \
|
||||
if(!py_castfloat(py_arg(1), &y)) return false; \
|
||||
py_newfloat(py_retval(), func(x, y)); \
|
||||
return true; \
|
||||
}
|
||||
|
||||
ONE_ARG_FUNC(ceil, ceil)
|
||||
ONE_ARG_FUNC(fabs, fabs)
|
||||
ONE_ARG_FUNC(floor, floor)
|
||||
ONE_ARG_FUNC(trunc, trunc)
|
||||
|
||||
static bool math_fsum(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
PY_CHECK_ARG_TYPE(0, tp_list);
|
||||
py_Ref list = py_arg(0);
|
||||
double sum = 0;
|
||||
double c = 0;
|
||||
for(int i = 0; i < py_list__len(list); i++) {
|
||||
py_Ref item = py_list__getitem(list, i);
|
||||
double x;
|
||||
if(!py_castfloat(item, &x)) return false;
|
||||
double y = x - c;
|
||||
double t = sum + y;
|
||||
c = (t - sum) - y;
|
||||
sum = t;
|
||||
}
|
||||
py_newfloat(py_retval(), sum);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool math_gcd(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
PY_CHECK_ARG_TYPE(0, tp_int);
|
||||
PY_CHECK_ARG_TYPE(1, tp_int);
|
||||
py_i64 a = py_toint(py_arg(0));
|
||||
py_i64 b = py_toint(py_arg(1));
|
||||
if(a < 0) a = -a;
|
||||
if(b < 0) b = -b;
|
||||
while(b != 0) {
|
||||
py_i64 t = b;
|
||||
b = a % b;
|
||||
a = t;
|
||||
}
|
||||
py_newint(py_retval(), a);
|
||||
return true;
|
||||
}
|
||||
|
||||
ONE_ARG_FUNC(isfinite, isfinite)
|
||||
ONE_ARG_FUNC(isinf, isinf)
|
||||
ONE_ARG_FUNC(isnan, isnan)
|
||||
|
||||
static bool math_isclose(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(2);
|
||||
double a, b;
|
||||
if(!py_castfloat(py_arg(0), &a)) return false;
|
||||
if(!py_castfloat(py_arg(1), &b)) return false;
|
||||
py_newbool(py_retval(), fabs(a - b) < 1e-9);
|
||||
return true;
|
||||
}
|
||||
|
||||
ONE_ARG_FUNC(exp, exp)
|
||||
|
||||
static bool math_log(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARG_TYPE(0, tp_float);
|
||||
double x;
|
||||
if(!py_castfloat(py_arg(0), &x)) return false;
|
||||
if(argc == 1) {
|
||||
py_newfloat(py_retval(), log(x));
|
||||
} else if(argc == 2) {
|
||||
double base;
|
||||
if(!py_castfloat(py_arg(1), &base)) return false;
|
||||
py_newfloat(py_retval(), log(x) / log(base));
|
||||
} else {
|
||||
return TypeError("log() takes 1 or 2 arguments");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ONE_ARG_FUNC(log2, log2)
|
||||
ONE_ARG_FUNC(log10, log10)
|
||||
|
||||
TWO_ARG_FUNC(pow, pow)
|
||||
|
||||
ONE_ARG_FUNC(sqrt, sqrt)
|
||||
|
||||
ONE_ARG_FUNC(acos, acos)
|
||||
ONE_ARG_FUNC(asin, asin)
|
||||
ONE_ARG_FUNC(atan, atan)
|
||||
|
||||
ONE_ARG_FUNC(cos, cos)
|
||||
ONE_ARG_FUNC(sin, sin)
|
||||
ONE_ARG_FUNC(tan, tan)
|
||||
|
||||
TWO_ARG_FUNC(atan2, atan2)
|
||||
|
||||
static bool math_degrees(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
double x;
|
||||
if(!py_castfloat(py_arg(0), &x)) return false;
|
||||
py_newfloat(py_retval(), x * 180 / 3.1415926535897932384);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool math_radians(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
double x;
|
||||
if(!py_castfloat(py_arg(0), &x)) return false;
|
||||
py_newfloat(py_retval(), x * 3.1415926535897932384 / 180);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool math_modf(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
double i;
|
||||
double f = modf(py_tofloat(py_arg(0)), &i);
|
||||
py_newtuple(py_retval(), 2);
|
||||
py_Ref _0 = py_tuple__getitem(py_retval(), 0);
|
||||
py_Ref _1 = py_tuple__getitem(py_retval(), 1);
|
||||
py_newfloat(_0, f);
|
||||
py_newfloat(_1, i);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool math_factorial(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
PY_CHECK_ARG_TYPE(0, tp_int);
|
||||
py_i64 n = py_toint(py_arg(0));
|
||||
if(n < 0) return ValueError("factorial() not defined for negative values");
|
||||
py_i64 r = 1;
|
||||
for(py_i64 i = 2; i <= n; i++)
|
||||
r *= i;
|
||||
py_newint(py_retval(), r);
|
||||
return true;
|
||||
}
|
||||
|
||||
void pk__add_module_math() {
|
||||
py_Ref mod = py_newmodule("math");
|
||||
|
||||
py_newfloat(py_emplacedict(mod, py_name("pi")), 3.1415926535897932384);
|
||||
py_newfloat(py_emplacedict(mod, py_name("e")), 2.7182818284590452354);
|
||||
py_newfloat(py_emplacedict(mod, py_name("inf")), 1.0 / 0.0);
|
||||
py_newfloat(py_emplacedict(mod, py_name("nan")), 0.0 / 0.0);
|
||||
|
||||
py_bindfunc(mod, "ceil", math_ceil);
|
||||
py_bindfunc(mod, "fabs", math_fabs);
|
||||
py_bindfunc(mod, "floor", math_floor);
|
||||
py_bindfunc(mod, "trunc", math_trunc);
|
||||
|
||||
py_bindfunc(mod, "fsum", math_fsum);
|
||||
py_bindfunc(mod, "gcd", math_gcd);
|
||||
|
||||
py_bindfunc(mod, "isfinite", math_isfinite);
|
||||
py_bindfunc(mod, "isinf", math_isinf);
|
||||
py_bindfunc(mod, "isnan", math_isnan);
|
||||
py_bindfunc(mod, "isclose", math_isclose);
|
||||
|
||||
py_bindfunc(mod, "exp", math_exp);
|
||||
py_bindfunc(mod, "log", math_log);
|
||||
py_bindfunc(mod, "log2", math_log2);
|
||||
py_bindfunc(mod, "log10", math_log10);
|
||||
|
||||
py_bindfunc(mod, "pow", math_pow);
|
||||
py_bindfunc(mod, "sqrt", math_sqrt);
|
||||
|
||||
py_bindfunc(mod, "acos", math_acos);
|
||||
py_bindfunc(mod, "asin", math_asin);
|
||||
py_bindfunc(mod, "atan", math_atan);
|
||||
|
||||
py_bindfunc(mod, "cos", math_cos);
|
||||
py_bindfunc(mod, "sin", math_sin);
|
||||
py_bindfunc(mod, "tan", math_tan);
|
||||
|
||||
py_bindfunc(mod, "atan2", math_atan2);
|
||||
|
||||
py_bindfunc(mod, "degrees", math_degrees);
|
||||
py_bindfunc(mod, "radians", math_radians);
|
||||
|
||||
py_bindfunc(mod, "modf", math_modf);
|
||||
py_bindfunc(mod, "factorial", math_factorial);
|
||||
}
|
49
src/modules/os.c
Normal file
49
src/modules/os.c
Normal file
@ -0,0 +1,49 @@
|
||||
#include "pocketpy/pocketpy.h"
|
||||
|
||||
#include "pocketpy/common/utils.h"
|
||||
#include "pocketpy/objects/object.h"
|
||||
#include "pocketpy/common/sstream.h"
|
||||
#include "pocketpy/interpreter/vm.h"
|
||||
|
||||
#if _WIN32
|
||||
#include <direct.h>
|
||||
|
||||
int platform_chdir(const char* path) { return _chdir(path); }
|
||||
|
||||
bool platform_getcwd(char* buf, size_t size) { return _getcwd(buf, size) != NULL; }
|
||||
|
||||
#elif __linux__
|
||||
#include <unistd.h>
|
||||
|
||||
int platform_chdir(const char* path) { return chdir(path); }
|
||||
|
||||
bool platform_getcwd(char* buf, size_t size) { return getcwd(buf, size) != NULL; }
|
||||
#else
|
||||
|
||||
int platform_chdir(const char* path) { return -1; }
|
||||
|
||||
bool platform_getcwd(char* buf, size_t size) { return false; }
|
||||
|
||||
#endif
|
||||
|
||||
static bool os_chdir(int argc, py_Ref argv) {
|
||||
PY_CHECK_ARGC(1);
|
||||
PY_CHECK_ARG_TYPE(0, tp_str);
|
||||
const char* path = py_tostr(py_arg(0));
|
||||
int code = platform_chdir(path);
|
||||
if(code != 0) return OSError("chdir() failed: %d", code);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool os_getcwd(int argc, py_Ref argv) {
|
||||
char buf[1024];
|
||||
if(!platform_getcwd(buf, sizeof(buf))) return OSError("getcwd() failed");
|
||||
py_newstr(py_retval(), buf);
|
||||
return true;
|
||||
}
|
||||
|
||||
void pk__add_module_os() {
|
||||
py_Ref mod = py_newmodule("os");
|
||||
py_bindfunc(mod, "chdir", os_chdir);
|
||||
py_bindfunc(mod, "getcwd", os_getcwd);
|
||||
}
|
@ -19,7 +19,7 @@ bool py_castfloat(py_Ref self, double* out) {
|
||||
switch(self->type) {
|
||||
case tp_int: *out = (double)self->_i64; return true;
|
||||
case tp_float: *out = self->_f64; return true;
|
||||
default: return false;
|
||||
default: return TypeError("expected int or float, got %t", self->type);
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,11 +46,9 @@ bool py_checktype(py_Ref self, py_Type type) {
|
||||
return TypeError("expected %t, got %t", type, self->type);
|
||||
}
|
||||
|
||||
bool py_isinstance(py_Ref obj, py_Type type){
|
||||
return py_issubclass(obj->type, type);
|
||||
}
|
||||
bool py_isinstance(py_Ref obj, py_Type type) { return py_issubclass(obj->type, type); }
|
||||
|
||||
bool py_issubclass(py_Type derived, py_Type base){
|
||||
bool py_issubclass(py_Type derived, py_Type base) {
|
||||
pk_TypeInfo* types = pk_current_vm->types.data;
|
||||
do {
|
||||
if(derived == base) return true;
|
||||
|
@ -52,21 +52,53 @@ py_Ref py_newmodule(const char* path) {
|
||||
return py_getmodule(path);
|
||||
}
|
||||
|
||||
bool py_import(const char* path_cstr) {
|
||||
int py_import(const char* path_cstr) {
|
||||
// printf("importing %s\n", path_cstr);
|
||||
|
||||
pk_VM* vm = pk_current_vm;
|
||||
c11_sv path = {path_cstr, strlen(path_cstr)};
|
||||
if(path.size == 0) return ValueError("empty module name");
|
||||
|
||||
if(path.data[0] == '.') {
|
||||
// try relative import
|
||||
py_Ref package = py_getdict(&vm->top_frame->module, __package__);
|
||||
int dot_count = 1;
|
||||
while(dot_count < path.size && path.data[dot_count] == '.')
|
||||
dot_count++;
|
||||
|
||||
c11_sv top_filename = c11_string__sv(vm->top_frame->co->src->filename);
|
||||
int is_init = c11_sv__endswith(top_filename, (c11_sv){"__init__.py", 11});
|
||||
|
||||
py_Ref package = py_getdict(&vm->top_frame->module, __path__);
|
||||
c11_sv package_sv = py_tosv(package);
|
||||
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);
|
||||
if(package_sv.size == 0) {
|
||||
return ImportError("attempted relative import with no known parent package");
|
||||
}
|
||||
|
||||
c11_vector /* T=c11_sv */ cpnts = c11_sv__split(package_sv, '.');
|
||||
for(int i = is_init; i < dot_count; i++) {
|
||||
if(cpnts.count == 0)
|
||||
return ImportError("attempted relative import beyond top-level package");
|
||||
c11_vector__pop(&cpnts);
|
||||
}
|
||||
|
||||
if(dot_count < path.size) {
|
||||
c11_sv last_cpnt = c11_sv__slice(path, dot_count);
|
||||
c11_vector__push(c11_sv, &cpnts, last_cpnt);
|
||||
}
|
||||
|
||||
// join cpnts
|
||||
c11_sbuf buf;
|
||||
c11_sbuf__ctor(&buf);
|
||||
for(int i = 0; i < cpnts.count; i++) {
|
||||
if(i > 0) c11_sbuf__write_char(&buf, '.');
|
||||
c11_sbuf__write_sv(&buf, c11__getitem(c11_sv, &cpnts, i));
|
||||
}
|
||||
|
||||
c11_vector__dtor(&cpnts);
|
||||
c11_string* new_path = c11_sbuf__submit(&buf);
|
||||
int res = py_import(new_path->data);
|
||||
c11_string__delete(new_path);
|
||||
return ok;
|
||||
return res;
|
||||
}
|
||||
|
||||
assert(path.data[0] != '.' && path.data[path.size - 1] != '.');
|
||||
@ -74,17 +106,10 @@ bool py_import(const char* path_cstr) {
|
||||
// check existing module
|
||||
py_TmpRef ext_mod = py_getmodule(path.data);
|
||||
if(ext_mod) {
|
||||
py_Ref is_pending = py_getdict(ext_mod, __module_is_pending__);
|
||||
if(is_pending) return ImportError("circular import detected");
|
||||
py_assign(py_retval(), ext_mod);
|
||||
return true;
|
||||
}
|
||||
|
||||
// vector<std::string_view> path_cpnts = path.split('.');
|
||||
// // check circular import
|
||||
// if(__import_context.pending.size() > 128) { ImportError("maximum recursion depth exceeded
|
||||
// while importing"); }
|
||||
|
||||
// try import
|
||||
c11_string* slashed_path = c11_sv__replace(path, '.', PK_PLATFORM_SEP);
|
||||
c11_string* filename = c11_string__new3("%s.py", slashed_path->data);
|
||||
@ -96,33 +121,29 @@ bool py_import(const char* path_cstr) {
|
||||
goto __SUCCESS;
|
||||
}
|
||||
|
||||
c11_string__delete(filename);
|
||||
filename = c11_string__new3("%s.py", slashed_path->data);
|
||||
data = vm->import_file(slashed_path->data);
|
||||
data = vm->import_file(filename->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);
|
||||
data = vm->import_file(filename->data);
|
||||
if(data != NULL) goto __SUCCESS;
|
||||
|
||||
c11_string__delete(filename);
|
||||
c11_string__delete(slashed_path);
|
||||
return ImportError("module %q not found", path);
|
||||
return 0;
|
||||
|
||||
__SUCCESS:
|
||||
py_push(py_newmodule(path_cstr));
|
||||
py_Ref mod = py_peek(-1);
|
||||
py_setdict(mod, __module_is_pending__, py_True);
|
||||
bool ok = py_exec((const char*)data, filename->data, EXEC_MODE, mod);
|
||||
py_deldict(mod, __module_is_pending__);
|
||||
py_assign(py_retval(), mod);
|
||||
py_pop();
|
||||
|
||||
c11_string__delete(filename);
|
||||
c11_string__delete(slashed_path);
|
||||
if(need_free) free((void*)data);
|
||||
return ok;
|
||||
return ok ? 1 : -1;
|
||||
}
|
||||
|
||||
//////////////////////////
|
||||
|
@ -136,6 +136,21 @@ bool py_getattr(py_Ref self, py_Name name) {
|
||||
}
|
||||
}
|
||||
|
||||
if(self->type == tp_module) {
|
||||
py_Ref path = py_getdict(self, __path__);
|
||||
c11_sbuf buf;
|
||||
c11_sbuf__ctor(&buf);
|
||||
pk_sprintf(&buf, "%v.%n", py_tosv(path), name);
|
||||
c11_string* new_path = c11_sbuf__submit(&buf);
|
||||
int res = py_import(new_path->data);
|
||||
c11_string__delete(new_path);
|
||||
if(res == -1) {
|
||||
return false;
|
||||
} else if(res == 1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return AttributeError(self, name);
|
||||
}
|
||||
|
||||
|
@ -247,9 +247,7 @@ static bool _py_str__startswith(int argc, py_Ref argv) {
|
||||
c11_string* self = py_touserdata(&argv[0]);
|
||||
PY_CHECK_ARG_TYPE(1, tp_str);
|
||||
c11_string* other = py_touserdata(&argv[1]);
|
||||
c11_sv _0 = c11_sv__slice2(c11_string__sv(self), 0, other->size);
|
||||
c11_sv _1 = c11_string__sv(other);
|
||||
py_newbool(py_retval(), c11__sveq(_0, _1));
|
||||
py_newbool(py_retval(), c11_sv__startswith(c11_string__sv(self), c11_string__sv(other)));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -258,9 +256,7 @@ static bool _py_str__endswith(int argc, py_Ref argv) {
|
||||
c11_string* self = py_touserdata(&argv[0]);
|
||||
PY_CHECK_ARG_TYPE(1, tp_str);
|
||||
c11_string* other = py_touserdata(&argv[1]);
|
||||
c11_sv _0 = c11_sv__slice2(c11_string__sv(self), self->size - other->size, self->size);
|
||||
c11_sv _1 = c11_string__sv(other);
|
||||
py_newbool(py_retval(), c11__sveq(_0, _1));
|
||||
py_newbool(py_retval(), c11_sv__endswith(c11_string__sv(self), c11_string__sv(other)));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -538,10 +534,6 @@ bool py_str(py_Ref val) {
|
||||
return py_call(tmp, 1, val);
|
||||
}
|
||||
|
||||
bool py_repr(py_Ref val) {
|
||||
return pk_callmagic(__repr__, 1, val);
|
||||
}
|
||||
bool py_repr(py_Ref val) { return pk_callmagic(__repr__, 1, val); }
|
||||
|
||||
bool py_len(py_Ref val){
|
||||
return pk_callmagic(__len__, 1, val);
|
||||
}
|
||||
bool py_len(py_Ref val) { return pk_callmagic(__len__, 1, val); }
|
@ -29,6 +29,11 @@ void py_setdict(py_Ref self, py_Name name, py_Ref val) {
|
||||
}
|
||||
}
|
||||
|
||||
py_TmpRef py_emplacedict(py_Ref self, py_Name name){
|
||||
py_setdict(self, name, py_NIL);
|
||||
return py_getdict(self, name);
|
||||
}
|
||||
|
||||
bool py_deldict(py_Ref self, py_Name name) {
|
||||
assert(self && self->is_ptr);
|
||||
if(!py_ismagicname(name) || self->type != tp_type) {
|
||||
|
@ -4,6 +4,7 @@ except ImportError:
|
||||
exit(0)
|
||||
|
||||
os.chdir('tests')
|
||||
assert os.getcwd().endswith('tests')
|
||||
|
||||
import test1
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user