checker: more infix checks
							parent
							
								
									07f69fab19
								
							
						
					
					
						commit
						717e26b45e
					
				| 
						 | 
					@ -48,6 +48,7 @@ pub:
 | 
				
			||||||
pub struct FloatLiteral {
 | 
					pub struct FloatLiteral {
 | 
				
			||||||
pub:
 | 
					pub:
 | 
				
			||||||
	val string
 | 
						val string
 | 
				
			||||||
 | 
						pos token.Position
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub struct StringLiteral {
 | 
					pub struct StringLiteral {
 | 
				
			||||||
| 
						 | 
					@ -73,11 +74,13 @@ mut:
 | 
				
			||||||
pub struct CharLiteral {
 | 
					pub struct CharLiteral {
 | 
				
			||||||
pub:
 | 
					pub:
 | 
				
			||||||
	val string
 | 
						val string
 | 
				
			||||||
 | 
						pos token.Position
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub struct BoolLiteral {
 | 
					pub struct BoolLiteral {
 | 
				
			||||||
pub:
 | 
					pub:
 | 
				
			||||||
	val bool
 | 
						val bool
 | 
				
			||||||
 | 
						pos token.Position
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// `foo.bar`
 | 
					// `foo.bar`
 | 
				
			||||||
| 
						 | 
					@ -737,36 +740,20 @@ pub fn expr_is_call(expr Expr) bool {
 | 
				
			||||||
fn (expr Expr) position() token.Position {
 | 
					fn (expr Expr) position() token.Position {
 | 
				
			||||||
	// all uncommented have to be implemented
 | 
						// all uncommented have to be implemented
 | 
				
			||||||
	match var expr {
 | 
						match var expr {
 | 
				
			||||||
		ArrayInit {
 | 
							ArrayInit { return it.pos }
 | 
				
			||||||
			return it.pos
 | 
							AsCast { return it.pos }
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		AsCast {
 | 
					 | 
				
			||||||
			return it.pos
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		// ast.Ident { }
 | 
							// ast.Ident { }
 | 
				
			||||||
		AssignExpr {
 | 
							AssignExpr { return it.pos }
 | 
				
			||||||
			return it.pos
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		// ast.CastExpr { }
 | 
							// ast.CastExpr { }
 | 
				
			||||||
		Assoc {
 | 
							Assoc { return it.pos }
 | 
				
			||||||
			return it.pos
 | 
							BoolLiteral { return it.pos }
 | 
				
			||||||
		}
 | 
							CallExpr { return it.pos }
 | 
				
			||||||
		// ast.BoolLiteral { }
 | 
							CharLiteral { return it.pos }
 | 
				
			||||||
		CallExpr {
 | 
							EnumVal { return it.pos }
 | 
				
			||||||
			return it.pos
 | 
							FloatLiteral { return it.pos }
 | 
				
			||||||
		}
 | 
							IfExpr { return it.pos }
 | 
				
			||||||
		// ast.CharLiteral { }
 | 
					 | 
				
			||||||
		EnumVal {
 | 
					 | 
				
			||||||
			return it.pos
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		// ast.FloatLiteral { }
 | 
					 | 
				
			||||||
		IfExpr {
 | 
					 | 
				
			||||||
			return it.pos
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		// ast.IfGuardExpr { }
 | 
							// ast.IfGuardExpr { }
 | 
				
			||||||
		IndexExpr {
 | 
							IndexExpr { return it.pos }
 | 
				
			||||||
			return it.pos
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		InfixExpr {
 | 
							InfixExpr {
 | 
				
			||||||
			left_pos := it.left.position()
 | 
								left_pos := it.left.position()
 | 
				
			||||||
			right_pos := it.right.position()
 | 
								right_pos := it.right.position()
 | 
				
			||||||
| 
						 | 
					@ -779,40 +766,20 @@ fn (expr Expr) position() token.Position {
 | 
				
			||||||
				len: right_pos.pos - left_pos.pos + right_pos.len
 | 
									len: right_pos.pos - left_pos.pos + right_pos.len
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		IntegerLiteral {
 | 
							IntegerLiteral { return it.pos }
 | 
				
			||||||
			return it.pos
 | 
							MapInit { return it.pos }
 | 
				
			||||||
		}
 | 
							MatchExpr { return it.pos }
 | 
				
			||||||
		MapInit {
 | 
							PostfixExpr { return it.pos }
 | 
				
			||||||
			return it.pos
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		MatchExpr {
 | 
					 | 
				
			||||||
			return it.pos
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		PostfixExpr {
 | 
					 | 
				
			||||||
			return it.pos
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		// ast.None { }
 | 
							// ast.None { }
 | 
				
			||||||
		PrefixExpr {
 | 
							PrefixExpr { return it.pos }
 | 
				
			||||||
			return it.pos
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		// ast.ParExpr { }
 | 
							// ast.ParExpr { }
 | 
				
			||||||
		SelectorExpr {
 | 
							SelectorExpr { return it.pos }
 | 
				
			||||||
			return it.pos
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		// ast.SizeOf { }
 | 
							// ast.SizeOf { }
 | 
				
			||||||
		StringLiteral {
 | 
							StringLiteral { return it.pos }
 | 
				
			||||||
			return it.pos
 | 
							StringInterLiteral { return it.pos }
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		StringInterLiteral {
 | 
					 | 
				
			||||||
			return it.pos
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		// ast.Type { }
 | 
							// ast.Type { }
 | 
				
			||||||
		StructInit {
 | 
							StructInit { return it.pos }
 | 
				
			||||||
			return it.pos
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		// ast.TypeOf { }
 | 
							// ast.TypeOf { }
 | 
				
			||||||
		else {
 | 
							else { return token.Position{} }
 | 
				
			||||||
			return token.Position{}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -270,11 +270,6 @@ pub fn (c mut Checker) infix_expr(infix_expr mut ast.InfixExpr) table.Type {
 | 
				
			||||||
	right := c.table.get_type_symbol(right_type)
 | 
						right := c.table.get_type_symbol(right_type)
 | 
				
			||||||
	left := c.table.get_type_symbol(left_type)
 | 
						left := c.table.get_type_symbol(left_type)
 | 
				
			||||||
	if infix_expr.op == .left_shift {
 | 
						if infix_expr.op == .left_shift {
 | 
				
			||||||
		if left.kind != .array && !left.is_int() {
 | 
					 | 
				
			||||||
			// c.error('<< can only be used with numbers and arrays', infix_expr.pos)
 | 
					 | 
				
			||||||
			c.error('cannot shift type $right.name into $left.name', infix_expr.right.position())
 | 
					 | 
				
			||||||
			return table.void_type
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if left.kind == .array {
 | 
							if left.kind == .array {
 | 
				
			||||||
			// `array << elm`
 | 
								// `array << elm`
 | 
				
			||||||
			// the expressions have different types (array_x and x)
 | 
								// the expressions have different types (array_x and x)
 | 
				
			||||||
| 
						 | 
					@ -288,6 +283,12 @@ pub fn (c mut Checker) infix_expr(infix_expr mut ast.InfixExpr) table.Type {
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			c.error('cannot shift type $right.name into $left.name', infix_expr.right.position())
 | 
								c.error('cannot shift type $right.name into $left.name', infix_expr.right.position())
 | 
				
			||||||
			return table.void_type
 | 
								return table.void_type
 | 
				
			||||||
 | 
							} else if !left.is_int() {
 | 
				
			||||||
 | 
								c.error('cannot shift type $right.name into non-integer type $left.name', infix_expr.left.position())
 | 
				
			||||||
 | 
								return table.void_type
 | 
				
			||||||
 | 
							} else if !right.is_int() {
 | 
				
			||||||
 | 
								c.error('cannot shift non-integer type $right.name into type $left.name', infix_expr.right.position())
 | 
				
			||||||
 | 
								return table.void_type
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if infix_expr.op in [.key_in, .not_in] {
 | 
						if infix_expr.op in [.key_in, .not_in] {
 | 
				
			||||||
| 
						 | 
					@ -302,20 +303,19 @@ pub fn (c mut Checker) infix_expr(infix_expr mut ast.InfixExpr) table.Type {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return table.bool_type
 | 
							return table.bool_type
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if !c.table.check(right_type, left_type) {
 | 
					 | 
				
			||||||
		// for type-unresolved consts
 | 
					 | 
				
			||||||
		if left_type == table.void_type || right_type == table.void_type {
 | 
					 | 
				
			||||||
			return table.void_type
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		c.error('infix expr: cannot use `$right.name` (right expression) as `$left.name`',
 | 
					 | 
				
			||||||
			infix_expr.pos)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if infix_expr.op in [.amp, .pipe, .xor] {
 | 
						if infix_expr.op in [.amp, .pipe, .xor] {
 | 
				
			||||||
		if !left.is_int() {
 | 
							if !left.is_int() {
 | 
				
			||||||
			c.error('operator ${infix_expr.op.str()} not defined on left type `$left.name`', infix_expr.pos)
 | 
								c.error('left type of `${infix_expr.op.str()}` cannot be non-integer type $left.name', infix_expr.left.position())
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else if !right.is_int() {
 | 
							else if !right.is_int() {
 | 
				
			||||||
			c.error('operator ${infix_expr.op.str()} not defined on right type `$right.name`', infix_expr.pos)
 | 
								c.error('right type of `${infix_expr.op.str()}` cannot be non-integer type $right.name', infix_expr.right.position())
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if infix_expr.op == .mod {
 | 
				
			||||||
 | 
							if left.is_int() && !right.is_int() {
 | 
				
			||||||
 | 
								c.error('right type of `${infix_expr.op.str()}` cannot be non-integer type $right.name', infix_expr.right.position())
 | 
				
			||||||
 | 
							} else if !left.is_int() && right.is_int() {
 | 
				
			||||||
 | 
								c.error('left type of `${infix_expr.op.str()}` cannot be non-integer type $left.name', infix_expr.left.position())
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if left_type == table.bool_type && !(infix_expr.op in [.eq, .ne, .logical_or, .and]) {
 | 
						if left_type == table.bool_type && !(infix_expr.op in [.eq, .ne, .logical_or, .and]) {
 | 
				
			||||||
| 
						 | 
					@ -327,6 +327,13 @@ pub fn (c mut Checker) infix_expr(infix_expr mut ast.InfixExpr) table.Type {
 | 
				
			||||||
		c.error('string types only have the following operators defined: `==`, `!=`, `<`, `>`, `<=`, `>=`, and `&&`',
 | 
							c.error('string types only have the following operators defined: `==`, `!=`, `<`, `>`, `<=`, `>=`, and `&&`',
 | 
				
			||||||
			infix_expr.pos)
 | 
								infix_expr.pos)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if !c.table.check(right_type, left_type) {
 | 
				
			||||||
 | 
							// for type-unresolved consts
 | 
				
			||||||
 | 
							if left_type == table.void_type || right_type == table.void_type {
 | 
				
			||||||
 | 
								return table.void_type
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							c.error('infix expr: cannot use `$right.name` (right expression) as `$left.name`', infix_expr.pos)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	if infix_expr.op.is_relational() {
 | 
						if infix_expr.op.is_relational() {
 | 
				
			||||||
		return table.bool_type
 | 
							return table.bool_type
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,5 @@
 | 
				
			||||||
vlib/v/checker/tests/inout/bit_op_wrong_left_type_err.v:2:6: error: operator & not defined on left type `f64`
 | 
					vlib/v/checker/tests/inout/bit_op_wrong_left_type_err.v:2:2: error: left type of `&` cannot be non-integer type f64
 | 
				
			||||||
    1| fn main() {
 | 
					    1| fn main() {
 | 
				
			||||||
    2|     0.5 & 1
 | 
					    2|     0.5 & 1
 | 
				
			||||||
               ^
 | 
					           ~~~
 | 
				
			||||||
    3| }
 | 
					    3| }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,5 @@
 | 
				
			||||||
vlib/v/checker/tests/inout/bit_op_wrong_right_type_err.v:2:4: error: operator | not defined on right type `f64`
 | 
					vlib/v/checker/tests/inout/bit_op_wrong_right_type_err.v:2:6: error: right type of `|` cannot be non-integer type f64
 | 
				
			||||||
    1| fn main() {
 | 
					    1| fn main() {
 | 
				
			||||||
    2|     1 | 0.5
 | 
					    2|     1 | 0.5
 | 
				
			||||||
             ^
 | 
					               ~~~
 | 
				
			||||||
    3| }
 | 
					    3| }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,3 @@
 | 
				
			||||||
 | 
					fn main() {
 | 
				
			||||||
 | 
						1 | 0.5
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,5 @@
 | 
				
			||||||
 | 
					vlib/v/checker/tests/inout/mod_op_wrong_left_type_err.v:2:2: error: left type of `%` cannot be non-integer type f64
 | 
				
			||||||
 | 
					    1| fn main() {
 | 
				
			||||||
 | 
					    2|     0.5 % 1
 | 
				
			||||||
 | 
					           ~~~
 | 
				
			||||||
 | 
					    3| }
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,3 @@
 | 
				
			||||||
 | 
					fn main() {
 | 
				
			||||||
 | 
						0.5 % 1
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,5 @@
 | 
				
			||||||
 | 
					vlib/v/checker/tests/inout/mod_op_wrong_right_type_err.v:2:6: error: right type of `%` cannot be non-integer type f64
 | 
				
			||||||
 | 
					    1| fn main() {
 | 
				
			||||||
 | 
					    2|     1 % 0.5
 | 
				
			||||||
 | 
					               ~~~
 | 
				
			||||||
 | 
					    3| }
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,3 @@
 | 
				
			||||||
 | 
					fn main() {
 | 
				
			||||||
 | 
						1 % 0.5
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,5 @@
 | 
				
			||||||
 | 
					vlib/v/checker/tests/inout/shift_op_wrong_left_type_err.v:2:2: error: cannot shift type int into non-integer type f64
 | 
				
			||||||
 | 
					    1| fn main() {
 | 
				
			||||||
 | 
					    2|     0.5 << 1
 | 
				
			||||||
 | 
					           ~~~
 | 
				
			||||||
 | 
					    3| }
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,3 @@
 | 
				
			||||||
 | 
					fn main() {
 | 
				
			||||||
 | 
						0.5 << 1
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,5 @@
 | 
				
			||||||
 | 
					vlib/v/checker/tests/inout/shift_op_wrong_right_type_err.v:2:7: error: cannot shift non-integer type f64 into type int
 | 
				
			||||||
 | 
					    1| fn main() {
 | 
				
			||||||
 | 
					    2|     1 << 0.5
 | 
				
			||||||
 | 
					                ~~~
 | 
				
			||||||
 | 
					    3| }
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,3 @@
 | 
				
			||||||
 | 
					fn main() {
 | 
				
			||||||
 | 
						1 << 0.5
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,6 @@ vlib/v/checker/tests/inout/struct_unknown_field.v:8:9: error: unknown field `bar
 | 
				
			||||||
    6|     t := Test{
 | 
					    6|     t := Test{
 | 
				
			||||||
    7|         foo: true
 | 
					    7|         foo: true
 | 
				
			||||||
    8|         bar: false
 | 
					    8|         bar: false
 | 
				
			||||||
               ^
 | 
					               ~~~~~~~~~~
 | 
				
			||||||
    9|     }
 | 
					    9|     }
 | 
				
			||||||
   10| }
 | 
					   10| }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -875,6 +875,7 @@ fn (var p Parser) parse_number_literal() 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: lit
 | 
				
			||||||
 | 
								pos: pos
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		node = ast.IntegerLiteral{
 | 
							node = ast.IntegerLiteral{
 | 
				
			||||||
| 
						 | 
					@ -1210,10 +1211,10 @@ fn (var p Parser) assoc() ast.Assoc {
 | 
				
			||||||
fn (p &Parser) new_true_expr() ast.Expr {
 | 
					fn (p &Parser) new_true_expr() ast.Expr {
 | 
				
			||||||
	return ast.BoolLiteral{
 | 
						return ast.BoolLiteral{
 | 
				
			||||||
		val: true
 | 
							val: true
 | 
				
			||||||
 | 
							pos: p.tok.position()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn verror(s string) {
 | 
					fn verror(s string) {
 | 
				
			||||||
	util.verror('parser error', s)
 | 
						util.verror('parser error', s)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,6 +29,7 @@ pub fn (var p Parser) expr(precedence int) ast.Expr {
 | 
				
			||||||
		.chartoken {
 | 
							.chartoken {
 | 
				
			||||||
			node = ast.CharLiteral{
 | 
								node = ast.CharLiteral{
 | 
				
			||||||
				val: p.tok.lit
 | 
									val: p.tok.lit
 | 
				
			||||||
 | 
									pos: p.tok.position()
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			p.next()
 | 
								p.next()
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -39,6 +40,7 @@ pub fn (var p Parser) expr(precedence int) ast.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
 | 
				
			||||||
 | 
									pos: p.tok.position()
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			p.next()
 | 
								p.next()
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue