00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026
00027 #include "Cell.h"
00028 #include "error.h"
00029 #include "oct-map.h"
00030 #include "oct-obj.h"
00031 #include "oct-lvalue.h"
00032 #include "ov.h"
00033 #include "pager.h"
00034 #include "pt-arg-list.h"
00035 #include "pt-bp.h"
00036 #include "pt-id.h"
00037 #include "pt-idx.h"
00038 #include "pt-walk.h"
00039 #include "utils.h"
00040 #include "variables.h"
00041 #include "gripes.h"
00042
00043
00044
00045 tree_index_expression::tree_index_expression (int l, int c)
00046 : tree_expression (l, c), expr (0), args (0), type (),
00047 arg_nm (), dyn_field () { }
00048
00049 tree_index_expression::tree_index_expression (tree_expression *e,
00050 tree_argument_list *lst,
00051 int l, int c, char t)
00052 : tree_expression (l, c), expr (e), args (0), type (),
00053 arg_nm (), dyn_field ()
00054 {
00055 append (lst, t);
00056 }
00057
00058 tree_index_expression::tree_index_expression (tree_expression *e,
00059 const std::string& n,
00060 int l, int c)
00061 : tree_expression (l, c), expr (e), args (0), type (),
00062 arg_nm (), dyn_field ()
00063 {
00064 append (n);
00065 }
00066
00067 tree_index_expression::tree_index_expression (tree_expression *e,
00068 tree_expression *df,
00069 int l, int c)
00070 : tree_expression (l, c), expr (e), args (0), type (),
00071 arg_nm (), dyn_field ()
00072 {
00073 append (df);
00074 }
00075
00076 void
00077 tree_index_expression::append (tree_argument_list *lst, char t)
00078 {
00079 args.push_back (lst);
00080 type.append (1, t);
00081 arg_nm.push_back (lst ? lst->get_arg_names () : string_vector ());
00082 dyn_field.push_back (static_cast<tree_expression *> (0));
00083
00084 if (lst && lst->has_magic_tilde ())
00085 error ("invalid use of empty argument (~) in index expression");
00086 }
00087
00088 void
00089 tree_index_expression::append (const std::string& n)
00090 {
00091 args.push_back (static_cast<tree_argument_list *> (0));
00092 type.append (".");
00093 arg_nm.push_back (n);
00094 dyn_field.push_back (static_cast<tree_expression *> (0));
00095 }
00096
00097 void
00098 tree_index_expression::append (tree_expression *df)
00099 {
00100 args.push_back (static_cast<tree_argument_list *> (0));
00101 type.append (".");
00102 arg_nm.push_back ("");
00103 dyn_field.push_back (df);
00104 }
00105
00106 tree_index_expression::~tree_index_expression (void)
00107 {
00108 delete expr;
00109
00110 while (! args.empty ())
00111 {
00112 std::list<tree_argument_list *>::iterator p = args.begin ();
00113 delete *p;
00114 args.erase (p);
00115 }
00116
00117 while (! dyn_field.empty ())
00118 {
00119 std::list<tree_expression *>::iterator p = dyn_field.begin ();
00120 delete *p;
00121 dyn_field.erase (p);
00122 }
00123 }
00124
00125 bool
00126 tree_index_expression::has_magic_end (void) const
00127 {
00128 for (std::list<tree_argument_list *>::const_iterator p = args.begin ();
00129 p != args.end ();
00130 p++)
00131 {
00132 tree_argument_list *elt = *p;
00133
00134 if (elt && elt->has_magic_end ())
00135 return true;
00136 }
00137
00138 return false;
00139 }
00140
00141
00142
00143
00144 std::string
00145 tree_index_expression::name (void) const
00146 {
00147 return expr->name ();
00148 }
00149
00150 static Cell
00151 make_subs_cell (tree_argument_list *args, const string_vector& arg_nm)
00152 {
00153 Cell retval;
00154
00155 octave_value_list arg_values;
00156
00157 if (args)
00158 arg_values = args->convert_to_const_vector ();
00159
00160 if (! error_state)
00161 {
00162 int n = arg_values.length ();
00163
00164 if (n > 0)
00165 {
00166 arg_values.stash_name_tags (arg_nm);
00167
00168 retval.resize (dim_vector (1, n));
00169
00170 for (int i = 0; i < n; i++)
00171 retval(0,i) = arg_values(i);
00172 }
00173 }
00174
00175 return retval;
00176 }
00177
00178 static inline octave_value_list
00179 make_value_list (tree_argument_list *args, const string_vector& arg_nm,
00180 const octave_value *object, bool rvalue = true)
00181 {
00182 octave_value_list retval;
00183
00184 if (args)
00185 {
00186 if (rvalue && object && args->has_magic_end () && object->is_undefined ())
00187 gripe_invalid_inquiry_subscript ();
00188 else
00189 retval = args->convert_to_const_vector (object);
00190 }
00191
00192 if (! error_state)
00193 {
00194 octave_idx_type n = retval.length ();
00195
00196 if (n > 0)
00197 retval.stash_name_tags (arg_nm);
00198 }
00199
00200 return retval;
00201 }
00202
00203 std::string
00204 tree_index_expression::get_struct_index
00205 (std::list<string_vector>::const_iterator p_arg_nm,
00206 std::list<tree_expression *>::const_iterator p_dyn_field) const
00207 {
00208 std::string fn = (*p_arg_nm)(0);
00209
00210 if (fn.empty ())
00211 {
00212 tree_expression *df = *p_dyn_field;
00213
00214 if (df)
00215 {
00216 octave_value t = df->rvalue1 ();
00217
00218 if (! error_state)
00219 {
00220 fn = t.string_value ();
00221
00222 if (! valid_identifier (fn))
00223 ::error ("invalid structure field name '%s'", fn.c_str ());
00224 }
00225 }
00226 else
00227 panic_impossible ();
00228 }
00229
00230 return fn;
00231 }
00232
00233 octave_map
00234 tree_index_expression::make_arg_struct (void) const
00235 {
00236 int n = args.size ();
00237
00238 Cell type_field (n, 1);
00239 Cell subs_field (n, 1);
00240
00241 std::list<tree_argument_list *>::const_iterator p_args = args.begin ();
00242 std::list<string_vector>::const_iterator p_arg_nm = arg_nm.begin ();
00243 std::list<tree_expression *>::const_iterator p_dyn_field = dyn_field.begin ();
00244
00245 octave_map m;
00246
00247 for (int i = 0; i < n; i++)
00248 {
00249 switch (type[i])
00250 {
00251 case '(':
00252 subs_field(i) = make_subs_cell (*p_args, *p_arg_nm);
00253 break;
00254
00255 case '{':
00256 subs_field(i) = make_subs_cell (*p_args, *p_arg_nm);
00257 break;
00258
00259 case '.':
00260 subs_field(i) = get_struct_index (p_arg_nm, p_dyn_field);
00261 break;
00262
00263 default:
00264 panic_impossible ();
00265 }
00266
00267 if (error_state)
00268 return m;
00269
00270 p_args++;
00271 p_arg_nm++;
00272 p_dyn_field++;
00273 }
00274
00275 m.assign ("type", type_field);
00276 m.assign ("subs", subs_field);
00277
00278 return m;
00279 }
00280
00281 octave_value_list
00282 tree_index_expression::rvalue (int nargout)
00283 {
00284 return tree_index_expression::rvalue (nargout, 0);
00285 }
00286
00287 octave_value_list
00288 tree_index_expression::rvalue (int nargout, const std::list<octave_lvalue> *lvalue_list)
00289 {
00290 octave_value_list retval;
00291
00292 if (error_state)
00293 return retval;
00294
00295 octave_value first_expr_val;
00296
00297 octave_value_list first_args;
00298
00299 bool have_args = false;
00300
00301 if (expr->is_identifier () && type[0] == '(')
00302 {
00303 tree_identifier *id = dynamic_cast<tree_identifier *> (expr);
00304
00305 if (! (id->is_variable () || args.empty ()))
00306 {
00307 tree_argument_list *al = *(args.begin ());
00308
00309 size_t n = al ? al->length () : 0;
00310
00311 if (n > 0)
00312 {
00313 string_vector anm = *(arg_nm.begin ());
00314 have_args = true;
00315 first_args = al -> convert_to_const_vector ();
00316 first_args.stash_name_tags (anm);
00317
00318 if (! error_state)
00319 first_expr_val = id->do_lookup (first_args);
00320 }
00321 }
00322 }
00323
00324 if (! error_state)
00325 {
00326 if (first_expr_val.is_undefined ())
00327 first_expr_val = expr->rvalue1 ();
00328
00329 octave_value tmp = first_expr_val;
00330 octave_idx_type tmpi = 0;
00331
00332 std::list<octave_value_list> idx;
00333
00334 int n = args.size ();
00335
00336 std::list<tree_argument_list *>::iterator p_args = args.begin ();
00337 std::list<string_vector>::iterator p_arg_nm = arg_nm.begin ();
00338 std::list<tree_expression *>::iterator p_dyn_field = dyn_field.begin ();
00339
00340 for (int i = 0; i < n; i++)
00341 {
00342 if (i > 0)
00343 {
00344 tree_argument_list *al = *p_args;
00345
00346
00347
00348
00349
00350
00351 bool force_split = type[i-1] == '(' && type[i] != '.';
00352
00353 if (force_split || (al && al->has_magic_end ()))
00354 {
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365 const octave_value_list tmp_list
00366 = tmp.subsref (type.substr (tmpi, i - tmpi), idx, nargout);
00367
00368 tmp = tmp_list.length () ? tmp_list(0) : octave_value ();
00369 tmpi = i;
00370 idx.clear ();
00371
00372 if (tmp.is_cs_list ())
00373 gripe_indexed_cs_list ();
00374
00375 if (error_state)
00376 break;
00377 }
00378 }
00379
00380 switch (type[i])
00381 {
00382 case '(':
00383 if (have_args)
00384 {
00385 idx.push_back (first_args);
00386 have_args = false;
00387 }
00388 else
00389 idx.push_back (make_value_list (*p_args, *p_arg_nm, &tmp));
00390 break;
00391
00392 case '{':
00393 idx.push_back (make_value_list (*p_args, *p_arg_nm, &tmp));
00394 break;
00395
00396 case '.':
00397 idx.push_back (octave_value (get_struct_index (p_arg_nm, p_dyn_field)));
00398 break;
00399
00400 default:
00401 panic_impossible ();
00402 }
00403
00404 if (error_state)
00405 break;
00406
00407 p_args++;
00408 p_arg_nm++;
00409 p_dyn_field++;
00410 }
00411
00412 if (! error_state)
00413 retval = tmp.subsref (type.substr (tmpi, n - tmpi), idx, nargout,
00414 lvalue_list);
00415 }
00416
00417 return retval;
00418 }
00419
00420 octave_value
00421 tree_index_expression::rvalue1 (int nargout)
00422 {
00423 octave_value retval;
00424
00425 const octave_value_list tmp = rvalue (nargout);
00426
00427 if (! tmp.empty ())
00428 retval = tmp(0);
00429
00430 return retval;
00431 }
00432
00433 octave_lvalue
00434 tree_index_expression::lvalue (void)
00435 {
00436 octave_lvalue retval;
00437
00438 std::list<octave_value_list> idx;
00439 std::string tmp_type;
00440
00441 int n = args.size ();
00442
00443 std::list<tree_argument_list *>::iterator p_args = args.begin ();
00444 std::list<string_vector>::iterator p_arg_nm = arg_nm.begin ();
00445 std::list<tree_expression *>::iterator p_dyn_field = dyn_field.begin ();
00446
00447 retval = expr->lvalue ();
00448
00449 if (! error_state)
00450 {
00451 const octave_value *tro = retval.object ();
00452
00453 octave_value tmp;
00454
00455 if (tro)
00456 tmp = *tro;
00457
00458 octave_idx_type tmpi = 0;
00459 std::list<octave_value_list> tmpidx;
00460
00461 for (int i = 0; i < n; i++)
00462 {
00463 if (retval.numel () != 1)
00464 gripe_indexed_cs_list ();
00465 else if (tmpi < i)
00466 {
00467 tmp = tmp.subsref (type.substr (tmpi, i - tmpi), tmpidx, true);
00468 tmpidx.clear ();
00469 }
00470
00471 if (error_state)
00472 break;
00473
00474 switch (type[i])
00475 {
00476 case '(':
00477 {
00478 octave_value_list tidx
00479 = make_value_list (*p_args, *p_arg_nm, &tmp, false);
00480
00481 idx.push_back (tidx);
00482
00483 if (i < n - 1)
00484 {
00485 if (type[i+1] == '.')
00486 {
00487 tmpidx.push_back (tidx);
00488 tmpi = i+1;
00489 }
00490 else
00491 error ("() must be followed by . or close the index chain");
00492 }
00493 }
00494 break;
00495
00496 case '{':
00497 {
00498 octave_value_list tidx
00499 = make_value_list (*p_args, *p_arg_nm, &tmp, false);
00500
00501 if (tmp.is_undefined ())
00502 {
00503 if (tidx.has_magic_colon ())
00504 gripe_invalid_inquiry_subscript ();
00505 else
00506 tmp = Cell ();
00507 }
00508 else if (tmp.is_zero_by_zero ()
00509 && (tmp.is_matrix_type () || tmp.is_string ()))
00510 {
00511 tmp = Cell ();
00512 }
00513
00514 retval.numel (tmp.numel (tidx));
00515
00516 if (error_state)
00517 break;
00518
00519 idx.push_back (tidx);
00520 tmpidx.push_back (tidx);
00521 tmpi = i;
00522 }
00523 break;
00524
00525 case '.':
00526 {
00527 octave_value tidx = get_struct_index (p_arg_nm, p_dyn_field);
00528 if (error_state)
00529 break;
00530
00531 bool autoconv = (tmp.is_zero_by_zero ()
00532 && (tmp.is_matrix_type () || tmp.is_string ()
00533 || tmp.is_cell ()));
00534
00535 if (i > 0 && type [i-1] == '(')
00536 {
00537 octave_value_list pidx = idx.back ();
00538
00539
00540
00541 if (tmp.is_undefined ())
00542 {
00543 if (pidx.has_magic_colon ())
00544 gripe_invalid_inquiry_subscript ();
00545 else
00546 tmp = octave_map ();
00547 }
00548 else if (autoconv)
00549 tmp = octave_map ();
00550
00551 retval.numel (tmp.numel (pidx));
00552
00553 tmpi = i-1;
00554 tmpidx.push_back (tidx);
00555 }
00556 else
00557 {
00558 if (tmp.is_undefined () || autoconv)
00559 {
00560 tmpi = i+1;
00561 tmp = octave_value ();
00562 }
00563 else
00564 {
00565 retval.numel (tmp.numel (octave_value_list ()));
00566
00567 tmpi = i;
00568 tmpidx.push_back (tidx);
00569 }
00570 }
00571
00572 if (error_state)
00573 break;
00574
00575 idx.push_back (tidx);
00576 }
00577 break;
00578
00579 default:
00580 panic_impossible ();
00581 }
00582
00583 if (idx.back ().empty ())
00584 error ("invalid empty index list");
00585
00586 if (error_state)
00587 break;
00588
00589 p_args++;
00590 p_arg_nm++;
00591 p_dyn_field++;
00592 }
00593
00594 if (! error_state)
00595 retval.set_index (type, idx);
00596
00597 }
00598
00599 return retval;
00600 }
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639 tree_index_expression *
00640 tree_index_expression::dup (symbol_table::scope_id scope,
00641 symbol_table::context_id context) const
00642 {
00643 tree_index_expression *new_idx_expr
00644 = new tree_index_expression (line (), column ());
00645
00646 new_idx_expr->expr = expr ? expr->dup (scope, context) : 0;
00647
00648 std::list<tree_argument_list *> new_args;
00649
00650 for (std::list<tree_argument_list *>::const_iterator p = args.begin ();
00651 p != args.end ();
00652 p++)
00653 {
00654 const tree_argument_list *elt = *p;
00655
00656 new_args.push_back (elt ? elt->dup (scope, context) : 0);
00657 }
00658
00659 new_idx_expr->args = new_args;
00660
00661 new_idx_expr->type = type;
00662
00663 new_idx_expr->arg_nm = arg_nm;
00664
00665 std::list<tree_expression *> new_dyn_field;
00666
00667 for (std::list<tree_expression *>::const_iterator p = dyn_field.begin ();
00668 p != dyn_field.end ();
00669 p++)
00670 {
00671 const tree_expression *elt = *p;
00672
00673 new_dyn_field.push_back (elt ? elt->dup (scope, context) : 0);
00674 }
00675
00676 new_idx_expr->dyn_field = new_dyn_field;
00677
00678 new_idx_expr->copy_base (*this);
00679
00680 return new_idx_expr;
00681 }
00682
00683 void
00684 tree_index_expression::accept (tree_walker& tw)
00685 {
00686 tw.visit_index_expression (*this);
00687 }