# HG changeset patch # User Paul Boddie # Date 1239058624 -7200 # Node ID b0e016b1312054a66ced35beab61a0f678ac46ea # Parent c78a7a57092d5cb8ff67daabe4b04b02f763ed4b Extended the concepts document, subsuming the remainder of the structures document. Added comments to the data module and removed the redundant clstable attribute from the Program class. diff -r c78a7a57092d -r b0e016b13120 docs/concepts.txt --- a/docs/concepts.txt Mon Apr 06 01:57:40 2009 +0200 +++ b/docs/concepts.txt Tue Apr 07 00:57:04 2009 +0200 @@ -2,8 +2,10 @@ ======== * Contexts and values - * Tables and lookups + * Tables, attributes and lookups * Objects and structures + * Parameters and lookups + * Instantiation Contexts and Values =================== @@ -95,8 +97,8 @@ See assignment.txt for details. -Tables and Lookups -================== +Tables, Attributes and Lookups +============================== Attribute lookups, where the exact location of an object attribute is deduced, are performed differently in micropython than in other implementations. @@ -109,15 +111,16 @@ classes to attribute names. For example: class A: - # has attributes x, y + # instances have attributes x, y class B(A): - # introduces attribute z + # introduces attribute z for instances class C: - # has attributes a, b, z + # instances have attributes a, b, z -This would provide the following table: +This would provide the following table, referred to as an object table in the +context of classes and instances: Class/attr a b x y z @@ -131,7 +134,7 @@ the instance or any superclass of the instance's class. The table can be compacted using a representation known as a displacement -list: +list (referred to as an object list in this context): Classes with attribute offsets @@ -150,6 +153,14 @@ attributes are defined, whereas the attrcode defines the offset within a region of attributes corresponding to a single attribute of a given name. +Attribute Locations +------------------- + +The locations stored in table/list elements are for instance attributes +relative to the location of the instance, whereas those for class attributes +and modules are absolute addresses (although these could also be changed to +object-relative locations). + Objects and Structures ====================== @@ -158,7 +169,9 @@ certain common features and operations are supported in the same way for all of these things. To permit this, a common data structure format is used. - Identifier Identifier Address Details Type Object ... + Header........................................ Attributes................. + + Identifier Identifier Address Details Object Object ... 0 1 2 3 4 5 6 classcode attrcode invocation invocation __class__ attribute ... @@ -167,23 +180,167 @@ reference Here, the classcode refers to the attribute lookup table for the object (as -described above). Since classes and instances share the same classcode, they -might resemble the following: +described above). Classes and instances share the same classcode, and their +structures reflect this. Functions all belong to the same type and thus employ +the classcode for the function built-in type, whereas modules have distinct +types since they must support different sets of attributes. Class C: 0 1 2 3 4 5 6 - code for C attrcode __new__ __new__ class type attribute ... - for C reference #args, reference reference + classcode attrcode __new__ __new__ class type attribute ... + for C for C reference #args, reference reference defaults reference Instance of C: 0 1 2 3 4 5 6 - code for C attrcode C.__call__ C.__call__ class C attribute ... - for C reference #args, reference reference + classcode attrcode C.__call__ C.__call__ class C attribute ... + for C for C reference #args, reference reference (if exists) defaults reference +Function f: + 0 1 2 3 4 5 6 + classcode attrcode code code class attribute ... + for for reference #args, function (default) + function function defaults reference reference + reference + +Module m: + + 0 1 2 3 4 5 6 + classcode attrcode (unused) (unused) module type attribute ... + for m for m reference (global) + reference + +The __class__ Attribute +----------------------- + +All objects support the __class__ attribute and this is illustrated above with +the first attribute. + +Class: refers to the type class (type.__class__ also refers to the type class) +Function: refers to the function class +Instance: refers to the class instantiated to make the object + +Testing Instance Compatibility with Classes (attrcode) +------------------------------------------------------ + +Although it would be possible to have a data structure mapping classes to +compatible classes, such as a matrix indicating the subclasses (or +superclasses) of each class, the need to retain the key to such a data +structure for each class might introduce a noticeable overhead. + +Instead of having a separate structure, descendant classes of each class are +inserted as special attributes into the object table. This requires an extra +key to be retained, since each class must provide its own attribute code such +that upon an instance/class compatibility test, the code may be obtained and +used in the object table. + +Invocation and Code References +------------------------------ + +Modules: there is no meaningful invocation reference since modules cannot be +explicitly called. + +Functions: a simple code reference is employed pointing to code implementing +the function. Note that the function locals are completely distinct from this +structure and are not comparable to attributes. Instead, attributes are +reserved for default parameter values, although they do not appear in the +object table described above, appearing instead in a separate parameter table +described below. + +Classes: given that classes must be invoked in order to create instances, a +reference must be provided in class structures. However, this reference does +not point directly at the __init__ method of the class. Instead, the +referenced code belongs to a special initialiser function, __new__, consisting +of the following instructions: + + create instance for C + call C.__init__(instance, ...) + return instance + +Instances: each instance employs a reference to any __call__ method defined in +the class hierarchy for the instance, thus maintaining its callable nature. + +Both classes and modules may contain code in their definitions - the former in +the "body" of the class, potentially defining attributes, and the latter as +the "top-level" code in the module, potentially defining attributes/globals - +but this code is not associated with any invocation target. It is thus +generated in order of appearance and is not referenced externally. + +Invocation Operation +-------------------- + +Consequently, regardless of the object an invocation is always done as +follows: + + get invocation reference from the header + jump to reference + +Additional preparation is necessary before the above code: positional +arguments must be saved in the invocation frame, and keyword arguments must be +resolved and saved to the appropriate position in the invocation frame. + +See invocation.txt for details. + +Parameters and Lookups +====================== + +Since Python supports keyword arguments when making invocations, it becomes +necessary to record the parameter names associated with each function or +method. Just as object tables record attributes positions on classes and +instances, parameter tables record parameter positions in function or method +parameter lists. + +For a given program, a parameter table can be considered as being like a +matrix mapping functions/methods to parameter names. For example: + + def f(x, y, z): + pass + + def g(a, b, c): + pass + + def h(a, x): + pass + +This would provide the following table, referred to as a parameter table in +the context of functions and methods: + + Function/param a b c x y z + + f 1 2 3 + g 1 2 3 + h 1 2 + +Just as with parameter tables, a displacement list can be prepared from a +parameter table: + + Functions with parameter (attribute) offsets + + funccode f + attrcode a b c x y z + + g + a b c x y z + + h + a b c x y z + + List . . . 1 2 3 1 2 3 1 . . 2 . . + +Here, the funccode refers to the offset in the list at which a function's +parameters are defined, whereas the attrcode defines the offset within a +region of attributes corresponding to a single parameter of a given name. + +Instantiation +============= + +When instantiating classes, memory must be reserved for the header of the +resulting instance, along with locations for the attributes of the instance. +Since the instance header contains data common to all instances of a class, a +template header is copied to the start of the newly reserved memory region. diff -r c78a7a57092d -r b0e016b13120 docs/structures.txt --- a/docs/structures.txt Mon Apr 06 01:57:40 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,116 +0,0 @@ -Data Structures -=============== - -The __class__ Attribute ------------------------ - -All objects support the __class__ attribute: - -Class: refers to the type class (type.__class__ also refers to the type class) -Function: refers to the function class -Instance: refers to the class instantiated to make the object - -Invocation ----------- - -The following actions need to be supported: - -Class: create instance, call __init__ with instance, return object -Function: call function body, return result -Instance: call __call__ method, return result - -Structure Layout ----------------- - -The __new__ reference would lead to code consisting of the following -instructions: - - create instance for C - call C.__init__(instance, ...) - return instance - -If C has a __call__ attribute, the invocation "slot" of C instances would -refer to the same thing as C.__call__. This "slot" has to be prepared when -creating instances, either by modifying the sequence of instructions used in, -amongst other places, the instantiator function, or by generating a template -instance whose details are copied when new instances are created. - -For functions, the same general layout applies: - -Function f: - - 0 1 2 3 4 5 6 - code for attrcode code code class attribute ... - function for reference #args, function (default) - function defaults reference reference - reference - -Here, the code reference would lead to code for the function. Note that the -function locals are completely distinct from this structure and are not -comparable to attributes. Instead, attributes are reserved for default -parameter values. - -For modules, there is no meaningful invocation reference: - -Module m: - - 0 1 2 3 4 5 6 - code for m attrcode (unused) (unused) module type attribute ... - for m reference (global) - reference - -Both classes and modules have code in their definitions, but this would be -generated in order and not referenced externally. - -Invocation Operation --------------------- - -Consequently, regardless of the object an invocation is always done as -follows: - - get invocation reference (at object+1) - jump to reference - -Additional preparation is necessary before the above code: positional -arguments must be saved to the parameter stack, and keyword arguments must be -resolved and saved to the appropriate position in the parameter stack. - -Attribute Operations --------------------- - -Attribute access needs to go through the attribute lookup table. Some -optimisations are possible and are described in the appropriate section. - -One important aspect of attribute access is the appropriate setting of the -context in the acquired attribute value. From the table describing the -acquisition of values, it is clear that the principal exception is that where -a class-originating attribute is accessed on an instance. Consequently, the -following algorithm could be employed once an attribute has been located: - - 1. If the attribute's context is a special value, indicating that it should - be replaced upon instance access, then proceed to the next step; - otherwise, acquire both the context and the object as they are. - - 2. If the accessor is an instance, use that as the value's context, acquiring - only the object from the attribute. - -Where accesses can be determined ahead of time (as discussed in the -optimisations section), the above algorithm may not necessarily be employed in -the generated code for some accesses. - -Instance/Class Compatibility ----------------------------- - -Although it would be possible to have a data structure mapping classes to -compatible classes, which in the case of context (or self argument) -suitability in invocations would involve a mapping from a class to itself plus -its descendants, the need to retain the key to such a data structure for each -class might introduce a noticeable overhead. Such a structure would -effectively be a matrix with each dimension indexed using the same sequence of -codes for each of the classes in a program. - -The current solution is to insert descendants as special attributes into the -object/attribute lookup table. This requires an extra key to be retained, -since each class must provide its own attribute code such that upon an -instance/class compatibility test, the code may be obtained and used in the -object table. diff -r c78a7a57092d -r b0e016b13120 micropython/__init__.py --- a/micropython/__init__.py Mon Apr 06 01:57:40 2009 +0200 +++ b/micropython/__init__.py Tue Apr 07 00:57:04 2009 +0200 @@ -74,7 +74,6 @@ self.objtable = None self.paramtable = None - self.clstable = None # Main program information. diff -r c78a7a57092d -r b0e016b13120 micropython/data.py --- a/micropython/data.py Mon Apr 06 01:57:40 2009 +0200 +++ b/micropython/data.py Tue Apr 07 00:57:04 2009 +0200 @@ -499,7 +499,7 @@ classcode = objtable.as_list().get_code(self.full_name()) attrcode = objtable.get_index(self.full_name()) - # Append a template of an instance for use when instantiating classes. + # Include a template of an instance for use when instantiating classes. call_method = self.get("__call__") call_method_value = call_method and call_method.get_value() @@ -510,6 +510,9 @@ instantiator_code_location = self.get_instantiator().blocks[0].location return [ + + # Template instance... + DataObject( classcode, attrcode, call_method_code_location, ( @@ -519,6 +522,9 @@ 1, self.full_name() ), + + # Class... + DataObject( classcode, attrcode, instantiator_code_location, (