Mercurial > octave
annotate src/symtab.cc @ 7745:0ff0fc033f28
better handling of functions found by relative lookup
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Wed, 30 Apr 2008 17:51:02 -0400 |
parents | 3e450caf93f2 |
children | 40c428ea3408 |
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 |
7336 | 50 std::map<std::string, symbol_table::fcn_info> symbol_table::fcn_table; |
4913 | 51 |
7336 | 52 const symbol_table::scope_id symbol_table::xglobal_scope = 0; |
53 const symbol_table::scope_id symbol_table::xtop_scope = 1; | |
4238 | 54 |
7336 | 55 symbol_table::scope_id symbol_table::xcurrent_scope = 1; |
56 symbol_table::scope_id symbol_table::xcurrent_caller_scope = -1; | |
3308 | 57 |
7336 | 58 symbol_table::scope_id symbol_table::xparent_scope = -1; |
59 | |
60 std::deque<symbol_table::scope_id> symbol_table::scope_stack; | |
4238 | 61 |
7336 | 62 symbol_table::scope_id symbol_table::next_available_scope = 2; |
63 std::set<symbol_table::scope_id> symbol_table::scope_ids_in_use; | |
64 std::set<symbol_table::scope_id> symbol_table::scope_ids_free_list; | |
195 | 65 |
7336 | 66 // Should Octave always check to see if function files have changed |
67 // since they were last compiled? | |
68 static int Vignore_function_time_stamp = 1; | |
3355 | 69 |
7336 | 70 octave_value |
71 symbol_table::symbol_record::find (tree_argument_list *args, | |
72 const string_vector& arg_names, | |
73 octave_value_list& evaluated_args, | |
74 bool& args_evaluated) const | |
75 { | |
76 octave_value retval; | |
3355 | 77 |
7336 | 78 if (is_global ()) |
79 return symbol_table::varref (name (), symbol_table::xglobal_scope); | |
80 else | |
81 { | |
82 octave_value val = varval (); | |
83 | |
84 if (val.is_defined ()) | |
85 return val; | |
86 } | |
87 | |
88 return symbol_table::find_function (name (), args, arg_names, | |
89 evaluated_args, args_evaluated); | |
3355 | 90 } |
91 | |
7336 | 92 // Check the load path to see if file that defined this is still |
93 // visible. If the file is no longer visible, then erase the | |
94 // definition and move on. If the file is visible, then we also | |
95 // need to check to see whether the file has changed since the the | |
96 // function was loaded/parsed. However, this check should only | |
97 // happen once per prompt (for files found from relative path | |
98 // elements, we also check if the working directory has changed | |
99 // since the last time the function was loaded/parsed). | |
100 // | |
101 // FIXME -- perhaps this should be done for all loaded functions when | |
102 // the prompt is printed or the directory has changed, and then we | |
103 // would not check for it when finding symbol definitions. | |
3355 | 104 |
7336 | 105 static inline bool |
7745
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
106 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
|
107 octave_value& function) |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
108 { |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
109 bool retval = false; |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
110 |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
111 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
|
112 |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
113 if (fcn) |
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 retval = true; |
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 function = octave_value (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 else |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
120 function = octave_value (); |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
121 |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
122 return retval; |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
123 } |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
124 |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
125 static inline bool |
7336 | 126 out_of_date_check_internal (octave_value& function) |
1 | 127 { |
3013 | 128 bool retval = false; |
2949 | 129 |
7336 | 130 octave_function *fcn = function.function_value (true); |
5861 | 131 |
7336 | 132 if (fcn) |
220 | 133 { |
7336 | 134 // FIXME -- we need to handle nested functions properly here. |
4914 | 135 |
7336 | 136 if (! fcn->is_nested_function ()) |
137 { | |
138 std::string ff = fcn->fcn_file_name (); | |
4914 | 139 |
7336 | 140 if (! ff.empty ()) |
141 { | |
142 octave_time tc = fcn->time_checked (); | |
4913 | 143 |
7336 | 144 bool relative = fcn->is_relative (); |
3013 | 145 |
7336 | 146 if (tc < Vlast_prompt_time |
147 || (relative && tc < Vlast_chdir_time)) | |
4913 | 148 { |
7336 | 149 std::string nm = fcn->name (); |
4914 | 150 |
7336 | 151 int nm_len = nm.length (); |
4913 | 152 |
7336 | 153 std::string file; |
154 std::string dir_name; | |
4913 | 155 |
7336 | 156 if (octave_env::absolute_pathname (nm) |
157 && ((nm_len > 4 && (nm.substr (nm_len-4) == ".oct" | |
158 || nm.substr (nm_len-4) == ".mex")) | |
159 || (nm_len > 2 && nm.substr (nm_len-4) == ".m"))) | |
160 file = nm; | |
161 else | |
7745
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
162 { |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
163 // 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
|
164 // account for dispatch type. |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
165 |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
166 // 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
|
167 // 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
|
168 // 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
|
169 |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
170 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
|
171 } |
4913 | 172 |
7336 | 173 if (file.empty ()) |
174 { | |
175 // Can't see this function from current | |
176 // directory, so we should clear it. | |
195 | 177 |
7336 | 178 function = octave_value (); |
179 } | |
180 else if (same_file (file, ff)) | |
181 { | |
7745
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
182 // 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
|
183 |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
184 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
|
185 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
|
186 |
7336 | 187 fcn->mark_fcn_file_up_to_date (octave_time ()); |
1 | 188 |
7336 | 189 if (! (Vignore_function_time_stamp == 2 |
190 || (Vignore_function_time_stamp | |
191 && fcn->is_system_fcn_file ()))) | |
192 { | |
193 file_stat fs (ff); | |
572 | 194 |
7336 | 195 if (fs) |
196 { | |
197 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
|
198 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
|
199 function); |
7336 | 200 } |
201 else | |
202 function = octave_value (); | |
6829 | 203 } |
204 } | |
7745
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
205 else |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
206 { |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
207 // 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
|
208 // place of the old. |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
209 |
0ff0fc033f28
better handling of functions found by relative lookup
John W. Eaton <jwe@octave.org>
parents:
7437
diff
changeset
|
210 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
|
211 } |
6829 | 212 } |
213 } | |
4009 | 214 } |
215 } | |
216 | |
217 return retval; | |
218 } | |
219 | |
220 bool | |
7336 | 221 out_of_date_check (octave_value& function) |
4009 | 222 { |
7336 | 223 return out_of_date_check_internal (function); |
224 } | |
4009 | 225 |
7336 | 226 octave_value |
227 symbol_table::fcn_info::fcn_info_rep::load_private_function | |
228 (const std::string& dir_name) | |
229 { | |
230 octave_value retval; | |
231 | |
232 std::string file_name = load_path::find_private_fcn (dir_name, name); | |
233 | |
234 if (! file_name.empty ()) | |
4009 | 235 { |
7336 | 236 octave_function *fcn = load_fcn_from_file (file_name); |
4009 | 237 |
7336 | 238 if (fcn) |
4009 | 239 { |
7336 | 240 retval = octave_value (fcn); |
4009 | 241 |
7336 | 242 private_functions[dir_name] = retval; |
4009 | 243 } |
244 } | |
245 | |
246 return retval; | |
247 } | |
248 | |
7336 | 249 octave_value |
250 symbol_table::fcn_info::fcn_info_rep::load_class_constructor (void) | |
4009 | 251 { |
7336 | 252 octave_value retval; |
253 | |
254 std::string dir_name; | |
4009 | 255 |
7336 | 256 std::string file_name = load_path::find_method (name, name, dir_name); |
257 | |
258 if (! file_name.empty ()) | |
4009 | 259 { |
7336 | 260 octave_function *fcn = load_fcn_from_file (file_name, dir_name, name); |
4009 | 261 |
7336 | 262 if (fcn) |
4009 | 263 { |
7336 | 264 retval = octave_value (fcn); |
265 | |
266 class_constructors[name] = retval; | |
267 } | |
268 } | |
269 | |
270 return retval; | |
271 } | |
272 | |
273 octave_value | |
274 symbol_table::fcn_info::fcn_info_rep::load_class_method | |
275 (const std::string& dispatch_type) | |
276 { | |
277 octave_value retval; | |
4009 | 278 |
7336 | 279 std::string dir_name; |
280 | |
281 std::string file_name = load_path::find_method (dispatch_type, name, dir_name); | |
4009 | 282 |
7336 | 283 if (! file_name.empty ()) |
284 { | |
285 octave_function *fcn = load_fcn_from_file (file_name, dir_name, | |
286 dispatch_type); | |
4009 | 287 |
7336 | 288 if (fcn) |
289 { | |
290 retval = octave_value (fcn); | |
291 | |
292 class_methods[dispatch_type] = retval; | |
4009 | 293 } |
294 } | |
295 | |
296 return retval; | |
297 } | |
298 | |
7336 | 299 void |
300 symbol_table::fcn_info::fcn_info_rep::print_dispatch (std::ostream& os) const | |
1 | 301 { |
7336 | 302 if (dispatch_map.empty ()) |
303 os << "dispatch: " << name << " is not overloaded" << std::endl; | |
304 else | |
305 { | |
306 os << "Overloaded function " << name << ":\n\n"; | |
307 | |
308 for (const_dispatch_map_iterator p = dispatch_map.begin (); | |
309 p != dispatch_map.end (); p++) | |
310 os << " " << name << " (" << p->first << ", ...) -> " | |
311 << p->second << " (" << p->first << ", ...)\n"; | |
3013 | 312 |
7336 | 313 os << std::endl; |
314 } | |
315 } | |
316 | |
317 std::string | |
318 symbol_table::fcn_info::fcn_info_rep::help_for_dispatch (void) const | |
319 { | |
320 std::string retval; | |
321 | |
322 if (! dispatch_map.empty ()) | |
1 | 323 { |
7336 | 324 retval = "Overloaded function:\n\n"; |
325 | |
326 for (const_dispatch_map_iterator p = dispatch_map.begin (); | |
327 p != dispatch_map.end (); p++) | |
328 retval += " " + p->second + " (" + p->first + ", ...)\n\n"; | |
329 } | |
330 | |
331 return retval; | |
332 } | |
333 | |
334 // Find the definition of NAME according to the following precedence | |
335 // list: | |
336 // | |
337 // variable | |
338 // subfunction | |
339 // private function | |
340 // class constructor | |
341 // class method | |
342 // legacy dispatch | |
343 // command-line function | |
344 // autoload function | |
345 // function on the path | |
346 // built-in function | |
3013 | 347 |
7336 | 348 // Notes: |
349 // | |
350 // FIXME -- we need to evaluate the argument list to determine the | |
351 // dispatch type. The method used here works (pass in the args, pass | |
352 // out the evaluated args and a flag saying whether the evaluation was | |
353 // needed), but it seems a bit inelegant. We do need to save the | |
354 // evaluated args in some way to avoid evaluating them multiple times. | |
355 // Maybe evaluated args could be attached to the tree_argument_list | |
356 // object? Then the argument list could be evaluated outside of this | |
357 // function and we could elimnate the arg_names, evaluated_args, and | |
358 // args_evaluated arguments. We would still want to avoid computing | |
359 // the dispatch type unless it is needed, so the args should be passed | |
360 // rather than the dispatch type. But the arguments will need to be | |
361 // evaluated no matter what, so evaluating them beforehand should be | |
362 // OK. If the evaluated arguments are attached to args, then we would | |
363 // need to determine the appropriate place(s) to clear them (for | |
364 // example, before returning from tree_index_expression::rvalue). | |
365 | |
366 octave_value | |
367 symbol_table::fcn_info::fcn_info_rep::find | |
368 (tree_argument_list *args, const string_vector& arg_names, | |
369 octave_value_list& evaluated_args, bool& args_evaluated, | |
370 scope_id scope) | |
371 { | |
372 static bool deja_vu = false; | |
373 | |
374 // Subfunction. I think it only makes sense to check for | |
375 // subfunctions if we are currently executing a function defined | |
376 // from a .m file. | |
377 | |
378 scope_val_iterator r = subfunctions.find (scope); | |
379 | |
380 if (r != subfunctions.end ()) | |
381 { | |
382 // FIXME -- out-of-date check here. | |
383 | |
384 return r->second; | |
385 } | |
386 else if (curr_parent_function) | |
387 { | |
388 scope_id pscope = curr_parent_function->scope (); | |
389 | |
390 r = subfunctions.find (pscope); | |
391 | |
392 if (r != subfunctions.end ()) | |
1 | 393 { |
7336 | 394 // FIXME -- out-of-date check here. |
395 | |
396 return r->second; | |
1 | 397 } |
398 } | |
3013 | 399 |
7336 | 400 // Private function. |
1 | 401 |
7336 | 402 octave_function *curr_fcn = octave_call_stack::current (); |
1 | 403 |
7336 | 404 if (curr_fcn) |
405 { | |
406 std::string dir_name = curr_fcn->dir_name (); | |
1 | 407 |
7336 | 408 if (! dir_name.empty ()) |
409 { | |
410 str_val_iterator q = private_functions.find (dir_name); | |
4913 | 411 |
7336 | 412 if (q == private_functions.end ()) |
413 { | |
414 octave_value val = load_private_function (dir_name); | |
4913 | 415 |
7336 | 416 if (val.is_defined ()) |
417 return val; | |
418 } | |
419 else | |
4913 | 420 { |
7336 | 421 octave_value& fval = q->second; |
4913 | 422 |
7336 | 423 if (fval.is_defined ()) |
424 out_of_date_check_internal (fval); | |
4913 | 425 |
7336 | 426 if (fval.is_defined ()) |
427 return fval; | |
428 else | |
429 { | |
430 octave_value val = load_private_function (dir_name); | |
4913 | 431 |
7336 | 432 if (val.is_defined ()) |
433 return val; | |
4913 | 434 } |
435 } | |
436 } | |
437 } | |
438 | |
7336 | 439 // Class constructors. The class name and function name are the same. |
4913 | 440 |
7336 | 441 str_val_iterator q = class_constructors.find (name); |
4913 | 442 |
7336 | 443 if (q == class_constructors.end ()) |
444 { | |
445 octave_value val = load_class_constructor (); | |
3013 | 446 |
7336 | 447 if (val.is_defined ()) |
448 return val; | |
449 } | |
450 else | |
1 | 451 { |
7336 | 452 octave_value& fval = q->second; |
3013 | 453 |
7336 | 454 if (fval.is_defined ()) |
455 out_of_date_check_internal (fval); | |
867 | 456 |
7336 | 457 if (fval.is_defined ()) |
458 return fval; | |
459 else | |
460 { | |
461 octave_value val = load_class_constructor (); | |
867 | 462 |
7336 | 463 if (val.is_defined ()) |
464 return val; | |
1 | 465 } |
466 } | |
1755 | 467 |
7336 | 468 // Class methods. |
1 | 469 |
7336 | 470 if (args_evaluated || (args && args->length () > 0)) |
471 { | |
472 if (! args_evaluated) | |
473 evaluated_args = args->convert_to_const_vector (); | |
3013 | 474 |
7336 | 475 if (! error_state) |
476 { | |
477 int n = evaluated_args.length (); | |
478 | |
479 if (n > 0 && ! args_evaluated) | |
480 evaluated_args.stash_name_tags (arg_names); | |
481 | |
482 args_evaluated = true; | |
483 | |
484 // FIXME -- need to handle precedence. | |
3013 | 485 |
7336 | 486 std::string dispatch_type = evaluated_args(0).class_name (); |
3013 | 487 |
7336 | 488 for (int i = 1; i < n; i++) |
489 { | |
490 octave_value arg = evaluated_args(i); | |
3013 | 491 |
7336 | 492 if (arg.is_object ()) |
493 { | |
494 dispatch_type = arg.class_name (); | |
495 break; | |
496 } | |
497 } | |
3013 | 498 |
7336 | 499 octave_value fcn = find_method (dispatch_type); |
500 | |
501 if (fcn.is_defined ()) | |
502 return fcn; | |
503 } | |
504 else | |
505 return octave_value (); | |
3013 | 506 } |
507 | |
7336 | 508 // Legacy dispatch. We just check args_evaluated here because the |
509 // actual evaluation will have happened already when searching for | |
510 // class methods. | |
511 | |
512 if (args_evaluated && ! dispatch_map.empty ()) | |
513 { | |
514 std::string dispatch_type = evaluated_args(0).type_name (); | |
515 | |
516 std::string fname; | |
517 | |
518 dispatch_map_iterator p = dispatch_map.find (dispatch_type); | |
519 | |
520 if (p == dispatch_map.end ()) | |
521 p = dispatch_map.find ("any"); | |
3013 | 522 |
7336 | 523 if (p != dispatch_map.end ()) |
524 { | |
525 fname = p->second; | |
526 | |
527 octave_value fcn | |
528 = symbol_table::find_function (fname, evaluated_args, scope); | |
529 | |
530 if (fcn.is_defined ()) | |
531 return fcn; | |
532 } | |
533 } | |
534 | |
535 // Command-line function. | |
536 | |
537 if (cmdline_function.is_defined ()) | |
538 return cmdline_function; | |
539 | |
540 // Autoload? | |
3013 | 541 |
7336 | 542 octave_value fcn = find_autoload (); |
543 | |
544 if (fcn.is_defined ()) | |
545 return fcn; | |
546 | |
547 // Function on the path. | |
548 | |
549 fcn = find_user_function (); | |
550 | |
551 if (fcn.is_defined ()) | |
552 return fcn; | |
553 | |
554 // Built-in function. | |
555 | |
556 if (built_in_function.is_defined ()) | |
557 return built_in_function; | |
3013 | 558 |
7336 | 559 // At this point, we failed to find anything. It is possible that |
560 // the user created a file on the fly since the last prompt or | |
561 // chdir, so try updating the load path and searching again. | |
562 | |
563 octave_value retval; | |
3145 | 564 |
7336 | 565 if (! deja_vu) |
566 { | |
567 load_path::update (); | |
568 | |
569 deja_vu = true; | |
570 | |
571 retval = find (args, arg_names, evaluated_args, args_evaluated, scope); | |
572 } | |
573 | |
574 deja_vu = false; | |
575 | |
576 return retval; | |
3013 | 577 } |
1 | 578 |
7336 | 579 octave_value |
580 symbol_table::fcn_info::fcn_info_rep::find_method (const std::string& dispatch_type) | |
4913 | 581 { |
7336 | 582 octave_value retval; |
4913 | 583 |
7336 | 584 str_val_iterator q = class_methods.find (dispatch_type); |
4913 | 585 |
7336 | 586 if (q == class_methods.end ()) |
587 { | |
588 octave_value val = load_class_method (dispatch_type); | |
4913 | 589 |
7336 | 590 if (val.is_defined ()) |
591 return val; | |
592 } | |
593 else | |
594 { | |
595 octave_value& fval = q->second; | |
4913 | 596 |
7336 | 597 if (fval.is_defined ()) |
598 out_of_date_check_internal (fval); | |
599 | |
600 if (fval.is_defined ()) | |
601 return fval; | |
4913 | 602 else |
603 { | |
7336 | 604 octave_value val = load_class_method (dispatch_type); |
605 | |
606 if (val.is_defined ()) | |
607 return val; | |
4913 | 608 } |
609 } | |
610 | |
7336 | 611 return retval; |
4913 | 612 } |
613 | |
7336 | 614 octave_value |
615 symbol_table::fcn_info::fcn_info_rep::find_autoload (void) | |
4913 | 616 { |
7336 | 617 octave_value retval; |
4913 | 618 |
7336 | 619 // Autoloaded function. |
4913 | 620 |
7336 | 621 if (autoload_function.is_defined ()) |
622 out_of_date_check_internal (autoload_function); | |
4913 | 623 |
7336 | 624 if (! autoload_function.is_defined ()) |
625 { | |
626 std::string file_name = lookup_autoload (name); | |
4913 | 627 |
7336 | 628 if (! file_name.empty ()) |
629 { | |
630 size_t pos = file_name.find_last_of (file_ops::dir_sep_chars); | |
4913 | 631 |
7336 | 632 std::string dir_name = file_name.substr (0, pos); |
4913 | 633 |
7336 | 634 octave_function *fcn = load_fcn_from_file (file_name, dir_name, |
635 "", name, true); | |
4913 | 636 |
7336 | 637 if (fcn) |
638 autoload_function = octave_value (fcn); | |
639 } | |
4913 | 640 } |
641 | |
7336 | 642 return autoload_function; |
643 } | |
4914 | 644 |
7336 | 645 octave_value |
646 symbol_table::fcn_info::fcn_info_rep::find_user_function (void) | |
647 { | |
648 // Function on the path. | |
4913 | 649 |
7336 | 650 if (function_on_path.is_defined ()) |
651 out_of_date_check_internal (function_on_path); | |
4913 | 652 |
7336 | 653 if (! function_on_path.is_defined ()) |
654 { | |
655 std::string dir_name; | |
4913 | 656 |
7336 | 657 std::string file_name = load_path::find_fcn (name, dir_name); |
4913 | 658 |
7336 | 659 if (! file_name.empty ()) |
660 { | |
661 octave_function *fcn = load_fcn_from_file (file_name, dir_name); | |
4913 | 662 |
7336 | 663 if (fcn) |
664 function_on_path = octave_value (fcn); | |
4913 | 665 } |
666 } | |
667 | |
7336 | 668 return function_on_path; |
669 } | |
670 | |
671 octave_value | |
672 symbol_table::fcn_info::find (tree_argument_list *args, | |
673 const string_vector& arg_names, | |
674 octave_value_list& evaluated_args, | |
675 bool& args_evaluated, scope_id scope) | |
676 { | |
677 return rep->find (args, arg_names, evaluated_args, args_evaluated, scope); | |
678 } | |
679 | |
680 octave_value | |
681 symbol_table::find (const std::string& name, tree_argument_list *args, | |
682 const string_vector& arg_names, | |
683 octave_value_list& evaluated_args, bool& args_evaluated, | |
684 symbol_table::scope_id scope, bool skip_variables) | |
685 { | |
686 symbol_table *inst = get_instance (scope); | |
687 | |
688 return inst | |
689 ? inst->do_find (name, args, arg_names, evaluated_args, | |
690 args_evaluated, scope, skip_variables) | |
691 : octave_value (); | |
692 } | |
693 | |
694 octave_value | |
695 symbol_table::find_function (const std::string& name, tree_argument_list *args, | |
696 const string_vector& arg_names, | |
697 octave_value_list& evaluated_args, | |
698 bool& args_evaluated, scope_id scope) | |
699 { | |
700 return find (name, args, arg_names, evaluated_args, args_evaluated, | |
701 scope, true); | |
4913 | 702 } |
703 | |
7336 | 704 octave_value |
705 symbol_table::do_find (const std::string& name, tree_argument_list *args, | |
706 const string_vector& arg_names, | |
707 octave_value_list& evaluated_args, | |
708 bool& args_evaluated, scope_id scope, | |
709 bool skip_variables) | |
3013 | 710 { |
7336 | 711 octave_value retval; |
4913 | 712 |
7336 | 713 // Variable. |
4913 | 714 |
7336 | 715 if (! skip_variables) |
3013 | 716 { |
7336 | 717 table_iterator p = table.find (name); |
3013 | 718 |
7336 | 719 if (p != table.end ()) |
720 { | |
721 symbol_record& sr = p->second; | |
3013 | 722 |
7336 | 723 // FIXME -- should we be using something other than varref here? |
5005 | 724 |
7336 | 725 if (sr.is_global ()) |
726 return symbol_table::varref (name, xglobal_scope); | |
727 else | |
728 { | |
729 octave_value& val = sr.varref (); | |
4913 | 730 |
7336 | 731 if (val.is_defined ()) |
732 return val; | |
733 } | |
734 } | |
735 } | |
4913 | 736 |
7336 | 737 fcn_table_iterator p = fcn_table.find (name); |
4913 | 738 |
7336 | 739 if (p != fcn_table.end ()) |
740 { | |
741 evaluated_args = octave_value_list (); | |
742 args_evaluated = false; | |
3013 | 743 |
7336 | 744 return p->second.find (args, arg_names, evaluated_args, args_evaluated, |
745 scope); | |
3013 | 746 } |
747 else | |
748 { | |
7336 | 749 fcn_info finfo (name); |
750 | |
751 octave_value fcn = finfo.find (args, arg_names, evaluated_args, | |
752 args_evaluated, scope); | |
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 */ |