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 /*