diff libinterp/octave-value/ov-typeinfo.cc @ 24540:46440078d73b

don't use singleton for octave_value_typeinfo * ov-typeinfo.h, ov-typeinfo.cc (type_info): New class containing the functionaity provided by the non-static functions in the octave_value_typeinfo class. Define in octave namespace. (octave_value_typeinfo): Now a namespace containing global functions instead of a class containing all static functions. Provided for backward compatibility, so all functions are tagged as deprecated. * ops.h (INSTALL_UNOP_TI, INSTALL_NCUNOP_TI, INSTALL_BINOP_TI, INSTALL_CATOP_TI, INSTALL_ASSIGNOP_TI, INSTALL_ASSIGNANYOP_TI, INSTALL_ASSIGNCONV_TI, INSTALL_WIDENOP_TI): New macros. (install_ops): Accept reference to type_info object as an argument. * mk-ops.sh: Generate function decls and calls that pass reference to type_info object as an argument. * op-b-b.cc, op-b-bm.cc, op-b-sbm.cc, op-bm-b.cc, op-bm-bm.cc, op-bm-sbm.cc, op-cdm-cdm.cc, op-cell.cc, op-chm.cc, op-class.cc, op-cm-cm.cc, op-cm-cs.cc, op-cm-m.cc, op-cm-s.cc, op-cm-scm.cc, op-cm-sm.cc, op-cs-cm.cc, op-cs-cs.cc, op-cs-m.cc, op-cs-s.cc, op-cs-scm.cc, op-cs-sm.cc, op-dm-dm.cc, op-dm-scm.cc, op-dm-sm.cc, op-dm-template.cc, op-dms-template.cc, op-fcdm-fcdm.cc, op-fcm-fcm.cc, op-fcm-fcs.cc, op-fcm-fm.cc, op-fcm-fs.cc, op-fcn.cc, op-fcs-fcm.cc, op-fcs-fcs.cc, op-fcs-fm.cc, op-fcs-fs.cc, op-fdm-fdm.cc, op-fm-fcm.cc, op-fm-fcs.cc, op-fm-fm.cc, op-fm-fs.cc, op-fs-fcm.cc, op-fs-fcs.cc, op-fs-fm.cc, op-fs-fs.cc, op-i16-i16.cc, op-i32-i32.cc, op-i64-i64.cc, op-i8-i8.cc, op-int-concat.cc, op-int.h, op-m-cm.cc, op-m-cs.cc, op-m-m.cc, op-m-s.cc, op-m-scm.cc, op-m-sm.cc, op-pm-pm.cc, op-pm-scm.cc, op-pm-sm.cc, op-pm-template.cc, op-range.cc, op-s-cm.cc, op-s-cs.cc, op-s-m.cc, op-s-s.cc, op-s-scm.cc, op-s-sm.cc, op-sbm-b.cc, op-sbm-bm.cc, op-sbm-sbm.cc, op-scm-cm.cc, op-scm-cs.cc, op-scm-m.cc, op-scm-s.cc, op-scm-scm.cc, op-scm-sm.cc, op-sm-cm.cc, op-sm-cs.cc, op-sm-m.cc, op-sm-s.cc, op-sm-scm.cc, op-sm-sm.cc, op-str-m.cc, op-str-s.cc, op-str-str.cc, op-struct.cc, op-ui16-ui16.cc, op-ui32-ui32.cc, op-ui64-ui64.cc, op-ui8-ui8.cc): Use new _T1 macros. Update install_TYPE_ops function for each type to accept reference to type_info object as argument. * interpreter.h, interpreter.cc (interpreter::m_type_info): New member variable. (interpreter::get_type_info): New function. (interpreter::interpreter): Initialize m_type_info before m_symbol_table. Don't call install_types or install ops. That is now handled by the in type_info constructor. Don't call m_cdef_manager. That is now handled by the cdef_manager constructor. * interpreter-private.h, interpreter-private.cc (__get_type_info__): New function. Use where necessary to get reference to interpreter::m_type_info object. * ov-classdef.cc, ov-classdef.h (octave_classdef::octave_classdef): Handle all initialization here. (octave_classdef::initialize): Delete unused function. * ov.h, ov.cc (install_types): Accept reference to type_info object as argument. Pass on to individual register_type functions. * ov-base.h, ov-base.cc (DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA): Update to define additional register_type functions that accepts reference to type_info object. (install_base_type_conversions): Update to use new *_TI macros.
author John W. Eaton <jwe@octave.org>
date Fri, 05 Jan 2018 18:44:53 -0500
parents 194eb4bd202b
children 5f445419559f
line wrap: on
line diff
--- a/libinterp/octave-value/ov-typeinfo.cc	Sat Jan 06 14:57:23 2018 -0500
+++ b/libinterp/octave-value/ov-typeinfo.cc	Fri Jan 05 18:44:53 2018 -0500
@@ -25,553 +25,980 @@
 #endif
 
 #include "Array.h"
-#include "singleton-cleanup.h"
 
 #include "defun.h"
 #include "error.h"
+#include "interpreter.h"
+#include "interpreter-private.h"
+#include "ops.h"
 #include "ov-typeinfo.h"
-
-const int
-octave_value_typeinfo::init_tab_sz (16);
-
-octave_value_typeinfo *
-octave_value_typeinfo::instance (nullptr);
-
-bool
-octave_value_typeinfo::instance_ok (void)
-{
-  bool retval = true;
-
-  if (! instance)
-    {
-      instance = new octave_value_typeinfo ();
-
-      if (instance)
-        singleton_cleanup_list::add (cleanup_instance);
-    }
-
-  if (! instance)
-    error ("unable to create value type info object!");
-
-  return retval;
-}
-
-int
-octave_value_typeinfo::register_type (const std::string& t_name,
-                                      const std::string& c_name,
-                                      const octave_value& val)
-{
-  return (instance_ok ())
-         ? instance->do_register_type (t_name, c_name, val) : -1;
-}
-
-bool
-octave_value_typeinfo::register_unary_class_op (octave_value::unary_op op,
-                                                octave_value_typeinfo::unary_class_op_fcn f)
-{
-  return (instance_ok ())
-         ? instance->do_register_unary_class_op (op, f) : false;
-}
-
-bool
-octave_value_typeinfo::register_unary_op (octave_value::unary_op op,
-                                          int t,
-                                          octave_value_typeinfo::unary_op_fcn f)
-{
-  return (instance_ok ())
-         ? instance->do_register_unary_op (op, t, f) : false;
-}
-
-bool
-octave_value_typeinfo::register_non_const_unary_op (octave_value::unary_op op,
-                                                    int t,
-                                                    octave_value_typeinfo::non_const_unary_op_fcn f)
-{
-  return (instance_ok ())
-         ? instance->do_register_non_const_unary_op (op, t, f) : false;
-}
-
-bool
-octave_value_typeinfo::register_binary_class_op (octave_value::binary_op op,
-                                                 octave_value_typeinfo::binary_class_op_fcn f)
-{
-  return (instance_ok ())
-         ? instance->do_register_binary_class_op (op, f) : false;
-}
-
-bool
-octave_value_typeinfo::register_binary_op (octave_value::binary_op op,
-                                           int t1, int t2,
-                                           octave_value_typeinfo::binary_op_fcn f)
-{
-  return (instance_ok ())
-         ? instance->do_register_binary_op (op, t1, t2, f) : false;
-}
-
-bool
-octave_value_typeinfo::register_binary_class_op (octave_value::compound_binary_op op,
-                                                 octave_value_typeinfo::binary_class_op_fcn f)
-{
-  return (instance_ok ())
-         ? instance->do_register_binary_class_op (op, f) : false;
-}
-
-bool
-octave_value_typeinfo::register_binary_op (octave_value::compound_binary_op op,
-                                           int t1, int t2,
-                                           octave_value_typeinfo::binary_op_fcn f)
-{
-  return (instance_ok ())
-         ? instance->do_register_binary_op (op, t1, t2, f) : false;
-}
-
-bool
-octave_value_typeinfo::register_cat_op (int t1, int t2,
-                                        octave_value_typeinfo::cat_op_fcn f)
-{
-  return (instance_ok ())
-         ? instance->do_register_cat_op (t1, t2, f) : false;
-}
-
-bool
-octave_value_typeinfo::register_assign_op (octave_value::assign_op op,
-                                           int t_lhs, int t_rhs,
-                                           octave_value_typeinfo::assign_op_fcn f)
-{
-  return (instance_ok ())
-         ? instance->do_register_assign_op (op, t_lhs, t_rhs, f) : false;
-}
-
-bool
-octave_value_typeinfo::register_assignany_op (octave_value::assign_op op,
-                                              int t_lhs, octave_value_typeinfo::assignany_op_fcn f)
-{
-  return (instance_ok ())
-         ? instance->do_register_assignany_op (op, t_lhs, f) : false;
-}
-
-bool
-octave_value_typeinfo::register_pref_assign_conv (int t_lhs, int t_rhs,
-                                                  int t_result)
-{
-  return (instance_ok ())
-         ? instance->do_register_pref_assign_conv (t_lhs, t_rhs, t_result)
-         : false;
-}
-
-bool
-octave_value_typeinfo::register_widening_op (int t, int t_result,
-                                             octave_base_value::type_conv_fcn f)
-{
-  return (instance_ok ())
-         ? instance->do_register_widening_op (t, t_result, f) : false;
-}
+#include "ov.h"
 
 // FIXME: we should also store all class names and provide a
 // way to list them (calling class with nargin == 0?).
 
-int
-octave_value_typeinfo::do_register_type (const std::string& t_name,
-                                         const std::string& /* c_name */,
-                                         const octave_value& val)
+static NDArray
+as_nd_array (const Array<int>& x)
 {
-  int i = 0;
-
-  for (i = 0; i < num_types; i++)
-    if (t_name == types (i))
-      return i;
-
-  int len = types.numel ();
-
-  if (i == len)
-    {
-      len *= 2;
-
-      types.resize (dim_vector (len, 1), "");
-
-      vals.resize (dim_vector (len, 1), octave_value ());
-
-      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;
-
-  vals (i) = val;
-
-  num_types++;
-
-  return i;
-}
-
-bool
-octave_value_typeinfo::do_register_unary_class_op (octave_value::unary_op op,
-                                                   octave_value_typeinfo::unary_class_op_fcn f)
-{
-  if (lookup_unary_class_op (op))
-    {
-      std::string op_name = octave_value::unary_op_as_string (op);
+  NDArray retval (x.dims ());
 
-      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
-octave_value_typeinfo::do_register_unary_op (octave_value::unary_op op,
-                                             int t,
-                                             octave_value_typeinfo::unary_op_fcn f)
-{
-  if (lookup_unary_op (op, t))
-    {
-      std::string op_name = octave_value::unary_op_as_string (op);
-      std::string type_name = types(t);
-
-      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;
-}
+  for (int i = 0; i < x.numel (); i++)
+    retval.xelem(i) = x(i);
 
-bool
-octave_value_typeinfo::do_register_non_const_unary_op
-  (octave_value::unary_op op, int t,
-   octave_value_typeinfo::non_const_unary_op_fcn f)
-{
-  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);
-
-      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
-octave_value_typeinfo::do_register_binary_class_op (octave_value::binary_op op,
-                                                    octave_value_typeinfo::binary_class_op_fcn f)
-{
-  if (lookup_binary_class_op (op))
-    {
-      std::string op_name = octave_value::binary_op_as_string (op);
-
-      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;
+  return retval;
 }
 
-bool
-octave_value_typeinfo::do_register_binary_op (octave_value::binary_op op,
-                                              int t1, int t2,
-                                              octave_value_typeinfo::binary_op_fcn f)
-{
-  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);
-
-      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
-octave_value_typeinfo::do_register_binary_class_op (octave_value::compound_binary_op op,
-                                                    octave_value_typeinfo::binary_class_op_fcn f)
-{
-  if (lookup_binary_class_op (op))
-    {
-      std::string op_name = octave_value::binary_op_fcn_name (op);
-
-      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
-octave_value_typeinfo::do_register_binary_op (octave_value::compound_binary_op op,
-                                              int t1, int t2,
-                                              octave_value_typeinfo::binary_op_fcn f)
-{
-  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);
-
-      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
-octave_value_typeinfo::do_register_cat_op (int t1, int t2,
-                                           octave_value_typeinfo::cat_op_fcn f)
-{
-  if (lookup_cat_op (t1, t2))
-    {
-      std::string t1_name = types(t1);
-      std::string t2_name = types(t2);
-
-      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
-octave_value_typeinfo::do_register_assign_op (octave_value::assign_op op,
-                                              int t_lhs, int t_rhs,
-                                              octave_value_typeinfo::assign_op_fcn f)
+static boolNDArray
+as_bool_nd_array (const Array<void *>& x)
 {
-  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);
-
-      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
-octave_value_typeinfo::do_register_assignany_op (octave_value::assign_op op,
-                                                 int t_lhs, octave_value_typeinfo::assignany_op_fcn f)
-{
-  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);
-
-      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;
-}
+  boolNDArray retval (x.dims ());
 
-bool
-octave_value_typeinfo::do_register_pref_assign_conv (int t_lhs, int t_rhs,
-                                                     int t_result)
-{
-  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);
-
-      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
-octave_value_typeinfo::do_register_widening_op
-  (int t, int t_result, octave_base_value::type_conv_fcn f)
-{
-  if (lookup_widening_op (t, t_result))
-    {
-      std::string t_name = types(t);
-      std::string t_result_name = types(t_result);
-
-      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
-octave_value_typeinfo::do_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;
-        }
-    }
+  for (octave_idx_type i = 0; i < x.numel (); i++)
+    retval.xelem (i) = x(i);
 
   return retval;
 }
 
-octave_value_typeinfo::unary_class_op_fcn
-octave_value_typeinfo::do_lookup_unary_class_op (octave_value::unary_op op)
-{
-  void *f = unary_class_ops.checkelem (static_cast<int> (op));
-  return reinterpret_cast<octave_value_typeinfo::unary_class_op_fcn> (f);
-}
-
-octave_value_typeinfo::unary_op_fcn
-octave_value_typeinfo::do_lookup_unary_op (octave_value::unary_op op, int t)
-{
-  void *f = unary_ops.checkelem (static_cast<int> (op), t);
-  return reinterpret_cast<octave_value_typeinfo::unary_op_fcn> (f);
-}
-
-octave_value_typeinfo::non_const_unary_op_fcn
-octave_value_typeinfo::do_lookup_non_const_unary_op
-  (octave_value::unary_op op, int t)
+namespace octave
 {
-  void *f = non_const_unary_ops.checkelem (static_cast<int> (op), t);
-  return reinterpret_cast<octave_value_typeinfo::non_const_unary_op_fcn> (f);
-}
+  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), octave_value ());
+
+        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;
+
+    vals (i) = 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;
+  }
 
-octave_value_typeinfo::binary_class_op_fcn
-octave_value_typeinfo::do_lookup_binary_class_op (octave_value::binary_op op)
-{
-  void *f = binary_class_ops.checkelem (static_cast<int> (op));
-  return reinterpret_cast<octave_value_typeinfo::binary_class_op_fcn> (f);
-}
+  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);
 
-octave_value_typeinfo::binary_op_fcn
-octave_value_typeinfo::do_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<octave_value_typeinfo::binary_op_fcn> (f);
-}
+        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);
 
-octave_value_typeinfo::binary_class_op_fcn
-octave_value_typeinfo::do_lookup_binary_class_op (octave_value::compound_binary_op op)
-{
-  void *f = compound_binary_class_ops.checkelem (static_cast<int> (op));
-  return reinterpret_cast<octave_value_typeinfo::binary_class_op_fcn> (f);
+    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;
+  }
 }
 
-octave_value_typeinfo::binary_op_fcn
-octave_value_typeinfo::do_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<octave_value_typeinfo::binary_op_fcn> (f);
-}
-
-octave_value_typeinfo::cat_op_fcn
-octave_value_typeinfo::do_lookup_cat_op (int t1, int t2)
+namespace octave_value_typeinfo
 {
-  void *f = cat_ops.checkelem (t1, t2);
-  return reinterpret_cast<octave_value_typeinfo::cat_op_fcn> (f);
-}
+  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);
+  }
+
+  bool register_unary_class_op (octave_value::unary_op op,
+                                unary_class_op_fcn f)
+  {
+    octave::type_info& type_info
+      = octave::__get_type_info__ ("register_unary_class_op");
+
+    return type_info.register_unary_class_op (op, f);
+  }
+
+  bool register_unary_op (octave_value::unary_op op,
+                          int t, unary_op_fcn f)
+  {
+    octave::type_info& type_info
+      = octave::__get_type_info__ ("register_unary_op");
+
+    return type_info.register_unary_op (op, t, f);
+  }
+
+  bool register_non_const_unary_op (octave_value::unary_op op,
+                                    int t, non_const_unary_op_fcn f)
+  {
+    octave::type_info& type_info
+      = octave::__get_type_info__ ("register_non_const_unary_op");
+
+    return type_info.register_non_const_unary_op (op, t, f);
+  }
+
+  bool register_binary_class_op (octave_value::binary_op op,
+                                 binary_class_op_fcn f)
+  {
+    octave::type_info& type_info
+      = octave::__get_type_info__ ("register_binary_class_op");
+
+    return type_info.register_binary_class_op (op, f);
+  }
+
+  bool register_binary_op (octave_value::binary_op op,
+                           int t1, int t2, binary_op_fcn f)
+  {
+    octave::type_info& type_info
+      = octave::__get_type_info__ ("register_binary_op");
+
+    return type_info.register_binary_op (op, t1, t2, f);
+  }
+
+  bool register_binary_class_op (octave_value::compound_binary_op op,
+                                 binary_class_op_fcn f)
+  {
+    octave::type_info& type_info
+      = octave::__get_type_info__ ("register_binary_class_op");
+
+    return type_info.register_binary_class_op (op, f);
+  }
+
+  bool register_binary_op (octave_value::compound_binary_op op,
+                           int t1, int t2, binary_op_fcn f)
+  {
+    octave::type_info& type_info
+      = octave::__get_type_info__ ("register_binary_op");
+
+    return type_info.register_binary_op (op, t1, t2, f);
+  }
+
+  bool register_cat_op (int t1, int t2, cat_op_fcn f)
+  {
+    octave::type_info& type_info
+      = octave::__get_type_info__ ("register_cat_op");
+
+    return type_info.register_cat_op (t1, t2, f);
+  }
+
+  bool register_assign_op (octave_value::assign_op op,
+                           int t_lhs, int t_rhs, assign_op_fcn f)
+  {
+    octave::type_info& type_info
+      = octave::__get_type_info__ ("register_assign_op");
+
+    return type_info.register_assign_op (op, t_lhs, t_rhs, f);
+  }
+
+  bool register_assignany_op (octave_value::assign_op op,
+                              int t_lhs, assignany_op_fcn f)
+  {
+    octave::type_info& type_info
+      = octave::__get_type_info__ ("register_assignany_op");
+
+    return type_info.register_assignany_op (op, t_lhs, f);
+  }
+
+  bool register_pref_assign_conv (int t_lhs, int t_rhs, int t_result)
+  {
+    octave::type_info& type_info
+      = octave::__get_type_info__ ("register_pref_assign_conv");
+
+    return type_info.register_pref_assign_conv (t_lhs, t_rhs, t_result);
+  }
+
+  bool register_widening_op (int t, int t_result,
+                             octave_base_value::type_conv_fcn f)
+  {
+    octave::type_info& type_info
+      = octave::__get_type_info__ ("register_widening_op");
+
+    return type_info.register_widening_op (t, t_result, f);
+  }
+
+  octave_value lookup_type (const std::string& nm)
+  {
+    octave::type_info& type_info
+      = octave::__get_type_info__ ("lookup_type");
 
-octave_value_typeinfo::assign_op_fcn
-octave_value_typeinfo::do_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<octave_value_typeinfo::assign_op_fcn> (f);
+    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 ();
+  }
 }
 
-octave_value_typeinfo::assignany_op_fcn
-octave_value_typeinfo::do_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<octave_value_typeinfo::assignany_op_fcn> (f);
-}
-
-int
-octave_value_typeinfo::do_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
-octave_value_typeinfo::do_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
-octave_value_typeinfo::do_installed_type_names (void) const
-{
-  string_vector retval (num_types);
-
-  for (int i = 0; i < num_types; i++)
-    retval(i) = types(i);
-
-  return retval;
-}
-
-DEFUN (typeinfo, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (typeinfo, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn  {} {} typeinfo ()
 @deftypefnx {} {} typeinfo (@var{expr})
 
@@ -588,7 +1015,11 @@
     print_usage ();
 
   if (nargin == 0)
-    return ovl (Cell (octave_value_typeinfo::installed_type_names ()));
+    {
+      octave::type_info& type_info = interp.get_type_info ();
+
+      return ovl (Cell (type_info.installed_type_names ()));
+    }
   else
     return ovl (args(0).type_name ());
 }
@@ -689,200 +1120,8 @@
 %!error typeinfo ("foo", 1)
 */
 
-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;
-}
-
-octave_scalar_map
-octave_value_typeinfo::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
-octave_value_typeinfo::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
-octave_value_typeinfo::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
-octave_value_typeinfo::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
-octave_value_typeinfo::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
-octave_value_typeinfo::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;
-}
-
-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;
-}
-
-octave_scalar_map
-octave_value_typeinfo::do_installed_type_info (void) const
-{
-  octave_scalar_map retval;
-
-  retval.setfield ("types", octave_value (Cell (do_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;
-}
-
-DEFUN (__dump_typeinfo__, args, ,
-       doc: /* -*- texinfo -*-
+DEFMETHOD (__dump_typeinfo__, interp, args, ,
+           doc: /* -*- texinfo -*-
 @deftypefn {} {} __dump_typeinfo__ ()
 Undocumented internal function.
 @end deftypefn */)
@@ -890,5 +1129,7 @@
   if (args.length () > 0)
     print_usage ();
 
-  return ovl (octave_value_typeinfo::installed_type_info ());
+  octave::type_info& type_info = interp.get_type_info ();
+
+  return ovl (type_info.installed_type_info ());
 }