Files
spl/stage1/test18_match.spl

489 lines
10 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* ===== 模块4match 语句 =====
* test18_match — match 枚举匹配 + 整数匹配(类似 switch
* 难度3/5
* 验证点:枚举匹配、带数据绑定、结构体字段绑定、枚举指针、
* 整数自变量匹配、默认分支 _
*/
/* ---- 简单枚举(无数据) ---- */
type Color = enum {
Red;
Green;
Blue;
}
/* ---- 带 i32 数据的枚举 ---- */
type Optional = enum {
Some: i32;
None;
}
/* ---- 带结构体数据的枚举 ---- */
type Point = struct {
var x: i32;
var y: i32;
}
type Shape = enum {
Circle: i32;
Rect: Point;
}
/* ---- 多变体枚举 ---- */
type ActionResult = enum {
Success: i32;
NotFound;
Timeout: i32;
Error: *u8;
}
/* ============================================================
* 测试 1: 无数据枚举匹配
* ============================================================ */
fn test_color_match() i32 {
var c: Color = Color { .Red };
var val: i32 = 0;
match c {
.Red => { val = 1; },
.Green => { val = 2; },
.Blue => { val = 3; }
}
if val != 1 { ret 1; }
c = Color { .Green };
match c {
.Red => { val = 0; },
.Green => { val = 2; },
.Blue => { val = 0; }
}
if val != 2 { ret 2; }
c = Color { .Blue };
match c {
.Red => { val = 0; },
.Green => { val = 0; },
.Blue => { val = 3; }
}
if val != 3 { ret 3; }
ret 0;
}
/* ============================================================
* 测试 2: 带 i32 数据枚举匹配
* ============================================================ */
fn test_optional_match() i32 {
var o: Optional = Optional { .Some = 42 };
match o {
.Some(val) => {
if val != 42 { ret 1; }
},
.None => {
ret 2;
}
}
o = Optional { .None };
var is_none: i32 = 0;
match o {
.Some(val) => {},
.None => { is_none = 1; }
}
if is_none != 1 { ret 3; }
/* 多次提取不同值 */
o = Optional { .Some = 99 };
match o {
.Some(val) => {
if val != 99 { ret 4; }
},
.None => { ret 5; }
}
ret 0;
}
/* ============================================================
* 测试 3: 带结构体数据枚举匹配(多字段绑定)
* ============================================================ */
fn test_shape_match() i32 {
/* Circle: 单数据 */
var s: Shape = Shape { .Circle = 10 };
match s {
.Circle(r) => {
if r != 10 { ret 1; }
},
.Rect(w, h) => {
ret 2;
}
}
/* Rect: 结构体数据,绑定为 (x, y) 对应 Point 的字段 */
s = Shape { .Rect = Point { .x = 3, .y = 4 } };
match s {
.Circle(r) => { ret 3; },
.Rect(w, h) => {
if w != 3 { ret 4; }
if h != 4 { ret 5; }
}
}
ret 0;
}
/* ============================================================
* 测试 4: 多数据变体枚举匹配
* ============================================================ */
fn test_action_result_match() i32 {
var r: ActionResult = ActionResult { .Success = 200 };
match r {
.Success(code) => {
if code != 200 { ret 1; }
},
.NotFound => {
ret 2;
},
.Timeout(ms) => {
ret 3;
},
.Error(msg) => {
ret 4;
}
}
r = ActionResult { .NotFound };
var found: i32 = 1;
match r {
.Success(code) => { found = 0; },
.NotFound => { },
.Timeout(ms) => { found = 0; },
.Error(msg) => { found = 0; }
}
if found != 1 { ret 5; }
r = ActionResult { .Timeout = 5000 };
match r {
.Success(code) => { ret 6; },
.NotFound => { ret 7; },
.Timeout(ms) => {
if ms != 5000 { ret 8; }
},
.Error(msg) => { ret 9; }
}
ret 0;
}
/* ============================================================
* 测试 5: 枚举指针匹配
* ============================================================ */
fn test_ptr_match() i32 {
var c: Color = Color { .Green };
var p: *Color = &c;
match p {
.Red => { ret 1; },
.Green => { },
.Blue => { ret 2; }
}
/* 修改后通过指针匹配 */
c = Color { .Blue };
match p {
.Red => { ret 3; },
.Green => { ret 4; },
.Blue => { }
}
ret 0;
}
/* ============================================================
* 测试 6: match 作为函数返回值
* ============================================================ */
fn classify_color(c: Color) i32 {
match c {
.Red => { ret 1; },
.Green => { ret 2; },
.Blue => { ret 3; }
}
ret 0;
}
fn test_match_in_func() i32 {
var r: i32;
r = classify_color(Color { .Red });
if r != 1 { ret 1; }
r = classify_color(Color { .Green });
if r != 2 { ret 2; }
r = classify_color(Color { .Blue });
if r != 3 { ret 3; }
ret 0;
}
/* ============================================================
* 测试 7: match 嵌套在循环中
* ============================================================ */
fn test_match_in_loop() i32 {
var i: i32 = 0;
var sum: i32 = 0;
while i < 3 {
var o: Optional;
if i == 0 {
o = Optional { .Some = 10 };
} else if i == 1 {
o = Optional { .Some = 20 };
} else {
o = Optional { .Some = 30 };
}
match o {
.Some(val) => {
sum = sum + val;
},
.None => { }
}
i = i + 1;
}
if sum != 60 { ret 1; }
ret 0;
}
/* ============================================================
* 测试 8: 整数 match类似 switch
* ============================================================ */
fn test_int_match() i32 {
var x: i32 = 2;
var result: i32 = 0;
match x {
1 => { result = 10; },
2 => { result = 20; },
3 => { result = 30; }
}
if result != 20 { ret 1; }
/* 匹配第一个值 */
x = 1;
match x {
1 => { result = 100; },
2 => { result = 200; },
3 => { result = 300; }
}
if result != 100 { ret 2; }
/* 匹配最后一个值 */
x = 3;
match x {
1 => { result = 1000; },
2 => { result = 2000; },
3 => { result = 3000; }
}
if result != 3000 { ret 3; }
ret 0;
}
/* ============================================================
* 测试 9: 整数 match 带默认分支 _
* ============================================================ */
fn test_int_match_default() i32 {
var x: i32 = 99;
var result: i32 = 0;
match x {
1 => { result = 1; },
2 => { result = 2; },
_ => { result = 99; }
}
if result != 99 { ret 1; }
/* 默认分支未触发 */
x = 1;
match x {
1 => { result = 1; },
2 => { result = 2; },
_ => { result = 99; }
}
if result != 1 { ret 2; }
ret 0;
}
/* ============================================================
* 测试 10: 整数 match 多个值跳转到相同逻辑
* ============================================================ */
fn test_int_match_multi() i32 {
var x: i32 = 2;
var result: i32 = 0;
/* 每个分支独立 */
match x {
0 => { result = 0; },
1 => { result = 1; },
2 => { result = 2; },
3 => { result = 3; }
}
if result != 2 { ret 1; }
/* 负数和零 */
x = -1;
match x {
-1 => { result = -1; },
0 => { result = 0; },
1 => { result = 1; }
}
if result != -1 { ret 2; }
x = 0;
match x {
-1 => { result = -1; },
0 => { result = 0; },
1 => { result = 1; }
}
if result != 0 { ret 3; }
ret 0;
}
/* ============================================================
* 测试 11a: match 多值 fallthrough: 1, 2, 3 => body
* ============================================================ */
fn test_int_match_fallthrough() i32 {
var x: i32;
var r: i32;
/* 三个值映射到同一个 body */
x = 1; r = 0;
match x {
1, 2, 3 => { r = 10; },
4, 5 => { r = 20; }
}
if r != 10 { ret 1; }
x = 3;
match x {
1, 2, 3 => { r = 10; },
4, 5 => { r = 20; }
}
if r != 10 { ret 2; }
x = 5;
match x {
1, 2, 3 => { r = 10; },
4, 5 => { r = 20; }
}
if r != 20 { ret 3; }
/* 单一值(非fallthrough)仍然正常 */
x = 7; r = 0;
match x {
1 => { r = 1; },
7 => { r = 7; }
}
if r != 7 { ret 4; }
/* 多个负数值 */
x = -2; r = 0;
match x {
-3, -2, -1 => { r = 100; },
0, 1 => { r = 200; }
}
if r != 100 { ret 5; }
ret 0;
}
/* ============================================================
* 测试 11b: match with body 中修改变量
* ============================================================ */
fn test_match_with_side_effects() i32 {
var x: i32 = 3;
var acc: i32 = 0;
match x {
1 => { acc = acc + 1; },
2 => { acc = acc + 2; },
3 => { acc = acc + 3; },
4 => { acc = acc + 4; }
}
if acc != 3 { ret 1; }
/* 再次 match 同一个变量 */
match x {
1 => { acc = acc + 1; },
2 => { acc = acc + 2; },
3 => { acc = acc + 3; },
4 => { acc = acc + 4; }
}
if acc != 6 { ret 2; }
ret 0;
}
/* ============================================================
* 主函数
* ============================================================ */
fn main() i32 {
var r: i32;
r = test_color_match();
if r != 0 { ret r; }
r = test_optional_match();
if r != 0 { ret r + 10; }
r = test_shape_match();
if r != 0 { ret r + 20; }
r = test_action_result_match();
if r != 0 { ret r + 30; }
r = test_ptr_match();
if r != 0 { ret r + 40; }
r = test_match_in_func();
if r != 0 { ret r + 50; }
r = test_match_in_loop();
if r != 0 { ret r + 60; }
r = test_int_match();
if r != 0 { ret r + 70; }
r = test_int_match_default();
if r != 0 { ret r + 80; }
r = test_int_match_multi();
if r != 0 { ret r + 90; }
r = test_match_with_side_effects();
if r != 0 { ret r + 100; }
r = test_int_match_fallthrough();
if r != 0 { ret r + 110; }
ret 0;
}