Mercurial > octave-nkf
annotate src/pt-check.cc @ 7715:5b4d278ec828
parse scripts completely before executing
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Wed, 16 Apr 2008 15:09:56 -0400 |
parents | a1dbe9d80eee |
children | 73c4516fae10 |
rev | line source |
---|---|
3011 | 1 /* |
2 | |
7017 | 3 Copyright (C) 1996, 1997, 2000, 2002, 2003, 2004, 2005, 2006, 2007 |
4 John W. Eaton | |
3011 | 5 |
6 This file is part of Octave. | |
7 | |
8 Octave is free software; you can redistribute it and/or modify it | |
9 under the terms of the GNU General Public License as published by the | |
7016 | 10 Free Software Foundation; either version 3 of the License, or (at your |
11 option) any later version. | |
3011 | 12 |
13 Octave is distributed in the hope that it will be useful, but WITHOUT | |
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
16 for more details. | |
17 | |
18 You should have received a copy of the GNU General Public License | |
7016 | 19 along with Octave; see the file COPYING. If not, see |
20 <http://www.gnu.org/licenses/>. | |
3011 | 21 |
22 */ | |
23 | |
24 #ifdef HAVE_CONFIG_H | |
25 #include <config.h> | |
26 #endif | |
27 | |
28 #include "error.h" | |
29 #include "input.h" | |
30 #include "ov-usr-fcn.h" | |
31 #include "pt-all.h" | |
32 | |
33 void | |
34 tree_checker::visit_argument_list (tree_argument_list& lst) | |
35 { | |
4219 | 36 tree_argument_list::iterator p = lst.begin (); |
3011 | 37 |
4219 | 38 while (p != lst.end ()) |
3011 | 39 { |
4219 | 40 tree_expression *elt = *p++; |
3011 | 41 |
42 if (elt) | |
43 { | |
44 if (do_lvalue_check && ! elt->lvalue_ok ()) | |
45 gripe ("invalid lvalue in multiple assignment", elt->line ()); | |
46 } | |
47 } | |
48 } | |
49 | |
50 void | |
51 tree_checker::visit_binary_expression (tree_binary_expression& expr) | |
52 { | |
53 tree_expression *op1 = expr.lhs (); | |
54 | |
55 if (op1) | |
56 op1->accept (*this); | |
57 | |
58 tree_expression *op2 = expr.rhs (); | |
59 | |
60 if (op2) | |
61 op2->accept (*this); | |
62 } | |
63 | |
64 void | |
4207 | 65 tree_checker::visit_break_command (tree_break_command&) |
3011 | 66 { |
67 } | |
68 | |
69 void | |
70 tree_checker::visit_colon_expression (tree_colon_expression& expr) | |
71 { | |
72 tree_expression *op1 = expr.base (); | |
73 | |
74 if (op1) | |
75 op1->accept (*this); | |
76 | |
77 tree_expression *op3 = expr.increment (); | |
78 | |
79 if (op3) | |
80 op3->accept (*this); | |
81 | |
82 tree_expression *op2 = expr.limit (); | |
83 | |
84 if (op2) | |
85 op2->accept (*this); | |
86 } | |
87 | |
88 void | |
4207 | 89 tree_checker::visit_continue_command (tree_continue_command&) |
3011 | 90 { |
91 } | |
92 | |
93 void | |
94 tree_checker::visit_decl_command (tree_decl_command& cmd) | |
95 { | |
96 tree_decl_init_list *init_list = cmd.initializer_list (); | |
97 | |
98 if (init_list) | |
99 init_list->accept (*this); | |
100 } | |
101 | |
102 void | |
103 tree_checker::visit_decl_elt (tree_decl_elt& cmd) | |
104 { | |
105 tree_identifier *id = cmd.ident (); | |
106 | |
107 if (id) | |
108 id->accept (*this); | |
109 | |
110 tree_expression *expr = cmd.expression (); | |
111 | |
112 if (expr) | |
113 expr->accept (*this); | |
114 } | |
115 | |
116 void | |
117 tree_checker::visit_decl_init_list (tree_decl_init_list& lst) | |
118 { | |
4219 | 119 tree_decl_init_list::iterator p = lst.begin (); |
3011 | 120 |
4219 | 121 while (p != lst.end ()) |
3011 | 122 { |
4219 | 123 tree_decl_elt *elt = *p++; |
3011 | 124 |
125 if (elt) | |
126 elt->accept (*this); | |
127 } | |
128 } | |
129 | |
130 void | |
131 tree_checker::visit_simple_for_command (tree_simple_for_command& cmd) | |
132 { | |
133 tree_expression *lhs = cmd.left_hand_side (); | |
134 | |
135 if (lhs) | |
136 { | |
137 if (! lhs->lvalue_ok ()) | |
138 gripe ("invalid lvalue in for command", cmd.line ()); | |
139 } | |
140 | |
141 tree_expression *expr = cmd.control_expr (); | |
142 | |
143 if (expr) | |
144 expr->accept (*this); | |
145 | |
146 tree_statement_list *list = cmd.body (); | |
147 | |
148 if (list) | |
149 list->accept (*this); | |
150 } | |
151 | |
152 void | |
153 tree_checker::visit_complex_for_command (tree_complex_for_command& cmd) | |
154 { | |
155 tree_argument_list *lhs = cmd.left_hand_side (); | |
156 | |
157 if (lhs) | |
158 { | |
159 int len = lhs->length (); | |
160 | |
3018 | 161 if (len == 0 || len > 2) |
3011 | 162 gripe ("invalid number of output arguments in for command", |
163 cmd.line ()); | |
164 | |
165 do_lvalue_check = true; | |
166 | |
167 lhs->accept (*this); | |
168 | |
169 do_lvalue_check = false; | |
170 } | |
171 | |
172 tree_expression *expr = cmd.control_expr (); | |
173 | |
174 if (expr) | |
175 expr->accept (*this); | |
176 | |
177 tree_statement_list *list = cmd.body (); | |
178 | |
179 if (list) | |
180 list->accept (*this); | |
181 } | |
182 | |
183 void | |
7715
5b4d278ec828
parse scripts completely before executing
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
184 tree_checker::visit_octave_user_script (octave_user_script& fcn) |
5b4d278ec828
parse scripts completely before executing
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
185 { |
5b4d278ec828
parse scripts completely before executing
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
186 tree_statement_list *cmd_list = fcn.body (); |
5b4d278ec828
parse scripts completely before executing
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
187 |
5b4d278ec828
parse scripts completely before executing
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
188 if (cmd_list) |
5b4d278ec828
parse scripts completely before executing
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
189 cmd_list->accept (*this); |
5b4d278ec828
parse scripts completely before executing
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
190 } |
5b4d278ec828
parse scripts completely before executing
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
191 |
5b4d278ec828
parse scripts completely before executing
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
192 void |
3011 | 193 tree_checker::visit_octave_user_function (octave_user_function& fcn) |
194 { | |
195 tree_statement_list *cmd_list = fcn.body (); | |
196 | |
197 if (cmd_list) | |
198 cmd_list->accept (*this); | |
199 } | |
200 | |
201 void | |
7715
5b4d278ec828
parse scripts completely before executing
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
202 tree_checker::visit_function_def (tree_function_def& fdef) |
5b4d278ec828
parse scripts completely before executing
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
203 { |
5b4d278ec828
parse scripts completely before executing
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
204 octave_function *fcn = fdef.function (); |
5b4d278ec828
parse scripts completely before executing
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
205 |
5b4d278ec828
parse scripts completely before executing
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
206 if (fcn) |
5b4d278ec828
parse scripts completely before executing
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
207 fcn->accept (*this); |
5b4d278ec828
parse scripts completely before executing
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
208 } |
5b4d278ec828
parse scripts completely before executing
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
209 |
5b4d278ec828
parse scripts completely before executing
John W. Eaton <jwe@octave.org>
parents:
7017
diff
changeset
|
210 void |
3011 | 211 tree_checker::visit_identifier (tree_identifier& /* id */) |
212 { | |
213 } | |
214 | |
215 void | |
216 tree_checker::visit_if_clause (tree_if_clause& cmd) | |
217 { | |
218 tree_expression *expr = cmd.condition (); | |
219 | |
220 if (expr) | |
221 expr->accept (*this); | |
222 | |
223 tree_statement_list *list = cmd.commands (); | |
224 | |
225 if (list) | |
226 list->accept (*this); | |
227 } | |
228 | |
229 void | |
230 tree_checker::visit_if_command (tree_if_command& cmd) | |
231 { | |
232 tree_if_command_list *list = cmd.cmd_list (); | |
233 | |
234 if (list) | |
235 list->accept (*this); | |
236 } | |
237 | |
238 void | |
239 tree_checker::visit_if_command_list (tree_if_command_list& lst) | |
240 { | |
4219 | 241 tree_if_command_list::iterator p = lst.begin (); |
3011 | 242 |
4219 | 243 while (p != lst.end ()) |
3011 | 244 { |
4219 | 245 tree_if_clause *elt = *p++; |
3011 | 246 |
247 if (elt) | |
248 elt->accept (*this); | |
249 } | |
250 } | |
251 | |
252 void | |
253 tree_checker::visit_index_expression (tree_index_expression& expr) | |
254 { | |
255 tree_expression *e = expr.expression (); | |
256 | |
257 if (e) | |
258 e->accept (*this); | |
259 | |
4219 | 260 std::list<tree_argument_list *> lst = expr.arg_lists (); |
3933 | 261 |
4219 | 262 std::list<tree_argument_list *>::iterator p = lst.begin (); |
3011 | 263 |
4219 | 264 while (p != lst.end ()) |
3933 | 265 { |
4219 | 266 tree_argument_list *elt = *p++; |
3933 | 267 |
268 if (elt) | |
269 elt->accept (*this); | |
270 } | |
3011 | 271 } |
272 | |
273 void | |
274 tree_checker::visit_matrix (tree_matrix& lst) | |
275 { | |
4219 | 276 tree_matrix::iterator p = lst.begin (); |
3011 | 277 |
4219 | 278 while (p != lst.end ()) |
3011 | 279 { |
4219 | 280 tree_argument_list *elt = *p++; |
281 | |
282 if (elt) | |
283 elt->accept (*this); | |
284 } | |
285 } | |
3011 | 286 |
4219 | 287 void |
288 tree_checker::visit_cell (tree_cell& lst) | |
289 { | |
290 tree_matrix::iterator p = lst.begin (); | |
291 | |
292 while (p != lst.end ()) | |
293 { | |
294 tree_argument_list *elt = *p++; | |
3011 | 295 |
296 if (elt) | |
297 elt->accept (*this); | |
298 } | |
299 } | |
300 | |
301 void | |
302 tree_checker::visit_multi_assignment (tree_multi_assignment& expr) | |
303 { | |
304 tree_argument_list *lhs = expr.left_hand_side (); | |
305 | |
306 if (lhs) | |
307 { | |
308 do_lvalue_check = true; | |
309 | |
310 lhs->accept (*this); | |
311 | |
312 do_lvalue_check = false; | |
313 } | |
314 | |
315 tree_expression *rhs = expr.right_hand_side (); | |
316 | |
317 if (rhs) | |
318 rhs->accept (*this); | |
319 } | |
320 | |
321 void | |
322 tree_checker::visit_no_op_command (tree_no_op_command& /* cmd */) | |
323 { | |
324 } | |
325 | |
326 void | |
5861 | 327 tree_checker::visit_anon_fcn_handle (tree_anon_fcn_handle& /* afh */) |
328 { | |
329 } | |
330 | |
331 void | |
3011 | 332 tree_checker::visit_constant (tree_constant& /* val */) |
333 { | |
334 } | |
335 | |
336 void | |
4342 | 337 tree_checker::visit_fcn_handle (tree_fcn_handle& /* fh */) |
338 { | |
339 } | |
340 | |
341 void | |
3011 | 342 tree_checker::visit_parameter_list (tree_parameter_list& lst) |
343 { | |
4219 | 344 tree_parameter_list::iterator p = lst.begin (); |
3011 | 345 |
4219 | 346 while (p != lst.end ()) |
3011 | 347 { |
6215 | 348 tree_decl_elt *elt = *p++; |
3011 | 349 |
350 if (elt) | |
351 elt->accept (*this); | |
352 } | |
353 } | |
354 | |
355 void | |
356 tree_checker::visit_postfix_expression (tree_postfix_expression& expr) | |
357 { | |
358 tree_expression *e = expr.operand (); | |
359 | |
360 if (e) | |
361 e->accept (*this); | |
362 } | |
363 | |
364 void | |
365 tree_checker::visit_prefix_expression (tree_prefix_expression& expr) | |
366 { | |
367 tree_expression *e = expr.operand (); | |
368 | |
369 if (e) | |
370 e->accept (*this); | |
371 } | |
372 | |
373 void | |
4207 | 374 tree_checker::visit_return_command (tree_return_command&) |
3011 | 375 { |
376 } | |
377 | |
378 void | |
379 tree_checker::visit_return_list (tree_return_list& lst) | |
380 { | |
4219 | 381 tree_return_list::iterator p = lst.begin (); |
3011 | 382 |
4219 | 383 while (p != lst.end ()) |
3011 | 384 { |
4219 | 385 tree_index_expression *elt = *p++; |
3011 | 386 |
387 if (elt) | |
388 elt->accept (*this); | |
389 } | |
390 } | |
391 | |
392 void | |
393 tree_checker::visit_simple_assignment (tree_simple_assignment& expr) | |
394 { | |
395 tree_expression *lhs = expr.left_hand_side (); | |
396 | |
397 if (lhs) | |
398 { | |
399 if (! lhs->lvalue_ok ()) | |
400 gripe ("invalid lvalue in assignment", expr.line ()); | |
401 } | |
402 | |
403 tree_expression *rhs = expr.right_hand_side (); | |
404 | |
405 if (rhs) | |
406 rhs->accept (*this); | |
407 } | |
408 | |
409 void | |
410 tree_checker::visit_statement (tree_statement& stmt) | |
411 { | |
412 tree_command *cmd = stmt.command (); | |
413 | |
414 if (cmd) | |
415 cmd->accept (*this); | |
416 else | |
417 { | |
418 tree_expression *expr = stmt.expression (); | |
419 | |
420 if (expr) | |
421 expr->accept (*this); | |
422 } | |
423 } | |
424 | |
425 void | |
426 tree_checker::visit_statement_list (tree_statement_list& lst) | |
427 { | |
4219 | 428 for (tree_statement_list::iterator p = lst.begin (); p != lst.end (); p++) |
3011 | 429 { |
4219 | 430 tree_statement *elt = *p; |
3011 | 431 |
432 if (elt) | |
433 elt->accept (*this); | |
434 } | |
435 } | |
436 | |
437 void | |
438 tree_checker::visit_switch_case (tree_switch_case& cs) | |
439 { | |
440 tree_expression *label = cs.case_label (); | |
441 | |
442 if (label) | |
443 label->accept (*this); | |
444 | |
445 tree_statement_list *list = cs.commands (); | |
446 | |
447 if (list) | |
448 list->accept (*this); | |
449 } | |
450 | |
451 void | |
452 tree_checker::visit_switch_case_list (tree_switch_case_list& lst) | |
453 { | |
4219 | 454 tree_switch_case_list::iterator p = lst.begin (); |
3011 | 455 |
4219 | 456 while (p != lst.end ()) |
3011 | 457 { |
4219 | 458 tree_switch_case *elt = *p++; |
3011 | 459 |
460 if (elt) | |
461 elt->accept (*this); | |
462 } | |
463 } | |
464 | |
465 void | |
466 tree_checker::visit_switch_command (tree_switch_command& cmd) | |
467 { | |
468 tree_expression *expr = cmd.switch_value (); | |
469 | |
470 if (expr) | |
471 expr->accept (*this); | |
472 | |
473 tree_switch_case_list *list = cmd.case_list (); | |
474 | |
475 if (list) | |
476 list->accept (*this); | |
477 } | |
478 | |
479 void | |
480 tree_checker::visit_try_catch_command (tree_try_catch_command& cmd) | |
481 { | |
482 tree_statement_list *try_code = cmd.body (); | |
483 | |
484 if (try_code) | |
485 try_code->accept (*this); | |
486 | |
487 tree_statement_list *catch_code = cmd.cleanup (); | |
488 | |
489 if (catch_code) | |
490 catch_code->accept (*this); | |
491 } | |
492 | |
493 void | |
494 tree_checker::visit_unwind_protect_command | |
495 (tree_unwind_protect_command& cmd) | |
496 { | |
497 tree_statement_list *unwind_protect_code = cmd.body (); | |
498 | |
499 if (unwind_protect_code) | |
500 unwind_protect_code->accept (*this); | |
501 | |
502 tree_statement_list *cleanup_code = cmd.cleanup (); | |
503 | |
504 if (cleanup_code) | |
505 cleanup_code->accept (*this); | |
506 } | |
507 | |
508 void | |
509 tree_checker::visit_while_command (tree_while_command& cmd) | |
510 { | |
511 tree_expression *expr = cmd.condition (); | |
512 | |
513 if (expr) | |
514 expr->accept (*this); | |
515 | |
516 tree_statement_list *list = cmd.body (); | |
517 | |
518 if (list) | |
519 list->accept (*this); | |
520 } | |
521 | |
522 void | |
4229 | 523 tree_checker::visit_do_until_command (tree_do_until_command& cmd) |
524 { | |
525 tree_statement_list *list = cmd.body (); | |
526 | |
527 if (list) | |
528 list->accept (*this); | |
529 | |
530 tree_expression *expr = cmd.condition (); | |
531 | |
532 if (expr) | |
533 expr->accept (*this); | |
534 } | |
535 | |
536 void | |
3523 | 537 tree_checker::gripe (const std::string& msg, int line) |
3011 | 538 { |
539 if (curr_fcn_file_name.empty ()) | |
540 error ("%s", msg.c_str ()); | |
541 else | |
542 error ("%s: %d: %s", curr_fcn_file_name.c_str (), line, msg.c_str ()); | |
543 } | |
544 | |
545 /* | |
546 ;;; Local Variables: *** | |
547 ;;; mode: C++ *** | |
548 ;;; End: *** | |
549 */ |