diff --git a/python/collections.py b/python/collections.py index 8adffd76..98632b72 100644 --- a/python/collections.py +++ b/python/collections.py @@ -1,4 +1,3 @@ -from pkpy import _enable_instance_dict from typing import Generic, TypeVar, Iterable T = TypeVar('T') diff --git a/src/compiler/compiler.c b/src/compiler/compiler.c index b127a141..1f8d2401 100644 --- a/src/compiler/compiler.c +++ b/src/compiler/compiler.c @@ -1833,7 +1833,10 @@ static Error* exprName(Compiler* self) { py_Name name = py_namev(Token__sv(prev())); NameScope scope = name_scope(self); // promote this name to global scope if needed - if(c11_smallmap_n2i__contains(&ctx()->global_names, name)) { scope = NAME_GLOBAL; } + if(c11_smallmap_n2i__contains(&ctx()->global_names, name)) { + if(scope == NAME_GLOBAL_UNKNOWN) return SyntaxError(self, "cannot use global keyword here"); + scope = NAME_GLOBAL; + } NameExpr* e = NameExpr__new(prev()->line, name, scope); Ctx__s_push(ctx(), (Expr*)e); return NULL; diff --git a/src/public/modules.c b/src/public/modules.c index 3094b244..3dbfc7cc 100644 --- a/src/public/modules.c +++ b/src/public/modules.c @@ -5,6 +5,7 @@ #include "pocketpy/common/sstream.h" #include "pocketpy/interpreter/vm.h" #include "pocketpy/common/_generated.h" +#include py_Ref py_getmodule(const char* path) { VM* vm = pk_current_vm; @@ -231,6 +232,37 @@ static bool builtins_divmod(int argc, py_Ref argv) { return pk_callmagic(__divmod__, 2, argv); } +static bool builtins_round(int argc, py_Ref argv) { + py_i64 ndigits; + + if(argc == 1) { + ndigits = -1; + } else if(argc == 2) { + PY_CHECK_ARG_TYPE(1, tp_int); + ndigits = py_toint(py_arg(1)); + if(ndigits < 0) return ValueError("ndigits should be non-negative"); + } else { + return TypeError("round() takes 1 or 2 arguments"); + } + + if(py_isint(py_arg(0))) { + py_assign(py_retval(), py_arg(0)); + return true; + } + + PY_CHECK_ARG_TYPE(0, tp_float); + py_f64 x = py_tofloat(py_arg(0)); + py_f64 offset = x >= 0 ? 0.5 : -0.5; + if(ndigits == -1) { + py_newint(py_retval(), (py_i64)(x + offset)); + return true; + } + + py_f64 factor = pow(10, ndigits); + py_newfloat(py_retval(), (py_i64)(x * factor + offset) / factor); + return true; +} + static bool builtins_print(int argc, py_Ref argv) { int length; py_TValue* args = pk_arrayview(argv, &length); @@ -355,7 +387,7 @@ static bool builtins_ord(int argc, py_Ref argv) { static bool builtins_globals(int argc, py_Ref argv) { Frame* frame = pk_current_vm->top_frame; - if(frame->is_dynamic){ + if(frame->is_dynamic) { py_assign(py_retval(), &frame->p0[0]); return true; } @@ -363,9 +395,9 @@ static bool builtins_globals(int argc, py_Ref argv) { return true; } -static bool builtins_locals(int argc, py_Ref argv){ +static bool builtins_locals(int argc, py_Ref argv) { Frame* frame = pk_current_vm->top_frame; - if(frame->is_dynamic){ + if(frame->is_dynamic) { py_assign(py_retval(), &frame->p0[1]); return true; } @@ -377,7 +409,7 @@ static bool builtins_locals(int argc, py_Ref argv){ static bool _builtins_execdyn(const char* title, int argc, py_Ref argv, enum py_CompileMode mode) { PY_CHECK_ARG_TYPE(0, tp_str); Frame* frame = pk_current_vm->top_frame; - switch(argc){ + switch(argc) { case 1: { // system globals + system locals if(!builtins_globals(0, NULL)) return false; @@ -403,7 +435,7 @@ static bool _builtins_execdyn(const char* title, int argc, py_Ref argv, enum py_ return py_execdyn(py_tostr(argv), "", mode, frame->module); } -static bool builtins_exec(int argc, py_Ref argv){ +static bool builtins_exec(int argc, py_Ref argv) { return _builtins_execdyn("exec", argc, argv, EXEC_MODE); } @@ -437,6 +469,7 @@ py_TValue pk_builtins__register() { py_bindfunc(builtins, "hash", builtins_hash); py_bindfunc(builtins, "abs", builtins_abs); py_bindfunc(builtins, "divmod", builtins_divmod); + py_bindfunc(builtins, "round", builtins_round); py_bind(builtins, "print(*args, sep=' ', end='\\n')", builtins_print);