mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
native: match expr/stmt (#15537)
This commit is contained in:
parent
02a47f42f3
commit
e5c53cf412
@ -2572,3 +2572,76 @@ fn (mut g Gen) reverse_string(reg Register) {
|
||||
g.write8(0xf1)
|
||||
g.println('jmp 0xf')
|
||||
}
|
||||
|
||||
fn (mut g Gen) gen_match_expr_amd64(expr ast.MatchExpr) {
|
||||
branch_labels := []int{len: expr.branches.len, init: g.labels.new_label() + it * 0} // call new_label for all elements in the array
|
||||
end_label := g.labels.new_label()
|
||||
|
||||
if expr.is_sum_type {
|
||||
// TODO
|
||||
} else {
|
||||
g.expr(expr.cond)
|
||||
}
|
||||
g.push(.rax)
|
||||
|
||||
mut else_label := 0
|
||||
for i, branch in expr.branches {
|
||||
if branch.is_else {
|
||||
else_label = branch_labels[i]
|
||||
} else {
|
||||
for cond in branch.exprs {
|
||||
match cond {
|
||||
ast.RangeExpr {
|
||||
g.pop(.rdx)
|
||||
g.expr(cond.low)
|
||||
g.cmp_reg(.rax, .rdx)
|
||||
g.write([u8(0x0f), 0x9e, 0xc3])
|
||||
g.println('setle bl')
|
||||
g.expr(cond.high)
|
||||
g.cmp_reg(.rax, .rdx)
|
||||
g.write([u8(0x0f), 0x9d, 0xc1])
|
||||
g.println('setge cl')
|
||||
g.write([u8(0x20), 0xcb])
|
||||
g.println('and bl, cl')
|
||||
g.write([u8(0x84), 0xdb])
|
||||
g.println('test bl, bl')
|
||||
then_addr := g.cjmp(.jne)
|
||||
g.labels.patches << LabelPatch{
|
||||
id: branch_labels[i]
|
||||
pos: then_addr
|
||||
}
|
||||
g.push(.rdx)
|
||||
}
|
||||
else {
|
||||
g.expr(cond)
|
||||
g.pop(.rdx)
|
||||
g.cmp_reg(.rax, .rdx)
|
||||
then_addr := g.cjmp(.je)
|
||||
g.labels.patches << LabelPatch{
|
||||
id: branch_labels[i]
|
||||
pos: then_addr
|
||||
}
|
||||
g.push(.rdx)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
g.pop(.rdx)
|
||||
else_addr := g.jmp(0)
|
||||
g.labels.patches << LabelPatch{
|
||||
id: else_label
|
||||
pos: else_addr
|
||||
}
|
||||
for i, branch in expr.branches {
|
||||
g.labels.addrs[branch_labels[i]] = g.pos()
|
||||
for stmt in branch.stmts {
|
||||
g.stmt(stmt)
|
||||
}
|
||||
g.labels.patches << LabelPatch{
|
||||
id: end_label
|
||||
pos: g.jmp(0)
|
||||
}
|
||||
}
|
||||
g.labels.addrs[end_label] = g.pos()
|
||||
}
|
||||
|
@ -482,6 +482,14 @@ fn (mut g Gen) call_fn(node ast.CallExpr) {
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut g Gen) gen_match_expr(expr ast.MatchExpr) {
|
||||
if g.pref.arch == .arm64 {
|
||||
// g.gen_match_expr_arm64(expr)
|
||||
} else {
|
||||
g.gen_match_expr_amd64(expr)
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut g Gen) gen_var_to_string(reg Register, var Var, config VarConfig) {
|
||||
typ := g.get_type_from_var(var)
|
||||
if typ.is_int() {
|
||||
@ -601,7 +609,6 @@ g.expr
|
||||
ast.InfixExpr {}
|
||||
ast.IsRefType {}
|
||||
ast.MapInit {}
|
||||
ast.MatchExpr {}
|
||||
ast.OrExpr {}
|
||||
ast.ParExpr {}
|
||||
ast.RangeExpr {}
|
||||
@ -609,6 +616,9 @@ g.expr
|
||||
ast.SqlExpr {}
|
||||
ast.TypeNode {}
|
||||
*/
|
||||
ast.MatchExpr {
|
||||
g.gen_match_expr(expr)
|
||||
}
|
||||
ast.TypeOf {
|
||||
g.gen_typeof_expr(expr, newline)
|
||||
}
|
||||
@ -1045,6 +1055,9 @@ fn (mut g Gen) expr(node ast.Expr) {
|
||||
ast.GoExpr {
|
||||
g.v_error('native backend doesnt support threads yet', node.pos)
|
||||
}
|
||||
ast.MatchExpr {
|
||||
g.gen_match_expr(node)
|
||||
}
|
||||
else {
|
||||
g.n_error('expr: unhandled node type: $node.type_name()')
|
||||
}
|
||||
|
125
vlib/v/gen/native/tests/match.vv
Normal file
125
vlib/v/gen/native/tests/match.vv
Normal file
@ -0,0 +1,125 @@
|
||||
fn match_for_test() { // from for_loops_2_test.v
|
||||
mut a := 2
|
||||
mut b := 0
|
||||
for {
|
||||
match a {
|
||||
2 {
|
||||
println('a == 2')
|
||||
a = 0
|
||||
continue
|
||||
}
|
||||
0 {
|
||||
println('a == 0')
|
||||
a = 5
|
||||
b++
|
||||
break
|
||||
}
|
||||
else {
|
||||
println('unexpected branch')
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
assert a == 5
|
||||
assert b == 1
|
||||
println(b)
|
||||
println(a)
|
||||
}
|
||||
|
||||
fn ifexpr_match_test() { // from if_expr_with_nested_match_expr_test.v
|
||||
b := true // this is needed. why?
|
||||
a := if b {
|
||||
match 5 {
|
||||
5 { 0 }
|
||||
else { 1 }
|
||||
}
|
||||
} else {
|
||||
3
|
||||
}
|
||||
assert a == 0
|
||||
println(a)
|
||||
}
|
||||
|
||||
fn integer_match_test() { // from match_test.v
|
||||
mut a := 3
|
||||
mut b := 0
|
||||
match a {
|
||||
2 {
|
||||
println('two')
|
||||
}
|
||||
3 {
|
||||
println('three')
|
||||
b = 3
|
||||
}
|
||||
4 {
|
||||
println('four')
|
||||
}
|
||||
else {
|
||||
println('???')
|
||||
}
|
||||
}
|
||||
assert b == 3
|
||||
assert match 2 {
|
||||
1 { 2 }
|
||||
2 { 3 }
|
||||
else { 5 }
|
||||
} == 3
|
||||
assert match 0 {
|
||||
1 { 2 }
|
||||
2 { 3 }
|
||||
else { 5 }
|
||||
} == 5
|
||||
assert match 1 {
|
||||
2 { 0 }
|
||||
else { 5 }
|
||||
} == 5
|
||||
a = 0
|
||||
match 2 {
|
||||
0 {
|
||||
a = 1
|
||||
}
|
||||
1 {
|
||||
a = 2
|
||||
}
|
||||
else {
|
||||
a = 3
|
||||
}
|
||||
}
|
||||
assert a == 3
|
||||
a = 0
|
||||
/* match 1 {
|
||||
0 {
|
||||
a = 1
|
||||
}
|
||||
1 {
|
||||
a = 2
|
||||
a = a + 2
|
||||
a = a + 2
|
||||
}
|
||||
else {}
|
||||
}
|
||||
assert a == 6
|
||||
a = 0
|
||||
match 1 {
|
||||
0 {}
|
||||
else { a = -2 }
|
||||
}
|
||||
assert a == -2*/
|
||||
}
|
||||
|
||||
fn multiple_test() { // from match_test.v
|
||||
a := 9
|
||||
match a {
|
||||
1, 2, 3 { println('1-3') }
|
||||
4, 5 { println('4-5') }
|
||||
6...9 { println('6-9') }
|
||||
else { println('other') }
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
match_for_test()
|
||||
ifexpr_match_test()
|
||||
integer_match_test()
|
||||
multiple_test()
|
||||
}
|
7
vlib/v/gen/native/tests/match.vv.out
Normal file
7
vlib/v/gen/native/tests/match.vv.out
Normal file
@ -0,0 +1,7 @@
|
||||
a == 2
|
||||
a == 0
|
||||
1
|
||||
5
|
||||
0
|
||||
three
|
||||
6-9
|
Loading…
Reference in New Issue
Block a user