diff --git a/artiq/compiler/builtins.py b/artiq/compiler/builtins.py index dde80af12..73035600d 100644 --- a/artiq/compiler/builtins.py +++ b/artiq/compiler/builtins.py @@ -83,6 +83,10 @@ class TValueError(TException): def __init__(self): super().__init__("ValueError") +class TZeroDivisionError(TException): + def __init__(self): + super().__init__("ZeroDivisionError") + def fn_bool(): return types.TConstructor("bool") @@ -107,6 +111,9 @@ def fn_IndexError(): def fn_ValueError(): return types.TExceptionConstructor("ValueError") +def fn_ZeroDivisionError(): + return types.TExceptionConstructor("ZeroDivisionError") + def fn_range(): return types.TBuiltinFunction("range") diff --git a/artiq/compiler/prelude.py b/artiq/compiler/prelude.py index bed44af6c..600b7a800 100644 --- a/artiq/compiler/prelude.py +++ b/artiq/compiler/prelude.py @@ -7,16 +7,17 @@ from . import builtins def globals(): return { - "bool": builtins.fn_bool(), - "int": builtins.fn_int(), - "float": builtins.fn_float(), - "list": builtins.fn_list(), - "range": builtins.fn_range(), - "Exception": builtins.fn_Exception(), - "IndexError": builtins.fn_IndexError(), - "ValueError": builtins.fn_ValueError(), - "len": builtins.fn_len(), - "round": builtins.fn_round(), - "print": builtins.fn_print(), - "syscall": builtins.fn_syscall(), + "bool": builtins.fn_bool(), + "int": builtins.fn_int(), + "float": builtins.fn_float(), + "list": builtins.fn_list(), + "range": builtins.fn_range(), + "Exception": builtins.fn_Exception(), + "IndexError": builtins.fn_IndexError(), + "ValueError": builtins.fn_ValueError(), + "ZeroDivisionError": builtins.fn_ZeroDivisionError(), + "len": builtins.fn_len(), + "round": builtins.fn_round(), + "print": builtins.fn_print(), + "syscall": builtins.fn_syscall(), } diff --git a/artiq/compiler/transforms/artiq_ir_generator.py b/artiq/compiler/transforms/artiq_ir_generator.py index 502ad651a..1c49508e2 100644 --- a/artiq/compiler/transforms/artiq_ir_generator.py +++ b/artiq/compiler/transforms/artiq_ir_generator.py @@ -899,13 +899,16 @@ class ARTIQIRGenerator(algorithm.Visitor): def visit_BinOpT(self, node): if builtins.is_numeric(node.type): - # TODO: check for division by zero rhs = self.visit(node.right) if isinstance(node.op, (ast.LShift, ast.RShift)): # Check for negative shift amount. self._make_check(self.append(ir.Compare(ast.GtE(loc=None), rhs, ir.Constant(0, rhs.type))), lambda: self.append(ir.Alloc([], builtins.TValueError()))) + elif isinstance(node.op, (ast.Div, ast.FloorDiv)): + self._make_check(self.append(ir.Compare(ast.NotEq(loc=None), rhs, + ir.Constant(0, rhs.type))), + lambda: self.append(ir.Alloc([], builtins.TZeroDivisionError()))) return self.append(ir.Arith(node.op, self.visit(node.left), rhs)) elif isinstance(node.op, ast.Add): # list + list, tuple + tuple