# HG changeset patch # User Paul Boddie # Date 1480376839 -3600 # Node ID 5be8a7aa0f86686e47fe457fd600ac91e2b6d63e # Parent 5c63b82aa1caec1fc403d6fb9298f6bb93da0afa Support attribute accesses on the type class using other classes as contexts, treating self (the context) in type methods as either class or instance. This simplifies the str and repr functions but introduces a special case in the deducer for the type class and makes the __test_context operation more expensive for non-instance contexts. diff -r 5c63b82aa1ca -r 5be8a7aa0f86 deducer.py --- a/deducer.py Mon Nov 28 23:51:45 2016 +0100 +++ b/deducer.py Tue Nov 29 00:47:19 2016 +0100 @@ -1354,7 +1354,7 @@ "Return whether 'path' refers to a method." class_name, method_name = path.rsplit(".", 1) - return self.importer.classes.has_key(class_name) and class_name + return class_name != "__builtins__.core.type" and self.importer.classes.has_key(class_name) and class_name def init_reference_details(self, location): diff -r 5c63b82aa1ca -r 5be8a7aa0f86 generator.py --- a/generator.py Mon Nov 28 23:51:45 2016 +0100 +++ b/generator.py Tue Nov 29 00:47:19 2016 +0100 @@ -51,11 +51,12 @@ "A code generator." + # NOTE: These must be synchronised with the library. + function_type = "__builtins__.core.function" type_error_type = "__builtins__.core.TypeError" memory_error_type = "__builtins__.core.MemoryError" - - # NOTE: These must be synchronised with the library. + type_type = "__builtins__.core.type" predefined_constant_members = ( ("__builtins__.boolean", "False"), @@ -352,12 +353,18 @@ #define __FUNCTION_INSTANCE_SIZE %s #define __TYPE_ERROR_INSTANTIATOR %s #define __MEMORY_ERROR_INSTANTIATOR %s +#define __TYPE_CLASS_TYPE %s +#define __TYPE_CLASS_POS %s +#define __TYPE_CLASS_CODE %s #endif /* __PROGTYPES_H__ */""" % ( encode_path(self.function_type), encode_size("", self.function_type), encode_instantiator_pointer(self.type_error_type), - encode_instantiator_pointer(self.memory_error_type) + encode_instantiator_pointer(self.memory_error_type), + encode_path(self.type_type), + encode_symbol("pos", encode_type_attribute(self.type_type)), + encode_symbol("code", encode_type_attribute(self.type_type)), ) print >>f_signatures, """\ diff -r 5c63b82aa1ca -r 5be8a7aa0f86 inspector.py --- a/inspector.py Mon Nov 28 23:51:45 2016 +0100 +++ b/inspector.py Tue Nov 29 00:47:19 2016 +0100 @@ -530,7 +530,8 @@ self.set_name("__fn__") # special instantiator attribute self.set_name("__args__") # special instantiator attribute - self.assign_general_local("__name__", self.get_constant("string", class_name)) + self.set_name("__name__", self.get_constant("string", class_name).reference()) + self.process_structure_node(n.code) self.exit_namespace() self.in_class = in_class diff -r 5c63b82aa1ca -r 5be8a7aa0f86 lib/__builtins__/core.py --- a/lib/__builtins__/core.py Mon Nov 28 23:51:45 2016 +0100 +++ b/lib/__builtins__/core.py Tue Nov 29 00:47:19 2016 +0100 @@ -97,13 +97,21 @@ __repr__ = __str__ -class type(object): +class type: - "The class of all classes." + """ + The class of all classes. Methods of this class do not treat contexts as + instances, even though classes are meant to be instances of this class. + Instead, contexts are either classes or instances. + """ - # __str__ and __repr__ are handled by str and repr for classes. + def __str__(self): + + "Return a string representation." - pass + return self.__name__ + + __repr__ = __str__ class BaseException: diff -r 5c63b82aa1ca -r 5be8a7aa0f86 lib/__builtins__/identity.py --- a/lib/__builtins__/identity.py Mon Nov 28 23:51:45 2016 +0100 +++ b/lib/__builtins__/identity.py Tue Nov 29 00:47:19 2016 +0100 @@ -86,14 +86,8 @@ "Return a program representation for 'obj'." - # Classes do not provide __repr__ directly. - - if isclass(obj): - return obj.__name__ - # Class attributes of instances provide __repr__. - else: - return obj.__repr__() + return obj.__repr__() # vim: tabstop=4 expandtab shiftwidth=4 diff -r 5c63b82aa1ca -r 5be8a7aa0f86 lib/__builtins__/str.py --- a/lib/__builtins__/str.py Mon Nov 28 23:51:45 2016 +0100 +++ b/lib/__builtins__/str.py Tue Nov 29 00:47:19 2016 +0100 @@ -114,14 +114,8 @@ "Return the string representation of 'obj'." - # Classes do not provide __str__ directly. - - if isclass(obj): - return obj.__name__ - # Class attributes of instances provide __str__. - else: - return obj.__str__() + return obj.__str__() # vim: tabstop=4 expandtab shiftwidth=4 diff -r 5c63b82aa1ca -r 5be8a7aa0f86 templates/ops.c --- a/templates/ops.c Mon Nov 28 23:51:45 2016 +0100 +++ b/templates/ops.c Tue Nov 29 00:47:19 2016 +0100 @@ -59,6 +59,11 @@ return obj->pos == __INSTANCEPOS; } +int __is_type_instance(__ref obj) +{ + return __HASATTR(__get_class(obj), __TYPE_CLASS_POS, __TYPE_CLASS_CODE); +} + __ref __get_class(__ref obj) { return __load_via_object(obj, __pos___class__).value; @@ -186,6 +191,11 @@ else __raise_type_error(); + /* Test for access to a type class attribute using a type instance. */ + + if (__test_specific_type(attr.context, &__TYPE_CLASS_TYPE) && __is_type_instance(context)) + return __replace_context(context, attr); + /* Otherwise, preserve the attribute as retrieved. */ return attr; diff -r 5c63b82aa1ca -r 5be8a7aa0f86 templates/ops.h --- a/templates/ops.h Mon Nov 28 23:51:45 2016 +0100 +++ b/templates/ops.h Tue Nov 29 00:47:19 2016 +0100 @@ -24,6 +24,7 @@ /* Introspection. */ int __is_instance(__ref obj); +int __is_type_instance(__ref obj); __ref __get_class(__ref obj); __attr __get_class_attr(__ref obj);