# HG changeset patch # User Paul Boddie # Date 1221435277 -7200 # Node ID b6d5759c931a85604ba5bca82ac0ba65fa72e241 # Parent 7bdf1b4636b8ecba3ca3578c314387dedbfcd8a7 Added exception conditions for various RSVP instructions using AttributeError and TypeError references. Added exception handling around "for" loop item assignment. Added NoneType to the builtins. Added class details for constants in the raw image format. Added an optimisation around simple assignments. diff -r 7bdf1b4636b8 -r b6d5759c931a lib/builtins.py --- a/lib/builtins.py Sun Sep 07 20:23:10 2008 +0200 +++ b/lib/builtins.py Mon Sep 15 01:34:37 2008 +0200 @@ -262,7 +262,8 @@ # Various types. -class EllipsisType(object): pass +class EllipsisType: pass +class NoneType: pass class NotImplementedType: pass # Special values. diff -r 7bdf1b4636b8 -r b6d5759c931a micropython/ast.py --- a/micropython/ast.py Sun Sep 07 20:23:10 2008 +0200 +++ b/micropython/ast.py Mon Sep 15 01:34:37 2008 +0200 @@ -1512,7 +1512,19 @@ def visitAssign(self, node): self.dispatch(node.expr) - self.record_value(0) + + # Check nodes for immediate usage. + + immediate = 1 + + for n in node.nodes: + if not isinstance(n, compiler.ast.AssName): + immediate = 0 + break + + # Record the value and then dispatch to the assignment targets. + + self.record_value(immediate) for n in node.nodes: self.dispatch(n) @@ -1713,6 +1725,8 @@ self._visitBinary(node, "__floordiv__", "__rfloordiv__") def visitFor(self, node): + next_handler_label = self.new_label() + end_handler_label = self.new_label() exit_label = self.new_label() next_label = self.new_label() else_label = self.new_label() @@ -1732,6 +1746,10 @@ self.set_label(next_label) + # Handle exceptions when calling "next"... + + self.new_op(PushHandler(next_handler_label)) + # Use the iterator to get the next value. self._startCallFunc() @@ -1745,6 +1763,15 @@ self.record_value() + # Skip the handler where the call was successful. + + self.new_op(Jump(end_handler_label)) + + # Enter the exception handler. + + self.set_label(next_handler_label) + self.new_op(PopHandler()) + # Test for StopIteration. self.load_builtin("StopIteration", node) @@ -1754,6 +1781,14 @@ else: self.new_op(JumpIfTrue(exit_label)) + # Re-raise the exception otherwise. + + self.new_op(RaiseException()) + + # After the handler. + + self.set_label(end_handler_label) + # Assign to the target. self.dispatch(node.assign) diff -r 7bdf1b4636b8 -r b6d5759c931a micropython/rsvp.py --- a/micropython/rsvp.py Sun Sep 07 20:23:10 2008 +0200 +++ b/micropython/rsvp.py Mon Sep 15 01:34:37 2008 +0200 @@ -23,6 +23,12 @@ from micropython.data import Attr, Class, Const, Function def raw(code, objtable, paramtable): + + """ + Return the raw image representation of the given 'code', using the given + 'objtable' and 'paramtable' to populate structures. + """ + new_code = [] for item in code: @@ -50,8 +56,8 @@ elif isinstance(item, Const): # NOTE: Need class details! new_code.append(( - None, #objtable.as_list().get_code(item.full_name()), - None, #objtable.get_index(item.full_name()), + objtable.as_list().get_code(item.value_type_name()), + objtable.get_index(item.value_type_name()), None, None, 1 diff -r 7bdf1b4636b8 -r b6d5759c931a rsvp.py --- a/rsvp.py Sun Sep 07 20:23:10 2008 +0200 +++ b/rsvp.py Mon Sep 15 01:34:37 2008 +0200 @@ -68,7 +68,7 @@ "A really simple virtual processor." - def __init__(self, memory, objlist, paramlist, pc=None, debug=0): + def __init__(self, memory, objlist, paramlist, attr_error, type_error, pc=None, debug=0): """ Initialise the processor with a 'memory' (a list of values containing @@ -102,6 +102,11 @@ self.result = None self.exception = None + # Constants. + + self.attr_error = attr_error + self.type_error = type_error + def dump(self): print "PC", self.pc, "->", self.load(self.pc) print "PC stack", self.pc_stack @@ -311,8 +316,7 @@ else: self.value = self.load(ref + offset) else: - # NOTE: This should cause an attribute error. - raise Exception, "LoadAttrIndex % r" % element + self.exception = self.attr_error def StoreAttrIndex(self): context, ref = self.value @@ -321,14 +325,11 @@ attr_index, class_attr, replace_context, offset = element if attr_index == self.operand: if class_attr: - # NOTE: This should cause an attribute or type error. - # Class attributes cannot be changed at run-time. - raise Exception, "StoreAttrIndex % r" % element + self.exception = self.type_error else: self.save(ref + offset, self.source) else: - # NOTE: This should cause an attribute error. - raise Exception, "StoreAttrIndex % r" % element + self.exception = self.attr_error # NOTE: LoadAttrIndexContext is a possibility if a particular attribute can always be overridden. @@ -356,8 +357,7 @@ if attr_index == self.operand: self.frame_stack[frame + offset] = self.value else: - # NOTE: This should cause an argument error. - raise Exception, "StoreFrameIndex % r" % element + self.exception = self.type_error def LoadCallable(self): context, ref = self.value diff -r 7bdf1b4636b8 -r b6d5759c931a test.py --- a/test.py Sun Sep 07 20:23:10 2008 +0200 +++ b/test.py Mon Sep 15 01:34:37 2008 +0200 @@ -33,11 +33,14 @@ print "Getting raw structures..." ot = importer.get_object_table() pt = importer.get_parameter_table() - objlist = ot.as_raw() - paramlist = pt.as_raw() + objlist = ot.as_list() + paramlist = pt.as_list() + attr_error = objlist.access("__builtins__", "AttributeError").value.location + type_error = objlist.access("__builtins__", "TypeError").value.location + print "Getting raw image..." rc = raw(importer.get_image(), ot, pt) print "Initialising the machine..." - rm = rsvp.RSVPMachine(rc, objlist, paramlist, debug=debug) + rm = rsvp.RSVPMachine(rc, objlist.as_raw(), paramlist.as_raw(), attr_error, type_error, debug=debug) rm.pc = importer.code_location return rm