kaish_kernel/interpreter/
control_flow.rs1use super::result::ExecResult;
7
8#[derive(Debug, Clone)]
13pub enum ControlFlow {
14 Normal(ExecResult),
16 Break { levels: usize, result: ExecResult },
18 Continue { levels: usize, result: ExecResult },
20 Return { value: ExecResult },
22 Exit { code: i64 },
24}
25
26impl ControlFlow {
27 pub fn ok(result: ExecResult) -> Self {
29 ControlFlow::Normal(result)
30 }
31
32 pub fn break_one() -> Self {
34 ControlFlow::Break {
35 levels: 1,
36 result: ExecResult::success(""),
37 }
38 }
39
40 pub fn break_n(n: usize) -> Self {
42 ControlFlow::Break {
43 levels: n,
44 result: ExecResult::success(""),
45 }
46 }
47
48 pub fn continue_one() -> Self {
50 ControlFlow::Continue {
51 levels: 1,
52 result: ExecResult::success(""),
53 }
54 }
55
56 pub fn continue_n(n: usize) -> Self {
58 ControlFlow::Continue {
59 levels: n,
60 result: ExecResult::success(""),
61 }
62 }
63
64 pub fn return_value(value: ExecResult) -> Self {
66 ControlFlow::Return { value }
67 }
68
69 pub fn exit_code(code: i64) -> Self {
71 ControlFlow::Exit { code }
72 }
73
74 pub fn is_normal(&self) -> bool {
76 matches!(self, ControlFlow::Normal(_))
77 }
78
79 pub fn into_result(self) -> Option<ExecResult> {
81 match self {
82 ControlFlow::Normal(r) => Some(r),
83 _ => None,
84 }
85 }
86
87 pub fn decrement_level(&mut self) -> bool {
92 match self {
93 ControlFlow::Break { levels, .. } | ControlFlow::Continue { levels, .. } => {
94 if *levels <= 1 {
95 true
96 } else {
97 *levels -= 1;
98 false
99 }
100 }
101 _ => false,
102 }
103 }
104}
105
106impl Default for ControlFlow {
107 fn default() -> Self {
108 ControlFlow::Normal(ExecResult::success(""))
109 }
110}
111
112impl From<ExecResult> for ControlFlow {
113 fn from(result: ExecResult) -> Self {
114 ControlFlow::Normal(result)
115 }
116}
117
118#[cfg(test)]
119mod tests {
120 use super::*;
121
122 #[test]
123 fn test_normal_flow() {
124 let flow = ControlFlow::ok(ExecResult::success("test"));
125 assert!(flow.is_normal());
126 }
127
128 #[test]
129 fn test_break_decrement() {
130 let mut flow = ControlFlow::break_n(3);
131 assert!(!flow.decrement_level()); assert!(!flow.decrement_level()); assert!(flow.decrement_level()); }
135
136 #[test]
137 fn test_continue_decrement() {
138 let mut flow = ControlFlow::continue_n(2);
139 assert!(!flow.decrement_level()); assert!(flow.decrement_level()); }
142
143 #[test]
144 fn test_from_exec_result() {
145 let result = ExecResult::success("hello");
146 let flow: ControlFlow = result.into();
147 assert!(flow.is_normal());
148 }
149}