diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 5687d45933..903d76fe76 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -2445,26 +2445,15 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) { if is_decl { left_type = c.table.mktyp(right_type) if left_type == table.int_type { - mut expr := right - mut negative := false - if right is ast.PrefixExpr { - expr = right.right - if right.op == .minus { - negative = true - } - } - if mut expr is ast.IntegerLiteral { - mut is_large := false - if expr.val.len > 8 { - val := expr.val.i64() - if (!negative && val > checker.int_max) - || (negative && -val < checker.int_min) { - is_large = true - } + if right is ast.IntegerLiteral { + mut is_large := right.val.len > 13 + if !is_large && right.val.len > 8 { + val := right.val.i64() + is_large = val > checker.int_max || val < checker.int_min } if is_large { c.error('overflow in implicit type `int`, use explicit type casting instead', - expr.pos) + right.pos) } } } @@ -4886,12 +4875,9 @@ fn (mut c Checker) check_index(typ_sym &table.TypeSymbol, index ast.Expr, index_ } c.error('$type_str', pos) } - if index is ast.PrefixExpr { - if index.op == .minus && index.right is ast.IntegerLiteral { - val := (index.right as ast.IntegerLiteral).val - if val.int() > 0 { - c.error('invalid index `-$val` (index must be non-negative)', index.pos) - } + if index is ast.IntegerLiteral { + if index.val.starts_with('-') { + c.error('invalid index `$index.val` (index must be non-negative)', index.pos) } } if index_type.has_flag(.optional) { diff --git a/vlib/v/checker/tests/index_expr.out b/vlib/v/checker/tests/index_expr.out index 7a28dc8c00..e6594088c0 100644 --- a/vlib/v/checker/tests/index_expr.out +++ b/vlib/v/checker/tests/index_expr.out @@ -16,7 +16,7 @@ vlib/v/checker/tests/index_expr.vv:7:8: error: invalid index `-1` (index must be 5 | a := [2] 6 | _ = a[a] 7 | _ = a[-1] - | ^ + | ~~ 8 | } 9 | vlib/v/checker/tests/index_expr.vv:12:7: error: type `int` does not support indexing @@ -51,19 +51,19 @@ vlib/v/checker/tests/index_expr.vv:18:8: error: invalid index `-1` (index must b 16 | _ = a[a..] 17 | _ = a[..a] 18 | _ = a[-1..] - | ^ + | ~~ 19 | _ = a[..-1] 20 | _ = a[-1..-2] vlib/v/checker/tests/index_expr.vv:19:10: error: invalid index `-1` (index must be non-negative) 17 | _ = a[..a] 18 | _ = a[-1..] 19 | _ = a[..-1] - | ^ + | ~~ 20 | _ = a[-1..-2] 21 | } vlib/v/checker/tests/index_expr.vv:20:8: error: invalid index `-1` (index must be non-negative) 18 | _ = a[-1..] 19 | _ = a[..-1] 20 | _ = a[-1..-2] - | ^ + | ~~ 21 | } diff --git a/vlib/v/checker/tests/overflow_int_err.out b/vlib/v/checker/tests/overflow_int_err.out index 258aba5fe3..b26b09743d 100644 --- a/vlib/v/checker/tests/overflow_int_err.out +++ b/vlib/v/checker/tests/overflow_int_err.out @@ -1,8 +1,8 @@ -vlib/v/checker/tests/overflow_int_err.vv:4:8: error: overflow in implicit type `int`, use explicit type casting instead +vlib/v/checker/tests/overflow_int_err.vv:4:7: error: overflow in implicit type `int`, use explicit type casting instead 2 | a := -2147483648 3 | b := 2147483647 4 | c := -2147483649 - | ~~~~~~~~~~ + | ~~~~~~~~~~~ 5 | d := 2147483648 6 | println(a) vlib/v/checker/tests/overflow_int_err.vv:5:7: error: overflow in implicit type `int`, use explicit type casting instead diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index c43caf9170..9dd72c5470 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -2612,9 +2612,12 @@ fn (mut g Gen) expr(node ast.Expr) { } g.write('(${cast_label}(') g.expr(node.expr) - if node.expr is ast.IntegerLiteral - && node.typ in [table.u64_type, table.u32_type, table.u16_type] { - g.write('U') + if node.expr is ast.IntegerLiteral { + if node.typ in [table.u64_type, table.u32_type, table.u16_type] { + if !node.expr.val.starts_with('-') { + g.write('U') + } + } } g.write('))') } @@ -2691,6 +2694,9 @@ fn (mut g Gen) expr(node ast.Expr) { if node.val.starts_with('0o') { g.write('0') g.write(node.val[2..]) + } else if node.val.starts_with('-0o') { + g.write('-0') + g.write(node.val[3..]) } else { g.write(node.val) // .int().str()) } diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index e8cbcfe2c0..58e037f482 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -1726,17 +1726,23 @@ fn (mut p Parser) string_expr() ast.Expr { } fn (mut p Parser) parse_number_literal() ast.Expr { + mut pos := p.tok.position() + is_neg := p.tok.kind == .minus + if is_neg { + p.next() + pos = pos.extend(p.tok.position()) + } lit := p.tok.lit - pos := p.tok.position() + full_lit := if is_neg { '-' + lit } else { lit } mut node := ast.Expr{} if lit.index_any('.eE') >= 0 && lit[..2] !in ['0x', '0X', '0o', '0O', '0b', '0B'] { node = ast.FloatLiteral{ - val: lit + val: full_lit pos: pos } } else { node = ast.IntegerLiteral{ - val: lit + val: full_lit pos: pos } } diff --git a/vlib/v/parser/pratt.v b/vlib/v/parser/pratt.v index 05a8312f5b..2df9ad22f4 100644 --- a/vlib/v/parser/pratt.v +++ b/vlib/v/parser/pratt.v @@ -74,10 +74,17 @@ pub fn (mut p Parser) expr(precedence int) ast.Expr { } p.next() } - .minus, .amp, .mul, .not, .bit_not, .arrow { + .amp, .mul, .not, .bit_not, .arrow { // -1, -a, !x, &x, ~x, <-a node = p.prefix_expr() } + .minus { + if p.peek_tok.kind == .number { + node = p.parse_number_literal() + } else { + node = p.prefix_expr() + } + } .key_true, .key_false { node = ast.BoolLiteral{ val: p.tok.kind == .key_true diff --git a/vlib/v/parser/v_parser_test.v b/vlib/v/parser/v_parser_test.v index 3e82438c79..e2844a64aa 100644 --- a/vlib/v/parser/v_parser_test.v +++ b/vlib/v/parser/v_parser_test.v @@ -175,6 +175,48 @@ fn test_parse_expr() { } } +fn test_num_literals() { + inputs := [ + 'a := -1', + 'b := -12.e17' + 'c := -12.' + 'd := -a' + ] + table := table.new_table() + mut scope := &ast.Scope{ + start_pos: 0 + parent: 0 + } + mut rhs_types := []string{} + for input in inputs { + stmt := parser.parse_stmt(input, table, scope) + r := (stmt as ast.AssignStmt).right + match r[0] { + ast.IntegerLiteral { + rhs_types << 'int literal' + } + ast.FloatLiteral { + rhs_types << 'float literal' + } + ast.PrefixExpr { + rhs_types << 'prefix expression' + } + else { + rhs_types << 'something else' + } + } + } + mut rhs_type := rhs_types[0] + assert rhs_type == 'int literal' + rhs_type = rhs_types[1] + assert rhs_type == 'float literal' + rhs_type = rhs_types[2] + assert rhs_type == 'float literal' + rhs_type = rhs_types[3] + assert rhs_type == 'prefix expression' +} + + /* table := &table.Table{} for s in text_expr { diff --git a/vlib/v/tests/array_map_or_test.v b/vlib/v/tests/array_map_or_test.v index a7f60f0ebe..f7c73eaae9 100644 --- a/vlib/v/tests/array_map_or_test.v +++ b/vlib/v/tests/array_map_or_test.v @@ -94,7 +94,7 @@ fn test_propagation() { 17 } n := get_arr_el_direct(0) or { - int(-73) + -73 } assert testvar1 == -34 assert testvar2 == 99