Line data Source code
1 : /* valaccodecontrolflowmodule.vala
2 : *
3 : * Copyright (C) 2006-2011 Jürg Billeter
4 : * Copyright (C) 2006-2008 Raffaele Sandrini
5 : *
6 : * This library is free software; you can redistribute it and/or
7 : * modify it under the terms of the GNU Lesser General Public
8 : * License as published by the Free Software Foundation; either
9 : * version 2.1 of the License, or (at your option) any later version.
10 :
11 : * This library is distributed in the hope that it will be useful,
12 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : * Lesser General Public License for more details.
15 :
16 : * You should have received a copy of the GNU Lesser General Public
17 : * License along with this library; if not, write to the Free Software
18 : * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 : *
20 : * Author:
21 : * Jürg Billeter <j@bitron.ch>
22 : * Raffaele Sandrini <raffaele@sandrini.ch>
23 : */
24 :
25 : using GLib;
26 :
27 2930 : public abstract class Vala.CCodeControlFlowModule : CCodeMethodModule {
28 4905 : public override void visit_if_statement (IfStatement stmt) {
29 4905 : ccode.open_if (get_cvalue (stmt.condition));
30 :
31 4905 : stmt.true_statement.emit (this);
32 :
33 4905 : if (stmt.false_statement != null) {
34 2411 : ccode.add_else ();
35 2411 : stmt.false_statement.emit (this);
36 : }
37 :
38 4905 : ccode.close ();
39 : }
40 :
41 56 : void visit_string_switch_statement (SwitchStatement stmt) {
42 : // we need a temporary variable to save the property value
43 28 : var temp_value = create_temp_value (stmt.expression.value_type, false, stmt);
44 628 : var ctemp = get_cvalue_ (temp_value);
45 :
46 28 : var cinit = new CCodeAssignment (ctemp, get_cvalue (stmt.expression));
47 28 : var czero = new CCodeConstant ("0");
48 :
49 28 : var free_call = new CCodeFunctionCall (new CCodeIdentifier ("g_free"));
50 28 : free_call.add_argument (ctemp);
51 :
52 28 : var cisnull = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, new CCodeConstant ("NULL"), ctemp);
53 28 : var cquark = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_string"));
54 28 : cquark.add_argument (ctemp);
55 :
56 28 : var ccond = new CCodeConditionalExpression (cisnull, new CCodeConstant ("0"), cquark);
57 :
58 28 : int label_temp_id = next_temp_var_id++;
59 :
60 28 : temp_value = create_temp_value (gquark_type, true, stmt);
61 :
62 28 : int label_count = 0;
63 :
64 310 : foreach (SwitchSection section in stmt.get_sections ()) {
65 152 : if (section.has_default_label ()) {
66 22 : continue;
67 : }
68 :
69 410 : foreach (SwitchLabel label in section.get_labels ()) {
70 140 : label.expression.emit (this);
71 140 : var cexpr = get_cvalue (label.expression);
72 :
73 140 : if (is_constant_ccode_expression (cexpr)) {
74 140 : var cname = "_tmp%d_label%d".printf (label_temp_id, label_count++);
75 :
76 140 : ccode.add_declaration (get_ccode_name (gquark_type), new CCodeVariableDeclarator (cname, czero), CCodeModifiers.STATIC);
77 : }
78 : }
79 : }
80 :
81 28 : ccode.add_expression (cinit);
82 :
83 56 : ctemp = get_cvalue_ (temp_value);
84 28 : cinit = new CCodeAssignment (ctemp, ccond);
85 :
86 28 : ccode.add_expression (cinit);
87 :
88 28 : if (stmt.expression.value_type.value_owned) {
89 : // free owned string
90 1 : ccode.add_expression (free_call);
91 : }
92 :
93 28 : SwitchSection default_section = null;
94 28 : label_count = 0;
95 :
96 28 : int n = 0;
97 :
98 310 : foreach (SwitchSection section in stmt.get_sections ()) {
99 152 : if (section.has_default_label ()) {
100 566 : default_section = section;
101 22 : continue;
102 : }
103 :
104 130 : CCodeBinaryExpression cor = null;
105 410 : foreach (SwitchLabel label in section.get_labels ()) {
106 140 : label.expression.emit (this);
107 140 : var cexpr = get_cvalue (label.expression);
108 :
109 280 : if (is_constant_ccode_expression (cexpr)) {
110 140 : var cname = new CCodeIdentifier ("_tmp%d_label%d".printf (label_temp_id, label_count++));
111 140 : var ccondition = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, czero, cname);
112 140 : var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_static_string"));
113 140 : cinit = new CCodeAssignment (cname, ccall);
114 :
115 140 : ccall.add_argument (cexpr);
116 :
117 140 : cexpr = new CCodeConditionalExpression (ccondition, cname, cinit);
118 : } else {
119 0 : var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_quark_from_string"));
120 0 : ccall.add_argument (cexpr);
121 0 : cexpr = ccall;
122 : }
123 :
124 140 : var ccmp = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, ctemp, cexpr);
125 :
126 140 : if (cor == null) {
127 270 : cor = ccmp;
128 : } else {
129 10 : cor = new CCodeBinaryExpression (CCodeBinaryOperator.OR, cor, ccmp);
130 : }
131 : }
132 :
133 130 : if (n > 0) {
134 102 : ccode.else_if (cor);
135 : } else {
136 28 : ccode.open_if (cor);
137 : }
138 :
139 130 : ccode.open_switch (new CCodeConstant ("0"));
140 130 : ccode.add_default ();
141 :
142 130 : section.emit (this);
143 :
144 130 : ccode.close ();
145 :
146 130 : n++;
147 : }
148 :
149 28 : if (default_section != null) {
150 22 : if (n > 0) {
151 22 : ccode.add_else ();
152 : }
153 :
154 22 : ccode.open_switch (new CCodeConstant ("0"));
155 22 : ccode.add_default ();
156 :
157 22 : default_section.emit (this);
158 :
159 22 : ccode.close ();
160 : }
161 :
162 28 : if (n > 0) {
163 28 : ccode.close ();
164 : }
165 : }
166 :
167 88 : public override void visit_switch_statement (SwitchStatement stmt) {
168 88 : if (stmt.expression.value_type.compatible (string_type)) {
169 28 : visit_string_switch_statement (stmt);
170 28 : return;
171 : }
172 :
173 60 : ccode.open_switch (get_cvalue (stmt.expression));
174 :
175 60 : bool has_default = false;
176 :
177 668 : foreach (SwitchSection section in stmt.get_sections ()) {
178 304 : if (section.has_default_label ()) {
179 35 : ccode.add_default ();
180 35 : has_default = true;
181 : }
182 304 : section.emit (this);
183 : }
184 :
185 60 : if (!has_default) {
186 : // silence C compiler
187 25 : ccode.add_default ();
188 25 : ccode.add_break ();
189 : }
190 :
191 60 : ccode.close ();
192 : }
193 :
194 531 : public override void visit_switch_label (SwitchLabel label) {
195 531 : if (((SwitchStatement) label.section.parent_node).expression.value_type.compatible (string_type)) {
196 : return;
197 : }
198 :
199 369 : if (label.expression != null) {
200 334 : label.expression.emit (this);
201 :
202 334 : visit_end_full_expression (label.expression);
203 :
204 334 : ccode.add_case (get_cvalue (label.expression));
205 : }
206 : }
207 :
208 465 : public override void visit_loop_statement (LoopStatement stmt) {
209 465 : if (context.profile == Profile.GOBJECT) {
210 465 : ccode.open_while (new CCodeConstant ("TRUE"));
211 : } else {
212 0 : cfile.add_include ("stdbool.h");
213 0 : ccode.open_while (new CCodeConstant ("true"));
214 : }
215 :
216 465 : stmt.body.emit (this);
217 :
218 465 : ccode.close ();
219 : }
220 :
221 318 : public override void visit_foreach_statement (ForeachStatement stmt) {
222 159 : ccode.open_block ();
223 :
224 159 : var collection_backup = stmt.collection_variable;
225 159 : var collection_type = collection_backup.variable_type;
226 :
227 159 : var array_type = collection_type as ArrayType;
228 113 : if (array_type != null) {
229 : // avoid assignment issues
230 113 : array_type.inline_allocated = false;
231 113 : array_type.fixed_length = false;
232 : }
233 :
234 159 : visit_local_variable (collection_backup);
235 159 : ccode.add_assignment (get_variable_cexpression (get_local_cname (collection_backup)), get_cvalue (stmt.collection));
236 :
237 159 : if (stmt.tree_can_fail && stmt.collection.tree_can_fail) {
238 : // exception handling
239 0 : add_simple_check (stmt.collection);
240 : }
241 :
242 272 : if (stmt.collection.value_type is ArrayType) {
243 226 : array_type = (ArrayType) stmt.collection.value_type;
244 :
245 113 : var array_len = get_variable_cexpression (get_array_length_cname (get_local_cname (collection_backup), 1));
246 :
247 : // store array length for use by _vala_array_free
248 113 : ccode.add_assignment (array_len, get_array_length_cexpression (stmt.collection));
249 :
250 113 : var iterator_variable = new LocalVariable (array_type.length_type.copy (), stmt.variable_name + "_it");
251 113 : visit_local_variable (iterator_variable);
252 113 : var it_name = get_local_cname (iterator_variable);
253 :
254 113 : var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, get_variable_cexpression (it_name), array_len);
255 :
256 113 : ccode.open_for (new CCodeAssignment (get_variable_cexpression (it_name), new CCodeConstant ("0")),
257 : ccond,
258 : new CCodeAssignment (get_variable_cexpression (it_name), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, get_variable_cexpression (it_name), new CCodeConstant ("1"))));
259 :
260 113 : CCodeExpression element_expr = new CCodeElementAccess (get_variable_cexpression (get_local_cname (collection_backup)), get_variable_cexpression (it_name));
261 :
262 113 : var element_type = array_type.element_type.copy ();
263 113 : element_type.value_owned = false;
264 226 : element_expr = get_cvalue_ (transform_value (new GLibValue (element_type, element_expr, true), stmt.type_reference, stmt));
265 :
266 113 : visit_local_variable (stmt.element_variable);
267 113 : ccode.add_assignment (get_variable_cexpression (get_local_cname (stmt.element_variable)), element_expr);
268 :
269 : // set array length for stacked arrays
270 113 : if (stmt.type_reference is ArrayType) {
271 0 : var inner_array_type = (ArrayType) stmt.type_reference;
272 0 : for (int dim = 1; dim <= inner_array_type.rank; dim++) {
273 0 : ccode.add_assignment (get_variable_cexpression (get_array_length_cname (get_local_cname (stmt.element_variable), dim)), new CCodeConstant ("-1"));
274 : }
275 : }
276 :
277 113 : stmt.body.emit (this);
278 :
279 113 : ccode.close ();
280 50 : } else if (stmt.collection.value_type.compatible (new ObjectType (garray_type))) {
281 : // iterating over a GArray
282 :
283 4 : var iterator_variable = new LocalVariable (uint_type.copy (), "%s_index".printf (stmt.variable_name));
284 4 : visit_local_variable (iterator_variable);
285 4 : var arr_index = get_variable_cname (get_local_cname (iterator_variable));
286 :
287 4 : var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, get_variable_cexpression (arr_index), new CCodeMemberAccess.pointer (get_variable_cexpression (get_local_cname (collection_backup)), "len"));
288 :
289 4 : ccode.open_for (new CCodeAssignment (get_variable_cexpression (arr_index), new CCodeConstant ("0")),
290 : ccond,
291 : new CCodeAssignment (get_variable_cexpression (arr_index), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, get_variable_cexpression (arr_index), new CCodeConstant ("1"))));
292 :
293 4 : var get_item = new CCodeFunctionCall (new CCodeIdentifier ("g_array_index"));
294 4 : get_item.add_argument (get_variable_cexpression (get_local_cname (collection_backup)));
295 4 : get_item.add_argument (new CCodeIdentifier (get_ccode_name (stmt.type_reference)));
296 4 : get_item.add_argument (get_variable_cexpression (arr_index));
297 :
298 4 : if (collection_type.get_type_arguments ().size != 1) {
299 0 : Report.error (stmt.source_reference, "internal error: missing generic type argument");
300 0 : stmt.error = true;
301 0 : return;
302 : }
303 :
304 4 : var element_type = collection_type.get_type_arguments ().get (0).copy ();
305 4 : element_type.value_owned = false;
306 8 : var element_expr = get_cvalue_ (transform_value (new GLibValue (element_type, get_item, true), stmt.type_reference, stmt));
307 :
308 4 : visit_local_variable (stmt.element_variable);
309 4 : ccode.add_assignment (get_variable_cexpression (get_local_cname (stmt.element_variable)), element_expr);
310 :
311 4 : stmt.body.emit (this);
312 :
313 4 : ccode.close ();
314 73 : } else if (stmt.collection.value_type.compatible (new ObjectType (glist_type)) || stmt.collection.value_type.compatible (new ObjectType (gslist_type))) {
315 : // iterating over a GList or GSList
316 :
317 31 : var iterator_variable = new LocalVariable (collection_type.copy (), stmt.variable_name + "_it");
318 31 : visit_local_variable (iterator_variable);
319 31 : var it_name = get_local_cname (iterator_variable);
320 :
321 31 : var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, get_variable_cexpression (it_name), new CCodeConstant ("NULL"));
322 :
323 31 : ccode.open_for (new CCodeAssignment (get_variable_cexpression (it_name), get_variable_cexpression (get_local_cname (collection_backup))),
324 : ccond,
325 : new CCodeAssignment (get_variable_cexpression (it_name), new CCodeMemberAccess.pointer (get_variable_cexpression (it_name), "next")));
326 :
327 31 : CCodeExpression element_expr = new CCodeMemberAccess.pointer (get_variable_cexpression (it_name), "data");
328 :
329 31 : if (collection_type.get_type_arguments ().size != 1) {
330 0 : Report.error (stmt.source_reference, "internal error: missing generic type argument");
331 0 : stmt.error = true;
332 0 : return;
333 : }
334 :
335 31 : var element_data_type = collection_type.get_type_arguments ().get (0).copy ();
336 31 : element_data_type.value_owned = false;
337 31 : element_expr = convert_from_generic_pointer (element_expr, element_data_type);
338 62 : element_expr = get_cvalue_ (transform_value (new GLibValue (element_data_type, element_expr), stmt.type_reference, stmt));
339 :
340 31 : visit_local_variable (stmt.element_variable);
341 31 : ccode.add_assignment (get_variable_cexpression (get_local_cname (stmt.element_variable)), element_expr);
342 :
343 31 : stmt.body.emit (this);
344 :
345 31 : ccode.close ();
346 17 : } else if (stmt.collection.value_type.compatible (new ObjectType ((Class) genericarray_type))) {
347 : // iterating over a GenericArray / GPtrArray
348 :
349 6 : var iterator_variable = new LocalVariable (uint_type.copy (), "%s_index".printf (stmt.variable_name));
350 6 : visit_local_variable (iterator_variable);
351 6 : var arr_index = get_variable_cname (get_local_cname (iterator_variable));
352 :
353 6 : var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, get_variable_cexpression (arr_index), new CCodeMemberAccess.pointer (get_variable_cexpression (get_local_cname (collection_backup)), "len"));
354 :
355 6 : ccode.open_for (new CCodeAssignment (get_variable_cexpression (arr_index), new CCodeConstant ("0")),
356 : ccond,
357 : new CCodeAssignment (get_variable_cexpression (arr_index), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, get_variable_cexpression (arr_index), new CCodeConstant ("1"))));
358 :
359 6 : var get_item = new CCodeFunctionCall (new CCodeIdentifier ("g_ptr_array_index"));
360 6 : get_item.add_argument (get_variable_cexpression (get_local_cname (collection_backup)));
361 6 : get_item.add_argument (get_variable_cexpression (arr_index));
362 :
363 6 : CCodeExpression element_expr = get_item;
364 6 : element_expr = convert_from_generic_pointer (element_expr, stmt.element_variable.variable_type);
365 :
366 6 : if (stmt.type_reference.value_owned) {
367 6 : element_expr = get_cvalue_ (copy_value (new GLibValue (stmt.type_reference, element_expr), stmt.element_variable));
368 : }
369 :
370 6 : visit_local_variable (stmt.element_variable);
371 6 : ccode.add_assignment (get_variable_cexpression (get_local_cname (stmt.element_variable)), element_expr);
372 :
373 6 : stmt.body.emit (this);
374 :
375 6 : ccode.close ();
376 7 : } else if (stmt.collection.value_type.compatible (new ObjectType (gvaluearray_type))) {
377 : // iterating over a GValueArray
378 :
379 2 : var iterator_variable = new LocalVariable (uint_type.copy (), "%s_index".printf (stmt.variable_name));
380 2 : visit_local_variable (iterator_variable);
381 2 : var arr_index = get_variable_cname (get_local_cname (iterator_variable));
382 :
383 2 : var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.LESS_THAN, get_variable_cexpression (arr_index), new CCodeMemberAccess.pointer (get_variable_cexpression (get_local_cname (collection_backup)), "n_values"));
384 :
385 2 : ccode.open_for (new CCodeAssignment (get_variable_cexpression (arr_index), new CCodeConstant ("0")),
386 : ccond,
387 : new CCodeAssignment (get_variable_cexpression (arr_index), new CCodeBinaryExpression (CCodeBinaryOperator.PLUS, get_variable_cexpression (arr_index), new CCodeConstant ("1"))));
388 :
389 2 : var get_item = new CCodeFunctionCall (new CCodeIdentifier ("g_value_array_get_nth"));
390 2 : get_item.add_argument (get_variable_cexpression (get_local_cname (collection_backup)));
391 2 : get_item.add_argument (get_variable_cexpression (arr_index));
392 :
393 2 : CCodeExpression element_expr = new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, get_item);
394 :
395 2 : if (stmt.type_reference.value_owned) {
396 2 : element_expr = get_cvalue_ (copy_value (new GLibValue (stmt.type_reference, element_expr), new StructValueType (gvalue_type)));
397 : }
398 :
399 2 : visit_local_variable (stmt.element_variable);
400 2 : ccode.add_assignment (get_variable_cexpression (get_local_cname (stmt.element_variable)), element_expr);
401 :
402 2 : stmt.body.emit (this);
403 :
404 2 : ccode.close ();
405 5 : } else if (stmt.collection.value_type.compatible (new ObjectType (gsequence_type))) {
406 : // iterating over a GSequence
407 :
408 2 : var iterator_variable = new LocalVariable (new ObjectType (gsequence_iter_type), "%s_iter".printf (stmt.variable_name));
409 2 : visit_local_variable (iterator_variable);
410 2 : var sequence_iter = get_variable_cname (get_local_cname (iterator_variable));
411 :
412 2 : var ccond_is_end = new CCodeFunctionCall (new CCodeIdentifier ("g_sequence_iter_is_end"));
413 2 : ccond_is_end.add_argument (get_variable_cexpression (sequence_iter));
414 2 : var ccond = new CCodeUnaryExpression (CCodeUnaryOperator.LOGICAL_NEGATION, ccond_is_end);
415 2 : var cbegin = new CCodeFunctionCall (new CCodeIdentifier ("g_sequence_get_begin_iter"));
416 2 : cbegin.add_argument (get_variable_cexpression (get_local_cname (collection_backup)));
417 2 : var cnext = new CCodeFunctionCall (new CCodeIdentifier ("g_sequence_iter_next"));
418 2 : cnext.add_argument (get_variable_cexpression (sequence_iter));
419 :
420 2 : ccode.open_for (new CCodeAssignment (get_variable_cexpression (sequence_iter), cbegin),
421 : ccond,
422 : new CCodeAssignment (get_variable_cexpression (sequence_iter), cnext));
423 :
424 2 : var get_item = new CCodeFunctionCall (new CCodeIdentifier ("g_sequence_get"));
425 2 : get_item.add_argument (get_variable_cexpression (sequence_iter));
426 :
427 2 : CCodeExpression element_expr = get_item;
428 :
429 2 : if (collection_type.get_type_arguments ().size != 1) {
430 0 : Report.error (stmt.source_reference, "internal error: missing generic type argument");
431 0 : stmt.error = true;
432 0 : return;
433 : }
434 :
435 2 : var element_type = collection_type.get_type_arguments ().get (0).copy ();
436 2 : element_type.value_owned = false;
437 2 : element_expr = convert_from_generic_pointer (element_expr, element_type);
438 4 : element_expr = get_cvalue_ (transform_value (new GLibValue (element_type, element_expr), stmt.type_reference, stmt));
439 :
440 2 : visit_local_variable (stmt.element_variable);
441 2 : ccode.add_assignment (get_variable_cexpression (get_local_cname (stmt.element_variable)), element_expr);
442 :
443 2 : stmt.body.emit (this);
444 :
445 2 : ccode.close ();
446 2 : } else if (stmt.collection.value_type.compatible (string_type)) {
447 : // iterating over a string
448 :
449 1 : var validate = new CCodeFunctionCall (new CCodeIdentifier ("g_utf8_validate"));
450 1 : validate.add_argument (get_variable_cexpression (get_local_cname (collection_backup)));
451 1 : validate.add_argument (new CCodeConstant ("-1"));
452 1 : validate.add_argument (new CCodeConstant ("NULL"));
453 1 : var cassert = new CCodeFunctionCall (new CCodeIdentifier ("_vala_warn_if_fail"));
454 1 : cassert.add_argument (validate);
455 1 : cassert.add_argument (new CCodeConstant ("\"Invalid UTF-8 string\""));
456 1 : requires_assert = true;
457 1 : ccode.add_expression (cassert);
458 :
459 1 : var iterator_variable = new LocalVariable (collection_type, "%s_iter".printf (stmt.variable_name));
460 1 : visit_local_variable (iterator_variable);
461 1 : var string_iter = get_variable_cname (get_local_cname (iterator_variable));
462 :
463 1 : var ccond = new CCodeBinaryExpression (CCodeBinaryOperator.INEQUALITY, new CCodeUnaryExpression (CCodeUnaryOperator.POINTER_INDIRECTION, get_variable_cexpression (string_iter)), new CCodeConstant ("'\\0'"));
464 1 : var next_char_call = new CCodeFunctionCall (new CCodeIdentifier ("g_utf8_next_char"));
465 1 : next_char_call.add_argument (get_variable_cexpression (string_iter));
466 :
467 1 : ccode.open_for (new CCodeAssignment (get_variable_cexpression (string_iter), get_variable_cexpression (collection_backup.name)),
468 : ccond,
469 : new CCodeAssignment (get_variable_cexpression (string_iter), next_char_call));
470 :
471 1 : var element_expr = new CCodeFunctionCall (new CCodeIdentifier ("g_utf8_get_char"));
472 1 : element_expr.add_argument (get_variable_cexpression (string_iter));
473 :
474 1 : visit_local_variable (stmt.element_variable);
475 1 : ccode.add_assignment (get_variable_cexpression (get_local_cname (stmt.element_variable)), element_expr);
476 :
477 1 : stmt.body.emit (this);
478 :
479 1 : ccode.close ();
480 : } else {
481 0 : Report.error (stmt.source_reference, "internal error: unsupported collection type");
482 0 : stmt.error = true;
483 0 : return;
484 : }
485 :
486 477 : foreach (LocalVariable local in stmt.get_local_variables ()) {
487 159 : if (requires_destroy (local.variable_type)) {
488 15 : ccode.add_expression (destroy_local (local));
489 : }
490 : }
491 :
492 159 : ccode.close ();
493 : }
494 :
495 808 : public override void visit_break_statement (BreakStatement stmt) {
496 808 : append_local_free (current_symbol, stmt);
497 :
498 808 : ccode.add_break ();
499 : }
500 :
501 41 : public override void visit_continue_statement (ContinueStatement stmt) {
502 41 : append_local_free (current_symbol, stmt);
503 :
504 41 : ccode.add_continue ();
505 : }
506 : }
507 :
|