comparison libinterp/octave-value/ov-classdef.cc @ 15913:8521321604df classdef

Initial support for object array semantic. * libinterp/octave-value/ov-classdef.h (class cdef_object_array): New class. (cdef_object_rep::empty_clone, cdef_object_rep::copy, cdef_object_rep::make_array, cdef_object_rep::is_array, cdef_object_rep::array_value): New methods. (cdef_object::empty_clone, cdef_object::make_array, cdef_object::copy, cdef_object::is_array, cdef_object::array_value): Likewise. (cdef_object_base::empty_clone, cdef_object_base::make_array): Likewise. (handle_cdef_object::copy): Likewise. (value_cdef_object::copy): Likewise. (cdef_class::cdef_class_rep::copy, cdef_property::cdef_property_rep::copy, cdef_method::cdef_method_rep::copy, cdef_package::cdef_package_rep::copy): Likewise. (handle_cdef_object::handle_cdef_object): New copy constructor. (cdef_object::make_unique): New method. (cdef_object::subsasgn): Use it. (cdef_class::cdef_class_rep::meta): New member. (cdef_class::cdef_class_rep::cdef_class_rep): Initialize it. (cdef_class::cdef_class_rep::mark_as_meta_class, cdef_class::cdef_class_rep::is_meta): Use and manipulate it. (cdef_class::mark_as_meta_class, cdef_class::is_meta): Likewise. (cdef_class::cdef_class_rep::construct_object, cdef_class::cdef_class_rep::is_abstract, cdef_class::cdef_class_rep::is_sealed): New methods. (cdef_class::construct_object, cdef_class::is_abstract, cdef_class::is_sealed): Likewise. (cdef_class::cdef_class_rep::cdef_class_rep): New copy constructor. (cdef_property::cdef_property_rep::default_value): Remove member. (cdef_property::cdef_property_rep::get_value ()): Use "DefaultValue" slot. (cdef_property::cdef_property_rep::set_value (octave_value)): Remove method. (cdef_property::set_value (octave_value)): Likewise. (cdef_property::cdef_property_rep::cdef_property_rep): New copy constructor. (cdef_method::cdef_method_rep::cdef_method_rep): Likewise. (cdef_package::cdef_package_rep::cdef_package_rep): Likewise. (octave_classdef::empty_clone): Call cdef_object::empty_clone. (octave_classdef::undef_subsasgn): New method. (class cdef_property, class cdef_method, class cdef_package): Mark cdef_class as friend. * libinterp/octave-value/ov-classdef.cc: Include Array.cc. (make_class): Initialize "Abstract" property. Do not register classes with empty name. (make_meta_class): New static function. (make_method): Check whether function object is valid. (make_package): Do not register packages with empty name. (octave_classdef::undef_subsasgn): New method. (class cdef_object_array): New class. (cdef_class::cdef_class_rep::cdef_class_rep): Initialize meta. (cdef_class::cdef_class_rep::find_methods, cdef_class::cdef_class_rep::find_names): Use cdef_method::is_constructor instead of relying on the method name. (cdef_class::cdef_class_rep::construct_object): New method. (cdef_class::cdef_class_rep::construct): Use it. (install_classdef): Use make_meta_class. Create "Abstract" property for class meta.class.
author Michael Goffioul <michael.goffioul@gmail.com>
date Tue, 08 Jan 2013 12:34:30 -0500
parents b18b7e560236
children 837a4a9b5049
comparison
equal deleted inserted replaced
15911:b18b7e560236 15913:8521321604df
38 #include "pt-misc.h" 38 #include "pt-misc.h"
39 #include "pt-stmt.h" 39 #include "pt-stmt.h"
40 #include "pt-walk.h" 40 #include "pt-walk.h"
41 #include "symtab.h" 41 #include "symtab.h"
42 #include "toplev.h" 42 #include "toplev.h"
43
44 #include "Array.cc"
43 45
44 static std::map<std::string, cdef_class> all_classes; 46 static std::map<std::string, cdef_class> all_classes;
45 static std::map<std::string, cdef_package> all_packages; 47 static std::map<std::string, cdef_package> all_packages;
46 48
47 static void 49 static void
609 const std::list<cdef_class>& super_list = std::list<cdef_class> ()) 611 const std::list<cdef_class>& super_list = std::list<cdef_class> ())
610 { 612 {
611 cdef_class cls (name, super_list); 613 cdef_class cls (name, super_list);
612 614
613 cls.set_class (cdef_class::meta_class ()); 615 cls.set_class (cdef_class::meta_class ());
616 cls.put ("Abstract", false);
614 cls.put ("ConstructOnLoad", false); 617 cls.put ("ConstructOnLoad", false);
615 cls.put ("ContainingPackage", Matrix ()); 618 cls.put ("ContainingPackage", Matrix ());
616 cls.put ("Description", std::string ()); 619 cls.put ("Description", std::string ());
617 cls.put ("DetailedDescription", std::string ()); 620 cls.put ("DetailedDescription", std::string ());
618 cls.put ("Events", Cell ()); 621 cls.put ("Events", Cell ());
655 } 658 }
656 659
657 if (error_state) 660 if (error_state)
658 return cdef_class (); 661 return cdef_class ();
659 662
660 all_classes[name] = cls; 663 if (! name.empty ())
664 all_classes[name] = cls;
661 665
662 return cls; 666 return cls;
663 } 667 }
664 668
665 static cdef_class 669 static cdef_class
666 make_class (const std::string& name, const cdef_class& super) 670 make_class (const std::string& name, const cdef_class& super)
667 { 671 {
668 return make_class (name, std::list<cdef_class> (1, super)); 672 return make_class (name, std::list<cdef_class> (1, super));
673 }
674
675 static cdef_class
676 make_meta_class (const std::string& name, const cdef_class& super)
677 {
678 cdef_class cls = make_class (name, super);
679
680 cls.put ("Sealed", true);
681 cls.mark_as_meta_class ();
682
683 return cls;
669 } 684 }
670 685
671 static cdef_property 686 static cdef_property
672 make_property (const cdef_class& cls, const std::string& name, 687 make_property (const cdef_class& cls, const std::string& name,
673 const octave_value& get_method = Matrix (), 688 const octave_value& get_method = Matrix (),
674 const std::string& get_access = "public", 689 const std::string& get_access = "public",
675 const octave_value& set_method = Matrix (), 690 const octave_value& set_method = Matrix (),
676 const std::string& set_access = "public") 691 const std::string& set_access = "public")
677 { 692 {
678 // FIXME: what about default value?
679
680 cdef_property prop (name); 693 cdef_property prop (name);
681 694
682 prop.set_class (cdef_class::meta_property ()); 695 prop.set_class (cdef_class::meta_property ());
683 prop.put ("Description", std::string ()); 696 prop.put ("Description", std::string ());
684 prop.put ("DetailedDescription", std::string ()); 697 prop.put ("DetailedDescription", std::string ());
728 meth.put ("DetailedDescription", std::string ()); 741 meth.put ("DetailedDescription", std::string ());
729 meth.put ("Hidden", false); 742 meth.put ("Hidden", false);
730 meth.put ("Sealed", true); 743 meth.put ("Sealed", true);
731 meth.put ("Static", is_static); 744 meth.put ("Static", is_static);
732 745
733 make_function_of_class (cls, fcn); 746 if (fcn.is_defined ())
747 make_function_of_class (cls, fcn);
734 748
735 meth.set_function (fcn); 749 meth.set_function (fcn);
736 750
737 return meth; 751 return meth;
738 } 752 }
755 769
756 pack.set_class (cdef_class::meta_package ()); 770 pack.set_class (cdef_class::meta_package ());
757 pack.put ("Name", nm); 771 pack.put ("Name", nm);
758 pack.put ("ContainingPackage", to_ov (all_packages[parent])); 772 pack.put ("ContainingPackage", to_ov (all_packages[parent]));
759 773
760 all_packages[nm] = pack; 774 if (! nm.empty ())
775 all_packages[nm] = pack;
761 776
762 return pack; 777 return pack;
763 } 778 }
764 779
765 //---------------------------------------------------------------------------- 780 //----------------------------------------------------------------------------
802 octave_classdef::subsasgn (const std::string& type, 817 octave_classdef::subsasgn (const std::string& type,
803 const std::list<octave_value_list>& idx, 818 const std::list<octave_value_list>& idx,
804 const octave_value& rhs) 819 const octave_value& rhs)
805 { 820 {
806 return object.subsasgn (type, idx, rhs); 821 return object.subsasgn (type, idx, rhs);
822 }
823
824 octave_value
825 octave_classdef::undef_subsasgn (const std::string& type,
826 const std::list<octave_value_list>& idx,
827 const octave_value& rhs)
828 {
829 if (type.length () == 1 && type[0] == '(')
830 {
831 object = object.make_array ();
832
833 if (! error_state)
834 return subsasgn (type, idx, rhs);
835 }
836 else
837 return octave_base_value::undef_subsasgn (type, idx, rhs);
838
839 return octave_value ();
807 } 840 }
808 841
809 //---------------------------------------------------------------------------- 842 //----------------------------------------------------------------------------
810 843
811 class octave_classdef_proxy : public octave_function 844 class octave_classdef_proxy : public octave_function
1178 1211
1179 if (! error_state) 1212 if (! error_state)
1180 ctor_list[cls] = supcls_list; 1213 ctor_list[cls] = supcls_list;
1181 } 1214 }
1182 } 1215 }
1216
1217 octave_value_list
1218 cdef_object_array::subsref (const std::string& type,
1219 const std::list<octave_value_list>& idx,
1220 int /* nargout */, size_t& skip,
1221 const cdef_class& /* context */)
1222 {
1223 octave_value_list retval;
1224
1225 skip = 1;
1226
1227 switch (type[0])
1228 {
1229 case '(':
1230 {
1231 const octave_value_list& ival = idx.front ();
1232 bool is_scalar = true;
1233 Array<idx_vector> iv (dim_vector (1, ival.length ()));
1234
1235 for (int i = 0; ! error_state && i < ival.length (); i++)
1236 {
1237 iv(i) = ival(i).index_vector ();
1238 if (! error_state)
1239 is_scalar = is_scalar && iv(i).is_scalar ();
1240 }
1241
1242 if (! error_state)
1243 {
1244 Array<cdef_object> ires = array.index (iv);
1245
1246 if (! error_state)
1247 {
1248 if (is_scalar)
1249 retval(0) = to_ov (ires(0));
1250 else
1251 {
1252 cdef_object array_obj (new cdef_object_array (ires));
1253
1254 array_obj.set_class (get_class ());
1255
1256 retval(0) = to_ov (array_obj);
1257 }
1258 }
1259 }
1260 }
1261 break;
1262
1263 default:
1264 ::error ("can't perform indexing operation on array of %s objects",
1265 class_name ().c_str ());
1266 break;
1267 }
1268
1269 return retval;
1270 }
1271
1272 octave_value
1273 cdef_object_array::subsasgn (const std::string& type,
1274 const std::list<octave_value_list>& idx,
1275 const octave_value& rhs)
1276 {
1277 octave_value retval;
1278
1279 switch (type[0])
1280 {
1281 case '(':
1282 if (type.length () == 1)
1283 {
1284 cdef_object rhs_obj = to_cdef (rhs);
1285
1286 if (! error_state)
1287 {
1288 if (rhs_obj.get_class () == get_class ())
1289 {
1290 const octave_value_list& ival = idx.front ();
1291 bool is_scalar = true;
1292 Array<idx_vector> iv (dim_vector (1, ival.length ()));
1293
1294 for (int i = 0; ! error_state && i < ival.length (); i++)
1295 {
1296 iv(i) = ival(i).index_vector ();
1297 if (! error_state)
1298 is_scalar = is_scalar && iv(i).is_scalar ();
1299 }
1300
1301 if (! error_state)
1302 {
1303 Array<cdef_object> rhs_mat;
1304
1305 if (! rhs_obj.is_array ())
1306 {
1307 rhs_mat = Array<cdef_object> (dim_vector (1, 1));
1308 rhs_mat(0) = rhs_obj;
1309 }
1310 else
1311 rhs_mat = rhs_obj.array_value ();
1312
1313 if (! error_state)
1314 {
1315 octave_idx_type n = array.numel ();
1316
1317 array.assign (iv, rhs_mat, cdef_object ());
1318
1319 if (! error_state)
1320 {
1321 if (array.numel () > n)
1322 fill_empty_values ();
1323
1324 if (! error_state)
1325 {
1326 refcount++;
1327 retval = to_ov (cdef_object (this));
1328 }
1329 }
1330 }
1331 }
1332 }
1333 else
1334 ::error ("can't assign %s object into array of %s objects.",
1335 rhs_obj.class_name ().c_str (),
1336 class_name ().c_str ());
1337 }
1338 }
1339 else
1340 ::error ("can't perform indexing operation on array of %s objects",
1341 class_name ().c_str ());
1342 break;
1343
1344 default:
1345 ::error ("can't perform indexing operation on array of %s objects",
1346 class_name ().c_str ());
1347 break;
1348 }
1349
1350 return retval;
1351 }
1352
1353 void
1354 cdef_object_array::fill_empty_values (void)
1355 {
1356 cdef_class cls = get_class ();
1357
1358 if (! error_state)
1359 {
1360 cdef_object obj;
1361
1362 int n = array.numel ();
1363
1364 for (int i = 0; ! error_state && i < n; i++)
1365 {
1366 if (! array.xelem (i).ok ())
1367 {
1368 if (! obj.ok ())
1369 {
1370 obj = cls.construct_object (octave_value_list ());
1371
1372 if (! error_state)
1373 array.xelem (i) = obj;
1374 }
1375 else
1376 array.xelem (i) = obj.copy ();
1377 }
1378 }
1379 }
1380 }
1183 1381
1184 bool cdef_object_scalar::is_constructed_for (const cdef_class& cls) const 1382 bool cdef_object_scalar::is_constructed_for (const cdef_class& cls) const
1185 { 1383 {
1186 return (is_constructed () 1384 return (is_constructed ()
1187 || ctor_list.find (cls) == ctor_list.end ()); 1385 || ctor_list.find (cls) == ctor_list.end ());
1217 get_class ().get_name ().c_str ()); 1415 get_class ().get_name ().c_str ());
1218 } 1416 }
1219 1417
1220 cdef_class::cdef_class_rep::cdef_class_rep (const std::list<cdef_class>& superclasses) 1418 cdef_class::cdef_class_rep::cdef_class_rep (const std::list<cdef_class>& superclasses)
1221 : handle_cdef_object (), member_count (0), handle_class (false), 1419 : handle_cdef_object (), member_count (0), handle_class (false),
1222 object_count (0) 1420 object_count (0), meta (false)
1223 { 1421 {
1224 put ("SuperClasses", to_ov (superclasses)); 1422 put ("SuperClasses", to_ov (superclasses));
1225 implicit_ctor_list = superclasses; 1423 implicit_ctor_list = superclasses;
1226 } 1424 }
1227 1425
1472 { 1670 {
1473 load_all_methods (); 1671 load_all_methods ();
1474 1672
1475 method_const_iterator it; 1673 method_const_iterator it;
1476 1674
1477 std::string cls_name = get_base_name (get_name ());
1478
1479 for (it = method_map.begin (); it != method_map.end (); ++it) 1675 for (it = method_map.begin (); it != method_map.end (); ++it)
1480 { 1676 {
1481 std::string nm = it->second.get_name (); 1677 if (! it->second.is_constructor ())
1482 1678 {
1483 if (nm != cls_name) 1679 std::string nm = it->second.get_name ();
1484 { 1680
1485 if (meths.find (nm) == meths.end ()) 1681 if (meths.find (nm) == meths.end ())
1486 { 1682 {
1487 if (only_inherited) 1683 if (only_inherited)
1488 { 1684 {
1489 octave_value acc = it->second.get ("Access"); 1685 octave_value acc = it->second.get ("Access");
1622 cdef_class::cdef_class_rep::find_names (std::set<std::string>& names, 1818 cdef_class::cdef_class_rep::find_names (std::set<std::string>& names,
1623 bool all) 1819 bool all)
1624 { 1820 {
1625 load_all_methods (); 1821 load_all_methods ();
1626 1822
1627 std::string cls_name = get_base_name (get_name ());
1628
1629 for (method_const_iterator it = method_map.begin (); 1823 for (method_const_iterator it = method_map.begin ();
1630 ! error_state && it != method_map.end(); ++it) 1824 ! error_state && it != method_map.end(); ++it)
1631 { 1825 {
1632 std::string nm = it->second.get_name (); 1826 if (! it->second.is_constructor ())
1633 1827 {
1634 if (nm != cls_name) 1828 std::string nm = it->second.get_name ();
1635 { 1829
1636 if (! all) 1830 if (! all)
1637 { 1831 {
1638 octave_value acc = it->second.get ("Access"); 1832 octave_value acc = it->second.get ("Access");
1639 1833
1640 if (! acc.is_string() 1834 if (! acc.is_string()
1846 } 2040 }
1847 2041
1848 octave_value 2042 octave_value
1849 cdef_class::cdef_class_rep::construct (const octave_value_list& args) 2043 cdef_class::cdef_class_rep::construct (const octave_value_list& args)
1850 { 2044 {
1851 cdef_object_rep *r; 2045 cdef_object obj = construct_object (args);
1852 2046
1853 if (is_handle_class ()) 2047 if (! error_state && obj.ok ())
1854 r = new handle_cdef_object (); 2048 return to_ov (obj);
2049
2050 return octave_value ();
2051 }
2052
2053 cdef_object
2054 cdef_class::cdef_class_rep::construct_object (const octave_value_list& args)
2055 {
2056 if (! is_abstract ())
2057 {
2058 cdef_object obj;
2059
2060 if (is_meta_class ())
2061 {
2062 // This code path is only used to create empty meta objects
2063 // as filler for the empty values within a meta object array.
2064
2065 cdef_class this_cls = wrap ();
2066
2067 static cdef_object empty_class;
2068
2069 if (this_cls == cdef_class::meta_class ())
2070 {
2071 if (! empty_class.ok ())
2072 empty_class = make_class ("", std::list<cdef_class> ());
2073 obj = empty_class;
2074 }
2075 else if (this_cls == cdef_class::meta_property ())
2076 {
2077 static cdef_property empty_property;
2078
2079 if (! empty_class.ok ())
2080 empty_class = make_class ("", std::list<cdef_class> ());
2081 if (! empty_property.ok ())
2082 empty_property = make_property (empty_class, "");
2083 obj = empty_property;
2084 }
2085 else if (this_cls == cdef_class::meta_method ())
2086 {
2087 static cdef_method empty_method;
2088
2089 if (! empty_class.ok ())
2090 empty_class = make_class ("", std::list<cdef_class> ());
2091 if (! empty_method.ok ())
2092 empty_method = make_method (empty_class, "", octave_value ());
2093 obj = empty_method;
2094 }
2095 else if (this_cls == cdef_class::meta_package ())
2096 {
2097 static cdef_package empty_package;
2098
2099 if (! empty_package.ok ())
2100 empty_package = make_package ("");
2101 obj = empty_package;
2102 }
2103 else
2104 panic_impossible ();
2105
2106 return obj;
2107 }
2108 else
2109 {
2110 if (is_handle_class ())
2111 obj = cdef_object (new handle_cdef_object ());
2112 else
2113 obj = cdef_object (new value_cdef_object ());
2114 obj.set_class (wrap ());
2115
2116 initialize_object (obj);
2117
2118 if (! error_state)
2119 {
2120 run_constructor (obj, args);
2121
2122 if (! error_state)
2123 return obj;
2124 }
2125 }
2126 }
1855 else 2127 else
1856 r = new value_cdef_object (); 2128 error ("cannot instantiate object for abstract class `%s'",
1857 r->set_class (wrap ()); 2129 get_name ().c_str ());
1858 2130
1859 cdef_object obj (r); 2131 return cdef_object ();
1860
1861 initialize_object (obj);
1862
1863 if (! error_state)
1864 {
1865 run_constructor (obj, args);
1866
1867 if (! error_state)
1868 return to_ov (obj);
1869 }
1870
1871 return octave_value();
1872 } 2132 }
1873 2133
1874 static octave_value 2134 static octave_value
1875 compute_attribute_value (tree_classdef_attribute* t) 2135 compute_attribute_value (tree_classdef_attribute* t)
1876 { 2136 {
2441 { 2701 {
2442 octave_classdef::register_type (); 2702 octave_classdef::register_type ();
2443 2703
2444 /* bootstrap */ 2704 /* bootstrap */
2445 cdef_class handle = make_class ("handle"); 2705 cdef_class handle = make_class ("handle");
2446 cdef_class meta_class = cdef_class::_meta_class = make_class ("meta.class", handle); 2706 cdef_class meta_class = cdef_class::_meta_class = make_meta_class ("meta.class", handle);
2447 handle.set_class (meta_class); 2707 handle.set_class (meta_class);
2448 meta_class.set_class (meta_class); 2708 meta_class.set_class (meta_class);
2449 2709
2450 /* meta classes */ 2710 /* meta classes */
2451 cdef_class meta_property = cdef_class::_meta_property = make_class ("meta.property", handle); 2711 cdef_class meta_property = cdef_class::_meta_property = make_meta_class ("meta.property", handle);
2452 cdef_class meta_method = cdef_class::_meta_method = make_class ("meta.method", handle); 2712 cdef_class meta_method = cdef_class::_meta_method = make_meta_class ("meta.method", handle);
2453 cdef_class meta_package = cdef_class::_meta_package = make_class ("meta.package", handle); 2713 cdef_class meta_package = cdef_class::_meta_package = make_meta_class ("meta.package", handle);
2454 2714
2455 cdef_class meta_event = make_class ("meta.event", handle); 2715 cdef_class meta_event = make_meta_class ("meta.event", handle);
2456 cdef_class meta_dynproperty = make_class ("meta.dynamicproperty", handle); 2716 cdef_class meta_dynproperty = make_meta_class ("meta.dynamicproperty", handle);
2457
2458 /* meta classes are all sealed */
2459 meta_class.put ("Sealed", true);
2460 meta_property.put ("Sealed", true);
2461 meta_method.put ("Sealed", true);
2462 meta_package.put ("Sealed", true);
2463 meta_event.put ("Sealed", true);
2464 meta_dynproperty.put ("Sealed", true);
2465 2717
2466 /* meta.class properties */ 2718 /* meta.class properties */
2719 meta_class.install_property (make_attribute (meta_class, "Abstract"));
2467 meta_class.install_property (make_attribute (meta_class, "ConstructOnLoad")); 2720 meta_class.install_property (make_attribute (meta_class, "ConstructOnLoad"));
2468 meta_class.install_property (make_property (meta_class, "ContainingPackage")); 2721 meta_class.install_property (make_property (meta_class, "ContainingPackage"));
2469 meta_class.install_property (make_property (meta_class, "Description")); 2722 meta_class.install_property (make_property (meta_class, "Description"));
2470 meta_class.install_property (make_property (meta_class, "DetailedDescription")); 2723 meta_class.install_property (make_property (meta_class, "DetailedDescription"));
2471 meta_class.install_property (make_property (meta_class, "Events")); 2724 meta_class.install_property (make_property (meta_class, "Events"));