Mercurial > octave
comparison libinterp/parse-tree/pt-eval.cc @ 22196:dd992fd74fce
put parser, lexer, and evaluator in namespace; interpreter now owns evaluator
* oct-parse.in.yy, parse.h: Move parser classes to octave namespace.
* lex.ll, lex.h: Move lexer classes to octave namespace.
* pt-eval.h, pt-eval.cc: Move evaluator class to octave namespace.
Don't define global current evaluator pointer here.
* debug.cc, error.cc, input.cc, input.h, ls-mat-ascii.cc, pt-jit.cc,
sighandlers.cc, utils.cc, variables.cc, ov-usr-fcn.cc, pt-assign.cc,
pt-exp.h, pt-id.cc: Update for namespaces.
* interpreter.cc, interpreter.h (current_evaluator): New global var.
(interpreter::m_evaluator): New data member.
(interpreter::~interpreter): Delete evaluator.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Tue, 12 Jul 2016 14:28:07 -0400 |
parents | 5d4a286061c8 |
children | bac0d6f07a3e |
comparison
equal
deleted
inserted
replaced
22195:93ed9396f2c3 | 22196:dd992fd74fce |
---|---|
47 #include "unwind-prot.h" | 47 #include "unwind-prot.h" |
48 | 48 |
49 //FIXME: This should be part of tree_evaluator | 49 //FIXME: This should be part of tree_evaluator |
50 #include "pt-jit.h" | 50 #include "pt-jit.h" |
51 | 51 |
52 static tree_evaluator std_evaluator; | |
53 | |
54 tree_evaluator *current_evaluator = &std_evaluator; | |
55 | |
56 int tree_evaluator::dbstep_flag = 0; | |
57 | |
58 size_t tree_evaluator::current_frame = 0; | |
59 | |
60 bool tree_evaluator::debug_mode = false; | |
61 | |
62 bool tree_evaluator::quiet_breakpoint_flag = false; | |
63 | |
64 tree_evaluator::stmt_list_type tree_evaluator::statement_context | |
65 = tree_evaluator::other; | |
66 | |
67 bool tree_evaluator::in_loop_command = false; | |
68 | |
69 // Maximum nesting level for functions, scripts, or sourced files called | 52 // Maximum nesting level for functions, scripts, or sourced files called |
70 // recursively. | 53 // recursively. |
71 int Vmax_recursion_depth = 256; | 54 int Vmax_recursion_depth = 256; |
72 | 55 |
73 // If TRUE, turn off printing of results in functions (as if a | 56 // If TRUE, turn off printing of results in functions (as if a |
74 // semicolon has been appended to each statement). | 57 // semicolon has been appended to each statement). |
75 static bool Vsilent_functions = false; | 58 static bool Vsilent_functions = false; |
76 | 59 |
77 // Normal evaluator. | 60 namespace octave |
78 | |
79 void | |
80 tree_evaluator::visit_anon_fcn_handle (tree_anon_fcn_handle&) | |
81 { | 61 { |
82 panic_impossible (); | 62 int tree_evaluator::dbstep_flag = 0; |
83 } | 63 |
84 | 64 size_t tree_evaluator::current_frame = 0; |
85 void | 65 |
86 tree_evaluator::visit_argument_list (tree_argument_list&) | 66 bool tree_evaluator::debug_mode = false; |
87 { | 67 |
88 panic_impossible (); | 68 bool tree_evaluator::quiet_breakpoint_flag = false; |
89 } | 69 |
90 | 70 tree_evaluator::stmt_list_type tree_evaluator::statement_context |
91 void | 71 = tree_evaluator::other; |
92 tree_evaluator::visit_binary_expression (tree_binary_expression&) | 72 |
93 { | 73 bool tree_evaluator::in_loop_command = false; |
94 panic_impossible (); | 74 |
95 } | 75 // Normal evaluator. |
96 | 76 |
97 void | 77 void |
98 tree_evaluator::visit_break_command (tree_break_command& cmd) | 78 tree_evaluator::visit_anon_fcn_handle (tree_anon_fcn_handle&) |
99 { | 79 { |
100 if (debug_mode) | 80 panic_impossible (); |
101 do_breakpoint (cmd.is_breakpoint (true)); | 81 } |
102 | 82 |
103 if (statement_context == function || statement_context == script | 83 void |
104 || in_loop_command) | 84 tree_evaluator::visit_argument_list (tree_argument_list&) |
105 tree_break_command::breaking = 1; | 85 { |
106 } | 86 panic_impossible (); |
107 | 87 } |
108 void | 88 |
109 tree_evaluator::visit_colon_expression (tree_colon_expression&) | 89 void |
110 { | 90 tree_evaluator::visit_binary_expression (tree_binary_expression&) |
111 panic_impossible (); | 91 { |
112 } | 92 panic_impossible (); |
113 | 93 } |
114 void | 94 |
115 tree_evaluator::visit_continue_command (tree_continue_command& cmd) | 95 void |
116 { | 96 tree_evaluator::visit_break_command (tree_break_command& cmd) |
117 if (debug_mode) | 97 { |
118 do_breakpoint (cmd.is_breakpoint (true)); | 98 if (debug_mode) |
119 | 99 do_breakpoint (cmd.is_breakpoint (true)); |
120 if (statement_context == function || statement_context == script | 100 |
121 || in_loop_command) | 101 if (statement_context == function || statement_context == script |
122 tree_continue_command::continuing = 1; | 102 || in_loop_command) |
123 } | 103 tree_break_command::breaking = 1; |
124 | 104 } |
125 void | 105 |
126 tree_evaluator::reset_debug_state (void) | 106 void |
127 { | 107 tree_evaluator::visit_colon_expression (tree_colon_expression&) |
128 debug_mode = bp_table::have_breakpoints () || Vdebugging; | 108 { |
129 | 109 panic_impossible (); |
130 dbstep_flag = 0; | 110 } |
131 } | 111 |
132 | 112 void |
133 bool | 113 tree_evaluator::visit_continue_command (tree_continue_command& cmd) |
134 tree_evaluator::statement_printing_enabled (void) | 114 { |
135 { | 115 if (debug_mode) |
136 return ! (Vsilent_functions && (statement_context == function | 116 do_breakpoint (cmd.is_breakpoint (true)); |
137 || statement_context == script)); | 117 |
118 if (statement_context == function || statement_context == script | |
119 || in_loop_command) | |
120 tree_continue_command::continuing = 1; | |
121 } | |
122 | |
123 void | |
124 tree_evaluator::reset_debug_state (void) | |
125 { | |
126 debug_mode = bp_table::have_breakpoints () || Vdebugging; | |
127 | |
128 dbstep_flag = 0; | |
129 } | |
130 | |
131 bool | |
132 tree_evaluator::statement_printing_enabled (void) | |
133 { | |
134 return ! (Vsilent_functions && (statement_context == function | |
135 || statement_context == script)); | |
136 } | |
138 } | 137 } |
139 | 138 |
140 static inline void | 139 static inline void |
141 do_global_init (tree_decl_elt& elt) | 140 do_global_init (tree_decl_elt& elt) |
142 { | 141 { |
189 ult.assign (octave_value::op_asn_eq, init_val); | 188 ult.assign (octave_value::op_asn_eq, init_val); |
190 } | 189 } |
191 } | 190 } |
192 } | 191 } |
193 | 192 |
194 void | 193 namespace octave |
195 tree_evaluator::do_decl_init_list (decl_elt_init_fcn fcn, | |
196 tree_decl_init_list *init_list) | |
197 { | 194 { |
198 if (init_list) | 195 void |
199 { | 196 tree_evaluator::do_decl_init_list (decl_elt_init_fcn fcn, |
200 for (tree_decl_init_list::iterator p = init_list->begin (); | 197 tree_decl_init_list *init_list) |
201 p != init_list->end (); p++) | 198 { |
202 { | 199 if (init_list) |
203 tree_decl_elt *elt = *p; | 200 { |
204 | 201 for (tree_decl_init_list::iterator p = init_list->begin (); |
205 fcn (*elt); | 202 p != init_list->end (); p++) |
206 } | 203 { |
207 } | 204 tree_decl_elt *elt = *p; |
208 } | 205 |
209 | 206 fcn (*elt); |
210 void | 207 } |
211 tree_evaluator::visit_global_command (tree_global_command& cmd) | 208 } |
212 { | 209 } |
213 if (debug_mode) | 210 |
214 do_breakpoint (cmd.is_breakpoint (true)); | 211 void |
215 | 212 tree_evaluator::visit_global_command (tree_global_command& cmd) |
216 do_decl_init_list (do_global_init, cmd.initializer_list ()); | 213 { |
217 } | 214 if (debug_mode) |
218 | 215 do_breakpoint (cmd.is_breakpoint (true)); |
219 void | 216 |
220 tree_evaluator::visit_persistent_command (tree_persistent_command& cmd) | 217 do_decl_init_list (do_global_init, cmd.initializer_list ()); |
221 { | 218 } |
222 if (debug_mode) | 219 |
223 do_breakpoint (cmd.is_breakpoint (true)); | 220 void |
224 | 221 tree_evaluator::visit_persistent_command (tree_persistent_command& cmd) |
225 do_decl_init_list (do_static_init, cmd.initializer_list ()); | 222 { |
226 } | 223 if (debug_mode) |
227 | 224 do_breakpoint (cmd.is_breakpoint (true)); |
228 void | 225 |
229 tree_evaluator::visit_decl_elt (tree_decl_elt&) | 226 do_decl_init_list (do_static_init, cmd.initializer_list ()); |
230 { | 227 } |
231 panic_impossible (); | 228 |
232 } | 229 void |
233 | 230 tree_evaluator::visit_decl_elt (tree_decl_elt&) |
234 #if 0 | 231 { |
235 bool | 232 panic_impossible (); |
236 tree_decl_elt::eval (void) | 233 } |
237 { | 234 |
238 bool retval = false; | 235 void |
239 | 236 tree_evaluator::visit_decl_init_list (tree_decl_init_list&) |
240 if (id && expr) | 237 { |
241 { | 238 panic_impossible (); |
242 octave_lvalue ult = id->lvalue (); | 239 } |
243 | |
244 octave_value init_val = expr->rvalue1 (); | |
245 | |
246 ult.assign (octave_value::op_asn_eq, init_val); | |
247 | |
248 retval = true; | |
249 } | |
250 | |
251 return retval; | |
252 } | |
253 #endif | |
254 | |
255 void | |
256 tree_evaluator::visit_decl_init_list (tree_decl_init_list&) | |
257 { | |
258 panic_impossible (); | |
259 } | 240 } |
260 | 241 |
261 // Decide if it's time to quit a for or while loop. | 242 // Decide if it's time to quit a for or while loop. |
262 static inline bool | 243 static inline bool |
263 quit_loop_now (void) | 244 quit_loop_now (void) |
277 tree_break_command::breaking--; | 258 tree_break_command::breaking--; |
278 | 259 |
279 return quit; | 260 return quit; |
280 } | 261 } |
281 | 262 |
282 void | 263 namespace octave |
283 tree_evaluator::visit_simple_for_command (tree_simple_for_command& cmd) | |
284 { | 264 { |
285 if (debug_mode) | 265 void |
286 do_breakpoint (cmd.is_breakpoint (true)); | 266 tree_evaluator::visit_simple_for_command (tree_simple_for_command& cmd) |
287 | 267 { |
288 // FIXME: need to handle PARFOR loops here using cmd.in_parallel () | 268 if (debug_mode) |
289 // and cmd.maxproc_expr (); | 269 do_breakpoint (cmd.is_breakpoint (true)); |
290 | 270 |
291 octave::unwind_protect frame; | 271 // FIXME: need to handle PARFOR loops here using cmd.in_parallel () |
292 | 272 // and cmd.maxproc_expr (); |
293 frame.protect_var (in_loop_command); | 273 |
294 | 274 octave::unwind_protect frame; |
295 in_loop_command = true; | 275 |
296 | 276 frame.protect_var (in_loop_command); |
297 tree_expression *expr = cmd.control_expr (); | 277 |
298 | 278 in_loop_command = true; |
299 octave_value rhs = expr->rvalue1 (); | 279 |
280 tree_expression *expr = cmd.control_expr (); | |
281 | |
282 octave_value rhs = expr->rvalue1 (); | |
300 | 283 |
301 #if defined (HAVE_LLVM) | 284 #if defined (HAVE_LLVM) |
302 if (tree_jit::execute (cmd, rhs)) | 285 if (tree_jit::execute (cmd, rhs)) |
303 return; | 286 return; |
304 #endif | 287 #endif |
305 | 288 |
306 if (rhs.is_undefined ()) | 289 if (rhs.is_undefined ()) |
307 return; | 290 return; |
308 | 291 |
309 tree_expression *lhs = cmd.left_hand_side (); | 292 tree_expression *lhs = cmd.left_hand_side (); |
310 | 293 |
311 octave_lvalue ult = lhs->lvalue (); | 294 octave_lvalue ult = lhs->lvalue (); |
312 | 295 |
313 tree_statement_list *loop_body = cmd.body (); | 296 tree_statement_list *loop_body = cmd.body (); |
314 | 297 |
315 if (rhs.is_range ()) | 298 if (rhs.is_range ()) |
316 { | 299 { |
317 Range rng = rhs.range_value (); | 300 Range rng = rhs.range_value (); |
318 | 301 |
319 octave_idx_type steps = rng.numel (); | 302 octave_idx_type steps = rng.numel (); |
320 | 303 |
321 for (octave_idx_type i = 0; i < steps; i++) | 304 for (octave_idx_type i = 0; i < steps; i++) |
305 { | |
306 octave_value val (rng.elem (i)); | |
307 | |
308 ult.assign (octave_value::op_asn_eq, val); | |
309 | |
310 if (loop_body) | |
311 loop_body->accept (*this); | |
312 | |
313 if (quit_loop_now ()) | |
314 break; | |
315 } | |
316 } | |
317 else if (rhs.is_scalar_type ()) | |
318 { | |
319 ult.assign (octave_value::op_asn_eq, rhs); | |
320 | |
321 if (loop_body) | |
322 loop_body->accept (*this); | |
323 | |
324 // Maybe decrement break and continue states. | |
325 quit_loop_now (); | |
326 } | |
327 else if (rhs.is_matrix_type () || rhs.is_cell () || rhs.is_string () | |
328 || rhs.is_map ()) | |
329 { | |
330 // A matrix or cell is reshaped to 2 dimensions and iterated by | |
331 // columns. | |
332 | |
333 dim_vector dv = rhs.dims ().redim (2); | |
334 | |
335 octave_idx_type nrows = dv(0); | |
336 octave_idx_type steps = dv(1); | |
337 | |
338 if (steps > 0) | |
339 { | |
340 octave_value arg = rhs; | |
341 if (rhs.ndims () > 2) | |
342 arg = arg.reshape (dv); | |
343 | |
344 // for row vectors, use single index to speed things up. | |
345 octave_value_list idx; | |
346 octave_idx_type iidx; | |
347 if (nrows == 1) | |
348 { | |
349 idx.resize (1); | |
350 iidx = 0; | |
351 } | |
352 else | |
353 { | |
354 idx.resize (2); | |
355 idx(0) = octave_value::magic_colon_t; | |
356 iidx = 1; | |
357 } | |
358 | |
359 for (octave_idx_type i = 1; i <= steps; i++) | |
360 { | |
361 // do_index_op expects one-based indices. | |
362 idx(iidx) = i; | |
363 octave_value val = arg.do_index_op (idx); | |
364 | |
365 ult.assign (octave_value::op_asn_eq, val); | |
366 | |
367 if (loop_body) | |
368 loop_body->accept (*this); | |
369 | |
370 if (quit_loop_now ()) | |
371 break; | |
372 } | |
373 } | |
374 } | |
375 else | |
376 error ("invalid type in for loop expression near line %d, column %d", | |
377 cmd.line (), cmd.column ()); | |
378 } | |
379 | |
380 void | |
381 tree_evaluator::visit_complex_for_command (tree_complex_for_command& cmd) | |
382 { | |
383 if (debug_mode) | |
384 do_breakpoint (cmd.is_breakpoint (true)); | |
385 | |
386 octave::unwind_protect frame; | |
387 | |
388 frame.protect_var (in_loop_command); | |
389 | |
390 in_loop_command = true; | |
391 | |
392 tree_expression *expr = cmd.control_expr (); | |
393 | |
394 octave_value rhs = expr->rvalue1 (); | |
395 | |
396 if (rhs.is_undefined ()) | |
397 return; | |
398 | |
399 if (! rhs.is_map ()) | |
400 error ("in statement 'for [X, Y] = VAL', VAL must be a structure"); | |
401 | |
402 // Cycle through structure elements. First element of id_list | |
403 // is set to value and the second is set to the name of the | |
404 // structure element. | |
405 | |
406 tree_argument_list *lhs = cmd.left_hand_side (); | |
407 | |
408 tree_argument_list::iterator p = lhs->begin (); | |
409 | |
410 tree_expression *elt = *p++; | |
411 | |
412 octave_lvalue val_ref = elt->lvalue (); | |
413 | |
414 elt = *p; | |
415 | |
416 octave_lvalue key_ref = elt->lvalue (); | |
417 | |
418 const octave_map tmp_val = rhs.map_value (); | |
419 | |
420 tree_statement_list *loop_body = cmd.body (); | |
421 | |
422 string_vector keys = tmp_val.keys (); | |
423 | |
424 octave_idx_type nel = keys.numel (); | |
425 | |
426 for (octave_idx_type i = 0; i < nel; i++) | |
427 { | |
428 std::string key = keys[i]; | |
429 | |
430 const Cell val_lst = tmp_val.contents (key); | |
431 | |
432 octave_idx_type n = val_lst.numel (); | |
433 | |
434 octave_value val = (n == 1) ? val_lst(0) : octave_value (val_lst); | |
435 | |
436 val_ref.assign (octave_value::op_asn_eq, val); | |
437 key_ref.assign (octave_value::op_asn_eq, key); | |
438 | |
439 if (loop_body) | |
440 loop_body->accept (*this); | |
441 | |
442 if (quit_loop_now ()) | |
443 break; | |
444 } | |
445 } | |
446 | |
447 void | |
448 tree_evaluator::visit_octave_user_script (octave_user_script&) | |
449 { | |
450 panic_impossible (); | |
451 } | |
452 | |
453 void | |
454 tree_evaluator::visit_octave_user_function (octave_user_function&) | |
455 { | |
456 panic_impossible (); | |
457 } | |
458 | |
459 void | |
460 tree_evaluator::visit_octave_user_function_header (octave_user_function&) | |
461 { | |
462 panic_impossible (); | |
463 } | |
464 | |
465 void | |
466 tree_evaluator::visit_octave_user_function_trailer (octave_user_function&) | |
467 { | |
468 panic_impossible (); | |
469 } | |
470 | |
471 void | |
472 tree_evaluator::visit_function_def (tree_function_def& cmd) | |
473 { | |
474 octave_value fcn = cmd.function (); | |
475 | |
476 octave_function *f = fcn.function_value (); | |
477 | |
478 if (f) | |
479 { | |
480 std::string nm = f->name (); | |
481 | |
482 symbol_table::install_cmdline_function (nm, fcn); | |
483 | |
484 // Make sure that any variable with the same name as the new | |
485 // function is cleared. | |
486 | |
487 symbol_table::assign (nm); | |
488 } | |
489 } | |
490 | |
491 void | |
492 tree_evaluator::visit_identifier (tree_identifier&) | |
493 { | |
494 panic_impossible (); | |
495 } | |
496 | |
497 void | |
498 tree_evaluator::visit_if_clause (tree_if_clause&) | |
499 { | |
500 panic_impossible (); | |
501 } | |
502 | |
503 void | |
504 tree_evaluator::visit_if_command (tree_if_command& cmd) | |
505 { | |
506 tree_if_command_list *lst = cmd.cmd_list (); | |
507 | |
508 if (lst) | |
509 lst->accept (*this); | |
510 } | |
511 | |
512 void | |
513 tree_evaluator::visit_if_command_list (tree_if_command_list& lst) | |
514 { | |
515 for (tree_if_command_list::iterator p = lst.begin (); p != lst.end (); p++) | |
516 { | |
517 tree_if_clause *tic = *p; | |
518 | |
519 tree_expression *expr = tic->condition (); | |
520 | |
521 if (statement_context == function || statement_context == script) | |
522 octave_call_stack::set_location (tic->line (), tic->column ()); | |
523 | |
524 if (debug_mode && ! tic->is_else_clause ()) | |
525 do_breakpoint (tic->is_breakpoint (true)); | |
526 | |
527 if (tic->is_else_clause () || expr->is_logically_true ("if")) | |
528 { | |
529 tree_statement_list *stmt_lst = tic->commands (); | |
530 | |
531 if (stmt_lst) | |
532 stmt_lst->accept (*this); | |
533 | |
534 break; | |
535 } | |
536 } | |
537 } | |
538 | |
539 void | |
540 tree_evaluator::visit_index_expression (tree_index_expression&) | |
541 { | |
542 panic_impossible (); | |
543 } | |
544 | |
545 void | |
546 tree_evaluator::visit_matrix (tree_matrix&) | |
547 { | |
548 panic_impossible (); | |
549 } | |
550 | |
551 void | |
552 tree_evaluator::visit_cell (tree_cell&) | |
553 { | |
554 panic_impossible (); | |
555 } | |
556 | |
557 void | |
558 tree_evaluator::visit_multi_assignment (tree_multi_assignment&) | |
559 { | |
560 panic_impossible (); | |
561 } | |
562 | |
563 void | |
564 tree_evaluator::visit_no_op_command (tree_no_op_command& cmd) | |
565 { | |
566 if (debug_mode && cmd.is_end_of_fcn_or_script ()) | |
567 do_breakpoint (cmd.is_breakpoint (true), true); | |
568 } | |
569 | |
570 void | |
571 tree_evaluator::visit_constant (tree_constant&) | |
572 { | |
573 panic_impossible (); | |
574 } | |
575 | |
576 void | |
577 tree_evaluator::visit_fcn_handle (tree_fcn_handle&) | |
578 { | |
579 panic_impossible (); | |
580 } | |
581 | |
582 void | |
583 tree_evaluator::visit_funcall (tree_funcall&) | |
584 { | |
585 panic_impossible (); | |
586 } | |
587 | |
588 void | |
589 tree_evaluator::visit_parameter_list (tree_parameter_list&) | |
590 { | |
591 panic_impossible (); | |
592 } | |
593 | |
594 void | |
595 tree_evaluator::visit_postfix_expression (tree_postfix_expression&) | |
596 { | |
597 panic_impossible (); | |
598 } | |
599 | |
600 void | |
601 tree_evaluator::visit_prefix_expression (tree_prefix_expression&) | |
602 { | |
603 panic_impossible (); | |
604 } | |
605 | |
606 void | |
607 tree_evaluator::visit_return_command (tree_return_command& cmd) | |
608 { | |
609 if (debug_mode) | |
610 do_breakpoint (cmd.is_breakpoint (true)); | |
611 | |
612 // Act like dbcont. | |
613 | |
614 if (Vdebugging | |
615 && octave_call_stack::current_frame () == current_frame) | |
616 { | |
617 Vdebugging = false; | |
618 | |
619 reset_debug_state (); | |
620 } | |
621 else if (statement_context == function || statement_context == script | |
622 || in_loop_command) | |
623 tree_return_command::returning = 1; | |
624 } | |
625 | |
626 void | |
627 tree_evaluator::visit_return_list (tree_return_list&) | |
628 { | |
629 panic_impossible (); | |
630 } | |
631 | |
632 void | |
633 tree_evaluator::visit_simple_assignment (tree_simple_assignment&) | |
634 { | |
635 panic_impossible (); | |
636 } | |
637 | |
638 void | |
639 tree_evaluator::visit_statement (tree_statement& stmt) | |
640 { | |
641 tree_command *cmd = stmt.command (); | |
642 tree_expression *expr = stmt.expression (); | |
643 | |
644 if (cmd || expr) | |
645 { | |
646 if (statement_context == function || statement_context == script) | |
647 { | |
648 // Skip commands issued at a debug> prompt to avoid disturbing | |
649 // the state of the program we are debugging. | |
650 | |
651 if (Vtrack_line_num) | |
652 octave_call_stack::set_location (stmt.line (), stmt.column ()); | |
653 | |
654 if ((statement_context == script | |
655 && ((Vecho_executing_commands & ECHO_SCRIPTS | |
656 && octave_call_stack::all_scripts ()) | |
657 || Vecho_executing_commands & ECHO_FUNCTIONS)) | |
658 || (statement_context == function | |
659 && Vecho_executing_commands & ECHO_FUNCTIONS)) | |
660 stmt.echo_code (); | |
661 } | |
662 | |
663 try | |
664 { | |
665 if (cmd) | |
666 cmd->accept (*this); | |
667 else | |
668 { | |
669 if (debug_mode) | |
670 do_breakpoint (expr->is_breakpoint (true)); | |
671 | |
672 // FIXME: maybe all of this should be packaged in | |
673 // one virtual function that returns a flag saying whether | |
674 // or not the expression will take care of binding ans and | |
675 // printing the result. | |
676 | |
677 // FIXME: it seems that we should just have to | |
678 // call expr->rvalue1 () and that should take care of | |
679 // everything, binding ans as necessary? | |
680 | |
681 bool do_bind_ans = false; | |
682 | |
683 if (expr->is_identifier ()) | |
684 { | |
685 tree_identifier *id = dynamic_cast<tree_identifier *> (expr); | |
686 | |
687 do_bind_ans = (! id->is_variable ()); | |
688 } | |
689 else | |
690 do_bind_ans = (! expr->is_assignment_expression ()); | |
691 | |
692 octave_value tmp_result = expr->rvalue1 (0); | |
693 | |
694 if (do_bind_ans && tmp_result.is_defined ()) | |
695 bind_ans (tmp_result, expr->print_result () | |
696 && statement_printing_enabled ()); | |
697 | |
698 // if (tmp_result.is_defined ()) | |
699 // result_values(0) = tmp_result; | |
700 } | |
701 } | |
702 catch (const std::bad_alloc&) | |
703 { | |
704 // FIXME: We want to use error_with_id here so that give users | |
705 // control over this error message but error_with_id will | |
706 // require some memory allocations. Is there anything we can | |
707 // do to make those more likely to succeed? | |
708 | |
709 error_with_id ("Octave:bad-alloc", | |
710 "out of memory or dimension too large for Octave's index type"); | |
711 } | |
712 } | |
713 } | |
714 | |
715 void | |
716 tree_evaluator::visit_statement_list (tree_statement_list& lst) | |
717 { | |
718 // FIXME: commented out along with else clause below. | |
719 // static octave_value_list empty_list; | |
720 | |
721 tree_statement_list::iterator p = lst.begin (); | |
722 | |
723 if (p != lst.end ()) | |
724 { | |
725 while (true) | |
726 { | |
727 tree_statement *elt = *p++; | |
728 | |
729 if (! elt) | |
730 error ("invalid statement found in statement list!"); | |
731 | |
732 octave_quit (); | |
733 | |
734 elt->accept (*this); | |
735 | |
736 if (tree_break_command::breaking | |
737 || tree_continue_command::continuing) | |
738 break; | |
739 | |
740 if (tree_return_command::returning) | |
741 break; | |
742 | |
743 if (p == lst.end ()) | |
744 break; | |
745 else | |
746 { | |
747 // Clear previous values before next statement is | |
748 // evaluated so that we aren't holding an extra | |
749 // reference to a value that may be used next. For | |
750 // example, in code like this: | |
751 // | |
752 // X = rand (N); # refcount for X should be 1 | |
753 // # after this statement | |
754 // | |
755 // X(idx) = val; # no extra copy of X should be | |
756 // # needed, but we will be faked | |
757 // # out if retval is not cleared | |
758 // # between statements here | |
759 | |
760 // result_values = empty_list; | |
761 } | |
762 } | |
763 } | |
764 } | |
765 | |
766 void | |
767 tree_evaluator::visit_switch_case (tree_switch_case&) | |
768 { | |
769 panic_impossible (); | |
770 } | |
771 | |
772 void | |
773 tree_evaluator::visit_switch_case_list (tree_switch_case_list&) | |
774 { | |
775 panic_impossible (); | |
776 } | |
777 | |
778 void | |
779 tree_evaluator::visit_switch_command (tree_switch_command& cmd) | |
780 { | |
781 if (debug_mode) | |
782 do_breakpoint (cmd.is_breakpoint (true)); | |
783 | |
784 tree_expression *expr = cmd.switch_value (); | |
785 | |
786 if (! expr) | |
787 error ("missing value in switch command near line %d, column %d", | |
788 cmd.line (), cmd.column ()); | |
789 | |
790 octave_value val = expr->rvalue1 (); | |
791 | |
792 tree_switch_case_list *lst = cmd.case_list (); | |
793 | |
794 if (lst) | |
795 { | |
796 for (tree_switch_case_list::iterator p = lst->begin (); | |
797 p != lst->end (); p++) | |
798 { | |
799 tree_switch_case *t = *p; | |
800 | |
801 if (t->is_default_case () || t->label_matches (val)) | |
802 { | |
803 tree_statement_list *stmt_lst = t->commands (); | |
804 | |
805 if (stmt_lst) | |
806 stmt_lst->accept (*this); | |
807 | |
808 break; | |
809 } | |
810 } | |
811 } | |
812 } | |
813 | |
814 void | |
815 tree_evaluator::visit_try_catch_command (tree_try_catch_command& cmd) | |
816 { | |
817 bool execution_error = false; | |
818 | |
819 { // unwind frame before catch block | |
820 octave::unwind_protect frame; | |
821 | |
822 frame.protect_var (buffer_error_messages); | |
823 frame.protect_var (Vdebug_on_error); | |
824 frame.protect_var (Vdebug_on_warning); | |
825 | |
826 buffer_error_messages++; | |
827 Vdebug_on_error = false; | |
828 Vdebug_on_warning = false; | |
829 | |
830 // The catch code is *not* added to unwind_protect stack; | |
831 // it doesn't need to be run on interrupts. | |
832 | |
833 tree_statement_list *try_code = cmd.body (); | |
834 | |
835 if (try_code) | |
322 { | 836 { |
323 octave_value val (rng.elem (i)); | 837 try |
324 | |
325 ult.assign (octave_value::op_asn_eq, val); | |
326 | |
327 if (loop_body) | |
328 loop_body->accept (*this); | |
329 | |
330 if (quit_loop_now ()) | |
331 break; | |
332 } | |
333 } | |
334 else if (rhs.is_scalar_type ()) | |
335 { | |
336 ult.assign (octave_value::op_asn_eq, rhs); | |
337 | |
338 if (loop_body) | |
339 loop_body->accept (*this); | |
340 | |
341 // Maybe decrement break and continue states. | |
342 quit_loop_now (); | |
343 } | |
344 else if (rhs.is_matrix_type () || rhs.is_cell () || rhs.is_string () | |
345 || rhs.is_map ()) | |
346 { | |
347 // A matrix or cell is reshaped to 2 dimensions and iterated by | |
348 // columns. | |
349 | |
350 dim_vector dv = rhs.dims ().redim (2); | |
351 | |
352 octave_idx_type nrows = dv(0); | |
353 octave_idx_type steps = dv(1); | |
354 | |
355 if (steps > 0) | |
356 { | |
357 octave_value arg = rhs; | |
358 if (rhs.ndims () > 2) | |
359 arg = arg.reshape (dv); | |
360 | |
361 // for row vectors, use single index to speed things up. | |
362 octave_value_list idx; | |
363 octave_idx_type iidx; | |
364 if (nrows == 1) | |
365 { | 838 { |
366 idx.resize (1); | 839 in_try_catch++; |
367 iidx = 0; | 840 try_code->accept (*this); |
841 in_try_catch--; | |
368 } | 842 } |
369 else | 843 catch (const octave_execution_exception&) |
370 { | 844 { |
371 idx.resize (2); | 845 recover_from_exception (); |
372 idx(0) = octave_value::magic_colon_t; | 846 |
373 iidx = 1; | 847 in_try_catch--; // must be restored before "catch" block |
374 } | 848 execution_error = true; |
375 | |
376 for (octave_idx_type i = 1; i <= steps; i++) | |
377 { | |
378 // do_index_op expects one-based indices. | |
379 idx(iidx) = i; | |
380 octave_value val = arg.do_index_op (idx); | |
381 | |
382 ult.assign (octave_value::op_asn_eq, val); | |
383 | |
384 if (loop_body) | |
385 loop_body->accept (*this); | |
386 | |
387 if (quit_loop_now ()) | |
388 break; | |
389 } | 849 } |
390 } | 850 } |
851 // Unwind to let the user print any messages from | |
852 // errors that occurred in the body of the try_catch statement, | |
853 // or throw further errors. | |
391 } | 854 } |
392 else | 855 |
393 error ("invalid type in for loop expression near line %d, column %d", | 856 if (execution_error) |
394 cmd.line (), cmd.column ()); | 857 { |
395 } | 858 tree_statement_list *catch_code = cmd.cleanup (); |
396 | 859 if (catch_code) |
397 void | 860 { |
398 tree_evaluator::visit_complex_for_command (tree_complex_for_command& cmd) | 861 tree_identifier *expr_id = cmd.identifier (); |
399 { | 862 octave_lvalue ult; |
400 if (debug_mode) | 863 |
401 do_breakpoint (cmd.is_breakpoint (true)); | 864 if (expr_id) |
402 | 865 { |
403 octave::unwind_protect frame; | 866 ult = expr_id->lvalue (); |
404 | 867 |
405 frame.protect_var (in_loop_command); | 868 octave_scalar_map err; |
406 | 869 |
407 in_loop_command = true; | 870 err.assign ("message", last_error_message ()); |
408 | 871 err.assign ("identifier", last_error_id ()); |
409 tree_expression *expr = cmd.control_expr (); | 872 err.assign ("stack", last_error_stack ()); |
410 | 873 |
411 octave_value rhs = expr->rvalue1 (); | 874 ult.assign (octave_value::op_asn_eq, err); |
412 | 875 } |
413 if (rhs.is_undefined ()) | 876 |
414 return; | 877 // perform actual "catch" block |
415 | 878 if (catch_code) |
416 if (! rhs.is_map ()) | 879 catch_code->accept (*this); |
417 error ("in statement 'for [X, Y] = VAL', VAL must be a structure"); | 880 } |
418 | 881 } |
419 // Cycle through structure elements. First element of id_list | 882 } |
420 // is set to value and the second is set to the name of the | 883 |
421 // structure element. | 884 void |
422 | 885 tree_evaluator::do_unwind_protect_cleanup_code (tree_statement_list *list) |
423 tree_argument_list *lhs = cmd.left_hand_side (); | 886 { |
424 | 887 octave::unwind_protect frame; |
425 tree_argument_list::iterator p = lhs->begin (); | 888 |
426 | 889 frame.protect_var (octave_interrupt_state); |
427 tree_expression *elt = *p++; | 890 octave_interrupt_state = 0; |
428 | 891 |
429 octave_lvalue val_ref = elt->lvalue (); | 892 // We want to preserve the last location info for possible |
430 | 893 // backtracking. |
431 elt = *p; | 894 frame.add_fcn (octave_call_stack::set_line, |
432 | 895 octave_call_stack::current_line ()); |
433 octave_lvalue key_ref = elt->lvalue (); | 896 frame.add_fcn (octave_call_stack::set_column, |
434 | 897 octave_call_stack::current_column ()); |
435 const octave_map tmp_val = rhs.map_value (); | 898 |
436 | 899 // Similarly, if we have seen a return or break statement, allow all |
437 tree_statement_list *loop_body = cmd.body (); | 900 // the cleanup code to run before returning or handling the break. |
438 | 901 // We don't have to worry about continue statements because they can |
439 string_vector keys = tmp_val.keys (); | 902 // only occur in loops. |
440 | 903 |
441 octave_idx_type nel = keys.numel (); | 904 frame.protect_var (tree_return_command::returning); |
442 | 905 tree_return_command::returning = 0; |
443 for (octave_idx_type i = 0; i < nel; i++) | 906 |
444 { | 907 frame.protect_var (tree_break_command::breaking); |
445 std::string key = keys[i]; | 908 tree_break_command::breaking = 0; |
446 | 909 |
447 const Cell val_lst = tmp_val.contents (key); | 910 try |
448 | 911 { |
449 octave_idx_type n = val_lst.numel (); | 912 if (list) |
450 | 913 list->accept (*this); |
451 octave_value val = (n == 1) ? val_lst(0) : octave_value (val_lst); | 914 } |
452 | 915 catch (const octave_execution_exception&) |
453 val_ref.assign (octave_value::op_asn_eq, val); | 916 { |
454 key_ref.assign (octave_value::op_asn_eq, key); | 917 recover_from_exception (); |
455 | 918 |
456 if (loop_body) | 919 if (tree_break_command::breaking || tree_return_command::returning) |
457 loop_body->accept (*this); | 920 frame.discard (2); |
458 | 921 else |
459 if (quit_loop_now ()) | 922 frame.run (2); |
460 break; | 923 |
461 } | 924 frame.discard (2); |
462 } | 925 |
463 | 926 throw; |
464 void | 927 } |
465 tree_evaluator::visit_octave_user_script (octave_user_script&) | 928 |
466 { | 929 // The unwind_protects are popped off the stack in the reverse of |
467 panic_impossible (); | 930 // the order they are pushed on. |
468 } | 931 |
469 | 932 // FIXME: these statements say that if we see a break or |
470 void | 933 // return statement in the cleanup block, that we want to use the |
471 tree_evaluator::visit_octave_user_function (octave_user_function&) | 934 // new value of the breaking or returning flag instead of restoring |
472 { | 935 // the previous value. Is that the right thing to do? I think so. |
473 panic_impossible (); | 936 // Consider the case of |
474 } | 937 // |
475 | 938 // function foo () |
476 void | 939 // unwind_protect |
477 tree_evaluator::visit_octave_user_function_header (octave_user_function&) | 940 // fprintf (stderr, "1: this should always be executed\n"); |
478 { | 941 // break; |
479 panic_impossible (); | 942 // fprintf (stderr, "1: this should never be executed\n"); |
480 } | 943 // unwind_protect_cleanup |
481 | 944 // fprintf (stderr, "2: this should always be executed\n"); |
482 void | 945 // return; |
483 tree_evaluator::visit_octave_user_function_trailer (octave_user_function&) | 946 // fprintf (stderr, "2: this should never be executed\n"); |
484 { | 947 // end_unwind_protect |
485 panic_impossible (); | 948 // endfunction |
486 } | 949 // |
487 | 950 // If we reset the value of the breaking flag, both the returning |
488 void | 951 // flag and the breaking flag will be set, and we shouldn't have |
489 tree_evaluator::visit_function_def (tree_function_def& cmd) | 952 // both. So, use the most recent one. If there is no return or |
490 { | 953 // break in the cleanup block, the values should be reset to |
491 octave_value fcn = cmd.function (); | 954 // whatever they were when the cleanup block was entered. |
492 | 955 |
493 octave_function *f = fcn.function_value (); | 956 if (tree_break_command::breaking || tree_return_command::returning) |
494 | 957 frame.discard (2); |
495 if (f) | 958 else |
496 { | 959 frame.run (2); |
497 std::string nm = f->name (); | 960 } |
498 | 961 |
499 symbol_table::install_cmdline_function (nm, fcn); | 962 void |
500 | 963 tree_evaluator::visit_unwind_protect_command (tree_unwind_protect_command& cmd) |
501 // Make sure that any variable with the same name as the new | 964 { |
502 // function is cleared. | 965 tree_statement_list *cleanup_code = cmd.cleanup (); |
503 | 966 |
504 symbol_table::assign (nm); | 967 tree_statement_list *unwind_protect_code = cmd.body (); |
505 } | 968 |
506 } | 969 if (unwind_protect_code) |
507 | 970 { |
508 void | 971 try |
509 tree_evaluator::visit_identifier (tree_identifier&) | 972 { |
510 { | 973 unwind_protect_code->accept (*this); |
511 panic_impossible (); | 974 } |
512 } | 975 catch (const octave_execution_exception&) |
513 | 976 { |
514 void | 977 // FIXME: Maybe we should be able to temporarily set the |
515 tree_evaluator::visit_if_clause (tree_if_clause&) | 978 // interpreter's exception handling state to something "safe" |
516 { | 979 // while the cleanup block runs instead of just resetting it |
517 panic_impossible (); | 980 // here? |
518 } | 981 recover_from_exception (); |
519 | 982 |
520 void | 983 // Run the cleanup code on exceptions, so that it is run even |
521 tree_evaluator::visit_if_command (tree_if_command& cmd) | 984 // in case of interrupt or out-of-memory. |
522 { | 985 do_unwind_protect_cleanup_code (cleanup_code); |
523 tree_if_command_list *lst = cmd.cmd_list (); | 986 |
524 | 987 // If an error occurs inside the cleanup code, a new |
525 if (lst) | 988 // exception will be thrown instead of the original. |
526 lst->accept (*this); | 989 throw; |
527 } | 990 } |
528 | 991 |
529 void | 992 // Also execute the unwind_protect_cleanump code if the |
530 tree_evaluator::visit_if_command_list (tree_if_command_list& lst) | 993 // unwind_protect block runs without error. |
531 { | 994 do_unwind_protect_cleanup_code (cleanup_code); |
532 for (tree_if_command_list::iterator p = lst.begin (); p != lst.end (); p++) | 995 } |
533 { | 996 } |
534 tree_if_clause *tic = *p; | 997 |
535 | 998 void |
536 tree_expression *expr = tic->condition (); | 999 tree_evaluator::visit_while_command (tree_while_command& cmd) |
537 | 1000 { |
538 if (statement_context == function || statement_context == script) | 1001 #if defined (HAVE_LLVM) |
539 octave_call_stack::set_location (tic->line (), tic->column ()); | 1002 if (tree_jit::execute (cmd)) |
540 | 1003 return; |
541 if (debug_mode && ! tic->is_else_clause ()) | 1004 #endif |
542 do_breakpoint (tic->is_breakpoint (true)); | 1005 |
543 | 1006 octave::unwind_protect frame; |
544 if (tic->is_else_clause () || expr->is_logically_true ("if")) | 1007 |
545 { | 1008 frame.protect_var (in_loop_command); |
546 tree_statement_list *stmt_lst = tic->commands (); | 1009 |
547 | 1010 in_loop_command = true; |
548 if (stmt_lst) | 1011 |
549 stmt_lst->accept (*this); | 1012 tree_expression *expr = cmd.condition (); |
550 | 1013 |
1014 if (! expr) | |
1015 panic_impossible (); | |
1016 | |
1017 for (;;) | |
1018 { | |
1019 if (debug_mode) | |
1020 do_breakpoint (cmd.is_breakpoint (true)); | |
1021 | |
1022 if (expr->is_logically_true ("while")) | |
1023 { | |
1024 tree_statement_list *loop_body = cmd.body (); | |
1025 | |
1026 if (loop_body) | |
1027 loop_body->accept (*this); | |
1028 | |
1029 if (quit_loop_now ()) | |
1030 break; | |
1031 } | |
1032 else | |
551 break; | 1033 break; |
552 } | 1034 } |
553 } | 1035 } |
554 } | 1036 |
555 | 1037 void |
556 void | 1038 tree_evaluator::visit_do_until_command (tree_do_until_command& cmd) |
557 tree_evaluator::visit_index_expression (tree_index_expression&) | 1039 { |
558 { | 1040 #if defined (HAVE_LLVM) |
559 panic_impossible (); | 1041 if (tree_jit::execute (cmd)) |
560 } | 1042 return; |
561 | 1043 #endif |
562 void | 1044 |
563 tree_evaluator::visit_matrix (tree_matrix&) | |
564 { | |
565 panic_impossible (); | |
566 } | |
567 | |
568 void | |
569 tree_evaluator::visit_cell (tree_cell&) | |
570 { | |
571 panic_impossible (); | |
572 } | |
573 | |
574 void | |
575 tree_evaluator::visit_multi_assignment (tree_multi_assignment&) | |
576 { | |
577 panic_impossible (); | |
578 } | |
579 | |
580 void | |
581 tree_evaluator::visit_no_op_command (tree_no_op_command& cmd) | |
582 { | |
583 if (debug_mode && cmd.is_end_of_fcn_or_script ()) | |
584 do_breakpoint (cmd.is_breakpoint (true), true); | |
585 } | |
586 | |
587 void | |
588 tree_evaluator::visit_constant (tree_constant&) | |
589 { | |
590 panic_impossible (); | |
591 } | |
592 | |
593 void | |
594 tree_evaluator::visit_fcn_handle (tree_fcn_handle&) | |
595 { | |
596 panic_impossible (); | |
597 } | |
598 | |
599 void | |
600 tree_evaluator::visit_funcall (tree_funcall&) | |
601 { | |
602 panic_impossible (); | |
603 } | |
604 | |
605 void | |
606 tree_evaluator::visit_parameter_list (tree_parameter_list&) | |
607 { | |
608 panic_impossible (); | |
609 } | |
610 | |
611 void | |
612 tree_evaluator::visit_postfix_expression (tree_postfix_expression&) | |
613 { | |
614 panic_impossible (); | |
615 } | |
616 | |
617 void | |
618 tree_evaluator::visit_prefix_expression (tree_prefix_expression&) | |
619 { | |
620 panic_impossible (); | |
621 } | |
622 | |
623 void | |
624 tree_evaluator::visit_return_command (tree_return_command& cmd) | |
625 { | |
626 if (debug_mode) | |
627 do_breakpoint (cmd.is_breakpoint (true)); | |
628 | |
629 // Act like dbcont. | |
630 | |
631 if (Vdebugging | |
632 && octave_call_stack::current_frame () == current_frame) | |
633 { | |
634 Vdebugging = false; | |
635 | |
636 reset_debug_state (); | |
637 } | |
638 else if (statement_context == function || statement_context == script | |
639 || in_loop_command) | |
640 tree_return_command::returning = 1; | |
641 } | |
642 | |
643 void | |
644 tree_evaluator::visit_return_list (tree_return_list&) | |
645 { | |
646 panic_impossible (); | |
647 } | |
648 | |
649 void | |
650 tree_evaluator::visit_simple_assignment (tree_simple_assignment&) | |
651 { | |
652 panic_impossible (); | |
653 } | |
654 | |
655 void | |
656 tree_evaluator::visit_statement (tree_statement& stmt) | |
657 { | |
658 tree_command *cmd = stmt.command (); | |
659 tree_expression *expr = stmt.expression (); | |
660 | |
661 if (cmd || expr) | |
662 { | |
663 if (statement_context == function || statement_context == script) | |
664 { | |
665 // Skip commands issued at a debug> prompt to avoid disturbing | |
666 // the state of the program we are debugging, but still track | |
667 // progress through user functions called from debug> prompt. | |
668 | |
669 if (Vtrack_line_num) | |
670 octave_call_stack::set_location (stmt.line (), stmt.column ()); | |
671 | |
672 if ((statement_context == script | |
673 && ((Vecho_executing_commands & ECHO_SCRIPTS | |
674 && octave_call_stack::all_scripts ()) | |
675 || Vecho_executing_commands & ECHO_FUNCTIONS)) | |
676 || (statement_context == function | |
677 && Vecho_executing_commands & ECHO_FUNCTIONS)) | |
678 stmt.echo_code (); | |
679 } | |
680 | |
681 try | |
682 { | |
683 if (cmd) | |
684 cmd->accept (*this); | |
685 else | |
686 { | |
687 if (debug_mode) | |
688 do_breakpoint (expr->is_breakpoint (true)); | |
689 | |
690 // FIXME: maybe all of this should be packaged in | |
691 // one virtual function that returns a flag saying whether | |
692 // or not the expression will take care of binding ans and | |
693 // printing the result. | |
694 | |
695 // FIXME: it seems that we should just have to | |
696 // call expr->rvalue1 () and that should take care of | |
697 // everything, binding ans as necessary? | |
698 | |
699 bool do_bind_ans = false; | |
700 | |
701 if (expr->is_identifier ()) | |
702 { | |
703 tree_identifier *id = dynamic_cast<tree_identifier *> (expr); | |
704 | |
705 do_bind_ans = (! id->is_variable ()); | |
706 } | |
707 else | |
708 do_bind_ans = (! expr->is_assignment_expression ()); | |
709 | |
710 octave_value tmp_result = expr->rvalue1 (0); | |
711 | |
712 if (do_bind_ans && tmp_result.is_defined ()) | |
713 bind_ans (tmp_result, expr->print_result () | |
714 && statement_printing_enabled ()); | |
715 | |
716 // if (tmp_result.is_defined ()) | |
717 // result_values(0) = tmp_result; | |
718 } | |
719 } | |
720 catch (const std::bad_alloc&) | |
721 { | |
722 // FIXME: We want to use error_with_id here so that give users | |
723 // control over this error message but error_with_id will | |
724 // require some memory allocations. Is there anything we can | |
725 // do to make those more likely to succeed? | |
726 | |
727 error_with_id ("Octave:bad-alloc", | |
728 "out of memory or dimension too large for Octave's index type"); | |
729 } | |
730 } | |
731 } | |
732 | |
733 void | |
734 tree_evaluator::visit_statement_list (tree_statement_list& lst) | |
735 { | |
736 // FIXME: commented out along with else clause below. | |
737 // static octave_value_list empty_list; | |
738 | |
739 tree_statement_list::iterator p = lst.begin (); | |
740 | |
741 if (p != lst.end ()) | |
742 { | |
743 while (true) | |
744 { | |
745 tree_statement *elt = *p++; | |
746 | |
747 if (! elt) | |
748 error ("invalid statement found in statement list!"); | |
749 | |
750 octave_quit (); | |
751 | |
752 elt->accept (*this); | |
753 | |
754 if (tree_break_command::breaking | |
755 || tree_continue_command::continuing) | |
756 break; | |
757 | |
758 if (tree_return_command::returning) | |
759 break; | |
760 | |
761 if (p == lst.end ()) | |
762 break; | |
763 else | |
764 { | |
765 // Clear previous values before next statement is | |
766 // evaluated so that we aren't holding an extra | |
767 // reference to a value that may be used next. For | |
768 // example, in code like this: | |
769 // | |
770 // X = rand (N); # refcount for X should be 1 | |
771 // # after this statement | |
772 // | |
773 // X(idx) = val; # no extra copy of X should be | |
774 // # needed, but we will be faked | |
775 // # out if retval is not cleared | |
776 // # between statements here | |
777 | |
778 // result_values = empty_list; | |
779 } | |
780 } | |
781 } | |
782 } | |
783 | |
784 void | |
785 tree_evaluator::visit_switch_case (tree_switch_case&) | |
786 { | |
787 panic_impossible (); | |
788 } | |
789 | |
790 void | |
791 tree_evaluator::visit_switch_case_list (tree_switch_case_list&) | |
792 { | |
793 panic_impossible (); | |
794 } | |
795 | |
796 void | |
797 tree_evaluator::visit_switch_command (tree_switch_command& cmd) | |
798 { | |
799 if (debug_mode) | |
800 do_breakpoint (cmd.is_breakpoint (true)); | |
801 | |
802 tree_expression *expr = cmd.switch_value (); | |
803 | |
804 if (! expr) | |
805 error ("missing value in switch command near line %d, column %d", | |
806 cmd.line (), cmd.column ()); | |
807 | |
808 octave_value val = expr->rvalue1 (); | |
809 | |
810 tree_switch_case_list *lst = cmd.case_list (); | |
811 | |
812 if (lst) | |
813 { | |
814 for (tree_switch_case_list::iterator p = lst->begin (); | |
815 p != lst->end (); p++) | |
816 { | |
817 tree_switch_case *t = *p; | |
818 | |
819 if (t->is_default_case () || t->label_matches (val)) | |
820 { | |
821 tree_statement_list *stmt_lst = t->commands (); | |
822 | |
823 if (stmt_lst) | |
824 stmt_lst->accept (*this); | |
825 | |
826 break; | |
827 } | |
828 } | |
829 } | |
830 } | |
831 | |
832 void | |
833 tree_evaluator::visit_try_catch_command (tree_try_catch_command& cmd) | |
834 { | |
835 bool execution_error = false; | |
836 | |
837 { // unwind frame before catch block | |
838 octave::unwind_protect frame; | 1045 octave::unwind_protect frame; |
839 | 1046 |
840 frame.protect_var (buffer_error_messages); | 1047 frame.protect_var (in_loop_command); |
841 frame.protect_var (Vdebug_on_error); | 1048 |
842 frame.protect_var (Vdebug_on_warning); | 1049 in_loop_command = true; |
843 | 1050 |
844 buffer_error_messages++; | 1051 tree_expression *expr = cmd.condition (); |
845 Vdebug_on_error = false; | 1052 int until_line = cmd.line (); |
846 Vdebug_on_warning = false; | 1053 int until_column = cmd.column (); |
847 | 1054 |
848 // The catch code is *not* added to unwind_protect stack; | 1055 if (! expr) |
849 // it doesn't need to be run on interrupts. | 1056 panic_impossible (); |
850 | 1057 |
851 tree_statement_list *try_code = cmd.body (); | 1058 for (;;) |
852 | 1059 { |
853 if (try_code) | 1060 tree_statement_list *loop_body = cmd.body (); |
854 { | 1061 |
855 try | 1062 if (loop_body) |
856 { | 1063 loop_body->accept (*this); |
857 in_try_catch++; | 1064 |
858 try_code->accept (*this); | 1065 if (quit_loop_now ()) |
859 in_try_catch--; | 1066 break; |
860 } | 1067 |
861 catch (const octave_execution_exception&) | 1068 if (debug_mode) |
862 { | 1069 do_breakpoint (cmd.is_breakpoint (true)); |
863 recover_from_exception (); | 1070 |
864 | 1071 octave_call_stack::set_location (until_line, until_column); |
865 in_try_catch--; // must be restored before "catch" block | 1072 |
866 execution_error = true; | 1073 if (expr->is_logically_true ("do-until")) |
867 } | 1074 break; |
868 } | 1075 } |
869 // Unwind to let the user print any messages from | 1076 } |
870 // errors that occurred in the body of the try_catch statement, | 1077 |
871 // or throw further errors. | 1078 void |
872 } | 1079 tree_evaluator::do_breakpoint (tree_statement& stmt) const |
873 | 1080 { |
874 if (execution_error) | 1081 do_breakpoint (stmt.is_breakpoint (true), stmt.is_end_of_fcn_or_script ()); |
875 { | 1082 } |
876 tree_statement_list *catch_code = cmd.cleanup (); | 1083 |
877 if (catch_code) | 1084 void |
878 { | 1085 tree_evaluator::do_breakpoint (bool is_breakpoint, |
879 tree_identifier *expr_id = cmd.identifier (); | 1086 bool is_end_of_fcn_or_script) const |
880 octave_lvalue ult; | 1087 { |
881 | 1088 bool break_on_this_statement = false; |
882 if (expr_id) | 1089 |
883 { | 1090 if (octave_debug_on_interrupt_state) |
884 ult = expr_id->lvalue (); | 1091 { |
885 | 1092 break_on_this_statement = true; |
886 octave_scalar_map err; | 1093 |
887 | 1094 octave_debug_on_interrupt_state = false; |
888 err.assign ("message", last_error_message ()); | 1095 |
889 err.assign ("identifier", last_error_id ()); | 1096 current_frame = octave_call_stack::current_frame (); |
890 err.assign ("stack", last_error_stack ()); | 1097 } |
891 | 1098 else if (is_breakpoint) |
892 ult.assign (octave_value::op_asn_eq, err); | 1099 { |
893 } | 1100 break_on_this_statement = true; |
894 | 1101 |
895 // perform actual "catch" block | 1102 dbstep_flag = 0; |
896 if (catch_code) | 1103 |
897 catch_code->accept (*this); | 1104 current_frame = octave_call_stack::current_frame (); |
898 } | 1105 } |
899 } | 1106 else if (dbstep_flag > 0) |
900 } | 1107 { |
901 | 1108 if (octave_call_stack::current_frame () == current_frame) |
902 void | 1109 { |
903 tree_evaluator::do_unwind_protect_cleanup_code (tree_statement_list *list) | 1110 if (dbstep_flag == 1 || is_end_of_fcn_or_script) |
904 { | 1111 { |
905 octave::unwind_protect frame; | 1112 // We get here if we are doing a "dbstep" or a "dbstep N" and the |
906 | 1113 // count has reached 1 so that we must stop and return to debug |
907 frame.protect_var (octave_interrupt_state); | 1114 // prompt. Alternatively, "dbstep N" has been used but the end |
908 octave_interrupt_state = 0; | 1115 // of the frame has been reached so we stop at the last line and |
909 | 1116 // return to prompt. |
910 // We want to preserve the last location info for possible | 1117 |
911 // backtracking. | 1118 break_on_this_statement = true; |
912 frame.add_fcn (octave_call_stack::set_line, | 1119 |
913 octave_call_stack::current_line ()); | 1120 dbstep_flag = 0; |
914 frame.add_fcn (octave_call_stack::set_column, | 1121 } |
915 octave_call_stack::current_column ()); | 1122 else |
916 | 1123 { |
917 // Similarly, if we have seen a return or break statement, allow all | 1124 // Executing "dbstep N". Decrease N by one and continue. |
918 // the cleanup code to run before returning or handling the break. | 1125 |
919 // We don't have to worry about continue statements because they can | 1126 dbstep_flag--; |
920 // only occur in loops. | 1127 } |
921 | 1128 |
922 frame.protect_var (tree_return_command::returning); | 1129 } |
923 tree_return_command::returning = 0; | 1130 else if (dbstep_flag == 1 |
924 | 1131 && octave_call_stack::current_frame () < current_frame) |
925 frame.protect_var (tree_break_command::breaking); | 1132 { |
926 tree_break_command::breaking = 0; | 1133 // We stepped out from the end of a function. |
927 | 1134 |
928 try | 1135 current_frame = octave_call_stack::current_frame (); |
929 { | 1136 |
930 if (list) | 1137 break_on_this_statement = true; |
931 list->accept (*this); | 1138 |
932 } | 1139 dbstep_flag = 0; |
933 catch (const octave_execution_exception&) | 1140 } |
934 { | 1141 } |
935 recover_from_exception (); | 1142 else if (dbstep_flag == -1) |
936 | 1143 { |
937 if (tree_break_command::breaking || tree_return_command::returning) | 1144 // We get here if we are doing a "dbstep in". |
938 frame.discard (2); | 1145 |
939 else | 1146 break_on_this_statement = true; |
940 frame.run (2); | 1147 |
941 | 1148 dbstep_flag = 0; |
942 frame.discard (2); | 1149 |
943 | 1150 current_frame = octave_call_stack::current_frame (); |
944 throw; | 1151 } |
945 } | 1152 else if (dbstep_flag == -2) |
946 | 1153 { |
947 // The unwind_protects are popped off the stack in the reverse of | 1154 // We get here if we are doing a "dbstep out". Check for end of |
948 // the order they are pushed on. | 1155 // function and whether the current frame is the same as the |
949 | 1156 // cached value because we want to step out from the frame where |
950 // FIXME: these statements say that if we see a break or | 1157 // "dbstep out" was evaluated, not from any functions called from |
951 // return statement in the cleanup block, that we want to use the | 1158 // that frame. |
952 // new value of the breaking or returning flag instead of restoring | 1159 |
953 // the previous value. Is that the right thing to do? I think so. | 1160 if (is_end_of_fcn_or_script |
954 // Consider the case of | 1161 && octave_call_stack::current_frame () == current_frame) |
955 // | 1162 dbstep_flag = -1; |
956 // function foo () | 1163 } |
957 // unwind_protect | 1164 |
958 // fprintf (stderr, "1: this should always be executed\n"); | 1165 if (break_on_this_statement) |
959 // break; | 1166 do_keyboard (); |
960 // fprintf (stderr, "1: this should never be executed\n"); | 1167 |
961 // unwind_protect_cleanup | 1168 } |
962 // fprintf (stderr, "2: this should always be executed\n"); | 1169 |
963 // return; | 1170 // ARGS is currently unused, but since the do_keyboard function in |
964 // fprintf (stderr, "2: this should never be executed\n"); | 1171 // input.cc accepts an argument list, we preserve it here so that the |
965 // end_unwind_protect | 1172 // interface won't have to change if we decide to use it in the future. |
966 // endfunction | 1173 |
967 // | 1174 octave_value |
968 // If we reset the value of the breaking flag, both the returning | 1175 tree_evaluator::do_keyboard (const octave_value_list& args) const |
969 // flag and the breaking flag will be set, and we shouldn't have | 1176 { |
970 // both. So, use the most recent one. If there is no return or | 1177 return ::do_keyboard (args); |
971 // break in the cleanup block, the values should be reset to | 1178 } |
972 // whatever they were when the cleanup block was entered. | |
973 | |
974 if (tree_break_command::breaking || tree_return_command::returning) | |
975 frame.discard (2); | |
976 else | |
977 frame.run (2); | |
978 } | |
979 | |
980 void | |
981 tree_evaluator::visit_unwind_protect_command (tree_unwind_protect_command& cmd) | |
982 { | |
983 tree_statement_list *cleanup_code = cmd.cleanup (); | |
984 | |
985 tree_statement_list *unwind_protect_code = cmd.body (); | |
986 | |
987 if (unwind_protect_code) | |
988 { | |
989 try | |
990 { | |
991 unwind_protect_code->accept (*this); | |
992 } | |
993 catch (const octave_execution_exception&) | |
994 { | |
995 // FIXME: Maybe we should be able to temporarily set the | |
996 // interpreter's exception handling state to something "safe" | |
997 // while the cleanup block runs instead of just resetting it | |
998 // here? | |
999 recover_from_exception (); | |
1000 | |
1001 // Run the cleanup code on exceptions, so that it is run even | |
1002 // in case of interrupt or out-of-memory. | |
1003 do_unwind_protect_cleanup_code (cleanup_code); | |
1004 | |
1005 // If an error occurs inside the cleanup code, a new | |
1006 // exception will be thrown instead of the original. | |
1007 throw; | |
1008 } | |
1009 | |
1010 // Also execute the unwind_protect_cleanump code if the | |
1011 // unwind_protect block runs without error. | |
1012 do_unwind_protect_cleanup_code (cleanup_code); | |
1013 } | |
1014 } | |
1015 | |
1016 void | |
1017 tree_evaluator::visit_while_command (tree_while_command& cmd) | |
1018 { | |
1019 #if defined (HAVE_LLVM) | |
1020 if (tree_jit::execute (cmd)) | |
1021 return; | |
1022 #endif | |
1023 | |
1024 octave::unwind_protect frame; | |
1025 | |
1026 frame.protect_var (in_loop_command); | |
1027 | |
1028 in_loop_command = true; | |
1029 | |
1030 tree_expression *expr = cmd.condition (); | |
1031 | |
1032 if (! expr) | |
1033 panic_impossible (); | |
1034 | |
1035 for (;;) | |
1036 { | |
1037 if (debug_mode) | |
1038 do_breakpoint (cmd.is_breakpoint (true)); | |
1039 | |
1040 if (expr->is_logically_true ("while")) | |
1041 { | |
1042 tree_statement_list *loop_body = cmd.body (); | |
1043 | |
1044 if (loop_body) | |
1045 loop_body->accept (*this); | |
1046 | |
1047 if (quit_loop_now ()) | |
1048 break; | |
1049 } | |
1050 else | |
1051 break; | |
1052 } | |
1053 } | |
1054 | |
1055 void | |
1056 tree_evaluator::visit_do_until_command (tree_do_until_command& cmd) | |
1057 { | |
1058 #if defined (HAVE_LLVM) | |
1059 if (tree_jit::execute (cmd)) | |
1060 return; | |
1061 #endif | |
1062 | |
1063 octave::unwind_protect frame; | |
1064 | |
1065 frame.protect_var (in_loop_command); | |
1066 | |
1067 in_loop_command = true; | |
1068 | |
1069 tree_expression *expr = cmd.condition (); | |
1070 int until_line = cmd.line (); | |
1071 int until_column = cmd.column (); | |
1072 | |
1073 if (! expr) | |
1074 panic_impossible (); | |
1075 | |
1076 for (;;) | |
1077 { | |
1078 tree_statement_list *loop_body = cmd.body (); | |
1079 | |
1080 if (loop_body) | |
1081 loop_body->accept (*this); | |
1082 | |
1083 if (quit_loop_now ()) | |
1084 break; | |
1085 | |
1086 if (debug_mode) | |
1087 do_breakpoint (cmd.is_breakpoint (true)); | |
1088 | |
1089 octave_call_stack::set_location (until_line, until_column); | |
1090 | |
1091 if (expr->is_logically_true ("do-until")) | |
1092 break; | |
1093 } | |
1094 } | |
1095 | |
1096 void | |
1097 tree_evaluator::do_breakpoint (tree_statement& stmt) const | |
1098 { | |
1099 do_breakpoint (stmt.is_breakpoint (true), stmt.is_end_of_fcn_or_script ()); | |
1100 } | |
1101 | |
1102 void | |
1103 tree_evaluator::do_breakpoint (bool is_breakpoint, | |
1104 bool is_end_of_fcn_or_script) const | |
1105 { | |
1106 bool break_on_this_statement = false; | |
1107 | |
1108 if (octave_debug_on_interrupt_state) | |
1109 { | |
1110 break_on_this_statement = true; | |
1111 | |
1112 octave_debug_on_interrupt_state = false; | |
1113 | |
1114 current_frame = octave_call_stack::current_frame (); | |
1115 } | |
1116 else if (is_breakpoint) | |
1117 { | |
1118 break_on_this_statement = true; | |
1119 | |
1120 dbstep_flag = 0; | |
1121 | |
1122 current_frame = octave_call_stack::current_frame (); | |
1123 } | |
1124 else if (dbstep_flag > 0) | |
1125 { | |
1126 if (octave_call_stack::current_frame () == current_frame) | |
1127 { | |
1128 if (dbstep_flag == 1 || is_end_of_fcn_or_script) | |
1129 { | |
1130 // We get here if we are doing a "dbstep" or a "dbstep N" and the | |
1131 // count has reached 1 so that we must stop and return to debug | |
1132 // prompt. Alternatively, "dbstep N" has been used but the end | |
1133 // of the frame has been reached so we stop at the last line and | |
1134 // return to prompt. | |
1135 | |
1136 break_on_this_statement = true; | |
1137 | |
1138 dbstep_flag = 0; | |
1139 } | |
1140 else | |
1141 { | |
1142 // Executing "dbstep N". Decrease N by one and continue. | |
1143 | |
1144 dbstep_flag--; | |
1145 } | |
1146 | |
1147 } | |
1148 else if (dbstep_flag == 1 | |
1149 && octave_call_stack::current_frame () < current_frame) | |
1150 { | |
1151 // We stepped out from the end of a function. | |
1152 | |
1153 current_frame = octave_call_stack::current_frame (); | |
1154 | |
1155 break_on_this_statement = true; | |
1156 | |
1157 dbstep_flag = 0; | |
1158 } | |
1159 } | |
1160 else if (dbstep_flag == -1) | |
1161 { | |
1162 // We get here if we are doing a "dbstep in". | |
1163 | |
1164 break_on_this_statement = true; | |
1165 | |
1166 dbstep_flag = 0; | |
1167 | |
1168 current_frame = octave_call_stack::current_frame (); | |
1169 } | |
1170 else if (dbstep_flag == -2) | |
1171 { | |
1172 // We get here if we are doing a "dbstep out". Check for end of | |
1173 // function and whether the current frame is the same as the | |
1174 // cached value because we want to step out from the frame where | |
1175 // "dbstep out" was evaluated, not from any functions called from | |
1176 // that frame. | |
1177 | |
1178 if (is_end_of_fcn_or_script | |
1179 && octave_call_stack::current_frame () == current_frame) | |
1180 dbstep_flag = -1; | |
1181 } | |
1182 | |
1183 if (break_on_this_statement) | |
1184 do_keyboard (); | |
1185 | |
1186 } | |
1187 | |
1188 // ARGS is currently unused, but since the do_keyboard function in | |
1189 // input.cc accepts an argument list, we preserve it here so that the | |
1190 // interface won't have to change if we decide to use it in the future. | |
1191 | |
1192 octave_value | |
1193 tree_evaluator::do_keyboard (const octave_value_list& args) const | |
1194 { | |
1195 return ::do_keyboard (args); | |
1196 } | 1179 } |
1197 | 1180 |
1198 DEFUN (max_recursion_depth, args, nargout, | 1181 DEFUN (max_recursion_depth, args, nargout, |
1199 doc: /* -*- texinfo -*- | 1182 doc: /* -*- texinfo -*- |
1200 @deftypefn {} {@var{val} =} max_recursion_depth () | 1183 @deftypefn {} {@var{val} =} max_recursion_depth () |