GNU Octave 10.1.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 
Loading...
Searching...
No Matches
pt-idx.cc
Go to the documentation of this file.
1////////////////////////////////////////////////////////////////////////
2//
3// Copyright (C) 1996-2025 The Octave Project Developers
4//
5// See the file COPYRIGHT.md in the top-level directory of this
6// distribution or <https://octave.org/copyright/>.
7//
8// This file is part of Octave.
9//
10// Octave is free software: you can redistribute it and/or modify it
11// under the terms of the GNU General Public License as published by
12// the Free Software Foundation, either version 3 of the License, or
13// (at your option) any later version.
14//
15// Octave is distributed in the hope that it will be useful, but
16// WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU General Public License for more details.
19//
20// You should have received a copy of the GNU General Public License
21// along with Octave; see the file COPYING. If not, see
22// <https://www.gnu.org/licenses/>.
23//
24////////////////////////////////////////////////////////////////////////
25
26#if defined (HAVE_CONFIG_H)
27# include "config.h"
28#endif
29
30#include "Cell.h"
31#include "error.h"
32#include "interpreter-private.h"
33#include "oct-map.h"
34#include "ovl.h"
35#include "oct-lvalue.h"
36#include "ov.h"
37#include "pt-arg-list.h"
38#include "pt-eval.h"
39#include "pt-id.h"
40#include "pt-idx.h"
41#include "utils.h"
42#include "variables.h"
43#include "errwarn.h"
44
46
47// Index expressions.
48
49tree_index_expression::tree_index_expression (tree_expression *e, const token& open_delim, tree_argument_list *lst, const token& close_delim, char t)
50 : m_expr (e), m_args (0), m_type (), m_arg_nm (), m_dyn_field (), m_word_list_cmd (false)
51{
52 append (open_delim, lst, close_delim, t);
53}
54
56 : m_expr (e), m_args (0), m_type (), m_arg_nm (), m_dyn_field (), m_word_list_cmd (false)
57{
58 append (dot_tok, struct_elt_tok);
59}
60
61tree_index_expression::tree_index_expression (tree_expression *e, const token& dot_tok, const token& open_paren, tree_expression *df, const token& close_paren)
62 : m_expr (e), m_args (0), m_type (), m_arg_nm (), m_dyn_field (), m_word_list_cmd (false)
63{
64 append (dot_tok, open_paren, df, close_paren);
65}
66
68tree_index_expression::append (const token& open_delim, tree_argument_list *lst, const token& close_delim, char t)
69{
70 lst->mark_in_delims (open_delim, close_delim);
71 m_args.push_back (lst);
72 m_type.append (1, t);
73 m_dot_tok.push_back (token ());
74 m_arg_nm.push_back (lst ? lst->get_arg_names () : string_vector ());
75 m_dyn_field.push_back (static_cast<tree_expression *> (nullptr));
76
77 if (lst && lst->has_magic_tilde ())
78 error ("invalid use of empty argument (~) in index expression");
79
80 return this;
81}
82
84tree_index_expression::append (const token& dot_tok, const token& struct_elt_tok)
85{
86 m_args.push_back (static_cast<tree_argument_list *> (nullptr));
87 m_type += '.';
88 m_dot_tok.push_back (dot_tok);
89 m_arg_nm.push_back (struct_elt_tok.text ());
90 m_dyn_field.push_back (static_cast<tree_expression *> (nullptr));
91
92 return this;
93}
94
96tree_index_expression::append (const token& dot_tok, const token& open_paren, tree_expression *df, const token& close_paren)
97{
98 m_args.push_back (static_cast<tree_argument_list *> (nullptr));
99 m_type += '.';
100 m_dot_tok.push_back (dot_tok);
101 m_arg_nm.push_back ("");
102 df->mark_in_delims (open_paren, close_paren);
103 m_dyn_field.push_back (df);
104
105 return this;
106}
107
109{
110 delete m_expr;
111
112 while (! m_args.empty ())
113 {
114 auto p = m_args.begin ();
115 delete *p;
116 m_args.erase (p);
117 }
118
119 while (! m_dyn_field.empty ())
120 {
121 auto p = m_dyn_field.begin ();
122 delete *p;
123 m_dyn_field.erase (p);
124 }
125}
126
127// This is useful for printing the name of the variable in an indexed
128// assignment.
129
130std::string
132{
133 return m_expr->name ();
134}
135
138{
139 int n = m_args.size ();
140
141 if (n == 0)
142 return m_expr->end_pos ();
143
144 switch (m_type[n-1])
145 {
146 case '(':
147 case '{':
148 {
149 tree_argument_list *args = m_args.back ();
150 return args->end_pos ();
151 }
152 break;
153
154 case '.':
155 {
156 string_vector arg_names = m_arg_nm.back ();
157
158 if (arg_names.empty ())
159 {
160 tree_expression *dyn_field = m_dyn_field.back ();
161
162 if (dyn_field)
163 return dyn_field->end_pos ();
164 else
165 error ("unexpected: dynamic field is nullptr in call to tree_index_expression::end_pos - please report this bug");
166
167 }
168
169 token dot_tok = m_dot_tok.back ();
170 std::string arg_nm = arg_names(0);
171
172 // FIXME: this might not be correct because we have no way
173 // to account for space between the '.' operator and the
174 // field name. Maybe we should really be storing an
175 // identifier that contains position information?
176
177 filepos pos = dot_tok.end_pos ();
178 pos.increment_column (arg_nm.size ());
179
180 return pos;
181 }
182
183 default:
184 error ("unexpected: index not '(', '{', or '.' in tree_index_expression::end_pos - please report this bug");
185 }
186}
187
188std::string
190(tree_evaluator& tw,
191 std::list<string_vector>::const_iterator p_arg_nm,
192 std::list<tree_expression *>::const_iterator p_dyn_field) const
193{
194 std::string fn = (*p_arg_nm)(0);
195
196 if (fn.empty ())
197 {
198 tree_expression *df = *p_dyn_field;
199
200 if (df)
201 {
202 octave_value t = df->evaluate (tw);
203
204 fn = t.xstring_value ("dynamic structure field names must be strings");
205 }
206 else
207 error ("unexpected: DF is nullptr in call to tree_index_expression::get_struct_index - please report this bug");
208 }
209
210 return fn;
211}
212
215{
216 std::list<octave_value_list> idx;
217
218 int n = m_args.size ();
219
220 auto p_args = m_args.begin ();
221 auto p_arg_nm = m_arg_nm.begin ();
222 auto p_dyn_field = m_dyn_field.begin ();
223
224 octave_lvalue retval = m_expr->lvalue (tw);
225
227 act ([&tw] (const octave_value& val,
228 const std::string& index_type,
229 const std::list<octave_value_list>& index_list)
230 {
231 tw.set_indexed_object (val);
232 tw.set_index_list (index_type, index_list);
233 }, tw.indexed_object (), tw.index_type (), tw.index_list ());
234
235 tw.set_indexed_object (retval.value ());
236 tw.clear_index_list ();
237
238 for (int i = 0; i < n; i++)
239 {
240 switch (m_type[i])
241 {
242 case '(':
243 {
244 octave_value_list tidx = tw.make_value_list (*p_args, *p_arg_nm);
245
246 tw.append_index_list ('(', tidx);
247 idx.push_back (tidx);
248 }
249 break;
250
251 case '{':
252 {
253 octave_value_list tidx = tw.make_value_list (*p_args, *p_arg_nm);
254
255 tw.append_index_list ('{', tidx);
256 idx.push_back (tidx);
257 }
258 break;
259
260 case '.':
261 {
262 octave_value tidx = get_struct_index (tw, p_arg_nm, p_dyn_field);
263
264 tw.append_index_list ('.', tidx);
265 idx.push_back (tidx);
266 }
267 break;
268
269 default:
270 error ("unexpected: index not '(', '{', or '.' in tree_index_expression::lvalue - please report this bug");
271 }
272
273 if (idx.back ().empty ())
274 error ("invalid empty index list");
275
276 p_args++;
277 p_arg_nm++;
278 p_dyn_field++;
279 }
280
281 retval.set_index (m_type, idx);
282
283 return retval;
284}
285
288{
289 tree_index_expression *new_idx_expr = new tree_index_expression ();
290
291 new_idx_expr->m_expr = (m_expr ? m_expr->dup (scope) : nullptr);
292
293 std::list<tree_argument_list *> new_args;
294
295 for (const tree_argument_list *elt : m_args)
296 new_args.push_back (elt ? elt->dup (scope) : nullptr);
297
298 new_idx_expr->m_args = new_args;
299
300 new_idx_expr->m_type = m_type;
301
302 new_idx_expr->m_arg_nm = m_arg_nm;
303
304 std::list<tree_expression *> new_dyn_field;
305
306 for (const tree_expression *elt : m_dyn_field)
307 new_dyn_field.push_back (elt ? elt->dup (scope) : nullptr);
308
309 new_idx_expr->m_dyn_field = new_dyn_field;
310
311 new_idx_expr->copy_base (*this);
312
313 return new_idx_expr;
314}
315
316// Unlike Matlab, which does not allow the result of a function call
317// or array indexing expression to be further indexed, Octave attempts
318// to handle arbitrary index expressions. For example, Octave allows
319// expressions like
320//
321// svd (rand (10))(1:5)
322//
323// Although octave_value objects may contain function objects, no
324// indexing operation or function call is supposed to return them
325// directly. Instead, the language is supposed to only allow function
326// objects to be stored as function handles (named or anonymous) or as
327// inline functions. The only place a function object should appear
328// directly is if the symbol stored in a tree_identifier object
329// resolves to a function. This means that the only place we need to
330// look for functions is in the first element of the index
331// expression.
332//
333// Steps:
334//
335// * Obtain the initial value from the expression component of the
336// tree_index_expression object. If it is a tree_identifier object
337// indexed by '(args)' and the identifier is not a variable, then
338// perform a function call. Use the (optional) arguments to perform
339// the function lookup so we choose the correct function or class
340// method to call. Otherwise, evaluate the first expression
341// without any additional arguments.
342//
343// * Iterate over the remaining elements of the index expression and
344// call the octave_value::subsref method. If indexing a class or
345// classdef object, build up a list of indices for a call to the
346// subsref method for the object. Otherwise, use the result of
347// each temporary evaluation for the next index element.
348//
349// * If not indexing a class or classdef object and any partial
350// expression evaluation produces a class or classdef object, then
351// build up a complete argument list from that point on for a final
352// subsref call for that object.
353//
354// Multiple partial evaluations may be required. For example,
355// given a class or classdef object X, then for the expression
356//
357// x.a{end}(2:end).b
358//
359// we must evaluate x.a to obtain the size for the first {end}
360// expression, then we must evaluate x.a{end} to obtain the size
361// for the second (2:end) expression. Finally, the complete
362// expression may be evaluated.
363//
364// If X is a cell array in the above expression, and none of the
365// intermediate evaluations produces a class or classdef object,
366// then the evaluation is performed as the following series of
367// steps
368//
369// tmp = x.a
370// tmp = tmp{end}
371// tmp = tmp(2:end)
372// result = tmp.b
373//
374// If any of the partial evaluations produces a class or classdef
375// object, then the subsref method for that object is called as
376// described above. For example, suppose x.a produces a classdef
377// object. Then the evaluation is performed as the following
378// series of steps
379//
380// base_expr = tmp = x.a
381// tmp = base_expr{end}
382// base_expr{end}(2:end).b
383//
384// In the last two steps, the partial value computed in the
385// previous step is used to determine the value of END.
386
389{
390 octave_value_list retval;
391
392 panic_if (m_args.empty ());
393
394 auto p_args = m_args.begin ();
395 auto p_arg_nm = m_arg_nm.begin ();
396 auto p_dyn_field = m_dyn_field.begin ();
397
398 int n = m_args.size ();
399 int beg = 0;
400
401 octave_value base_expr_val;
402
403 if (m_expr->is_identifier () && m_type[beg] == '(')
404 {
405 tree_identifier *id = dynamic_cast<tree_identifier *> (m_expr);
406
407 bool is_var = tw.is_variable (m_expr);
408
409 std::string nm = id->name ();
410
411 if (is_var && is_word_list_cmd ())
412 {
413 bool maybe_binary_op = false;
414 if ((*p_args) && (*p_args)->size () > 0)
415 {
416 // check if first character of first argument might be (the
417 // start of) a binary operator
418 std::string ops = "+-*/\\.^|&";
419 string_vector arg_list = (*p_args)->get_arg_names ();
420 if (! arg_list.isempty ()
421 && (ops.find (arg_list(0)[1]) != std::string::npos))
422 maybe_binary_op = true;
423 }
424
425 std::string advice;
426 if (maybe_binary_op)
427 advice = "\nCheck whitespace around potential binary operator.";
428
429 error ("variable \"%s\" used as function in command style expression%s",
430 nm.c_str (), advice.c_str ());
431 }
432
433 if (! is_var)
434 {
435 octave_value_list first_args;
436
437 tree_argument_list *al = *p_args;
438
439 if (al && al->size () > 0)
440 {
441 unwind_action act ([&tw] (const std::list<octave_lvalue> *lvl)
442 {
443 tw.set_lvalue_list (lvl);
444 }, tw.lvalue_list ());
445
446 tw.set_lvalue_list (nullptr);
447
448 string_vector anm = *p_arg_nm;
449
450 first_args = tw.convert_to_const_vector (al);
451
452 first_args.stash_name_tags (anm);
453 }
454
455 interpreter& interp = tw.get_interpreter ();
456
457 symbol_table& symtab = interp.get_symbol_table ();
458
459 octave_value val = symtab.find_function (nm, first_args);
460
461 octave_function *fcn = nullptr;
462
463 if (val.is_function ())
464 fcn = val.function_value (true);
465
466 if (fcn)
467 {
468 try
469 {
470 retval = fcn->call (tw, nargout, first_args);
471 }
472 catch (index_exception& ie)
473 {
474 tw.final_index_error (ie, m_expr);
475 }
476
477 beg++;
478 p_args++;
479 p_arg_nm++;
480 p_dyn_field++;
481
482 if (n > beg)
483 {
484 // More indices to follow. Silently ignore
485 // extra output values.
486
487 if (retval.length () == 0)
488 error ("indexing undefined value");
489 else
490 base_expr_val = retval(0);
491 }
492 else
493 {
494 // No more indices, so we are done.
495
496 // See note at end of function about deleting
497 // temporaries prior to pushing result.
498
499 base_expr_val = octave_value ();
500 first_args = octave_value_list ();
501
502 return retval;
503 }
504 }
505 }
506 }
507
508 if (base_expr_val.is_undefined ())
509 base_expr_val = m_expr->evaluate (tw);
510
511 // If we are indexing an object or looking at something like
512 //
513 // classname.static_function (args, ...);
514 //
515 // then we'll just build a complete index list for one big subsref
516 // call. If the expression we are indexing is a classname then
517 // base_expr_val will be an octave_classdef_meta object. If we have
518 // files in a +packagename folder, they will also be an
519 // octave_classdef_meta object, but we don't want to index them.
520
521 std::list<octave_value_list> idx_list;
522
523 {
524 // Note: need new scope so that the following unwind action will
525 // happen before we perform the final indexing for objects (for
526 // example).
527
529 act ([&tw] (const octave_value& val,
530 const std::string& index_type,
531 const std::list<octave_value_list>& index_list)
532 {
533 tw.set_indexed_object (val);
534 tw.set_index_list (index_type, index_list);
535 },
536 tw.indexed_object (),
537 tw.index_type (), tw.index_list ());
538
539 tw.set_indexed_object ();
540 tw.clear_index_list ();
541
542 bool indexing_object = (base_expr_val.isobject ()
543 || base_expr_val.isjava ()
544 || (base_expr_val.is_classdef_meta ()
545 && ! base_expr_val.is_package ()));
546
547 octave_value partial_expr_val = base_expr_val;
548
549 for (int i = beg; i < n; i++)
550 {
551 if (i > beg)
552 {
553 if (! indexing_object)
554 {
555 // Evaluate what we have so far.
556
557 try
558 {
559 // Silently ignore extra output values.
560
561 octave_value_list tmp_list
562 = base_expr_val.subsref (m_type.substr (beg, i-beg),
563 idx_list, nargout);
564
565 partial_expr_val
566 = tmp_list.length () ? tmp_list(0) : octave_value ();
567
568 base_expr_val = partial_expr_val;
569
570 if (partial_expr_val.is_cs_list ())
572
573 retval = partial_expr_val;
574
575 beg = i;
576 idx_list.clear ();
577 tw.clear_index_list ();
578
579 if (partial_expr_val.isobject ()
580 || partial_expr_val.isjava ()
581 || (partial_expr_val.is_classdef_meta ()
582 && ! partial_expr_val.is_package ()))
583 {
584 // Found an object, so now we'll build up
585 // complete index list for one big subsref
586 // call from this point on.
587
588 // FIXME: is is also possible to have a
589 // static method call buried somewhere in
590 // the depths of a complex indexing
591 // expression so that we would also need to
592 // check for an octave_classdef_meta object
593 // here?
594
595 indexing_object = true;
596 }
597 }
598 catch (index_exception& ie)
599 {
600 tw.final_index_error (ie, m_expr);
601 }
602 }
603 }
604
605 tw.set_indexed_object (partial_expr_val);
606
607 switch (m_type[i])
608 {
609 case '(':
610 {
611 octave_value_list tmp = tw.make_value_list (*p_args, *p_arg_nm);
612 tw.append_index_list ('(', tmp);
613 idx_list.push_back (tmp);
614 }
615 break;
616
617 case '{':
618 {
619 octave_value_list tmp = tw.make_value_list (*p_args, *p_arg_nm);
620 tw.append_index_list ('{', tmp);
621 idx_list.push_back (tmp);
622 }
623 break;
624
625 case '.':
626 {
627 octave_value tmp = get_struct_index (tw, p_arg_nm, p_dyn_field);
628 tw.append_index_list ('.', tmp);
629 idx_list.push_back (tmp);
630 }
631 break;
632
633 default:
634 error ("unexpected: index not '(', '{', or '.' in tree_index_expression::evaluate_n - please report this bug");
635 }
636
637 p_args++;
638 p_arg_nm++;
639 p_dyn_field++;
640 }
641 }
642
643 // If ! idx_list.empty () that means we still have stuff to index
644 // otherwise they would have been dealt with and idx_list would have
645 // been emptied.
646 if (! idx_list.empty ())
647 {
648 // This is for +package and other classdef_meta objects
649 if (! base_expr_val.is_function ()
650 || base_expr_val.is_classdef_meta ())
651 {
652 try
653 {
654 retval = base_expr_val.subsref (m_type.substr (beg, n-beg),
655 idx_list, nargout);
656 beg = n;
657 idx_list.clear ();
658 }
659 catch (index_exception& ie)
660 {
661 tw.final_index_error (ie, m_expr);
662 }
663 }
664 else
665 {
666 // FIXME: we want this to only be a superclass constructor
667 // call Should we actually make a check for this or are all
668 // other types of calls already dealt with?
669
670 octave_function *fcn = base_expr_val.function_value ();
671
672 if (fcn)
673 {
674 try
675 {
676 // FIXME: is it possible for the IDX_LIST to have
677 // more than one element here? Do we need to check?
678
679 octave_value_list final_args;
680
681 if (idx_list.size () != 1)
682 error ("unexpected extra index at end of expression");
683
684 if (m_type[beg] != '(')
685 error ("invalid index type '%c' for function call",
686 m_type[beg]);
687
688 final_args = idx_list.front ();
689
690 // FIXME: Do we ever need the names of the arguments
691 // passed to FCN here?
692
693 retval = fcn->call (tw, nargout, final_args);
694 }
695 catch (index_exception& ie)
696 {
697 tw.final_index_error (ie, m_expr);
698 }
699 }
700 }
701 }
702
703 // FIXME: when can the following happen? In what case does indexing
704 // result in a value that is a function? Classdef method calls?
705 // Something else?
706
707 octave_value val = (retval.length () ? retval(0) : octave_value ());
708
709 if (val.is_function ())
710 {
711 octave_function *fcn = val.function_value (true);
712
713 if (fcn)
714 {
715 octave_value_list final_args;
716
717 if (! idx_list.empty ())
718 {
719 if (n - beg != 1)
720 error ("unexpected extra index at end of expression");
721
722 if (m_type[beg] != '(')
723 error ("invalid index type '%c' for function call",
724 m_type[beg]);
725
726 final_args = idx_list.front ();
727 }
728
729 retval = fcn->call (tw, nargout, final_args);
730 }
731 }
732
733 // Delete any temporary values prior to returning so that
734 // destructors for any temporary classdef handle objects will be
735 // called before we return.
736
737 idx_list.clear ();
738 base_expr_val = octave_value ();
739 val = octave_value ();
740
741 return retval;
742}
743
744OCTAVE_END_NAMESPACE(octave)
745
746/*
747%!test
748%! clear x;
749%! clear y;
750%! y = 3;
751%! x(y(end)) = 1;
752%! assert (x, [0, 0, 1]);
753%! clear x;
754%! clear y;
755%! y = {3};
756%! x(y{end}) = 1;
757%! assert (x, [0, 0, 1]);
758
759%!test
760%! x = {1, 2, 3};
761%! [x{:}] = deal (4, 5, 6);
762%! assert (x, {4, 5, 6});
763
764%!test
765%! [x.a, x.b.c] = deal (1, 2);
766%! assert (x.a == 1 && x.b.c == 2);
767
768%!test
769%! [x.a, x(2).b] = deal (1, 2);
770%! assert (x(1).a == 1 && isempty (x(2).a) && isempty (x(1).b) && x(2).b == 2);
771
772%!test
773%! x = struct (zeros (0, 1), {"a", "b"});
774%! x(2).b = 1;
775%! assert (x(2).b == 1);
776
777%!test
778%! x = struct (zeros (0, 1), {"a", "b"});
779%! x(2).b = 1;
780%! assert (x(2).b == 1);
781*/
void increment_column(int val=1)
Definition filepos.h:56
symbol_table & get_symbol_table()
virtual octave_value_list call(octave::tree_evaluator &tw, int nargout=0, const octave_value_list &args=octave_value_list())
Definition ov-fcn.cc:67
void set_index(const std::string &t, const std::list< octave_value_list > &i)
octave_value value() const
void stash_name_tags(const string_vector &nm)
Definition ovl.h:163
void clear()
Definition ovl.h:171
octave_idx_type length() const
Definition ovl.h:111
bool is_undefined() const
Definition ov.h:595
octave_value subsref(const std::string &type, const std::list< octave_value_list > &idx)
Definition ov.h:476
octave_function * function_value(bool silent=false) const
bool is_classdef_meta() const
Definition ov.h:652
bool isjava() const
Definition ov.h:667
bool is_function() const
Definition ov.h:777
bool is_package() const
Definition ov.h:661
bool is_cs_list() const
Definition ov.h:670
std::string xstring_value(const char *fmt,...) const
bool isobject() const
Definition ov.h:664
bool isempty() const
Definition str-vec.h:100
octave_value find_function(const std::string &name, const symbol_scope &search_scope=symbol_scope::invalid())
Definition symtab.cc:254
Definition token.h:42
filepos end_pos() const
Definition token.h:129
std::string text() const
Definition token.h:151
filepos end_pos() const
Definition pt-arg-list.h:86
string_vector get_arg_names() const
bool has_magic_tilde() const
tree_argument_list * mark_in_delims(const token &open_delim, const token &close_delim)
Definition pt-arg-list.h:66
void set_indexed_object(const octave_value &obj=octave_value())
Definition pt-eval.h:722
interpreter & get_interpreter()
Definition pt-eval.h:422
void final_index_error(index_exception &ie, const tree_expression *expr)
Definition pt-eval.cc:4826
const std::list< octave_lvalue > * lvalue_list() const
Definition pt-eval.h:762
octave_value_list convert_to_const_vector(tree_argument_list *arg_list)
Definition pt-eval.cc:2358
const std::list< octave_value_list > & index_list() const
Definition pt-eval.h:727
octave_value indexed_object() const
Definition pt-eval.h:717
octave_value_list make_value_list(tree_argument_list *args, const string_vector &arg_nm)
Definition pt-eval.cc:4864
bool is_variable(const std::string &name) const
Definition pt-eval.cc:1881
const std::string & index_type() const
Definition pt-eval.h:751
void set_lvalue_list(const std::list< octave_lvalue > *lst)
Definition pt-eval.h:767
void append_index_list(char type, const octave_value_list &idx)
Definition pt-eval.h:745
void clear_index_list()
Definition pt-eval.h:739
void set_index_list(const std::string &index_type, const std::list< octave_value_list > &index_list)
Definition pt-eval.h:732
virtual octave_value evaluate(tree_evaluator &tw, int nargout=1)=0
virtual bool is_identifier() const
Definition pt-exp.h:68
tree_expression * mark_in_delims(const token &open_delim, const token &close_delim)
Definition pt-exp.h:119
virtual void copy_base(const tree_expression &e)
Definition pt-exp.h:137
virtual std::string name() const
Definition pt-exp.h:111
virtual tree_expression * dup(symbol_scope &scope) const =0
virtual octave_lvalue lvalue(tree_evaluator &)
Definition pt-exp.cc:43
octave_value_list evaluate_n(tree_evaluator &tw, int nargout=1)
Definition pt-idx.cc:388
filepos end_pos() const
Definition pt-idx.cc:137
tree_index_expression * dup(symbol_scope &scope) const
Definition pt-idx.cc:287
std::string name() const
Definition pt-idx.cc:131
std::list< string_vector > arg_names()
Definition pt-idx.h:87
bool is_word_list_cmd() const
Definition pt-idx.h:93
tree_index_expression(tree_expression *e, const token &open_delim, tree_argument_list *lst, const token &close_delim, char t)
Definition pt-idx.cc:49
std::string get_struct_index(tree_evaluator &tw, std::list< string_vector >::const_iterator p_arg_nm, std::list< tree_expression * >::const_iterator p_dyn_field) const
Definition pt-idx.cc:190
octave_lvalue lvalue(tree_evaluator &tw)
Definition pt-idx.cc:214
tree_index_expression * append(const token &open_delim, tree_argument_list *lst, const token &close_delim, char t='(')
Definition pt-idx.cc:68
virtual filepos end_pos() const =0
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
void error(const char *fmt,...)
Definition error.cc:1003
void err_indexed_cs_list()
Definition errwarn.cc:65
#define panic_if(cond)
Definition panic.h:57