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, result: ExecResult },
29}
30
31impl ControlFlow {
32 pub fn ok(result: ExecResult) -> Self {
34 ControlFlow::Normal(result)
35 }
36
37 pub fn break_one() -> Self {
39 ControlFlow::Break {
40 levels: 1,
41 result: ExecResult::success(""),
42 }
43 }
44
45 pub fn break_n(n: usize) -> Self {
47 ControlFlow::Break {
48 levels: n,
49 result: ExecResult::success(""),
50 }
51 }
52
53 pub fn continue_one() -> Self {
55 ControlFlow::Continue {
56 levels: 1,
57 result: ExecResult::success(""),
58 }
59 }
60
61 pub fn continue_n(n: usize) -> Self {
63 ControlFlow::Continue {
64 levels: n,
65 result: ExecResult::success(""),
66 }
67 }
68
69 pub fn return_value(value: ExecResult) -> Self {
71 ControlFlow::Return { value }
72 }
73
74 pub fn exit_code(code: i64) -> Self {
79 ControlFlow::Exit {
80 code,
81 result: ExecResult::success(""),
82 }
83 }
84
85 pub fn is_normal(&self) -> bool {
87 matches!(self, ControlFlow::Normal(_))
88 }
89
90 pub fn into_result(self) -> Option<ExecResult> {
92 match self {
93 ControlFlow::Normal(r) => Some(r),
94 _ => None,
95 }
96 }
97
98 pub fn decrement_level(&mut self) -> bool {
103 match self {
104 ControlFlow::Break { levels, .. } | ControlFlow::Continue { levels, .. } => {
105 if *levels <= 1 {
106 true
107 } else {
108 *levels -= 1;
109 false
110 }
111 }
112 _ => false,
113 }
114 }
115}
116
117impl Default for ControlFlow {
118 fn default() -> Self {
119 ControlFlow::Normal(ExecResult::success(""))
120 }
121}
122
123impl From<ExecResult> for ControlFlow {
124 fn from(result: ExecResult) -> Self {
125 ControlFlow::Normal(result)
126 }
127}
128
129#[cfg(test)]
130mod tests {
131 use super::*;
132
133 #[test]
134 fn test_normal_flow() {
135 let flow = ControlFlow::ok(ExecResult::success("test"));
136 assert!(flow.is_normal());
137 }
138
139 #[test]
140 fn test_break_decrement() {
141 let mut flow = ControlFlow::break_n(3);
142 assert!(!flow.decrement_level()); assert!(!flow.decrement_level()); assert!(flow.decrement_level()); }
146
147 #[test]
148 fn test_continue_decrement() {
149 let mut flow = ControlFlow::continue_n(2);
150 assert!(!flow.decrement_level()); assert!(flow.decrement_level()); }
153
154 #[test]
155 fn test_from_exec_result() {
156 let result = ExecResult::success("hello");
157 let flow: ControlFlow = result.into();
158 assert!(flow.is_normal());
159 }
160}