checker: more infix checks
							parent
							
								
									07f69fab19
								
							
						
					
					
						commit
						717e26b45e
					
				|  | @ -48,6 +48,7 @@ pub: | |||
| pub struct FloatLiteral { | ||||
| pub: | ||||
| 	val string | ||||
| 	pos token.Position | ||||
| } | ||||
| 
 | ||||
| pub struct StringLiteral { | ||||
|  | @ -73,11 +74,13 @@ mut: | |||
| pub struct CharLiteral { | ||||
| pub: | ||||
| 	val string | ||||
| 	pos token.Position | ||||
| } | ||||
| 
 | ||||
| pub struct BoolLiteral { | ||||
| pub: | ||||
| 	val bool | ||||
| 	pos token.Position | ||||
| } | ||||
| 
 | ||||
| // `foo.bar`
 | ||||
|  | @ -737,36 +740,20 @@ pub fn expr_is_call(expr Expr) bool { | |||
| fn (expr Expr) position() token.Position { | ||||
| 	// all uncommented have to be implemented
 | ||||
| 	match var expr { | ||||
| 		ArrayInit { | ||||
| 			return it.pos | ||||
| 		} | ||||
| 		AsCast { | ||||
| 			return it.pos | ||||
| 		} | ||||
| 		ArrayInit { return it.pos } | ||||
| 		AsCast { return it.pos } | ||||
| 		// ast.Ident { }
 | ||||
| 		AssignExpr { | ||||
| 			return it.pos | ||||
| 		} | ||||
| 		AssignExpr { return it.pos } | ||||
| 		// ast.CastExpr { }
 | ||||
| 		Assoc { | ||||
| 			return it.pos | ||||
| 		} | ||||
| 		// ast.BoolLiteral { }
 | ||||
| 		CallExpr { | ||||
| 			return it.pos | ||||
| 		} | ||||
| 		// ast.CharLiteral { }
 | ||||
| 		EnumVal { | ||||
| 			return it.pos | ||||
| 		} | ||||
| 		// ast.FloatLiteral { }
 | ||||
| 		IfExpr { | ||||
| 			return it.pos | ||||
| 		} | ||||
| 		Assoc { return it.pos } | ||||
| 		BoolLiteral { return it.pos } | ||||
| 		CallExpr { return it.pos } | ||||
| 		CharLiteral { return it.pos } | ||||
| 		EnumVal { return it.pos } | ||||
| 		FloatLiteral { return it.pos } | ||||
| 		IfExpr { return it.pos } | ||||
| 		// ast.IfGuardExpr { }
 | ||||
| 		IndexExpr { | ||||
| 			return it.pos | ||||
| 		} | ||||
| 		IndexExpr { return it.pos } | ||||
| 		InfixExpr { | ||||
| 			left_pos := it.left.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 | ||||
| 			} | ||||
| 		} | ||||
| 		IntegerLiteral { | ||||
| 			return it.pos | ||||
| 		} | ||||
| 		MapInit { | ||||
| 			return it.pos | ||||
| 		} | ||||
| 		MatchExpr { | ||||
| 			return it.pos | ||||
| 		} | ||||
| 		PostfixExpr { | ||||
| 			return it.pos | ||||
| 		} | ||||
| 		IntegerLiteral { return it.pos } | ||||
| 		MapInit { return it.pos } | ||||
| 		MatchExpr { return it.pos } | ||||
| 		PostfixExpr { return it.pos } | ||||
| 		// ast.None { }
 | ||||
| 		PrefixExpr { | ||||
| 			return it.pos | ||||
| 		} | ||||
| 		PrefixExpr { return it.pos } | ||||
| 		// ast.ParExpr { }
 | ||||
| 		SelectorExpr { | ||||
| 			return it.pos | ||||
| 		} | ||||
| 		SelectorExpr { return it.pos } | ||||
| 		// ast.SizeOf { }
 | ||||
| 		StringLiteral { | ||||
| 			return it.pos | ||||
| 		} | ||||
| 		StringInterLiteral { | ||||
| 			return it.pos | ||||
| 		} | ||||
| 		StringLiteral { return it.pos } | ||||
| 		StringInterLiteral { return it.pos } | ||||
| 		// ast.Type { }
 | ||||
| 		StructInit { | ||||
| 			return it.pos | ||||
| 		} | ||||
| 		StructInit { return it.pos } | ||||
| 		// ast.TypeOf { }
 | ||||
| 		else { | ||||
| 			return token.Position{} | ||||
| 		} | ||||
| 		else { 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) | ||||
| 	left := c.table.get_type_symbol(left_type) | ||||
| 	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 { | ||||
| 			// `array << elm`
 | ||||
| 			// 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()) | ||||
| 			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] { | ||||
|  | @ -302,20 +303,19 @@ pub fn (c mut Checker) infix_expr(infix_expr mut ast.InfixExpr) table.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 !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() { | ||||
| 			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]) { | ||||
|  | @ -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 `&&`', | ||||
| 			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() { | ||||
| 		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() { | ||||
|     2|     0.5 & 1 | ||||
|                ^ | ||||
|            ~~~ | ||||
|     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() { | ||||
|     2|     1 | 0.5 | ||||
|              ^ | ||||
|                ~~~ | ||||
|     3| } | ||||
|  |  | |||
|  | @ -1,3 +1,3 @@ | |||
| fn main() { | ||||
| 	1 | 0.5 | ||||
| fn main() { | ||||
| 	1 | 0.5 | ||||
| } | ||||
|  | @ -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{ | ||||
|     7|         foo: true | ||||
|     8|         bar: false | ||||
|                ^ | ||||
|                ~~~~~~~~~~ | ||||
|     9|     } | ||||
|    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'] { | ||||
| 		node = ast.FloatLiteral{ | ||||
| 			val: lit | ||||
| 			pos: pos | ||||
| 		} | ||||
| 	} else { | ||||
| 		node = ast.IntegerLiteral{ | ||||
|  | @ -1210,10 +1211,10 @@ fn (var p Parser) assoc() ast.Assoc { | |||
| fn (p &Parser) new_true_expr() ast.Expr { | ||||
| 	return ast.BoolLiteral{ | ||||
| 		val: true | ||||
| 		pos: p.tok.position() | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| fn verror(s string) { | ||||
| 	util.verror('parser error', s) | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -29,6 +29,7 @@ pub fn (var p Parser) expr(precedence int) ast.Expr { | |||
| 		.chartoken { | ||||
| 			node = ast.CharLiteral{ | ||||
| 				val: p.tok.lit | ||||
| 				pos: p.tok.position() | ||||
| 			} | ||||
| 			p.next() | ||||
| 		} | ||||
|  | @ -39,6 +40,7 @@ pub fn (var p Parser) expr(precedence int) ast.Expr { | |||
| 		.key_true, .key_false { | ||||
| 			node = ast.BoolLiteral{ | ||||
| 				val: p.tok.kind == .key_true | ||||
| 				pos: p.tok.position() | ||||
| 			} | ||||
| 			p.next() | ||||
| 		} | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue