Mercurial > hg > octave-nkf
comparison src/ov-fcn-handle.cc @ 4930:bdb307dc8613
[project @ 2004-08-05 04:55:26 by jwe]
author | jwe |
---|---|
date | Thu, 05 Aug 2004 04:55:26 +0000 |
parents | 90f51232d751 |
children | cd58733c326b |
comparison
equal
deleted
inserted
replaced
4929:585e9a8c2ef8 | 4930:bdb307dc8613 |
---|---|
36 #include "oct-map.h" | 36 #include "oct-map.h" |
37 #include "ov-base.h" | 37 #include "ov-base.h" |
38 #include "ov-fcn-handle.h" | 38 #include "ov-fcn-handle.h" |
39 #include "pr-output.h" | 39 #include "pr-output.h" |
40 #include "variables.h" | 40 #include "variables.h" |
41 #include "parse.h" | |
41 | 42 |
42 DEFINE_OCTAVE_ALLOCATOR (octave_fcn_handle); | 43 DEFINE_OCTAVE_ALLOCATOR (octave_fcn_handle); |
43 | 44 |
44 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_fcn_handle, | 45 DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_fcn_handle, |
45 "function handle", | 46 "function handle", |
46 "function handle"); | 47 "function handle"); |
48 | |
49 octave_fcn_handle::octave_fcn_handle (const std::string& f, | |
50 const string_vector& a, | |
51 const std::string& n) | |
52 : typ (fcn_inline), nm (n), iftext (f), ifargs (a) | |
53 { | |
54 // Find a function name that isn't already in the symbol table. | |
55 | |
56 std::string fname = "__inline__"; | |
57 | |
58 while (symbol_exist (fname)) | |
59 fname.append ("X"); | |
60 | |
61 // Form a string representing the function. | |
62 | |
63 OSSTREAM buf; | |
64 | |
65 buf << "function __retval__ = " << fname << "("; | |
66 | |
67 for (int i = 0; i < ifargs.length (); i++) | |
68 { | |
69 if (i > 0) | |
70 buf << ", "; | |
71 | |
72 buf << ifargs(i); | |
73 } | |
74 | |
75 buf << ")\n __retval__ = " << iftext << ";\nendfunction" << OSSTREAM_ENDS; | |
76 | |
77 // Parse this function and create a user function. | |
78 | |
79 octave_value eval_args (OSSTREAM_STR (buf)); | |
80 | |
81 feval ("eval", eval_args, 0); | |
82 | |
83 OSSTREAM_FREEZE (buf); | |
84 | |
85 octave_value tmp = lookup_function (fname); | |
86 | |
87 if (tmp.is_function ()) | |
88 { | |
89 fcn = tmp; | |
90 | |
91 // XXX FIXME XXX -- probably shouldn't be directly altering the | |
92 // symbol table here. | |
93 | |
94 fbi_sym_tab->clear_function (fname); | |
95 } | |
96 else | |
97 error ("inline: unable to define function"); | |
98 } | |
47 | 99 |
48 octave_value_list | 100 octave_value_list |
49 octave_fcn_handle::subsref (const std::string& type, | 101 octave_fcn_handle::subsref (const std::string& type, |
50 const std::list<octave_value_list>& idx, | 102 const std::list<octave_value_list>& idx, |
51 int nargout) | 103 int nargout) |
63 | 115 |
64 | 116 |
65 case '{': | 117 case '{': |
66 case '.': | 118 case '.': |
67 { | 119 { |
68 std::string nm = type_name (); | 120 std::string typ_nm = type_name (); |
69 error ("%s cannot be indexed with %c", nm.c_str (), type[0]); | 121 error ("%s cannot be indexed with %c", typ_nm.c_str (), type[0]); |
70 } | 122 } |
71 break; | 123 break; |
72 | 124 |
73 default: | 125 default: |
74 panic_impossible (); | 126 panic_impossible (); |
92 } | 144 } |
93 | 145 |
94 void | 146 void |
95 octave_fcn_handle::print_raw (std::ostream& os, bool pr_as_read_syntax) const | 147 octave_fcn_handle::print_raw (std::ostream& os, bool pr_as_read_syntax) const |
96 { | 148 { |
97 octave_print_internal (os, nm, pr_as_read_syntax, | 149 if (is_inline ()) |
98 current_print_indent_level ()); | 150 { |
151 OSSTREAM buf; | |
152 | |
153 if (nm.empty ()) | |
154 buf << "@f("; | |
155 else | |
156 buf << nm << "("; | |
157 | |
158 for (int i = 0; i < ifargs.length (); i++) | |
159 { | |
160 if (i) | |
161 buf << ", "; | |
162 | |
163 buf << ifargs(i); | |
164 } | |
165 | |
166 buf << ") = " << iftext << OSSTREAM_ENDS; | |
167 | |
168 octave_print_internal (os, OSSTREAM_STR (buf), pr_as_read_syntax, | |
169 current_print_indent_level ()); | |
170 OSSTREAM_FREEZE (buf); | |
171 } | |
172 else | |
173 octave_print_internal (os, nm, pr_as_read_syntax, | |
174 current_print_indent_level ()); | |
175 } | |
176 | |
177 octave_value | |
178 octave_fcn_handle::convert_to_str_internal (bool, bool) const | |
179 { | |
180 octave_value retval; | |
181 | |
182 if (is_inline ()) | |
183 retval = octave_value (inline_fcn_text ()); | |
184 else | |
185 error ("convert_to_str_internal: must be an inline function"); | |
186 | |
187 return retval; | |
99 } | 188 } |
100 | 189 |
101 octave_value | 190 octave_value |
102 make_fcn_handle (const std::string& nm) | 191 make_fcn_handle (const std::string& nm) |
103 { | 192 { |
104 octave_value retval; | 193 octave_value retval; |
105 | 194 |
106 octave_function *f = lookup_function (nm); | 195 octave_value f = lookup_function (nm); |
107 | 196 |
108 if (f) | 197 if (f.is_function ()) |
109 retval = octave_value (f, nm); | 198 retval = octave_value (new octave_fcn_handle (f, nm)); |
110 else | 199 else |
111 error ("error creating function handle \"@%s\"", nm.c_str ()); | 200 error ("error creating function handle \"@%s\"", nm.c_str ()); |
112 | 201 |
113 return retval; | 202 return retval; |
114 } | 203 } |
115 | 204 |
116 DEFUN (functions, args, , | 205 DEFUN (inline, args, , |
117 "-*- texinfo -*-\n\ | 206 "-*- texinfo -*-\n\ |
118 @deftypefn {Built-in Function} {} functions (@var{fcn_handle})\n\ | 207 @deftypefn {Built-in Function} {} inline (@var{str})\n\ |
119 Return a struct containing information about the function handle\n\ | 208 @deftypefnx {Built-in Function} {} inline (@var{str}, @var{arg1}, ...)\n\ |
120 @var{fcn_handle}.\n\ | 209 @deftypefnx {Built-in Function} {} inline (@var{str}, @var{n})\n\ |
121 @end deftypefn") | 210 Define a function from a string @var{str}.\n\ |
122 { | 211 \n\ |
123 octave_value retval; | 212 Create an inline function. Called with a single argument, the\n\ |
124 | 213 function is assumed to have a single argument and will be defined\n\ |
125 if (args.length () == 1) | 214 as the first isolated lower case character, except i or j.\n\ |
126 { | 215 \n\ |
127 octave_fcn_handle *fh = args(0).fcn_handle_value (); | 216 If the second and subsequent arguments are strings, they are the names of\n\ |
217 the arguments of the function.\n\ | |
218 \n\ | |
219 If the second argument is an integer @var{n}, the arguments are\n\ | |
220 @code{\"x\"}, @code{\"P1\"}, @dots{}, @code{\"P@var{N}\"}.\n\ | |
221 @end deftypefn\n\ | |
222 @seealso{argnames, formula, vectorize}") | |
223 { | |
224 octave_value retval; | |
225 | |
226 int nargin = args.length (); | |
227 | |
228 if (nargin > 0) | |
229 { | |
230 std::string fun = args(0).string_value (); | |
128 | 231 |
129 if (! error_state) | 232 if (! error_state) |
130 { | 233 { |
131 octave_function *fcn = fh ? fh->function_value (true) : 0; | 234 string_vector fargs; |
132 | 235 |
133 if (fcn) | 236 if (nargin == 1) |
134 { | 237 { |
135 Octave_map m; | 238 fargs.resize (1); |
136 | 239 |
137 std::string fh_nm = fh->name (); | 240 // Find the first isolated string as the argument of the |
138 | 241 // function. |
139 m.assign ("function", fh_nm.substr (1)); | 242 |
140 | 243 // XXX FIXME XXX -- use just "x" for now. |
141 if (fcn->is_nested_function ()) | 244 fargs(0) = "x"; |
142 m.assign ("type", "subfunction"); | 245 } |
246 else if (nargin == 2 && args(1).is_numeric_type ()) | |
247 { | |
248 int n = args(1).int_value (); | |
249 | |
250 if (! error_state) | |
251 { | |
252 if (n >= 0) | |
253 { | |
254 fargs.resize (n+1); | |
255 | |
256 fargs(0) = "x"; | |
257 | |
258 for (int i = 1; i < n+1; i++) | |
259 { | |
260 OSSTREAM buf; | |
261 buf << "P" << i << OSSTREAM_ENDS; | |
262 fargs(i) = OSSTREAM_STR (buf); | |
263 OSSTREAM_FREEZE (buf); | |
264 } | |
265 } | |
266 else | |
267 { | |
268 error ("inline: numeric argument must be nonnegative"); | |
269 return retval; | |
270 } | |
271 } | |
143 else | 272 else |
144 m.assign ("type", "simple"); | 273 { |
145 | 274 error ("inline: expecting second argument to be an integer"); |
146 std::string nm = fcn->fcn_file_name (); | 275 return retval; |
147 | 276 } |
148 if (nm.empty ()) | |
149 m.assign ("file", "built-in function"); | |
150 else | |
151 m.assign ("file", nm); | |
152 | |
153 retval = m; | |
154 } | 277 } |
155 else | 278 else |
156 error ("functions: invalid function handle object"); | 279 { |
280 fargs.resize (nargin - 1); | |
281 | |
282 for (int i = 1; i < nargin; i++) | |
283 { | |
284 std::string s = args(i).string_value (); | |
285 | |
286 if (! error_state) | |
287 fargs(i-1) = s; | |
288 else | |
289 { | |
290 error ("inline: expecting string arguments"); | |
291 return retval; | |
292 } | |
293 } | |
294 } | |
295 | |
296 retval = octave_value (new octave_fcn_handle (fun, fargs)); | |
157 } | 297 } |
158 else | 298 else |
159 error ("functions: argument must be a function handle object"); | 299 error ("inline: first argument must be a string"); |
160 } | 300 } |
161 else | 301 else |
162 print_usage ("functions"); | 302 print_usage ("inline"); |
163 | 303 |
164 return retval; | 304 return retval; |
165 } | 305 } |
166 | 306 |
167 DEFUN (func2str, args, , | 307 DEFUN (formula, args, , |
168 "-*- texinfo -*-\n\ | 308 "-*- texinfo -*-\n\ |
169 @deftypefn {Built-in Function} {} func2str (@var{fcn_handle})\n\ | 309 @deftypefn {Built-in Function} {} formula (@var{fun})\n\ |
170 Return a string containing the name of the function referenced by\n\ | 310 Return a string representing the inline function @var{fun}.\n\ |
171 the function handle @var{fcn_handle}.\n\ | 311 @end deftypefn\n\ |
172 @end deftypefn") | 312 @seealso{argnames, inline, vectorize}") |
173 { | 313 { |
174 octave_value retval; | 314 octave_value retval; |
175 | 315 |
176 if (args.length () == 1) | 316 int nargin = args.length (); |
177 { | 317 |
178 octave_fcn_handle *fh = args(0).fcn_handle_value (); | 318 if (nargin == 1) |
179 | 319 { |
180 if (! error_state && fh) | 320 octave_fcn_handle* fn = args(0).fcn_handle_value (true); |
321 | |
322 if (fn && fn->is_inline ()) | |
323 retval = octave_value (fn->inline_fcn_text ()); | |
324 else | |
325 error ("formula: must be an inline function"); | |
326 } | |
327 else | |
328 print_usage ("formula"); | |
329 | |
330 return retval; | |
331 } | |
332 | |
333 DEFUN (argnames, args, , | |
334 "-*- texinfo -*-\n\ | |
335 @deftypefn {Built-in Function} {} argnames (@var{fun})\n\ | |
336 Return a cell array of strings containing the names of the arguments\n\ | |
337 of the inline function @var{fun}.\n\ | |
338 @end deftypefn\n\ | |
339 @seealso{argnames, inline, formula, vectorize}") | |
340 { | |
341 octave_value retval; | |
342 | |
343 int nargin = args.length (); | |
344 | |
345 if (nargin == 1) | |
346 { | |
347 octave_fcn_handle *fn = args(0).fcn_handle_value (true); | |
348 | |
349 if (fn && fn->is_inline ()) | |
181 { | 350 { |
182 std::string fh_nm = fh->name (); | 351 string_vector t1 = fn->inline_fcn_arg_names (); |
183 retval = fh_nm.substr (1); | 352 |
353 Cell t2 (dim_vector (t1.length (), 1)); | |
354 | |
355 for (int i = 0; i < t1.length (); i++) | |
356 t2(i) = t1(i); | |
357 | |
358 retval = t2; | |
184 } | 359 } |
185 else | 360 else |
186 error ("func2str: expecting valid function handle as first argument"); | 361 error ("argnames: argument must be an inline function"); |
187 } | 362 } |
188 else | 363 else |
189 print_usage ("func2str"); | 364 print_usage ("argnames"); |
190 | 365 |
191 return retval; | 366 return retval; |
192 } | 367 } |
193 | 368 |
194 DEFUN (str2func, args, , | 369 DEFUN (vectorize, args, , |
195 "-*- texinfo -*-\n\ | 370 "-*- texinfo -*-\n\ |
196 @deftypefn {Built-in Function} {} str2func (@var{fcn_name})\n\ | 371 @deftypefn {Built-in Function} {} argnames (@var{fun})\n\ |
197 Return a function handle constructed from the string @var{fcn_name}.\n\ | 372 Create a vectorized version of the inline function @var{fun}\n\ |
198 @end deftypefn") | 373 by replacing all occurrences of @code{*}, @code{/}, etc., with\n\ |
199 { | 374 @code{.*}, @code{./}, etc.\n\ |
200 octave_value retval; | 375 @end deftypefn\n\ |
201 | 376 @seealso{argnames, inline, formula, vectorize}") |
202 if (args.length () == 1) | 377 { |
203 { | 378 octave_value retval; |
204 std::string nm = args(0).string_value (); | 379 |
205 | 380 int nargin = args.length (); |
206 if (! error_state) | 381 |
207 retval = make_fcn_handle (nm); | 382 if (nargin == 1) |
383 { | |
384 octave_fcn_handle* old = args(0).fcn_handle_value (true); | |
385 | |
386 if (old && old->is_inline ()) | |
387 { | |
388 std::string old_func = old->inline_fcn_text (); | |
389 std::string new_func; | |
390 | |
391 size_t i = 0; | |
392 | |
393 while (i < old_func.length ()) | |
394 { | |
395 std::string t1 = old_func.substr (i, 1); | |
396 | |
397 if (t1 == "*" || t1 == "/" || t1 == "\\" || t1 == "^") | |
398 { | |
399 if (i && old_func.substr (i-1, 1) != ".") | |
400 new_func.append ("."); | |
401 | |
402 // Special case for ** operator. | |
403 if (t1 == "*" && i < (old_func.length () - 1) | |
404 && old_func.substr (i+1, 1) == "*") | |
405 { | |
406 new_func.append ("*"); | |
407 i++; | |
408 } | |
409 } | |
410 new_func.append (t1); | |
411 i++; | |
412 } | |
413 | |
414 retval = octave_value (new octave_fcn_handle (new_func, old->inline_fcn_arg_names ())); | |
415 } | |
208 else | 416 else |
209 error ("str2func: expecting string as first argument"); | 417 error ("vectorize: must be an inline function"); |
210 } | 418 } |
211 else | 419 else |
212 print_usage ("str2func"); | 420 print_usage ("vectorize"); |
213 | 421 |
214 return retval; | 422 return retval; |
215 } | 423 } |
216 | 424 |
217 /* | 425 /* |