pt-colon.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 "error.h"
00028 #include "oct-obj.h"
00029 #include "pager.h"
00030 #include "ov.h"
00031 #include "pt-bp.h"
00032 #include "pt-colon.h"
00033 #include "pt-walk.h"
00034 
00035 // Colon expressions.
00036 
00037 tree_colon_expression *
00038 tree_colon_expression::append (tree_expression *t)
00039 {
00040   tree_colon_expression *retval = 0;
00041 
00042   if (op_base)
00043     {
00044       if (op_limit)
00045         {
00046           if (op_increment)
00047             ::error ("invalid colon expression");
00048           else
00049             {
00050               // Stupid syntax:
00051               //
00052               // base : limit
00053               // base : increment : limit
00054 
00055               op_increment = op_limit;
00056               op_limit = t;
00057             }
00058         }
00059       else
00060         op_limit = t;
00061 
00062       retval = this;
00063     }
00064   else
00065     ::error ("invalid colon expression");
00066 
00067   return retval;
00068 }
00069 
00070 octave_value_list
00071 tree_colon_expression::rvalue (int nargout)
00072 {
00073   octave_value_list retval;
00074 
00075   if (nargout > 1)
00076     error ("invalid number of output arguments for colon expression");
00077   else
00078     retval = rvalue1 (nargout);
00079 
00080   return retval;
00081 }
00082 
00083 octave_value
00084 tree_colon_expression::make_range (const Matrix& m_base,
00085                                    const Matrix& m_limit,
00086                                    const Matrix& m_increment,
00087                                    bool result_is_str, bool dq_str) const
00088 {
00089   octave_value retval;
00090 
00091   bool base_empty = m_base.is_empty ();
00092   bool limit_empty = m_limit.is_empty ();
00093   bool increment_empty = m_increment.is_empty ();
00094 
00095   if (base_empty || limit_empty || increment_empty)
00096     retval = Range ();
00097   else
00098     {
00099       retval = Range (m_base(0), m_limit(0), m_increment(0));
00100 
00101       if (result_is_str)
00102         retval = retval.convert_to_str (false, true, dq_str ? '"' : '\'');
00103     }
00104 
00105   return retval;
00106 }
00107 
00108 octave_value
00109 tree_colon_expression::make_range (const octave_value& ov_base,
00110                                    const octave_value& ov_limit,
00111                                    const octave_value& ov_increment) const
00112 {
00113   octave_value retval;
00114 
00115   if (ov_base.is_object () || ov_limit.is_object () ||
00116       ov_increment.is_object ())
00117     {
00118       octave_value_list tmp1;
00119       tmp1(2) = ov_limit;
00120       tmp1(1) = ov_increment;
00121       tmp1(0) = ov_base;
00122 
00123       octave_value fcn = symbol_table::find_function ("colon", tmp1);
00124 
00125       if (fcn.is_defined ())
00126         {
00127           octave_value_list tmp2 = fcn.do_multi_index_op (1, tmp1);
00128 
00129           if (! error_state)
00130             retval = tmp2 (0);
00131         }
00132       else
00133         ::error ("can not find overloaded colon function");
00134     }
00135   else
00136     {
00137       bool result_is_str = (ov_base.is_string () && ov_limit.is_string ());
00138       bool dq_str = (ov_base.is_dq_string () || ov_limit.is_dq_string ());
00139 
00140       Matrix m_base = ov_base.matrix_value (true);
00141 
00142       if (error_state)
00143         eval_error ("invalid base value in colon expression");
00144       else
00145         {
00146           Matrix m_limit = ov_limit.matrix_value (true);
00147 
00148           if (error_state)
00149             eval_error ("invalid limit value in colon expression");
00150           else
00151             {
00152               Matrix m_increment = ov_increment.matrix_value (true);
00153 
00154               if (error_state)
00155                 eval_error ("invalid increment value in colon expression");
00156               else
00157                 retval = make_range (m_base, m_limit, m_increment,
00158                                      result_is_str, dq_str);
00159             }
00160         }
00161     }
00162 
00163   return retval;
00164 }
00165 
00166 octave_value
00167 tree_colon_expression::rvalue1 (int)
00168 {
00169   octave_value retval;
00170 
00171   if (error_state || ! op_base || ! op_limit)
00172     return retval;
00173 
00174   octave_value ov_base = op_base->rvalue1 ();
00175 
00176   if (error_state || ov_base.is_undefined ())
00177     eval_error ("invalid base value in colon expression");
00178   else
00179     {
00180       octave_value ov_limit = op_limit->rvalue1 ();
00181 
00182       if (error_state || ov_limit.is_undefined ())
00183         eval_error ("invalid limit value in colon expression");
00184       else if (ov_base.is_object () || ov_limit.is_object ())
00185         {
00186           octave_value_list tmp1;
00187 
00188           if (op_increment)
00189             {
00190               octave_value ov_increment = op_increment->rvalue1 ();
00191 
00192               if (error_state || ov_increment.is_undefined ())
00193                 eval_error ("invalid increment value in colon expression");
00194               else
00195                 {
00196                   tmp1(2) = ov_limit;
00197                   tmp1(1) = ov_increment;
00198                   tmp1(0) = ov_base;
00199                 }
00200             }
00201           else
00202             {
00203               tmp1(1) = ov_limit;
00204               tmp1(0) = ov_base;
00205             }
00206 
00207           if (!error_state)
00208             {
00209               octave_value fcn = symbol_table::find_function ("colon", tmp1);
00210 
00211               if (fcn.is_defined ())
00212                 {
00213                   octave_value_list tmp2 = fcn.do_multi_index_op (1, tmp1);
00214 
00215                   if (! error_state)
00216                     retval = tmp2 (0);
00217                 }
00218               else
00219                 ::error ("can not find overloaded colon function");
00220             }
00221         }
00222       else
00223         {
00224           octave_value ov_increment = 1.0;
00225 
00226           if (op_increment)
00227             {
00228               ov_increment = op_increment->rvalue1 ();
00229 
00230               if (error_state || ov_increment.is_undefined ())
00231                 eval_error ("invalid increment value in colon expression");
00232             }
00233 
00234           if (! error_state)
00235             retval = make_range (ov_base, ov_limit, ov_increment);
00236         }
00237     }
00238 
00239   return retval;
00240 }
00241 
00242 void
00243 tree_colon_expression::eval_error (const std::string& s) const
00244 {
00245   ::error ("%s", s.c_str ());
00246 }
00247 
00248 int
00249 tree_colon_expression::line (void) const
00250 {
00251   return (op_base ? op_base->line ()
00252           : (op_increment ? op_increment->line ()
00253              : (op_limit ? op_limit->line ()
00254                 : -1)));
00255 }
00256 
00257 int
00258 tree_colon_expression::column (void) const
00259 {
00260   return (op_base ? op_base->column ()
00261           : (op_increment ? op_increment->column ()
00262              : (op_limit ? op_limit->column ()
00263                 : -1)));
00264 }
00265 
00266 tree_expression *
00267 tree_colon_expression::dup (symbol_table::scope_id scope,
00268                             symbol_table::context_id context) const
00269 {
00270   tree_colon_expression *new_ce = new
00271     tree_colon_expression (op_base ? op_base->dup (scope, context) : 0,
00272                            op_limit ? op_limit->dup (scope, context) : 0,
00273                            op_increment ? op_increment->dup (scope, context) : 0,
00274                            line (), column ());
00275 
00276   new_ce->copy_base (*new_ce);
00277 
00278   return new_ce;
00279 }
00280 
00281 void
00282 tree_colon_expression::accept (tree_walker& tw)
00283 {
00284   tw.visit_colon_expression (*this);
00285 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines