Пример #1
0
 def visitAstTryCatchExpression(self, node):
     tryTy = self.visit(node.expression)
     exnTy = ir_t.ClassType.forReceiver(getExceptionClass())
     if node.catchHandler is None:
         catchTy = ir_t.NoType
     else:
         catchTy = self.visit(node.catchHandler, exnTy)
     if node.finallyHandler is not None:
         self.visit(node.finallyHandler)
     ty = tryTy.combine(catchTy, node.location)
     return ty
Пример #2
0
 def testTryExpr(self):
     info = self.analyzeFromSource("class Base\n" +
                                   "class A <: Base\n" +
                                   "  def this = {}\n" +
                                   "class B <: Base\n" +
                                   "  def this = {}\n" +
                                   "def f = try A catch\n" +
                                   "    case exn => B\n" +
                                   "  finally 12")
     baseTy = ClassType(info.package.findClass(name="Base"), ())
     astBody = info.ast.definitions[3].body
     self.assertEquals(baseTy, info.getType(astBody))
     self.assertEquals(ClassType(getExceptionClass()),
                       info.getType(astBody.catchHandler.cases[0].pattern))
     self.assertEquals(I64Type, info.getType(astBody.finallyHandler))
Пример #3
0
def getExceptionClassType():
    return ClassType(builtins.getExceptionClass())
Пример #4
0
 def testInheritFromException(self):
     info = self.analyzeFromSource("class Foo <: Exception")
     ast = info.ast
     clas = info.package.findClass(name="Foo")
     classInfo = info.getClassInfo(clas)
     self.assertIs(getExceptionClass(), classInfo.superclassInfo.irDefn)
Пример #5
0
 def testInheritFromException(self):
     info = self.analyzeFromSource("class Foo <: Exception")
     ast = info.ast
     classInfo = info.getClassInfo(ast.definitions[0])
     superclassInfo = classInfo.superclassInfo
     self.assertIs(getExceptionClass(), superclassInfo.irDefn)
Пример #6
0
 def visitAstThrowExpression(self, node):
     exnTy = self.visit(node.exception)
     if not exnTy.isSubtypeOf(ir_t.ClassType(getExceptionClass())):
         raise TypeException(node.location, "throw expression must produce an Exception")
     return ir_t.NoType
Пример #7
0
    def visitAstTryCatchExpression(self, expr, mode):
        # Create blocks. If there is a finally handler, we need some extra logic.
        tryBlock = self.newBlock()
        catchBlock = self.newBlock()
        doneBlock = self.newBlock()
        rethrowBlock = self.newBlock()
        if expr.finallyHandler is None:
            assert expr.catchHandler is not None
            successBlock = doneBlock
            failBlock = rethrowBlock
        elif expr.catchHandler is None:
            assert expr.finallyHandler is not None
            successBlock = self.newBlock()
            failBlock = catchBlock
            finallyBlock = self.newBlock()
        else:
            successBlock = self.newBlock()
            failBlock = self.newBlock()
            finallyBlock = self.newBlock()

        # Enter the try expression.
        # Stack at this point: [...]
        self.pushtry(tryBlock.id, catchBlock.id)

        # Compile the try expression.
        # Stack at this point: [...]
        self.setCurrentBlock(tryBlock)
        with UnreachableScope(self):
            self.visit(expr.expression, mode)
            if expr.finallyHandler is not None:
                self.poptry(successBlock.id)
            else:
                self.poptry(doneBlock.id)

        # Compile the catch. When we land here, the stack is reset to the same height as the
        # beginning of the try, and the Exception object is pushed on top.
        # Stack at this point: [exception, ...]
        if expr.catchHandler is not None:
            self.setCurrentBlock(catchBlock)
            self.visitAstPartialFunctionExpression(expr.catchHandler, mode,
                                                   getExceptionClassType(),
                                                   successBlock, failBlock)

        if expr.finallyHandler is not None:
            # Compile the finally handler if there is one. Before entering this block, a
            # nullable pointer to the exception should be pushed. If the pointer is non-null,
            # the exception will be rethrown; otherwise, execution will continue normally.
            # Stack at this point: [exception, ...]
            self.setCurrentBlock(failBlock)
            if mode is COMPILE_FOR_VALUE:
                self.uninitialized()
            self.swap()
            self.branch(finallyBlock.id)

            # Stack at this point: [result, ...]
            self.setCurrentBlock(successBlock)
            self.null()
            self.branch(finallyBlock.id)

            # Stack at this point: [exception, result, ...]
            self.setCurrentBlock(finallyBlock)
            self.visit(expr.finallyHandler, COMPILE_FOR_EFFECT)
            exnTy = ClassType(getExceptionClass(), (), NULLABLE_TYPE_FLAG)
            self.dup()
            self.null()
            self.eqp()
            self.branchif(doneBlock.id, rethrowBlock.id)

            # Stack at this point: [exception, dummy-result, ...]
            self.setCurrentBlock(rethrowBlock)
            self.throw()

            # Stack at this point: [exception, result, ...]
            self.setCurrentBlock(doneBlock)
            self.drop()

        else:
            # If there is no finally handler, our lives are much easier.
            # Stack at this point: [exception, ...]
            self.setCurrentBlock(rethrowBlock)
            self.throw()

            # Stack at this point: [result, ...]
            self.setCurrentBlock(doneBlock)