micropython

Changeset

332:c368d83770c7
2010-06-11 Paul Boddie raw files shortlog changelog graph Replaced the native mechanism for list initialisation with a Python-based list.__init__ method and a simplified native method for initialising the initial list fragment. Introduced automatic namespace traversal of __init__ attributes for any namespace providing such attributes. Unfortunately, this inflates the program size substantially and needs to be reviewed. Enabled proper testing of xrange instances using the updated support for list initialisation.
TO_DO.txt (file) lib/builtins.py (file) micropython/__init__.py (file) rsvplib.py (file) tests/xrange.py (file)
     1.1 --- a/TO_DO.txt	Sat Jun 05 01:39:16 2010 +0200
     1.2 +++ b/TO_DO.txt	Fri Jun 11 00:56:08 2010 +0200
     1.3 @@ -1,3 +1,7 @@
     1.4 +Support __init__ traversal (and other implicit names) more effectively.
     1.5 +
     1.6 +Check context_value initialisation (avoiding or handling None effectively).
     1.7 +
     1.8  Loop entry points should capture usage to update later assignments in the loop.
     1.9  The continue and break statements should affect usage propagation.
    1.10  
     2.1 --- a/lib/builtins.py	Sat Jun 05 01:39:16 2010 +0200
     2.2 +++ b/lib/builtins.py	Fri Jun 11 00:56:08 2010 +0200
     2.3 @@ -143,7 +143,22 @@
     2.4      def __rrshift__(self): pass
     2.5  
     2.6  class list(object):
     2.7 -    def __init__(self, args=()): pass
     2.8 +
     2.9 +    "Implementation of list."
    2.10 +
    2.11 +    def __init__(self, args=None):
    2.12 +
    2.13 +        "Initialise the list."
    2.14 +
    2.15 +        self.__new__()
    2.16 +
    2.17 +        if args is not None:
    2.18 +            for arg in args:
    2.19 +                self.append(arg)
    2.20 +
    2.21 +    def __new__(self):
    2.22 +        self._elements = None # defined in a native method
    2.23 +
    2.24      def __getitem__(self, index): pass
    2.25      def __setitem__(self, index, value): pass
    2.26      def __getslice__(self, start, end=None): pass
     3.1 --- a/micropython/__init__.py	Sat Jun 05 01:39:16 2010 +0200
     3.2 +++ b/micropython/__init__.py	Fri Jun 11 00:56:08 2010 +0200
     3.3 @@ -5,7 +5,7 @@
     3.4  from the simplify package but has had various details related to that package
     3.5  removed.
     3.6  
     3.7 -Copyright (C) 2006, 2007, 2008, 2009 Paul Boddie <paul@boddie.org.uk>
     3.8 +Copyright (C) 2006, 2007, 2008, 2009, 2010 Paul Boddie <paul@boddie.org.uk>
     3.9  
    3.10  This program is free software; you can redistribute it and/or modify it under
    3.11  the terms of the GNU General Public License as published by the Free Software
    3.12 @@ -334,7 +334,7 @@
    3.13          }
    3.14  
    3.15      names_always_used = [
    3.16 -        "bool", "__init__", "__call__", "__bool__", "__builtins__", "__main__"
    3.17 +        "bool", "__init__", "__call__", "__bool__"
    3.18          ]
    3.19  
    3.20      def __init__(self, path=None, verbose=0, optimisations=None):
    3.21 @@ -498,9 +498,10 @@
    3.22          # Include names which may not be explicitly used in programs.
    3.23          # NOTE: Potentially declare these when inspecting.
    3.24  
    3.25 -        for name in self.names_always_used:
    3.26 -            for objname in objtable.all_possible_objects([name]):
    3.27 -                self.use_attribute(objname, name)
    3.28 +        for attrname in self.names_always_used:
    3.29 +            for objname in objtable.all_possible_objects([attrname]):
    3.30 +                self.use_attribute(objname, attrname)
    3.31 +                self._collect_attributes(objname + "." + attrname, objtable)
    3.32  
    3.33      def _collect_attributes(self, from_name, objtable):
    3.34  
    3.35 @@ -536,6 +537,13 @@
    3.36              self.use_attribute(objname, attrname)
    3.37              self._collect_attributes(objname + "." + attrname, objtable)
    3.38  
    3.39 +        # Where the object has an __init__ attribute, assume that it is an
    3.40 +        # initialiser which is called at some point, and collect attributes used
    3.41 +        # in this initialiser.
    3.42 +
    3.43 +        if "__init__" in objtable.table.get(from_name, []):
    3.44 +            self._collect_attributes(from_name + ".__init__", objtable)
    3.45 +
    3.46      # Constant accounting.
    3.47  
    3.48      def init_predefined_constants(self):
     4.1 --- a/rsvplib.py	Sat Jun 05 01:39:16 2010 +0200
     4.2 +++ b/rsvplib.py	Fri Jun 11 00:56:08 2010 +0200
     4.3 @@ -254,36 +254,19 @@
     4.4      def builtins_list_new(self):
     4.5          frame = self.local_sp_stack[-1]
     4.6  
     4.7 -        # The first parameter should be empty.
     4.8 -        # NOTE: Specific copying of tuples/lists.
     4.9 +        # The first parameter should be the instance.
    4.10  
    4.11 -        args_value = self.frame_stack[frame + 1]
    4.12 +        list_value = self.frame_stack[frame]
    4.13  
    4.14 -        # Test operand suitability.
    4.15 +        # Make a new sequence.
    4.16 +        # NOTE: Using an arbitrary size.
    4.17  
    4.18 -        if self.machine._CheckInstance(args_value.ref, self.list_class):
    4.19 -            sequence = self.machine.load(args_value.ref + 1)
    4.20 -            header = self.machine.load(sequence.ref)
    4.21 -            size = header.occupied_size
    4.22 -        elif self.machine._CheckInstance(args_value.ref, self.tuple_class):
    4.23 -            sequence = args_value.ref
    4.24 -            header = self.machine.load(sequence)
    4.25 -            size = header.size
    4.26 -        else:
    4.27 -            self.machine.exception = self.machine._MakeObject(2, self.type_error_instance)
    4.28 -            return self.machine.RaiseException()
    4.29 +        new_fragment = self.machine._MakeFragment(5)
    4.30  
    4.31 -        # Copy the sequence contents.
    4.32 -
    4.33 -        new_fragment = self.machine._MakeFragment(size)
    4.34 -        for i in range(1, size):
    4.35 -            self.machine.save(new_fragment + i, self.machine.load(sequence + i))
    4.36 +        # Complete the list instance by saving the fragment reference.
    4.37  
    4.38 -        # Make the list instance.
    4.39 -
    4.40 -        addr = self.machine._MakeObject(2, self.list_instance)
    4.41 -        self.machine.save(addr + 1, DataValue(None, new_fragment))
    4.42 -
    4.43 +        addr = list_value.ref + 1
    4.44 +        self.machine.save(addr, DataValue(None, new_fragment))
    4.45          self.machine.result = DataValue(addr, addr)
    4.46  
    4.47      def builtins_list_getitem(self):
    4.48 @@ -500,9 +483,9 @@
    4.49          "__builtins__.object.__init__" : builtins_object_init,        # NOTE: A no-operation.
    4.50          "__builtins__.BaseException.__init__" : builtins_object_init, # NOTE: To be made distinct, potentially in the builtins module.
    4.51  
    4.52 -        # Native instantiators:
    4.53 +        # Native instantiator helpers:
    4.54  
    4.55 -        "__builtins__.list" : builtins_list_new,
    4.56 +        "__builtins__.list.__new__" : builtins_list_new,
    4.57          }
    4.58  
    4.59  # vim: tabstop=4 expandtab shiftwidth=4
     5.1 --- a/tests/xrange.py	Sat Jun 05 01:39:16 2010 +0200
     5.2 +++ b/tests/xrange.py	Fri Jun 11 00:56:08 2010 +0200
     5.3 @@ -1,6 +1,7 @@
     5.4  #!/usr/bin/env python
     5.5  
     5.6  xr = xrange(0, 10, 1)
     5.7 +l = list(xr)
     5.8  result_0 = xr.start
     5.9  result_10 = xr.end
    5.10  result_1 = xr.step