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
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))
def getExceptionClassType(): return ClassType(builtins.getExceptionClass())
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)
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)
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
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)