1.1 --- a/micropython/common.py Sun Dec 08 00:05:51 2013 +0100
1.2 +++ b/micropython/common.py Sun Dec 08 01:41:43 2013 +0100
1.3 @@ -117,14 +117,14 @@
1.4
1.5 return isinstance(value, (Const, Constant))
1.6
1.7 - def provides_self_access(self, node, unit):
1.8 + def provides_self_access(self, expr, unit):
1.9
1.10 """
1.11 - Return whether the 'node' in the given 'unit' provides a self-based
1.12 + Return whether the 'expr' in the given 'unit' provides a self-based
1.13 attribute access.
1.14 """
1.15
1.16 - attr_value = self.get_attribute_and_value(node._expr)
1.17 + attr_value = self.get_attribute_and_value(expr)
1.18
1.19 if attr_value:
1.20 target, value = attr_value
1.21 @@ -134,20 +134,19 @@
1.22
1.23 return False
1.24
1.25 - def possible_attributes_from_annotation(self, node):
1.26 + def possible_attributes_from_annotation(self, expr, attr, attrname):
1.27
1.28 """
1.29 - Return (attribute, value) details provided by any _expr or _attr
1.30 - annotations on 'node'.
1.31 + Return (attribute, value) details provided by the 'expr' or 'attr'
1.32 + annotations on a node for an access involving 'attrname'.
1.33 """
1.34
1.35 - attr_value = self.get_attribute_and_value(node._attr)
1.36 + attr_value = self.get_attribute_and_value(attr)
1.37
1.38 if attr_value:
1.39 return [attr_value]
1.40
1.41 attrs = set()
1.42 - expr = node._expr
1.43
1.44 if expr:
1.45
1.46 @@ -163,13 +162,13 @@
1.47 # attribute.
1.48
1.49 for expr in exprs:
1.50 - attr = expr.all_attributes().get(node.attrname)
1.51 + found_attr = expr.all_attributes().get(attrname)
1.52
1.53 # Where an attribute can be obtained, record its
1.54 # details.
1.55
1.56 - if attr:
1.57 - attrs.add((attr, attr.get_value()))
1.58 + if found_attr:
1.59 + attrs.add((found_attr, found_attr.get_value()))
1.60
1.61 return attrs
1.62
2.1 --- a/micropython/deduce.py Sun Dec 08 00:05:51 2013 +0100
2.2 +++ b/micropython/deduce.py Sun Dec 08 01:41:43 2013 +0100
2.3 @@ -90,8 +90,6 @@
2.4 that can be used by subsequent activities.
2.5 """
2.6
2.7 - unit = self.get_unit()
2.8 -
2.9 # Remember to permit deductions on the expression node. Here, we may
2.10 # also obtain a concrete type associated with an instantiation.
2.11
2.12 @@ -104,14 +102,24 @@
2.13 # an instance: all other "instances" may actually be classes in certain
2.14 # cases.
2.15
2.16 - target = node._expr
2.17 + self._annotateAttr(node, node._expr, node.attrname)
2.18 +
2.19 + def _annotateAttr(self, node, target, attrname):
2.20 +
2.21 + """
2.22 + Annotate the access on the given 'node' using the 'target' and
2.23 + 'attrname' information.
2.24 + """
2.25 +
2.26 + unit = self.get_unit()
2.27 +
2.28 instance_target = isinstance(target, TypedInstance)
2.29 typed_instance_attr = isinstance(target, BaseAttr) and isinstance(target.get_value(), TypedInstance)
2.30 - self_access = self.provides_self_access(node, unit)
2.31 + self_access = self.provides_self_access(target, unit)
2.32
2.33 # Attempt to deduce attributes from explicit annotations.
2.34
2.35 - node._attrs_deduced = attrs = self.possible_attributes_from_annotation(node)
2.36 + node._attrs_deduced = attrs = self.possible_attributes_from_annotation(target, node._attr, attrname)
2.37
2.38 if len(attrs) == 1:
2.39 for attr, value in attrs:
2.40 @@ -168,11 +176,11 @@
2.41
2.42 # Find instance attributes.
2.43
2.44 - attr = cls.instance_attributes().get(node.attrname)
2.45 + attr = cls.instance_attributes().get(attrname)
2.46
2.47 # Where self is involved, descendants can also provide attributes.
2.48
2.49 - attrs = self_access and filter(None, [desc.instance_attributes().get(node.attrname) for desc in cls.descendants]) or []
2.50 + attrs = self_access and filter(None, [desc.instance_attributes().get(attrname) for desc in cls.descendants]) or []
2.51
2.52 # A "leaf" class whose instances provide an attribute.
2.53
2.54 @@ -207,7 +215,7 @@
2.55 # The context will be overridden for compatible class attributes
2.56 # only.
2.57
2.58 - attr = cls.all_class_attributes().get(node.attrname)
2.59 + attr = cls.all_class_attributes().get(attrname)
2.60
2.61 if attr:
2.62
2.63 @@ -252,7 +260,7 @@
2.64 # only this attribute.
2.65
2.66 if not specific_targets or not targets:
2.67 - attribute_targets = self.possible_accessors_for_attribute(node.attrname)
2.68 + attribute_targets = self.possible_accessors_for_attribute(attrname)
2.69 if not specific_targets:
2.70 specific_targets = attribute_targets
2.71 if not targets:
2.72 @@ -260,8 +268,8 @@
2.73
2.74 # Get the attributes from the deduced targets.
2.75
2.76 - node._attrs_deduced_from_specific_usage = self.get_attributes(specific_targets, node.attrname)
2.77 - node._attrs_deduced_from_usage = attrs = self.get_attributes(targets, node.attrname)
2.78 + node._attrs_deduced_from_specific_usage = self.get_attributes(specific_targets, attrname)
2.79 + node._attrs_deduced_from_usage = attrs = self.get_attributes(targets, attrname)
2.80
2.81 # Generate optimisations where only a single attribute applies.
2.82
2.83 @@ -364,6 +372,28 @@
2.84 if value and isinstance(value, Class):
2.85 return TypedInstance(value)
2.86
2.87 + def _visitOperator(self, node):
2.88 +
2.89 + "Annotate operators with function information."
2.90 +
2.91 + self._annotateAttr(node, node._module, node._attr.name)
2.92 +
2.93 + visitAdd = \
2.94 + visitBitand = \
2.95 + visitBitor = \
2.96 + visitBitxor = \
2.97 + visitDiv = \
2.98 + visitFloorDiv = \
2.99 + visitInvert = \
2.100 + visitLeftShift = \
2.101 + visitMod = \
2.102 + visitMul = \
2.103 + visitPower = \
2.104 + visitRightShift = \
2.105 + visitSub = \
2.106 + visitUnaryAdd = \
2.107 + visitUnarySub = _visitOperator
2.108 +
2.109 # Convenience functions.
2.110
2.111 def deduce(program):
4.1 --- a/micropython/syspython.py Sun Dec 08 00:05:51 2013 +0100
4.2 +++ b/micropython/syspython.py Sun Dec 08 01:41:43 2013 +0100
4.3 @@ -556,32 +556,31 @@
4.4 # Expression-related helper methods.
4.5
4.6 def _visitBitBinary(self, node):
4.7 - op_name = operator_functions[node.__class__.__name__]
4.8 + attr = self._visitAttr(node, special_name(node._module.full_name()), node._attr.name)
4.9 last = self.dispatch(node.nodes[0])
4.10
4.11 for n in node.nodes[1:]:
4.12 - last = compiler.ast.CallFunc(
4.13 - special_name("apply"),
4.14 - [module_attribute("operator", op_name), last, self.dispatch(n)]
4.15 + last = self._visitCallFunc(
4.16 + node._attr,
4.17 + [attr, last, self.dispatch(n)]
4.18 )
4.19
4.20 return last
4.21
4.22 def _visitBinary(self, node):
4.23 - op_name = operator_functions[node.__class__.__name__]
4.24 + attr = self._visitAttr(node, special_name(node._module.full_name()), node._attr.name)
4.25
4.26 - return compiler.ast.CallFunc(
4.27 - special_name("apply"),
4.28 - [module_attribute("operator", op_name),
4.29 - self.dispatch(node.left), self.dispatch(node.right)]
4.30 + return self._visitCallFunc(
4.31 + node._attr,
4.32 + [attr, self.dispatch(node.left), self.dispatch(node.right)]
4.33 )
4.34
4.35 def _visitUnary(self, node):
4.36 - op_name = operator_functions[node.__class__.__name__]
4.37 + attr = self._visitAttr(node, special_name(node._module.full_name()), node._attr.name)
4.38
4.39 - return compiler.ast.CallFunc(
4.40 - special_name("apply"),
4.41 - [module_attribute("operator", op_name), self.dispatch(node.expr)]
4.42 + return self._visitCallFunc(
4.43 + node._attr,
4.44 + [attr, self.dispatch(node.expr)]
4.45 )
4.46
4.47 def _generateValue(self, value):
4.48 @@ -598,7 +597,7 @@
4.49
4.50 return None
4.51
4.52 - def _visitAttr(self, node, expr=None):
4.53 + def _visitAttr(self, node, accessor, attrname, expr=None):
4.54 unit = self.get_unit()
4.55
4.56 # Choose the appropriate special functions.
4.57 @@ -606,8 +605,6 @@
4.58 (opattrcontext, opattrcontextcond, opattr, opattrindexcontextcond, opconstant) = \
4.59 expr and assattr_functions or getattr_functions
4.60
4.61 - accessor = self.dispatch(node.expr)
4.62 -
4.63 # Generate already-deduced accesses.
4.64
4.65 if node._access_type == "constant":
4.66 @@ -646,13 +643,13 @@
4.67 # Handle unsupported operations.
4.68
4.69 if not op:
4.70 - raise TranslateError("Storing of class attribute %r via self not permitted." % node.attrname)
4.71 + raise TranslateError("Storing of class attribute %r via self not permitted." % attrname)
4.72
4.73 # Define the arguments: accessor, attribute name and optional value.
4.74
4.75 args = [
4.76 parent or accessor,
4.77 - special_name(node.attrname)
4.78 + special_name(attrname)
4.79 ]
4.80
4.81 if expr:
4.82 @@ -668,21 +665,21 @@
4.83 # Positioned accesses are normal accesses via instances.
4.84
4.85 if node._access_type == "positioned":
4.86 - args = [accessor, special_name(node.attrname)]
4.87 + args = [accessor, special_name(attrname)]
4.88 if expr:
4.89 args.append(expr)
4.90 return compiler.ast.CallFunc(special_name(opattr), args)
4.91
4.92 # With no usable deductions, generate a table-based access.
4.93
4.94 - args = [accessor, special_name(node.attrname)]
4.95 + args = [accessor, special_name(attrname)]
4.96 if expr:
4.97 args.append(expr)
4.98 access = compiler.ast.CallFunc(special_name(opattrindexcontextcond), args)
4.99
4.100 # class.__class__ => __builtins__.type
4.101
4.102 - if node.attrname == "__class__":
4.103 + if attrname == "__class__":
4.104
4.105 # storetemp(n, <accessor>)
4.106 # isclass(n) and __builtins__.type or <access>
4.107 @@ -724,7 +721,7 @@
4.108 if compiler.ast.is_deletion(node):
4.109 return compiler.ast.Stmt([])
4.110
4.111 - return self._visitAttr(node, expr)
4.112 + return self._visitAttr(node, self.dispatch(node.expr), node.attrname, expr)
4.113
4.114 def visitAssList(self, node, expr=None):
4.115
4.116 @@ -764,22 +761,20 @@
4.117
4.118 visitAssTuple = visitAssList
4.119
4.120 - def visitBitand(self, node):
4.121 - self._visitBitBinary(node)
4.122 + visitBitand = _visitBitBinary
4.123
4.124 - def visitBitor(self, node):
4.125 - self._visitBitBinary(node)
4.126 + visitBitor = _visitBitBinary
4.127
4.128 - def visitBitxor(self, node):
4.129 - self._visitBitBinary(node)
4.130 + visitBitxor = _visitBitBinary
4.131
4.132 def visitCallFunc(self, node):
4.133
4.134 # Determine whether the invocation target is known.
4.135
4.136 args = [self.dispatch(node.node)] + [self.dispatch(arg) for arg in node.args]
4.137 + return self._visitCallFunc(node.node, args, node.star_args, node.dstar_args)
4.138
4.139 - target = node.node
4.140 + def _visitCallFunc(self, target, args, star_args=None, dstar_args=None):
4.141
4.142 # Attribute information is only known for specific accessors.
4.143
4.144 @@ -830,8 +825,8 @@
4.145 return compiler.ast.CallFunc(
4.146 special_name(op),
4.147 args,
4.148 - node.star_args and self.dispatch(node.star_args),
4.149 - node.dstar_args and self.dispatch(node.dstar_args)
4.150 + star_args and self.dispatch(star_args),
4.151 + dstar_args and self.dispatch(dstar_args)
4.152 )
4.153
4.154 def visitCompare(self, node):
4.155 @@ -881,7 +876,7 @@
4.156 return self._visitBinary(node)
4.157
4.158 def visitGetattr(self, node, expr=None):
4.159 - return self._visitAttr(node, expr)
4.160 + return self._visitAttr(node, self.dispatch(node.expr), node.attrname, expr)
4.161
4.162 def visitGenExpr(self, node):
4.163 return compiler.ast.GenExpr(self.dispatch(node.code))