forked from M-Labs/artiq
Add support for exceptions.
This commit is contained in:
parent
a4a9cd884e
commit
f430bf3f63
|
@ -33,6 +33,10 @@ class FunctionDefT(ast.FunctionDef, scoped):
|
||||||
class ModuleT(ast.Module, scoped):
|
class ModuleT(ast.Module, scoped):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
class ExceptHandlerT(ast.ExceptHandler, commontyped):
|
||||||
|
_fields = ("filter", "name", "body") # rename ast.ExceptHandler.type
|
||||||
|
_types = ("name_type",)
|
||||||
|
|
||||||
class AttributeT(ast.Attribute, commontyped):
|
class AttributeT(ast.Attribute, commontyped):
|
||||||
pass
|
pass
|
||||||
class BinOpT(ast.BinOp, commontyped):
|
class BinOpT(ast.BinOp, commontyped):
|
||||||
|
|
|
@ -125,7 +125,7 @@ def is_builtin(typ, name):
|
||||||
return isinstance(typ, types.TBuiltin) and \
|
return isinstance(typ, types.TBuiltin) and \
|
||||||
typ.name == name
|
typ.name == name
|
||||||
|
|
||||||
def is_exception(typ, name=None):
|
def is_exn_constructor(typ, name=None):
|
||||||
typ = typ.find()
|
typ = typ.find()
|
||||||
if name is not None:
|
if name is not None:
|
||||||
return isinstance(typ, types.TExceptionConstructor) and \
|
return isinstance(typ, types.TExceptionConstructor) and \
|
||||||
|
|
|
@ -227,6 +227,9 @@ class TExceptionConstructor(TBuiltin):
|
||||||
Note that this is not the same as the type of an instance of
|
Note that this is not the same as the type of an instance of
|
||||||
the class, which is ``TMono("Exception", ...)``.
|
the class, which is ``TMono("Exception", ...)``.
|
||||||
"""
|
"""
|
||||||
|
def to_exception_type(self):
|
||||||
|
# Exceptions currently can't have type parameters
|
||||||
|
return TMono(self.name, {})
|
||||||
|
|
||||||
class TValue(Type):
|
class TValue(Type):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -328,6 +328,15 @@ class ASTTypedRewriter(algorithm.Transformer):
|
||||||
finally:
|
finally:
|
||||||
self.env_stack.pop()
|
self.env_stack.pop()
|
||||||
|
|
||||||
|
def visit_ExceptHandler(self, node):
|
||||||
|
node = self.generic_visit(node)
|
||||||
|
node = asttyped.ExceptHandlerT(
|
||||||
|
name_type=self._find_name(node.name, node.name_loc),
|
||||||
|
filter=node.type, name=node.name, body=node.body,
|
||||||
|
except_loc=node.except_loc, as_loc=node.as_loc, name_loc=node.name_loc,
|
||||||
|
colon_loc=node.colon_loc, loc=node.loc)
|
||||||
|
return node
|
||||||
|
|
||||||
def visit_Raise(self, node):
|
def visit_Raise(self, node):
|
||||||
node = self.generic_visit(node)
|
node = self.generic_visit(node)
|
||||||
if node.cause:
|
if node.cause:
|
||||||
|
@ -363,7 +372,6 @@ class ASTTypedRewriter(algorithm.Transformer):
|
||||||
visit_Delete = visit_unsupported
|
visit_Delete = visit_unsupported
|
||||||
visit_Import = visit_unsupported
|
visit_Import = visit_unsupported
|
||||||
visit_ImportFrom = visit_unsupported
|
visit_ImportFrom = visit_unsupported
|
||||||
visit_Try = visit_unsupported
|
|
||||||
|
|
||||||
|
|
||||||
class Inferencer(algorithm.Visitor):
|
class Inferencer(algorithm.Visitor):
|
||||||
|
@ -1070,6 +1078,30 @@ class Inferencer(algorithm.Visitor):
|
||||||
node.context_expr.loc)
|
node.context_expr.loc)
|
||||||
self.engine.process(diag)
|
self.engine.process(diag)
|
||||||
|
|
||||||
|
def visit_ExceptHandlerT(self, node):
|
||||||
|
self.generic_visit(node)
|
||||||
|
|
||||||
|
if not builtins.is_exn_constructor(node.filter.type):
|
||||||
|
diag = diagnostic.Diagnostic("error",
|
||||||
|
"this expression must refer to an exception constructor",
|
||||||
|
{"type": types.TypePrinter().name(node.filter.type)},
|
||||||
|
node.filter.loc)
|
||||||
|
self.engine.process(diag)
|
||||||
|
else:
|
||||||
|
def makenotes(printer, typea, typeb, loca, locb):
|
||||||
|
return [
|
||||||
|
diagnostic.Diagnostic("note",
|
||||||
|
"expression of type {typea}",
|
||||||
|
{"typea": printer.name(typea)},
|
||||||
|
loca),
|
||||||
|
diagnostic.Diagnostic("note",
|
||||||
|
"constructor of an exception of type {typeb}",
|
||||||
|
{"typeb": printer.name(typeb)},
|
||||||
|
locb)
|
||||||
|
]
|
||||||
|
self._unify(node.name_type, node.filter.type.to_exception_type(),
|
||||||
|
node.name_loc, node.filter.loc, makenotes)
|
||||||
|
|
||||||
def _type_from_arguments(self, node, ret):
|
def _type_from_arguments(self, node, ret):
|
||||||
self.generic_visit(node)
|
self.generic_visit(node)
|
||||||
|
|
||||||
|
@ -1166,6 +1198,13 @@ class Printer(algorithm.Visitor):
|
||||||
self.rewriter.insert_before(node.colon_loc,
|
self.rewriter.insert_before(node.colon_loc,
|
||||||
"->{}".format(self.type_printer.name(node.return_type)))
|
"->{}".format(self.type_printer.name(node.return_type)))
|
||||||
|
|
||||||
|
def visit_ExceptHandlerT(self, node):
|
||||||
|
super().generic_visit(node)
|
||||||
|
|
||||||
|
if node.name_loc:
|
||||||
|
self.rewriter.insert_after(node.name_loc,
|
||||||
|
":{}".format(self.type_printer.name(node.name_type)))
|
||||||
|
|
||||||
def generic_visit(self, node):
|
def generic_visit(self, node):
|
||||||
super().generic_visit(node)
|
super().generic_visit(node)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
# RUN: %python -m artiq.py2llvm.typing +diag %s >%t
|
||||||
|
# RUN: OutputCheck %s --file-to-check=%t
|
||||||
|
|
||||||
|
try:
|
||||||
|
pass
|
||||||
|
# CHECK-L: ${LINE:+1}: error: this expression must refer to an exception constructor
|
||||||
|
except 1:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
pass
|
||||||
|
# CHECK-L: ${LINE:+1}: error: cannot unify int(width='a) with Exception
|
||||||
|
except Exception as e:
|
||||||
|
e = 1
|
|
@ -3,3 +3,11 @@
|
||||||
|
|
||||||
# CHECK-L: Exception:<constructor Exception>
|
# CHECK-L: Exception:<constructor Exception>
|
||||||
Exception
|
Exception
|
||||||
|
|
||||||
|
try:
|
||||||
|
pass
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
except Exception as e:
|
||||||
|
# CHECK-L: e:Exception
|
||||||
|
e
|
||||||
|
|
Loading…
Reference in New Issue