1.1 --- a/rsvplib.py Sun Aug 07 23:01:35 2011 +0200
1.2 +++ b/rsvplib.py Sun Aug 21 14:24:28 2011 +0200
1.3 @@ -2,6 +2,9 @@
1.4
1.5 """
1.6 A native function library for a really simple virtual processor.
1.7 +NOTE: Ultimately, this should only implement only operations at the lowest
1.8 +NOTE: possible level, with generated native methods providing the functionality
1.9 +NOTE: instead.
1.10
1.11 Copyright (C) 2007, 2008, 2009, 2010, 2011 Paul Boddie <paul@boddie.org.uk>
1.12
1.13 @@ -56,9 +59,6 @@
1.14 self.attr_error_instance = self.machine.attr_error_instance
1.15 self.type_error_instance = self.machine.type_error_instance
1.16
1.17 - self.frame_stack = self.machine.frame_stack
1.18 - self.local_sp_stack = self.machine.local_sp_stack
1.19 -
1.20 def _get_builtin_class_and_template(self, name):
1.21 cls = self.machine._get_class("__builtins__", name)
1.22 if cls is not None:
1.23 @@ -75,10 +75,10 @@
1.24 pass
1.25
1.26 def native_int_arithmetic_op(self, op):
1.27 - self.machine.LoadName(0) # left value
1.28 - left_data = self.machine.value + self.instance_data_offset
1.29 - self.machine.LoadName(1) # right value
1.30 - right_data = self.machine.value + self.instance_data_offset
1.31 + left = self.machine.load_from_frame(0)
1.32 + left_data = left.ref + self.instance_data_offset
1.33 + right = self.machine.load_from_frame(1)
1.34 + right_data = right.ref + self.instance_data_offset
1.35
1.36 # Make a new object.
1.37
1.38 @@ -92,24 +92,24 @@
1.39 # Return the new object.
1.40 # Introduce object as context for the new object.
1.41
1.42 - self.machine.result_context = addr
1.43 - self.machine.result_value = addr
1.44 + self.machine.LoadImmediate(addr, "result_context")
1.45 + self.machine.LoadImmediate(addr, "result")
1.46
1.47 def native_logical_op(self, op):
1.48 - self.machine.LoadName(0) # left value
1.49 - left_data = self.machine.value + self.instance_data_offset
1.50 - self.machine.LoadName(1) # right value
1.51 - right_data = self.machine.value + self.instance_data_offset
1.52 + left = self.machine.load_from_frame(0)
1.53 + left_data = left.ref + self.instance_data_offset
1.54 + right = self.machine.load_from_frame(1)
1.55 + right_data = right.ref + self.instance_data_offset
1.56
1.57 # Test the data.
1.58 # NOTE: The data is considered ready to use.
1.59
1.60 if op(self.machine.load(left_data), self.machine.load(right_data)):
1.61 - self.machine.result_context = self.constants[True]
1.62 - self.machine.result_value = self.constants[True]
1.63 + self.machine.LoadImmediate(self.constants[True], "result_context")
1.64 + self.machine.LoadImmediate(self.constants[True], "result")
1.65 else:
1.66 - self.machine.result_context = self.constants[False]
1.67 - self.machine.result_value = self.constants[False]
1.68 + self.machine.LoadImmediate(self.constants[False], "result_context")
1.69 + self.machine.LoadImmediate(self.constants[False], "result")
1.70
1.71 # Operators.
1.72 # Although this takes a short-cut by using the operator module, testing is
1.73 @@ -152,8 +152,8 @@
1.74 # Specific operator methods.
1.75
1.76 def builtins_int_neg(self):
1.77 - self.machine.LoadName(0) # left value
1.78 - left_data = self.machine.value + self.instance_data_offset
1.79 + left = self.machine.load_from_frame(0)
1.80 + left_data = left.ref + self.instance_data_offset
1.81
1.82 # Make a new object.
1.83
1.84 @@ -167,17 +167,14 @@
1.85 # Return the new object.
1.86 # Introduce object as context for the new object.
1.87
1.88 - self.machine.result_context = addr
1.89 - self.machine.result_value = addr
1.90 + self.machine.LoadImmediate(addr, "result_context")
1.91 + self.machine.LoadImmediate(addr, "result")
1.92
1.93 # Various built-in methods.
1.94
1.95 def builtins_list_new(self):
1.96 - frame = self.local_sp_stack[-1]
1.97 -
1.98 - # The first parameter should be the instance.
1.99 -
1.100 - list_value = self.frame_stack[frame]
1.101 + list_value = self.machine.load_from_frame(0)
1.102 + list_addr = list_value.ref + self.instance_data_offset
1.103
1.104 # Make a new sequence.
1.105 # NOTE: Using an arbitrary size.
1.106 @@ -187,23 +184,17 @@
1.107 # Complete the list instance by saving the fragment reference.
1.108 # NOTE: This requires an attribute in the list structure.
1.109
1.110 - addr = list_value.ref + self.instance_data_offset
1.111 - self.machine.save(addr, DataValue(None, new_fragment))
1.112 + self.machine.save(list_addr, DataValue(None, new_fragment))
1.113
1.114 def builtins_list_get_single_item(self):
1.115 - frame = self.local_sp_stack[-1]
1.116 -
1.117 - # Get the operand address.
1.118 -
1.119 - item_value = self.frame_stack[frame + 1]
1.120 -
1.121 - # Get the list address.
1.122 -
1.123 - obj_value = self.frame_stack[frame]
1.124 + obj_value = self.machine.load_from_frame(0)
1.125 + fragment_member = obj_value.ref + self.instance_data_offset
1.126 + item_value = self.machine.load_from_frame(1)
1.127 + item_pos_member = item_value.ref + self.instance_data_offset
1.128
1.129 # Get the fragment address.
1.130
1.131 - fragment = self.machine.load(obj_value.ref + self.instance_data_offset)
1.132 + fragment = self.machine.load(fragment_member)
1.133
1.134 # Get the fragment header.
1.135
1.136 @@ -212,28 +203,25 @@
1.137
1.138 # Get the item position.
1.139
1.140 - item_pos = self.machine.load(item_value.ref + self.instance_data_offset)
1.141 + item_pos = self.machine.load(item_pos_member)
1.142
1.143 if not self._check_index(item_pos, nelements):
1.144 - self.machine.exception = self.machine._MakeObject(self.instance_size, self.index_error_instance)
1.145 + self.machine.LoadImmediate(self.machine._MakeObject(self.instance_size, self.index_error_instance), "exception")
1.146 return self.machine.RaiseException()
1.147
1.148 # Get the item itself.
1.149
1.150 data = self.machine.load(fragment.ref + self.fragment_data_offset + item_pos)
1.151 - self.machine.result_context = data.context
1.152 - self.machine.result_value = data.ref
1.153 + self.machine.LoadImmediate(data.context, "result_context")
1.154 + self.machine.LoadImmediate(data.ref, "result")
1.155
1.156 def builtins_list_len(self):
1.157 - frame = self.local_sp_stack[-1]
1.158 -
1.159 - # Get the list address.
1.160 -
1.161 - obj_value = self.frame_stack[frame]
1.162 + obj_value = self.machine.load_from_frame(0)
1.163 + fragment_member = obj_value.ref + self.instance_data_offset
1.164
1.165 # Get the fragment address.
1.166
1.167 - fragment = self.machine.load(obj_value.ref + self.instance_data_offset)
1.168 + fragment = self.machine.load(fragment_member)
1.169
1.170 # Get the fragment header.
1.171
1.172 @@ -252,23 +240,17 @@
1.173 # Return the new object.
1.174 # Introduce object as context for the new object.
1.175
1.176 - self.machine.result_context = addr
1.177 - self.machine.result_value = addr
1.178 + self.machine.LoadImmediate(addr, "result_context")
1.179 + self.machine.LoadImmediate(addr, "result")
1.180
1.181 def builtins_list_append(self):
1.182 - frame = self.local_sp_stack[-1]
1.183 -
1.184 - # Get operand address.
1.185 -
1.186 - arg_value = self.frame_stack[frame + 1]
1.187 -
1.188 - # Get the list address.
1.189 -
1.190 - obj_value = self.frame_stack[frame]
1.191 + obj_value = self.machine.load_from_frame(0)
1.192 + fragment_member = obj_value.ref + self.instance_data_offset
1.193 + arg_value = self.machine.load_from_frame(1)
1.194
1.195 # Get the fragment address.
1.196
1.197 - fragment = self.machine.load(obj_value.ref + self.instance_data_offset)
1.198 + fragment = self.machine.load(fragment_member)
1.199
1.200 # Get the fragment header.
1.201
1.202 @@ -296,10 +278,9 @@
1.203 # Set the new fragment in the object.
1.204 # NOTE: The old fragment could be deallocated.
1.205
1.206 - self.machine.save(obj_value.ref + self.instance_data_offset, DataValue(None, new_fragment))
1.207 + self.machine.save(fragment_member, DataValue(None, new_fragment))
1.208
1.209 def builtins_tuple_new(self):
1.210 - frame = self.local_sp_stack[-1]
1.211
1.212 # Get the sequence address.
1.213 # The first argument should be empty since this function acts as an
1.214 @@ -307,34 +288,34 @@
1.215 # that it can be filled in for the call to an initialiser without
1.216 # allocating a new frame.
1.217
1.218 - obj_value = self.frame_stack[frame + 1]
1.219 + obj_value = self.machine.load_from_frame(1)
1.220 return self._builtins_tuple(obj_value)
1.221
1.222 def builtins_tuple(self):
1.223 - frame = self.local_sp_stack[-1]
1.224
1.225 # Get the sequence address.
1.226
1.227 - obj_value = self.frame_stack[frame]
1.228 + obj_value = self.machine.load_from_frame(0)
1.229 return self._builtins_tuple(obj_value)
1.230
1.231 def _builtins_tuple(self, obj_value):
1.232 + fragment_member = obj_value.ref + self.instance_data_offset
1.233
1.234 if self.machine._CheckInstance(obj_value.ref, self.tuple_class):
1.235 - self.machine.result_context = obj_value.context
1.236 - self.machine.result_value = obj_value.ref
1.237 + self.machine.LoadImmediate(obj_value.context, "result_context")
1.238 + self.machine.LoadImmediate(obj_value.ref, "result")
1.239 return
1.240
1.241 # Reject non-list, non-tuple types.
1.242 # NOTE: This should probably accept any sequence.
1.243
1.244 elif not self.machine._CheckInstance(obj_value.ref, self.list_class):
1.245 - self.machine.exception = self.machine._MakeObject(self.instance_size, self.type_error_instance)
1.246 + self.machine.LoadImmediate(self.machine._MakeObject(self.instance_size, self.type_error_instance), "exception")
1.247 return self.machine.RaiseException()
1.248
1.249 # Get the fragment address.
1.250
1.251 - fragment = self.machine.load(obj_value.ref + self.instance_data_offset)
1.252 + fragment = self.machine.load(fragment_member)
1.253
1.254 # Get the fragment header.
1.255
1.256 @@ -353,15 +334,11 @@
1.257 # Return the new object.
1.258 # Introduce object as context for the new object.
1.259
1.260 - self.machine.result_context = addr
1.261 - self.machine.result_value = addr
1.262 + self.machine.LoadImmediate(addr, "result_context")
1.263 + self.machine.LoadImmediate(addr, "result")
1.264
1.265 def builtins_tuple_len(self):
1.266 - frame = self.local_sp_stack[-1]
1.267 -
1.268 - # Get the tuple address.
1.269 -
1.270 - obj_value = self.frame_stack[frame]
1.271 + obj_value = self.machine.load_from_frame(0)
1.272
1.273 # Get the header.
1.274
1.275 @@ -380,19 +357,14 @@
1.276 # Return the new object.
1.277 # Introduce object as context for the new object.
1.278
1.279 - self.machine.result_context = addr
1.280 - self.machine.result_value = addr
1.281 + self.machine.LoadImmediate(addr, "result_context")
1.282 + self.machine.LoadImmediate(addr, "result")
1.283
1.284 def builtins_tuple_get_single_item(self):
1.285 - frame = self.local_sp_stack[-1]
1.286 -
1.287 - # Get the operand address.
1.288 -
1.289 - item_value = self.frame_stack[frame + 1]
1.290 -
1.291 - # Get the tuple address.
1.292 -
1.293 - obj_value = self.frame_stack[frame]
1.294 + obj_value = self.machine.load_from_frame(0)
1.295 + fragment_member = obj_value.ref + self.instance_data_offset
1.296 + item_value = self.machine.load_from_frame(1)
1.297 + item_pos_member = item_value.ref + self.instance_data_offset
1.298
1.299 # Get the header.
1.300
1.301 @@ -401,33 +373,30 @@
1.302
1.303 # NOTE: Assume single location for data and header.
1.304
1.305 - item_pos = self.machine.load(item_value.ref + self.instance_data_offset)
1.306 + item_pos = self.machine.load(item_pos_member)
1.307
1.308 if not self._check_index(item_pos, nelements):
1.309 - self.machine.exception = self.machine._MakeObject(self.instance_size, self.index_error_instance)
1.310 + self.machine.LoadImmediate(self.machine._MakeObject(self.instance_size, self.index_error_instance), "exception")
1.311 return self.machine.RaiseException()
1.312
1.313 # Get the item.
1.314
1.315 - data = self.machine.load(obj_value.ref + self.instance_data_offset + item_pos)
1.316 - self.machine.result_context = data.context
1.317 - self.machine.result_value = data.ref
1.318 + data = self.machine.load(fragment_member + item_pos)
1.319 + self.machine.LoadImmediate(data.context, "result_context")
1.320 + self.machine.LoadImmediate(data.ref, "result")
1.321
1.322 def builtins_getattr(self):
1.323 - frame = self.local_sp_stack[-1]
1.324 -
1.325 - # Get the object, attribute name.
1.326 -
1.327 - obj_value = self.frame_stack[frame]
1.328 - name_value = self.frame_stack[frame + 1]
1.329 + obj_value = self.machine.load_from_frame(0)
1.330 + name_value = self.machine.load_from_frame(1)
1.331 + index_member = name_value.ref + self.instance_data_offset + 1
1.332
1.333 if not self.machine._CheckInstance(name_value.ref, self.accessor_class):
1.334 - self.machine.exception = self.machine._MakeObject(self.instance_size, self.attr_error_instance)
1.335 + self.machine.LoadImmediate(self.machine._MakeObject(self.instance_size, self.attr_error_instance), "exception")
1.336 return self.machine.RaiseException()
1.337
1.338 # Get the object table index from the name. It is a bare integer, not a reference.
1.339
1.340 - index = self.machine.load(name_value.ref + self.instance_data_offset + 1)
1.341 + index = self.machine.load(index_member)
1.342
1.343 # NOTE: This is very much like LoadAttrIndexContextCond.
1.344
1.345 @@ -443,27 +412,23 @@
1.346 loaded_data = self.machine._LoadAddressContextCond(loaded_data.context, loaded_data.ref, obj_value.ref)
1.347 else:
1.348 loaded_data = self.machine.load(obj_value.ref + offset)
1.349 - self.machine.result_context = loaded_data.context
1.350 - self.machine.result_value = loaded_data.ref
1.351 + self.machine.LoadImmediate(loaded_data.context, "result_context")
1.352 + self.machine.LoadImmediate(loaded_data.ref, "result")
1.353 return
1.354
1.355 - self.machine.exception = self.machine._MakeObject(self.instance_size, self.attr_error_instance)
1.356 + self.machine.LoadImmediate(self.machine._MakeObject(self.instance_size, self.attr_error_instance), "exception")
1.357 return self.machine.RaiseException()
1.358
1.359 def builtins_isinstance(self):
1.360 - frame = self.local_sp_stack[-1]
1.361 -
1.362 - # Get the operand addresses.
1.363 -
1.364 - obj_value = self.frame_stack[frame]
1.365 - cls_value = self.frame_stack[frame + 1]
1.366 + obj_value = self.machine.load_from_frame(0)
1.367 + cls_value = self.machine.load_from_frame(1)
1.368
1.369 if self.machine._CheckInstance(obj_value.ref, cls_value.ref):
1.370 - self.machine.result_context = self.constants[True]
1.371 - self.machine.result_value = self.constants[True]
1.372 + self.machine.LoadImmediate(self.constants[True], "result_context")
1.373 + self.machine.LoadImmediate(self.constants[True], "result")
1.374 else:
1.375 - self.machine.result_context = self.constants[False]
1.376 - self.machine.result_value = self.constants[False]
1.377 + self.machine.LoadImmediate(self.constants[False], "result_context")
1.378 + self.machine.LoadImmediate(self.constants[False], "result")
1.379
1.380 def builtins_print(self):
1.381 # NOTE: Do nothing for now.
1.382 @@ -477,43 +442,43 @@
1.383
1.384 # Native method implementations:
1.385
1.386 - "native._int_add" : native_int_add,
1.387 - "native._int_sub" : native_int_sub,
1.388 - "native._int_pow" : native_int_pow,
1.389 - "native._int_and" : native_int_and,
1.390 - "native._int_or" : native_int_or,
1.391 - "native._int_lt" : native_int_lt,
1.392 - "native._int_gt" : native_int_gt,
1.393 - "native._int_eq" : native_int_eq,
1.394 - "native._str_lt" : native_str_lt,
1.395 - "native._str_gt" : native_str_gt,
1.396 - "native._str_eq" : native_str_eq,
1.397 - "__builtins__.int.__neg__" : builtins_int_neg,
1.398 - "__builtins__.list.__get_single_item__" : builtins_list_get_single_item,
1.399 - "__builtins__.list.__len__" : builtins_list_len,
1.400 - "__builtins__.list.append" : builtins_list_append,
1.401 - "__builtins__.tuple" : builtins_tuple_new,
1.402 - "__builtins__.tuple.__len__" : builtins_tuple_len,
1.403 - "__builtins__.tuple.__get_single_item__" : builtins_tuple_get_single_item,
1.404 + "native._int_add" : native_int_add,
1.405 + "native._int_sub" : native_int_sub,
1.406 + "native._int_pow" : native_int_pow,
1.407 + "native._int_and" : native_int_and,
1.408 + "native._int_or" : native_int_or,
1.409 + "native._int_lt" : native_int_lt,
1.410 + "native._int_gt" : native_int_gt,
1.411 + "native._int_eq" : native_int_eq,
1.412 + "native._str_lt" : native_str_lt,
1.413 + "native._str_gt" : native_str_gt,
1.414 + "native._str_eq" : native_str_eq,
1.415 + "__builtins__.int.__neg__" : builtins_int_neg,
1.416 + "__builtins__.list.__get_single_item__" : builtins_list_get_single_item,
1.417 + "__builtins__.list.__len__" : builtins_list_len,
1.418 + "__builtins__.list.append" : builtins_list_append,
1.419 + "__builtins__.tuple" : builtins_tuple_new,
1.420 + "__builtins__.tuple.__len__" : builtins_tuple_len,
1.421 + "__builtins__.tuple.__get_single_item__" : builtins_tuple_get_single_item,
1.422
1.423 # Native initialisers:
1.424
1.425 - "__builtins__.BaseException.__init__" : builtins_no_op, # NOTE: To be made distinct, potentially in the builtins module.
1.426 + "__builtins__.BaseException.__init__" : builtins_no_op, # NOTE: To be made distinct, potentially in the builtins module.
1.427
1.428 # Native functions:
1.429
1.430 - "__builtins__._getattr" : builtins_getattr,
1.431 + "__builtins__._getattr" : builtins_getattr,
1.432
1.433 # Native instantiator helpers:
1.434
1.435 - "__builtins__.list.__new__" : builtins_list_new,
1.436 + "__builtins__.list.__new__" : builtins_list_new,
1.437
1.438 # Native helper functions:
1.439
1.440 - "__builtins__._isinstance" : builtins_isinstance,
1.441 - "__builtins__._print" : builtins_print,
1.442 - "__builtins__._printnl" : builtins_printnl,
1.443 - "__builtins__._tuple" : builtins_tuple,
1.444 + "__builtins__._isinstance" : builtins_isinstance,
1.445 + "__builtins__._print" : builtins_print,
1.446 + "__builtins__._printnl" : builtins_printnl,
1.447 + "__builtins__._tuple" : builtins_tuple,
1.448 }
1.449
1.450 # vim: tabstop=4 expandtab shiftwidth=4