kaish_kernel/interpreter/
control_flow.rs1use super::result::ExecResult;
7
8#[derive(Debug, Clone)]
13#[non_exhaustive]
14pub enum ControlFlow {
15 Normal(ExecResult),
17 Break { levels: usize, result: ExecResult },
19 Continue { levels: usize, result: ExecResult },
21 Return { value: ExecResult },
23 Exit { code: i64, result: ExecResult },
30}
31
32impl ControlFlow {
33 pub fn ok(result: ExecResult) -> Self {
35 ControlFlow::Normal(result)
36 }
37
38 pub fn break_one() -> Self {
40 ControlFlow::Break {
41 levels: 1,
42 result: ExecResult::success(""),
43 }
44 }
45
46 pub fn break_n(n: usize) -> Self {
48 ControlFlow::Break {
49 levels: n,
50 result: ExecResult::success(""),
51 }
52 }
53
54 pub fn continue_one() -> Self {
56 ControlFlow::Continue {
57 levels: 1,
58 result: ExecResult::success(""),
59 }
60 }
61
62 pub fn continue_n(n: usize) -> Self {
64 ControlFlow::Continue {
65 levels: n,
66 result: ExecResult::success(""),
67 }
68 }
69
70 pub fn return_value(value: ExecResult) -> Self {
72 ControlFlow::Return { value }
73 }
74
75 pub fn exit_code(code: i64) -> Self {
80 ControlFlow::Exit {
81 code,
82 result: ExecResult::success(""),
83 }
84 }
85
86 pub fn is_normal(&self) -> bool {
88 matches!(self, ControlFlow::Normal(_))
89 }
90
91 pub fn into_result(self) -> Option<ExecResult> {
93 match self {
94 ControlFlow::Normal(r) => Some(r),
95 _ => None,
96 }
97 }
98
99 pub fn decrement_level(&mut self) -> bool {
104 match self {
105 ControlFlow::Break { levels, .. } | ControlFlow::Continue { levels, .. } => {
106 if *levels <= 1 {
107 true
108 } else {
109 *levels -= 1;
110 false
111 }
112 }
113 _ => false,
114 }
115 }
116}
117
118impl Default for ControlFlow {
119 fn default() -> Self {
120 ControlFlow::Normal(ExecResult::success(""))
121 }
122}
123
124impl From<ExecResult> for ControlFlow {
125 fn from(result: ExecResult) -> Self {
126 ControlFlow::Normal(result)
127 }
128}
129
130#[cfg(test)]
131mod tests {
132 use super::*;
133
134 #[test]
135 fn test_normal_flow() {
136 let flow = ControlFlow::ok(ExecResult::success("test"));
137 assert!(flow.is_normal());
138 }
139
140 #[test]
141 fn test_break_decrement() {
142 let mut flow = ControlFlow::break_n(3);
143 assert!(!flow.decrement_level()); assert!(!flow.decrement_level()); assert!(flow.decrement_level()); }
147
148 #[test]
149 fn test_continue_decrement() {
150 let mut flow = ControlFlow::continue_n(2);
151 assert!(!flow.decrement_level()); assert!(flow.decrement_level()); }
154
155 #[test]
156 fn test_from_exec_result() {
157 let result = ExecResult::success("hello");
158 let flow: ControlFlow = result.into();
159 assert!(flow.is_normal());
160 }
161}