all: handle `<-` arrow token for channel operations (#6152)
parent
c01fd4ac58
commit
9a5f040f72
|
@ -639,6 +639,17 @@ pub fn (mut c Checker) infix_expr(mut infix_expr ast.InfixExpr) table.Type {
|
||||||
}
|
}
|
||||||
return table.bool_type
|
return table.bool_type
|
||||||
}
|
}
|
||||||
|
.arrow { // `chan <- elem`
|
||||||
|
if left.kind == .chan {
|
||||||
|
elem_type := left.chan_info().elem_type
|
||||||
|
if !c.check_types(right_type, elem_type) {
|
||||||
|
c.error('cannot push `$right.name` on `$left.name`', right_pos)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
c.error('cannot push on non-channel `$left.name`', left_pos)
|
||||||
|
}
|
||||||
|
return table.void_type
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
// use `()` to make the boolean expression clear error
|
// use `()` to make the boolean expression clear error
|
||||||
// for example: `(a && b) || c` instead of `a && b || c`
|
// for example: `(a && b) || c` instead of `a && b || c`
|
||||||
|
@ -2441,6 +2452,14 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type {
|
||||||
if node.op == .not && right_type != table.bool_type_idx && !c.pref.translated {
|
if node.op == .not && right_type != table.bool_type_idx && !c.pref.translated {
|
||||||
c.error('! operator can only be used with bool types', node.pos)
|
c.error('! operator can only be used with bool types', node.pos)
|
||||||
}
|
}
|
||||||
|
if node.op == .arrow {
|
||||||
|
right := c.table.get_type_symbol(right_type)
|
||||||
|
if right.kind == .chan {
|
||||||
|
return right.chan_info().elem_type
|
||||||
|
} else {
|
||||||
|
c.error('<- operator can only be used with `chan` types', node.pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
return right_type
|
return right_type
|
||||||
}
|
}
|
||||||
ast.None {
|
ast.None {
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
vlib/v/checker/tests/arrow_op_wrong_left_type_err_a.v:4:2: error: cannot push on non-channel `i64`
|
||||||
|
2 | ch := i64(3)
|
||||||
|
3 | obj := 5
|
||||||
|
4 | ch <- obj
|
||||||
|
| ~~
|
||||||
|
5 | }
|
|
@ -0,0 +1,5 @@
|
||||||
|
fn main() {
|
||||||
|
ch := i64(3)
|
||||||
|
obj := 5
|
||||||
|
ch <- obj
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
vlib/v/checker/tests/arrow_op_wrong_left_type_err_b.v:4:8: error: cannot assign `string` to `obj` of type `int`
|
||||||
|
2 | ch := chan string{}
|
||||||
|
3 | mut obj := 9
|
||||||
|
4 | obj = <-ch
|
||||||
|
| ~~
|
||||||
|
5 | }
|
|
@ -0,0 +1,5 @@
|
||||||
|
fn main() {
|
||||||
|
ch := chan string{}
|
||||||
|
mut obj := 9
|
||||||
|
obj = <-ch
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
vlib/v/checker/tests/arrow_op_wrong_right_type_err_a.v:4:8: error: cannot push `string` on `chan_u64`
|
||||||
|
2 | ch := chan u64{cap: 10}
|
||||||
|
3 | obj := 'test'
|
||||||
|
4 | ch <- obj
|
||||||
|
| ~~~
|
||||||
|
5 | }
|
|
@ -0,0 +1,5 @@
|
||||||
|
fn main() {
|
||||||
|
ch := chan u64{cap: 10}
|
||||||
|
obj := 'test'
|
||||||
|
ch <- obj
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
vlib/v/checker/tests/arrow_op_wrong_right_type_err_b.v:3:9: error: <- operator can only be used with `chan` types
|
||||||
|
1 | fn main() {
|
||||||
|
2 | ch := i64(3)
|
||||||
|
3 | obj := <-ch
|
||||||
|
| ~~
|
||||||
|
4 | println(obj)
|
||||||
|
5 | }
|
|
@ -0,0 +1,5 @@
|
||||||
|
fn main() {
|
||||||
|
ch := i64(3)
|
||||||
|
obj := <-ch
|
||||||
|
println(obj)
|
||||||
|
}
|
|
@ -858,7 +858,7 @@ fn (mut p Parser) parse_multi_expr(is_top_level bool) ast.Stmt {
|
||||||
return p.partial_assign_stmt(left, left_comments)
|
return p.partial_assign_stmt(left, left_comments)
|
||||||
} else if is_top_level && tok.kind !in [.key_if, .key_match, .key_lock, .key_rlock] &&
|
} else if is_top_level && tok.kind !in [.key_if, .key_match, .key_lock, .key_rlock] &&
|
||||||
left0 !is ast.CallExpr && left0 !is ast.PostfixExpr && !(left0 is ast.InfixExpr &&
|
left0 !is ast.CallExpr && left0 !is ast.PostfixExpr && !(left0 is ast.InfixExpr &&
|
||||||
(left0 as ast.InfixExpr).op == .left_shift) && left0 !is ast.ComptimeCall {
|
(left0 as ast.InfixExpr).op in [.left_shift, .arrow]) && left0 !is ast.ComptimeCall {
|
||||||
p.error_with_pos('expression evaluated but not used', left0.position())
|
p.error_with_pos('expression evaluated but not used', left0.position())
|
||||||
}
|
}
|
||||||
if left.len == 1 {
|
if left.len == 1 {
|
||||||
|
|
|
@ -60,7 +60,7 @@ pub fn (mut p Parser) expr(precedence int) ast.Expr {
|
||||||
}
|
}
|
||||||
p.next()
|
p.next()
|
||||||
}
|
}
|
||||||
.minus, .amp, .mul, .not, .bit_not {
|
.minus, .amp, .mul, .not, .bit_not, .arrow {
|
||||||
// -1, -a, !x, &x, ~x
|
// -1, -a, !x, &x, ~x
|
||||||
node = p.prefix_expr()
|
node = p.prefix_expr()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1037,6 +1037,9 @@ fn (mut s Scanner) text_scan() token.Token {
|
||||||
}
|
}
|
||||||
s.pos++
|
s.pos++
|
||||||
return s.new_token(.left_shift, '', 2)
|
return s.new_token(.left_shift, '', 2)
|
||||||
|
} else if nextc == `-` {
|
||||||
|
s.pos++
|
||||||
|
return s.new_token(.arrow, '', 2)
|
||||||
} else {
|
} else {
|
||||||
return s.new_token(.lt, '', 1)
|
return s.new_token(.lt, '', 1)
|
||||||
}
|
}
|
||||||
|
@ -1045,9 +1048,6 @@ fn (mut s Scanner) text_scan() token.Token {
|
||||||
if nextc == `=` {
|
if nextc == `=` {
|
||||||
s.pos++
|
s.pos++
|
||||||
return s.new_token(.eq, '', 2)
|
return s.new_token(.eq, '', 2)
|
||||||
} else if nextc == `>` {
|
|
||||||
s.pos++
|
|
||||||
return s.new_token(.arrow, '', 2)
|
|
||||||
} else {
|
} else {
|
||||||
return s.new_token(.assign, '', 1)
|
return s.new_token(.assign, '', 1)
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ pub enum Kind {
|
||||||
comma
|
comma
|
||||||
semicolon
|
semicolon
|
||||||
colon
|
colon
|
||||||
arrow // =>
|
arrow // <-
|
||||||
amp
|
amp
|
||||||
hash
|
hash
|
||||||
dollar
|
dollar
|
||||||
|
@ -181,7 +181,7 @@ fn build_token_str() []string {
|
||||||
// s[Kind.at] = '@'
|
// s[Kind.at] = '@'
|
||||||
s[Kind.semicolon] = ';'
|
s[Kind.semicolon] = ';'
|
||||||
s[Kind.colon] = ':'
|
s[Kind.colon] = ':'
|
||||||
s[Kind.arrow] = '=>'
|
s[Kind.arrow] = '<-'
|
||||||
s[Kind.assign] = '='
|
s[Kind.assign] = '='
|
||||||
s[Kind.decl_assign] = ':='
|
s[Kind.decl_assign] = ':='
|
||||||
s[Kind.plus_assign] = '+='
|
s[Kind.plus_assign] = '+='
|
||||||
|
@ -339,6 +339,7 @@ pub fn build_precedences() []Precedence {
|
||||||
p[Kind.left_shift] = .product
|
p[Kind.left_shift] = .product
|
||||||
p[Kind.right_shift] = .product
|
p[Kind.right_shift] = .product
|
||||||
p[Kind.amp] = .product
|
p[Kind.amp] = .product
|
||||||
|
p[Kind.arrow] = .product
|
||||||
// `+` | `-` | `|` | `^`
|
// `+` | `-` | `|` | `^`
|
||||||
p[Kind.plus] = .sum
|
p[Kind.plus] = .sum
|
||||||
p[Kind.minus] = .sum
|
p[Kind.minus] = .sum
|
||||||
|
@ -394,7 +395,7 @@ pub fn (tok Token) is_scalar() bool {
|
||||||
pub fn (tok Token) is_unary() bool {
|
pub fn (tok Token) is_unary() bool {
|
||||||
return tok.kind in [
|
return tok.kind in [
|
||||||
// `+` | `-` | `!` | `~` | `*` | `&`
|
// `+` | `-` | `!` | `~` | `*` | `&`
|
||||||
.plus, .minus, .not, .bit_not, .mul, .amp]
|
.plus, .minus, .not, .bit_not, .mul, .amp, .arrow]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (tok Kind) is_relational() bool {
|
pub fn (tok Kind) is_relational() bool {
|
||||||
|
@ -412,5 +413,5 @@ pub fn (kind Kind) is_infix() bool {
|
||||||
//
|
//
|
||||||
.key_as, .ge, .le, .logical_or, .xor, .not_in, .key_is, .not_is,
|
.key_as, .ge, .le, .logical_or, .xor, .not_in, .key_is, .not_is,
|
||||||
//
|
//
|
||||||
.and, .dot, .pipe, .amp, .left_shift, .right_shift]
|
.and, .dot, .pipe, .amp, .left_shift, .right_shift, .arrow]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue