Mercurial > octave
view libinterp/octave-value/ov-typeinfo.cc @ 27918:b442ec6dda5c
use centralized file for copyright info for individual contributors
* COPYRIGHT.md: New file.
* In most other files, use "Copyright (C) YYYY-YYYY The Octave Project
Developers" instead of tracking individual names in separate source
files. The motivation is to reduce the effort required to update the
notices each year.
Until now, the Octave source files contained copyright notices that
list individual contributors. I adopted these file-scope copyright
notices because that is what everyone was doing 30 years ago in the
days before distributed version control systems. But now, with many
contributors and modern version control systems, having these
file-scope copyright notices causes trouble when we update copyright
years or refactor code.
Over time, the file-scope copyright notices may become outdated as new
contributions are made or code is moved from one file to
another. Sometimes people contribute significant patches but do not
add a line claiming copyright. Other times, people add a copyright
notice for their contribution but then a later refactoring moves part
or all of their contribution to another file and the notice is not
moved with the code. As a practical matter, moving such notices is
difficult -- determining what parts are due to a particular
contributor requires a time-consuming search through the project
history. Even managing the yearly update of copyright years is
problematic. We have some contributors who are no longer
living. Should we update the copyright dates for their contributions
when we release new versions? Probably not, but we do still want to
claim copyright for the project as a whole.
To minimize the difficulty of maintaining the copyright notices, I
would like to change Octave's sources to use what is described here:
https://softwarefreedom.org/resources/2012/ManagingCopyrightInformation.html
in the section "Maintaining centralized copyright notices":
The centralized notice approach consolidates all copyright
notices in a single location, usually a top-level file.
This file should contain all of the copyright notices
provided project contributors, unless the contribution was
clearly insignificant. It may also credit -- without a copyright
notice -- anyone who helped with the project but did not
contribute code or other copyrighted material.
This approach captures less information about contributions
within individual files, recognizing that the DVCS is better
equipped to record those details. As we mentioned before, it
does have one disadvantage as compared to the file-scope
approach: if a single file is separated from the distribution,
the recipient won't see the contributors' copyright notices.
But this can be easily remedied by including a single
copyright notice in each file's header, pointing to the
top-level file:
Copyright YYYY-YYYY The Octave Project Developers
See the COPYRIGHT file at the top-level directory
of this distribution or at https://octave.org/COPYRIGHT.html.
followed by the usual GPL copyright statement.
For more background, see the discussion here:
https://lists.gnu.org/archive/html/octave-maintainers/2020-01/msg00009.html
Most files in the following directories have been skipped intentinally
in this changeset:
doc
libgui/qterminal
liboctave/external
m4
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Mon, 06 Jan 2020 15:38:17 -0500 |
parents | 097774bed4ed |
children | 1891570abac8 |
line wrap: on
line source
/* Copyright (C) 1996-2019 The Octave Project Developers See the file COPYRIGHT.md in the top-level directory of this distribution or <https://octave.org/COPYRIGHT.html/>. This file is part of Octave. Octave is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Octave is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Octave; see the file COPYING. If not, see <https://www.gnu.org/licenses/>. */ #if defined (HAVE_CONFIG_H) # include "config.h" #endif #include <iostream> #include "Array.h" #include "defun.h" #include "error.h" #include "interpreter.h" #include "interpreter-private.h" #include "ops.h" #include "ov-typeinfo.h" #include "ov.h" namespace octave { // FIXME: we should also store all class names and provide a // way to list them (calling class with nargin == 0?). static NDArray as_nd_array (const Array<int>& x) { NDArray retval (x.dims ()); for (int i = 0; i < x.numel (); i++) retval.xelem(i) = x(i); return retval; } static boolNDArray as_bool_nd_array (const Array<void *>& x) { boolNDArray retval (x.dims ()); for (octave_idx_type i = 0; i < x.numel (); i++) retval.xelem (i) = x(i); return retval; } type_info::type_info (int init_tab_sz) : num_types (0), types (dim_vector (init_tab_sz, 1), ""), vals (dim_vector (init_tab_sz, 1)), unary_class_ops (dim_vector (octave_value::num_unary_ops, 1), nullptr), unary_ops (dim_vector (octave_value::num_unary_ops, init_tab_sz), nullptr), non_const_unary_ops (dim_vector (octave_value::num_unary_ops, init_tab_sz), nullptr), binary_class_ops (dim_vector (octave_value::num_binary_ops, 1), nullptr), binary_ops (dim_vector (octave_value::num_binary_ops, init_tab_sz, init_tab_sz), nullptr), compound_binary_class_ops (dim_vector (octave_value::num_compound_binary_ops, 1), nullptr), compound_binary_ops (dim_vector (octave_value::num_compound_binary_ops, init_tab_sz, init_tab_sz), nullptr), cat_ops (dim_vector (init_tab_sz, init_tab_sz), nullptr), assign_ops (dim_vector (octave_value::num_assign_ops, init_tab_sz, init_tab_sz), nullptr), assignany_ops (dim_vector (octave_value::num_assign_ops, init_tab_sz), nullptr), pref_assign_conv (dim_vector (init_tab_sz, init_tab_sz), -1), widening_ops (dim_vector (init_tab_sz, init_tab_sz), nullptr) { install_types (*this); install_ops (*this); } int type_info::register_type (const std::string& t_name, const std::string& /* c_name */, const octave_value& val, bool abort_on_duplicate) { int i = 0; for (i = 0; i < num_types; i++) { if (t_name == types (i)) { if (abort_on_duplicate) { std::cerr << "duplicate type " << t_name << std::endl; abort (); } warning ("duplicate type %s\n", t_name.c_str ()); return i; } } int len = types.numel (); if (i == len) { len *= 2; types.resize (dim_vector (len, 1), ""); vals.resize (dim_vector (len, 1), nullptr); unary_ops.resize (dim_vector (octave_value::num_unary_ops, len), nullptr); non_const_unary_ops.resize (dim_vector (octave_value::num_unary_ops, len), nullptr); binary_ops.resize (dim_vector (octave_value::num_binary_ops, len, len), nullptr); compound_binary_ops.resize (dim_vector (octave_value::num_compound_binary_ops, len, len), nullptr); cat_ops.resize (dim_vector (len, len), nullptr); assign_ops.resize (dim_vector (octave_value::num_assign_ops, len, len), nullptr); assignany_ops.resize (dim_vector (octave_value::num_assign_ops, len), nullptr); pref_assign_conv.resize (dim_vector (len, len), -1); widening_ops.resize (dim_vector (len, len), nullptr); } types (i) = t_name; // Yes, this object is intentionally not deleted in the destructor // so that we avoid a crash on exit for user-defined data types. // See bug #53156. If that problem is properly fixed, then this // could be stored as an object instead of a pointer to an object // allocated with new. vals(i) = new octave_value (val); num_types++; return i; } bool type_info::register_unary_class_op (octave_value::unary_op op, type_info::unary_class_op_fcn f, bool abort_on_duplicate) { if (lookup_unary_class_op (op)) { std::string op_name = octave_value::unary_op_as_string (op); if (abort_on_duplicate) { std::cerr << "duplicate unary operator '" << op_name << "' for class dispatch" << std::endl; abort (); } warning ("duplicate unary operator '%s' for class dispatch", op_name.c_str ()); } unary_class_ops.checkelem (static_cast<int> (op)) = reinterpret_cast<void *> (f); return false; } bool type_info::register_unary_op (octave_value::unary_op op, int t, unary_op_fcn f, bool abort_on_duplicate) { if (lookup_unary_op (op, t)) { std::string op_name = octave_value::unary_op_as_string (op); std::string type_name = types(t); if (abort_on_duplicate) { std::cerr << "duplicate unary operator '" << op_name << "' for type '" << type_name << "'" << std::endl; abort (); } warning ("duplicate unary operator '%s' for type '%s'", op_name.c_str (), type_name.c_str ()); } unary_ops.checkelem (static_cast<int> (op), t) = reinterpret_cast<void *> (f); return false; } bool type_info::register_non_const_unary_op (octave_value::unary_op op, int t, type_info::non_const_unary_op_fcn f, bool abort_on_duplicate) { if (lookup_non_const_unary_op (op, t)) { std::string op_name = octave_value::unary_op_as_string (op); std::string type_name = types(t); if (abort_on_duplicate) { std::cerr << "duplicate unary operator '" << op_name << "' for type '" << type_name << "'" << std::endl; abort (); } warning ("duplicate unary operator '%s' for type '%s'", op_name.c_str (), type_name.c_str ()); } non_const_unary_ops.checkelem (static_cast<int> (op), t) = reinterpret_cast<void *> (f); return false; } bool type_info::register_binary_class_op (octave_value::binary_op op, type_info::binary_class_op_fcn f, bool abort_on_duplicate) { if (lookup_binary_class_op (op)) { std::string op_name = octave_value::binary_op_as_string (op); if (abort_on_duplicate) { std::cerr << "duplicate binary operator '" << op_name << "' for class dispatch" << std::endl; abort (); } warning ("duplicate binary operator '%s' for class dispatch", op_name.c_str ()); } binary_class_ops.checkelem (static_cast<int> (op)) = reinterpret_cast<void *> (f); return false; } bool type_info::register_binary_op (octave_value::binary_op op, int t1, int t2, type_info::binary_op_fcn f, bool abort_on_duplicate) { if (lookup_binary_op (op, t1, t2)) { std::string op_name = octave_value::binary_op_as_string (op); std::string t1_name = types(t1); std::string t2_name = types(t2); if (abort_on_duplicate) { std::cerr << "duplicate binary operator '" << op_name << "' for types '" << t1_name << "' and '" << t2_name << "'" << std::endl; abort (); } warning ("duplicate binary operator '%s' for types '%s' and '%s'", op_name.c_str (), t1_name.c_str (), t1_name.c_str ()); } binary_ops.checkelem (static_cast<int> (op), t1, t2) = reinterpret_cast<void *> (f); return false; } bool type_info::register_binary_class_op (octave_value::compound_binary_op op, type_info::binary_class_op_fcn f, bool abort_on_duplicate) { if (lookup_binary_class_op (op)) { std::string op_name = octave_value::binary_op_fcn_name (op); if (abort_on_duplicate) { std::cerr << "duplicate compound binary operator '" << op_name << "' for class dispatch" << std::endl; abort (); } warning ("duplicate compound binary operator '%s' for class dispatch", op_name.c_str ()); } compound_binary_class_ops.checkelem (static_cast<int> (op)) = reinterpret_cast<void *> (f); return false; } bool type_info::register_binary_op (octave_value::compound_binary_op op, int t1, int t2, type_info::binary_op_fcn f, bool abort_on_duplicate) { if (lookup_binary_op (op, t1, t2)) { std::string op_name = octave_value::binary_op_fcn_name (op); std::string t1_name = types(t1); std::string t2_name = types(t2); if (abort_on_duplicate) { std::cerr << "duplicate compound binary operator '" << op_name << "' for types '" << t1_name << "' and '" << t2_name << "'" << std::endl; abort (); } warning ("duplicate compound binary operator '%s' for types '%s' and '%s'", op_name.c_str (), t1_name.c_str (), t1_name.c_str ()); } compound_binary_ops.checkelem (static_cast<int> (op), t1, t2) = reinterpret_cast<void *> (f); return false; } bool type_info::register_cat_op (int t1, int t2, type_info::cat_op_fcn f, bool abort_on_duplicate) { if (lookup_cat_op (t1, t2)) { std::string t1_name = types(t1); std::string t2_name = types(t2); if (abort_on_duplicate) { std::cerr << "duplicate concatenation operator for types '" << t1_name << "' and '" << t2_name << "'" << std::endl; abort (); } warning ("duplicate concatenation operator for types '%s' and '%s'", t1_name.c_str (), t1_name.c_str ()); } cat_ops.checkelem (t1, t2) = reinterpret_cast<void *> (f); return false; } bool type_info::register_assign_op (octave_value::assign_op op, int t_lhs, int t_rhs, type_info::assign_op_fcn f, bool abort_on_duplicate) { if (lookup_assign_op (op, t_lhs, t_rhs)) { std::string op_name = octave_value::assign_op_as_string (op); std::string t_lhs_name = types(t_lhs); std::string t_rhs_name = types(t_rhs); if (abort_on_duplicate) { std::cerr << "duplicate assignment operator '" << op_name << "' for types '" << t_lhs_name << "' and '" << t_rhs_name << "'" << std::endl; abort (); } warning ("duplicate assignment operator '%s' for types '%s' and '%s'", op_name.c_str (), t_lhs_name.c_str (), t_rhs_name.c_str ()); } assign_ops.checkelem (static_cast<int> (op), t_lhs, t_rhs) = reinterpret_cast<void *> (f); return false; } bool type_info::register_assignany_op (octave_value::assign_op op, int t_lhs, type_info::assignany_op_fcn f, bool abort_on_duplicate) { if (lookup_assignany_op (op, t_lhs)) { std::string op_name = octave_value::assign_op_as_string (op); std::string t_lhs_name = types(t_lhs); if (abort_on_duplicate) { std::cerr << "duplicate assignment operator '" << op_name << "' for types '" << t_lhs_name << "'" << std::endl; abort (); } warning ("duplicate assignment operator '%s' for types '%s'", op_name.c_str (), t_lhs_name.c_str ()); } assignany_ops.checkelem (static_cast<int> (op), t_lhs) = reinterpret_cast<void *> (f); return false; } bool type_info::register_pref_assign_conv (int t_lhs, int t_rhs, int t_result, bool abort_on_duplicate) { if (lookup_pref_assign_conv (t_lhs, t_rhs) >= 0) { std::string t_lhs_name = types(t_lhs); std::string t_rhs_name = types(t_rhs); if (abort_on_duplicate) { std::cerr << "overriding assignment conversion for types '" << t_lhs_name << "' and '" << t_rhs_name << "'" << std::endl; abort (); } warning ("overriding assignment conversion for types '%s' and '%s'", t_lhs_name.c_str (), t_rhs_name.c_str ()); } pref_assign_conv.checkelem (t_lhs, t_rhs) = t_result; return false; } bool type_info::register_widening_op (int t, int t_result, octave_base_value::type_conv_fcn f, bool abort_on_duplicate) { if (lookup_widening_op (t, t_result)) { std::string t_name = types(t); std::string t_result_name = types(t_result); if (abort_on_duplicate) { std::cerr << "overriding widening op for '" << t_name << "' to '" << t_result_name << "'" << std::endl; abort (); } warning ("overriding widening op for '%s' to '%s'", t_name.c_str (), t_result_name.c_str ()); } widening_ops.checkelem (t, t_result) = reinterpret_cast<void *> (f); return false; } octave_value type_info::lookup_type (const std::string& nm) { octave_value retval; for (int i = 0; i < num_types; i++) { if (nm == types(i)) { retval = *vals(i); retval.make_unique (); break; } } return retval; } type_info::unary_class_op_fcn type_info::lookup_unary_class_op (octave_value::unary_op op) { void *f = unary_class_ops.checkelem (static_cast<int> (op)); return reinterpret_cast<type_info::unary_class_op_fcn> (f); } type_info::unary_op_fcn type_info::lookup_unary_op (octave_value::unary_op op, int t) { void *f = unary_ops.checkelem (static_cast<int> (op), t); return reinterpret_cast<type_info::unary_op_fcn> (f); } type_info::non_const_unary_op_fcn type_info::lookup_non_const_unary_op (octave_value::unary_op op, int t) { void *f = non_const_unary_ops.checkelem (static_cast<int> (op), t); return reinterpret_cast<type_info::non_const_unary_op_fcn> (f); } type_info::binary_class_op_fcn type_info::lookup_binary_class_op (octave_value::binary_op op) { void *f = binary_class_ops.checkelem (static_cast<int> (op)); return reinterpret_cast<type_info::binary_class_op_fcn> (f); } type_info::binary_op_fcn type_info::lookup_binary_op (octave_value::binary_op op, int t1, int t2) { void *f = binary_ops.checkelem (static_cast<int> (op), t1, t2); return reinterpret_cast<type_info::binary_op_fcn> (f); } type_info::binary_class_op_fcn type_info::lookup_binary_class_op (octave_value::compound_binary_op op) { void *f = compound_binary_class_ops.checkelem (static_cast<int> (op)); return reinterpret_cast<type_info::binary_class_op_fcn> (f); } type_info::binary_op_fcn type_info::lookup_binary_op (octave_value::compound_binary_op op, int t1, int t2) { void *f = compound_binary_ops.checkelem (static_cast<int> (op), t1, t2); return reinterpret_cast<type_info::binary_op_fcn> (f); } type_info::cat_op_fcn type_info::lookup_cat_op (int t1, int t2) { void *f = cat_ops.checkelem (t1, t2); return reinterpret_cast<type_info::cat_op_fcn> (f); } type_info::assign_op_fcn type_info::lookup_assign_op (octave_value::assign_op op, int t_lhs, int t_rhs) { void *f = assign_ops.checkelem (static_cast<int> (op), t_lhs, t_rhs); return reinterpret_cast<type_info::assign_op_fcn> (f); } type_info::assignany_op_fcn type_info::lookup_assignany_op (octave_value::assign_op op, int t_lhs) { void *f = assignany_ops.checkelem (static_cast<int> (op), t_lhs); return reinterpret_cast<type_info::assignany_op_fcn> (f); } int type_info::lookup_pref_assign_conv (int t_lhs, int t_rhs) { return pref_assign_conv.checkelem (t_lhs, t_rhs); } octave_base_value::type_conv_fcn type_info::lookup_widening_op (int t, int t_result) { void *f = widening_ops.checkelem (t, t_result); return reinterpret_cast<octave_base_value::type_conv_fcn> (f); } string_vector type_info::installed_type_names (void) const { string_vector retval (num_types); for (int i = 0; i < num_types; i++) retval(i) = types(i); return retval; } octave_scalar_map type_info::unary_ops_map (void) const { octave_scalar_map retval; int len = std::min (static_cast<int> (non_const_unary_ops.columns ()), num_types); dim_vector tab_dims (1, len); for (int j = 0; j < octave_value::num_unary_ops; j++) { boolNDArray tab (tab_dims); for (int i = 0; i < len; i++) tab.xelem (i) = (unary_ops(j,i) != nullptr); octave_value::unary_op op_id = static_cast<octave_value::unary_op> (j); retval.setfield (octave_value::unary_op_as_string (op_id), tab); } return retval; } octave_scalar_map type_info::non_const_unary_ops_map (void) const { octave_scalar_map retval; int len = std::min (static_cast<int> (non_const_unary_ops.columns ()), num_types); dim_vector tab_dims (1, len); for (int j = 0; j < octave_value::num_unary_ops; j++) { boolNDArray tab (tab_dims); for (int i = 0; i < len; i++) tab.xelem (i) = (non_const_unary_ops(j,i) != nullptr); octave_value::unary_op op_id = static_cast<octave_value::unary_op> (j); retval.setfield (octave_value::unary_op_as_string (op_id), tab); } return retval; } octave_scalar_map type_info::binary_ops_map (void) const { octave_scalar_map retval; int len = std::min (static_cast<int> (binary_ops.columns ()), num_types); dim_vector tab_dims (len, len); for (int k = 0; k < octave_value::num_binary_ops; k++) { boolNDArray tab (tab_dims); for (int j = 0; j < len; j++) for (int i = 0; i < len; i++) tab.xelem (j,i) = (binary_ops(k,j,i) != nullptr); octave_value::binary_op op_id = static_cast<octave_value::binary_op> (k); retval.setfield (octave_value::binary_op_as_string (op_id), tab); } return retval; } octave_scalar_map type_info::compound_binary_ops_map (void) const { octave_scalar_map retval; int len = std::min (static_cast<int> (compound_binary_ops.columns ()), num_types); dim_vector tab_dims (len, len); for (int k = 0; k < octave_value::num_compound_binary_ops; k++) { boolNDArray tab (tab_dims); for (int j = 0; j < len; j++) for (int i = 0; i < len; i++) tab.xelem (j,i) = (compound_binary_ops(k,j,i) != nullptr); octave_value::compound_binary_op op_id = static_cast<octave_value::compound_binary_op> (k); retval.setfield (octave_value::binary_op_fcn_name (op_id), tab); } return retval; } octave_scalar_map type_info::assign_ops_map (void) const { octave_scalar_map retval; int len = std::min (static_cast<int> (assign_ops.columns ()), num_types); dim_vector tab_dims (len, len); for (int k = 0; k < octave_value::num_assign_ops; k++) { boolNDArray tab (tab_dims); for (int j = 0; j < len; j++) for (int i = 0; i < len; i++) tab.xelem (j,i) = (assign_ops(k,j,i) != nullptr); octave_value::assign_op op_id = static_cast<octave_value::assign_op> (k); retval.setfield (octave_value::assign_op_as_string (op_id), tab); } return retval; } octave_scalar_map type_info::assignany_ops_map (void) const { octave_scalar_map retval; int len = std::min (static_cast<int> (assignany_ops.columns ()), num_types); dim_vector tab_dims (1, len); for (int j = 0; j < octave_value::num_assign_ops; j++) { boolNDArray tab (tab_dims); for (int i = 0; i < len; i++) tab.xelem (i) = (assignany_ops(j,i) != nullptr); octave_value::assign_op op_id = static_cast<octave_value::assign_op> (j); retval.setfield (octave_value::assign_op_as_string (op_id), tab); } return retval; } octave_scalar_map type_info::installed_type_info (void) const { octave_scalar_map retval; retval.setfield ("types", octave_value (Cell (installed_type_names ()))); retval.setfield ("unary_ops", unary_ops_map ()); retval.setfield ("non_const_unary_ops", non_const_unary_ops_map ()); retval.setfield ("binary_ops", binary_ops_map ()); retval.setfield ("compound_binary_ops", compound_binary_ops_map ()); retval.setfield ("cat_ops", as_bool_nd_array (cat_ops)); retval.setfield ("assign_ops", assign_ops_map ()); retval.setfield ("assignany_ops", assignany_ops_map ()); retval.setfield ("pref_assign_conv", as_nd_array (pref_assign_conv)); retval.setfield ("widening_ops", as_bool_nd_array (widening_ops)); return retval; } } namespace octave_value_typeinfo { int register_type (const std::string& t_name, const std::string& c_name, const octave_value& val) { octave::type_info& type_info = octave::__get_type_info__ ("register_type"); return type_info.register_type (t_name, c_name, val); } octave_value lookup_type (const std::string& nm) { octave::type_info& type_info = octave::__get_type_info__ ("lookup_type"); return type_info.lookup_type (nm); } unary_class_op_fcn lookup_unary_class_op (octave_value::unary_op op) { octave::type_info& type_info = octave::__get_type_info__ ("lookup_unary_class_op"); return type_info.lookup_unary_class_op (op); } unary_op_fcn lookup_unary_op (octave_value::unary_op op, int t) { octave::type_info& type_info = octave::__get_type_info__ ("lookup_unary_op"); return type_info.lookup_unary_op (op, t); } non_const_unary_op_fcn lookup_non_const_unary_op (octave_value::unary_op op, int t) { octave::type_info& type_info = octave::__get_type_info__ ("lookup_non_const_unary_op"); return type_info.lookup_non_const_unary_op (op, t); } binary_class_op_fcn lookup_binary_class_op (octave_value::binary_op op) { octave::type_info& type_info = octave::__get_type_info__ ("lookup_binary_class_op"); return type_info.lookup_binary_class_op (op); } binary_op_fcn lookup_binary_op (octave_value::binary_op op, int t1, int t2) { octave::type_info& type_info = octave::__get_type_info__ ("lookup_binary_op"); return type_info.lookup_binary_op (op, t1, t2); } binary_class_op_fcn lookup_binary_class_op (octave_value::compound_binary_op op) { octave::type_info& type_info = octave::__get_type_info__ ("lookup_binary_class_op"); return type_info.lookup_binary_class_op (op); } binary_op_fcn lookup_binary_op (octave_value::compound_binary_op op, int t1, int t2) { octave::type_info& type_info = octave::__get_type_info__ ("lookup_binary_op"); return type_info.lookup_binary_op (op, t1, t2); } cat_op_fcn lookup_cat_op (int t1, int t2) { octave::type_info& type_info = octave::__get_type_info__ ("lookup_cat_op"); return type_info.lookup_cat_op (t1, t2); } assign_op_fcn lookup_assign_op (octave_value::assign_op op, int t_lhs, int t_rhs) { octave::type_info& type_info = octave::__get_type_info__ ("lookup_assign_op"); return type_info.lookup_assign_op (op, t_lhs, t_rhs); } assignany_op_fcn lookup_assignany_op (octave_value::assign_op op, int t_lhs) { octave::type_info& type_info = octave::__get_type_info__ ("lookup_assignany_op"); return type_info.lookup_assignany_op (op, t_lhs); } int lookup_pref_assign_conv (int t_lhs, int t_rhs) { octave::type_info& type_info = octave::__get_type_info__ ("lookup_pref_assign_conv"); return type_info.lookup_pref_assign_conv (t_lhs, t_rhs); } octave_base_value::type_conv_fcn lookup_widening_op (int t, int t_result) { octave::type_info& type_info = octave::__get_type_info__ ("lookup_widening_op"); return type_info.lookup_widening_op (t, t_result); } string_vector installed_type_names (void) { octave::type_info& type_info = octave::__get_type_info__ ("installed_type_names"); return type_info.installed_type_names (); } octave_scalar_map installed_type_info (void) { octave::type_info& type_info = octave::__get_type_info__ ("installed_type_info"); return type_info.installed_type_info (); } } DEFMETHOD (typeinfo, interp, args, , doc: /* -*- texinfo -*- @deftypefn {} {} typeinfo () @deftypefnx {} {} typeinfo (@var{expr}) Return the type of the expression @var{expr}, as a string. If @var{expr} is omitted, return a cell array of strings containing all the currently installed data types. @seealso{class, isa} @end deftypefn */) { int nargin = args.length (); if (nargin > 1) print_usage (); if (nargin == 0) { octave::type_info& type_info = interp.get_type_info (); return ovl (Cell (type_info.installed_type_names ())); } else return ovl (args(0).type_name ()); } /* %!assert (iscellstr (typeinfo ())) %!assert (typeinfo ({"cell"}), "cell") %!assert (typeinfo (1), "scalar") %!assert (typeinfo (double (1)), "scalar") %!assert (typeinfo (i), "complex scalar") %!assert (typeinfo ([1, 2]), "matrix") %!assert (typeinfo (double ([1, 2])), "matrix") %!assert (typeinfo (diag ([1, 2])), "diagonal matrix") %!assert (typeinfo ([i, 2]), "complex matrix") %!assert (typeinfo (diag ([i, 2])), "complex diagonal matrix") %!assert (typeinfo (1:2), "range") %!assert (typeinfo (false), "bool") %!assert (typeinfo ([true, false]), "bool matrix") %!assert (typeinfo ("string"), "string") %!assert (typeinfo ('string'), "sq_string") %!assert (typeinfo (int8 (1)), "int8 scalar") %!assert (typeinfo (int16 (1)), "int16 scalar") %!assert (typeinfo (int32 (1)), "int32 scalar") %!assert (typeinfo (int64 (1)), "int64 scalar") %!assert (typeinfo (uint8 (1)), "uint8 scalar") %!assert (typeinfo (uint16 (1)), "uint16 scalar") %!assert (typeinfo (uint32 (1)), "uint32 scalar") %!assert (typeinfo (uint64 (1)), "uint64 scalar") %!assert (typeinfo (int8 ([1,2])), "int8 matrix") %!assert (typeinfo (int16 ([1,2])), "int16 matrix") %!assert (typeinfo (int32 ([1,2])), "int32 matrix") %!assert (typeinfo (int64 ([1,2])), "int64 matrix") %!assert (typeinfo (uint8 ([1,2])), "uint8 matrix") %!assert (typeinfo (uint16 ([1,2])), "uint16 matrix") %!assert (typeinfo (uint32 ([1,2])), "uint32 matrix") %!assert (typeinfo (uint64 ([1,2])), "uint64 matrix") %!assert (typeinfo (sparse ([true, false])), "sparse bool matrix") %!assert (typeinfo (logical (sparse (i * eye (10)))), "sparse bool matrix") %!assert (typeinfo (sparse ([1,2])), "sparse matrix") %!assert (typeinfo (sparse (eye (10))), "sparse matrix") %!assert (typeinfo (sparse ([i,2])), "sparse complex matrix") %!assert (typeinfo (sparse (i * eye (10))), "sparse complex matrix") %!test %! s(2).a = 1; %! assert (typeinfo (s), "struct"); %!test %! s.a = 1; %! assert (typeinfo (s), "scalar struct"); ## FIXME: This doesn't work as a test for comma-separated list %!#test %! clist = {1, 2, 3}; %! assert (typeinfo (clist{:}), "cs-list"); %!assert (typeinfo (@sin), "function handle") %!assert (typeinfo (@(x) x), "function handle") %!assert (typeinfo (inline ("x^2")), "inline function") %!assert (typeinfo (single (1)), "float scalar") %!assert (typeinfo (single (i)), "float complex scalar") %!assert (typeinfo (single ([1, 2])), "float matrix") %!assert (typeinfo (single (diag ([1, 2]))), "float diagonal matrix") %!assert (typeinfo (diag (single ([1, 2]))), "float diagonal matrix") %!assert (typeinfo (single (diag ([i, 2]))), "float complex diagonal matrix") %!assert (typeinfo (diag (single ([i, 2]))), "float complex diagonal matrix") %!assert (typeinfo (eye(3)(:,[1 3 2])), "permutation matrix") %!test %! [l, u, p] = lu (rand (3)); %! assert (typeinfo (p), "permutation matrix"); %!assert (typeinfo ([]), "null_matrix") %!assert (typeinfo (""), "null_string") %!assert (typeinfo (''), "null_sq_string") %!test %! cvar = onCleanup (@() ""); %! assert (typeinfo (cvar), "onCleanup"); %!testif HAVE_JAVA; usejava ("jvm") %! x = javaObject ("java.lang.StringBuffer"); %! assert (typeinfo (x), "octave_java"); ## Test input validation %!error typeinfo ("foo", 1) */ DEFMETHOD (__dump_typeinfo__, interp, args, , doc: /* -*- texinfo -*- @deftypefn {} {} __dump_typeinfo__ () Undocumented internal function. @end deftypefn */) { if (args.length () > 0) print_usage (); octave::type_info& type_info = interp.get_type_info (); return ovl (type_info.installed_type_info ()); }