1.1 --- a/rsvp.py Fri Sep 25 00:35:17 2009 +0200
1.2 +++ b/rsvp.py Wed Sep 30 00:24:41 2009 +0200
1.3 @@ -53,7 +53,7 @@
1.4 """
1.5
1.6 from micropython.program import ReplaceableContext, PlaceholderContext, FragmentObject
1.7 -import operator
1.8 +from rsvplib import Library
1.9
1.10 class IllegalInstruction(Exception):
1.11 pass
1.12 @@ -791,446 +791,6 @@
1.13 else:
1.14 return context, ref
1.15
1.16 -class Library:
1.17 -
1.18 - "Native function implementations."
1.19 -
1.20 - def __init__(self, machine, true_constant, false_constant):
1.21 -
1.22 - """
1.23 - Initialise the library with the 'machine' and the addresses
1.24 - 'true_constant' and 'false_constant'.
1.25 - """
1.26 -
1.27 - self.machine = machine
1.28 - self.true_constant = true_constant
1.29 - self.false_constant = false_constant
1.30 -
1.31 - # Native class constants.
1.32 -
1.33 - cls = self.machine._get_class("__builtins__", "int")
1.34 - self.int_class = cls.location
1.35 - self.int_instance = cls.instance_template_location
1.36 - cls = self.machine._get_class("__builtins__", "list")
1.37 - self.list_class = cls.location
1.38 - self.list_instance = cls.instance_template_location
1.39 - cls = self.machine._get_class("__builtins__", "IndexError")
1.40 - self.index_error = cls.location
1.41 - self.index_error_instance = cls.instance_template_location
1.42 -
1.43 - self.tuple_class = self.machine.tuple_class
1.44 - self.type_error_instance = self.machine.type_error_instance
1.45 -
1.46 - self.frame_stack = self.machine.frame_stack
1.47 - self.local_sp_stack = self.machine.local_sp_stack
1.48 -
1.49 - def builtins_int_arithmetic_op(self, op):
1.50 - frame = self.local_sp_stack[-1]
1.51 -
1.52 - # Get operands addresses.
1.53 -
1.54 - left_context, left = self.frame_stack[frame]
1.55 - right_context, right = self.frame_stack[frame + 1]
1.56 -
1.57 - # Test operand suitability.
1.58 - # NOTE: Support other types.
1.59 -
1.60 - if not (self.machine._CheckInstance(left, self.int_class) and self.machine._CheckInstance(right, self.int_class)):
1.61 - self.machine.exception = self.machine._MakeObject(2, self.type_error_instance)
1.62 - return self.machine.RaiseException()
1.63 -
1.64 - # NOTE: Assume single location for data.
1.65 -
1.66 - left_data = left + 1
1.67 - right_data = right + 1
1.68 -
1.69 - # Make a new object.
1.70 -
1.71 - addr = self.machine._MakeObject(2, self.int_instance)
1.72 -
1.73 - # Store the result.
1.74 - # NOTE: The data is considered ready to use.
1.75 -
1.76 - self.machine.save(addr + 1, op(self.machine.load(left_data), self.machine.load(right_data)))
1.77 -
1.78 - # Return the new object.
1.79 - # Introduce object as context for the new object.
1.80 -
1.81 - self.machine.result = addr, addr
1.82 -
1.83 - def builtins_int_bool(self):
1.84 - frame = self.local_sp_stack[-1]
1.85 -
1.86 - # Get operands addresses.
1.87 -
1.88 - left_context, left = self.frame_stack[frame]
1.89 -
1.90 - # Test operand suitability.
1.91 -
1.92 - if not self.machine._CheckInstance(left, self.int_class):
1.93 - self.machine.exception = self.machine._MakeObject(2, self.type_error_instance)
1.94 - return self.machine.RaiseException()
1.95 -
1.96 - # NOTE: Assume single location for data.
1.97 -
1.98 - left_data = left + 1
1.99 -
1.100 - # Test the data.
1.101 - # NOTE: The data is considered ready to use.
1.102 -
1.103 - if self.machine.load(left_data) != 0:
1.104 - self.machine.result = self.true_constant, self.true_constant
1.105 - else:
1.106 - self.machine.result = self.false_constant, self.false_constant
1.107 -
1.108 - def builtins_int_neg(self):
1.109 - frame = self.local_sp_stack[-1]
1.110 -
1.111 - # Get operands addresses.
1.112 -
1.113 - left_context, left = self.frame_stack[frame]
1.114 -
1.115 - # Test operand suitability.
1.116 -
1.117 - if not self.machine._CheckInstance(left, self.int_class):
1.118 - self.machine.exception = self.machine._MakeObject(2, self.type_error_instance)
1.119 - return self.machine.RaiseException()
1.120 -
1.121 - # NOTE: Assume single location for data.
1.122 -
1.123 - left_data = left + 1
1.124 -
1.125 - # Make a new object.
1.126 -
1.127 - addr = self.machine._MakeObject(2, self.int_instance)
1.128 -
1.129 - # Store the result.
1.130 - # NOTE: The data is considered ready to use.
1.131 -
1.132 - self.machine.save(addr + 1, -self.machine.load(left_data))
1.133 -
1.134 - # Return the new object.
1.135 - # Introduce object as context for the new object.
1.136 -
1.137 - self.machine.result = addr, addr
1.138 -
1.139 - def builtins_int_op(self, op, true_if_incompatible):
1.140 - frame = self.local_sp_stack[-1]
1.141 -
1.142 - # Get operands addresses.
1.143 -
1.144 - left_context, left = self.frame_stack[frame]
1.145 - right_context, right = self.frame_stack[frame + 1]
1.146 -
1.147 - # Test operand suitability.
1.148 - # NOTE: Support other types.
1.149 - # NOTE: Handle comparisons of incompatible types more appropriately.
1.150 -
1.151 - if not (self.machine._CheckInstance(left, self.int_class) and self.machine._CheckInstance(right, self.int_class)):
1.152 - if true_if_incompatible:
1.153 - self.machine.result = self.true_constant, self.true_constant
1.154 - else:
1.155 - self.machine.result = self.false_constant, self.false_constant
1.156 - return
1.157 -
1.158 - # NOTE: Assume single location for data.
1.159 -
1.160 - left_data = left + 1
1.161 - right_data = right + 1
1.162 -
1.163 - # Test the data.
1.164 - # NOTE: The data is considered ready to use.
1.165 -
1.166 - if op(self.machine.load(left_data), self.machine.load(right_data)):
1.167 - self.machine.result = self.true_constant, self.true_constant
1.168 - else:
1.169 - self.machine.result = self.false_constant, self.false_constant
1.170 -
1.171 - def builtins_int_add(self):
1.172 - return self.builtins_int_arithmetic_op(operator.add)
1.173 -
1.174 - def builtins_int_sub(self):
1.175 - return self.builtins_int_arithmetic_op(operator.sub)
1.176 -
1.177 - def builtins_int_lt(self):
1.178 - return self.builtins_int_op(operator.lt, 0)
1.179 -
1.180 - def builtins_int_le(self):
1.181 - return self.builtins_int_op(operator.le, 0)
1.182 -
1.183 - def builtins_int_gt(self):
1.184 - return self.builtins_int_op(operator.gt, 0)
1.185 -
1.186 - def builtins_int_ge(self):
1.187 - return self.builtins_int_op(operator.ge, 0)
1.188 -
1.189 - def builtins_int_eq(self):
1.190 - return self.builtins_int_op(operator.eq, 0)
1.191 -
1.192 - def builtins_int_ne(self):
1.193 - return self.builtins_int_op(operator.ne, 1)
1.194 -
1.195 - def builtins_int_and(self):
1.196 - return self.builtins_int_arithmetic_op(operator.and_)
1.197 -
1.198 - def builtins_int_or(self):
1.199 - return self.builtins_int_arithmetic_op(operator.or_)
1.200 -
1.201 - def builtins_bool_bool(self):
1.202 - frame = self.local_sp_stack[-1]
1.203 -
1.204 - # Get operands addresses.
1.205 -
1.206 - left_context, left = self.frame_stack[frame]
1.207 - self.machine.result = left, left
1.208 -
1.209 - def builtins_list_new(self):
1.210 - frame = self.local_sp_stack[-1]
1.211 -
1.212 - # The first parameter should be empty.
1.213 - # NOTE: Specific copying of tuples/lists.
1.214 -
1.215 - args_context, args = self.frame_stack[frame + 1]
1.216 -
1.217 - # Test operand suitability.
1.218 -
1.219 - if self.machine._CheckInstance(args, self.list_class):
1.220 - _x, sequence = self.machine.load(args + 1)
1.221 - header = self.machine.load(sequence)
1.222 - size = header.occupied_size
1.223 - elif self.machine._CheckInstance(args, self.tuple_class):
1.224 - sequence = args
1.225 - header = self.machine.load(sequence)
1.226 - size = header.size
1.227 - else:
1.228 - self.machine.exception = self.machine._MakeObject(2, self.type_error_instance)
1.229 - return self.machine.RaiseException()
1.230 -
1.231 - # Copy the sequence contents.
1.232 -
1.233 - new_fragment = self.machine._MakeFragment(size)
1.234 - for i in range(1, size):
1.235 - self.machine.save(new_fragment + i, self.machine.load(sequence + i))
1.236 -
1.237 - # Make the list instance.
1.238 -
1.239 - addr = self.machine._MakeObject(2, self.list_instance)
1.240 - self.machine.save(addr + 1, (None, new_fragment))
1.241 -
1.242 - self.machine.result = addr, addr
1.243 -
1.244 - def builtins_list_getitem(self):
1.245 - frame = self.local_sp_stack[-1]
1.246 -
1.247 - # Get the operand address.
1.248 -
1.249 - item_context, item = self.frame_stack[frame + 1]
1.250 -
1.251 - # Get the list address.
1.252 -
1.253 - obj_context, obj = self.frame_stack[frame]
1.254 -
1.255 - # Get the fragment address.
1.256 - # NOTE: Assume single location for header.
1.257 -
1.258 - _x, fragment = self.machine.load(obj + 1)
1.259 -
1.260 - # Get the fragment header.
1.261 -
1.262 - header = self.machine.load(fragment)
1.263 - nelements = header.occupied_size - 1
1.264 -
1.265 - # NOTE: Assume single location for data and header.
1.266 -
1.267 - item_pos = self.machine.load(item + 1)
1.268 -
1.269 - if item_pos >= 0 and item_pos < nelements:
1.270 - pass
1.271 - elif item_pos < 0 and item_pos >= -nelements:
1.272 - item_pos = nelements + item_pos
1.273 - else:
1.274 - self.machine.exception = self.machine._MakeObject(2, self.index_error_instance)
1.275 - return self.machine.RaiseException()
1.276 -
1.277 - # NOTE: Assume single location for header.
1.278 -
1.279 - self.machine.result = self.machine.load(fragment + 1 + item_pos)
1.280 -
1.281 - def builtins_list_len(self):
1.282 - frame = self.local_sp_stack[-1]
1.283 -
1.284 - # Get the list address.
1.285 -
1.286 - obj_context, obj = self.frame_stack[frame]
1.287 -
1.288 - # Get the fragment address.
1.289 - # NOTE: Assume single location for header.
1.290 -
1.291 - _x, fragment = self.machine.load(obj + 1)
1.292 -
1.293 - # Get the fragment header.
1.294 -
1.295 - header = self.machine.load(fragment)
1.296 - nelements = header.occupied_size - 1
1.297 -
1.298 - # Make a new object.
1.299 -
1.300 - addr = self.machine._MakeObject(2, self.int_instance)
1.301 -
1.302 - # Store the result.
1.303 - # NOTE: The data is considered ready to use.
1.304 -
1.305 - self.machine.save(addr + 1, nelements)
1.306 -
1.307 - # Return the new object.
1.308 - # Introduce object as context for the new object.
1.309 -
1.310 - self.machine.result = addr, addr
1.311 -
1.312 - def builtins_list_append(self):
1.313 - frame = self.local_sp_stack[-1]
1.314 -
1.315 - # Get operand address.
1.316 -
1.317 - arg_context, arg = self.frame_stack[frame + 1]
1.318 -
1.319 - # Get the list address.
1.320 -
1.321 - obj_context, obj = self.frame_stack[frame]
1.322 -
1.323 - # Get the fragment address.
1.324 - # NOTE: Assume single location for header.
1.325 -
1.326 - _x, fragment = self.machine.load(obj + 1)
1.327 -
1.328 - # Get the fragment header.
1.329 -
1.330 - header = self.machine.load(fragment)
1.331 -
1.332 - # Attempt to add the reference.
1.333 -
1.334 - if header.occupied_size < header.allocated_size:
1.335 - self.machine.save(fragment + header.occupied_size, (arg_context, arg))
1.336 - header.occupied_size += 1
1.337 - else:
1.338 -
1.339 - # Make a new fragment, maintaining more space than currently
1.340 - # occupied in order to avoid reallocation.
1.341 -
1.342 - new_fragment = self.machine._MakeFragment(header.allocated_size + 1)
1.343 -
1.344 - # Copy existing elements.
1.345 -
1.346 - for i in range(1, header.allocated_size):
1.347 - self.machine.save(new_fragment + i, self.machine.load(fragment + i))
1.348 -
1.349 - self.machine.save(new_fragment + header.allocated_size, (arg_context, arg))
1.350 -
1.351 - # Set the new fragment in the object.
1.352 - # NOTE: The old fragment could be deallocated.
1.353 -
1.354 - self.machine.save(obj + 1, (None, new_fragment))
1.355 -
1.356 - def builtins_tuple_len(self):
1.357 - frame = self.local_sp_stack[-1]
1.358 -
1.359 - # Get the tuple address.
1.360 -
1.361 - obj_context, obj = self.frame_stack[frame]
1.362 -
1.363 - # Get the header.
1.364 - # NOTE: Assume single location for header.
1.365 -
1.366 - header = self.machine.load(obj)
1.367 - nelements = header.size - 1
1.368 -
1.369 - # Make a new object.
1.370 -
1.371 - addr = self.machine._MakeObject(2, self.int_instance)
1.372 -
1.373 - # Store the result.
1.374 - # NOTE: The data is considered ready to use.
1.375 -
1.376 - self.machine.save(addr + 1, nelements)
1.377 -
1.378 - # Return the new object.
1.379 - # Introduce object as context for the new object.
1.380 -
1.381 - self.machine.result = addr, addr
1.382 -
1.383 - def builtins_tuple_getitem(self):
1.384 - frame = self.local_sp_stack[-1]
1.385 -
1.386 - # Get the operand address.
1.387 -
1.388 - item_context, item = self.frame_stack[frame + 1]
1.389 -
1.390 - # Get the tuple address.
1.391 -
1.392 - obj_context, obj = self.frame_stack[frame]
1.393 -
1.394 - # Get the header.
1.395 - # NOTE: Assume single location for header.
1.396 -
1.397 - header = self.machine.load(obj)
1.398 - nelements = header.size - 1
1.399 -
1.400 - # NOTE: Assume single location for data and header.
1.401 -
1.402 - item_pos = self.machine.load(item + 1)
1.403 -
1.404 - if item_pos >= 0 and item_pos < nelements:
1.405 - pass
1.406 - elif item_pos < 0 and item_pos >= -nelements:
1.407 - item_pos = nelements + item_pos
1.408 - else:
1.409 - self.machine.exception = self.machine._MakeObject(2, self.index_error_instance)
1.410 - return self.machine.RaiseException()
1.411 -
1.412 - # NOTE: Assume single location for header.
1.413 -
1.414 - self.machine.result = self.machine.load(obj + 1 + item_pos)
1.415 -
1.416 - def builtins_object_init(self):
1.417 - pass
1.418 -
1.419 - native_functions = {
1.420 -
1.421 - # Native method implementations:
1.422 -
1.423 - "__builtins__.int.__add__" : builtins_int_add,
1.424 - "__builtins__.int.__radd__" : builtins_int_add, # NOTE: To be made distinct.
1.425 - "__builtins__.int.__sub__" : builtins_int_sub,
1.426 - "__builtins__.int.__iadd__" : builtins_int_add,
1.427 - "__builtins__.int.__bool__" : builtins_int_bool,
1.428 - "__builtins__.int.__neg__" : builtins_int_neg,
1.429 - "__builtins__.int.__lt__" : builtins_int_lt,
1.430 - "__builtins__.int.__le__" : builtins_int_le,
1.431 - "__builtins__.int.__gt__" : builtins_int_gt,
1.432 - "__builtins__.int.__ge__" : builtins_int_ge,
1.433 - "__builtins__.int.__eq__" : builtins_int_eq,
1.434 - "__builtins__.int.__ne__" : builtins_int_ne,
1.435 - "__builtins__.int.__and__" : builtins_int_and,
1.436 - "__builtins__.int.__rand__" : builtins_int_and,
1.437 - "__builtins__.int.__or__" : builtins_int_or,
1.438 - "__builtins__.int.__ror__" : builtins_int_or,
1.439 - "__builtins__.bool.__bool__" : builtins_bool_bool,
1.440 - "__builtins__.list.__getitem__" : builtins_list_getitem,
1.441 - "__builtins__.list.__len__" : builtins_list_len,
1.442 - "__builtins__.list.append" : builtins_list_append,
1.443 - "__builtins__.tuple.__len__" : builtins_tuple_len,
1.444 - "__builtins__.tuple.__getitem__" : builtins_tuple_getitem,
1.445 -
1.446 - # Native initialisers:
1.447 -
1.448 - "__builtins__.object.__init__" : builtins_object_init, # NOTE: A no-operation.
1.449 - "__builtins__.BaseException.__init__" : builtins_object_init, # NOTE: To be made distinct, potentially in the builtins module.
1.450 -
1.451 - # Native instantiators:
1.452 -
1.453 - "__builtins__.list" : builtins_list_new,
1.454 - }
1.455 -
1.456 # Convenience functions.
1.457
1.458 def machine(program, with_builtins=0, debug=0, abort_upon_exception=0):