Ejemplo n.º 1
0
Archivo: root.py Proyecto: dckc/typhon
    def callAtom(self, atom, arguments, namedArgsMap):
        """
        This method is used to reuse atoms without having to rebuild them.
        """
        # Promote the atom, on the basis that atoms are generally reused.
        atom = promote(atom)
        # Log the atom to the JIT log. Don't do this if the atom's not
        # promoted; it'll be slow.
        jit_debug(atom.repr)

        try:
            return self.recvNamed(atom, arguments, namedArgsMap)
        except Refused as r:
            addTrail(r, self, atom, arguments)
            raise
        except UserException as ue:
            addTrail(ue, self, atom, arguments)
            raise
        except MemoryError:
            ue = userError(u"Memory corruption or exhausted heap")
            addTrail(ue, self, atom, arguments)
            raise ue
        except StackOverflow:
            check_stack_overflow()
            ue = userError(u"Stack overflow")
            addTrail(ue, self, atom, arguments)
            raise ue
Ejemplo n.º 2
0
 def _interpret(self, space, pc, frame, bytecode):
     prev_instr = frame.last_instr
     frame.last_instr = pc
     if (space.getexecutioncontext().hastraceproc()
             and bytecode.lineno_table[pc] !=
             bytecode.lineno_table[prev_instr]):
         space.getexecutioncontext().invoke_trace_proc(space,
                                                       "line",
                                                       None,
                                                       None,
                                                       frame=frame)
     try:
         pc = self.handle_bytecode(space, pc, frame, bytecode)
     except RubyError as e:
         pc = self.handle_ruby_error(space, pc, frame, bytecode, e)
     except RaiseReturn as e:
         pc = self.handle_raise_return(space, pc, frame, bytecode, e)
     except RaiseBreak as e:
         pc = self.handle_raise_break(space, pc, frame, bytecode, e)
     except Throw as e:
         pc = self.handle_throw(space, pc, frame, bytecode, e)
     except rstackovf.StackOverflow:
         rstackovf.check_stack_overflow()
         pc = self.handle_ruby_error(
             space, pc, frame, bytecode,
             space.error(space.w_SystemStackError, "stack level too deep"))
     return pc
Ejemplo n.º 3
0
 def dump_w_obj(self, w_obj):
     space = self.space
     try:
         self.put_w_obj(w_obj)
     except rstackovf.StackOverflow:
         rstackovf.check_stack_overflow()
         self._overflow()
Ejemplo n.º 4
0
 def dump_w_obj(self, w_obj):
     space = self.space
     try:
         self.put_w_obj(w_obj)
     except rstackovf.StackOverflow:
         rstackovf.check_stack_overflow()
         self._overflow()
Ejemplo n.º 5
0
 def dump_w_obj(self, w_obj):
     space = self.space
     if (space.type(w_obj).is_heaptype() and
         space.lookup(w_obj, "__buffer__") is None):
         w_err = space.wrap("only builtins can be marshaled")
         raise OperationError(space.w_ValueError, w_err)
     try:
         self.put_w_obj(w_obj)
     except rstackovf.StackOverflow:
         rstackovf.check_stack_overflow()
         self._overflow()
Ejemplo n.º 6
0
 def handle_exception(self, space, e):
     try:
         if not we_are_translated():
             raise
         raise e
     except KeyboardInterrupt:
         raise OperationError(space.w_KeyboardInterrupt, space.w_None)
     except MemoryError:
         raise OperationError(space.w_MemoryError, space.w_None)
     except rstackovf.StackOverflow, e:
         rstackovf.check_stack_overflow()
         raise OperationError(space.w_RuntimeError, space.wrap("maximum recursion depth exceeded"))
Ejemplo n.º 7
0
 def load_w_obj(self, allow_null=False):
     try:
         return self._get_w_obj(allow_null)
     except rstackovf.StackOverflow:
         rstackovf.check_stack_overflow()
         self._overflow()
     except OperationError as e:
         if not e.match(self.space, self.space.w_RecursionError):
             raise
         # somebody else has already converted the rpython overflow error to
         # an OperationError (e.g. one of che space.call* calls in
         # marshal_impl), turn it into a ValueError
         self._overflow()
Ejemplo n.º 8
0
 def handle_exception(self, space, e):
     try:
         if not we_are_translated():
             raise
         raise e
     except KeyboardInterrupt:
         raise OperationError(space.w_KeyboardInterrupt, space.w_None)
     except MemoryError:
         raise OperationError(space.w_MemoryError, space.w_None)
     except rstackovf.StackOverflow, e:
         rstackovf.check_stack_overflow()
         raise OperationError(
             space.w_RuntimeError,
             space.wrap("maximum recursion depth exceeded"))
Ejemplo n.º 9
0
 def dump_w_obj(self, w_obj):
     space = self.space
     if space.type(w_obj).is_heaptype():
         try:
             buf = space.readbuf_w(w_obj)
         except OperationError as e:
             if not e.match(space, space.w_TypeError):
                 raise
             self.raise_exc("unmarshallable object")
         else:
             w_obj = space.newbuffer(buf)
     try:
         self.put_w_obj(w_obj)
     except rstackovf.StackOverflow:
         rstackovf.check_stack_overflow()
         self._overflow()
Ejemplo n.º 10
0
 def dump_w_obj(self, w_obj):
     space = self.space
     if space.type(w_obj).is_heaptype():
         try:
             buf = space.readbuf_w(w_obj)
         except OperationError as e:
             if not e.match(space, space.w_TypeError):
                 raise
             self.raise_exc("unmarshallable object")
         else:
             w_obj = space.newbuffer(buf)
     try:
         self.put_w_obj(w_obj)
     except rstackovf.StackOverflow:
         rstackovf.check_stack_overflow()
         self._overflow()
Ejemplo n.º 11
0
 def stack_frame(self, s_frame, s_sender, may_context_switch=True):
     if self.is_tracing():
         self.stack_depth += 1
     vref = s_frame.enter_virtual_frame(s_sender)
     try:
         self.loop_bytecodes(s_frame, may_context_switch)
     except rstackovf.StackOverflow:
         rstackovf.check_stack_overflow()
         raise StackOverflow(s_frame)
     except LocalReturn, ret:
         if s_frame.get_state() is DirtyContext:
             s_new_sender = s_frame.s_sender()  # The sender has changed!
             s_frame._activate_unwind_context(self)
             raise NonVirtualReturn(s_new_sender, s_new_sender, ret.value(self.space))
         else:
             s_frame._activate_unwind_context(self)
             raise ret
Ejemplo n.º 12
0
 def stack_frame(self, s_frame, s_sender, may_context_switch):
     if self.is_tracing():
         self.stack_depth += 1
     vref = s_frame.enter_virtual_frame(s_sender)
     try:
         self.loop_bytecodes(s_frame, may_context_switch)
     except rstackovf.StackOverflow:
         rstackovf.check_stack_overflow()
         raise StackOverflow(s_frame)
     except LocalReturn, ret:
         if s_frame.get_state() is DirtyContext:
             s_new_sender = s_frame.s_sender()  # The sender has changed!
             s_frame._activate_unwind_context(self)
             raise NonVirtualReturn(s_new_sender, s_new_sender, ret.value(self.space))
         else:
             s_frame._activate_unwind_context(self)
             raise ret
Ejemplo n.º 13
0
def get_converted_unexpected_exception(space, e):
    """This is used in two places when we get an non-OperationError
    RPython exception: from gateway.py when calling an interp-level
    function raises; and from pyopcode.py when we're exiting the
    interpretation of the frame with an exception.  Note that it
    *cannot* be used in pyopcode.py: that place gets a
    ContinueRunningNormally exception from the JIT, which must not end
    up here!
    """
    try:
        if not we_are_translated():
            raise
        raise e
    except KeyboardInterrupt:
        return OperationError(space.w_KeyboardInterrupt, space.w_None)
    except MemoryError:
        return OperationError(space.w_MemoryError, space.w_None)
    except rstackovf.StackOverflow as e:
        # xxx twisted logic which happens to give the result that we
        # want: when untranslated, a RuntimeError or its subclass
        # NotImplementedError is caught here.  Then
        # check_stack_overflow() will re-raise it directly.  We see
        # the result as this exception propagates directly.  But when
        # translated, an RPython-level RuntimeError is turned into
        # an app-level RuntimeError by the next case.
        rstackovf.check_stack_overflow()
        return oefmt(space.w_RecursionError,
                     "maximum recursion depth exceeded")
    except RuntimeError:  # not on top of py.py
        return OperationError(space.w_RuntimeError, space.w_None)
    except:
        if we_are_translated():
            from rpython.rlib.debug import debug_print_traceback
            debug_print_traceback()
            extra = '; internal traceback was dumped to stderr'
        else:
            # when untranslated, we don't wrap into an app-level
            # SystemError (this makes debugging tests harder)
            raise
        return OperationError(
            space.w_SystemError,
            space.newtext(
                "unexpected internal exception (please report a bug): %r%s" %
                (e, extra)))
Ejemplo n.º 14
0
def get_converted_unexpected_exception(space, e):
    """This is used in two places when we get an non-OperationError
    RPython exception: from gateway.py when calling an interp-level
    function raises; and from pyopcode.py when we're exiting the
    interpretation of the frame with an exception.  Note that it
    *cannot* be used in pyopcode.py: that place gets a
    ContinueRunningNormally exception from the JIT, which must not end
    up here!
    """
    try:
        if not we_are_translated():
            raise
        raise e
    except KeyboardInterrupt:
        return OperationError(space.w_KeyboardInterrupt, space.w_None)
    except MemoryError:
        return OperationError(space.w_MemoryError, space.w_None)
    except rstackovf.StackOverflow as e:
        # xxx twisted logic which happens to give the result that we
        # want: when untranslated, a RuntimeError or its subclass
        # NotImplementedError is caught here.  Then
        # check_stack_overflow() will re-raise it directly.  We see
        # the result as this exception propagates directly.  But when
        # translated, an RPython-level RuntimeError is turned into
        # an app-level RuntimeError by the next case.
        rstackovf.check_stack_overflow()
        return oefmt(space.w_RuntimeError, "maximum recursion depth exceeded")
    except RuntimeError:  # not on top of py.py
        return OperationError(space.w_RuntimeError, space.w_None)
    except:
        if we_are_translated():
            from rpython.rlib.debug import debug_print_traceback

            debug_print_traceback()
            extra = "; internal traceback was dumped to stderr"
        else:
            # when untranslated, we don't wrap into an app-level
            # SystemError (this makes debugging tests harder)
            raise
        return OperationError(
            space.w_SystemError, space.wrap("unexpected internal exception (please report a bug): %r%s" % (e, extra))
        )
Ejemplo n.º 15
0
 def _interpret(self, space, pc, frame, bytecode):
     prev_instr = frame.last_instr
     frame.last_instr = pc
     if (space.getexecutioncontext().hastraceproc() and
         bytecode.lineno_table[pc] != bytecode.lineno_table[prev_instr]):
         space.getexecutioncontext().invoke_trace_proc(space, "line", None, None, frame=frame)
     try:
         pc = self.handle_bytecode(space, pc, frame, bytecode)
     except RubyError as e:
         pc = self.handle_ruby_error(space, pc, frame, bytecode, e)
     except RaiseReturn as e:
         pc = self.handle_raise_return(space, pc, frame, bytecode, e)
     except RaiseBreak as e:
         pc = self.handle_raise_break(space, pc, frame, bytecode, e)
     except Throw as e:
         pc = self.handle_throw(space, pc, frame, bytecode, e)
     except rstackovf.StackOverflow:
         rstackovf.check_stack_overflow()
         pc = self.handle_ruby_error(space, pc, frame, bytecode, space.error(space.w_SystemStackError, "stack level too deep"))
     return pc
Ejemplo n.º 16
0
 def stack_frame(self, s_frame, s_sender, may_context_switch=True):
     try:
         if self.is_tracing():
             self.stack_depth += 1
         if s_frame._s_sender is None and s_sender is not None:
             s_frame.store_s_sender(s_sender)
         # Now (continue to) execute the context bytecodes
         # assert s_frame.state is InactiveContext
         s_frame.state = ActiveContext
         self.loop_bytecodes(s_frame, may_context_switch)
     except rstackovf.StackOverflow:
         rstackovf.check_stack_overflow()
         raise StackOverflow(s_frame)
     except LocalReturn, ret:
         if s_frame.state is DirtyContext:
             s_sender = s_frame.s_sender()  # The sender has changed!
             s_frame._activate_unwind_context(self)
             raise NonVirtualReturn(s_sender, s_sender, ret.value(self.space))
         else:
             s_frame._activate_unwind_context(self)
             raise ret
Ejemplo n.º 17
0
    def callAtom(self, atom, arguments, namedArgsMap=None, span=None):
        """
        This method is used to reuse atoms without having to rebuild them.

        This is the correct method to call if you have an atom.
        """

        # Promote the atom, on the basis that atoms are generally reused.
        atom = promote(atom)
        # Log the atom to the JIT log. Don't do this if the atom's not
        # promoted; it'll be slow.
        jit_debug(atom.repr)

        if namedArgsMap is None or namedArgsMap.isEmpty():
            namedArgsMap = MIRANDA_MAP
        else:
            from typhon.objects.collections.maps import ConstMap
            namedArgsMap = ConstMap(namedArgsMap._or(MIRANDA_ARGS))

        try:
            return self.recvNamed(atom, arguments, namedArgsMap)
        except Refused as r:
            r.addTrail(self, atom, arguments, span)
            raise
        except UserException as ue:
            ue.addTrail(self, atom, arguments, span)
            raise
        except MemoryError:
            ue = userError(u"Memory corruption or exhausted heap")
            ue.addTrail(self, atom, arguments, span)
            raise ue
        except StackOverflow:
            check_stack_overflow()
            ue = userError(u"Stack overflow")
            ue.addTrail(self, atom, arguments, span)
            raise ue
Ejemplo n.º 18
0
 def stack_frame(self, s_frame, s_sender, may_context_switch=True):
     try:
         if self.is_tracing():
             self.stack_depth += 1
         if s_frame._s_sender is None and s_sender is not None:
             s_frame.store_s_sender(s_sender)
         # Now (continue to) execute the context bytecodes
         # assert s_frame.state is InactiveContext
         s_frame.state = ActiveContext
         self.loop_bytecodes(s_frame, may_context_switch)
     except rstackovf.StackOverflow:
         rstackovf.check_stack_overflow()
         raise StackOverflow(s_frame)
     except Return, ret:
         if s_frame.state is DirtyContext:
             s_sender = s_frame.s_sender()  # The sender has changed!
             s_frame._activate_unwind_context(self)
             target_context = s_sender if ret.is_local else ret.s_target_context
             raise NonVirtualReturn(target_context, s_sender, ret.value)
         else:
             s_frame._activate_unwind_context(self)
             if ret.is_local or ret.s_target_context is s_sender:
                 ret.arrived_at_target = True
             raise ret
Ejemplo n.º 19
0
    def callAtom(self, atom, arguments, namedArgsMap=None, span=None):
        """
        This method is used to reuse atoms without having to rebuild them.

        This is the correct method to call if you have an atom.
        """

        # Promote the atom, on the basis that atoms are generally reused.
        atom = promote(atom)
        # Log the atom to the JIT log. Don't do this if the atom's not
        # promoted; it'll be slow.
        jit_debug(atom.repr)

        if namedArgsMap is None or namedArgsMap.isEmpty():
            namedArgsMap = MIRANDA_MAP
        else:
            from typhon.objects.collections.maps import ConstMap
            namedArgsMap = ConstMap(namedArgsMap._or(MIRANDA_ARGS))

        try:
            return self.recvNamed(atom, arguments, namedArgsMap)
        except Refused as r:
            r.addTrail(self, atom, arguments, span)
            raise
        except UserException as ue:
            ue.addTrail(self, atom, arguments, span)
            raise
        except MemoryError:
            ue = userError(u"Memory corruption or exhausted heap")
            ue.addTrail(self, atom, arguments, span)
            raise ue
        except StackOverflow:
            check_stack_overflow()
            ue = userError(u"Stack overflow")
            ue.addTrail(self, atom, arguments, span)
            raise ue
Ejemplo n.º 20
0
 def load_w_obj(self):
     try:
         return self.get_w_obj()
     except rstackovf.StackOverflow:
         rstackovf.check_stack_overflow()
         self._overflow()
Ejemplo n.º 21
0
 def load_w_obj(self):
     try:
         return self.get_w_obj()
     except rstackovf.StackOverflow:
         rstackovf.check_stack_overflow()
         self._overflow()
Ejemplo n.º 22
0
    def callAtom(self, atom, arguments, namedArgsMap):
        """
        This method is used to reuse atoms without having to rebuild them.
        """
        from typhon.objects.collections.maps import EMPTY_MAP
        # Promote the atom, on the basis that atoms are generally reused.
        atom = promote(atom)
        # Log the atom to the JIT log. Don't do this if the atom's not
        # promoted; it'll be slow.
        jit_debug(atom.repr)

        try:
            return self.recvNamed(atom, arguments, namedArgsMap)
        except Refused as r:
            # This block of method implementations is Typhon's Miranda
            # protocol. ~ C.

            if atom is _CONFORMTO_1:
                # Welcome to _conformTo/1.
                # to _conformTo(_): return self
                return self

            if atom is _GETALLEGEDINTERFACE_0:
                # Welcome to _getAllegedInterface/0.
                interface = self.optInterface()
                if interface is None:
                    from typhon.objects.interfaces import ComputedInterface
                    interface = ComputedInterface(self)
                return interface

            if atom is _PRINTON_1:
                # Welcome to _printOn/1.
                from typhon.objects.constants import NullObject
                self.printOn(arguments[0])
                return NullObject

            if atom is _RESPONDSTO_2:
                from typhon.objects.constants import wrapBool
                from typhon.objects.data import unwrapInt, unwrapStr
                verb = unwrapStr(arguments[0])
                arity = unwrapInt(arguments[1])
                atom = getAtom(verb, arity)
                result = (atom in self.respondingAtoms() or
                          atom in mirandaAtoms)
                return wrapBool(result)

            if atom is _SEALEDDISPATCH_1:
                # to _sealedDispatch(_): return null
                from typhon.objects.constants import NullObject
                return NullObject

            if atom is _UNCALL_0:
                from typhon.objects.constants import NullObject
                return NullObject

            if atom is _WHENMORERESOLVED_1:
                # Welcome to _whenMoreResolved.
                # This method's implementation, in Monte, should be:
                # to _whenMoreResolved(callback): callback<-(self)
                from typhon.vats import currentVat
                vat = currentVat.get()
                vat.sendOnly(arguments[0], RUN_1, [self], EMPTY_MAP)
                from typhon.objects.constants import NullObject
                return NullObject

            addTrail(r, self, atom, arguments)
            raise

        except UserException as ue:
            addTrail(ue, self, atom, arguments)
            raise
        except MemoryError:
            ue = userError(u"Memory corruption or exhausted heap")
            addTrail(ue, self, atom, arguments)
            raise ue
        except StackOverflow:
            check_stack_overflow()
            ue = userError(u"Stack overflow")
            addTrail(ue, self, atom, arguments)
            raise ue
Ejemplo n.º 23
0
class LLFrame(object):
    def __init__(self, graph, args, llinterpreter):
        assert not graph or isinstance(graph, FunctionGraph)
        self.graph = graph
        self.args = args
        self.llinterpreter = llinterpreter
        self.heap = llinterpreter.heap
        self.bindings = {}
        self.curr_block = None
        self.curr_operation_index = 0
        self.alloca_objects = []

    def newsubframe(self, graph, args):
        return self.__class__(graph, args, self.llinterpreter)

    # _______________________________________________________
    # variable setters/getters helpers

    def clear(self):
        self.bindings.clear()

    def fillvars(self, block, values):
        vars = block.inputargs
        assert len(vars) == len(values), (
            "block %s received %d args, expected %d" %
            (block, len(values), len(vars)))
        for var, val in zip(vars, values):
            self.setvar(var, val)

    def setvar(self, var, val):
        if var.concretetype is not lltype.Void:
            try:
                val = lltype.enforce(var.concretetype, val)
            except TypeError:
                assert False, "type error: input value of type:\n\n\t%r\n\n===> variable of type:\n\n\t%r\n" % (
                    lltype.typeOf(val), var.concretetype)
        assert isinstance(var, Variable)
        self.bindings[var] = val

    def setifvar(self, var, val):
        if isinstance(var, Variable):
            self.setvar(var, val)

    def getval(self, varorconst):
        try:
            val = varorconst.value
        except AttributeError:
            val = self.bindings[varorconst]
        if isinstance(val, ComputedIntSymbolic):
            val = val.compute_fn()
        if varorconst.concretetype is not lltype.Void:
            try:
                val = lltype.enforce(varorconst.concretetype, val)
            except TypeError:
                assert False, "type error: %r val from %r var/const" % (
                    lltype.typeOf(val), varorconst.concretetype)
        return val

    # _______________________________________________________
    # other helpers
    def getoperationhandler(self, opname):
        ophandler = getattr(self, 'op_' + opname, None)
        if ophandler is None:
            # try to import the operation from opimpl.py
            ophandler = lloperation.LL_OPERATIONS[opname].fold
            setattr(self.__class__, 'op_' + opname, staticmethod(ophandler))
        return ophandler

    # _______________________________________________________
    # evaling functions

    def eval(self):
        graph = self.graph
        tracer = self.llinterpreter.tracer
        if tracer:
            tracer.enter(graph)
        self.llinterpreter.frame_stack.append(self)
        try:
            try:
                nextblock = graph.startblock
                args = self.args
                while 1:
                    self.clear()
                    self.fillvars(nextblock, args)
                    nextblock, args = self.eval_block(nextblock)
                    if nextblock is None:
                        for obj in self.alloca_objects:
                            obj._obj._free()
                        return args
            except Exception:
                self.llinterpreter.traceback_frames.append(self)
                raise
        finally:
            leavingframe = self.llinterpreter.frame_stack.pop()
            assert leavingframe is self
            if tracer:
                tracer.leave()

    def eval_block(self, block):
        """ return (nextblock, values) tuple. If nextblock
            is None, values is the concrete return value.
        """
        self.curr_block = block
        e = None

        try:
            for i, op in enumerate(block.operations):
                self.curr_operation_index = i
                self.eval_operation(op)
        except LLException, e:
            if op is not block.raising_op:
                raise
        except RuntimeError, e:
            rstackovf.check_stack_overflow()
            # xxx fish fish fish for proper etype and evalue to use
            rtyper = self.llinterpreter.typer
            bk = rtyper.annotator.bookkeeper
            classdef = bk.getuniqueclassdef(rstackovf._StackOverflow)
            exdata = rtyper.exceptiondata
            evalue = exdata.get_standard_ll_exc_instance(rtyper, classdef)
            etype = exdata.fn_type_of_exc_inst(evalue)
            e = LLException(etype, evalue)
            if op is not block.raising_op:
                raise e
Ejemplo n.º 24
0
    def callAtom(self, atom, arguments, namedArgsMap):
        """
        This method is used to reuse atoms without having to rebuild them.
        """
        from typhon.objects.collections.maps import EMPTY_MAP
        # Promote the atom, on the basis that atoms are generally reused.
        atom = promote(atom)
        # Log the atom to the JIT log. Don't do this if the atom's not
        # promoted; it'll be slow.
        jit_debug(atom.repr)

        try:
            return self.recvNamed(atom, arguments, namedArgsMap)
        except Refused as r:
            # This block of method implementations is Typhon's Miranda
            # protocol. ~ C.

            if atom is _CONFORMTO_1:
                # Welcome to _conformTo/1.
                # to _conformTo(_): return self
                return self

            if atom is _GETALLEGEDINTERFACE_0:
                # Welcome to _getAllegedInterface/0.
                interface = self.optInterface()
                if interface is None:
                    from typhon.objects.interfaces import ComputedInterface
                    interface = ComputedInterface(self)
                return interface

            if atom is _PRINTON_1:
                # Welcome to _printOn/1.
                from typhon.objects.constants import NullObject
                self.printOn(arguments[0])
                return NullObject

            if atom is _RESPONDSTO_2:
                from typhon.objects.constants import wrapBool
                from typhon.objects.data import unwrapInt, unwrapStr
                verb = unwrapStr(arguments[0])
                arity = unwrapInt(arguments[1])
                atom = getAtom(verb, arity)
                result = (atom in self.respondingAtoms()
                          or atom in mirandaAtoms)
                return wrapBool(result)

            if atom is _SEALEDDISPATCH_1:
                # to _sealedDispatch(_): return null
                from typhon.objects.constants import NullObject
                return NullObject

            if atom is _UNCALL_0:
                from typhon.objects.constants import NullObject
                return NullObject

            if atom is _WHENMORERESOLVED_1:
                # Welcome to _whenMoreResolved.
                # This method's implementation, in Monte, should be:
                # to _whenMoreResolved(callback): callback<-(self)
                from typhon.vats import currentVat
                vat = currentVat.get()
                vat.sendOnly(arguments[0], RUN_1, [self], EMPTY_MAP)
                from typhon.objects.constants import NullObject
                return NullObject

            addTrail(r, self, atom, arguments)
            raise

        except UserException as ue:
            addTrail(ue, self, atom, arguments)
            raise
        except MemoryError:
            ue = userError(u"Memory corruption or exhausted heap")
            addTrail(ue, self, atom, arguments)
            raise ue
        except StackOverflow:
            check_stack_overflow()
            ue = userError(u"Stack overflow")
            addTrail(ue, self, atom, arguments)
            raise ue
Ejemplo n.º 25
0
    def eval_block(self, block):
        """ return (nextblock, values) tuple. If nextblock
            is None, values is the concrete return value.
        """
        self.curr_block = block
        e = None

        try:
            for i, op in enumerate(block.operations):
                self.curr_operation_index = i
                self.eval_operation(op)
        except LLException as e:
            if op is not block.raising_op:
                raise
        except RuntimeError as e:
            rstackovf.check_stack_overflow()
            # xxx fish fish fish for proper etype and evalue to use
            rtyper = self.llinterpreter.typer
            bk = rtyper.annotator.bookkeeper
            classdef = bk.getuniqueclassdef(rstackovf._StackOverflow)
            exdata = rtyper.exceptiondata
            evalue = exdata.get_standard_ll_exc_instance(rtyper, classdef)
            etype = exdata.fn_type_of_exc_inst(evalue)
            e = LLException(etype, evalue)
            if op is not block.raising_op:
                raise e

        # determine nextblock and/or return value
        if len(block.exits) == 0:
            # return block
            tracer = self.llinterpreter.tracer
            if len(block.inputargs) == 2:
                # exception
                if tracer:
                    tracer.dump('raise')
                etypevar, evaluevar = block.getvariables()
                etype = self.getval(etypevar)
                evalue = self.getval(evaluevar)
                # watch out, these are _ptr's
                raise LLException(etype, evalue)
            resultvar, = block.getvariables()
            result = self.getval(resultvar)
            exc_data = self.llinterpreter.get_transformed_exc_data(self.graph)
            if exc_data:
                # re-raise the exception set by this graph, if any
                etype = exc_data.exc_type
                if etype:
                    evalue = exc_data.exc_value
                    if tracer:
                        tracer.dump('raise')
                    exc_data.exc_type = lltype.typeOf(etype)._defl()
                    exc_data.exc_value = lltype.typeOf(evalue)._defl()
                    from rpython.translator import exceptiontransform
                    T = resultvar.concretetype
                    errvalue = exceptiontransform.error_value(T)
                    # check that the exc-transformed graph returns the error
                    # value when it returns with an exception set
                    assert result == errvalue
                    raise LLException(etype, evalue)
            if tracer:
                tracer.dump('return')
            return None, result
        elif block.exitswitch is None:
            # single-exit block
            assert len(block.exits) == 1
            link = block.exits[0]
        elif block.canraise:
            link = block.exits[0]
            if e:
                exdata = self.llinterpreter.typer.exceptiondata
                cls = e.args[0]
                inst = e.args[1]
                for link in block.exits[1:]:
                    assert issubclass(link.exitcase, py.builtin.BaseException)
                    if self.op_direct_call(exdata.fn_exception_match,
                                           cls, link.llexitcase):
                        self.setifvar(link.last_exception, cls)
                        self.setifvar(link.last_exc_value, inst)
                        break
                else:
                    # no handler found, pass on
                    raise e
        else:
            llexitvalue = self.getval(block.exitswitch)
            if block.exits[-1].exitcase == "default":
                defaultexit = block.exits[-1]
                nondefaultexits = block.exits[:-1]
                assert defaultexit.llexitcase is None
            else:
                defaultexit = None
                nondefaultexits = block.exits
            for link in nondefaultexits:
                if link.llexitcase == llexitvalue:
                    break   # found -- the result is in 'link'
            else:
                if defaultexit is None:
                    raise ValueError("exit case %r not found in the exit links "
                                     "of %r" % (llexitvalue, block))
                else:
                    link = defaultexit
        return link.target, [self.getval(x) for x in link.args]