diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index ccd3c978d4..692469b125 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -547,14 +547,6 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type { } } } - if infix_expr.op in [.div, .mod] { - if (infix_expr.right is ast.IntegerLiteral && - infix_expr.right.str() == '0') || - (infix_expr.right is ast.FloatLiteral && infix_expr.right.str().f64() == 0.0) { - oper := if infix_expr.op == .div { 'division' } else { 'modulo' } - c.error('$oper by zero', right_pos) - } - } return_type = promoted_type } } diff --git a/vlib/v/parser/pratt.v b/vlib/v/parser/pratt.v index 870b1758e1..a8cd9ad715 100644 --- a/vlib/v/parser/pratt.v +++ b/vlib/v/parser/pratt.v @@ -239,6 +239,28 @@ fn (mut p Parser) infix_expr(left ast.Expr) ast.Expr { p.expecting_type = true } right = p.expr(precedence) + + if op in [.div, .mod] { + oper := if op == .div { 'division' } else { 'modulo' } + match right { + ast.FloatLiteral { + if it.val.f64() == 0.0 { + p.error_with_pos('$oper by zero', right.pos) + } + } + ast.Ident { + if p.is_var_zero(right.name) { + p.error_with_pos('$oper by zero', right.pos) + } + } + ast.IntegerLiteral { + if it.val.int() == 0 { + p.error_with_pos('$oper by zero', right.pos) + } + } + else {} + } + } return ast.InfixExpr{ left: left right: right @@ -247,6 +269,26 @@ fn (mut p Parser) infix_expr(left ast.Expr) ast.Expr { } } +fn (mut p Parser) is_var_zero(name string) bool { + var := p.scope.find_var(name) or { + return false + } + match var.expr { + ast.FloatLiteral { + if it.val.f64() == 0.0 { + return true + } + } + ast.IntegerLiteral { + if it.val.int() == 0 { + return true + } + } + else {} + } + return false +} + fn (mut p Parser) prefix_expr() ast.PrefixExpr { pos := p.tok.position() op := p.tok.kind diff --git a/vlib/v/parser/tests/division_by_zero_0b0_err.out b/vlib/v/parser/tests/division_by_zero_0b0_err.out new file mode 100644 index 0000000000..bd43770085 --- /dev/null +++ b/vlib/v/parser/tests/division_by_zero_0b0_err.out @@ -0,0 +1,5 @@ +vlib/v/parser/tests/division_by_zero_0b0_err.v:2:12: error: division by zero + 1 | fn main() { + 2 | println(1/0b0) + | ~~~ + 3 | } diff --git a/vlib/v/parser/tests/division_by_zero_0b0_err.vv b/vlib/v/parser/tests/division_by_zero_0b0_err.vv new file mode 100644 index 0000000000..1f8ece86d4 --- /dev/null +++ b/vlib/v/parser/tests/division_by_zero_0b0_err.vv @@ -0,0 +1,3 @@ +fn main() { + println(1/0b0) +} diff --git a/vlib/v/parser/tests/division_by_zero_0x0_err.out b/vlib/v/parser/tests/division_by_zero_0x0_err.out new file mode 100644 index 0000000000..4cfc8d1342 --- /dev/null +++ b/vlib/v/parser/tests/division_by_zero_0x0_err.out @@ -0,0 +1,5 @@ +vlib/v/parser/tests/division_by_zero_0x0_err.v:2:12: error: division by zero + 1 | fn main() { + 2 | println(1/0x0) + | ~~~ + 3 | } diff --git a/vlib/v/parser/tests/division_by_zero_0x0_err.vv b/vlib/v/parser/tests/division_by_zero_0x0_err.vv new file mode 100644 index 0000000000..812eb2cbe9 --- /dev/null +++ b/vlib/v/parser/tests/division_by_zero_0x0_err.vv @@ -0,0 +1,3 @@ +fn main() { + println(1/0x0) +} diff --git a/vlib/v/parser/tests/division_by_zero_0x0_var_err.out b/vlib/v/parser/tests/division_by_zero_0x0_var_err.out new file mode 100644 index 0000000000..ebee0a7632 --- /dev/null +++ b/vlib/v/parser/tests/division_by_zero_0x0_var_err.out @@ -0,0 +1,6 @@ +vlib/v/parser/tests/division_by_zero_0x0_var_err.v:3:12: error: division by zero + 1 | fn main() { + 2 | a := 0x0 + 3 | println(1/a) + | ^ + 4 | } diff --git a/vlib/v/parser/tests/division_by_zero_0x0_var_err.vv b/vlib/v/parser/tests/division_by_zero_0x0_var_err.vv new file mode 100644 index 0000000000..c7c3066f7d --- /dev/null +++ b/vlib/v/parser/tests/division_by_zero_0x0_var_err.vv @@ -0,0 +1,4 @@ +fn main() { + a := 0x0 + println(1/a) +} diff --git a/vlib/v/checker/tests/division_by_zero_float_err.out b/vlib/v/parser/tests/division_by_zero_float_err.out similarity index 52% rename from vlib/v/checker/tests/division_by_zero_float_err.out rename to vlib/v/parser/tests/division_by_zero_float_err.out index f7b7609eff..c59a1032c3 100644 --- a/vlib/v/checker/tests/division_by_zero_float_err.out +++ b/vlib/v/parser/tests/division_by_zero_float_err.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/division_by_zero_float_err.v:2:14: error: division by zero +vlib/v/parser/tests/division_by_zero_float_err.v:2:14: error: division by zero 1 | fn main() { 2 | println(1.0/0.0) | ~~~ diff --git a/vlib/v/checker/tests/division_by_zero_float_err.vv b/vlib/v/parser/tests/division_by_zero_float_err.vv similarity index 100% rename from vlib/v/checker/tests/division_by_zero_float_err.vv rename to vlib/v/parser/tests/division_by_zero_float_err.vv diff --git a/vlib/v/parser/tests/division_by_zero_float_var_err.out b/vlib/v/parser/tests/division_by_zero_float_var_err.out new file mode 100644 index 0000000000..4a4dbcdc0d --- /dev/null +++ b/vlib/v/parser/tests/division_by_zero_float_var_err.out @@ -0,0 +1,6 @@ +vlib/v/parser/tests/division_by_zero_float_var_err.v:3:14: error: division by zero + 1 | fn main() { + 2 | a := 0.0 + 3 | println(1.0/a) + | ^ + 4 | } diff --git a/vlib/v/parser/tests/division_by_zero_float_var_err.vv b/vlib/v/parser/tests/division_by_zero_float_var_err.vv new file mode 100644 index 0000000000..612e0df040 --- /dev/null +++ b/vlib/v/parser/tests/division_by_zero_float_var_err.vv @@ -0,0 +1,4 @@ +fn main() { + a := 0.0 + println(1.0/a) +} diff --git a/vlib/v/checker/tests/division_by_zero_int_err.out b/vlib/v/parser/tests/division_by_zero_int_err.out similarity index 50% rename from vlib/v/checker/tests/division_by_zero_int_err.out rename to vlib/v/parser/tests/division_by_zero_int_err.out index 3e00c2c739..a7af55da33 100644 --- a/vlib/v/checker/tests/division_by_zero_int_err.out +++ b/vlib/v/parser/tests/division_by_zero_int_err.out @@ -1,4 +1,4 @@ -vlib/v/checker/tests/division_by_zero_int_err.v:2:12: error: division by zero +vlib/v/parser/tests/division_by_zero_int_err.v:2:12: error: division by zero 1 | fn main() { 2 | println(1/0) | ^ diff --git a/vlib/v/checker/tests/division_by_zero_int_err.vv b/vlib/v/parser/tests/division_by_zero_int_err.vv similarity index 100% rename from vlib/v/checker/tests/division_by_zero_int_err.vv rename to vlib/v/parser/tests/division_by_zero_int_err.vv diff --git a/vlib/v/parser/tests/division_by_zero_int_var_err.out b/vlib/v/parser/tests/division_by_zero_int_var_err.out new file mode 100644 index 0000000000..0a4ccaebf5 --- /dev/null +++ b/vlib/v/parser/tests/division_by_zero_int_var_err.out @@ -0,0 +1,6 @@ +vlib/v/parser/tests/division_by_zero_int_var_err.v:3:12: error: division by zero + 1 | fn main() { + 2 | a := 0 + 3 | println(1/a) + | ^ + 4 | } diff --git a/vlib/v/parser/tests/division_by_zero_int_var_err.vv b/vlib/v/parser/tests/division_by_zero_int_var_err.vv new file mode 100644 index 0000000000..bcf6bec0b6 --- /dev/null +++ b/vlib/v/parser/tests/division_by_zero_int_var_err.vv @@ -0,0 +1,4 @@ +fn main() { + a := 0 + println(1/a) +}