1.1 --- a/lib/builtins.py Mon Jun 15 00:40:25 2009 +0200
1.2 +++ b/lib/builtins.py Sun Jun 21 02:02:53 2009 +0200
1.3 @@ -336,7 +336,13 @@
1.4 def isinstance(obj, cls_or_tuple): pass
1.5 def issubclass(obj, cls_or_tuple): pass
1.6 def iter(collection_or_callable, sentinel=None): pass
1.7 -def len(obj): pass
1.8 +
1.9 +def len(obj):
1.10 +
1.11 + "Implementation of len."
1.12 +
1.13 + return obj.__len__()
1.14 +
1.15 def locals(): pass
1.16 def map(function, *args): pass
1.17 def max(*args): pass
1.18 @@ -346,7 +352,16 @@
1.19 def ord(c): pass
1.20 def pow(x, y, z=None): pass
1.21 def property(fget=None, fset=None, fdel=None, doc=None): pass
1.22 -def range(start_or_end, end=None, step=None): pass
1.23 +
1.24 +def range(start_or_end, end=None, step=1):
1.25 +
1.26 + "Implementation of range."
1.27 +
1.28 + l = []
1.29 + for i in xrange(start_or_end, end, step):
1.30 + l.append(i)
1.31 + return l
1.32 +
1.33 def raw_input(prompt=None): pass
1.34 def reduce(function, sequence, initial=None): pass
1.35 def reload(module): pass
2.1 --- a/micropython/ast.py Mon Jun 15 00:40:25 2009 +0200
2.2 +++ b/micropython/ast.py Sun Jun 21 02:02:53 2009 +0200
2.3 @@ -412,7 +412,7 @@
2.4 self._visitAttr(node, self.attribute_load_instructions)
2.5
2.6 def visitList(self, node):
2.7 - self._generateSequence("list", node)
2.8 + self._generateList(node)
2.9
2.10 def visitListComp(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "ListComp")
2.11
2.12 @@ -438,7 +438,7 @@
2.13 self._endCallFunc(temp_target, target, temp_context)
2.14
2.15 def visitTuple(self, node):
2.16 - self._generateSequence("tuple", node)
2.17 + self._generateTuple(node)
2.18
2.19 # Definitions.
2.20
3.1 --- a/micropython/program.py Mon Jun 15 00:40:25 2009 +0200
3.2 +++ b/micropython/program.py Sun Jun 21 02:02:53 2009 +0200
3.3 @@ -44,6 +44,17 @@
3.4 (self.classcode, self.attrcode, self.codeaddr, self.funccode, self.size), self.name
3.5 )
3.6
3.7 +class FragmentObject:
3.8 +
3.9 + "A representation of a list fragment, used by list instances."
3.10 +
3.11 + def __init__(self, occupied_size, allocated_size):
3.12 + self.occupied_size = occupied_size
3.13 + self.allocated_size = allocated_size
3.14 +
3.15 + def __repr__(self):
3.16 + return "%r" % ((self.occupied_size, self.allocated_size),)
3.17 +
3.18 class Context:
3.19
3.20 """
4.1 --- a/micropython/rsvp.py Mon Jun 15 00:40:25 2009 +0200
4.2 +++ b/micropython/rsvp.py Sun Jun 21 02:02:53 2009 +0200
4.3 @@ -174,7 +174,8 @@
4.4 class LoadAddressContextCond(Address):
4.5 """Load the current value from the given fixed attribute address, only using the current value as
4.6 context if the attribute is compatible."""
4.7 -class MakeInstance(Immediate): "Make a new instance."
4.8 +class MakeInstance(Immediate): "Make a new instance using the current value as a reference to a template."
4.9 +class MakeFragment(Immediate): "Make a new list fragment."
4.10
4.11 # Access to address-relative data. (LoadAttrIndexContext not defined.)
4.12
5.1 --- a/micropython/trans.py Mon Jun 15 00:40:25 2009 +0200
5.2 +++ b/micropython/trans.py Sun Jun 21 02:02:53 2009 +0200
5.3 @@ -1220,12 +1220,44 @@
5.4 self.new_op(JumpIfTrue(handled_block))
5.5 self.new_op(RaiseException())
5.6
5.7 - def _generateSequence(self, sequence_type, node):
5.8 + def _generateTuple(self, node):
5.9 +
5.10 + "Make a tuple using the given program 'node'."
5.11 +
5.12 + self.make_instance(self.get_builtin_class("tuple", node), len(node.nodes))
5.13 + temp = self.get_temp()
5.14 + self._populateSequence(temp, node)
5.15 + self.new_op(temp)
5.16 + self.discard_temp(temp)
5.17 +
5.18 + def _generateList(self, node):
5.19 +
5.20 + "Make a list using the given program 'node'."
5.21 +
5.22 + # Make a fragment containing the list elements.
5.23
5.24 - "Make a sequence of 'sequence_type' for the given program 'node'."
5.25 + self.new_op(MakeFragment(len(node.nodes) + 1))
5.26 + temp = self.get_temp()
5.27 + self._populateSequence(temp, node)
5.28 + self.new_op(temp)
5.29 + self.record_value()
5.30
5.31 - self.make_instance(self.get_builtin_class(sequence_type, node), len(node.nodes))
5.32 - temp = self.get_temp()
5.33 + self.make_instance(self.get_builtin_class("list", node), 1)
5.34 + list_temp = self.get_temp()
5.35 + self.new_op(list_temp)
5.36 + self.new_op(StoreAttr(Attr(0, None, None)))
5.37 + self.set_source()
5.38 + self.discard_value()
5.39 +
5.40 + self.new_op(list_temp)
5.41 + self.discard_temp(temp)
5.42 + self.discard_temp(list_temp)
5.43 +
5.44 + def _populateSequence(self, temp, node):
5.45 +
5.46 + """
5.47 + Populate a sequence using the given 'temp' reference and program 'node'.
5.48 + """
5.49
5.50 for i, n in enumerate(node.nodes):
5.51 self.dispatch(n)
5.52 @@ -1235,9 +1267,6 @@
5.53 self.set_source()
5.54 self.discard_value()
5.55
5.56 - self.new_op(temp)
5.57 - self.discard_temp(temp)
5.58 -
5.59 def _generateTestBoolean(self, node, temp):
5.60
5.61 """
6.1 --- a/rsvp.py Mon Jun 15 00:40:25 2009 +0200
6.2 +++ b/rsvp.py Sun Jun 21 02:02:53 2009 +0200
6.3 @@ -52,7 +52,7 @@
6.4 current callable
6.5 """
6.6
6.7 -from micropython.program import ReplaceableContext, PlaceholderContext
6.8 +from micropython.program import ReplaceableContext, PlaceholderContext, FragmentObject
6.9 import operator
6.10
6.11 class IllegalInstruction(Exception):
6.12 @@ -79,7 +79,7 @@
6.13
6.14 "A really simple virtual processor."
6.15
6.16 - def __init__(self, memory, objlist, paramlist, true_constant, false_constant, pc=None, debug=0):
6.17 + def __init__(self, memory, objlist, paramlist, true_constant, false_constant, pc=None, debug=0, abort_upon_exception=0):
6.18
6.19 """
6.20 Initialise the processor with a 'memory' (a list of values containing
6.21 @@ -98,6 +98,7 @@
6.22
6.23 self.pc = pc or 0
6.24 self.debug = debug
6.25 + self.abort_upon_exception = abort_upon_exception
6.26
6.27 # Stacks.
6.28
6.29 @@ -138,7 +139,10 @@
6.30 self.int_class = cls.location
6.31 self.int_instance = cls.instance_template_location
6.32 cls = self._get_class("__builtins__", "list")
6.33 + self.list_class = cls.location
6.34 self.list_instance = cls.instance_template_location
6.35 + cls = self._get_class("__builtins__", "tuple")
6.36 + self.tuple_class = cls.location
6.37
6.38 # Debugging attributes.
6.39
6.40 @@ -447,6 +451,12 @@
6.41 # Introduce object as context for the new object.
6.42 self.value = addr, addr
6.43
6.44 + def MakeFragment(self):
6.45 + size = self.operand
6.46 + addr = self._MakeFragment(size)
6.47 + # NOTE: Context is not relevant for fragments.
6.48 + self.value = None, addr
6.49 +
6.50 def LoadAttr(self):
6.51 context, ref = self.value
6.52 # Retrieved context should already be appropriate for the instance.
6.53 @@ -682,6 +692,8 @@
6.54 # NOTE: Adding the program counter as the first attribute.
6.55 self.save(self.exception + 1, self.pc)
6.56 # Jumping to the current handler.
6.57 + if self.abort_upon_exception:
6.58 + raise Exception
6.59 return self.handler_stack[-1]
6.60
6.61 def PushHandler(self):
6.62 @@ -743,6 +755,13 @@
6.63 self.save(addr, data.with_size(size))
6.64 return addr
6.65
6.66 + def _MakeFragment(self, size):
6.67 + # Reserve twice the amount of space.
6.68 + addr = self.new(size * 2)
6.69 + # Save the header, overriding the size.
6.70 + self.save(addr, FragmentObject(size, size * 2))
6.71 + return addr
6.72 +
6.73 def _LoadAddressContextCond(self, context, ref, inst_ref):
6.74 # Check the instance context against the target's context.
6.75 # This provides the context overriding for methods.
6.76 @@ -915,26 +934,56 @@
6.77 # NOTE: Specific copying of tuples/lists.
6.78
6.79 args_context, args = self.frame_stack[frame + 1]
6.80 - header = self.load(args)
6.81 +
6.82 + # Test operand suitability.
6.83
6.84 - list = self._MakeObject(header.size, self.list_instance)
6.85 - for i in range(1, header.size):
6.86 - self.save(list + i, self.load(args + i))
6.87 + if self._CheckInstance(args, self.list_class):
6.88 + _x, sequence = self.load(args + 1)
6.89 + header = self.load(sequence)
6.90 + size = header.occupied_size
6.91 + elif self._CheckInstance(args, self.tuple_class):
6.92 + sequence = args
6.93 + header = self.load(sequence)
6.94 + size = header.size
6.95 + else:
6.96 + self.exception = self._MakeObject(2, self.type_error_instance)
6.97 + return self.RaiseException()
6.98
6.99 - self.result = list, list
6.100 + # Copy the sequence contents.
6.101 +
6.102 + new_fragment = self._MakeFragment(size)
6.103 + for i in range(1, size):
6.104 + self.save(new_fragment + i, self.load(sequence + i))
6.105 +
6.106 + # Make the list instance.
6.107 +
6.108 + addr = self._MakeObject(2, self.list_instance)
6.109 + self.save(addr + 1, (None, new_fragment))
6.110 +
6.111 + self.result = addr, addr
6.112
6.113 def builtins_list_getitem(self):
6.114 frame = self.local_sp_stack[-1]
6.115
6.116 - # Get operands addresses.
6.117 + # Get the operand address.
6.118
6.119 - obj_context, obj = self.frame_stack[frame]
6.120 item_context, item = self.frame_stack[frame + 1]
6.121
6.122 - header = self.load(obj)
6.123 - nelements = header.size - 1
6.124 + # Get the list address.
6.125 +
6.126 + obj_context, obj = self.frame_stack[frame]
6.127 +
6.128 + # Get the fragment address.
6.129 + # NOTE: Assume single location for header.
6.130
6.131 - # NOTE: Assume single location for data.
6.132 + _x, fragment = self.load(obj + 1)
6.133 +
6.134 + # Get the fragment header.
6.135 +
6.136 + header = self.load(fragment)
6.137 + nelements = header.occupied_size - 1
6.138 +
6.139 + # NOTE: Assume single location for data and header.
6.140
6.141 item_pos = self.load(item + 1)
6.142 if item_pos >= 0 and item_pos < nelements:
6.143 @@ -945,7 +994,84 @@
6.144 self.exception = self._MakeObject(2, self.index_error_instance)
6.145 return self.RaiseException()
6.146
6.147 - self.result = self.load(obj + 1 + item_pos)
6.148 + # NOTE: Assume single location for header.
6.149 +
6.150 + self.result = self.load(fragment + 1 + item_pos)
6.151 +
6.152 + def builtins_list_len(self):
6.153 + frame = self.local_sp_stack[-1]
6.154 +
6.155 + # Get the list address.
6.156 +
6.157 + obj_context, obj = self.frame_stack[frame]
6.158 +
6.159 + # Get the fragment address.
6.160 + # NOTE: Assume single location for header.
6.161 +
6.162 + _x, fragment = self.load(obj + 1)
6.163 +
6.164 + # Get the fragment header.
6.165 +
6.166 + header = self.load(fragment)
6.167 + nelements = header.occupied_size - 1
6.168 +
6.169 + # Make a new object.
6.170 +
6.171 + addr = self._MakeObject(2, self.int_instance)
6.172 +
6.173 + # Store the result.
6.174 + # NOTE: The data is considered ready to use.
6.175 +
6.176 + self.save(addr + 1, nelements)
6.177 +
6.178 + # Return the new object.
6.179 + # Introduce object as context for the new object.
6.180 +
6.181 + self.result = addr, addr
6.182 +
6.183 + def builtins_list_append(self):
6.184 + frame = self.local_sp_stack[-1]
6.185 +
6.186 + # Get operand address.
6.187 +
6.188 + arg_context, arg = self.frame_stack[frame + 1]
6.189 +
6.190 + # Get the list address.
6.191 +
6.192 + obj_context, obj = self.frame_stack[frame]
6.193 +
6.194 + # Get the fragment address.
6.195 + # NOTE: Assume single location for header.
6.196 +
6.197 + _x, fragment = self.load(obj + 1)
6.198 +
6.199 + # Get the fragment header.
6.200 +
6.201 + header = self.load(fragment)
6.202 +
6.203 + # Attempt to add the reference.
6.204 +
6.205 + if header.occupied_size < header.allocated_size:
6.206 + self.save(fragment + header.occupied_size, (arg_context, arg))
6.207 + header.occupied_size += 1
6.208 + else:
6.209 +
6.210 + # Make a new fragment, maintaining more space than currently
6.211 + # occupied in order to avoid reallocation.
6.212 +
6.213 + new_fragment = self._MakeFragment(header.allocated_size)
6.214 +
6.215 + # Copy existing elements.
6.216 +
6.217 + for i in range(1, header.allocated_size):
6.218 + self.save(new_fragment + i, self.load(fragment + i))
6.219 +
6.220 + self.save(new_fragment + header.allocated_size, (arg_context, arg))
6.221 +
6.222 + # Set the new fragment in the object.
6.223 + # NOTE: The old fragment could be deallocated.
6.224 +
6.225 + self.save(obj + 1, (None, new_fragment))
6.226
6.227 def builtins_object_init(self):
6.228 pass
6.229 @@ -968,6 +1094,8 @@
6.230 "__builtins__.int.__ne__" : builtins_int_ne,
6.231 "__builtins__.bool.__bool__" : builtins_bool_bool,
6.232 "__builtins__.list.__getitem__" : builtins_list_getitem,
6.233 + "__builtins__.list.__len__" : builtins_list_len,
6.234 + "__builtins__.list.append" : builtins_list_append,
6.235 "__builtins__.object.__init__" : builtins_object_init, # NOTE: A no-operation.
6.236 "__builtins__.BaseException.__init__" : builtins_object_init, # NOTE: To be made distinct, potentially in the builtins module.
6.237
6.238 @@ -978,7 +1106,7 @@
6.239
6.240 # Convenience functions.
6.241
6.242 -def machine(program, with_builtins=0, debug=0):
6.243 +def machine(program, with_builtins=0, debug=0, abort_upon_exception=0):
6.244 print "Making the image..."
6.245 code = program.get_image(with_builtins)
6.246 print "Getting raw structures..."
6.247 @@ -992,7 +1120,7 @@
6.248 importer = program.get_importer()
6.249 true_constant = importer.get_constant(True).location
6.250 false_constant = importer.get_constant(False).location
6.251 - rm = RSVPMachine(rc, objlist, paramlist, true_constant, false_constant, debug=debug)
6.252 + rm = RSVPMachine(rc, objlist, paramlist, true_constant, false_constant, debug=debug, abort_upon_exception=abort_upon_exception)
6.253 rm.pc = program.code_location
6.254 print "Returning program occupying %d locations." % len(rm.memory)
6.255 return rm
7.1 --- a/test.py Mon Jun 15 00:40:25 2009 +0200
7.2 +++ b/test.py Sun Jun 21 02:02:53 2009 +0200
7.3 @@ -56,7 +56,7 @@
7.4 pt = p.get_parameter_table()
7.5
7.6 if "-m" in args or "-t" in args:
7.7 - rm = rsvp.machine(p)
7.8 + rm = rsvp.machine(p, debug=("-g" in args), abort_upon_exception=("-x" in args))
7.9 if "-t" in args:
7.10 success = rm.test(m)
7.11 print "Test successful?", success
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/tests/globals_vs_locals.py Sun Jun 21 02:02:53 2009 +0200
8.3 @@ -0,0 +1,17 @@
8.4 +#!/usr/bin/env python
8.5 +
8.6 +b = 2
8.7 +
8.8 +def f(x):
8.9 + b = x
8.10 +
8.11 +def g(x):
8.12 + global b
8.13 + b = x
8.14 +
8.15 +f(3)
8.16 +result_2 = b
8.17 +g(4)
8.18 +result_4 = b
8.19 +
8.20 +# vim: tabstop=4 expandtab shiftwidth=4
9.1 --- a/tests/methods.py Mon Jun 15 00:40:25 2009 +0200
9.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
9.3 @@ -1,44 +0,0 @@
9.4 -#!/usr/bin/env python
9.5 -
9.6 -class B:
9.7 - def f(self):
9.8 - pass
9.9 -
9.10 -def f(self):
9.11 - pass
9.12 -
9.13 -b = B()
9.14 -
9.15 - # on A on a
9.16 -class A:
9.17 - f1 = f # unbound (A) bound (a)
9.18 - f2 = B.f # unbound (B) unbound (B)
9.19 - f3 = b.f # bound (b) bound (b)
9.20 -
9.21 - def __init__(self):
9.22 - self.f4 = f # N/A function
9.23 - self.f5 = B.f # N/A unbound (B)
9.24 - self.f6 = b.f # N/A bound (b)
9.25 -
9.26 - def m(self):
9.27 - x = self.f1 # should use optimised attribute access
9.28 - x = self.f2
9.29 - x = self.f3
9.30 - x = self.f4
9.31 - x = self.f5
9.32 - x = self.f6
9.33 -
9.34 -a = A()
9.35 -a.m()
9.36 -
9.37 -A.f1
9.38 -A.f2
9.39 -A.f3
9.40 -a.f1
9.41 -a.f2
9.42 -a.f3
9.43 -a.f4
9.44 -a.f5
9.45 -a.f6
9.46 -
9.47 -# vim: tabstop=4 expandtab shiftwidth=4
12.1 --- a/tests/op_add.py Mon Jun 15 00:40:25 2009 +0200
12.2 +++ b/tests/op_add.py Sun Jun 21 02:02:53 2009 +0200
12.3 @@ -5,4 +5,7 @@
12.4 c = a + b
12.5 d = a + b + c
12.6
12.7 +result_3 = c
12.8 +result_6 = d
12.9 +
12.10 # vim: tabstop=4 expandtab shiftwidth=4
13.1 --- a/tests/op_add_call.py Mon Jun 15 00:40:25 2009 +0200
13.2 +++ b/tests/op_add_call.py Sun Jun 21 02:02:53 2009 +0200
13.3 @@ -6,6 +6,6 @@
13.4 a = 1
13.5 b = 2
13.6 c = 3
13.7 -d = f(a + b, b + c)
13.8 +result_8 = f(a + b, b + c)
13.9
13.10 # vim: tabstop=4 expandtab shiftwidth=4
14.1 --- a/tests/op_add_default.py Mon Jun 15 00:40:25 2009 +0200
14.2 +++ b/tests/op_add_default.py Sun Jun 21 02:02:53 2009 +0200
14.3 @@ -5,6 +5,6 @@
14.4
14.5 a = 10 # used in f default
14.6 b = 20 # used in f default
14.7 -x = f(1, 2)
14.8 +result_33 = f(1, 2)
14.9
14.10 # vim: tabstop=4 expandtab shiftwidth=4
15.1 --- a/tests/range.py Mon Jun 15 00:40:25 2009 +0200
15.2 +++ b/tests/range.py Sun Jun 21 02:02:53 2009 +0200
15.3 @@ -1,7 +1,11 @@
15.4 #!/usr/bin/env python
15.5
15.6 a = 1
15.7 -b = 2
15.8 -range(a, b)
15.9 +b = 20
15.10 +l = range(a, b)
15.11 +
15.12 +result1_19 = len(l)
15.13 +result_1 = l[0]
15.14 +result2_19 = l[-1]
15.15
15.16 # vim: tabstop=4 expandtab shiftwidth=4