# HG changeset patch # User Paul Boddie # Date 1300838337 -3600 # Node ID 930e3447f06f881d2a251f20189474f360e1a7f6 # Parent fd96865ebfb70e5cfd2d5d41d04dda16e52cb122 Fixed function definitions to copy extra parameters before the frame is extended, otherwise the extended frame elements are erroneously copied into the star argument tuple. Added tests to check the behaviour of star argument initialisation in the presence of locals. Introduced a _tuple native method to convert lists to tuples. Updated the native library functions to use variables indicating the size of fragment headers. diff -r fd96865ebfb7 -r 930e3447f06f TO_DO.txt --- a/TO_DO.txt Mon Mar 21 01:27:27 2011 +0100 +++ b/TO_DO.txt Wed Mar 23 00:58:57 2011 +0100 @@ -99,6 +99,8 @@ Other ===== +Support tuple as a function returning any input tuple uncopied. + Check context_value initialisation (avoiding or handling None effectively). __getitem__ could be written in Python, using a native method only to access fragments. diff -r fd96865ebfb7 -r 930e3447f06f lib/builtins.py --- a/lib/builtins.py Mon Mar 21 01:27:27 2011 +0100 +++ b/lib/builtins.py Wed Mar 23 00:58:57 2011 +0100 @@ -4,7 +4,7 @@ Simple built-in classes and functions. Objects which provide code that shall always be compiled should provide docstrings. -Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Paul Boddie +Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Paul Boddie This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -279,6 +279,9 @@ pass class tuple(object): + + #"Implementation of tuple." + def __init__(self, args): pass def __getitem__(self, index): @@ -291,7 +294,7 @@ "Return a slice starting from 'start', with the optional 'end'." - return tuple(_getslice(self, start, end)) + return _tuple(_getslice(self, start, end)) def __len__(self): pass def __add__(self, other): pass @@ -612,6 +615,7 @@ def _isinstance(obj, cls): pass def _print(dest, *args): pass def _printnl(dest, *args): pass +def _tuple(l): pass # Reference some names to ensure their existence. This should be everything # mentioned in a get_builtin or load_builtin call. Instances from this module diff -r fd96865ebfb7 -r 930e3447f06f micropython/ast.py --- a/micropython/ast.py Mon Mar 21 01:27:27 2011 +0100 +++ b/micropython/ast.py Wed Mar 23 00:58:57 2011 +0100 @@ -171,6 +171,8 @@ "Return the code for the given class 'cls'." + # Obtain the function object to be populated. + self.unit = cls.get_instantiator() self.reset() diff -r fd96865ebfb7 -r 930e3447f06f micropython/trans.py --- a/micropython/trans.py Mon Mar 21 01:27:27 2011 +0100 +++ b/micropython/trans.py Wed Mar 23 00:58:57 2011 +0100 @@ -1117,13 +1117,6 @@ self.set_block(fn.body_block) - extend = ExtendFrame() - self.new_op(extend) - - # Perform tuple assignment for any tuple parameters. - - self._visitFunctionTupleParameters(fn, node) - # For functions with star parameters, make a special list for the # extra arguments and re-map the parameter. @@ -1135,6 +1128,15 @@ self.new_op(CheckExtra(nparams)) self.new_op(StoreTemp(nparams)) + # Extend the frame for local usage. + + extend = ExtendFrame() + self.new_op(extend) + + # Perform tuple assignment for any tuple parameters. + + self._visitFunctionTupleParameters(fn, node) + # Add any attribute usage guards. self._generateGuards(node) diff -r fd96865ebfb7 -r 930e3447f06f rsvplib.py --- a/rsvplib.py Mon Mar 21 01:27:27 2011 +0100 +++ b/rsvplib.py Wed Mar 23 00:58:57 2011 +0100 @@ -30,6 +30,7 @@ instance_template_size = instance_data_offset = 1 instance_size = instance_template_size + 1 + fragment_data_offset = 1 def __init__(self, machine, constants): @@ -60,6 +61,7 @@ self.str_instance = cls.instance_template_location self.tuple_class = self.machine.tuple_class + self.tuple_instance = self.machine.tuple_instance self.type_error_instance = self.machine.type_error_instance self.frame_stack = self.machine.frame_stack @@ -262,7 +264,7 @@ # Make a new sequence. # NOTE: Using an arbitrary size. - new_fragment = self.machine._MakeFragment(1, 5) # include the header + new_fragment = self.machine._MakeFragment(self.fragment_data_offset, 5) # include the header # Complete the list instance by saving the fragment reference. # NOTE: This requires an attribute in the list structure. @@ -288,7 +290,7 @@ # Get the fragment header. header = self.machine.load(fragment.ref) - nelements = header.occupied_size - 1 + nelements = header.occupied_size - self.fragment_data_offset # Get the item position. @@ -300,7 +302,7 @@ # Get the item itself. - self.machine.result = self.machine.load(fragment.ref + 1 + item_pos) + self.machine.result = self.machine.load(fragment.ref + self.fragment_data_offset + item_pos) def builtins_list_len(self): frame = self.local_sp_stack[-1] @@ -316,7 +318,7 @@ # Get the fragment header. header = self.machine.load(fragment.ref) - nelements = header.occupied_size - 1 + nelements = header.occupied_size - self.fragment_data_offset # Make a new object. @@ -365,7 +367,7 @@ # Copy existing elements. - for i in range(1, header.occupied_size): + for i in range(self.fragment_data_offset, header.occupied_size): self.machine.save(new_fragment + i, self.machine.load(fragment.ref + i)) self.machine.save(new_fragment + header.occupied_size, arg_value) @@ -375,6 +377,40 @@ self.machine.save(obj_value.ref + self.instance_data_offset, DataValue(None, new_fragment)) + def builtins_tuple(self): + frame = self.local_sp_stack[-1] + + # Get the list address. + + obj_value = self.frame_stack[frame] + + if not self.machine._CheckInstance(obj_value.ref, self.list_class): + self.machine.exception = self.machine._MakeObject(self.instance_size, self.type_error_instance) + return self.machine.RaiseException() + + # Get the fragment address. + + fragment = self.machine.load(obj_value.ref + self.instance_data_offset) + + # Get the fragment header. + + header = self.machine.load(fragment.ref) + + # Make a new object. + + addr = self.machine._MakeObject(self.instance_data_offset + header.occupied_size - self.fragment_data_offset, self.tuple_instance) + + # Copy the fragment contents into the tuple. + # NOTE: This might be done by repurposing the fragment in some situations. + + for i in range(self.fragment_data_offset, header.occupied_size): + self.machine.save(addr + self.instance_data_offset + i - self.fragment_data_offset, self.machine.load(fragment.ref + i)) + + # Return the new object. + # Introduce object as context for the new object. + + self.machine.result = DataValue(addr, addr) + def builtins_tuple_len(self): frame = self.local_sp_stack[-1] @@ -501,6 +537,7 @@ "__builtins__._isinstance" : builtins_isinstance, "__builtins__._print" : builtins_print, "__builtins__._printnl" : builtins_printnl, + "__builtins__._tuple" : builtins_tuple, } # vim: tabstop=4 expandtab shiftwidth=4 diff -r fd96865ebfb7 -r 930e3447f06f tests/call_func_extra_known_with_locals.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/call_func_extra_known_with_locals.py Wed Mar 23 00:58:57 2011 +0100 @@ -0,0 +1,17 @@ +#!/usr/bin/env python + +def f(a, b, *c): + d = 123 # introduce locals in the frame + 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 fd96865ebfb7 -r 930e3447f06f tests/call_func_extra_unknown_with_locals.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/call_func_extra_unknown_with_locals.py Wed Mar 23 00:58:57 2011 +0100 @@ -0,0 +1,26 @@ +#!/usr/bin/env python + +def f(a, b, *c): + d = 123 # introduce locals in the frame + 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): + d = 123 # introduce locals in the frame + 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 diff -r fd96865ebfb7 -r 930e3447f06f tests/tuple_call.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/tuple_call.py Wed Mar 23 00:58:57 2011 +0100 @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +a1 = tuple((1, 2, 3)) +a2 = tuple((1, 2, 3)) +b1 = tuple((1, tuple((2, 3)), 4, 5)) + +result_1 = a1[0] +result_2 = a2[1] +result_3 = b1[1][1] +result_4 = b1[2] +resultL_2 = len(b1[1]) +resultL_3 = len(a1) +resultL_4 = len(b1) + +# vim: tabstop=4 expandtab shiftwidth=4