1.1 --- a/TO_DO.txt Tue Aug 31 00:59:16 2010 +0200
1.2 +++ b/TO_DO.txt Sat Sep 04 00:55:37 2010 +0200
1.3 @@ -1,7 +1,20 @@
1.4 +Support slicing. This is difficult because __getitem__ has to handle integers and slice
1.5 +objects differently. One could either just try and iterate over the argument and then
1.6 +catch the AttributeError for integers, or one could test the instances first.
1.7 +
1.8 +Support isinstance. Like slicing, the problem is dealing with the class or tuple input
1.9 +to the function. A strict tuple check is permissible according to the CPython behaviour,
1.10 +but an iterable would be more elegant (as would *args).
1.11 +
1.12 +Consider attribute usage observations being suspended inside blocks where AttributeError
1.13 +may be caught (although this doesn't anticipate such exceptions being caught outside a
1.14 +function altogether).
1.15 +
1.16 Fix object table entries for attributes not provided by any known object, or provide an
1.17 error, potentially overridden by options. For example, the augmented assignment methods
1.18 are not supported by the built-in objects and thus the operator module functions cause
1.19 -the compilation to fail.
1.20 +the compilation to fail. Alternatively, just supply the methods since something has to do
1.21 +so in the builtins.
1.22
1.23 Support tuple parameters.
1.24
1.25 @@ -45,8 +58,6 @@
1.26
1.27 __getitem__ could be written in Python, using a native method only to access fragments.
1.28
1.29 -Support slicing.
1.30 -
1.31 Consider better "macro" support where new expressions need to be generated and processed.
1.32
1.33 **** Constant attribute users need not maintain usage since they are already resolved. ****
2.1 --- a/micropython/inspect.py Tue Aug 31 00:59:16 2010 +0200
2.2 +++ b/micropython/inspect.py Sat Sep 04 00:55:37 2010 +0200
2.3 @@ -416,7 +416,7 @@
2.4 module = attr.get_value()
2.5 return module
2.6
2.7 - def _visitUnary(self, node):
2.8 + def _visitOperator(self, node):
2.9
2.10 "Accounting method for the operator 'node'."
2.11
2.12 @@ -425,7 +425,45 @@
2.13 self.use_specific_attribute(operator_module.full_name(), operator_fn)
2.14 return self.OP(node)
2.15
2.16 - _visitBinary = _visitUnary
2.17 + _visitBinary = _visitOperator
2.18 + _visitUnary = _visitOperator
2.19 +
2.20 + def _visitAttr(self, expr, attrname, node):
2.21 +
2.22 + # Attempt to identify the nature of the attribute.
2.23 +
2.24 + if isinstance(expr, Attr):
2.25 + value = expr.get_value()
2.26 +
2.27 + # Get the attribute and record its usage.
2.28 +
2.29 + if isinstance(value, (Class, Module)):
2.30 + attr = value.get(attrname)
2.31 + self.use_specific_attribute(value.full_name(), attrname)
2.32 +
2.33 + elif isinstance(value, UnresolvedName):
2.34 + attr = UnresolvedName(attrname, value.full_name(), self)
2.35 +
2.36 + else:
2.37 + attr = None
2.38 +
2.39 + # Note usage of the attribute where a local is involved.
2.40 +
2.41 + if expr.parent is self.get_namespace():
2.42 + node._attrusers = self.use_attribute(expr.name, attrname)
2.43 + node._username = expr.name
2.44 + else:
2.45 + self.use_name(attrname, node.expr)
2.46 +
2.47 + elif self.builtins is not None:
2.48 + attr = self.builtins.get(attrname)
2.49 + self.use_specific_attribute(self.builtins.full_name(), attrname)
2.50 +
2.51 + else:
2.52 + attr = None
2.53 + self.use_name(attrname, node)
2.54 +
2.55 + return attr
2.56
2.57 def _visitFunction(self, node, name):
2.58
2.59 @@ -806,40 +844,7 @@
2.60 def visitGetattr(self, node):
2.61 expr = self.dispatch(node.expr)
2.62 attrname = node.attrname
2.63 -
2.64 - # Attempt to identify the nature of the attribute.
2.65 -
2.66 - if isinstance(expr, Attr):
2.67 - value = expr.get_value()
2.68 -
2.69 - # Get the attribute and record its usage.
2.70 -
2.71 - if isinstance(value, (Class, Module)):
2.72 - attr = value.get(attrname)
2.73 - self.use_specific_attribute(value.full_name(), attrname)
2.74 -
2.75 - elif isinstance(value, UnresolvedName):
2.76 - attr = UnresolvedName(attrname, value.full_name(), self)
2.77 -
2.78 - else:
2.79 - attr = None
2.80 -
2.81 - # Note usage of the attribute where a local is involved.
2.82 -
2.83 - if expr.parent is self.get_namespace():
2.84 - node._attrusers = self.use_attribute(expr.name, attrname)
2.85 - node._username = expr.name
2.86 - else:
2.87 - self.use_name(attrname, node.expr)
2.88 -
2.89 - elif self.builtins is not None:
2.90 - attr = self.builtins.get(attrname)
2.91 - self.use_specific_attribute(self.builtins.full_name(), attrname)
2.92 -
2.93 - else:
2.94 - attr = UnresolvedName(attrname, value.full_name(), self)
2.95 -
2.96 - return attr
2.97 + return self._visitAttr(expr, attrname, node)
2.98
2.99 def visitGlobal(self, node):
2.100 if self.namespaces:
2.101 @@ -972,9 +977,15 @@
2.102 visitRightShift = _visitBinary
2.103
2.104 def visitSlice(self, node):
2.105 + expr = self.dispatch(node.expr)
2.106 + self._visitAttr(expr, "__getitem__", node)
2.107 +
2.108 + if node.lower is not None:
2.109 + self.dispatch(node.lower)
2.110 + if node.upper is not None:
2.111 + self.dispatch(node.upper)
2.112 +
2.113 self.use_specific_attribute("__builtins__", "slice")
2.114 - self.use_name("__getitem__", node)
2.115 - self.OP(node)
2.116
2.117 visitSliceobj = OP
2.118
2.119 @@ -986,8 +997,11 @@
2.120 visitSub = _visitBinary
2.121
2.122 def visitSubscript(self, node):
2.123 - self.use_name("__getitem__", node)
2.124 - self.OP(node)
2.125 + expr = self.dispatch(node.expr)
2.126 + self._visitAttr(expr, "__getitem__", node)
2.127 +
2.128 + for sub in node.subs:
2.129 + self.dispatch(sub)
2.130
2.131 def visitTryExcept(self, node):
2.132 self.dispatch(node.body)
3.1 --- a/rsvplib.py Tue Aug 31 00:59:16 2010 +0200
3.2 +++ b/rsvplib.py Sat Sep 04 00:55:37 2010 +0200
3.3 @@ -291,16 +291,24 @@
3.4 header = self.machine.load(fragment.ref)
3.5 nelements = header.occupied_size - 1
3.6
3.7 - # NOTE: Assume single location for data and header.
3.8 + # Test operand suitability.
3.9 +
3.10 + if self.machine._CheckInstance(item_value.ref, self.int_class):
3.11
3.12 - item_pos = self.machine.load(item_value.ref + 1)
3.13 + # NOTE: Assume single location for data and header.
3.14 +
3.15 + item_pos = self.machine.load(item_value.ref + 1)
3.16
3.17 - if item_pos >= 0 and item_pos < nelements:
3.18 - pass
3.19 - elif item_pos < 0 and item_pos >= -nelements:
3.20 - item_pos = nelements + item_pos
3.21 + if item_pos >= 0 and item_pos < nelements:
3.22 + pass
3.23 + elif item_pos < 0 and item_pos >= -nelements:
3.24 + item_pos = nelements + item_pos
3.25 + else:
3.26 + self.machine.exception = self.machine._MakeObject(2, self.index_error_instance)
3.27 + return self.machine.RaiseException()
3.28 +
3.29 else:
3.30 - self.machine.exception = self.machine._MakeObject(2, self.index_error_instance)
3.31 + self.machine.exception = self.machine._MakeObject(2, self.type_error_instance)
3.32 return self.machine.RaiseException()
3.33
3.34 # NOTE: Assume single location for header.
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/tests/slice.py Sat Sep 04 00:55:37 2010 +0200
4.3 @@ -0,0 +1,9 @@
4.4 +#!/usr/bin/env python
4.5 +
4.6 +l = [1, 2, 3, 4, 5]
4.7 +
4.8 +result1_3 = len(l[2:])
4.9 +result_2 = len(l[:2])
4.10 +result2_3 = len(l[1:4])
4.11 +
4.12 +# vim: tabstop=4 expandtab shiftwidth=4