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 {
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) {

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]
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 | }

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
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

View File

@ -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())
}

View File

@ -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
}
}

View File

@ -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

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{}
for s in text_expr {

View File

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