Mercurial > hg > octave-nkf
annotate src/pt-stmt.cc @ 7767:71f068b22fcc
scope and context fixes for function handles
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Wed, 07 May 2008 13:45:30 -0400 |
parents | 40c428ea3408 |
children | 73ef513855e7 |
rev | line source |
---|---|
2982 | 1 /* |
2 | |
7017 | 3 Copyright (C) 1996, 1997, 1999, 2000, 2001, 2002, 2003, 2004, 2005, |
4 2006, 2007 John W. Eaton | |
2982 | 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. | |
2982 | 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/>. | |
2982 | 21 |
22 */ | |
23 | |
24 #ifdef HAVE_CONFIG_H | |
25 #include <config.h> | |
26 #endif | |
27 | |
4153 | 28 #include "quit.h" |
29 | |
2982 | 30 #include "defun.h" |
31 #include "error.h" | |
32 #include "ov.h" | |
33 #include "oct-lvalue.h" | |
34 #include "input.h" | |
35 #include "pager.h" | |
3770 | 36 #include "pt-bp.h" |
2982 | 37 #include "pt-cmd.h" |
38 #include "pt-id.h" | |
39 #include "pt-idx.h" | |
2985 | 40 #include "pt-jump.h" |
2982 | 41 #include "pt-pr-code.h" |
42 #include "pt-stmt.h" | |
43 #include "pt-walk.h" | |
3707 | 44 #include "unwind-prot.h" |
2982 | 45 #include "utils.h" |
46 #include "variables.h" | |
47 | |
48 // A list of commands to be executed. | |
49 | |
50 tree_statement::~tree_statement (void) | |
51 { | |
52 delete cmd; | |
53 delete expr; | |
3665 | 54 delete comm; |
2982 | 55 } |
56 | |
57 int | |
58 tree_statement::line (void) | |
59 { | |
60 return cmd ? cmd->line () : (expr ? expr->line () : -1); | |
61 } | |
62 | |
63 int | |
64 tree_statement::column (void) | |
65 { | |
66 return cmd ? cmd->column () : (expr ? expr->column () : -1); | |
67 } | |
68 | |
69 void | |
7736 | 70 tree_statement::maybe_echo_code (bool in_function_or_script_body) |
2982 | 71 { |
7736 | 72 if (in_function_or_script_body |
2982 | 73 && (Vecho_executing_commands & ECHO_FUNCTIONS)) |
74 { | |
5794 | 75 tree_print_code tpc (octave_stdout, VPS4); |
2982 | 76 |
77 accept (tpc); | |
78 } | |
79 } | |
80 | |
81 octave_value_list | |
7736 | 82 tree_statement::eval (bool silent, int nargout, |
83 bool in_function_or_script_body) | |
2982 | 84 { |
85 octave_value_list retval; | |
86 | |
87 bool pf = silent ? false : print_flag; | |
88 | |
89 if (cmd || expr) | |
90 { | |
7752
40c428ea3408
initial implementation of dbup and dbdown
John W. Eaton <jwe@octave.org>
parents:
7736
diff
changeset
|
91 if (! (symbol_table::at_top_level () || Vdebugging)) |
7736 | 92 octave_call_stack::set_statement (this); |
3708 | 93 |
7736 | 94 maybe_echo_code (in_function_or_script_body); |
2982 | 95 |
7481
78f3811155f7
use exceptions in liboctave error handler
John W. Eaton <jwe@octave.org>
parents:
7336
diff
changeset
|
96 try |
2982 | 97 { |
7481
78f3811155f7
use exceptions in liboctave error handler
John W. Eaton <jwe@octave.org>
parents:
7336
diff
changeset
|
98 if (cmd) |
78f3811155f7
use exceptions in liboctave error handler
John W. Eaton <jwe@octave.org>
parents:
7336
diff
changeset
|
99 cmd->eval (); |
78f3811155f7
use exceptions in liboctave error handler
John W. Eaton <jwe@octave.org>
parents:
7336
diff
changeset
|
100 else |
78f3811155f7
use exceptions in liboctave error handler
John W. Eaton <jwe@octave.org>
parents:
7336
diff
changeset
|
101 { |
78f3811155f7
use exceptions in liboctave error handler
John W. Eaton <jwe@octave.org>
parents:
7336
diff
changeset
|
102 expr->set_print_flag (pf); |
2982 | 103 |
7481
78f3811155f7
use exceptions in liboctave error handler
John W. Eaton <jwe@octave.org>
parents:
7336
diff
changeset
|
104 // FIXME -- maybe all of this should be packaged in |
78f3811155f7
use exceptions in liboctave error handler
John W. Eaton <jwe@octave.org>
parents:
7336
diff
changeset
|
105 // one virtual function that returns a flag saying whether |
78f3811155f7
use exceptions in liboctave error handler
John W. Eaton <jwe@octave.org>
parents:
7336
diff
changeset
|
106 // or not the expression will take care of binding ans and |
78f3811155f7
use exceptions in liboctave error handler
John W. Eaton <jwe@octave.org>
parents:
7336
diff
changeset
|
107 // printing the result. |
2982 | 108 |
7481
78f3811155f7
use exceptions in liboctave error handler
John W. Eaton <jwe@octave.org>
parents:
7336
diff
changeset
|
109 // FIXME -- it seems that we should just have to |
78f3811155f7
use exceptions in liboctave error handler
John W. Eaton <jwe@octave.org>
parents:
7336
diff
changeset
|
110 // call expr->rvalue () and that should take care of |
78f3811155f7
use exceptions in liboctave error handler
John W. Eaton <jwe@octave.org>
parents:
7336
diff
changeset
|
111 // everything, binding ans as necessary? |
78f3811155f7
use exceptions in liboctave error handler
John W. Eaton <jwe@octave.org>
parents:
7336
diff
changeset
|
112 |
78f3811155f7
use exceptions in liboctave error handler
John W. Eaton <jwe@octave.org>
parents:
7336
diff
changeset
|
113 bool do_bind_ans = false; |
4203 | 114 |
7481
78f3811155f7
use exceptions in liboctave error handler
John W. Eaton <jwe@octave.org>
parents:
7336
diff
changeset
|
115 if (expr->is_identifier ()) |
78f3811155f7
use exceptions in liboctave error handler
John W. Eaton <jwe@octave.org>
parents:
7336
diff
changeset
|
116 { |
78f3811155f7
use exceptions in liboctave error handler
John W. Eaton <jwe@octave.org>
parents:
7336
diff
changeset
|
117 tree_identifier *id = dynamic_cast<tree_identifier *> (expr); |
2982 | 118 |
7481
78f3811155f7
use exceptions in liboctave error handler
John W. Eaton <jwe@octave.org>
parents:
7336
diff
changeset
|
119 do_bind_ans = (! id->is_variable ()); |
78f3811155f7
use exceptions in liboctave error handler
John W. Eaton <jwe@octave.org>
parents:
7336
diff
changeset
|
120 } |
78f3811155f7
use exceptions in liboctave error handler
John W. Eaton <jwe@octave.org>
parents:
7336
diff
changeset
|
121 else |
78f3811155f7
use exceptions in liboctave error handler
John W. Eaton <jwe@octave.org>
parents:
7336
diff
changeset
|
122 do_bind_ans = (! expr->is_assignment_expression ()); |
2982 | 123 |
7481
78f3811155f7
use exceptions in liboctave error handler
John W. Eaton <jwe@octave.org>
parents:
7336
diff
changeset
|
124 retval = expr->rvalue (nargout); |
78f3811155f7
use exceptions in liboctave error handler
John W. Eaton <jwe@octave.org>
parents:
7336
diff
changeset
|
125 |
78f3811155f7
use exceptions in liboctave error handler
John W. Eaton <jwe@octave.org>
parents:
7336
diff
changeset
|
126 if (do_bind_ans && ! (error_state || retval.empty ())) |
78f3811155f7
use exceptions in liboctave error handler
John W. Eaton <jwe@octave.org>
parents:
7336
diff
changeset
|
127 bind_ans (retval(0), pf); |
2982 | 128 } |
7481
78f3811155f7
use exceptions in liboctave error handler
John W. Eaton <jwe@octave.org>
parents:
7336
diff
changeset
|
129 } |
78f3811155f7
use exceptions in liboctave error handler
John W. Eaton <jwe@octave.org>
parents:
7336
diff
changeset
|
130 catch (octave_execution_exception) |
78f3811155f7
use exceptions in liboctave error handler
John W. Eaton <jwe@octave.org>
parents:
7336
diff
changeset
|
131 { |
78f3811155f7
use exceptions in liboctave error handler
John W. Eaton <jwe@octave.org>
parents:
7336
diff
changeset
|
132 octave_exception_state = octave_no_exception; |
78f3811155f7
use exceptions in liboctave error handler
John W. Eaton <jwe@octave.org>
parents:
7336
diff
changeset
|
133 error ("caught execution error in library function"); |
2982 | 134 } |
135 } | |
136 | |
137 return retval; | |
138 } | |
139 | |
5861 | 140 tree_statement * |
7767
71f068b22fcc
scope and context fixes for function handles
John W. Eaton <jwe@octave.org>
parents:
7752
diff
changeset
|
141 tree_statement::dup (symbol_table::scope_id scope, |
71f068b22fcc
scope and context fixes for function handles
John W. Eaton <jwe@octave.org>
parents:
7752
diff
changeset
|
142 symbol_table::context_id context) |
5861 | 143 { |
144 tree_statement *new_stmt = new tree_statement (); | |
145 | |
7767
71f068b22fcc
scope and context fixes for function handles
John W. Eaton <jwe@octave.org>
parents:
7752
diff
changeset
|
146 new_stmt->cmd = cmd ? cmd->dup (scope, context) : 0; |
5861 | 147 |
7767
71f068b22fcc
scope and context fixes for function handles
John W. Eaton <jwe@octave.org>
parents:
7752
diff
changeset
|
148 new_stmt->expr = expr ? expr->dup (scope, context) : 0; |
5861 | 149 |
150 new_stmt->comm = comm ? comm->dup () : 0; | |
151 | |
152 new_stmt->print_flag = print_flag; | |
153 | |
154 return new_stmt; | |
155 } | |
156 | |
2982 | 157 void |
158 tree_statement::accept (tree_walker& tw) | |
159 { | |
160 tw.visit_statement (*this); | |
161 } | |
162 | |
163 octave_value_list | |
164 tree_statement_list::eval (bool silent, int nargout) | |
165 { | |
166 octave_value_list retval; | |
167 | |
5858 | 168 static octave_value_list empty_list; |
169 | |
2982 | 170 if (error_state) |
171 return retval; | |
172 | |
5858 | 173 iterator p = begin (); |
2982 | 174 |
5858 | 175 if (p != end ()) |
176 { | |
177 while (true) | |
2982 | 178 { |
5858 | 179 tree_statement *elt = *p++; |
180 | |
181 if (elt) | |
182 { | |
183 OCTAVE_QUIT; | |
4153 | 184 |
7736 | 185 retval = elt->eval (silent, nargout, |
186 function_body || script_body); | |
5858 | 187 |
188 if (error_state) | |
189 break; | |
190 | |
191 if (tree_break_command::breaking | |
192 || tree_continue_command::continuing) | |
193 break; | |
194 | |
195 if (tree_return_command::returning) | |
196 break; | |
5855 | 197 |
5858 | 198 if (p == end ()) |
199 break; | |
200 else | |
201 { | |
202 // Clear preivous values before next statement is | |
203 // evaluated so that we aren't holding an extra | |
204 // reference to a value that may be used next. For | |
205 // example, in code like this: | |
206 // | |
207 // X = rand (N); ## refcount for X should be 1 | |
208 // ## after this statement | |
209 // | |
210 // X(idx) = val; ## no extra copy of X should be | |
211 // ## needed, but we will be faked | |
212 // ## out if retval is not cleared | |
213 // ## between statements here | |
2982 | 214 |
5858 | 215 retval = empty_list; |
216 } | |
217 } | |
218 else | |
219 error ("invalid statement found in statement list!"); | |
2982 | 220 } |
221 } | |
222 | |
223 return retval; | |
224 } | |
225 | |
3770 | 226 int |
227 tree_statement_list::set_breakpoint (int line) | |
228 { | |
229 tree_breakpoint tbp (line, tree_breakpoint::set); | |
230 accept (tbp); | |
231 | |
232 return tbp.get_line (); | |
233 } | |
234 | |
235 void | |
236 tree_statement_list::delete_breakpoint (int line) | |
237 { | |
3895 | 238 if (line < 0) |
239 { | |
4212 | 240 octave_value_list bp_lst = list_breakpoints (); |
3895 | 241 |
4212 | 242 int len = bp_lst.length (); |
3895 | 243 |
4587 | 244 for (int i = 0; i < len; i++) |
3895 | 245 { |
4587 | 246 tree_breakpoint tbp (i, tree_breakpoint::clear); |
3895 | 247 accept (tbp); |
248 } | |
249 } | |
250 else | |
251 { | |
252 tree_breakpoint tbp (line, tree_breakpoint::clear); | |
253 accept (tbp); | |
254 } | |
3770 | 255 } |
256 | |
257 octave_value_list | |
258 tree_statement_list::list_breakpoints (void) | |
259 { | |
260 tree_breakpoint tbp (0, tree_breakpoint::list); | |
261 accept (tbp); | |
262 | |
263 return tbp.get_list (); | |
264 } | |
265 | |
5861 | 266 tree_statement_list * |
7767
71f068b22fcc
scope and context fixes for function handles
John W. Eaton <jwe@octave.org>
parents:
7752
diff
changeset
|
267 tree_statement_list::dup (symbol_table::scope_id scope, |
71f068b22fcc
scope and context fixes for function handles
John W. Eaton <jwe@octave.org>
parents:
7752
diff
changeset
|
268 symbol_table::context_id context) |
5861 | 269 { |
270 tree_statement_list *new_list = new tree_statement_list (); | |
271 | |
272 new_list->function_body = function_body; | |
273 | |
274 for (iterator p = begin (); p != end (); p++) | |
275 { | |
276 tree_statement *elt = *p; | |
277 | |
7767
71f068b22fcc
scope and context fixes for function handles
John W. Eaton <jwe@octave.org>
parents:
7752
diff
changeset
|
278 new_list->append (elt ? elt->dup (scope, context) : 0); |
5861 | 279 } |
280 | |
281 return new_list; | |
282 } | |
283 | |
2982 | 284 void |
285 tree_statement_list::accept (tree_walker& tw) | |
286 { | |
287 tw.visit_statement_list (*this); | |
288 } | |
289 | |
290 /* | |
291 ;;; Local Variables: *** | |
292 ;;; mode: C++ *** | |
293 ;;; End: *** | |
294 */ |