@@ -7,21 +7,27 @@ pub fn interpret(ast: Vec<ASTNode>, is_verbose: bool) -> Option<Value> {
77 let mut result = None ;
88
99 for node in ast {
10- result = Some ( interpret_node ( & node, & mut symbol_table, is_verbose) ) ;
10+ result = Some ( interpret_node ( & node, & mut symbol_table, is_verbose, false ) ) ;
11+ if let Value :: Break = result. as_ref ( ) . unwrap ( ) {
12+ panic ! ( "Break statement outside of loop" ) ;
13+ }
14+ if let Value :: Continue = result. as_ref ( ) . unwrap ( ) {
15+ panic ! ( "Continue statement outside of loop" ) ;
16+ }
1117 }
1218
1319 result
1420}
1521
16- fn interpret_node ( node : & ASTNode , symbol_table : & mut HashMap < String , ( Value , bool ) > , is_verbose : bool ) -> Value {
22+ fn interpret_node ( node : & ASTNode , symbol_table : & mut HashMap < String , ( Value , bool ) > , is_verbose : bool , in_loop : bool ) -> Value {
1723 match node {
1824 ASTNode :: Number ( val) => Value :: Number ( * val) ,
1925 ASTNode :: String ( val) => Value :: String ( val. clone ( ) ) ,
2026 ASTNode :: Boolean ( val) => Value :: Boolean ( * val) ,
2127 ASTNode :: Null => Value :: Null ,
2228 ASTNode :: BinaryOp ( left, op, right) => {
23- let left_val = interpret_node ( left, symbol_table, is_verbose) ;
24- let right_val = interpret_node ( right, symbol_table, is_verbose) ;
29+ let left_val = interpret_node ( left, symbol_table, is_verbose, in_loop ) ;
30+ let right_val = interpret_node ( right, symbol_table, is_verbose, in_loop ) ;
2531 match ( left_val, right_val) {
2632 ( Value :: Number ( l) , Value :: Number ( r) ) => {
2733 match op {
@@ -64,7 +70,7 @@ fn interpret_node(node: &ASTNode, symbol_table: &mut HashMap<String, (Value, boo
6470 }
6571 } ,
6672 ASTNode :: Print ( expr) => {
67- let value = interpret_node ( expr, symbol_table, is_verbose) ;
73+ let value = interpret_node ( expr, symbol_table, is_verbose, in_loop ) ;
6874 if is_verbose {
6975 println ! ( "call print({:?})" , value) ;
7076 } else {
@@ -82,7 +88,7 @@ fn interpret_node(node: &ASTNode, symbol_table: &mut HashMap<String, (Value, boo
8288 } ,
8389 ASTNode :: Var ( name, expr, is_mutable) => {
8490 let value = if let Some ( expr) = expr {
85- interpret_node ( expr, symbol_table, is_verbose)
91+ interpret_node ( expr, symbol_table, is_verbose, in_loop )
8692 } else {
8793 Value :: Null
8894 } ;
@@ -91,9 +97,9 @@ fn interpret_node(node: &ASTNode, symbol_table: &mut HashMap<String, (Value, boo
9197 println ! ( "declare variable {} with {:?}" , name, value) ;
9298 }
9399 Value :: Null
94- }
100+ } ,
95101 ASTNode :: Assign ( name, expr) => {
96- let value = interpret_node ( expr, symbol_table, is_verbose) ;
102+ let value = interpret_node ( expr, symbol_table, is_verbose, in_loop ) ;
97103 if let Some ( ( _, is_mutable) ) = symbol_table. get ( name) {
98104 if !is_mutable {
99105 panic ! ( "Cannot assign to immutable variable: {}" , name) ;
@@ -106,17 +112,17 @@ fn interpret_node(node: &ASTNode, symbol_table: &mut HashMap<String, (Value, boo
106112 panic ! ( "Variable not declared: {}" , name) ;
107113 }
108114 Value :: Null
109- }
115+ } ,
110116 ASTNode :: Identifier ( name) => {
111117 if let Some ( ( value, _) ) = symbol_table. get ( name) {
112118 value. clone ( )
113119 } else {
114120 panic ! ( "Variable not found: {}" , name) ;
115121 }
116- }
122+ } ,
117123 ASTNode :: Index ( expr, index) => {
118- let value = interpret_node ( expr, symbol_table, is_verbose) ;
119- let index = interpret_node ( index, symbol_table, is_verbose) ;
124+ let value = interpret_node ( expr, symbol_table, is_verbose, in_loop ) ;
125+ let index = interpret_node ( index, symbol_table, is_verbose, in_loop ) ;
120126 match ( value, index) {
121127 ( Value :: String ( s) , Value :: Number ( i) ) => {
122128 if i < 0 || i >= s. len ( ) as i32 {
@@ -126,9 +132,9 @@ fn interpret_node(node: &ASTNode, symbol_table: &mut HashMap<String, (Value, boo
126132 }
127133 _ => panic ! ( "Invalid indexing operation" ) ,
128134 }
129- }
135+ } ,
130136 ASTNode :: Type ( expr) => {
131- let value = interpret_node ( expr, symbol_table, is_verbose) ;
137+ let value = interpret_node ( expr, symbol_table, is_verbose, in_loop ) ;
132138 let type_str = match value {
133139 Value :: Number ( _) => "int" ,
134140 Value :: String ( _) => "str" ,
@@ -142,21 +148,27 @@ fn interpret_node(node: &ASTNode, symbol_table: &mut HashMap<String, (Value, boo
142148 println ! ( "call type({:?}) = {}" , value, type_str) ;
143149 }
144150 Value :: Type ( type_str. to_string ( ) )
145- }
151+ } ,
146152 ASTNode :: TypeLiteral ( type_name) => Value :: Type ( type_name. clone ( ) ) ,
147153 ASTNode :: If ( condition, if_block, elif_blocks, else_block) => {
148- let condition_value = interpret_node ( condition, symbol_table, is_verbose) ;
154+ let condition_value = interpret_node ( condition, symbol_table, is_verbose, in_loop ) ;
149155 if let Value :: Boolean ( true ) = condition_value {
150156 for stmt in if_block {
151- interpret_node ( stmt, symbol_table, is_verbose) ;
157+ let result = interpret_node ( stmt, symbol_table, is_verbose, in_loop) ;
158+ if matches ! ( result, Value :: Break | Value :: Continue ) {
159+ return result;
160+ }
152161 }
153162 } else {
154163 let mut executed = false ;
155164 for ( elif_condition, elif_statements) in elif_blocks {
156- let elif_condition_value = interpret_node ( & elif_condition, symbol_table, is_verbose) ;
165+ let elif_condition_value = interpret_node ( elif_condition, symbol_table, is_verbose, in_loop ) ;
157166 if let Value :: Boolean ( true ) = elif_condition_value {
158167 for stmt in elif_statements {
159- interpret_node ( stmt, symbol_table, is_verbose) ;
168+ let result = interpret_node ( stmt, symbol_table, is_verbose, in_loop) ;
169+ if matches ! ( result, Value :: Break | Value :: Continue ) {
170+ return result;
171+ }
160172 }
161173 executed = true ;
162174 break ;
@@ -165,43 +177,48 @@ fn interpret_node(node: &ASTNode, symbol_table: &mut HashMap<String, (Value, boo
165177 if !executed {
166178 if let Some ( else_statements) = else_block {
167179 for stmt in else_statements {
168- interpret_node ( stmt, symbol_table, is_verbose) ;
180+ let result = interpret_node ( stmt, symbol_table, is_verbose, in_loop) ;
181+ if matches ! ( result, Value :: Break | Value :: Continue ) {
182+ return result;
183+ }
169184 }
170185 }
171186 }
172187 }
173188 Value :: Null
174189 } ,
175190 ASTNode :: For ( init, condition, update, body) => {
176- interpret_node ( init, symbol_table, is_verbose) ;
191+ interpret_node ( init, symbol_table, is_verbose, true ) ;
177192 loop {
178- let cond_value = interpret_node ( condition, symbol_table, is_verbose) ;
193+ let cond_value = interpret_node ( condition, symbol_table, is_verbose, true ) ;
179194 if let Value :: Boolean ( false ) = cond_value {
180195 break ;
181196 }
182197
183- let mut should_break = false ;
184198 for stmt in body {
185- let result = interpret_node ( stmt, symbol_table, is_verbose) ;
199+ let result = interpret_node ( stmt, symbol_table, is_verbose, true ) ;
186200 match result {
187- Value :: Break => {
188- should_break = true ;
189- break ;
190- } ,
201+ Value :: Break => return Value :: Null ,
191202 Value :: Continue => break ,
192203 _ => { }
193204 }
194205 }
195206
196- if should_break {
197- break ;
198- }
199-
200- interpret_node ( update, symbol_table, is_verbose) ;
207+ interpret_node ( update, symbol_table, is_verbose, true ) ;
201208 }
202209 Value :: Null
203210 } ,
204- ASTNode :: Break => Value :: Break ,
205- ASTNode :: Continue => Value :: Continue ,
211+ ASTNode :: Break => {
212+ if !in_loop {
213+ panic ! ( "Break statement outside of loop" ) ;
214+ }
215+ Value :: Break
216+ } ,
217+ ASTNode :: Continue => {
218+ if !in_loop {
219+ panic ! ( "Continue statement outside of loop" ) ;
220+ }
221+ Value :: Continue
222+ } ,
206223 }
207224}
0 commit comments