# HG changeset patch # User Paul Boddie # Date 1283714080 -7200 # Node ID 76db40f8dd8c39ac803665d1ff3aa748bac2aa08 # Parent 454d8255a4b117e7fd05aab6ffb86625d5a305fa Introduced an "in assignment" flag to distinguish between slice and subscript retrieval and assignment operations. Moved slice and subscript support into various operator module functions. diff -r 454d8255a4b1 -r 76db40f8dd8c lib/operator.py --- a/lib/operator.py Sun Sep 05 02:20:05 2010 +0200 +++ b/lib/operator.py Sun Sep 05 21:14:40 2010 +0200 @@ -220,4 +220,20 @@ def ne(a, b): return binary_op(a, b, lambda a: a.__ne__, lambda b: b.__ne__) +# Access and slicing functions. + +def getitem(a, b): + return a.__getitem__(b) + +def setitem(a, b, c): + a.__setitem__(b, c) + +# NOTE: Should be able to optimise temporary instance allocations for slices. + +def getslice(a, b, c): + return a.__getitem__(slice(b, c)) + +def setslice(a, b, c, d): + a.__setitem__(slice(b, c), d) + # vim: tabstop=4 expandtab shiftwidth=4 diff -r 454d8255a4b1 -r 76db40f8dd8c micropython/ast.py --- a/micropython/ast.py Sun Sep 05 02:20:05 2010 +0200 +++ b/micropython/ast.py Sun Sep 05 21:14:40 2010 +0200 @@ -86,6 +86,7 @@ self.loop_blocks = [] self.exception_blocks = [] self.in_exception_handler = 0 + self.in_assignment = 0 # for slicing and subscript self.reset() @@ -415,36 +416,29 @@ self._visitName(node, self.name_load_instructions) def visitSlice(self, node): + args = [node.expr] + if node.lower is None: + args.append(compiler.ast.Name("None")) if node.upper is None: - args = [] + args.append(compiler.ast.Name("None")) else: - args = [compiler.ast.Name("None"), node.upper] + args.append(node.upper) else: - args = [node.lower] + args.append(node.lower) if node.upper is None: args.append(compiler.ast.Name("None")) else: args.append(node.upper) - # NOTE: Need to guarantee reliable access to the slice built-in. - - slice = compiler.ast.CallFunc(compiler.ast.Name("slice"), args) - - self.dispatch(node.expr) - self._startCallFunc() - self._generateAttr(node, "__getitem__", self.attribute_load_instructions) - temp_target, target, temp_context = self._generateCallFunc([slice], node) - self._doCallFunc(temp_target, target) - self._endCallFunc(temp_target, temp_context) + temp_fn = self._getOperatorFunction(node, self.in_assignment and "AssSlice" or "Slice") + self._visitCall(node, temp_fn, args) + self.discard_temp(temp_fn) def visitSubscript(self, node): - self.dispatch(node.expr) - self._startCallFunc() - self._generateAttr(node, "__getitem__", self.attribute_load_instructions) - temp_target, target, temp_context = self._generateCallFunc(node.subs, node) - self._doCallFunc(temp_target, target) - self._endCallFunc(temp_target, temp_context) + temp_fn = self._getOperatorFunction(node, self.in_assignment and "AssSubscript" or "Subscript") + self._visitCall(node, temp_fn, [node.expr] + node.subs) + self.discard_temp(temp_fn) def visitTuple(self, node): self._generateTuple(node) @@ -464,9 +458,12 @@ self.record_value(self.has_immediate_usage(node.nodes)) + self.in_assignment = 1 + for n in node.nodes: self.dispatch(n) + self.in_assignment = 0 self.discard_value() def visitAssAttr(self, node): @@ -527,7 +524,7 @@ # Find the augmented assignment function and attempt to use it. temp_fn = self._getOperatorAugAssignFunction(node) - self._visitBinaryCall(node, temp_fn, node.node, node.expr) + self._visitCall(node, temp_fn, (node.node, node.expr)) self.discard_temp(temp_fn) # Assign the result to the name. diff -r 454d8255a4b1 -r 76db40f8dd8c micropython/common.py --- a/micropython/common.py Sun Sep 05 02:20:05 2010 +0200 +++ b/micropython/common.py Sun Sep 05 21:14:40 2010 +0200 @@ -283,7 +283,14 @@ "<" : "lt", "<=" : "le", ">=" : "ge", - ">" : "gt" + ">" : "gt", + + # Access and slicing. + + "AssSlice" : "setslice", + "Slice" : "getslice", + "AssSubscript" : "setitem", + "Subscript" : "getitem", } # vim: tabstop=4 expandtab shiftwidth=4 diff -r 454d8255a4b1 -r 76db40f8dd8c micropython/inspect.py --- a/micropython/inspect.py Sun Sep 05 02:20:05 2010 +0200 +++ b/micropython/inspect.py Sun Sep 05 21:14:40 2010 +0200 @@ -105,6 +105,7 @@ # Current expression state. self.expr = None + self.in_assignment = 0 # For slice and subscript handling. # Namespace state. @@ -416,12 +417,12 @@ module = attr.get_value() return module - def _visitOperator(self, node): + def _visitOperator(self, node, operator_name=None): "Accounting method for the operator 'node'." operator_module = self._ensureOperators() - operator_fn = operator_functions[node.__class__.__name__] + operator_fn = operator_functions[operator_name or node.__class__.__name__] self.use_specific_attribute(operator_module.full_name(), operator_fn) return self.OP(node) @@ -552,8 +553,10 @@ def visitAssign(self, node): self.expr = self.dispatch(node.expr) + self.in_assignment = 1 for n in node.nodes: self.dispatch(n) + self.in_assignment = 0 return None def visitAssAttr(self, node): @@ -977,15 +980,7 @@ visitRightShift = _visitBinary def visitSlice(self, node): - expr = self.dispatch(node.expr) - self._visitAttr(expr, "__getitem__", node) - - if node.lower is not None: - self.dispatch(node.lower) - if node.upper is not None: - self.dispatch(node.upper) - - self.use_specific_attribute("__builtins__", "slice") + self._visitOperator(node, self.in_assignment and "AssSlice" or "Slice") visitSliceobj = OP @@ -997,11 +992,7 @@ visitSub = _visitBinary def visitSubscript(self, node): - expr = self.dispatch(node.expr) - self._visitAttr(expr, "__getitem__", node) - - for sub in node.subs: - self.dispatch(sub) + self._visitOperator(node, self.in_assignment and "AssSubscript" or "Subscript") def visitTryExcept(self, node): self.dispatch(node.body) diff -r 454d8255a4b1 -r 76db40f8dd8c micropython/trans.py --- a/micropython/trans.py Sun Sep 05 02:20:05 2010 +0200 +++ b/micropython/trans.py Sun Sep 05 21:14:40 2010 +0200 @@ -1261,28 +1261,9 @@ """ temp_fn = self._getOperatorFunction(node) - self._visitUnaryCall(node, temp_fn, node.expr) + self._visitCall(node, temp_fn, (node.expr,)) self.discard_temp(temp_fn) - def _visitUnaryCall(self, node, temp_fn, expr): - - """ - Invoke the appropriate operator module function for the operation - represented by 'node', given a 'temp_fn' reference to a function, along - with the 'expr' operand node. - """ - - # Evaluate and store the operand in temporary storage. - - self.dispatch(expr) - temp = self.optimiser.optimise_temp_storage() - - self._generateInvocation(temp_fn, (temp,)) - - # Compilation duties... - - self.discard_temp(temp) - def _visitBinaryBit(self, node): """ @@ -1296,7 +1277,7 @@ for right in node.nodes: if left is not None: - self._visitBinaryCall(node, temp_fn, left, right) + self._visitCall(node, temp_fn, (left, right)) left = right self.discard_temp(temp_fn) @@ -1309,33 +1290,31 @@ """ temp_fn = self._getOperatorFunction(node) - self._visitBinaryCall(node, temp_fn, node.left, node.right) + self._visitCall(node, temp_fn, (node.left, node.right)) self.discard_temp(temp_fn) - def _visitBinaryCall(self, node, temp_fn, left, right): + def _visitCall(self, node, temp_fn, args): """ Invoke the appropriate operator module function for the operation represented by 'node', given a 'temp_fn' reference to a function, along - with the 'left' and 'right' operand nodes. + with the 'args' (the operand nodes). """ - # Evaluate and store the left operand in temporary storage. + # Evaluate and store the operands in temporary storage. - self.dispatch(left) - temp1 = self.optimiser.optimise_temp_storage() + temp_list = [] - # Evaluate and store the right operand in temporary storage. + for arg in args: + self.dispatch(arg) + temp_list.append(self.optimiser.optimise_temp_storage()) - self.dispatch(right) - temp2 = self.optimiser.optimise_temp_storage() - - self._generateInvocation(temp_fn, (temp1, temp2)) + self._generateInvocation(temp_fn, temp_list) # Compilation duties... - self.discard_temp(temp1) - self.discard_temp(temp2) + for temp in temp_list: + self.discard_temp(temp) def _generateInvocation(self, temp_fn, temp_list): @@ -1354,11 +1333,11 @@ self._doCallFunc(temp_fn) self._endCallFunc(temp_fn) - def _getOperatorFunction(self, node): + def _getOperatorFunction(self, node, operator_name=None): "Return an operator function reference for the given 'node'." - return self._generateOperatorFunction(node.__class__.__name__) + return self._generateOperatorFunction(operator_name or node.__class__.__name__) def _getOperatorAugAssignFunction(self, node):