Mercurial > hg > octave-nkf
annotate src/symtab.cc @ 7752:40c428ea3408
initial implementation of dbup and dbdown
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Sun, 04 May 2008 03:42:19 -0400 |
parents | 0ff0fc033f28 |
children | 5adeea5de26c |
rev | line source |
---|---|
1 | 1 /* |
2 | |
7017 | 3 Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, |
4 2002, 2003, 2004, 2005, 2006, 2007 John W. Eaton | |
7336 | 5 |
1 | 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. | |
1 | 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/>. | |
1 | 21 |
22 */ | |
23 | |
240 | 24 #ifdef HAVE_CONFIG_H |
1192 | 25 #include <config.h> |
1 | 26 #endif |
27 | |
7336 | 28 #include "oct-env.h" |
29 #include "oct-time.h" | |
30 #include "file-ops.h" | |
31 #include "file-stat.h" | |
1755 | 32 |
3308 | 33 #include "defun.h" |
7336 | 34 #include "dirfns.h" |
35 #include "input.h" | |
36 #include "load-path.h" | |
1755 | 37 #include "symtab.h" |
7336 | 38 #include "ov-fcn.h" |
39 #include "pager.h" | |
40 #include "parse.h" | |
41 #include "pt-arg-list.h" | |
42 #include "toplev.h" | |
43 #include "unwind-prot.h" | |
1 | 44 #include "utils.h" |
7336 | 45 |
46 symbol_table *symbol_table::instance = 0; | |
1 | 47 |
7336 | 48 std::map<symbol_table::scope_id, symbol_table*> symbol_table::all_instances; |
4913 | 49 |
7752
40c428ea3408
initial implementation of dbup and dbdown
John W. Eaton <jwe@octave.org>
parents:
7745
diff
changeset
|
50 std::map<std::string, octave_value> symbol_table::global_table; |
40c428ea3408
initial implementation of dbup and dbdown
John W. Eaton <jwe@octave.org>
parents:
7745
diff
changeset
|
51 |
7336 | 52 std::map<std::string, symbol_table::fcn_info> symbol_table::fcn_table; |
4913 | 53 |
7336 | 54 const symbol_table::scope_id symbol_table::xglobal_scope = 0; |
55 const symbol_table::scope_id symbol_table::xtop_scope = 1; | |
4238 | 56 |
7336 | 57 symbol_table::scope_id symbol_table::xcurrent_scope = 1; |
58 symbol_table::scope_id symbol_table::xcurrent_caller_scope = -1; | |
3308 | 59 |
7336 | 60 symbol_table::scope_id symbol_table::xparent_scope = -1; |
61 | |
62 std::deque<symbol_table::scope_id> symbol_table::scope_stack; | |
4238 | 63 |
7336 | 64 symbol_table::scope_id symbol_table::next_available_scope = 2; |
65 std::set<symbol_table::scope_id> symbol_table::scope_ids_in_use; | |
66 std::set<symbol_table::scope_id> symbol_table::scope_ids_free_list; | |
195 | 67 |
7752
40c428ea3408
initial implementation of dbup and dbdown
John W. Eaton <jwe@octave.org>
parents:
7745
diff
changeset
|
68 symbol_table::context_id symbol_table::xcurrent_context = 0; |
40c428ea3408
initial implementation of dbup and dbdown
John W. Eaton <jwe@octave.org>
parents:
7745
diff
changeset
|
69 |
7336 | 70 // Should Octave always check to see if function files have changed |
71 // since they were last compiled? | |
72 static int Vignore_function_time_stamp = 1; | |
3355 | 73 |
7336 | 74 octave_value |
75 symbol_table::symbol_record::find (tree_argument_list *args, | |
76 const string_vector& arg_names, | |
77 octave_value_list& evaluated_args, | |
78 bool& args_evaluated) const | |
79 { | |
80 octave_value retval; | |
3355 | 81 |
7336 | 82 if (is_global ()) |
7752
40c428ea3408
initial implementation of dbup and dbdown
John W. Eaton <jwe@octave.org>
parents:
7745
diff
changeset
|
83 return symbol_table::global_varref (name ()); |
7336 | 84 else |
85 { | |
86 octave_value val = varval (); | |
87 | |
88 if (val.is_defined ()) | |
89 return val; | |
90 } | |
91 | |
92 return symbol_table::find_function (name (), args, arg_names, | |
93 evaluated_args, args_evaluated); | |
3355 | 94 } |
95 | |
7336 | 96 // Check the load path to see if file that defined this is still |
97 // visible. If the file is no longer visible, then erase the | |
98 // definition and move on. If the file is visible, then we also | |
99 // need to check to see whether the file has changed since the the | |
100 // function was loaded/parsed. However, this check should only | |
101 // happen once per prompt (for files found from relative path | |
102 // elements, we also check if the working directory has changed | |
103 // since the last time the function was loaded/parsed). | |
104 // | |
105 // FIXME -- perhaps this should be done for all loaded functions when | |
106 // the prompt is printed or the directory has changed, and then we | |
107 // would not check for it when finding symbol definitions. | |
3355 | 108 |
7336 | 109 static inline bool |
7745
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
110 load_out_of_date_fcn (const std::string& ff, const std::string& dir_name, |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
111 octave_value& function) |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
112 { |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
113 bool retval = false; |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
114 |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
115 octave_function *fcn = load_fcn_from_file (ff, dir_name); |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
116 |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
117 if (fcn) |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
118 { |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
119 retval = true; |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
120 |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
121 function = octave_value (fcn); |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
122 } |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
123 else |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
124 function = octave_value (); |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
125 |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
126 return retval; |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
127 } |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
128 |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
129 static inline bool |
7336 | 130 out_of_date_check_internal (octave_value& function) |
1 | 131 { |
3013 | 132 bool retval = false; |
2949 | 133 |
7336 | 134 octave_function *fcn = function.function_value (true); |
5861 | 135 |
7336 | 136 if (fcn) |
220 | 137 { |
7336 | 138 // FIXME -- we need to handle nested functions properly here. |
4914 | 139 |
7336 | 140 if (! fcn->is_nested_function ()) |
141 { | |
142 std::string ff = fcn->fcn_file_name (); | |
4914 | 143 |
7336 | 144 if (! ff.empty ()) |
145 { | |
146 octave_time tc = fcn->time_checked (); | |
4913 | 147 |
7336 | 148 bool relative = fcn->is_relative (); |
3013 | 149 |
7336 | 150 if (tc < Vlast_prompt_time |
151 || (relative && tc < Vlast_chdir_time)) | |
4913 | 152 { |
7336 | 153 std::string nm = fcn->name (); |
4914 | 154 |
7336 | 155 int nm_len = nm.length (); |
4913 | 156 |
7336 | 157 std::string file; |
158 std::string dir_name; | |
4913 | 159 |
7336 | 160 if (octave_env::absolute_pathname (nm) |
161 && ((nm_len > 4 && (nm.substr (nm_len-4) == ".oct" | |
162 || nm.substr (nm_len-4) == ".mex")) | |
163 || (nm_len > 2 && nm.substr (nm_len-4) == ".m"))) | |
164 file = nm; | |
165 else | |
7745
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
166 { |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
167 // FIXME -- this lookup is not right since it doesn't |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
168 // account for dispatch type. |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
169 |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
170 // We don't want to make this an absolute name, |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
171 // because load_fcn_file looks at the name to |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
172 // decide whether it came from a relative lookup. |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
173 |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
174 file = load_path::find_fcn (nm, dir_name); |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
175 } |
4913 | 176 |
7336 | 177 if (file.empty ()) |
178 { | |
179 // Can't see this function from current | |
180 // directory, so we should clear it. | |
195 | 181 |
7336 | 182 function = octave_value (); |
183 } | |
184 else if (same_file (file, ff)) | |
185 { | |
7745
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
186 // Same file. If it is out of date, then reload it. |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
187 |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
188 octave_time ottp = fcn->time_parsed (); |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
189 time_t tp = ottp.unix_time (); |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
190 |
7336 | 191 fcn->mark_fcn_file_up_to_date (octave_time ()); |
1 | 192 |
7336 | 193 if (! (Vignore_function_time_stamp == 2 |
194 || (Vignore_function_time_stamp | |
195 && fcn->is_system_fcn_file ()))) | |
196 { | |
197 file_stat fs (ff); | |
572 | 198 |
7336 | 199 if (fs) |
200 { | |
201 if (fs.is_newer (tp)) | |
7745
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
202 retval = load_out_of_date_fcn (ff, dir_name, |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
203 function); |
7336 | 204 } |
205 else | |
206 function = octave_value (); | |
6829 | 207 } |
208 } | |
7745
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
209 else |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
210 { |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
211 // Not the same file, so load the new file in |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
212 // place of the old. |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
213 |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
214 retval = load_out_of_date_fcn (file, dir_name, function); |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
215 } |
6829 | 216 } |
217 } | |
4009 | 218 } |
219 } | |
220 | |
221 return retval; | |
222 } | |
223 | |
224 bool | |
7336 | 225 out_of_date_check (octave_value& function) |
4009 | 226 { |
7336 | 227 return out_of_date_check_internal (function); |
228 } | |
4009 | 229 |
7336 | 230 octave_value |
231 symbol_table::fcn_info::fcn_info_rep::load_private_function | |
232 (const std::string& dir_name) | |
233 { | |
234 octave_value retval; | |
235 | |
236 std::string file_name = load_path::find_private_fcn (dir_name, name); | |
237 | |
238 if (! file_name.empty ()) | |
4009 | 239 { |
7336 | 240 octave_function *fcn = load_fcn_from_file (file_name); |
4009 | 241 |
7336 | 242 if (fcn) |
4009 | 243 { |
7336 | 244 retval = octave_value (fcn); |
4009 | 245 |
7336 | 246 private_functions[dir_name] = retval; |
4009 | 247 } |
248 } | |
249 | |
250 return retval; | |
251 } | |
252 | |
7336 | 253 octave_value |
254 symbol_table::fcn_info::fcn_info_rep::load_class_constructor (void) | |
4009 | 255 { |
7336 | 256 octave_value retval; |
257 | |
258 std::string dir_name; | |
4009 | 259 |
7336 | 260 std::string file_name = load_path::find_method (name, name, dir_name); |
261 | |
262 if (! file_name.empty ()) | |
4009 | 263 { |
7336 | 264 octave_function *fcn = load_fcn_from_file (file_name, dir_name, name); |
4009 | 265 |
7336 | 266 if (fcn) |
4009 | 267 { |
7336 | 268 retval = octave_value (fcn); |
269 | |
270 class_constructors[name] = retval; | |
271 } | |
272 } | |
273 | |
274 return retval; | |
275 } | |
276 | |
277 octave_value | |
278 symbol_table::fcn_info::fcn_info_rep::load_class_method | |
279 (const std::string& dispatch_type) | |
280 { | |
281 octave_value retval; | |
4009 | 282 |
7336 | 283 std::string dir_name; |
284 | |
285 std::string file_name = load_path::find_method (dispatch_type, name, dir_name); | |
4009 | 286 |
7336 | 287 if (! file_name.empty ()) |
288 { | |
289 octave_function *fcn = load_fcn_from_file (file_name, dir_name, | |
290 dispatch_type); | |
4009 | 291 |
7336 | 292 if (fcn) |
293 { | |
294 retval = octave_value (fcn); | |
295 | |
296 class_methods[dispatch_type] = retval; | |
4009 | 297 } |
298 } | |
299 | |
300 return retval; | |
301 } | |
302 | |
7336 | 303 void |
304 symbol_table::fcn_info::fcn_info_rep::print_dispatch (std::ostream& os) const | |
1 | 305 { |
7336 | 306 if (dispatch_map.empty ()) |
307 os << "dispatch: " << name << " is not overloaded" << std::endl; | |
308 else | |
309 { | |
310 os << "Overloaded function " << name << ":\n\n"; | |
311 | |
312 for (const_dispatch_map_iterator p = dispatch_map.begin (); | |
313 p != dispatch_map.end (); p++) | |
314 os << " " << name << " (" << p->first << ", ...) -> " | |
315 << p->second << " (" << p->first << ", ...)\n"; | |
3013 | 316 |
7336 | 317 os << std::endl; |
318 } | |
319 } | |
320 | |
321 std::string | |
322 symbol_table::fcn_info::fcn_info_rep::help_for_dispatch (void) const | |
323 { | |
324 std::string retval; | |
325 | |
326 if (! dispatch_map.empty ()) | |
1 | 327 { |
7336 | 328 retval = "Overloaded function:\n\n"; |
329 | |
330 for (const_dispatch_map_iterator p = dispatch_map.begin (); | |
331 p != dispatch_map.end (); p++) | |
332 retval += " " + p->second + " (" + p->first + ", ...)\n\n"; | |
333 } | |
334 | |
335 return retval; | |
336 } | |
337 | |
338 // Find the definition of NAME according to the following precedence | |
339 // list: | |
340 // | |
341 // variable | |
342 // subfunction | |
343 // private function | |
344 // class constructor | |
345 // class method | |
346 // legacy dispatch | |
347 // command-line function | |
348 // autoload function | |
349 // function on the path | |
350 // built-in function | |
3013 | 351 |
7336 | 352 // Notes: |
353 // | |
354 // FIXME -- we need to evaluate the argument list to determine the | |
355 // dispatch type. The method used here works (pass in the args, pass | |
356 // out the evaluated args and a flag saying whether the evaluation was | |
357 // needed), but it seems a bit inelegant. We do need to save the | |
358 // evaluated args in some way to avoid evaluating them multiple times. | |
359 // Maybe evaluated args could be attached to the tree_argument_list | |
360 // object? Then the argument list could be evaluated outside of this | |
361 // function and we could elimnate the arg_names, evaluated_args, and | |
362 // args_evaluated arguments. We would still want to avoid computing | |
363 // the dispatch type unless it is needed, so the args should be passed | |
364 // rather than the dispatch type. But the arguments will need to be | |
365 // evaluated no matter what, so evaluating them beforehand should be | |
366 // OK. If the evaluated arguments are attached to args, then we would | |
367 // need to determine the appropriate place(s) to clear them (for | |
368 // example, before returning from tree_index_expression::rvalue). | |
369 | |
370 octave_value | |
371 symbol_table::fcn_info::fcn_info_rep::find | |
372 (tree_argument_list *args, const string_vector& arg_names, | |
7752
40c428ea3408
initial implementation of dbup and dbdown
John W. Eaton <jwe@octave.org>
parents:
7745
diff
changeset
|
373 octave_value_list& evaluated_args, bool& args_evaluated) |
7336 | 374 { |
375 static bool deja_vu = false; | |
376 | |
377 // Subfunction. I think it only makes sense to check for | |
378 // subfunctions if we are currently executing a function defined | |
379 // from a .m file. | |
380 | |
7752
40c428ea3408
initial implementation of dbup and dbdown
John W. Eaton <jwe@octave.org>
parents:
7745
diff
changeset
|
381 scope_val_iterator r = subfunctions.find (xcurrent_scope); |
7336 | 382 |
383 if (r != subfunctions.end ()) | |
384 { | |
385 // FIXME -- out-of-date check here. | |
386 | |
387 return r->second; | |
388 } | |
389 else if (curr_parent_function) | |
390 { | |
391 scope_id pscope = curr_parent_function->scope (); | |
392 | |
393 r = subfunctions.find (pscope); | |
394 | |
395 if (r != subfunctions.end ()) | |
1 | 396 { |
7336 | 397 // FIXME -- out-of-date check here. |
398 | |
399 return r->second; | |
1 | 400 } |
401 } | |
3013 | 402 |
7336 | 403 // Private function. |
1 | 404 |
7336 | 405 octave_function *curr_fcn = octave_call_stack::current (); |
1 | 406 |
7336 | 407 if (curr_fcn) |
408 { | |
409 std::string dir_name = curr_fcn->dir_name (); | |
1 | 410 |
7336 | 411 if (! dir_name.empty ()) |
412 { | |
413 str_val_iterator q = private_functions.find (dir_name); | |
4913 | 414 |
7336 | 415 if (q == private_functions.end ()) |
416 { | |
417 octave_value val = load_private_function (dir_name); | |
4913 | 418 |
7336 | 419 if (val.is_defined ()) |
420 return val; | |
421 } | |
422 else | |
4913 | 423 { |
7336 | 424 octave_value& fval = q->second; |
4913 | 425 |
7336 | 426 if (fval.is_defined ()) |
427 out_of_date_check_internal (fval); | |
4913 | 428 |
7336 | 429 if (fval.is_defined ()) |
430 return fval; | |
431 else | |
432 { | |
433 octave_value val = load_private_function (dir_name); | |
4913 | 434 |
7336 | 435 if (val.is_defined ()) |
436 return val; | |
4913 | 437 } |
438 } | |
439 } | |
440 } | |
441 | |
7336 | 442 // Class constructors. The class name and function name are the same. |
4913 | 443 |
7336 | 444 str_val_iterator q = class_constructors.find (name); |
4913 | 445 |
7336 | 446 if (q == class_constructors.end ()) |
447 { | |
448 octave_value val = load_class_constructor (); | |
3013 | 449 |
7336 | 450 if (val.is_defined ()) |
451 return val; | |
452 } | |
453 else | |
1 | 454 { |
7336 | 455 octave_value& fval = q->second; |
3013 | 456 |
7336 | 457 if (fval.is_defined ()) |
458 out_of_date_check_internal (fval); | |
867 | 459 |
7336 | 460 if (fval.is_defined ()) |
461 return fval; | |
462 else | |
463 { | |
464 octave_value val = load_class_constructor (); | |
867 | 465 |
7336 | 466 if (val.is_defined ()) |
467 return val; | |
1 | 468 } |
469 } | |
1755 | 470 |
7336 | 471 // Class methods. |
1 | 472 |
7336 | 473 if (args_evaluated || (args && args->length () > 0)) |
474 { | |
475 if (! args_evaluated) | |
476 evaluated_args = args->convert_to_const_vector (); | |
3013 | 477 |
7336 | 478 if (! error_state) |
479 { | |
480 int n = evaluated_args.length (); | |
481 | |
482 if (n > 0 && ! args_evaluated) | |
483 evaluated_args.stash_name_tags (arg_names); | |
484 | |
485 args_evaluated = true; | |
486 | |
487 // FIXME -- need to handle precedence. | |
3013 | 488 |
7336 | 489 std::string dispatch_type = evaluated_args(0).class_name (); |
3013 | 490 |
7336 | 491 for (int i = 1; i < n; i++) |
492 { | |
493 octave_value arg = evaluated_args(i); | |
3013 | 494 |
7336 | 495 if (arg.is_object ()) |
496 { | |
497 dispatch_type = arg.class_name (); | |
498 break; | |
499 } | |
500 } | |
3013 | 501 |
7336 | 502 octave_value fcn = find_method (dispatch_type); |
503 | |
504 if (fcn.is_defined ()) | |
505 return fcn; | |
506 } | |
507 else | |
508 return octave_value (); | |
3013 | 509 } |
510 | |
7336 | 511 // Legacy dispatch. We just check args_evaluated here because the |
512 // actual evaluation will have happened already when searching for | |
513 // class methods. | |
514 | |
515 if (args_evaluated && ! dispatch_map.empty ()) | |
516 { | |
517 std::string dispatch_type = evaluated_args(0).type_name (); | |
518 | |
519 std::string fname; | |
520 | |
521 dispatch_map_iterator p = dispatch_map.find (dispatch_type); | |
522 | |
523 if (p == dispatch_map.end ()) | |
524 p = dispatch_map.find ("any"); | |
3013 | 525 |
7336 | 526 if (p != dispatch_map.end ()) |
527 { | |
528 fname = p->second; | |
529 | |
530 octave_value fcn | |
7752
40c428ea3408
initial implementation of dbup and dbdown
John W. Eaton <jwe@octave.org>
parents:
7745
diff
changeset
|
531 = symbol_table::find_function (fname, evaluated_args); |
7336 | 532 |
533 if (fcn.is_defined ()) | |
534 return fcn; | |
535 } | |
536 } | |
537 | |
538 // Command-line function. | |
539 | |
540 if (cmdline_function.is_defined ()) | |
541 return cmdline_function; | |
542 | |
543 // Autoload? | |
3013 | 544 |
7336 | 545 octave_value fcn = find_autoload (); |
546 | |
547 if (fcn.is_defined ()) | |
548 return fcn; | |
549 | |
550 // Function on the path. | |
551 | |
552 fcn = find_user_function (); | |
553 | |
554 if (fcn.is_defined ()) | |
555 return fcn; | |
556 | |
557 // Built-in function. | |
558 | |
559 if (built_in_function.is_defined ()) | |
560 return built_in_function; | |
3013 | 561 |
7336 | 562 // At this point, we failed to find anything. It is possible that |
563 // the user created a file on the fly since the last prompt or | |
564 // chdir, so try updating the load path and searching again. | |
565 | |
566 octave_value retval; | |
3145 | 567 |
7336 | 568 if (! deja_vu) |
569 { | |
570 load_path::update (); | |
571 | |
572 deja_vu = true; | |
573 | |
7752
40c428ea3408
initial implementation of dbup and dbdown
John W. Eaton <jwe@octave.org>
parents:
7745
diff
changeset
|
574 retval = find (args, arg_names, evaluated_args, args_evaluated); |
7336 | 575 } |
576 | |
577 deja_vu = false; | |
578 | |
579 return retval; | |
3013 | 580 } |
1 | 581 |
7336 | 582 octave_value |
583 symbol_table::fcn_info::fcn_info_rep::find_method (const std::string& dispatch_type) | |
4913 | 584 { |
7336 | 585 octave_value retval; |
4913 | 586 |
7336 | 587 str_val_iterator q = class_methods.find (dispatch_type); |
4913 | 588 |
7336 | 589 if (q == class_methods.end ()) |
590 { | |
591 octave_value val = load_class_method (dispatch_type); | |
4913 | 592 |
7336 | 593 if (val.is_defined ()) |
594 return val; | |
595 } | |
596 else | |
597 { | |
598 octave_value& fval = q->second; | |
4913 | 599 |
7336 | 600 if (fval.is_defined ()) |
601 out_of_date_check_internal (fval); | |
602 | |
603 if (fval.is_defined ()) | |
604 return fval; | |
4913 | 605 else |
606 { | |
7336 | 607 octave_value val = load_class_method (dispatch_type); |
608 | |
609 if (val.is_defined ()) | |
610 return val; | |
4913 | 611 } |
612 } | |
613 | |
7336 | 614 return retval; |
4913 | 615 } |
616 | |
7336 | 617 octave_value |
618 symbol_table::fcn_info::fcn_info_rep::find_autoload (void) | |
4913 | 619 { |
7336 | 620 octave_value retval; |
4913 | 621 |
7336 | 622 // Autoloaded function. |
4913 | 623 |
7336 | 624 if (autoload_function.is_defined ()) |
625 out_of_date_check_internal (autoload_function); | |
4913 | 626 |
7336 | 627 if (! autoload_function.is_defined ()) |
628 { | |
629 std::string file_name = lookup_autoload (name); | |
4913 | 630 |
7336 | 631 if (! file_name.empty ()) |
632 { | |
633 size_t pos = file_name.find_last_of (file_ops::dir_sep_chars); | |
4913 | 634 |
7336 | 635 std::string dir_name = file_name.substr (0, pos); |
4913 | 636 |
7336 | 637 octave_function *fcn = load_fcn_from_file (file_name, dir_name, |
638 "", name, true); | |
4913 | 639 |
7336 | 640 if (fcn) |
641 autoload_function = octave_value (fcn); | |
642 } | |
4913 | 643 } |
644 | |
7336 | 645 return autoload_function; |
646 } | |
4914 | 647 |
7336 | 648 octave_value |
649 symbol_table::fcn_info::fcn_info_rep::find_user_function (void) | |
650 { | |
651 // Function on the path. | |
4913 | 652 |
7336 | 653 if (function_on_path.is_defined ()) |
654 out_of_date_check_internal (function_on_path); | |
4913 | 655 |
7336 | 656 if (! function_on_path.is_defined ()) |
657 { | |
658 std::string dir_name; | |
4913 | 659 |
7336 | 660 std::string file_name = load_path::find_fcn (name, dir_name); |
4913 | 661 |
7336 | 662 if (! file_name.empty ()) |
663 { | |
664 octave_function *fcn = load_fcn_from_file (file_name, dir_name); | |
4913 | 665 |
7336 | 666 if (fcn) |
667 function_on_path = octave_value (fcn); | |
4913 | 668 } |
669 } | |
670 | |
7336 | 671 return function_on_path; |
672 } | |
673 | |
674 octave_value | |
675 symbol_table::fcn_info::find (tree_argument_list *args, | |
676 const string_vector& arg_names, | |
677 octave_value_list& evaluated_args, | |
7752
40c428ea3408
initial implementation of dbup and dbdown
John W. Eaton <jwe@octave.org>
parents:
7745
diff
changeset
|
678 bool& args_evaluated) |
7336 | 679 { |
7752
40c428ea3408
initial implementation of dbup and dbdown
John W. Eaton <jwe@octave.org>
parents:
7745
diff
changeset
|
680 return rep->find (args, arg_names, evaluated_args, args_evaluated); |
7336 | 681 } |
682 | |
683 octave_value | |
684 symbol_table::find (const std::string& name, tree_argument_list *args, | |
685 const string_vector& arg_names, | |
686 octave_value_list& evaluated_args, bool& args_evaluated, | |
7752
40c428ea3408
initial implementation of dbup and dbdown
John W. Eaton <jwe@octave.org>
parents:
7745
diff
changeset
|
687 bool skip_variables) |
7336 | 688 { |
7752
40c428ea3408
initial implementation of dbup and dbdown
John W. Eaton <jwe@octave.org>
parents:
7745
diff
changeset
|
689 symbol_table *inst = get_instance (xcurrent_scope); |
7336 | 690 |
691 return inst | |
692 ? inst->do_find (name, args, arg_names, evaluated_args, | |
7752
40c428ea3408
initial implementation of dbup and dbdown
John W. Eaton <jwe@octave.org>
parents:
7745
diff
changeset
|
693 args_evaluated, skip_variables) |
7336 | 694 : octave_value (); |
695 } | |
696 | |
697 octave_value | |
698 symbol_table::find_function (const std::string& name, tree_argument_list *args, | |
699 const string_vector& arg_names, | |
700 octave_value_list& evaluated_args, | |
7752
40c428ea3408
initial implementation of dbup and dbdown
John W. Eaton <jwe@octave.org>
parents:
7745
diff
changeset
|
701 bool& args_evaluated) |
7336 | 702 { |
7752
40c428ea3408
initial implementation of dbup and dbdown
John W. Eaton <jwe@octave.org>
parents:
7745
diff
changeset
|
703 return find (name, args, arg_names, evaluated_args, args_evaluated, true); |
4913 | 704 } |
705 | |
7336 | 706 octave_value |
707 symbol_table::do_find (const std::string& name, tree_argument_list *args, | |
708 const string_vector& arg_names, | |
709 octave_value_list& evaluated_args, | |
7752
40c428ea3408
initial implementation of dbup and dbdown
John W. Eaton <jwe@octave.org>
parents:
7745
diff
changeset
|
710 bool& args_evaluated, bool skip_variables) |
3013 | 711 { |
7336 | 712 octave_value retval; |
4913 | 713 |
7336 | 714 // Variable. |
4913 | 715 |
7336 | 716 if (! skip_variables) |
3013 | 717 { |
7336 | 718 table_iterator p = table.find (name); |
3013 | 719 |
7336 | 720 if (p != table.end ()) |
721 { | |
722 symbol_record& sr = p->second; | |
3013 | 723 |
7336 | 724 // FIXME -- should we be using something other than varref here? |
5005 | 725 |
7336 | 726 if (sr.is_global ()) |
7752
40c428ea3408
initial implementation of dbup and dbdown
John W. Eaton <jwe@octave.org>
parents:
7745
diff
changeset
|
727 return symbol_table::global_varref (name); |
7336 | 728 else |
729 { | |
730 octave_value& val = sr.varref (); | |
4913 | 731 |
7336 | 732 if (val.is_defined ()) |
733 return val; | |
734 } | |
735 } | |
736 } | |
4913 | 737 |
7336 | 738 fcn_table_iterator p = fcn_table.find (name); |
4913 | 739 |
7336 | 740 if (p != fcn_table.end ()) |
741 { | |
742 evaluated_args = octave_value_list (); | |
743 args_evaluated = false; | |
3013 | 744 |
7752
40c428ea3408
initial implementation of dbup and dbdown
John W. Eaton <jwe@octave.org>
parents:
7745
diff
changeset
|
745 return p->second.find (args, arg_names, evaluated_args, args_evaluated); |
3013 | 746 } |
747 else | |
748 { | |
7336 | 749 fcn_info finfo (name); |
750 | |
751 octave_value fcn = finfo.find (args, arg_names, evaluated_args, | |
7752
40c428ea3408
initial implementation of dbup and dbdown
John W. Eaton <jwe@octave.org>
parents:
7745
diff
changeset
|
752 args_evaluated); |
3013 | 753 |
7336 | 754 if (fcn.is_defined ()) |
755 fcn_table[name] = finfo; | |
3013 | 756 |
7336 | 757 return fcn; |
3013 | 758 } |
759 | |
7336 | 760 return retval; |
605 | 761 } |
762 | |
7336 | 763 DEFUN (ignore_function_time_stamp, args, nargout, |
764 "-*- texinfo -*-\n\ | |
765 @deftypefn {Built-in Function} {@var{val} =} ignore_function_time_stamp ()\n\ | |
766 @deftypefnx {Built-in Function} {@var{old_val} =} ignore_function_time_stamp (@var{new_val})\n\ | |
767 Query or set the internal variable that controls whether Octave checks\n\ | |
768 the time stamp on files each time it looks up functions defined in\n\ | |
769 function files. If the internal variable is set to @code{\"system\"},\n\ | |
770 Octave will not automatically recompile function files in subdirectories of\n\ | |
771 @file{@var{octave-home}/lib/@var{version}} if they have changed since\n\ | |
772 they were last compiled, but will recompile other function files in the\n\ | |
773 search path if they change. If set to @code{\"all\"}, Octave will not\n\ | |
774 recompile any function files unless their definitions are removed with\n\ | |
775 @code{clear}. If set to \"none\", Octave will always check time stamps\n\ | |
776 on files to determine whether functions defined in function files\n\ | |
777 need to recompiled.\n\ | |
778 @end deftypefn") | |
220 | 779 { |
7336 | 780 octave_value retval; |
220 | 781 |
7336 | 782 if (nargout > 0) |
5861 | 783 { |
7336 | 784 switch (Vignore_function_time_stamp) |
5861 | 785 { |
7336 | 786 case 1: |
787 retval = "system"; | |
788 break; | |
5861 | 789 |
7336 | 790 case 2: |
791 retval = "all"; | |
792 break; | |
5861 | 793 |
7336 | 794 default: |
795 retval = "none"; | |
796 break; | |
5861 | 797 } |
798 } | |
799 | |
7336 | 800 int nargin = args.length (); |
5861 | 801 |
7336 | 802 if (nargin == 1) |
3013 | 803 { |
7336 | 804 std::string sval = args(0).string_value (); |
1 | 805 |
7336 | 806 if (! error_state) |
807 { | |
808 if (sval == "all") | |
809 Vignore_function_time_stamp = 2; | |
810 else if (sval == "system") | |
811 Vignore_function_time_stamp = 1; | |
812 else if (sval == "none") | |
813 Vignore_function_time_stamp = 0; | |
814 else | |
815 error ("ignore_function_time_stamp: expecting argument to be \"all\", \"system\", or \"none\""); | |
816 } | |
817 else | |
818 error ("ignore_function_time_stamp: expecting argument to be character string"); | |
819 } | |
820 else if (nargin > 1) | |
821 print_usage (); | |
4238 | 822 |
7336 | 823 return retval; |
3308 | 824 } |
825 | |
7437 | 826 #if 0 |
827 | |
828 // FIXME -- should we have functions like this in Octave? | |
829 | |
830 DEFUN (set_variable, args, , "set_variable (NAME, VALUE)") | |
831 { | |
832 octave_value retval; | |
833 | |
834 if (args.length () == 2) | |
835 { | |
836 std::string name = args(0).string_value (); | |
837 | |
838 if (! error_state) | |
839 symbol_table::varref (name) = args(1); | |
840 else | |
841 error ("set_variable: expecting variable name as first argument"); | |
842 } | |
843 else | |
844 print_usage (); | |
845 | |
846 return retval; | |
847 } | |
848 | |
849 DEFUN (variable_value, args, , "VALUE = variable_value (NAME)") | |
850 { | |
851 octave_value retval; | |
852 | |
853 if (args.length () == 1) | |
854 { | |
855 std::string name = args(0).string_value (); | |
856 | |
857 if (! error_state) | |
858 { | |
859 retval = symbol_table::varval (name); | |
860 | |
861 if (retval.is_undefined ()) | |
862 error ("variable_value: `%s' is not a variable in the current scope", | |
863 name.c_str ()); | |
864 } | |
865 else | |
866 error ("variable_value: expecting variable name as first argument"); | |
867 } | |
868 else | |
869 print_usage (); | |
870 | |
871 return retval; | |
872 } | |
873 #endif | |
874 | |
1 | 875 /* |
876 ;;; Local Variables: *** | |
877 ;;; mode: C++ *** | |
878 ;;; End: *** | |
879 */ |