This commit is contained in:
blueloveTH 2024-08-04 16:05:47 +08:00
parent 3c87bf8630
commit b1a8c6db8e
10 changed files with 43 additions and 15 deletions

View File

@ -271,12 +271,14 @@ bool py_import(const char* path) PY_RAISE;
bool py_exception(const char* name, const char* fmt, ...) PY_RAISE; bool py_exception(const char* name, const char* fmt, ...) PY_RAISE;
/// Raise an expection object. Always returns false. /// Raise an expection object. Always returns false.
bool py_raise(py_Ref) PY_RAISE; bool py_raise(py_Ref) PY_RAISE;
/// Print the last error to the console. /// Print the current exception.
void py_printexc(); void py_printexc();
/// Format the last error to a string. /// Format the current exception.
char* py_formatexc(); char* py_formatexc();
/// Check if an exception is raised. /// Check if an exception is raised.
bool py_checkexc(); bool py_checkexc();
/// Clear the current exception.
void py_clearexc(py_StackRef p0);
#define NameError(n) py_exception("NameError", "name '%n' is not defined", (n)) #define NameError(n) py_exception("NameError", "name '%n' is not defined", (n))
#define TypeError(...) py_exception("TypeError", __VA_ARGS__) #define TypeError(...) py_exception("TypeError", __VA_ARGS__)

View File

@ -56,6 +56,7 @@ with open("src/common/_generated.c", "wt", encoding='utf-8', newline='\n') as f:
f.write("\n") f.write("\n")
f.write("const char* load_kPythonLib(const char* name) {\n") f.write("const char* load_kPythonLib(const char* name) {\n")
f.write(" if (strchr(name, '.') != NULL) return NULL;\n")
for key in sorted(sources.keys()): for key in sorted(sources.keys()):
if key.startswith('_'): if key.startswith('_'):
continue continue

View File

@ -19,6 +19,7 @@ const char kPythonLibs_this[] = "print(\"\"\"The Zen of Python, by Tim Peters\n\
const char kPythonLibs_typing[] = "class _Placeholder:\n def __init__(self, *args, **kwargs):\n pass\n def __getitem__(self, *args):\n return self\n def __call__(self, *args, **kwargs):\n return self\n def __and__(self, other):\n return self\n def __or__(self, other):\n return self\n def __xor__(self, other):\n return self\n\n\n_PLACEHOLDER = _Placeholder()\n\nList = _PLACEHOLDER\nDict = _PLACEHOLDER\nTuple = _PLACEHOLDER\nSet = _PLACEHOLDER\nAny = _PLACEHOLDER\nUnion = _PLACEHOLDER\nOptional = _PLACEHOLDER\nCallable = _PLACEHOLDER\nType = _PLACEHOLDER\nProtocol = _PLACEHOLDER\n\nLiteral = _PLACEHOLDER\nLiteralString = _PLACEHOLDER\n\nIterable = _PLACEHOLDER\nGenerator = _PLACEHOLDER\n\nHashable = _PLACEHOLDER\n\nTypeVar = _PLACEHOLDER\nSelf = _PLACEHOLDER\n\nclass Generic:\n pass\n\nTYPE_CHECKING = False\n\n# decorators\noverload = lambda x: x\nfinal = lambda x: x\n"; const char kPythonLibs_typing[] = "class _Placeholder:\n def __init__(self, *args, **kwargs):\n pass\n def __getitem__(self, *args):\n return self\n def __call__(self, *args, **kwargs):\n return self\n def __and__(self, other):\n return self\n def __or__(self, other):\n return self\n def __xor__(self, other):\n return self\n\n\n_PLACEHOLDER = _Placeholder()\n\nList = _PLACEHOLDER\nDict = _PLACEHOLDER\nTuple = _PLACEHOLDER\nSet = _PLACEHOLDER\nAny = _PLACEHOLDER\nUnion = _PLACEHOLDER\nOptional = _PLACEHOLDER\nCallable = _PLACEHOLDER\nType = _PLACEHOLDER\nProtocol = _PLACEHOLDER\n\nLiteral = _PLACEHOLDER\nLiteralString = _PLACEHOLDER\n\nIterable = _PLACEHOLDER\nGenerator = _PLACEHOLDER\n\nHashable = _PLACEHOLDER\n\nTypeVar = _PLACEHOLDER\nSelf = _PLACEHOLDER\n\nclass Generic:\n pass\n\nTYPE_CHECKING = False\n\n# decorators\noverload = lambda x: x\nfinal = lambda x: x\n";
const char* load_kPythonLib(const char* name) { const char* load_kPythonLib(const char* name) {
if (strchr(name, '.') != NULL) return NULL;
if (strcmp(name, "bisect") == 0) return kPythonLibs_bisect; if (strcmp(name, "bisect") == 0) return kPythonLibs_bisect;
if (strcmp(name, "builtins") == 0) return kPythonLibs_builtins; if (strcmp(name, "builtins") == 0) return kPythonLibs_builtins;
if (strcmp(name, "cmath") == 0) return kPythonLibs_cmath; if (strcmp(name, "cmath") == 0) return kPythonLibs_cmath;

View File

@ -2477,6 +2477,7 @@ __EAT_DOTS_END:
OP_IMPORT_PATH, OP_IMPORT_PATH,
Ctx__add_const_string(ctx(), c11_string__sv(path)), Ctx__add_const_string(ctx(), c11_string__sv(path)),
prev()->line); prev()->line);
c11_string__delete(path);
consume(TK_IMPORT); consume(TK_IMPORT);
if(match(TK_MUL)) { if(match(TK_MUL)) {

View File

@ -920,7 +920,7 @@ pk_FrameResult pk_VM__run_top_frame(pk_VM* self) {
} }
case OP_POP_EXCEPTION: { case OP_POP_EXCEPTION: {
assert(self->curr_exception.type); assert(self->curr_exception.type);
self->curr_exception = *py_NIL; py_clearexc(NULL);
DISPATCH(); DISPATCH();
} }
////////////////// //////////////////

View File

@ -232,21 +232,29 @@ static bool _py_builtins__abs(int argc, py_Ref argv) {
static bool _py_builtins__sum(int argc, py_Ref argv) { static bool _py_builtins__sum(int argc, py_Ref argv) {
PY_CHECK_ARGC(1); PY_CHECK_ARGC(1);
int length;
py_TValue* p = pk_arrayview(argv, &length); if(!py_iter(py_arg(0))) return false;
if(!p) return TypeError("sum() expects a list or tuple"); py_push(py_retval()); // iter
py_i64 total_i64 = 0; py_i64 total_i64 = 0;
py_f64 total_f64 = 0.0; py_f64 total_f64 = 0.0;
bool is_float = false; bool is_float = false;
for(int i = 0; i < length; i++) { while(true) {
switch(p[i].type) { int res = py_next(py_peek(-1));
case tp_int: total_i64 += p[i]._i64; break; if(res == -1) {
py_pop();
return false;
}
if(res == 0) break;
py_Ref item = py_retval();
switch(item->type) {
case tp_int: total_i64 += item->_i64; break;
case tp_float: case tp_float:
is_float = true; is_float = true;
total_f64 += p[i]._f64; total_f64 += item->_f64;
break; break;
default: return TypeError("sum() expects a list of numbers"); default: return TypeError("sum() expects an iterable of numbers");
} }
} }
@ -255,6 +263,7 @@ static bool _py_builtins__sum(int argc, py_Ref argv) {
} else { } else {
py_newint(py_retval(), total_i64); py_newint(py_retval(), total_i64);
} }
py_pop();
return true; return true;
} }

View File

@ -115,6 +115,15 @@ bool py_checkexc() {
return !py_isnil(&vm->curr_exception); return !py_isnil(&vm->curr_exception);
} }
void py_clearexc(py_StackRef p0) {
pk_VM* vm = pk_current_vm;
vm->last_retval = *py_NIL;
vm->curr_exception = *py_NIL;
vm->is_stopiteration = false;
vm->__curr_class = NULL;
if(p0) vm->stack.sp = p0;
}
void py_printexc() { void py_printexc() {
char* msg = py_formatexc(); char* msg = py_formatexc();
if(!msg) return; if(!msg) return;

View File

@ -72,7 +72,12 @@ int py_next(py_Ref val) {
vm->is_stopiteration = false; vm->is_stopiteration = false;
py_Ref tmp = py_tpfindmagic(val->type, __next__); py_Ref tmp = py_tpfindmagic(val->type, __next__);
if(!tmp) return TypeError("'%t' object is not an iterator", val->type); if(!tmp) return TypeError("'%t' object is not an iterator", val->type);
py_StackRef p0 = py_peek(0);
if(py_call(tmp, 1, val)) return true; if(py_call(tmp, 1, val)) return true;
if(vm->curr_exception.type == tp_StopIteration) {
py_clearexc(p0);
vm->is_stopiteration = true;
}
return vm->is_stopiteration ? 0 : -1; return vm->is_stopiteration ? 0 : -1;
} }
@ -200,12 +205,12 @@ bool py_delitem(py_Ref self, py_Ref key) {
return ok; return ok;
} }
int py_equal(py_Ref lhs, py_Ref rhs){ int py_equal(py_Ref lhs, py_Ref rhs) {
if(!py_eq(lhs, rhs)) return -1; if(!py_eq(lhs, rhs)) return -1;
return py_bool(py_retval()); return py_bool(py_retval());
} }
int py_less(py_Ref lhs, py_Ref rhs){ int py_less(py_Ref lhs, py_Ref rhs) {
if(!py_lt(lhs, rhs)) return -1; if(!py_lt(lhs, rhs)) return -1;
return py_bool(py_retval()); return py_bool(py_retval());
} }

View File

@ -57,7 +57,7 @@ void py_assign(py_Ref dst, py_Ref src) { *dst = *src; }
/* Stack References */ /* Stack References */
py_Ref py_peek(int i) { py_Ref py_peek(int i) {
assert(i < 0); assert(i <= 0);
return pk_current_vm->stack.sp + i; return pk_current_vm->stack.sp + i;
} }

View File

@ -23,7 +23,7 @@ class Task:
def __next__(self): def __next__(self):
if self.i == self.n: if self.i == self.n:
return StopIteration raise StopIteration
self.i += 1 self.i += 1
return self.i return self.i