# HG changeset patch # User Paul Boddie # Date 1248034643 -7200 # Node ID be363259339cf02d54a9de8ab42dbf01c5331e43 # Parent 2c60577895f0ceddfef58fbe760a818f4321a5e0 Added a CheckExtra instruction in order to support star parameters. Removed star parameter presence from the CheckFrame instruction operand. Moved the list of instructions consuming the current value to the micropython.rsvp module. Split the extra argument tests into two separate tests respectively involving known and unknown invocation targets. diff -r 2c60577895f0 -r be363259339c micropython/ast.py --- a/micropython/ast.py Tue Jul 14 00:37:04 2009 +0200 +++ b/micropython/ast.py Sun Jul 19 22:17:23 2009 +0200 @@ -603,7 +603,7 @@ # Check the number of parameters and defaults. - self.new_op(CheckFrame((nparams, ndefaults, fn.has_star))) + self.new_op(CheckFrame((nparams, ndefaults))) if ndefaults > 0: self.new_op(LoadFunction(fn)) self.new_op(FillDefaults((nparams, ndefaults))) @@ -612,15 +612,19 @@ self.set_block(fn.body_block) + extend = ExtendFrame() + self.new_op(extend) + # For functions with star parameters, make a special list for the # extra arguments and re-map the parameter. if fn.has_star: self.new_op(CopyExtra(nparams)) - self.new_op(StoreName(nparams - 1)) + + # Ensure that the star parameter has a slot in the frame. - extend = ExtendFrame() - self.new_op(extend) + self.new_op(CheckExtra(nparams)) + self.new_op(StoreTemp(nparams)) self.dispatch(node.code) diff -r 2c60577895f0 -r be363259339c micropython/opt.py --- a/micropython/opt.py Tue Jul 14 00:37:04 2009 +0200 +++ b/micropython/opt.py Sun Jul 19 22:17:23 2009 +0200 @@ -184,21 +184,7 @@ to have the simple input registers as operands. """ - return isinstance(instruction, ( - StoreTemp, StoreFrame, StoreResult, StoreException, # as the value being stored - LoadAddressContext, LoadAddressContextCond, # as the object being referenced - LoadAttr, LoadAttrIndex, # LoadAttrIndexContext, # as the object being referenced - LoadAttrIndexContextCond, # as the object being referenced - StoreAttr, StoreAttrIndex, StoreCallable, # as the object being referenced - StoreFrameIndex, # as the object being referenced - StoreAddressContext, # as the context - LoadCallable, - TestIdentity, TestIdentityAddress, CheckSelf, # as one of the operands - CheckException, CheckFrame, FillDefaults, - MakeInstance, - CheckContext, CheckClass, - LoadContext # as the object providing the result - )) + return isinstance(instruction, simple_input_user_instructions) def is_resultant_no_operation(self, instruction): diff -r 2c60577895f0 -r be363259339c micropython/rsvp.py --- a/micropython/rsvp.py Tue Jul 14 00:37:04 2009 +0200 +++ b/micropython/rsvp.py Sun Jul 19 22:17:23 2009 +0200 @@ -210,6 +210,7 @@ # Access to frames upon invocation. class CheckFrame(Immediate): "Check the frame for the correct number of arguments." +class CheckExtra(Immediate): "Ensure that the frame can provide extra arguments." class FillDefaults(Immediate): "Fill frame positions with defaults, if appropriate." class ExtendFrame(Immediate): "Extend the current frame for temporary storage use." class CopyExtra(Immediate): "Copy extra arguments into a separate sequence, starting from the given position." @@ -256,4 +257,22 @@ CopyExtra ) +# Instructions which use the current value. + +simple_input_user_instructions = ( + StoreTemp, StoreFrame, StoreResult, StoreException, # as the value being stored + LoadAddressContext, LoadAddressContextCond, # as the object being referenced + LoadAttr, LoadAttrIndex, # LoadAttrIndexContext, # as the object being referenced + LoadAttrIndexContextCond, # as the object being referenced + StoreAttr, StoreAttrIndex, StoreCallable, # as the object being referenced + StoreFrameIndex, # as the object being referenced + StoreAddressContext, # as the context + LoadCallable, + TestIdentity, TestIdentityAddress, CheckSelf, # as one of the operands + CheckException, CheckFrame, FillDefaults, + MakeInstance, + CheckContext, CheckClass, + LoadContext # as the object providing the result + ) + # vim: tabstop=4 expandtab shiftwidth=4 diff -r 2c60577895f0 -r be363259339c rsvp.py --- a/rsvp.py Tue Jul 14 00:37:04 2009 +0200 +++ b/rsvp.py Sun Jul 19 22:17:23 2009 +0200 @@ -127,7 +127,7 @@ cls = self._get_class("__builtins__", "TypeError") self.type_error = cls.location self.type_error_instance = cls.instance_template_location - cls = self.machine._get_class("__builtins__", "tuple") + cls = self._get_class("__builtins__", "tuple") self.tuple_class = cls.location self.tuple_instance = cls.instance_template_location @@ -581,7 +581,7 @@ self.status = data.attrcode is None # absent attrcode == class def CheckFrame(self): - (nargs, ndefaults, has_star) = self.operand + (nargs, ndefaults) = self.operand # The frame is actually installed as the locals. # Retrieve the context from the first local. @@ -589,14 +589,25 @@ frame = self.local_sp_stack[-1] nlocals = len(self.frame_stack[frame:]) - # NOTE: Not testing (nlocals <= nargs or has_star) due to imprecise - # NOTE: invocation frame removal (after frame adjustment). - if not ((nargs - ndefaults) <= nlocals): raise Exception, "CheckFrame %r (%r <= %r <= %r)" % (self.operand, nargs - ndefaults, nlocals, nargs) self.exception = self._MakeObject(2, self.type_error_instance) return self.RaiseException() + def CheckExtra(self): + nargs = self.operand + + # The frame is actually installed as the locals. + # Retrieve the context from the first local. + + frame = self.local_sp_stack[-1] + nlocals = len(self.frame_stack[frame:]) + + # Provide the extra star parameter if necessary. + + if nlocals == nargs: + self.frame_stack.extend([None]) # ExtendFrame(1) + def FillDefaults(self): context, ref = self.value (nargs, ndefaults) = self.operand diff -r 2c60577895f0 -r be363259339c tests/call_func_extra.py --- a/tests/call_func_extra.py Tue Jul 14 00:37:04 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ -#!/usr/bin/env python - -def f(a, b, *c): - return c - -r1 = f(1, 2, 3) -r2 = f(1, b=2) -r3 = f(1, 2, 3, 4) - -g = f - -r4 = g(1, 2, 3) -r5 = g(1, b=2) -r6 = g(1, 2, 3, 4) - -def g(a, c, *b): - return b - -r7 = g(1, c=2) -r8 = g(1, 2, 3, 4) - -# vim: tabstop=4 expandtab shiftwidth=4 diff -r 2c60577895f0 -r be363259339c tests/call_func_extra_known.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/call_func_extra_known.py Sun Jul 19 22:17:23 2009 +0200 @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +def f(a, b, *c): + return c + +r1 = f(1, 2, 3) +r2 = f(1, b=2) +r3 = f(1, 2, 3, 4) + +result_0 = len(r2) +result_1 = len(r1) +result_2 = len(r3) +result_3 = r1[0] +result_4 = r3[1] + +# vim: tabstop=4 expandtab shiftwidth=4 diff -r 2c60577895f0 -r be363259339c tests/call_func_extra_unknown.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/call_func_extra_unknown.py Sun Jul 19 22:17:23 2009 +0200 @@ -0,0 +1,24 @@ +#!/usr/bin/env python + +def f(a, b, *c): + return c + +g = f + +r4 = g(1, 2, 3) +r5 = g(1, b=2) +r6 = g(1, 2, 3, 4) + +def g(a, c, *b): + return b + +r7 = g(1, c=2) +r8 = g(1, 2, 3, 4) + +result_0 = len(r5) +result_1 = len(r4) +result_2 = len(r6) +result2_0 = len(r7) +result2_2 = len(r8) + +# vim: tabstop=4 expandtab shiftwidth=4