cgen: implement channel `push()`/`pop()` using `<-` operator (#6154)

pull/6157/head
Uwe Krüger 2020-08-17 23:35:36 +02:00 committed by GitHub
parent 5c98c0760b
commit 0d7cc8829a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 52 additions and 21 deletions

View File

@ -1,45 +1,42 @@
import sync
import time
fn do_rec_i64(ch chan i64) {
mut sum := i64(0)
for _ in 0 .. 300 {
mut a := i64(0)
(&sync.Channel(ch)).pop(&a)
sum += a
sum += <-ch
}
assert sum == 300 * (300 - 1) / 2
}
fn do_send_int(ch chan int) {
for i in 0 .. 300 {
(&sync.Channel(ch)).push(&i)
ch <- i
}
}
fn do_send_byte(ch chan byte) {
for i in 0 .. 300 {
ii := byte(i)
(&sync.Channel(ch)).push(&ii)
ch <- byte(i)
}
}
fn do_send_i64(mut ch sync.Channel) {
fn do_send_i64(ch chan i64) {
for i in 0 .. 300 {
ii := i64(i)
ch.push(&ii)
ch <- i
}
}
fn test_select() {
chi := chan int{}
mut chl := sync.new_channel<i64>(1)
chl := chan i64{cap: 1}
chb := chan byte{cap: 10}
recch := chan i64{cap: 0}
go do_rec_i64(recch)
go do_send_int(chi)
go do_send_byte(chb)
go do_send_i64(mut chl)
mut channels := [&sync.Channel(chi), &sync.Channel(recch), chl, &sync.Channel(chb)]
go do_send_i64(chl)
mut channels := [&sync.Channel(chi), &sync.Channel(recch), &sync.Channel(chl), &sync.Channel(chb)]
directions := [sync.Direction.pop, .push, .pop, .pop]
mut sum := i64(0)
mut rl := i64(0)
@ -73,4 +70,5 @@ fn test_select() {
256 * (256 - 1) / 2 +
44 * (44 - 1) / 2
assert sum == expected_sum
time.sleep_ms(20) // to give assert in coroutine enough time
}

View File

@ -438,6 +438,8 @@ pub:
op token.Kind
right Expr
pos token.Position
pub mut:
right_type table.Type
}
pub struct IndexExpr {

View File

@ -2439,6 +2439,7 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type {
}
ast.PrefixExpr {
right_type := c.expr(node.right)
node.right_type = right_type
// TODO: testing ref/deref strategy
if node.op == .amp && !right_type.is_ptr() {
return right_type.to_ptr()

View File

@ -498,8 +498,21 @@ typedef struct {
g.type_definitions.writeln('typedef _Interface ${c_name(typ.name)};')
}
.chan {
if typ.name != 'chan' {
styp := util.no_dots(typ.name)
g.type_definitions.writeln('typedef chan $styp;')
el_stype := g.typ(typ.chan_info().elem_type)
g.hotcode_definitions.writeln('
static inline $el_stype __${styp}_popval($styp ch) {
$el_stype val;
sync__Channel_try_pop_priv(ch, &val, false);
return val;
}')
g.hotcode_definitions.writeln('
static inline void __${styp}_pushval($styp ch, $el_stype val) {
sync__Channel_try_push_priv(ch, &val, false);
}')
}
}
.map {
styp := util.no_dots(typ.name)
@ -1969,11 +1982,20 @@ fn (mut g Gen) expr(node ast.Expr) {
if node.op == .amp {
g.is_amp = true
}
if node.op == .arrow {
right_type := g.unwrap_generic(node.right_type)
right_sym := g.table.get_type_symbol(right_type)
styp := util.no_dots(right_sym.name)
g.write('__${styp}_popval(')
} else {
// g.write('/*pref*/')
g.write(node.op.str())
// g.write('(')
}
g.expr(node.right)
// g.write(')')
if node.op == .arrow {
g.write(')')
}
g.is_amp = false
}
ast.RangeExpr {
@ -2326,6 +2348,14 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) {
}
g.write(' }))')
}
} else if node.op == .arrow {
// chan <- val
styp := util.no_dots(left_sym.name)
g.write('__${styp}_pushval(')
g.expr(node.left)
g.write(', ')
g.expr(node.right)
g.write(')')
} else if unaliased_left.idx() in [table.u32_type_idx, table.u64_type_idx] && unaliased_right.is_signed() &&
node.op in [.eq, .ne, .gt, .lt, .ge, .le] {
bitsize := if unaliased_left.idx() == table.u32_type_idx &&