parser: parse `-1` and `-13.3` as number literals (#8321)

pull/8329/head
Uwe Krüger 2021-01-24 22:09:51 +01:00 committed by GitHub
parent 997f56a3dc
commit 815104e5d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 84 additions and 37 deletions

View File

@ -2445,26 +2445,15 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
if is_decl { if is_decl {
left_type = c.table.mktyp(right_type) left_type = c.table.mktyp(right_type)
if left_type == table.int_type { if left_type == table.int_type {
mut expr := right if right is ast.IntegerLiteral {
mut negative := false mut is_large := right.val.len > 13
if right is ast.PrefixExpr { if !is_large && right.val.len > 8 {
expr = right.right val := right.val.i64()
if right.op == .minus { is_large = val > checker.int_max || val < checker.int_min
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 is_large { if is_large {
c.error('overflow in implicit type `int`, use explicit type casting instead', 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) c.error('$type_str', pos)
} }
if index is ast.PrefixExpr { if index is ast.IntegerLiteral {
if index.op == .minus && index.right is ast.IntegerLiteral { if index.val.starts_with('-') {
val := (index.right as ast.IntegerLiteral).val c.error('invalid index `$index.val` (index must be non-negative)', index.pos)
if val.int() > 0 {
c.error('invalid index `-$val` (index must be non-negative)', index.pos)
}
} }
} }
if index_type.has_flag(.optional) { if index_type.has_flag(.optional) {

View File

@ -16,7 +16,7 @@ vlib/v/checker/tests/index_expr.vv:7:8: error: invalid index `-1` (index must be
5 | a := [2] 5 | a := [2]
6 | _ = a[a] 6 | _ = a[a]
7 | _ = a[-1] 7 | _ = a[-1]
| ^ | ~~
8 | } 8 | }
9 | 9 |
vlib/v/checker/tests/index_expr.vv:12:7: error: type `int` does not support indexing 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..] 16 | _ = a[a..]
17 | _ = a[..a] 17 | _ = a[..a]
18 | _ = a[-1..] 18 | _ = a[-1..]
| ^ | ~~
19 | _ = a[..-1] 19 | _ = a[..-1]
20 | _ = a[-1..-2] 20 | _ = a[-1..-2]
vlib/v/checker/tests/index_expr.vv:19:10: error: invalid index `-1` (index must be non-negative) vlib/v/checker/tests/index_expr.vv:19:10: error: invalid index `-1` (index must be non-negative)
17 | _ = a[..a] 17 | _ = a[..a]
18 | _ = a[-1..] 18 | _ = a[-1..]
19 | _ = a[..-1] 19 | _ = a[..-1]
| ^ | ~~
20 | _ = a[-1..-2] 20 | _ = a[-1..-2]
21 | } 21 | }
vlib/v/checker/tests/index_expr.vv:20:8: error: invalid index `-1` (index must be non-negative) vlib/v/checker/tests/index_expr.vv:20:8: error: invalid index `-1` (index must be non-negative)
18 | _ = a[-1..] 18 | _ = a[-1..]
19 | _ = a[..-1] 19 | _ = a[..-1]
20 | _ = a[-1..-2] 20 | _ = a[-1..-2]
| ^ | ~~
21 | } 21 | }

View File

@ -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 2 | a := -2147483648
3 | b := 2147483647 3 | b := 2147483647
4 | c := -2147483649 4 | c := -2147483649
| ~~~~~~~~~~ | ~~~~~~~~~~~
5 | d := 2147483648 5 | d := 2147483648
6 | println(a) 6 | println(a)
vlib/v/checker/tests/overflow_int_err.vv:5:7: error: overflow in implicit type `int`, use explicit type casting instead vlib/v/checker/tests/overflow_int_err.vv:5:7: error: overflow in implicit type `int`, use explicit type casting instead

View File

@ -2612,9 +2612,12 @@ fn (mut g Gen) expr(node ast.Expr) {
} }
g.write('(${cast_label}(') g.write('(${cast_label}(')
g.expr(node.expr) g.expr(node.expr)
if node.expr is ast.IntegerLiteral if node.expr is ast.IntegerLiteral {
&& node.typ in [table.u64_type, table.u32_type, table.u16_type] { if node.typ in [table.u64_type, table.u32_type, table.u16_type] {
g.write('U') if !node.expr.val.starts_with('-') {
g.write('U')
}
}
} }
g.write('))') g.write('))')
} }
@ -2691,6 +2694,9 @@ fn (mut g Gen) expr(node ast.Expr) {
if node.val.starts_with('0o') { if node.val.starts_with('0o') {
g.write('0') g.write('0')
g.write(node.val[2..]) g.write(node.val[2..])
} else if node.val.starts_with('-0o') {
g.write('-0')
g.write(node.val[3..])
} else { } else {
g.write(node.val) // .int().str()) g.write(node.val) // .int().str())
} }

View File

@ -1726,17 +1726,23 @@ fn (mut p Parser) string_expr() ast.Expr {
} }
fn (mut p Parser) parse_number_literal() 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 lit := p.tok.lit
pos := p.tok.position() full_lit := if is_neg { '-' + lit } else { lit }
mut node := ast.Expr{} mut node := ast.Expr{}
if lit.index_any('.eE') >= 0 && lit[..2] !in ['0x', '0X', '0o', '0O', '0b', '0B'] { if lit.index_any('.eE') >= 0 && lit[..2] !in ['0x', '0X', '0o', '0O', '0b', '0B'] {
node = ast.FloatLiteral{ node = ast.FloatLiteral{
val: lit val: full_lit
pos: pos pos: pos
} }
} else { } else {
node = ast.IntegerLiteral{ node = ast.IntegerLiteral{
val: lit val: full_lit
pos: pos pos: pos
} }
} }

View File

@ -74,10 +74,17 @@ pub fn (mut p Parser) expr(precedence int) ast.Expr {
} }
p.next() p.next()
} }
.minus, .amp, .mul, .not, .bit_not, .arrow { .amp, .mul, .not, .bit_not, .arrow {
// -1, -a, !x, &x, ~x, <-a // -1, -a, !x, &x, ~x, <-a
node = p.prefix_expr() 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 { .key_true, .key_false {
node = ast.BoolLiteral{ node = ast.BoolLiteral{
val: p.tok.kind == .key_true val: p.tok.kind == .key_true

View File

@ -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{} table := &table.Table{}
for s in text_expr { for s in text_expr {

View File

@ -94,7 +94,7 @@ fn test_propagation() {
17 17
} }
n := get_arr_el_direct(0) or { n := get_arr_el_direct(0) or {
int(-73) -73
} }
assert testvar1 == -34 assert testvar1 == -34
assert testvar2 == 99 assert testvar2 == 99