diff --git a/vlib/v/fmt/fmt.v b/vlib/v/fmt/fmt.v index a31847670d..036212b5f4 100644 --- a/vlib/v/fmt/fmt.v +++ b/vlib/v/fmt/fmt.v @@ -937,7 +937,42 @@ pub fn (mut f Fmt) expr(node ast.Expr) { f.expr(node.high) } ast.SelectExpr { - // TODO: implement this + f.writeln('select {') + f.indent++ + for branch in node.branches { + if branch.comment.text != '' { + f.comment(branch.comment, { + inline: true + }) + f.writeln('') + } + if branch.is_else { + f.write('else {') + } else { + if branch.is_timeout { + f.write('> ') + } + f.single_line_if = true + match branch.stmt as stmt { + ast.ExprStmt { f.expr(stmt.expr) } + else { f.stmt(branch.stmt) } + } + f.single_line_if = false + f.write(' {') + } + if branch.stmts.len > 0 { + f.writeln('') + f.stmts(branch.stmts) + } + f.writeln('}') + if branch.post_comments.len > 0 { + f.comments(branch.post_comments, { + inline: true + }) + } + } + f.indent-- + f.write('}') } ast.SelectorExpr { f.expr(node.expr) diff --git a/vlib/v/fmt/tests/select_keep.vv b/vlib/v/fmt/tests/select_keep.vv new file mode 100644 index 0000000000..998ac34b5c --- /dev/null +++ b/vlib/v/fmt/tests/select_keep.vv @@ -0,0 +1,128 @@ +import time +import sync + +struct St { + a int +} + +fn getint() int { + return 8 +} + +fn f1(ch1 chan int, ch2 chan St, ch3, ch4, ch5 chan int, sem sync.Semaphore) { + mut a := 5 + select { + // pre comment + a = <-ch3 { + a = 0 + } + b := <-ch2 { + a = b.a + } + ch3 <- 5 { + a = 1 + } + ch2 <- St{ + a: 37 + } { + a = 2 + } + // another comment + ch4 <- (6 + 7 * 9) { + a = 8 + } + ch5 <- getint() { + a = 9 + } + > 300 * time.millisecond { + a = 3 + } + // post comment + } + assert a == 3 + sem.post() +} + +fn f2(ch1 chan St, ch2 chan int, sem sync.Semaphore) { + mut r := 23 + for i in 0 .. 2 { + select { + b := <-ch1 { + r = b.a + } + ch2 <- r { + r = 17 + } + } + if i == 0 { + assert r == 17 + } else { + assert r == 13 + } + } + sem.post() +} + +fn test_select_blocks() { + ch1 := chan int{cap: 1} + ch2 := chan St{} + ch3 := chan int{} + ch4 := chan int{} + ch5 := chan int{} + sem := sync.new_semaphore() + mut r := false + t := select { + b := <-ch1 { + println(b) + } + else { + // no channel ready + r = true + } + } + assert r == true + assert t == true + go f2(ch2, ch3, sem) + n := <-ch3 + assert n == 23 + ch2 <- St{ + a: 13 + } + sem.wait() + stopwatch := time.new_stopwatch({}) + go f1(ch1, ch2, ch3, ch4, ch5, sem) + sem.wait() + elapsed_ms := f64(stopwatch.elapsed()) / time.millisecond + assert elapsed_ms >= 295.0 + ch1.close() + ch2.close() + mut h := 7 + mut is_open := true + if select { + b := <-ch2 { + h = 0 + } + ch1 <- h { + h = 1 + } + else { + h = 2 + } + } { + panic('channel is still open') + } else { + is_open = false + } + // no branch should have run + for select { + b := <-ch2 { + h = 0 + } + } { + println('ch2 open') + } + println('ch2 closed') + assert h == 7 + // since all channels are closed `select` should return `false` + assert is_open == false +}