blueloveTH 1 tahun lalu
induk
melakukan
1735e0d3b8
4 mengubah file dengan 85 tambahan dan 44 penghapusan
  1. 2 3
      src/interpreter/vm.c
  2. 74 40
      src/public/modules.c
  3. 5 1
      src/public/py_object.c
  4. 4 0
      tests/50_reflection.py

+ 2 - 3
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")));

+ 74 - 40
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>", 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>", 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;
 }
 
-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, "exec", builtins__exec);
-    py_bindfunc(builtins, "eval", builtins__eval);
+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));
+}
 
-    py_bind(builtins, "print(*args, sep=' ', end='\\n')", builtins__print);
-    py_bind(builtins, "sorted(iterable, key=None, reverse=False)", builtins__sorted);
+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;
+}
 
-    py_bindfunc(builtins, "isinstance", builtins__isinstance);
-    py_bindfunc(builtins, "issubclass", builtins__issubclass);
+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_bindfunc(builtins, "getattr", builtins__getattr);
+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, "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_bindfunc(builtins, "isinstance", builtins_isinstance);
+    py_bindfunc(builtins, "issubclass", builtins_issubclass);
+
+    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(), "<nativefunc object>");
     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;
 }
 

+ 5 - 1
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;
 }
 

+ 4 - 0
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')