pt-arg-list.cc

Go to the documentation of this file.
00001 /*
00002 
00003 Copyright (C) 1996-2012 John W. Eaton
00004 
00005 This file is part of Octave.
00006 
00007 Octave is free software; you can redistribute it and/or modify it
00008 under the terms of the GNU General Public License as published by the
00009 Free Software Foundation; either version 3 of the License, or (at your
00010 option) any later version.
00011 
00012 Octave is distributed in the hope that it will be useful, but WITHOUT
00013 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00015 for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with Octave; see the file COPYING.  If not, see
00019 <http://www.gnu.org/licenses/>.
00020 
00021 */
00022 
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026 
00027 #include <iostream>
00028 #include <string>
00029 
00030 #include "str-vec.h"
00031 
00032 #include "defun.h"
00033 #include "error.h"
00034 #include "oct-lvalue.h"
00035 #include "oct-obj.h"
00036 #include "ov.h"
00037 #include "ov-usr-fcn.h"
00038 #include "parse.h"
00039 #include "pt-arg-list.h"
00040 #include "pt-exp.h"
00041 #include "pt-id.h"
00042 #include "pt-pr-code.h"
00043 #include "pt-walk.h"
00044 #include "toplev.h"
00045 #include "unwind-prot.h"
00046 
00047 // Argument lists.
00048 
00049 tree_argument_list::~tree_argument_list (void)
00050 {
00051   while (! empty ())
00052     {
00053       iterator p = begin ();
00054       delete *p;
00055       erase (p);
00056     }
00057 }
00058 
00059 bool
00060 tree_argument_list::has_magic_end (void) const
00061 {
00062   for (const_iterator p = begin (); p != end (); p++)
00063     {
00064       tree_expression *elt = *p;
00065 
00066       if (elt && elt->has_magic_end ())
00067         return true;
00068     }
00069 
00070   return false;
00071 }
00072 
00073 void
00074 tree_argument_list::append (const element_type& s)
00075 {
00076   octave_base_list<tree_expression *>::append (s);
00077 
00078   if (! list_includes_magic_end && s && s->has_magic_end ())
00079     list_includes_magic_end = true;
00080 
00081   if (! list_includes_magic_tilde && s && s->is_identifier ())
00082     {
00083       tree_identifier *id = dynamic_cast<tree_identifier *> (s);
00084       list_includes_magic_tilde = id && id->is_black_hole ();
00085     }
00086 }
00087 
00088 bool
00089 tree_argument_list::all_elements_are_constant (void) const
00090 {
00091   for (const_iterator p = begin (); p != end (); p++)
00092     {
00093       tree_expression *elt = *p;
00094 
00095       if (! elt->is_constant ())
00096         return false;
00097     }
00098 
00099   return true;
00100 }
00101 
00102 static const octave_value *indexed_object = 0;
00103 static int index_position = 0;
00104 static int num_indices = 0;
00105 
00106 DEFCONSTFUN (__end__, , ,
00107   "internal function")
00108 {
00109   octave_value retval;
00110 
00111   if (indexed_object)
00112     {
00113       if (indexed_object->is_object ())
00114         {
00115           octave_value_list args;
00116 
00117           args(2) = num_indices;
00118           args(1) = index_position + 1;
00119           args(0) = *indexed_object;
00120 
00121           std::string class_name = indexed_object->class_name ();
00122 
00123           octave_value meth = symbol_table::find_method ("end", class_name);
00124 
00125           if (meth.is_defined ())
00126             return feval (meth.function_value (), args, 1);
00127         }
00128 
00129       dim_vector dv = indexed_object->dims ();
00130       int ndims = dv.length ();
00131 
00132       if (num_indices < ndims)
00133         {
00134           for (int i = num_indices; i < ndims; i++)
00135             dv(num_indices-1) *= dv(i);
00136 
00137           if (num_indices == 1)
00138             {
00139               ndims = 2;
00140               dv.resize (ndims);
00141               dv(1) = 1;
00142             }
00143           else
00144             {
00145               ndims = num_indices;
00146               dv.resize (ndims);
00147             }
00148         }
00149 
00150       if (index_position < ndims)
00151         retval = dv(index_position);
00152       else
00153         retval = 1;
00154     }
00155   else
00156     ::error ("invalid use of end");
00157 
00158   return retval;
00159 }
00160 
00161 octave_value_list
00162 tree_argument_list::convert_to_const_vector (const octave_value *object)
00163 {
00164   // END doesn't make sense for functions.  Maybe we need a different
00165   // way of asking an octave_value object this question?
00166 
00167   bool stash_object = (list_includes_magic_end
00168                        && object
00169                        && ! (object->is_function ()
00170                              || object->is_function_handle ()));
00171 
00172   unwind_protect frame;
00173 
00174   if (stash_object)
00175     {
00176       frame.protect_var (indexed_object);
00177 
00178       indexed_object = object;
00179     }
00180 
00181   int len = length ();
00182 
00183   std::list<octave_value_list> args;
00184 
00185   iterator p = begin ();
00186   for (int k = 0; k < len; k++)
00187     {
00188       if (stash_object)
00189         {
00190           frame.protect_var (index_position);
00191           frame.protect_var (num_indices);
00192 
00193           index_position = k;
00194           num_indices = len;
00195         }
00196 
00197       tree_expression *elt = *p++;
00198 
00199       if (elt)
00200         {
00201           octave_value tmp = elt->rvalue1 ();
00202 
00203           if (error_state)
00204             {
00205               ::error ("evaluating argument list element number %d", k+1);
00206               args.clear ();
00207               break;
00208             }
00209           else
00210             {
00211               if (tmp.is_cs_list ())
00212                 args.push_back (tmp.list_value ());
00213               else if (tmp.is_defined ())
00214                 args.push_back (tmp);
00215             }
00216         }
00217       else
00218         {
00219           args.push_back (octave_value ());
00220           break;
00221         }
00222     }
00223 
00224   return args;
00225 }
00226 
00227 std::list<octave_lvalue>
00228 tree_argument_list::lvalue_list (void)
00229 {
00230   std::list<octave_lvalue> retval;
00231 
00232   for (tree_argument_list::iterator p = begin ();
00233        p != end ();
00234        p++)
00235     {
00236       tree_expression *elt = *p;
00237 
00238       retval.push_back (elt->lvalue ());
00239     }
00240 
00241   return retval;
00242 }
00243 
00244 string_vector
00245 tree_argument_list::get_arg_names (void) const
00246 {
00247   int len = length ();
00248 
00249   string_vector retval (len);
00250 
00251   int k = 0;
00252 
00253   for (const_iterator p = begin (); p != end (); p++)
00254     {
00255       tree_expression *elt = *p;
00256 
00257       retval(k++) = elt->str_print_code ();
00258     }
00259 
00260   return retval;
00261 }
00262 
00263 tree_argument_list *
00264 tree_argument_list::dup (symbol_table::scope_id scope,
00265                          symbol_table::context_id context) const
00266 {
00267   tree_argument_list *new_list = new tree_argument_list ();
00268 
00269   new_list->list_includes_magic_end = list_includes_magic_end;
00270   new_list->simple_assign_lhs = simple_assign_lhs;
00271 
00272   for (const_iterator p = begin (); p != end (); p++)
00273     {
00274       const tree_expression *elt = *p;
00275 
00276       new_list->append (elt ? elt->dup (scope, context) : 0);
00277     }
00278 
00279   return new_list;
00280 }
00281 
00282 void
00283 tree_argument_list::accept (tree_walker& tw)
00284 {
00285   tw.visit_argument_list (*this);
00286 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines