GNU Octave  3.8.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
ov-typeinfo.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1996-2013 John W. Eaton
4 
5 This file is part of Octave.
6 
7 Octave is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26 
27 #include "Array.h"
28 #include "singleton-cleanup.h"
29 
30 #include "defun.h"
31 #include "error.h"
32 #include "ov-typeinfo.h"
33 
34 const int
36 
39 
40 bool
42 {
43  bool retval = true;
44 
45  if (! instance)
46  {
48 
49  if (instance)
51  }
52 
53  if (! instance)
54  {
55  ::error ("unable to create value type info object!");
56 
57  retval = false;
58  }
59 
60  return retval;
61 }
62 
63 int
64 octave_value_typeinfo::register_type (const std::string& t_name,
65  const std::string& c_name,
66  const octave_value& val)
67 {
68  return (instance_ok ())
69  ? instance->do_register_type (t_name, c_name, val) : -1;
70 }
71 
72 bool
75 {
76  return (instance_ok ())
77  ? instance->do_register_unary_class_op (op, f) : false;
78 }
79 
80 bool
82  int t,
84 {
85  return (instance_ok ())
86  ? instance->do_register_unary_op (op, t, f) : false;
87 }
88 
89 bool
91  int t,
93 {
94  return (instance_ok ())
95  ? instance->do_register_non_const_unary_op (op, t, f) : false;
96 }
97 
98 bool
101 {
102  return (instance_ok ())
103  ? instance->do_register_binary_class_op (op, f) : false;
104 }
105 
106 bool
108  int t1, int t2,
110 {
111  return (instance_ok ())
112  ? instance->do_register_binary_op (op, t1, t2, f) : false;
113 }
114 
115 bool
118 {
119  return (instance_ok ())
120  ? instance->do_register_binary_class_op (op, f) : false;
121 }
122 
123 bool
125  int t1, int t2,
127 {
128  return (instance_ok ())
129  ? instance->do_register_binary_op (op, t1, t2, f) : false;
130 }
131 
132 bool
135 {
136  return (instance_ok ())
137  ? instance->do_register_cat_op (t1, t2, f) : false;
138 }
139 
140 bool
142  int t_lhs, int t_rhs,
144 {
145  return (instance_ok ())
146  ? instance->do_register_assign_op (op, t_lhs, t_rhs, f) : -1;
147 }
148 
149 bool
152 {
153  return (instance_ok ())
154  ? instance->do_register_assignany_op (op, t_lhs, f) : -1;
155 }
156 
157 bool
159  int t_result)
160 {
161  return (instance_ok ())
162  ? instance->do_register_pref_assign_conv (t_lhs, t_rhs, t_result)
163  : false;
164 }
165 
166 bool
169 {
170  return (instance_ok ())
171  ? instance->do_register_type_conv_op (t, t_result, f) : false;
172 }
173 
174 bool
177 {
178  return (instance_ok ())
179  ? instance->do_register_widening_op (t, t_result, f) : false;
180 }
181 
182 // FIXME: we should also store all class names and provide a
183 // way to list them (calling class with nargin == 0?).
184 
185 int
186 octave_value_typeinfo::do_register_type (const std::string& t_name,
187  const std::string& /* c_name */,
188  const octave_value& val)
189 {
190  int i = 0;
191 
192  for (i = 0; i < num_types; i++)
193  if (t_name == types (i))
194  return i;
195 
196  int len = types.length ();
197 
198  if (i == len)
199  {
200  len *= 2;
201 
202  types.resize (dim_vector (len, 1), std::string ());
203 
204  vals.resize (dim_vector (len, 1), octave_value ());
205 
207 
210 
212  (dim_vector (octave_value::num_binary_ops, len, len), 0);
213 
216 
217  cat_ops.resize (dim_vector (len, len), 0);
218 
220  (dim_vector (octave_value::num_assign_ops, len, len), 0);
221 
224 
225  pref_assign_conv.resize (dim_vector (len, len), -1);
226 
227  type_conv_ops.resize (dim_vector (len, len), 0);
228 
229  widening_ops.resize (dim_vector (len, len), 0);
230  }
231 
232  types (i) = t_name;
233 
234  vals (i) = val;
235 
236  num_types++;
237 
238  return i;
239 }
240 
241 bool
244 {
245  if (lookup_unary_class_op (op))
246  {
247  std::string op_name = octave_value::unary_op_as_string (op);
248 
249  warning ("duplicate unary operator '%s' for class dispatch",
250  op_name.c_str ());
251  }
252 
253  unary_class_ops.checkelem (static_cast<int> (op))
254  = reinterpret_cast<void *> (f);
255 
256  return false;
257 }
258 
259 bool
261  int t,
263 {
264  if (lookup_unary_op (op, t))
265  {
266  std::string op_name = octave_value::unary_op_as_string (op);
267  std::string type_name = types(t);
268 
269  warning ("duplicate unary operator '%s' for type '%s'",
270  op_name.c_str (), type_name.c_str ());
271  }
272 
273  unary_ops.checkelem (static_cast<int> (op), t) = reinterpret_cast<void *> (f);
274 
275  return false;
276 }
277 
278 bool
282 {
283  if (lookup_non_const_unary_op (op, t))
284  {
285  std::string op_name = octave_value::unary_op_as_string (op);
286  std::string type_name = types(t);
287 
288  warning ("duplicate unary operator '%s' for type '%s'",
289  op_name.c_str (), type_name.c_str ());
290  }
291 
292  non_const_unary_ops.checkelem (static_cast<int> (op), t)
293  = reinterpret_cast<void *> (f);
294 
295  return false;
296 }
297 
298 bool
301 {
302  if (lookup_binary_class_op (op))
303  {
304  std::string op_name = octave_value::binary_op_as_string (op);
305 
306  warning ("duplicate binary operator '%s' for class dispatch",
307  op_name.c_str ());
308  }
309 
310  binary_class_ops.checkelem (static_cast<int> (op))
311  = reinterpret_cast<void *> (f);
312 
313  return false;
314 }
315 
316 bool
318  int t1, int t2,
320 {
321  if (lookup_binary_op (op, t1, t2))
322  {
323  std::string op_name = octave_value::binary_op_as_string (op);
324  std::string t1_name = types(t1);
325  std::string t2_name = types(t2);
326 
327  warning ("duplicate binary operator '%s' for types '%s' and '%s'",
328  op_name.c_str (), t1_name.c_str (), t1_name.c_str ());
329  }
330 
331  binary_ops.checkelem (static_cast<int> (op), t1, t2)
332  = reinterpret_cast<void *> (f);
333 
334  return false;
335 }
336 
337 bool
340 {
341  if (lookup_binary_class_op (op))
342  {
343  std::string op_name = octave_value::binary_op_fcn_name (op);
344 
345  warning ("duplicate compound binary operator '%s' for class dispatch",
346  op_name.c_str ());
347  }
348 
349  compound_binary_class_ops.checkelem (static_cast<int> (op))
350  = reinterpret_cast<void *> (f);
351 
352  return false;
353 }
354 
355 bool
357  int t1, int t2,
359 {
360  if (lookup_binary_op (op, t1, t2))
361  {
362  std::string op_name = octave_value::binary_op_fcn_name (op);
363  std::string t1_name = types(t1);
364  std::string t2_name = types(t2);
365 
366  warning ("duplicate compound binary operator '%s' for types '%s' and '%s'",
367  op_name.c_str (), t1_name.c_str (), t1_name.c_str ());
368  }
369 
370  compound_binary_ops.checkelem (static_cast<int> (op), t1, t2)
371  = reinterpret_cast<void *> (f);
372 
373  return false;
374 }
375 
376 bool
379 {
380  if (lookup_cat_op (t1, t2))
381  {
382  std::string t1_name = types(t1);
383  std::string t2_name = types(t2);
384 
385  warning ("duplicate concatenation operator for types '%s' and '%s'",
386  t1_name.c_str (), t1_name.c_str ());
387  }
388 
389  cat_ops.checkelem (t1, t2) = reinterpret_cast<void *> (f);
390 
391  return false;
392 }
393 
394 bool
396  int t_lhs, int t_rhs,
398 {
399  if (lookup_assign_op (op, t_lhs, t_rhs))
400  {
401  std::string op_name = octave_value::assign_op_as_string (op);
402  std::string t_lhs_name = types(t_lhs);
403  std::string t_rhs_name = types(t_rhs);
404 
405  warning ("duplicate assignment operator '%s' for types '%s' and '%s'",
406  op_name.c_str (), t_lhs_name.c_str (), t_rhs_name.c_str ());
407  }
408 
409  assign_ops.checkelem (static_cast<int> (op), t_lhs, t_rhs)
410  = reinterpret_cast<void *> (f);
411 
412  return false;
413 }
414 
415 bool
418 {
419  if (lookup_assignany_op (op, t_lhs))
420  {
421  std::string op_name = octave_value::assign_op_as_string (op);
422  std::string t_lhs_name = types(t_lhs);
423 
424  warning ("duplicate assignment operator '%s' for types '%s'",
425  op_name.c_str (), t_lhs_name.c_str ());
426  }
427 
428  assignany_ops.checkelem (static_cast<int> (op), t_lhs)
429  = reinterpret_cast<void *> (f);
430 
431  return false;
432 }
433 
434 bool
436  int t_result)
437 {
438  if (lookup_pref_assign_conv (t_lhs, t_rhs) >= 0)
439  {
440  std::string t_lhs_name = types(t_lhs);
441  std::string t_rhs_name = types(t_rhs);
442 
443  warning ("overriding assignment conversion for types '%s' and '%s'",
444  t_lhs_name.c_str (), t_rhs_name.c_str ());
445  }
446 
447  pref_assign_conv.checkelem (t_lhs, t_rhs) = t_result;
448 
449  return false;
450 }
451 
452 bool
454  (int t, int t_result, octave_base_value::type_conv_fcn f)
455 {
456  if (lookup_type_conv_op (t, t_result))
457  {
458  std::string t_name = types(t);
459  std::string t_result_name = types(t_result);
460 
461  warning ("overriding type conversion op for '%s' to '%s'",
462  t_name.c_str (), t_result_name.c_str ());
463  }
464 
465  type_conv_ops.checkelem (t, t_result) = reinterpret_cast<void *> (f);
466 
467  return false;
468 }
469 
470 bool
472  (int t, int t_result, octave_base_value::type_conv_fcn f)
473 {
474  if (lookup_widening_op (t, t_result))
475  {
476  std::string t_name = types(t);
477  std::string t_result_name = types(t_result);
478 
479  warning ("overriding widening op for '%s' to '%s'",
480  t_name.c_str (), t_result_name.c_str ());
481  }
482 
483  widening_ops.checkelem (t, t_result) = reinterpret_cast<void *> (f);
484 
485  return false;
486 }
487 
490 {
491  octave_value retval;
492 
493  for (int i = 0; i < num_types; i++)
494  {
495  if (nm == types(i))
496  {
497  retval = vals(i);
498  retval.make_unique ();
499  break;
500  }
501  }
502 
503  return retval;
504 }
505 
508 {
509  void *f = unary_class_ops.checkelem (static_cast<int> (op));
510  return reinterpret_cast<octave_value_typeinfo::unary_class_op_fcn> (f);
511 }
512 
515 {
516  void *f = unary_ops.checkelem (static_cast<int> (op), t);
517  return reinterpret_cast<octave_value_typeinfo::unary_op_fcn> (f);
518 }
519 
523 {
524  void *f = non_const_unary_ops.checkelem (static_cast<int> (op), t);
525  return reinterpret_cast<octave_value_typeinfo::non_const_unary_op_fcn> (f);
526 }
527 
530 {
531  void *f = binary_class_ops.checkelem (static_cast<int> (op));
532  return reinterpret_cast<octave_value_typeinfo::binary_class_op_fcn> (f);
533 }
534 
537  int t1, int t2)
538 {
539  void *f = binary_ops.checkelem (static_cast<int> (op), t1, t2);
540  return reinterpret_cast<octave_value_typeinfo::binary_op_fcn> (f);
541 }
542 
545 {
546  void *f = compound_binary_class_ops.checkelem (static_cast<int> (op));
547  return reinterpret_cast<octave_value_typeinfo::binary_class_op_fcn> (f);
548 }
549 
552  int t1, int t2)
553 {
554  void *f = compound_binary_ops.checkelem (static_cast<int> (op), t1, t2);
555  return reinterpret_cast<octave_value_typeinfo::binary_op_fcn> (f);
556 }
557 
560 {
561  void *f = cat_ops.checkelem (t1, t2);
562  return reinterpret_cast<octave_value_typeinfo::cat_op_fcn> (f);
563 }
564 
567  int t_lhs, int t_rhs)
568 {
569  void *f = assign_ops.checkelem (static_cast<int> (op), t_lhs, t_rhs);
570  return reinterpret_cast<octave_value_typeinfo::assign_op_fcn> (f);
571 }
572 
575  int t_lhs)
576 {
577  void *f = assignany_ops.checkelem (static_cast<int> (op), t_lhs);
578  return reinterpret_cast<octave_value_typeinfo::assignany_op_fcn> (f);
579 }
580 
581 int
583 {
584  return pref_assign_conv.checkelem (t_lhs, t_rhs);
585 }
586 
589 {
590  void *f = type_conv_ops.checkelem (t, t_result);
591  return reinterpret_cast<octave_base_value::type_conv_fcn> (f);
592 }
593 
596 {
597  void *f = widening_ops.checkelem (t, t_result);
598  return reinterpret_cast<octave_base_value::type_conv_fcn> (f);
599 }
600 
603 {
604  string_vector retval (num_types);
605 
606  for (int i = 0; i < num_types; i++)
607  retval(i) = types(i);
608 
609  return retval;
610 }
611 
612 DEFUN (typeinfo, args, ,
613  "-*- texinfo -*-\n\
614 @deftypefn {Built-in Function} {} typeinfo ()\n\
615 @deftypefnx {Built-in Function} {} typeinfo (@var{expr})\n\
616 \n\
617 Return the type of the expression @var{expr}, as a string. If\n\
618 @var{expr} is omitted, return an cell array of strings containing all the\n\
619 currently installed data types.\n\
620 @end deftypefn")
621 {
622  octave_value retval;
623 
624  int nargin = args.length ();
625 
626  if (nargin == 0)
628  else if (nargin == 1)
629  retval = args(0).type_name ();
630  else
631  print_usage ();
632 
633  return retval;
634 }
635 
636 /*
637 %!assert (iscellstr (typeinfo ()))
638 
639 %!assert (typeinfo ({"cell"}), "cell")
640 
641 %!assert (typeinfo (1), "scalar")
642 %!assert (typeinfo (double (1)), "scalar")
643 %!assert (typeinfo (i), "complex scalar")
644 
645 %!assert (typeinfo ([1, 2]), "matrix")
646 %!assert (typeinfo (double ([1, 2])), "matrix")
647 %!assert (typeinfo (diag ([1, 2])), "diagonal matrix")
648 %!assert (typeinfo ([i, 2]), "complex matrix")
649 %!assert (typeinfo (diag ([i, 2])), "complex diagonal matrix")
650 
651 %!assert (typeinfo (1:2), "range")
652 
653 %!assert (typeinfo (false), "bool")
654 %!assert (typeinfo ([true, false]), "bool matrix")
655 
656 %!assert (typeinfo ("string"), "string")
657 %!assert (typeinfo ('string'), "sq_string")
658 
659 %!assert (typeinfo (int8 (1)), "int8 scalar")
660 %!assert (typeinfo (int16 (1)), "int16 scalar")
661 %!assert (typeinfo (int32 (1)), "int32 scalar")
662 %!assert (typeinfo (int64 (1)), "int64 scalar")
663 %!assert (typeinfo (uint8 (1)), "uint8 scalar")
664 %!assert (typeinfo (uint16 (1)), "uint16 scalar")
665 %!assert (typeinfo (uint32 (1)), "uint32 scalar")
666 %!assert (typeinfo (uint64 (1)), "uint64 scalar")
667 
668 %!assert (typeinfo (int8 ([1,2])), "int8 matrix")
669 %!assert (typeinfo (int16 ([1,2])), "int16 matrix")
670 %!assert (typeinfo (int32 ([1,2])), "int32 matrix")
671 %!assert (typeinfo (int64 ([1,2])), "int64 matrix")
672 %!assert (typeinfo (uint8 ([1,2])), "uint8 matrix")
673 %!assert (typeinfo (uint16 ([1,2])), "uint16 matrix")
674 %!assert (typeinfo (uint32 ([1,2])), "uint32 matrix")
675 %!assert (typeinfo (uint64 ([1,2])), "uint64 matrix")
676 
677 %!assert (typeinfo (sparse ([true, false])), "sparse bool matrix")
678 %!assert (typeinfo (logical (sparse (i * eye (10)))), "sparse bool matrix")
679 %!assert (typeinfo (sparse ([1,2])), "sparse matrix")
680 %!assert (typeinfo (sparse (eye (10))), "sparse matrix")
681 %!assert (typeinfo (sparse ([i,2])), "sparse complex matrix")
682 %!assert (typeinfo (sparse (i * eye (10))), "sparse complex matrix")
683 
684 %!test
685 %! s(2).a = 1;
686 %! assert (typeinfo (s), "struct");
687 
688 %!test
689 %! s.a = 1;
690 %! assert (typeinfo (s), "scalar struct");
691 
692 ## FIXME: This doesn't work as a test for comma-separated list
693 %!#test
694 %! clist = {1, 2, 3};
695 %! assert (typeinfo (clist{:}), "cs-list");
696 
697 %!assert (typeinfo (@sin), "function handle")
698 %!assert (typeinfo (@(x) x), "function handle")
699 
700 %!assert (typeinfo (inline ("x^2")), "inline function")
701 
702 %!assert (typeinfo (single (1)), "float scalar")
703 %!assert (typeinfo (single (i)), "float complex scalar")
704 %!assert (typeinfo (single ([1, 2])), "float matrix")
705 
706 %!assert (typeinfo (single (diag ([1, 2]))), "float diagonal matrix")
707 %!assert (typeinfo (diag (single ([1, 2]))), "float diagonal matrix")
708 %!assert (typeinfo (single (diag ([i, 2]))), "float complex diagonal matrix")
709 %!assert (typeinfo (diag (single ([i, 2]))), "float complex diagonal matrix")
710 
711 %!assert (typeinfo (eye(3)(:,[1 3 2])), "permutation matrix")
712 %!test
713 %! [l, u, p] = lu (rand (3));
714 %! assert (typeinfo (p), "permutation matrix");
715 
716 %!assert (typeinfo ([]), "null_matrix")
717 %!assert (typeinfo (""), "null_string")
718 %!assert (typeinfo (''), "null_sq_string")
719 
720 %!test
721 %! cvar = onCleanup (@() "");
722 %! assert (typeinfo (cvar), "onCleanup");
723 
724 %!testif HAVE_JAVA
725 %! x = javaObject ("java.lang.StringBuffer");
726 %! assert (typeinfo (x), "octave_java");
727 
728 ## Test input validation
729 %!error typeinfo ("foo", 1)
730 */