enum Color { red green blue } pub fn (c Color) str() string { return 'tmp' } fn test_match_integers() { mut a := 3 mut b := 0 match a { 2 { println('two') } 3 { println('three') b = 3 } int(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 println('a is ${a}') } } 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 test_match_multiple() { assert match 9 { 1, 2, 3 { '1-3' } 4, 5 { '4-5' } 6...9 { '6-9' } else { 'other' } } == '6-9' } fn test_match_range() { assert match `f` { `0`...`9` { 'digit' } `A`...`Z` { 'uppercase' } `a`...`z` { 'lowercase' } else { 'other' } } == 'lowercase' } fn test_match_enums() { mut b := Color.red match b { .red { b = .green } .green { b = .blue } else { println('b is ${b.str()}') b = .red } } assert b == .green match b { .red { b = .green } else { println('b is ${b.str()}') b = .blue } } assert b == .blue } struct Counter { mut: val int } fn (mut c Counter) next() int { c.val++ return c.val } fn test_method_call() { mut c := Counter{ val: 1 } assert match c.next() { 1 { false } 2 { true } 3 { false } else { true } } } type Sum = A1 | B1 struct A1 { pos int } struct B1 { val string } fn f(s Sum) string { match s { A1 { return typeof(s).name } B1 { return '' } } return '' } fn test_sum_type_name() { a := A1{ pos: 22 } assert f(a) == 'A1' } fn f_else(s Sum) string { match s { A1 { return typeof(s).name } else { return '' } } } fn test_sum_type_else() { a := A1{ pos: 22 } assert f_else(a) == 'A1' } struct Alfa { char rune = `a` } fn (a Alfa) letter() rune { return a.char } struct Bravo { // A field so that Alfa and Bravo structures aren't the same dummy_field int pub mut: // Note: the `char` field is not `pub` or `mut` in all sumtype variants, but using it in aggregates should still work char rune = `b` } fn (b Bravo) letter() rune { return b.char } struct Charlie { char rune = `c` } type NATOAlphabet = Alfa | Bravo | Charlie fn test_match_sumtype_multiple_types() { a := Alfa{} l := NATOAlphabet(a) match l { Alfa, Bravo { assert l.char == `a` // TODO: make methods work // assert l.letter() == `a` } Charlie { assert false } } // test one branch match l { Alfa, Bravo, Charlie { assert l.char == `a` } } } fn test_sub_expression() { b := false && match 1 { 0 { true } else { true } } assert !b c := true || match 1 { 0 { false } else { false } } assert c } const one = 'one' fn test_match_constant_string() { s := one match s { one { assert true } else { assert false } } } type WithArray = []WithArray | int fn test_sumtype_with_array() { fa := [WithArray(0)] f := WithArray(fa) match f { []WithArray { assert true } int { assert false } } match f { int { assert false } []WithArray { assert true } } } fn test_match_expression_add() { a := match true { true { 1 } false { 2 } } + 3 assert a == 4 } type LeType = int | string fn test_noreturn() { t := LeType(3) _ := match t { int { 'test' } string { exit(0) } } } // for test the returns both interface and non-interface interface Any {} fn test_returns_both_interface_and_non_interface() { any := Any('abc') mut res := match any { string { any } else { 'literal' } } assert res == 'abc' variable := '' res = match any { string { any } else { variable } } assert res == 'abc' }