1.1 --- a/lib/__builtins__/identity.py Thu Nov 24 00:58:36 2016 +0100
1.2 +++ b/lib/__builtins__/identity.py Thu Nov 24 18:55:10 2016 +0100
1.3 @@ -19,31 +19,68 @@
1.4 this program. If not, see <http://www.gnu.org/licenses/>.
1.5 """
1.6
1.7 -from native import _isinstance
1.8 +from native import _isinstance, _issubclass
1.9 +
1.10 +def callable(obj):
1.11 +
1.12 + "Return whether 'obj' is callable."
1.13 +
1.14 + # NOTE: Classes and functions are callable, modules are not callable,
1.15 + # NOTE: only instances with __call__ methods should be callable.
1.16 +
1.17 + pass
1.18 +
1.19 +def help(*args):
1.20 +
1.21 + # NOTE: This should show any docstring, but it is currently unsupported.
1.22
1.23 -def callable(obj): pass
1.24 -def help(*args): pass
1.25 -def id(obj): pass
1.26 + pass
1.27 +
1.28 +def id(obj):
1.29 +
1.30 + # NOTE: This should show an object's address, but it is currently
1.31 + # NOTE: unsupported.
1.32 +
1.33 + pass
1.34 +
1.35 +def isclass(obj):
1.36 +
1.37 + "Return whether 'obj' is a class."
1.38 +
1.39 + return obj.__class__ is type
1.40
1.41 def isinstance(obj, cls_or_tuple):
1.42
1.43 """
1.44 Return whether 'obj' is an instance of 'cls_or_tuple', where the latter is
1.45 - either a class or a tuple of classes.
1.46 + either a class or a sequence of classes.
1.47 """
1.48
1.49 - # NOTE: CPython insists on tuples, but any sequence might be considered
1.50 - # NOTE: acceptable.
1.51 -
1.52 if _isinstance(cls_or_tuple, tuple):
1.53 for cls in cls_or_tuple:
1.54 - if obj.__class__ is cls or _isinstance(obj, cls):
1.55 + if obj.__class__ is cls or isclass(cls) and _isinstance(obj, cls):
1.56 return True
1.57 return False
1.58 else:
1.59 - return obj.__class__ is cls_or_tuple or _isinstance(obj, cls_or_tuple)
1.60 + return obj.__class__ is cls_or_tuple or isclass(cls_or_tuple) and _isinstance(obj, cls_or_tuple)
1.61 +
1.62 +def issubclass(obj, cls_or_tuple):
1.63 +
1.64 + """
1.65 + Return whether 'obj' is a class that is a subclass of 'cls_or_tuple', where
1.66 + the latter is either a class or a sequence of classes. If 'obj' is the same
1.67 + as the given class or classes, True is also returned.
1.68 + """
1.69
1.70 -def issubclass(obj, cls_or_tuple): pass
1.71 + if not isclass(obj):
1.72 + return False
1.73 + elif _isinstance(cls_or_tuple, tuple):
1.74 + for cls in cls_or_tuple:
1.75 + if obj is cls or isclass(cls) and _issubclass(obj, cls):
1.76 + return True
1.77 + return False
1.78 + else:
1.79 + return obj is cls_or_tuple or isclass(cls_or_tuple) and _issubclass(obj, cls_or_tuple)
1.80
1.81 def repr(obj):
1.82
2.1 --- a/lib/native.py Thu Nov 24 00:58:36 2016 +0100
2.2 +++ b/lib/native.py Thu Nov 24 18:55:10 2016 +0100
2.3 @@ -68,6 +68,7 @@
2.4 def _object_getattr(obj, name, default): pass
2.5
2.6 def _isinstance(obj, cls): pass
2.7 +def _issubclass(obj, cls): pass
2.8
2.9 def _read(fd, n): pass
2.10 def _write(fd, str): pass
3.1 --- a/templates/native.c Thu Nov 24 00:58:36 2016 +0100
3.2 +++ b/templates/native.c Thu Nov 24 18:55:10 2016 +0100
3.3 @@ -13,7 +13,7 @@
3.4
3.5 /* Utility functions. */
3.6
3.7 -inline __attr __new_int(int i)
3.8 +static __attr __new_int(int i)
3.9 {
3.10 /* Create a new integer and mutate the __data__ attribute. */
3.11 __attr attr = __new(&__InstanceTable___builtins___int_int, &__builtins___int_int, sizeof(__obj___builtins___int_int));
3.12 @@ -21,7 +21,7 @@
3.13 return attr;
3.14 }
3.15
3.16 -inline __attr __new_str(char *s)
3.17 +static __attr __new_str(char *s)
3.18 {
3.19 /* Create a new string and mutate the __data__ attribute. */
3.20 __attr attr = __new(&__InstanceTable___builtins___str_string, &__builtins___str_string, sizeof(__obj___builtins___str_string));
3.21 @@ -512,12 +512,30 @@
3.22 return __builtins___none_None;
3.23 }
3.24
3.25 +static int __issubclass(__ref obj, __attr cls)
3.26 +{
3.27 + return (__HASATTR(obj, __TYPEPOS(cls.value), __TYPECODE(cls.value)));
3.28 +}
3.29 +
3.30 __attr __fn_native__isinstance(__attr __args[])
3.31 {
3.32 __attr * const obj = &__args[1];
3.33 __attr * const cls = &__args[2];
3.34
3.35 - if (__is_instance(obj->value) && __HASATTR(__get_class(obj->value), __TYPEPOS(cls->value), __TYPECODE(cls->value)))
3.36 + /* cls must be a class. */
3.37 + if (__is_instance(obj->value) && __issubclass(__get_class(obj->value), *cls))
3.38 + return __builtins___boolean_True;
3.39 + else
3.40 + return __builtins___boolean_False;
3.41 +}
3.42 +
3.43 +__attr __fn_native__issubclass(__attr __args[])
3.44 +{
3.45 + __attr * const obj = &__args[1];
3.46 + __attr * const cls = &__args[2];
3.47 +
3.48 + /* obj and cls must be classes. */
3.49 + if (__issubclass(obj->value, *cls))
3.50 return __builtins___boolean_True;
3.51 else
3.52 return __builtins___boolean_False;
4.1 --- a/templates/native.h Thu Nov 24 00:58:36 2016 +0100
4.2 +++ b/templates/native.h Thu Nov 24 18:55:10 2016 +0100
4.3 @@ -57,6 +57,7 @@
4.4 __attr __fn_native__object_getattr(__attr __args[]);
4.5
4.6 __attr __fn_native__isinstance(__attr __args[]);
4.7 +__attr __fn_native__issubclass(__attr __args[]);
4.8
4.9 __attr __fn_native__read(__attr __args[]);
4.10 __attr __fn_native__write(__attr __args[]);
5.1 --- a/templates/ops.c Thu Nov 24 00:58:36 2016 +0100
5.2 +++ b/templates/ops.c Thu Nov 24 18:55:10 2016 +0100
5.3 @@ -53,6 +53,11 @@
5.4 return __load_via_object(obj, __pos___class__).value;
5.5 }
5.6
5.7 +__attr __get_class_attr(__ref obj)
5.8 +{
5.9 + return __load_via_object(obj, __pos___class__);
5.10 +}
5.11 +
5.12 /* Attribute testing operations. */
5.13
5.14 __ref __test_specific_instance(__ref obj, __ref type)
6.1 --- a/templates/ops.h Thu Nov 24 00:58:36 2016 +0100
6.2 +++ b/templates/ops.h Thu Nov 24 18:55:10 2016 +0100
6.3 @@ -24,6 +24,7 @@
6.4
6.5 int __is_instance(__ref obj);
6.6 __ref __get_class(__ref obj);
6.7 +__attr __get_class_attr(__ref obj);
6.8
6.9 /* Attribute testing operations. */
6.10
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/tests/identity.py Thu Nov 24 18:55:10 2016 +0100
7.3 @@ -0,0 +1,58 @@
7.4 +print isinstance("string", string) # True
7.5 +print isinstance("string", int) # False
7.6 +print isinstance(123, int) # True
7.7 +print isinstance(123, string) # False
7.8 +print
7.9 +
7.10 +class A:
7.11 + pass
7.12 +
7.13 +class B(A):
7.14 + pass
7.15 +
7.16 +class C(B):
7.17 + pass
7.18 +
7.19 +a = A()
7.20 +b = B()
7.21 +c = C()
7.22 +
7.23 +print isinstance(a, A) # True
7.24 +print isinstance(b, B) # True
7.25 +print isinstance(c, C) # True
7.26 +print
7.27 +print isinstance(a, a) # False
7.28 +print isinstance(b, b) # False
7.29 +print isinstance(c, c) # False
7.30 +print
7.31 +print isinstance(A, a) # False
7.32 +print isinstance(B, b) # False
7.33 +print isinstance(C, c) # False
7.34 +print
7.35 +print isinstance(a, B) # False
7.36 +print isinstance(b, C) # False
7.37 +print isinstance(c, A) # True
7.38 +print
7.39 +print isinstance(a, C) # False
7.40 +print isinstance(b, A) # True
7.41 +print isinstance(c, B) # True
7.42 +print
7.43 +print issubclass(A, A) # True
7.44 +print issubclass(B, B) # True
7.45 +print issubclass(C, C) # True
7.46 +print
7.47 +print issubclass(a, a) # False
7.48 +print issubclass(b, b) # False
7.49 +print issubclass(c, c) # False
7.50 +print
7.51 +print issubclass(a, A) # False
7.52 +print issubclass(b, B) # False
7.53 +print issubclass(c, C) # False
7.54 +print
7.55 +print issubclass(A, B) # False
7.56 +print issubclass(B, C) # False
7.57 +print issubclass(C, A) # True
7.58 +print
7.59 +print issubclass(A, C) # False
7.60 +print issubclass(B, A) # True
7.61 +print issubclass(C, B) # True