Mercurial > octave
diff src/ov-base.cc @ 5759:ce79d238f142
[project @ 2006-04-13 13:04:32 by jwe]
author | jwe |
---|---|
date | Thu, 13 Apr 2006 13:04:33 +0000 |
parents | c7d5a534afa5 |
children | ace8d8d26933 |
line wrap: on
line diff
--- a/src/ov-base.cc Wed Apr 12 19:23:26 2006 +0000 +++ b/src/ov-base.cc Thu Apr 13 13:04:33 2006 +0000 @@ -29,10 +29,12 @@ #include <iostream> +#include "Array-flags.h" #include "lo-ieee.h" #include "lo-mappers.h" #include "so-array.h" +#include "defun.h" #include "gripes.h" #include "oct-map.h" #include "oct-obj.h" @@ -50,11 +52,28 @@ #include "ov-scalar.h" #include "ov-str-mat.h" #include "ov-fcn-handle.h" +#include "parse.h" +#include "utils.h" #include "variables.h" DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_base_value, "<unknown type>", "unknown"); +// If TRUE, print the name along with the value. +static bool Vprint_answer_id_name; + +// If TRUE, turn off printing of results in functions (as if a +// semicolon has been appended to each statement). +static bool Vsilent_functions; + +// Should we print a warning when converting `[97, 98, 99, "123"]' +// to a character string? +bool Vwarn_num_to_str; + +// If TRUE, print a warning when a matrix is resized by an indexed +// assignment with indices outside the current bounds. +bool Vwarn_resize_on_range_error; + octave_value octave_base_value::squeeze (void) const { @@ -89,6 +108,12 @@ return octave_value (); } +octave_value +octave_base_value::do_index_op (const octave_value_list& idx) +{ + return do_index_op (idx, 0); +} + octave_value_list octave_base_value::do_multi_index_op (int, const octave_value_list&) { @@ -105,6 +130,31 @@ return idx_vector (); } +int +octave_base_value::ndims (void) const +{ + dim_vector dv = dims (); + + int n_dims = dv.length (); + + // Remove trailing singleton dimensions. + + for (int i = n_dims; i > 2; i--) + { + if (dv(i-1) == 1) + n_dims--; + else + break; + } + + // The result is always >= 2. + + if (n_dims < 2) + n_dims = 2; + + return n_dims; +} + octave_value octave_base_value::subsasgn (const std::string& type, const std::list<octave_value_list>& idx, @@ -209,6 +259,29 @@ } octave_value +octave_base_value::all (int) const +{ + return 0.0; +} + +octave_value +octave_base_value::any (int) const +{ + return 0.0; +} + +octave_value +octave_base_value::convert_to_str (bool pad, bool force, char type) const +{ + octave_value retval = convert_to_str_internal (pad, force, type); + + if (! force && is_numeric_type () && Vwarn_num_to_str) + gripe_implicit_conversion (type_name (), retval.type_name ()); + + return retval; +} + +octave_value octave_base_value::convert_to_str_internal (bool, bool, char) const { gripe_wrong_type_arg ("octave_base_value::convert_to_str_internal ()", @@ -257,6 +330,25 @@ } void +octave_base_value::print_with_name (std::ostream& output_buf, + const std::string& name, + bool print_padding) const +{ + if (! (evaluating_function_body && Vsilent_functions)) + { + bool pad_after = false; + + if (Vprint_answer_id_name) + pad_after = print_name_tag (output_buf, name); + + print (output_buf); + + if (print_padding && pad_after) + newline (output_buf); + } +} + +void octave_base_value::print_info (std::ostream& os, const std::string& /* prefix */) const { @@ -773,6 +865,193 @@ return false; } +static void +gripe_indexed_assignment (const std::string& tn1, const std::string& tn2) +{ + error ("assignment of `%s' to indexed `%s' not implemented", + tn2.c_str (), tn1.c_str ()); +} + +static void +gripe_assign_conversion_failed (const std::string& tn1, + const std::string& tn2) +{ + error ("type conversion for assignment of `%s' to indexed `%s' failed", + tn2.c_str (), tn1.c_str ()); +} + +static void +gripe_no_conversion (const std::string& on, const std::string& tn1, + const std::string& tn2) +{ + error ("operator %s: no conversion for assignment of `%s' to indexed `%s'", + on.c_str (), tn2.c_str (), tn1.c_str ()); +} + +octave_value +octave_base_value::numeric_assign (const std::string& type, + const std::list<octave_value_list>& idx, + const octave_value& rhs) +{ + octave_value retval; + + int t_lhs = type_id (); + int t_rhs = rhs.type_id (); + + octave_value_typeinfo::assign_op_fcn f + = octave_value_typeinfo::lookup_assign_op (octave_value::op_asn_eq, + t_lhs, t_rhs); + + bool done = false; + + if (f) + { + f (*this, idx.front (), rhs.get_rep ()); + + done = (! error_state); + } + + if (done) + { + count++; + retval = octave_value (this); + } + else + { + int t_result + = octave_value_typeinfo::lookup_pref_assign_conv (t_lhs, t_rhs); + + if (t_result >= 0) + { + octave_base_value::type_conv_fcn cf + = octave_value_typeinfo::lookup_widening_op (t_lhs, t_result); + + if (cf) + { + octave_base_value *tmp (cf (*this)); + + if (tmp) + { + retval = tmp->subsasgn (type, idx, rhs); + + done = (! error_state); + } + else + gripe_assign_conversion_failed (type_name (), + rhs.type_name ()); + } + else + gripe_indexed_assignment (type_name (), rhs.type_name ()); + } + + if (! (done || error_state)) + { + octave_value tmp_rhs; + + octave_base_value::type_conv_fcn cf_rhs + = rhs.numeric_conversion_function (); + + if (cf_rhs) + { + octave_base_value *tmp = cf_rhs (rhs.get_rep ()); + + if (tmp) + tmp_rhs = octave_value (tmp); + else + { + gripe_assign_conversion_failed (type_name (), + rhs.type_name ()); + return octave_value (); + } + } + else + tmp_rhs = rhs; + + octave_base_value::type_conv_fcn cf_this + = numeric_conversion_function (); + + octave_base_value *tmp_lhs = this; + + if (cf_this) + { + octave_base_value *tmp = cf_this (*this); + + if (tmp) + tmp_lhs = tmp; + else + { + gripe_assign_conversion_failed (type_name (), + rhs.type_name ()); + return octave_value (); + } + } + + if (cf_this || cf_rhs) + { + retval = tmp_lhs->subsasgn (type, idx, tmp_rhs); + + done = (! error_state); + } + else + gripe_no_conversion (octave_value::assign_op_as_string (octave_value::op_asn_eq), + type_name (), rhs.type_name ()); + } + } + + // The assignment may have converted to a type that is wider than + // necessary. + + retval.maybe_mutate (); + + return retval; +} + +// Current indentation. +int octave_base_value::curr_print_indent_level = 0; + +// TRUE means we are at the beginning of a line. +bool octave_base_value::beginning_of_line = true; + +// Each print() function should call this before printing anything. +// +// This doesn't need to be fast, but isn't there a better way? + +void +octave_base_value::indent (std::ostream& os) const +{ + assert (curr_print_indent_level >= 0); + + if (beginning_of_line) + { + // XXX FIXME XXX -- do we need this? + // os << prefix; + + for (int i = 0; i < curr_print_indent_level; i++) + os << " "; + + beginning_of_line = false; + } +} + +// All print() functions should use this to print new lines. + +void +octave_base_value::newline (std::ostream& os) const +{ + os << "\n"; + + beginning_of_line = true; +} + +// For ressetting print state. + +void +octave_base_value::reset (void) const +{ + beginning_of_line = true; + curr_print_indent_level = 0; +} + CONVDECLX (matrix_conv) { return new octave_matrix (); @@ -810,6 +1089,100 @@ INSTALL_WIDENOP (octave_base_value, octave_cell, cell_conv); } +static int +print_answer_id_name (void) +{ + Vprint_answer_id_name = check_preference ("print_answer_id_name"); + + return 0; +} + +static int +silent_functions (void) +{ + Vsilent_functions = check_preference ("silent_functions"); + + return 0; +} + +static int +warn_num_to_str (void) +{ + Vwarn_num_to_str = check_preference ("warn_num_to_str"); + + return 0; +} + +static int +warn_resize_on_range_error (void) +{ + Vwarn_resize_on_range_error + = check_preference ("warn_resize_on_range_error"); + + liboctave_wrore_flag = Vwarn_resize_on_range_error; + + return 0; +} + +void +symbols_of_ov_base (void) +{ + DEFVAR (print_answer_id_name, true, print_answer_id_name, + "-*- texinfo -*-\n\ +@defvr {Built-in Variable} print_answer_id_name\n\ +If the value of @code{print_answer_id_name} is nonzero, variable\n\ +names are printed along with the result. Otherwise, only the result\n\ +values are printed. The default value is 1.\n\ +@end defvr"); + + DEFVAR (silent_functions, false, silent_functions, + "-*- texinfo -*-\n\ +@defvr {Built-in Variable} silent_functions\n\ +If the value of @code{silent_functions} is nonzero, internal output\n\ +from a function is suppressed. Otherwise, the results of expressions\n\ +within a function body that are not terminated with a semicolon will\n\ +have their values printed. The default value is 0.\n\ +\n\ +For example, if the function\n\ +\n\ +@example\n\ +function f ()\n\ + 2 + 2\n\ +endfunction\n\ +@end example\n\ +\n\ +@noindent\n\ +is executed, Octave will either print @samp{ans = 4} or nothing\n\ +depending on the value of @code{silent_functions}.\n\ +@end defvr"); + + DEFVAR (warn_num_to_str, true, warn_num_to_str, + "-*- texinfo -*-\n\ +@defvr {Built-in Variable} warn_num_to_str\n\ +If the value of @code{warn_num_to_str} is nonzero, a warning is\n\ +printed for implicit conversions of numbers to their ASCII character\n\ +equivalents when strings are constructed using a mixture of strings and\n\ +numbers in matrix notation. For example,\n\ +\n\ +@example\n\ +@group\n\ +[ \"f\", 111, 111 ]\n\ + @result{} \"foo\"\n\ +@end group\n\ +@end example\n\ +elicits a warning if @code{warn_num_to_str} is nonzero. The default\n\ +value is 1.\n\ +@end defvr"); + + DEFVAR (warn_resize_on_range_error, false, warn_resize_on_range_error, + "-*- texinfo -*-\n\ +@defvr {Built-in Variable} warn_resize_on_range_error\n\ +If the value of @code{warn_resize_on_range_error} is nonzero, print a\n\ +warning when a matrix is resized by an indexed assignment with\n\ +indices outside the current bounds. The default value is 0.\n\ +@end defvr"); +} + /* ;;; Local Variables: *** ;;; mode: C++ ***