00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026
00027 #include "Array.h"
00028 #include "singleton-cleanup.h"
00029
00030 #include "defun.h"
00031 #include "error.h"
00032 #include "ov-typeinfo.h"
00033
00034 const int
00035 octave_value_typeinfo::init_tab_sz (16);
00036
00037 octave_value_typeinfo *
00038 octave_value_typeinfo::instance (0);
00039
00040 bool
00041 octave_value_typeinfo::instance_ok (void)
00042 {
00043 bool retval = true;
00044
00045 if (! instance)
00046 {
00047 instance = new octave_value_typeinfo ();
00048
00049 if (instance)
00050 singleton_cleanup_list::add (cleanup_instance);
00051 }
00052
00053 if (! instance)
00054 {
00055 ::error ("unable to create value type info object!");
00056
00057 retval = false;
00058 }
00059
00060 return retval;
00061 }
00062
00063 int
00064 octave_value_typeinfo::register_type (const std::string& t_name,
00065 const std::string& c_name,
00066 const octave_value& val)
00067 {
00068 return (instance_ok ())
00069 ? instance->do_register_type (t_name, c_name, val) : -1;
00070 }
00071
00072 bool
00073 octave_value_typeinfo::register_unary_class_op (octave_value::unary_op op,
00074 octave_value_typeinfo::unary_class_op_fcn f)
00075 {
00076 return (instance_ok ())
00077 ? instance->do_register_unary_class_op (op, f) : false;
00078 }
00079
00080 bool
00081 octave_value_typeinfo::register_unary_op (octave_value::unary_op op,
00082 int t, octave_value_typeinfo::unary_op_fcn f)
00083 {
00084 return (instance_ok ())
00085 ? instance->do_register_unary_op (op, t, f) : false;
00086 }
00087
00088 bool
00089 octave_value_typeinfo::register_non_const_unary_op (octave_value::unary_op op,
00090 int t,
00091 octave_value_typeinfo::non_const_unary_op_fcn f)
00092 {
00093 return (instance_ok ())
00094 ? instance->do_register_non_const_unary_op (op, t, f) : false;
00095 }
00096
00097 bool
00098 octave_value_typeinfo::register_binary_class_op (octave_value::binary_op op,
00099 octave_value_typeinfo::binary_class_op_fcn f)
00100 {
00101 return (instance_ok ())
00102 ? instance->do_register_binary_class_op (op, f) : false;
00103 }
00104
00105 bool
00106 octave_value_typeinfo::register_binary_op (octave_value::binary_op op,
00107 int t1, int t2,
00108 octave_value_typeinfo::binary_op_fcn f)
00109 {
00110 return (instance_ok ())
00111 ? instance->do_register_binary_op (op, t1, t2, f) : false;
00112 }
00113
00114 bool
00115 octave_value_typeinfo::register_binary_class_op (octave_value::compound_binary_op op,
00116 octave_value_typeinfo::binary_class_op_fcn f)
00117 {
00118 return (instance_ok ())
00119 ? instance->do_register_binary_class_op (op, f) : false;
00120 }
00121
00122 bool
00123 octave_value_typeinfo::register_binary_op (octave_value::compound_binary_op op,
00124 int t1, int t2,
00125 octave_value_typeinfo::binary_op_fcn f)
00126 {
00127 return (instance_ok ())
00128 ? instance->do_register_binary_op (op, t1, t2, f) : false;
00129 }
00130
00131 bool
00132 octave_value_typeinfo::register_cat_op (int t1, int t2, octave_value_typeinfo::cat_op_fcn f)
00133 {
00134 return (instance_ok ())
00135 ? instance->do_register_cat_op (t1, t2, f) : false;
00136 }
00137
00138 bool
00139 octave_value_typeinfo::register_assign_op (octave_value::assign_op op,
00140 int t_lhs, int t_rhs,
00141 octave_value_typeinfo::assign_op_fcn f)
00142 {
00143 return (instance_ok ())
00144 ? instance->do_register_assign_op (op, t_lhs, t_rhs, f) : -1;
00145 }
00146
00147 bool
00148 octave_value_typeinfo::register_assignany_op (octave_value::assign_op op,
00149 int t_lhs, octave_value_typeinfo::assignany_op_fcn f)
00150 {
00151 return (instance_ok ())
00152 ? instance->do_register_assignany_op (op, t_lhs, f) : -1;
00153 }
00154
00155 bool
00156 octave_value_typeinfo::register_pref_assign_conv (int t_lhs, int t_rhs,
00157 int t_result)
00158 {
00159 return (instance_ok ())
00160 ? instance->do_register_pref_assign_conv (t_lhs, t_rhs, t_result) : false;
00161 }
00162
00163 bool
00164 octave_value_typeinfo::register_type_conv_op (int t, int t_result,
00165 octave_base_value::type_conv_fcn f)
00166 {
00167 return (instance_ok ())
00168 ? instance->do_register_type_conv_op (t, t_result, f) : false;
00169 }
00170
00171 bool
00172 octave_value_typeinfo::register_widening_op (int t, int t_result,
00173 octave_base_value::type_conv_fcn f)
00174 {
00175 return (instance_ok ())
00176 ? instance->do_register_widening_op (t, t_result, f) : false;
00177 }
00178
00179
00180
00181
00182 int
00183 octave_value_typeinfo::do_register_type (const std::string& t_name,
00184 const std::string& ,
00185 const octave_value& val)
00186 {
00187 int i = 0;
00188
00189 for (i = 0; i < num_types; i++)
00190 if (t_name == types (i))
00191 return i;
00192
00193 int len = types.length ();
00194
00195 if (i == len)
00196 {
00197 len *= 2;
00198
00199 types.resize (dim_vector (len, 1), std::string ());
00200
00201 vals.resize (dim_vector (len, 1), octave_value ());
00202
00203 unary_ops.resize (dim_vector (octave_value::num_unary_ops, len), 0);
00204
00205 non_const_unary_ops.resize
00206 (dim_vector (octave_value::num_unary_ops, len), 0);
00207
00208 binary_ops.resize
00209 (dim_vector (octave_value::num_binary_ops, len, len), 0);
00210
00211 compound_binary_ops.resize
00212 (dim_vector (octave_value::num_compound_binary_ops, len, len), 0);
00213
00214 cat_ops.resize (dim_vector (len, len), 0);
00215
00216 assign_ops.resize
00217 (dim_vector (octave_value::num_assign_ops, len, len), 0);
00218
00219 assignany_ops.resize
00220 (dim_vector (octave_value::num_assign_ops, len), 0);
00221
00222 pref_assign_conv.resize (dim_vector (len, len), -1);
00223
00224 type_conv_ops.resize (dim_vector (len, len), 0);
00225
00226 widening_ops.resize (dim_vector (len, len), 0);
00227 }
00228
00229 types (i) = t_name;
00230
00231 vals (i) = val;
00232
00233 num_types++;
00234
00235 return i;
00236 }
00237
00238 bool
00239 octave_value_typeinfo::do_register_unary_class_op (octave_value::unary_op op,
00240 octave_value_typeinfo::unary_class_op_fcn f)
00241 {
00242 if (lookup_unary_class_op (op))
00243 {
00244 std::string op_name = octave_value::unary_op_as_string (op);
00245
00246 warning ("duplicate unary operator '%s' for class dispatch",
00247 op_name.c_str ());
00248 }
00249
00250 unary_class_ops.checkelem (static_cast<int> (op)) = reinterpret_cast<void *> (f);
00251
00252 return false;
00253 }
00254
00255 bool
00256 octave_value_typeinfo::do_register_unary_op (octave_value::unary_op op,
00257 int t, octave_value_typeinfo::unary_op_fcn f)
00258 {
00259 if (lookup_unary_op (op, t))
00260 {
00261 std::string op_name = octave_value::unary_op_as_string (op);
00262 std::string type_name = types(t);
00263
00264 warning ("duplicate unary operator '%s' for type '%s'",
00265 op_name.c_str (), type_name.c_str ());
00266 }
00267
00268 unary_ops.checkelem (static_cast<int> (op), t) = reinterpret_cast<void *> (f);
00269
00270 return false;
00271 }
00272
00273 bool
00274 octave_value_typeinfo::do_register_non_const_unary_op
00275 (octave_value::unary_op op, int t, octave_value_typeinfo::non_const_unary_op_fcn f)
00276 {
00277 if (lookup_non_const_unary_op (op, t))
00278 {
00279 std::string op_name = octave_value::unary_op_as_string (op);
00280 std::string type_name = types(t);
00281
00282 warning ("duplicate unary operator '%s' for type '%s'",
00283 op_name.c_str (), type_name.c_str ());
00284 }
00285
00286 non_const_unary_ops.checkelem (static_cast<int> (op), t) = reinterpret_cast<void *> (f);
00287
00288 return false;
00289 }
00290
00291 bool
00292 octave_value_typeinfo::do_register_binary_class_op (octave_value::binary_op op,
00293 octave_value_typeinfo::binary_class_op_fcn f)
00294 {
00295 if (lookup_binary_class_op (op))
00296 {
00297 std::string op_name = octave_value::binary_op_as_string (op);
00298
00299 warning ("duplicate binary operator '%s' for class dispatch",
00300 op_name.c_str ());
00301 }
00302
00303 binary_class_ops.checkelem (static_cast<int> (op)) = reinterpret_cast<void *> (f);
00304
00305 return false;
00306 }
00307
00308 bool
00309 octave_value_typeinfo::do_register_binary_op (octave_value::binary_op op,
00310 int t1, int t2,
00311 octave_value_typeinfo::binary_op_fcn f)
00312 {
00313 if (lookup_binary_op (op, t1, t2))
00314 {
00315 std::string op_name = octave_value::binary_op_as_string (op);
00316 std::string t1_name = types(t1);
00317 std::string t2_name = types(t2);
00318
00319 warning ("duplicate binary operator '%s' for types '%s' and '%s'",
00320 op_name.c_str (), t1_name.c_str (), t1_name.c_str ());
00321 }
00322
00323 binary_ops.checkelem (static_cast<int> (op), t1, t2) = reinterpret_cast<void *> (f);
00324
00325 return false;
00326 }
00327
00328 bool
00329 octave_value_typeinfo::do_register_binary_class_op (octave_value::compound_binary_op op,
00330 octave_value_typeinfo::binary_class_op_fcn f)
00331 {
00332 if (lookup_binary_class_op (op))
00333 {
00334 std::string op_name = octave_value::binary_op_fcn_name (op);
00335
00336 warning ("duplicate compound binary operator '%s' for class dispatch",
00337 op_name.c_str ());
00338 }
00339
00340 compound_binary_class_ops.checkelem (static_cast<int> (op)) = reinterpret_cast<void *> (f);
00341
00342 return false;
00343 }
00344
00345 bool
00346 octave_value_typeinfo::do_register_binary_op (octave_value::compound_binary_op op,
00347 int t1, int t2,
00348 octave_value_typeinfo::binary_op_fcn f)
00349 {
00350 if (lookup_binary_op (op, t1, t2))
00351 {
00352 std::string op_name = octave_value::binary_op_fcn_name (op);
00353 std::string t1_name = types(t1);
00354 std::string t2_name = types(t2);
00355
00356 warning ("duplicate compound binary operator '%s' for types '%s' and '%s'",
00357 op_name.c_str (), t1_name.c_str (), t1_name.c_str ());
00358 }
00359
00360 compound_binary_ops.checkelem (static_cast<int> (op), t1, t2) = reinterpret_cast<void *> (f);
00361
00362 return false;
00363 }
00364
00365 bool
00366 octave_value_typeinfo::do_register_cat_op (int t1, int t2, octave_value_typeinfo::cat_op_fcn f)
00367 {
00368 if (lookup_cat_op (t1, t2))
00369 {
00370 std::string t1_name = types(t1);
00371 std::string t2_name = types(t2);
00372
00373 warning ("duplicate concatenation operator for types '%s' and '%s'",
00374 t1_name.c_str (), t1_name.c_str ());
00375 }
00376
00377 cat_ops.checkelem (t1, t2) = reinterpret_cast<void *> (f);
00378
00379 return false;
00380 }
00381
00382 bool
00383 octave_value_typeinfo::do_register_assign_op (octave_value::assign_op op,
00384 int t_lhs, int t_rhs,
00385 octave_value_typeinfo::assign_op_fcn f)
00386 {
00387 if (lookup_assign_op (op, t_lhs, t_rhs))
00388 {
00389 std::string op_name = octave_value::assign_op_as_string (op);
00390 std::string t_lhs_name = types(t_lhs);
00391 std::string t_rhs_name = types(t_rhs);
00392
00393 warning ("duplicate assignment operator '%s' for types '%s' and '%s'",
00394 op_name.c_str (), t_lhs_name.c_str (), t_rhs_name.c_str ());
00395 }
00396
00397 assign_ops.checkelem (static_cast<int> (op), t_lhs, t_rhs) = reinterpret_cast<void *> (f);
00398
00399 return false;
00400 }
00401
00402 bool
00403 octave_value_typeinfo::do_register_assignany_op (octave_value::assign_op op,
00404 int t_lhs, octave_value_typeinfo::assignany_op_fcn f)
00405 {
00406 if (lookup_assignany_op (op, t_lhs))
00407 {
00408 std::string op_name = octave_value::assign_op_as_string (op);
00409 std::string t_lhs_name = types(t_lhs);
00410
00411 warning ("duplicate assignment operator '%s' for types '%s'",
00412 op_name.c_str (), t_lhs_name.c_str ());
00413 }
00414
00415 assignany_ops.checkelem (static_cast<int> (op), t_lhs) = reinterpret_cast<void *> (f);
00416
00417 return false;
00418 }
00419
00420 bool
00421 octave_value_typeinfo::do_register_pref_assign_conv (int t_lhs, int t_rhs,
00422 int t_result)
00423 {
00424 if (lookup_pref_assign_conv (t_lhs, t_rhs) >= 0)
00425 {
00426 std::string t_lhs_name = types(t_lhs);
00427 std::string t_rhs_name = types(t_rhs);
00428
00429 warning ("overriding assignment conversion for types '%s' and '%s'",
00430 t_lhs_name.c_str (), t_rhs_name.c_str ());
00431 }
00432
00433 pref_assign_conv.checkelem (t_lhs, t_rhs) = t_result;
00434
00435 return false;
00436 }
00437
00438 bool
00439 octave_value_typeinfo::do_register_type_conv_op
00440 (int t, int t_result, octave_base_value::type_conv_fcn f)
00441 {
00442 if (lookup_type_conv_op (t, t_result))
00443 {
00444 std::string t_name = types(t);
00445 std::string t_result_name = types(t_result);
00446
00447 warning ("overriding type conversion op for '%s' to '%s'",
00448 t_name.c_str (), t_result_name.c_str ());
00449 }
00450
00451 type_conv_ops.checkelem (t, t_result) = reinterpret_cast<void *> (f);
00452
00453 return false;
00454 }
00455
00456 bool
00457 octave_value_typeinfo::do_register_widening_op
00458 (int t, int t_result, octave_base_value::type_conv_fcn f)
00459 {
00460 if (lookup_widening_op (t, t_result))
00461 {
00462 std::string t_name = types(t);
00463 std::string t_result_name = types(t_result);
00464
00465 warning ("overriding widening op for '%s' to '%s'",
00466 t_name.c_str (), t_result_name.c_str ());
00467 }
00468
00469 widening_ops.checkelem (t, t_result) = reinterpret_cast<void *> (f);
00470
00471 return false;
00472 }
00473
00474 octave_value
00475 octave_value_typeinfo::do_lookup_type (const std::string& nm)
00476 {
00477 octave_value retval;
00478
00479 for (int i = 0; i < num_types; i++)
00480 {
00481 if (nm == types(i))
00482 {
00483 retval = vals(i);
00484 retval.make_unique ();
00485 break;
00486 }
00487 }
00488
00489 return retval;
00490 }
00491
00492 octave_value_typeinfo::unary_class_op_fcn
00493 octave_value_typeinfo::do_lookup_unary_class_op (octave_value::unary_op op)
00494 {
00495 void *f = unary_class_ops.checkelem (static_cast<int> (op));
00496 return reinterpret_cast<octave_value_typeinfo::unary_class_op_fcn> (f);
00497 }
00498
00499 octave_value_typeinfo::unary_op_fcn
00500 octave_value_typeinfo::do_lookup_unary_op (octave_value::unary_op op, int t)
00501 {
00502 void *f = unary_ops.checkelem (static_cast<int> (op), t);
00503 return reinterpret_cast<octave_value_typeinfo::unary_op_fcn> (f);
00504 }
00505
00506 octave_value_typeinfo::non_const_unary_op_fcn
00507 octave_value_typeinfo::do_lookup_non_const_unary_op
00508 (octave_value::unary_op op, int t)
00509 {
00510 void *f = non_const_unary_ops.checkelem (static_cast<int> (op), t);
00511 return reinterpret_cast<octave_value_typeinfo::non_const_unary_op_fcn> (f);
00512 }
00513
00514 octave_value_typeinfo::binary_class_op_fcn
00515 octave_value_typeinfo::do_lookup_binary_class_op (octave_value::binary_op op)
00516 {
00517 void *f = binary_class_ops.checkelem (static_cast<int> (op));
00518 return reinterpret_cast<octave_value_typeinfo::binary_class_op_fcn> (f);
00519 }
00520
00521 octave_value_typeinfo::binary_op_fcn
00522 octave_value_typeinfo::do_lookup_binary_op (octave_value::binary_op op,
00523 int t1, int t2)
00524 {
00525 void *f = binary_ops.checkelem (static_cast<int> (op), t1, t2);
00526 return reinterpret_cast<octave_value_typeinfo::binary_op_fcn> (f);
00527 }
00528
00529 octave_value_typeinfo::binary_class_op_fcn
00530 octave_value_typeinfo::do_lookup_binary_class_op (octave_value::compound_binary_op op)
00531 {
00532 void *f = compound_binary_class_ops.checkelem (static_cast<int> (op));
00533 return reinterpret_cast<octave_value_typeinfo::binary_class_op_fcn> (f);
00534 }
00535
00536 octave_value_typeinfo::binary_op_fcn
00537 octave_value_typeinfo::do_lookup_binary_op (octave_value::compound_binary_op op,
00538 int t1, int t2)
00539 {
00540 void *f = compound_binary_ops.checkelem (static_cast<int> (op), t1, t2);
00541 return reinterpret_cast<octave_value_typeinfo::binary_op_fcn> (f);
00542 }
00543
00544 octave_value_typeinfo::cat_op_fcn
00545 octave_value_typeinfo::do_lookup_cat_op (int t1, int t2)
00546 {
00547 void *f = cat_ops.checkelem (t1, t2);
00548 return reinterpret_cast<octave_value_typeinfo::cat_op_fcn> (f);
00549 }
00550
00551 octave_value_typeinfo::assign_op_fcn
00552 octave_value_typeinfo::do_lookup_assign_op (octave_value::assign_op op,
00553 int t_lhs, int t_rhs)
00554 {
00555 void *f = assign_ops.checkelem (static_cast<int> (op), t_lhs, t_rhs);
00556 return reinterpret_cast<octave_value_typeinfo::assign_op_fcn> (f);
00557 }
00558
00559 octave_value_typeinfo::assignany_op_fcn
00560 octave_value_typeinfo::do_lookup_assignany_op (octave_value::assign_op op,
00561 int t_lhs)
00562 {
00563 void *f = assignany_ops.checkelem (static_cast<int> (op), t_lhs);
00564 return reinterpret_cast<octave_value_typeinfo::assignany_op_fcn> (f);
00565 }
00566
00567 int
00568 octave_value_typeinfo::do_lookup_pref_assign_conv (int t_lhs, int t_rhs)
00569 {
00570 return pref_assign_conv.checkelem (t_lhs, t_rhs);
00571 }
00572
00573 octave_base_value::type_conv_fcn
00574 octave_value_typeinfo::do_lookup_type_conv_op (int t, int t_result)
00575 {
00576 void *f = type_conv_ops.checkelem (t, t_result);
00577 return reinterpret_cast<octave_base_value::type_conv_fcn> (f);
00578 }
00579
00580 octave_base_value::type_conv_fcn
00581 octave_value_typeinfo::do_lookup_widening_op (int t, int t_result)
00582 {
00583 void *f = widening_ops.checkelem (t, t_result);
00584 return reinterpret_cast<octave_base_value::type_conv_fcn> (f);
00585 }
00586
00587 string_vector
00588 octave_value_typeinfo::do_installed_type_names (void)
00589 {
00590 string_vector retval (num_types);
00591
00592 for (int i = 0; i < num_types; i++)
00593 retval(i) = types(i);
00594
00595 return retval;
00596 }
00597
00598 DEFUN (typeinfo, args, ,
00599 "-*- texinfo -*-\n\
00600 @deftypefn {Built-in Function} {} typeinfo ()\n\
00601 @deftypefnx {Built-in Function} {} typeinfo (@var{expr})\n\
00602 \n\
00603 Return the type of the expression @var{expr}, as a string. If\n\
00604 @var{expr} is omitted, return an cell array of strings containing all the\n\
00605 currently installed data types.\n\
00606 @end deftypefn")
00607 {
00608 octave_value retval;
00609
00610 int nargin = args.length ();
00611
00612 if (nargin == 0)
00613 retval = Cell (octave_value_typeinfo::installed_type_names ());
00614 else if (nargin == 1)
00615 retval = args(0).type_name ();
00616 else
00617 print_usage ();
00618
00619 return retval;
00620 }
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691