1.1 --- a/micropython/__init__.py Sun May 08 20:31:23 2011 +0200
1.2 +++ b/micropython/__init__.py Sun May 08 22:15:28 2011 +0200
1.3 @@ -573,6 +573,31 @@
1.4
1.5 self.attribute_users_visited.add(from_name)
1.6
1.7 + # The getattr function is a special case: it can potentially reference
1.8 + # any known attribute. Since accessor attributes must be known
1.9 + # constants, the intersection of known constants and attributes is used
1.10 + # to build a set of objects that might be referenced by getattr.
1.11 +
1.12 + if from_name == "__builtins__.getattr":
1.13 + all_attributes = set(objtable.attribute_names())
1.14 + all_string_constants = set([const.get_value() for const in self.constants() if const.value_type_name() == "__builtins__.str"])
1.15 + all_attribute_constants = all_attributes.intersection(all_string_constants)
1.16 +
1.17 + # Get the types supporting each attribute and visit the referenced
1.18 + # objects.
1.19 +
1.20 + all_objtypes = set()
1.21 +
1.22 + for attrname in all_attribute_constants:
1.23 + objtypes = objtable.any_possible_objects_plus_status([attrname])
1.24 + all_objtypes.update(objtypes)
1.25 +
1.26 + # Attribute assignment does not take place, so an empty list of
1.27 + # values is given.
1.28 +
1.29 + self._collect_attributes_for_types(from_name, objtable, all_objtypes,
1.30 + [{attrname : []} for attrname in all_attribute_constants])
1.31 +
1.32 # Get name references and find possible objects which support such
1.33 # combinations of attribute names.
1.34
1.35 @@ -600,48 +625,7 @@
1.36 user._attrtypes = {}
1.37
1.38 user._attrtypes[name] = all_objtypes
1.39 -
1.40 - # For each suggested object type, consider each attribute given by
1.41 - # the names.
1.42 -
1.43 - for objname, is_static in all_objtypes:
1.44 - for attrnames in usage:
1.45 - for attrname, attrvalues in attrnames.items():
1.46 -
1.47 - # Test for the presence of an attribute on the suggested
1.48 - # object type.
1.49 -
1.50 - try:
1.51 - attr = objtable.access(objname, attrname)
1.52 - except TableError:
1.53 - #print "Warning: object type %r does not support attribute %r" % (objname, attrname)
1.54 - continue
1.55 -
1.56 - # Get the real identity of the attribute in order to
1.57 - # properly collect usage from it.
1.58 -
1.59 - parent = attr.parent
1.60 - if isinstance(parent, micropython.data.Instance):
1.61 - parentname = objname
1.62 - else:
1.63 - parentname = parent.full_name()
1.64 -
1.65 - # Test for assignment.
1.66 -
1.67 - if attrvalues:
1.68 - for attrvalue in attrvalues:
1.69 - parent.set(attrname, attrvalue, 0)
1.70 -
1.71 - # Visit attributes of objects known to be used.
1.72 -
1.73 - if parentname in self.attributes_used:
1.74 - self.use_attribute(parentname, attrname)
1.75 - self._collect_attributes_from(from_name, parentname, attrname, objtable)
1.76 -
1.77 - # Record attributes of other objects for potential visiting.
1.78 -
1.79 - else:
1.80 - self.add_attribute_to_visit(parentname, attrname)
1.81 + self._collect_attributes_for_types(from_name, objtable, all_objtypes, usage)
1.82
1.83 # Get specific name references and visit the referenced objects.
1.84
1.85 @@ -669,6 +653,54 @@
1.86 self.use_attribute(from_name, attrname)
1.87 self._collect_attributes_from(from_name, from_name, attrname, objtable)
1.88
1.89 + def _collect_attributes_for_types(self, from_name, objtable, objtypes, usage):
1.90 +
1.91 + """
1.92 + For the unit known as 'from_name' and using the 'objtable' to validate
1.93 + each attribute, identify and attempt to visit attributes found for each
1.94 + of the suggested object types given by 'objtypes' and the 'usage'
1.95 + provided.
1.96 + """
1.97 +
1.98 + for objname, is_static in objtypes:
1.99 + for attrnames in usage:
1.100 + for attrname, attrvalues in attrnames.items():
1.101 +
1.102 + # Test for the presence of an attribute on the suggested
1.103 + # object type.
1.104 +
1.105 + try:
1.106 + attr = objtable.access(objname, attrname)
1.107 + except TableError:
1.108 + #print "Warning: object type %r does not support attribute %r" % (objname, attrname)
1.109 + continue
1.110 +
1.111 + # Get the real identity of the attribute in order to
1.112 + # properly collect usage from it.
1.113 +
1.114 + parent = attr.parent
1.115 + if isinstance(parent, micropython.data.Instance):
1.116 + parentname = objname
1.117 + else:
1.118 + parentname = parent.full_name()
1.119 +
1.120 + # Test for assignment.
1.121 +
1.122 + if attrvalues:
1.123 + for attrvalue in attrvalues:
1.124 + parent.set(attrname, attrvalue, 0)
1.125 +
1.126 + # Visit attributes of objects known to be used.
1.127 +
1.128 + if parentname in self.attributes_used:
1.129 + self.use_attribute(parentname, attrname)
1.130 + self._collect_attributes_from(from_name, parentname, attrname, objtable)
1.131 +
1.132 + # Record attributes of other objects for potential visiting.
1.133 +
1.134 + else:
1.135 + self.add_attribute_to_visit(parentname, attrname)
1.136 +
1.137 # Constant accounting.
1.138
1.139 def init_predefined_constants(self):
2.1 --- a/rsvplib.py Sun May 08 20:31:23 2011 +0200
2.2 +++ b/rsvplib.py Sun May 08 22:15:28 2011 +0200
2.3 @@ -483,7 +483,7 @@
2.4
2.5 index = self.machine.load(name_value.ref + self.instance_data_offset + 1)
2.6
2.7 - # NOTE: This is very much like LoadAttrIndex.
2.8 + # NOTE: This is very much like LoadAttrIndexContextCond.
2.9
2.10 data = self.machine.load(obj_value.ref)
2.11 element = self.machine.objlist[data.classcode + index]
2.12 @@ -492,7 +492,11 @@
2.13 attr_index, static_attr, offset = element
2.14 if attr_index == index:
2.15 if static_attr:
2.16 - self.machine.result = self.machine.load(offset) # offset is address of class/module attribute
2.17 + loaded_value = self.machine.load(offset) # offset is address of class/module attribute
2.18 + if data.attrcode is None: # absent attrcode == class/module
2.19 + self.machine.result = loaded_value
2.20 + else:
2.21 + self.machine.result = self.machine._LoadAddressContextCond(loaded_value.context, loaded_value.ref, obj_value.ref)
2.22 else:
2.23 self.machine.result = self.machine.load(obj_value.ref + offset)
2.24 return