# HG changeset patch # User Paul Boddie # Date 1247524624 -7200 # Node ID 2c60577895f0ceddfef58fbe760a818f4321a5e0 # Parent 13558f703a70550be2568785911f6b010ee077fa Attempt to define a mechanism which makes star parameter values properly available. diff -r 13558f703a70 -r 2c60577895f0 docs/invocation.txt --- a/docs/invocation.txt Mon Jul 13 01:02:42 2009 +0200 +++ b/docs/invocation.txt Tue Jul 14 00:37:04 2009 +0200 @@ -209,7 +209,29 @@ One motivation: avoid explicitly making sequences. Opportunity: avoid expensive dynamic allocation of sequences? -Star parameters, known callables and sequences: +Star parameters, approach #1: + + Make a sequence to hold the extra arguments, either in the caller for known + callables or in the function itself. + + Such a sequence would need allocating and its contents copying from the + stack. + +Star parameters, approach #2: + + Keep the extra arguments in the stack. + + Access to the star parameter would need to consider assignment to other + things and "escape situations" for the parameter: + + def f(*args): + return args # need to allocate and return the sequence + + Access to elements of the extra argument sequence would behave slightly + differently to normal sequences, but this could be identified at + compile-time. + +Star parameters, known callables and sequences, approach #1: g(1, 2, 3, 4) # g known as function g(a, *args) at compile-time @@ -217,10 +239,17 @@ 1 -> argument #1 2 -> reference to sequence containing arguments #2, #3, #4 - (This according to approach #1 described for unknown callables. With approach - #2, normal argument positioning would occur.) +Star parameters, known callables and sequences, approach #2: + + g(1, 2, 3, 4) # g known as function g(a, *args) at compile-time -Star parameters, unknown callables: + g -> don't get any context information + 1 -> argument #1 + 2 -> argument #2 + 3 -> argument #3 + 4 -> argument #4 + +Star parameters, unknown callables, both approach #1 and #2: g(1, 2, 3, 4) # g not known at compile-time diff -r 13558f703a70 -r 2c60577895f0 micropython/ast.py --- a/micropython/ast.py Mon Jul 13 01:02:42 2009 +0200 +++ b/micropython/ast.py Tue Jul 14 00:37:04 2009 +0200 @@ -421,9 +421,15 @@ def visitListCompIf(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "ListCompIf") def visitName(self, node): + + # Handle names referring to constants. + if self.importer.predefined_constants.has_key(node.name): const = self.importer.get_predefined_constant(node.name) self.new_op(LoadConst(const)) + + # Handle all other names. + else: self._visitName(node, self.name_load_instructions) @@ -606,6 +612,13 @@ self.set_block(fn.body_block) + # 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)) + extend = ExtendFrame() self.new_op(extend) diff -r 13558f703a70 -r 2c60577895f0 micropython/rsvp.py --- a/micropython/rsvp.py Mon Jul 13 01:02:42 2009 +0200 +++ b/micropython/rsvp.py Tue Jul 14 00:37:04 2009 +0200 @@ -212,6 +212,7 @@ class CheckFrame(Immediate): "Check the frame for the correct number of 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." # Invocation-related instructions, using a special result "register". @@ -251,7 +252,8 @@ LoadAddress, LoadAddressContext, LoadAddressContextCond, LoadAttr, LoadAttrIndex, LoadAttrIndexContextCond, LoadCallable, LoadContext, LoadResult, - LoadException, MakeInstance, MakeFragment + LoadException, MakeInstance, MakeFragment, + CopyExtra ) # vim: tabstop=4 expandtab shiftwidth=4 diff -r 13558f703a70 -r 2c60577895f0 rsvp.py --- a/rsvp.py Mon Jul 13 01:02:42 2009 +0200 +++ b/rsvp.py Tue Jul 14 00:37:04 2009 +0200 @@ -127,6 +127,9 @@ 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") + self.tuple_class = cls.location + self.tuple_instance = cls.instance_template_location # Debugging attributes. @@ -615,6 +618,28 @@ default += 1 pos += 1 + def CopyExtra(self): + start = self.operand + + # The frame is the source of the extra arguments. + + frame = self.local_sp_stack[-1] + nlocals = len(self.frame_stack[frame:]) + + # Make a tuple to hold the arguments. + + ref = self._MakeObject(nlocals - start + 1, self.tuple_instance) + + extra = 0 + pos = start + + while pos < nlocals: + self.save(ref + extra + 1, self.frame_stack[frame + pos]) # skip header when storing + extra += 1 + pos += 1 + + self.value = ref, ref + def CheckSelf(self): context, ref = self.value context_context, context_ref = self.source @@ -781,10 +806,10 @@ cls = self.machine._get_class("__builtins__", "IndexError") self.index_error = cls.location self.index_error_instance = cls.instance_template_location - cls = self.machine._get_class("__builtins__", "tuple") - self.tuple_class = cls.location + self.tuple_class = self.machine.tuple_class self.type_error_instance = self.machine.type_error_instance + self.frame_stack = self.machine.frame_stack self.local_sp_stack = self.machine.local_sp_stack