diff --git a/src/interpreter/vm.c b/src/interpreter/vm.c index ced3829c..d2331139 100644 --- a/src/interpreter/vm.c +++ b/src/interpreter/vm.c @@ -167,9 +167,8 @@ void VM__ctor(VM* self) { tp_BaseException, tp_Exception, tp_StopIteration, tp_SyntaxError}; for(int i = 0; i < c11__count_array(public_types); i++) { - py_Type t = public_types[i]; - py_TypeInfo* ti = c11__at(py_TypeInfo, &self->types, t); - py_setdict(&self->builtins, ti->name, py_tpobject(t)); + py_TypeInfo* ti = c11__at(py_TypeInfo, &self->types, public_types[i]); + py_setdict(&self->builtins, ti->name, &ti->self); } py_newnotimplemented(py_emplacedict(&self->builtins, py_name("NotImplemented"))); diff --git a/src/public/modules.c b/src/public/modules.c index 88f49bc8..e83e0c97 100644 --- a/src/public/modules.c +++ b/src/public/modules.c @@ -148,12 +148,12 @@ __SUCCESS: ////////////////////////// -static bool builtins__repr(int argc, py_Ref argv) { +static bool builtins_repr(int argc, py_Ref argv) { PY_CHECK_ARGC(1); return py_repr(argv); } -static bool builtins__exit(int argc, py_Ref argv) { +static bool builtins_exit(int argc, py_Ref argv) { int code = 0; if(argc > 1) return TypeError("exit() takes at most 1 argument"); if(argc == 1) { @@ -165,12 +165,12 @@ static bool builtins__exit(int argc, py_Ref argv) { return false; } -static bool builtins__len(int argc, py_Ref argv) { +static bool builtins_len(int argc, py_Ref argv) { PY_CHECK_ARGC(1); return py_len(argv); } -static bool builtins__reversed(int argc, py_Ref argv) { +static bool builtins_reversed(int argc, py_Ref argv) { PY_CHECK_ARGC(1); // convert _0 to list object if(!py_tpcall(tp_list, 1, argv)) return false; @@ -178,7 +178,7 @@ static bool builtins__reversed(int argc, py_Ref argv) { return true; } -static bool builtins__hex(int argc, py_Ref argv) { +static bool builtins_hex(int argc, py_Ref argv) { PY_CHECK_ARGC(1); PY_CHECK_ARG_TYPE(0, tp_int); @@ -208,12 +208,12 @@ static bool builtins__hex(int argc, py_Ref argv) { return true; } -static bool builtins__iter(int argc, py_Ref argv) { +static bool builtins_iter(int argc, py_Ref argv) { PY_CHECK_ARGC(1); return py_iter(argv); } -static bool builtins__next(int argc, py_Ref argv) { +static bool builtins_next(int argc, py_Ref argv) { PY_CHECK_ARGC(1); int res = py_next(argv); if(res == -1) return false; @@ -221,7 +221,7 @@ static bool builtins__next(int argc, py_Ref argv) { return py_exception(tp_StopIteration, ""); } -static bool builtins__sorted(int argc, py_Ref argv) { +static bool builtins_sorted(int argc, py_Ref argv) { PY_CHECK_ARGC(3); // convert _0 to list object if(!py_tpcall(tp_list, 1, py_arg(0))) return false; @@ -238,7 +238,7 @@ static bool builtins__sorted(int argc, py_Ref argv) { return true; } -static bool builtins__hash(int argc, py_Ref argv) { +static bool builtins_hash(int argc, py_Ref argv) { PY_CHECK_ARGC(1); py_i64 val; if(!py_hash(argv, &val)) return false; @@ -246,12 +246,12 @@ static bool builtins__hash(int argc, py_Ref argv) { return true; } -static bool builtins__abs(int argc, py_Ref argv) { +static bool builtins_abs(int argc, py_Ref argv) { PY_CHECK_ARGC(1); return pk_callmagic(__abs__, 1, argv); } -static bool builtins__sum(int argc, py_Ref argv) { +static bool builtins_sum(int argc, py_Ref argv) { PY_CHECK_ARGC(1); if(!py_iter(py_arg(0))) return false; @@ -288,7 +288,7 @@ static bool builtins__sum(int argc, py_Ref argv) { return true; } -static bool builtins__print(int argc, py_Ref argv) { +static bool builtins_print(int argc, py_Ref argv) { int length; py_TValue* args = pk_arrayview(argv, &length); assert(args != NULL); @@ -314,19 +314,19 @@ static bool NoneType__repr__(int argc, py_Ref argv) { return true; } -static bool builtins__exec(int argc, py_Ref argv) { +static bool builtins_exec(int argc, py_Ref argv) { PY_CHECK_ARGC(1); PY_CHECK_ARG_TYPE(0, tp_str); return py_exec(py_tostr(argv), "", EXEC_MODE, NULL); } -static bool builtins__eval(int argc, py_Ref argv) { +static bool builtins_eval(int argc, py_Ref argv) { PY_CHECK_ARGC(1); PY_CHECK_ARG_TYPE(0, tp_str); return py_exec(py_tostr(argv), "", EVAL_MODE, NULL); } -static bool builtins__isinstance(int argc, py_Ref argv) { +static bool builtins_isinstance(int argc, py_Ref argv) { PY_CHECK_ARGC(2); if(py_istuple(py_arg(1))) { int length = py_tuple__len(py_arg(1)); @@ -347,7 +347,7 @@ static bool builtins__isinstance(int argc, py_Ref argv) { return true; } -static bool builtins__issubclass(int argc, py_Ref argv) { +static bool builtins_issubclass(int argc, py_Ref argv) { PY_CHECK_ARGC(2); if(!py_checktype(py_arg(0), tp_type)) return false; if(!py_checktype(py_arg(1), tp_type)) return false; @@ -355,7 +355,7 @@ static bool builtins__issubclass(int argc, py_Ref argv) { return true; } -static bool builtins__getattr(int argc, py_Ref argv) { +static bool builtins_getattr(int argc, py_Ref argv) { PY_CHECK_ARG_TYPE(1, tp_str); py_Name name = py_namev(py_tosv(py_arg(1))); if(argc == 2) { @@ -365,7 +365,8 @@ static bool builtins__getattr(int argc, py_Ref argv) { bool ok = py_getattr(py_arg(0), name); if(!ok && py_matchexc(tp_AttributeError)) { py_clearexc(p0); - return py_arg(2); // default value + py_assign(py_retval(), py_arg(2)); + return true; // default value } return ok; } else { @@ -374,29 +375,62 @@ static bool builtins__getattr(int argc, py_Ref argv) { return true; } +static bool builtins_setattr(int argc, py_Ref argv) { + PY_CHECK_ARGC(3); + PY_CHECK_ARG_TYPE(1, tp_str); + py_Name name = py_namev(py_tosv(py_arg(1))); + return py_setattr(py_arg(0), name, py_arg(2)); +} + +static bool builtins_hasattr(int argc, py_Ref argv) { + PY_CHECK_ARGC(2); + PY_CHECK_ARG_TYPE(1, tp_str); + py_Name name = py_namev(py_tosv(py_arg(1))); + bool ok = py_getattr(py_arg(0), name); + if(ok) { + py_newbool(py_retval(), true); + return true; + } + if(py_matchexc(tp_AttributeError)) { + py_newbool(py_retval(), false); + return true; + } + return false; +} + +static bool builtins_delattr(int argc, py_Ref argv) { + PY_CHECK_ARGC(2); + PY_CHECK_ARG_TYPE(1, tp_str); + py_Name name = py_namev(py_tosv(py_arg(1))); + return py_delattr(py_arg(0), name); +} + py_TValue pk_builtins__register() { py_Ref builtins = py_newmodule("builtins"); - py_bindfunc(builtins, "repr", builtins__repr); - py_bindfunc(builtins, "exit", builtins__exit); - py_bindfunc(builtins, "len", builtins__len); - py_bindfunc(builtins, "reversed", builtins__reversed); - py_bindfunc(builtins, "hex", builtins__hex); - py_bindfunc(builtins, "iter", builtins__iter); - py_bindfunc(builtins, "next", builtins__next); - py_bindfunc(builtins, "hash", builtins__hash); - py_bindfunc(builtins, "abs", builtins__abs); - py_bindfunc(builtins, "sum", builtins__sum); + py_bindfunc(builtins, "repr", builtins_repr); + py_bindfunc(builtins, "exit", builtins_exit); + py_bindfunc(builtins, "len", builtins_len); + py_bindfunc(builtins, "reversed", builtins_reversed); + py_bindfunc(builtins, "hex", builtins_hex); + py_bindfunc(builtins, "iter", builtins_iter); + py_bindfunc(builtins, "next", builtins_next); + py_bindfunc(builtins, "hash", builtins_hash); + py_bindfunc(builtins, "abs", builtins_abs); + py_bindfunc(builtins, "sum", builtins_sum); - py_bindfunc(builtins, "exec", builtins__exec); - py_bindfunc(builtins, "eval", builtins__eval); + py_bindfunc(builtins, "exec", builtins_exec); + py_bindfunc(builtins, "eval", builtins_eval); - py_bind(builtins, "print(*args, sep=' ', end='\\n')", builtins__print); - py_bind(builtins, "sorted(iterable, key=None, reverse=False)", builtins__sorted); + py_bind(builtins, "print(*args, sep=' ', end='\\n')", builtins_print); + py_bind(builtins, "sorted(iterable, key=None, reverse=False)", builtins_sorted); - py_bindfunc(builtins, "isinstance", builtins__isinstance); - py_bindfunc(builtins, "issubclass", builtins__issubclass); + py_bindfunc(builtins, "isinstance", builtins_isinstance); + py_bindfunc(builtins, "issubclass", builtins_issubclass); - py_bindfunc(builtins, "getattr", builtins__getattr); + py_bindfunc(builtins, "getattr", builtins_getattr); + py_bindfunc(builtins, "setattr", builtins_setattr); + py_bindfunc(builtins, "hasattr", builtins_hasattr); + py_bindfunc(builtins, "delattr", builtins_delattr); // None __repr__ py_bindmagic(tp_NoneType, __repr__, NoneType__repr__); @@ -435,7 +469,7 @@ py_Type pk_function__register() { return type; } -static bool nativefunc__repr(int argc, py_Ref argv) { +static bool nativefunc__repr__(int argc, py_Ref argv) { PY_CHECK_ARGC(1); py_newstr(py_retval(), ""); return true; @@ -443,7 +477,7 @@ static bool nativefunc__repr(int argc, py_Ref argv) { py_Type pk_nativefunc__register() { py_Type type = pk_newtype("nativefunc", tp_object, NULL, NULL, false, true); - py_bindmagic(type, __repr__, nativefunc__repr); + py_bindmagic(type, __repr__, nativefunc__repr__); return type; } diff --git a/src/public/py_object.c b/src/public/py_object.c index e39015f8..1709de23 100644 --- a/src/public/py_object.c +++ b/src/public/py_object.c @@ -64,7 +64,11 @@ static bool type__base__getter(int argc, py_Ref argv) { PY_CHECK_ARGC(1); py_Type type = py_totype(argv); py_TypeInfo* ti = c11__at(py_TypeInfo, &pk_current_vm->types, type); - py_assign(py_retval(), py_tpobject(ti->base)); + if(ti->base){ + py_assign(py_retval(), py_tpobject(ti->base)); + }else{ + py_newnone(py_retval()); + } return true; } diff --git a/tests/50_reflection.py b/tests/50_reflection.py index 7140a853..50433fc7 100644 --- a/tests/50_reflection.py +++ b/tests/50_reflection.py @@ -13,7 +13,11 @@ assert getattr(1, '__add__')(2) == 3 a = object() setattr(a, 'b', 1) assert a.b == 1 +assert hasattr(a, 'b') assert getattr(a, 'b') == 1 +assert getattr(a, 'c', ...) == ... +delattr(a, 'b') +assert not hasattr(a, 'b') try: getattr(a, 'xxx')