Mercurial > octave-nkf
comparison libinterp/octave-value/ov-classdef.cc @ 20595:c1a6c31ac29a
eliminate more simple uses of error_state
* ov-classdef.cc: Eliminate simple uses of error_state.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Tue, 06 Oct 2015 00:20:02 -0400 |
parents | dd6345fd8a97 |
children | 729a85dafba8 |
comparison
equal
deleted
inserted
replaced
20594:a05a0432dff4 | 20595:c1a6c31ac29a |
---|---|
98 make_function_of_class (const std::string& class_name, | 98 make_function_of_class (const std::string& class_name, |
99 const octave_value& fcn) | 99 const octave_value& fcn) |
100 { | 100 { |
101 octave_function *of = fcn.function_value (); | 101 octave_function *of = fcn.function_value (); |
102 | 102 |
103 if (! error_state) | 103 of->stash_dispatch_class (class_name); |
104 { | 104 |
105 of->stash_dispatch_class (class_name); | 105 octave_user_function *uf = of->user_function_value (true); |
106 | 106 |
107 octave_user_function *uf = of->user_function_value (true); | 107 if (uf) |
108 | 108 { |
109 if (! error_state && uf) | 109 if (get_base_name (class_name) == uf->name ()) |
110 { | 110 { |
111 if (get_base_name (class_name) == uf->name ()) | 111 uf->mark_as_class_constructor (); |
112 { | 112 uf->mark_as_classdef_constructor (); |
113 uf->mark_as_class_constructor (); | 113 } |
114 uf->mark_as_classdef_constructor (); | 114 else |
115 } | 115 uf->mark_as_class_method (); |
116 else | |
117 uf->mark_as_class_method (); | |
118 } | |
119 } | 116 } |
120 } | 117 } |
121 | 118 |
122 static void | 119 static void |
123 make_function_of_class (const cdef_class& cls, const octave_value& fcn) | 120 make_function_of_class (const cdef_class& cls, const octave_value& fcn) |
180 return lookup_class (ov.string_value ()); | 177 return lookup_class (ov.string_value ()); |
181 else | 178 else |
182 { | 179 { |
183 cdef_class cls (to_cdef (ov)); | 180 cdef_class cls (to_cdef (ov)); |
184 | 181 |
185 if (! error_state) | 182 return lookup_class (cls); |
186 return lookup_class (cls); | |
187 } | 183 } |
188 | 184 |
189 return cdef_class (); | 185 return cdef_class (); |
190 } | 186 } |
191 | 187 |
233 retval = true; | 229 retval = true; |
234 else if (max_depth != 0) | 230 else if (max_depth != 0) |
235 { | 231 { |
236 Cell c = clsb.get ("SuperClasses").cell_value (); | 232 Cell c = clsb.get ("SuperClasses").cell_value (); |
237 | 233 |
238 for (int i = 0; ! error_state && ! retval && i < c.numel (); i++) | 234 for (int i = 0; ! retval && i < c.numel (); i++) |
239 { | 235 { |
240 cdef_class cls = lookup_class (c(i)); | 236 cdef_class cls = lookup_class (c(i)); |
241 | 237 |
242 if (! error_state) | 238 retval = is_superclass (clsa, cls, true, |
243 retval = is_superclass (clsa, cls, true, | 239 max_depth < 0 ? max_depth : max_depth-1); |
244 max_depth < 0 ? max_depth : max_depth-1); | |
245 } | 240 } |
246 } | 241 } |
247 | 242 |
248 return retval; | 243 return retval; |
249 } | 244 } |
285 || fcn->is_anonymous_function_of_class () | 280 || fcn->is_anonymous_function_of_class () |
286 || (fcn->is_private_function () | 281 || (fcn->is_private_function () |
287 && ! fcn->dispatch_class ().empty ()))) | 282 && ! fcn->dispatch_class ().empty ()))) |
288 { | 283 { |
289 cls = lookup_class (fcn->dispatch_class ()); | 284 cls = lookup_class (fcn->dispatch_class ()); |
290 if (! error_state) | 285 |
291 { | 286 name = fcn->name (); |
292 name = fcn->name (); | 287 in_constructor = fcn->is_classdef_constructor (); |
293 in_constructor = fcn->is_classdef_constructor (); | |
294 } | |
295 } | 288 } |
296 | 289 |
297 return cls; | 290 return cls; |
298 } | 291 } |
299 | 292 |
330 cdef_class ctx = get_class_context (); | 323 cdef_class ctx = get_class_context (); |
331 | 324 |
332 // The access is private or protected, this requires a | 325 // The access is private or protected, this requires a |
333 // valid class context. | 326 // valid class context. |
334 | 327 |
335 if (! error_state && ctx.ok ()) | 328 if (ctx.ok ()) |
336 { | 329 { |
337 if (acc_s == "private") | 330 if (acc_s == "private") |
338 return (ctx == cls); | 331 return (ctx == cls); |
339 else if (acc_s == "protected") | 332 else if (acc_s == "protected") |
340 { | 333 { |
388 | 381 |
389 cdef_class ctx = get_class_context (); | 382 cdef_class ctx = get_class_context (); |
390 | 383 |
391 // At this point, a class context is always required. | 384 // At this point, a class context is always required. |
392 | 385 |
393 if (! error_state && ctx.ok ()) | 386 if (ctx.ok ()) |
394 { | 387 { |
395 if (ctx == cls) | 388 if (ctx == cls) |
396 return true; | 389 return true; |
397 | 390 |
398 for (int i = 0; ! error_state && i < acc.numel (); i++) | 391 for (int i = 0; i < acc.numel (); i++) |
399 { | 392 { |
400 cdef_class acc_cls (to_cdef (acc_c(i))); | 393 cdef_class acc_cls (to_cdef (acc_c(i))); |
401 | 394 |
402 if (! error_state) | 395 if (is_superclass (acc_cls, ctx)) |
403 { | 396 return true; |
404 if (is_superclass (acc_cls, ctx)) | |
405 return true; | |
406 } | |
407 } | 397 } |
408 } | 398 } |
409 } | 399 } |
410 else | 400 else |
411 error ("invalid property/method access in class `%s'", | 401 error ("invalid property/method access in class `%s'", |
581 error ("fevalStatic: method not found: %s", meth_name.c_str ()); | 571 error ("fevalStatic: method not found: %s", meth_name.c_str ()); |
582 } | 572 } |
583 else | 573 else |
584 error ("fevalStatic: invalid method name, expected a string value"); | 574 error ("fevalStatic: invalid method name, expected a string value"); |
585 } | 575 } |
586 error ("fevalStatic: invalid object, expected a meta.class object"); | 576 else |
577 error ("fevalStatic: invalid object, expected a meta.class object"); | |
587 } | 578 } |
588 else | 579 else |
589 error ("fevalStatic: invalid arguments"); | 580 error ("fevalStatic: invalid arguments"); |
590 | 581 |
591 return retval; | 582 return retval; |
747 if (has_handle_class) | 738 if (has_handle_class) |
748 cls.mark_as_handle_class (); | 739 cls.mark_as_handle_class (); |
749 } | 740 } |
750 } | 741 } |
751 | 742 |
752 if (error_state) | |
753 return cdef_class (); | |
754 | |
755 if (! name.empty ()) | 743 if (! name.empty ()) |
756 cdef_manager::register_class (cls); | 744 cdef_manager::register_class (cls); |
757 | 745 |
758 return cls; | 746 return cls; |
759 } | 747 } |
907 { | 895 { |
908 octave_value_list args; | 896 octave_value_list args; |
909 | 897 |
910 args(1) = make_idx_args (type, idx, "subsref"); | 898 args(1) = make_idx_args (type, idx, "subsref"); |
911 | 899 |
912 if (! error_state) | 900 count++; |
913 { | 901 args(0) = octave_value (this); |
914 count++; | 902 |
915 args(0) = octave_value (this); | 903 retval = meth.execute (args, nargout, true, "subsref"); |
916 | |
917 retval = meth.execute (args, nargout, true, "subsref"); | |
918 } | |
919 | 904 |
920 return retval; | 905 return retval; |
921 } | 906 } |
922 } | 907 } |
923 | 908 |
924 // At this point, the default subsref mechanism must be used. | 909 // At this point, the default subsref mechanism must be used. |
925 | 910 |
926 retval = object.subsref (type, idx, nargout, skip, cdef_class ()); | 911 retval = object.subsref (type, idx, nargout, skip, cdef_class ()); |
927 | 912 |
928 if (! error_state) | 913 if (type.length () > skip && idx.size () > skip) |
929 { | 914 retval = retval(0).next_subsref (nargout, type, idx, skip); |
930 if (type.length () > skip && idx.size () > skip) | |
931 retval = retval(0).next_subsref (nargout, type, idx, skip); | |
932 } | |
933 | 915 |
934 return retval; | 916 return retval; |
935 } | 917 } |
936 | 918 |
937 octave_value | 919 octave_value |
947 // purpose (not sure we should even implement this) and any overload subsref | 929 // purpose (not sure we should even implement this) and any overload subsref |
948 // should not be called. | 930 // should not be called. |
949 | 931 |
950 retval = object.subsref (type, idx, 1, skip, cdef_class (), auto_add); | 932 retval = object.subsref (type, idx, 1, skip, cdef_class (), auto_add); |
951 | 933 |
952 if (! error_state) | 934 if (type.length () > skip && idx.size () > skip) |
953 { | 935 retval = retval(0).next_subsref (1, type, idx, skip); |
954 if (type.length () > skip && idx.size () > skip) | |
955 retval = retval(0).next_subsref (1, type, idx, skip); | |
956 } | |
957 | 936 |
958 return retval.length () > 0 ? retval(0) : octave_value (); | 937 return retval.length () > 0 ? retval(0) : octave_value (); |
959 } | 938 } |
960 | 939 |
961 octave_value | 940 octave_value |
975 { | 954 { |
976 octave_value_list args; | 955 octave_value_list args; |
977 | 956 |
978 args(1) = make_idx_args (type, idx, "subsasgn"); | 957 args(1) = make_idx_args (type, idx, "subsasgn"); |
979 | 958 |
980 if (! error_state) | 959 count++; |
981 { | 960 args(0) = octave_value (this); |
982 count++; | 961 args(2) = rhs; |
983 args(0) = octave_value (this); | 962 |
984 args(2) = rhs; | 963 octave_value_list retlist; |
985 | 964 |
986 octave_value_list retlist; | 965 retlist = meth.execute (args, 1, true, "subsasgn"); |
987 | 966 |
988 retlist = meth.execute (args, 1, true, "subsasgn"); | 967 if (retlist.length () > 0) |
989 | 968 retval = retlist(0); |
990 if (! error_state) | 969 else |
991 { | 970 error ("overloaded method `subsasgn' did not return any value"); |
992 if (retlist.length () > 0) | 971 } |
993 retval = retlist(0); | 972 } |
994 else | 973 |
995 error ("overloaded method `subsasgn' did not return any value"); | 974 if (! retval.is_defined ()) |
996 } | |
997 } | |
998 } | |
999 } | |
1000 | |
1001 if (! error_state && ! retval.is_defined ()) | |
1002 retval = object.subsasgn (type, idx, rhs); | 975 retval = object.subsasgn (type, idx, rhs); |
1003 | 976 |
1004 return retval; | 977 return retval; |
1005 } | 978 } |
1006 | 979 |
1011 { | 984 { |
1012 if (type.length () == 1 && type[0] == '(') | 985 if (type.length () == 1 && type[0] == '(') |
1013 { | 986 { |
1014 object = object.make_array (); | 987 object = object.make_array (); |
1015 | 988 |
1016 if (! error_state) | 989 return subsasgn (type, idx, rhs); |
1017 return subsasgn (type, idx, rhs); | |
1018 } | 990 } |
1019 else | 991 else |
1020 return octave_base_value::undef_subsasgn (type, idx, rhs); | 992 return octave_base_value::undef_subsasgn (type, idx, rhs); |
1021 | 993 |
1022 return octave_value (); | 994 return octave_value (); |
1199 default: | 1171 default: |
1200 retval = do_multi_index_op (1, octave_value_list ()); | 1172 retval = do_multi_index_op (1, octave_value_list ()); |
1201 break; | 1173 break; |
1202 } | 1174 } |
1203 | 1175 |
1204 if (! error_state) | 1176 if (type.length () > skip && idx.size () > skip |
1205 { | 1177 && retval.length () > 0) |
1206 if (type.length () > skip && idx.size () > skip | 1178 retval = retval(0).next_subsref (nargout, type, idx, skip); |
1207 && retval.length () > 0) | |
1208 retval = retval(0).next_subsref (nargout, type, idx, skip); | |
1209 } | |
1210 | 1179 |
1211 return retval; | 1180 return retval; |
1212 } | 1181 } |
1213 | 1182 |
1214 octave_value | 1183 octave_value |
1238 std::string mname = args(0).string_value (); | 1207 std::string mname = args(0).string_value (); |
1239 std::string cname = args(1).string_value (); | 1208 std::string cname = args(1).string_value (); |
1240 | 1209 |
1241 cdef_class cls = lookup_class (cname); | 1210 cdef_class cls = lookup_class (cname); |
1242 | 1211 |
1243 if (! error_state) | 1212 if (in_constructor) |
1244 { | 1213 { |
1245 if (in_constructor) | 1214 if (is_direct_superclass (cls, ctx)) |
1246 { | 1215 { |
1247 if (is_direct_superclass (cls, ctx)) | 1216 if (is_constructed_object (mname)) |
1248 { | 1217 { |
1249 if (is_constructed_object (mname)) | 1218 octave_value sym = symbol_table::varval (mname); |
1250 { | 1219 |
1251 octave_value sym = symbol_table::varval (mname); | 1220 cls.run_constructor (to_cdef_ref (sym), idx); |
1252 | 1221 |
1253 cls.run_constructor (to_cdef_ref (sym), idx); | 1222 retval(0) = sym; |
1254 | |
1255 retval(0) = sym; | |
1256 } | |
1257 else | |
1258 error ("cannot call superclass constructor with " | |
1259 "variable `%s'", mname.c_str ()); | |
1260 } | 1223 } |
1261 else | 1224 else |
1262 error ("`%s' is not a direct superclass of `%s'", | 1225 error ("cannot call superclass constructor with " |
1226 "variable `%s'", mname.c_str ()); | |
1227 } | |
1228 else | |
1229 error ("`%s' is not a direct superclass of `%s'", | |
1230 cname.c_str (), ctx.get_name ().c_str ()); | |
1231 } | |
1232 else | |
1233 { | |
1234 if (mname == meth_name) | |
1235 { | |
1236 if (is_strict_superclass (cls, ctx)) | |
1237 { | |
1238 // I see 2 possible implementations here: | |
1239 // 1) use cdef_object::subsref with a different class | |
1240 // context; this avoids duplicating code, but | |
1241 // assumes the object is always the first argument | |
1242 // 2) lookup the method manually and call | |
1243 // cdef_method::execute; this duplicates part of | |
1244 // logic in cdef_object::subsref, but avoid the | |
1245 // assumption of 1) | |
1246 // Not being sure about the assumption of 1), I | |
1247 // go with option 2) for the time being. | |
1248 | |
1249 cdef_method meth = cls.find_method (meth_name, false); | |
1250 | |
1251 if (meth.ok ()) | |
1252 retval = meth.execute (idx, nargout, true, | |
1253 meth_name); | |
1254 else | |
1255 error ("no method `%s' found in superclass `%s'", | |
1256 meth_name.c_str (), cname.c_str ()); | |
1257 } | |
1258 else | |
1259 error ("`%s' is not a superclass of `%s'", | |
1263 cname.c_str (), ctx.get_name ().c_str ()); | 1260 cname.c_str (), ctx.get_name ().c_str ()); |
1264 } | 1261 } |
1265 else | 1262 else |
1266 { | 1263 error ("method name mismatch (`%s' != `%s')", |
1267 if (mname == meth_name) | 1264 mname.c_str (), meth_name.c_str ()); |
1268 { | |
1269 if (is_strict_superclass (cls, ctx)) | |
1270 { | |
1271 // I see 2 possible implementations here: | |
1272 // 1) use cdef_object::subsref with a different class | |
1273 // context; this avoids duplicating code, but | |
1274 // assumes the object is always the first argument | |
1275 // 2) lookup the method manually and call | |
1276 // cdef_method::execute; this duplicates part of | |
1277 // logic in cdef_object::subsref, but avoid the | |
1278 // assumption of 1) | |
1279 // Not being sure about the assumption of 1), I | |
1280 // go with option 2) for the time being. | |
1281 | |
1282 cdef_method meth = cls.find_method (meth_name, false); | |
1283 | |
1284 if (meth.ok ()) | |
1285 retval = meth.execute (idx, nargout, true, | |
1286 meth_name); | |
1287 else | |
1288 error ("no method `%s' found in superclass `%s'", | |
1289 meth_name.c_str (), cname.c_str ()); | |
1290 } | |
1291 else | |
1292 error ("`%s' is not a superclass of `%s'", | |
1293 cname.c_str (), ctx.get_name ().c_str ()); | |
1294 } | |
1295 else | |
1296 error ("method name mismatch (`%s' != `%s')", | |
1297 mname.c_str (), meth_name.c_str ()); | |
1298 } | |
1299 } | 1265 } |
1300 } | 1266 } |
1301 else if (! error_state) | 1267 else if (! error_state) |
1302 error ("superclass calls can only occur in methods or constructors"); | 1268 error ("superclass calls can only occur in methods or constructors"); |
1303 | 1269 |
1360 Array<cdef_object> a_obj = array_value (); | 1326 Array<cdef_object> a_obj = array_value (); |
1361 | 1327 |
1362 Cell cvalue (a_obj.dims ()); | 1328 Cell cvalue (a_obj.dims ()); |
1363 | 1329 |
1364 for (octave_idx_type i = 0; i < a_obj.numel (); i++) | 1330 for (octave_idx_type i = 0; i < a_obj.numel (); i++) |
1365 { | 1331 cvalue (i) = it->second.get_value (a_obj(i), false); |
1366 cvalue (i) = it->second.get_value (a_obj(i), false); | 1332 |
1367 | 1333 retval.setfield (it->first, cvalue); |
1368 if (error_state) | |
1369 break; | |
1370 } | |
1371 | |
1372 if (! error_state) | |
1373 retval.setfield (it->first, cvalue); | |
1374 } | 1334 } |
1375 else | 1335 else |
1376 { | 1336 { |
1377 Cell cvalue (dim_vector (1, 1), | 1337 Cell cvalue (dim_vector (1, 1), |
1378 it->second.get_value (*this, false)); | 1338 it->second.get_value (*this, false)); |
1379 | 1339 |
1380 if (! error_state) | 1340 retval.setfield (it->first, cvalue); |
1381 retval.setfield (it->first, cvalue); | |
1382 } | 1341 } |
1383 | |
1384 if (error_state) | |
1385 break; | |
1386 } | 1342 } |
1387 } | 1343 } |
1388 | 1344 |
1389 return retval; | 1345 return retval; |
1390 } | 1346 } |
1448 retval = meth.execute (cdef_object (this), args, _nargout, | 1404 retval = meth.execute (cdef_object (this), args, _nargout, |
1449 true, "subsref"); | 1405 true, "subsref"); |
1450 } | 1406 } |
1451 } | 1407 } |
1452 | 1408 |
1453 if (skip == 0 && ! error_state) | 1409 if (skip == 0) |
1454 { | 1410 { |
1455 cdef_property prop = cls.find_property (name); | 1411 cdef_property prop = cls.find_property (name); |
1456 | 1412 |
1457 if (prop.ok ()) | 1413 if (prop.ok ()) |
1458 { | 1414 { |
1519 { | 1475 { |
1520 case '.': | 1476 case '.': |
1521 { | 1477 { |
1522 std::string name = (idx.front ())(0).string_value (); | 1478 std::string name = (idx.front ())(0).string_value (); |
1523 | 1479 |
1524 if (! error_state) | 1480 cdef_property prop = cls.find_property (name); |
1481 | |
1482 if (prop.ok ()) | |
1525 { | 1483 { |
1526 cdef_property prop = cls.find_property (name); | 1484 if (prop.is_constant ()) |
1527 | 1485 error ("subsasgn: cannot assign constant property: %s", |
1528 if (prop.ok ()) | 1486 name.c_str ()); |
1487 else | |
1529 { | 1488 { |
1530 if (prop.is_constant ()) | 1489 refcount++; |
1531 error ("subsasgn: cannot assign constant property: %s", | 1490 |
1532 name.c_str ()); | 1491 cdef_object obj (this); |
1492 | |
1493 if (type.length () == 1) | |
1494 { | |
1495 prop.set_value (obj, rhs, true, "subsasgn"); | |
1496 | |
1497 retval = to_ov (obj); | |
1498 } | |
1533 else | 1499 else |
1534 { | 1500 { |
1535 refcount++; | 1501 octave_value val = |
1536 | 1502 prop.get_value (obj, true, "subsasgn"); |
1537 cdef_object obj (this); | 1503 |
1538 | 1504 std::list<octave_value_list> args (idx); |
1539 if (type.length () == 1) | 1505 |
1540 { | 1506 args.erase (args.begin ()); |
1541 prop.set_value (obj, rhs, true, "subsasgn"); | 1507 |
1542 | 1508 val = val.assign (octave_value::op_asn_eq, |
1543 if (! error_state) | 1509 type.substr (1), args, rhs); |
1544 retval = to_ov (obj); | 1510 |
1545 } | 1511 if (val.class_name () != "object" |
1546 else | 1512 || ! to_cdef (val).is_handle_object ()) |
1547 { | 1513 prop.set_value (obj, val, true, "subsasgn"); |
1548 octave_value val = | 1514 |
1549 prop.get_value (obj, true, "subsasgn"); | 1515 retval = to_ov (obj); |
1550 | |
1551 if (! error_state) | |
1552 { | |
1553 std::list<octave_value_list> args (idx); | |
1554 | |
1555 args.erase (args.begin ()); | |
1556 | |
1557 val = val.assign (octave_value::op_asn_eq, | |
1558 type.substr (1), args, rhs); | |
1559 | |
1560 if (! error_state) | |
1561 { | |
1562 if (val.class_name () != "object" | |
1563 || ! to_cdef (val).is_handle_object ()) | |
1564 prop.set_value (obj, val, true, "subsasgn"); | |
1565 | |
1566 if (! error_state) | |
1567 retval = to_ov (obj); | |
1568 } | |
1569 } | |
1570 } | |
1571 } | 1516 } |
1572 } | 1517 } |
1573 else | |
1574 error ("subsasgn: unknown property: %s", name.c_str ()); | |
1575 } | 1518 } |
1519 else | |
1520 error ("subsasgn: unknown property: %s", name.c_str ()); | |
1576 } | 1521 } |
1577 break; | 1522 break; |
1578 | 1523 |
1579 case '(': | 1524 case '(': |
1580 { | 1525 { |
1588 | 1533 |
1589 new_obj.set_class (get_class ()); | 1534 new_obj.set_class (get_class ()); |
1590 | 1535 |
1591 octave_value tmp = new_obj.subsasgn (type, idx, rhs); | 1536 octave_value tmp = new_obj.subsasgn (type, idx, rhs); |
1592 | 1537 |
1593 if (! error_state) | 1538 retval = tmp; |
1594 retval = tmp; | |
1595 } | 1539 } |
1596 break; | 1540 break; |
1597 | 1541 |
1598 default: | 1542 default: |
1599 error ("subsasgn: object cannot be index with `%c'", type[0]); | 1543 error ("subsasgn: object cannot be index with `%c'", type[0]); |
1608 { | 1552 { |
1609 std::string cls_name = cls.get_name (); | 1553 std::string cls_name = cls.get_name (); |
1610 | 1554 |
1611 Cell supcls = cls.get ("SuperClasses").cell_value (); | 1555 Cell supcls = cls.get ("SuperClasses").cell_value (); |
1612 | 1556 |
1613 if (! error_state) | 1557 std::list<cdef_class> supcls_list = lookup_classes (supcls); |
1614 { | 1558 |
1615 std::list<cdef_class> supcls_list = lookup_classes (supcls); | 1559 ctor_list[cls] = supcls_list; |
1616 | |
1617 if (! error_state) | |
1618 ctor_list[cls] = supcls_list; | |
1619 } | |
1620 } | 1560 } |
1621 | 1561 |
1622 octave_value_list | 1562 octave_value_list |
1623 cdef_object_array::subsref (const std::string& type, | 1563 cdef_object_array::subsref (const std::string& type, |
1624 const std::list<octave_value_list>& idx, | 1564 const std::list<octave_value_list>& idx, |
1643 } | 1583 } |
1644 | 1584 |
1645 bool is_scalar = true; | 1585 bool is_scalar = true; |
1646 Array<idx_vector> iv (dim_vector (1, ival.length ())); | 1586 Array<idx_vector> iv (dim_vector (1, ival.length ())); |
1647 | 1587 |
1648 for (int i = 0; ! error_state && i < ival.length (); i++) | 1588 for (int i = 0; i < ival.length (); i++) |
1649 { | 1589 { |
1650 try | 1590 try |
1651 { | 1591 { |
1652 iv(i) = ival(i).index_vector (); | 1592 iv(i) = ival(i).index_vector (); |
1653 } | 1593 } |
1655 { | 1595 { |
1656 // Rethrow to allow more info to be reported later. | 1596 // Rethrow to allow more info to be reported later. |
1657 e.set_pos_if_unset (ival.length (), i+1); | 1597 e.set_pos_if_unset (ival.length (), i+1); |
1658 throw; | 1598 throw; |
1659 } | 1599 } |
1660 if (! error_state) | 1600 |
1661 is_scalar = is_scalar && iv(i).is_scalar (); | 1601 is_scalar = is_scalar && iv(i).is_scalar (); |
1662 } | 1602 } |
1663 | 1603 |
1664 if (! error_state) | 1604 Array<cdef_object> ires = array.index (iv, auto_add); |
1605 | |
1606 // If resizing is enabled (auto_add = true), it's possible | |
1607 // indexing was out-of-bound and the result array contains | |
1608 // invalid cdef_objects. | |
1609 | |
1610 if (auto_add) | |
1611 fill_empty_values (ires); | |
1612 | |
1613 if (is_scalar) | |
1614 retval(0) = to_ov (ires(0)); | |
1615 else | |
1665 { | 1616 { |
1666 Array<cdef_object> ires = array.index (iv, auto_add); | 1617 cdef_object array_obj (new cdef_object_array (ires)); |
1667 | 1618 |
1668 if (! error_state) | 1619 array_obj.set_class (get_class ()); |
1669 { | 1620 |
1670 // If resizing is enabled (auto_add = true), it's possible | 1621 retval(0) = to_ov (array_obj); |
1671 // indexing was out-of-bound and the result array contains | |
1672 // invalid cdef_objects. | |
1673 | |
1674 if (auto_add) | |
1675 fill_empty_values (ires); | |
1676 | |
1677 if (is_scalar) | |
1678 retval(0) = to_ov (ires(0)); | |
1679 else | |
1680 { | |
1681 cdef_object array_obj (new cdef_object_array (ires)); | |
1682 | |
1683 array_obj.set_class (get_class ()); | |
1684 | |
1685 retval(0) = to_ov (array_obj); | |
1686 } | |
1687 } | |
1688 } | 1622 } |
1689 } | 1623 } |
1690 break; | 1624 break; |
1691 | 1625 |
1692 case '.': | 1626 case '.': |
1703 for (octave_idx_type i = 0; i < n; i++) | 1637 for (octave_idx_type i = 0; i < n; i++) |
1704 { | 1638 { |
1705 octave_value_list r = array(i).subsref (type, idx, 1, dummy_skip, | 1639 octave_value_list r = array(i).subsref (type, idx, 1, dummy_skip, |
1706 dummy_cls); | 1640 dummy_cls); |
1707 | 1641 |
1708 if (! error_state) | 1642 if (r.length () > 0) |
1709 { | 1643 c(i) = r(0); |
1710 if (r.length () > 0) | |
1711 c(i) = r(0); | |
1712 } | |
1713 else | |
1714 break; | |
1715 } | 1644 } |
1716 | 1645 |
1717 if (! error_state) | 1646 retval(0) = octave_value (c, true); |
1718 retval(0) = octave_value (c, true); | |
1719 | 1647 |
1720 break; | 1648 break; |
1721 } | 1649 } |
1722 // fall through "default" | 1650 // fall through "default" |
1723 | 1651 |
1742 case '(': | 1670 case '(': |
1743 if (type.length () == 1) | 1671 if (type.length () == 1) |
1744 { | 1672 { |
1745 cdef_object rhs_obj = to_cdef (rhs); | 1673 cdef_object rhs_obj = to_cdef (rhs); |
1746 | 1674 |
1747 if (! error_state) | 1675 if (rhs_obj.get_class () == get_class ()) |
1748 { | 1676 { |
1749 if (rhs_obj.get_class () == get_class ()) | 1677 const octave_value_list& ival = idx.front (); |
1678 bool is_scalar = true; | |
1679 Array<idx_vector> iv (dim_vector (1, ival.length ())); | |
1680 | |
1681 for (int i = 0; i < ival.length (); i++) | |
1750 { | 1682 { |
1751 const octave_value_list& ival = idx.front (); | 1683 try |
1752 bool is_scalar = true; | |
1753 Array<idx_vector> iv (dim_vector (1, ival.length ())); | |
1754 | |
1755 for (int i = 0; ! error_state && i < ival.length (); i++) | |
1756 { | 1684 { |
1757 try | 1685 iv(i) = ival(i).index_vector (); |
1758 { | |
1759 iv(i) = ival(i).index_vector (); | |
1760 } | |
1761 catch (index_exception& e) | |
1762 { | |
1763 e.set_pos_if_unset (ival.length (), i+1); | |
1764 throw; // var name set in pt-idx.cc / pt-assign.cc | |
1765 } | |
1766 if (! error_state) | |
1767 is_scalar = is_scalar && iv(i).is_scalar (); | |
1768 } | 1686 } |
1769 | 1687 catch (index_exception& e) |
1770 if (! error_state) | |
1771 { | 1688 { |
1772 Array<cdef_object> rhs_mat; | 1689 e.set_pos_if_unset (ival.length (), i+1); |
1773 | 1690 throw; // var name set in pt-idx.cc / pt-assign.cc |
1774 if (! rhs_obj.is_array ()) | |
1775 { | |
1776 rhs_mat = Array<cdef_object> (dim_vector (1, 1)); | |
1777 rhs_mat(0) = rhs_obj; | |
1778 } | |
1779 else | |
1780 rhs_mat = rhs_obj.array_value (); | |
1781 | |
1782 if (! error_state) | |
1783 { | |
1784 octave_idx_type n = array.numel (); | |
1785 | |
1786 array.assign (iv, rhs_mat, cdef_object ()); | |
1787 | |
1788 if (! error_state) | |
1789 { | |
1790 if (array.numel () > n) | |
1791 fill_empty_values (); | |
1792 | |
1793 if (! error_state) | |
1794 { | |
1795 refcount++; | |
1796 retval = to_ov (cdef_object (this)); | |
1797 } | |
1798 } | |
1799 } | |
1800 } | 1691 } |
1692 | |
1693 is_scalar = is_scalar && iv(i).is_scalar (); | |
1694 } | |
1695 | |
1696 Array<cdef_object> rhs_mat; | |
1697 | |
1698 if (! rhs_obj.is_array ()) | |
1699 { | |
1700 rhs_mat = Array<cdef_object> (dim_vector (1, 1)); | |
1701 rhs_mat(0) = rhs_obj; | |
1801 } | 1702 } |
1802 else | 1703 else |
1803 error ("can't assign %s object into array of %s objects.", | 1704 rhs_mat = rhs_obj.array_value (); |
1804 rhs_obj.class_name ().c_str (), | 1705 |
1805 class_name ().c_str ()); | 1706 octave_idx_type n = array.numel (); |
1707 | |
1708 array.assign (iv, rhs_mat, cdef_object ()); | |
1709 | |
1710 if (array.numel () > n) | |
1711 fill_empty_values (); | |
1712 | |
1713 refcount++; | |
1714 retval = to_ov (cdef_object (this)); | |
1806 } | 1715 } |
1716 else | |
1717 error ("can't assign %s object into array of %s objects.", | |
1718 rhs_obj.class_name ().c_str (), | |
1719 class_name ().c_str ()); | |
1807 } | 1720 } |
1808 else | 1721 else |
1809 { | 1722 { |
1810 const octave_value_list& ival = idx.front (); | 1723 const octave_value_list& ival = idx.front (); |
1811 | 1724 |
1812 bool is_scalar = true; | 1725 bool is_scalar = true; |
1813 | 1726 |
1814 Array<idx_vector> iv (dim_vector (1, ival.length ())); | 1727 Array<idx_vector> iv (dim_vector (1, ival.length ())); |
1815 | 1728 |
1816 for (int i = 0; ! error_state && i < ival.length (); i++) | 1729 for (int i = 0; i < ival.length (); i++) |
1817 { | 1730 { |
1818 try | 1731 try |
1819 { | 1732 { |
1820 iv(i) = ival(i).index_vector (); | 1733 iv(i) = ival(i).index_vector (); |
1821 } | 1734 } |
1824 // Rethrow to allow more info to be reported later. | 1737 // Rethrow to allow more info to be reported later. |
1825 e.set_pos_if_unset (ival.length (), i+1); | 1738 e.set_pos_if_unset (ival.length (), i+1); |
1826 throw; | 1739 throw; |
1827 } | 1740 } |
1828 | 1741 |
1829 if (! error_state) | 1742 is_scalar = is_scalar && iv(i).is_scalar (); |
1743 | |
1744 if (! is_scalar) | |
1745 error ("subsasgn: invalid indexing for object array " | |
1746 "assignment, the index must reference a single " | |
1747 "object in the array."); | |
1748 } | |
1749 | |
1750 Array<cdef_object> a = array.index (iv, true); | |
1751 | |
1752 if (a.numel () != 1) | |
1753 error ("subsasgn: invalid indexing for object array " | |
1754 "assignment"); | |
1755 | |
1756 cdef_object obj = a(0); | |
1757 | |
1758 int ignore_copies = 0; | |
1759 | |
1760 // If the object in 'a' is not valid, this means the index | |
1761 // was out-of-bound and we need to create a new object. | |
1762 | |
1763 if (! obj.ok ()) | |
1764 obj = get_class ().construct_object (octave_value_list ()); | |
1765 else | |
1766 // Optimize the subsasgn call to come. There are 2 copies | |
1767 // that we can safely ignore: | |
1768 // - 1 in "array" | |
1769 // - 1 in "a" | |
1770 ignore_copies = 2; | |
1771 | |
1772 std::list<octave_value_list> next_idx (idx); | |
1773 | |
1774 next_idx.erase (next_idx.begin ()); | |
1775 | |
1776 octave_value tmp = obj.subsasgn (type.substr (1), next_idx, | |
1777 rhs, ignore_copies); | |
1778 | |
1779 cdef_object robj = to_cdef (tmp); | |
1780 | |
1781 if (robj.ok () | |
1782 && ! robj.is_array () | |
1783 && robj.get_class () == get_class ()) | |
1784 { | |
1785 // Small optimization, when dealing with handle | |
1786 // objects, we don't need to re-assign the result | |
1787 // of subsasgn back into the array. | |
1788 | |
1789 if (! robj.is (a(0))) | |
1830 { | 1790 { |
1831 is_scalar = is_scalar && iv(i).is_scalar (); | 1791 Array<cdef_object> rhs_a (dim_vector (1, 1), |
1832 | 1792 robj); |
1833 if (! is_scalar) | 1793 |
1834 error ("subsasgn: invalid indexing for object array " | 1794 octave_idx_type n = array.numel (); |
1835 "assignment, the index must reference a single " | 1795 |
1836 "object in the array."); | 1796 array.assign (iv, rhs_a); |
1797 | |
1798 if (array.numel () > n) | |
1799 fill_empty_values (); | |
1837 } | 1800 } |
1801 | |
1802 refcount++; | |
1803 | |
1804 retval = to_ov (cdef_object (this)); | |
1838 } | 1805 } |
1839 | 1806 else |
1840 if (! error_state) | 1807 error ("subasgn: invalid assignment into array of %s " |
1841 { | 1808 "objects", class_name ().c_str ()); |
1842 Array<cdef_object> a = array.index (iv, true); | |
1843 | |
1844 if (a.numel () != 1) | |
1845 error ("subsasgn: invalid indexing for object array " | |
1846 "assignment"); | |
1847 | |
1848 if (! error_state) | |
1849 { | |
1850 cdef_object obj = a(0); | |
1851 | |
1852 int ignore_copies = 0; | |
1853 | |
1854 // If the object in 'a' is not valid, this means the index | |
1855 // was out-of-bound and we need to create a new object. | |
1856 | |
1857 if (! obj.ok ()) | |
1858 obj = get_class ().construct_object (octave_value_list ()); | |
1859 else | |
1860 // Optimize the subsasgn call to come. There are 2 copies | |
1861 // that we can safely ignore: | |
1862 // - 1 in "array" | |
1863 // - 1 in "a" | |
1864 ignore_copies = 2; | |
1865 | |
1866 std::list<octave_value_list> next_idx (idx); | |
1867 | |
1868 next_idx.erase (next_idx.begin ()); | |
1869 | |
1870 octave_value tmp = obj.subsasgn (type.substr (1), next_idx, | |
1871 rhs, ignore_copies); | |
1872 | |
1873 if (! error_state) | |
1874 { | |
1875 cdef_object robj = to_cdef (tmp); | |
1876 | |
1877 if (robj.ok () | |
1878 && ! robj.is_array () | |
1879 && robj.get_class () == get_class ()) | |
1880 { | |
1881 // Small optimization, when dealing with handle | |
1882 // objects, we don't need to re-assign the result | |
1883 // of subsasgn back into the array. | |
1884 | |
1885 if (! robj.is (a(0))) | |
1886 { | |
1887 Array<cdef_object> rhs_a (dim_vector (1, 1), | |
1888 robj); | |
1889 | |
1890 octave_idx_type n = array.numel (); | |
1891 | |
1892 array.assign (iv, rhs_a); | |
1893 | |
1894 if (array.numel () > n) | |
1895 fill_empty_values (); | |
1896 } | |
1897 | |
1898 refcount++; | |
1899 | |
1900 retval = to_ov (cdef_object (this)); | |
1901 } | |
1902 else | |
1903 error ("subasgn: invalid assignment into array of %s " | |
1904 "objects", class_name ().c_str ()); | |
1905 } | |
1906 } | |
1907 } | |
1908 } | 1809 } |
1909 break; | 1810 break; |
1910 | 1811 |
1911 default: | 1812 default: |
1912 error ("can't perform indexing operation on array of %s objects", | 1813 error ("can't perform indexing operation on array of %s objects", |
1920 void | 1821 void |
1921 cdef_object_array::fill_empty_values (Array<cdef_object>& arr) | 1822 cdef_object_array::fill_empty_values (Array<cdef_object>& arr) |
1922 { | 1823 { |
1923 cdef_class cls = get_class (); | 1824 cdef_class cls = get_class (); |
1924 | 1825 |
1925 if (! error_state) | 1826 cdef_object obj; |
1926 { | 1827 |
1927 cdef_object obj; | 1828 int n = arr.numel (); |
1928 | 1829 |
1929 int n = arr.numel (); | 1830 for (int i = 0; i < n; i++) |
1930 | 1831 { |
1931 for (int i = 0; ! error_state && i < n; i++) | 1832 if (! arr.xelem (i).ok ()) |
1932 { | 1833 { |
1933 if (! arr.xelem (i).ok ()) | 1834 if (! obj.ok ()) |
1934 { | 1835 { |
1935 if (! obj.ok ()) | 1836 obj = cls.construct_object (octave_value_list ()); |
1936 { | 1837 |
1937 obj = cls.construct_object (octave_value_list ()); | 1838 arr.xelem (i) = obj; |
1938 | |
1939 if (! error_state) | |
1940 arr.xelem (i) = obj; | |
1941 } | |
1942 else | |
1943 arr.xelem (i) = obj.copy (); | |
1944 } | 1839 } |
1840 else | |
1841 arr.xelem (i) = obj.copy (); | |
1945 } | 1842 } |
1946 } | 1843 } |
1947 } | 1844 } |
1948 | 1845 |
1949 bool | 1846 bool |
2030 | 1927 |
2031 for (int i = 0; i < super_classes.numel (); i++) | 1928 for (int i = 0; i < super_classes.numel (); i++) |
2032 { | 1929 { |
2033 cdef_class cls = lookup_class (super_classes(i)); | 1930 cdef_class cls = lookup_class (super_classes(i)); |
2034 | 1931 |
2035 if (! error_state) | 1932 cdef_method meth = cls.find_method (nm); |
2036 { | 1933 |
2037 cdef_method meth = cls.find_method (nm); | 1934 if (meth.ok ()) |
2038 | 1935 return meth; |
2039 if (meth.ok ()) | |
2040 return meth; | |
2041 } | |
2042 } | 1936 } |
2043 } | 1937 } |
2044 | 1938 |
2045 return cdef_method (); | 1939 return cdef_method (); |
2046 } | 1940 } |
2052 : tree_walker (), who (ctor), obj_name (obj) { } | 1946 : tree_walker (), who (ctor), obj_name (obj) { } |
2053 | 1947 |
2054 void visit_statement_list (tree_statement_list& t) | 1948 void visit_statement_list (tree_statement_list& t) |
2055 { | 1949 { |
2056 for (tree_statement_list::const_iterator it = t.begin (); | 1950 for (tree_statement_list::const_iterator it = t.begin (); |
2057 ! error_state && it != t.end (); ++it) | 1951 it != t.end (); ++it) |
2058 (*it)->accept (*this); | 1952 (*it)->accept (*this); |
2059 } | 1953 } |
2060 | 1954 |
2061 void visit_statement (tree_statement& t) | 1955 void visit_statement (tree_statement& t) |
2062 { | 1956 { |
2186 { | 2080 { |
2187 std::string obj_name = ret_list->front ()->name (); | 2081 std::string obj_name = ret_list->front ()->name (); |
2188 ctor_analyzer a (meth.get_name (), obj_name); | 2082 ctor_analyzer a (meth.get_name (), obj_name); |
2189 | 2083 |
2190 body->accept (a); | 2084 body->accept (a); |
2191 if (! error_state) | 2085 |
2086 std::list<cdef_class> explicit_ctor_list | |
2087 = a.get_constructor_list (); | |
2088 | |
2089 for (std::list<cdef_class>::const_iterator | |
2090 it = explicit_ctor_list.begin (); | |
2091 it != explicit_ctor_list.end (); | |
2092 ++it) | |
2192 { | 2093 { |
2193 std::list<cdef_class> explicit_ctor_list | |
2194 = a.get_constructor_list (); | |
2195 | |
2196 for (std::list<cdef_class>::const_iterator | |
2197 it = explicit_ctor_list.begin (); | |
2198 ! error_state && it != explicit_ctor_list.end (); | |
2199 ++it) | |
2200 { | |
2201 #if DEBUG_TRACE | 2094 #if DEBUG_TRACE |
2202 std::cerr << "explicit superclass constructor: " | 2095 std::cerr << "explicit superclass constructor: " |
2203 << it->get_name () << std::endl; | 2096 << it->get_name () << std::endl; |
2204 #endif | 2097 #endif |
2205 | 2098 |
2206 implicit_ctor_list.remove (*it); | 2099 implicit_ctor_list.remove (*it); |
2207 } | |
2208 } | 2100 } |
2209 } | 2101 } |
2210 else | 2102 else |
2211 error ("%s: invalid constructor output arguments", | 2103 error ("%s: invalid constructor output arguments", |
2212 meth.get_name ().c_str ()); | 2104 meth.get_name ().c_str ()); |
2226 { | 2118 { |
2227 std::map<std::string,cdef_method> meths; | 2119 std::map<std::string,cdef_method> meths; |
2228 | 2120 |
2229 find_methods (meths, false); | 2121 find_methods (meths, false); |
2230 | 2122 |
2231 if (! error_state) | 2123 Cell c (meths.size (), 1); |
2232 { | 2124 |
2233 Cell c (meths.size (), 1); | 2125 int idx = 0; |
2234 | 2126 |
2235 int idx = 0; | 2127 for (std::map<std::string,cdef_method>::const_iterator |
2236 | 2128 it = meths.begin (); it != meths.end (); ++it, ++idx) |
2237 for (std::map<std::string,cdef_method>::const_iterator | 2129 c (idx, 0) = to_ov (it->second); |
2238 it = meths.begin (); it != meths.end (); ++it, ++idx) | 2130 |
2239 c (idx, 0) = to_ov (it->second); | 2131 return c; |
2240 | |
2241 return c; | |
2242 } | |
2243 | |
2244 return Cell (); | |
2245 } | 2132 } |
2246 | 2133 |
2247 void | 2134 void |
2248 cdef_class::cdef_class_rep::find_methods (std::map<std::string, | 2135 cdef_class::cdef_class_rep::find_methods (std::map<std::string, |
2249 cdef_method>& meths, | 2136 cdef_method>& meths, |
2281 | 2168 |
2282 for (int i = 0; i < super_classes.numel (); i++) | 2169 for (int i = 0; i < super_classes.numel (); i++) |
2283 { | 2170 { |
2284 cdef_class cls = lookup_class (super_classes(i)); | 2171 cdef_class cls = lookup_class (super_classes(i)); |
2285 | 2172 |
2286 if (! error_state) | 2173 cls.get_rep ()->find_methods (meths, true); |
2287 cls.get_rep ()->find_methods (meths, true); | |
2288 else | |
2289 break; | |
2290 } | 2174 } |
2291 } | 2175 } |
2292 | 2176 |
2293 cdef_property | 2177 cdef_property |
2294 cdef_class::cdef_class_rep::find_property (const std::string& nm) | 2178 cdef_class::cdef_class_rep::find_property (const std::string& nm) |
2309 | 2193 |
2310 for (int i = 0; i < super_classes.numel (); i++) | 2194 for (int i = 0; i < super_classes.numel (); i++) |
2311 { | 2195 { |
2312 cdef_class cls = lookup_class (super_classes(i)); | 2196 cdef_class cls = lookup_class (super_classes(i)); |
2313 | 2197 |
2314 if (! error_state) | 2198 cdef_property prop = cls.find_property (nm); |
2315 { | 2199 |
2316 cdef_property prop = cls.find_property (nm); | 2200 if (prop.ok ()) |
2317 | 2201 return prop; |
2318 if (prop.ok ()) | |
2319 return prop; | |
2320 } | |
2321 } | 2202 } |
2322 | 2203 |
2323 return cdef_property (); | 2204 return cdef_property (); |
2324 } | 2205 } |
2325 | 2206 |
2336 { | 2217 { |
2337 std::map<std::string,cdef_property> props; | 2218 std::map<std::string,cdef_property> props; |
2338 | 2219 |
2339 props = get_property_map (mode); | 2220 props = get_property_map (mode); |
2340 | 2221 |
2341 if (! error_state) | 2222 Cell c (props.size (), 1); |
2342 { | 2223 |
2343 Cell c (props.size (), 1); | 2224 int idx = 0; |
2344 | 2225 |
2345 int idx = 0; | 2226 for (std::map<std::string,cdef_property>::const_iterator |
2346 | 2227 it = props.begin (); it != props.end (); ++it, ++idx) |
2347 for (std::map<std::string,cdef_property>::const_iterator | 2228 c (idx, 0) = to_ov (it->second); |
2348 it = props.begin (); it != props.end (); ++it, ++idx) | 2229 |
2349 c (idx, 0) = to_ov (it->second); | 2230 return c; |
2350 | |
2351 return c; | |
2352 } | |
2353 | |
2354 return Cell (); | |
2355 } | 2231 } |
2356 | 2232 |
2357 std::map<std::string, cdef_property> | 2233 std::map<std::string, cdef_property> |
2358 cdef_class::cdef_class_rep::get_property_map (int mode) | 2234 cdef_class::cdef_class_rep::get_property_map (int mode) |
2359 { | 2235 { |
2369 cdef_property>& props, | 2245 cdef_property>& props, |
2370 int mode) | 2246 int mode) |
2371 { | 2247 { |
2372 property_const_iterator it; | 2248 property_const_iterator it; |
2373 | 2249 |
2374 for (it = property_map.begin (); ! error_state && it != property_map.end (); | 2250 for (it = property_map.begin (); it != property_map.end (); ++it) |
2375 ++it) | |
2376 { | 2251 { |
2377 std::string nm = it->second.get_name (); | 2252 std::string nm = it->second.get_name (); |
2378 | 2253 |
2379 if (props.find (nm) == props.end ()) | 2254 if (props.find (nm) == props.end ()) |
2380 { | 2255 { |
2393 | 2268 |
2394 // Look into superclasses | 2269 // Look into superclasses |
2395 | 2270 |
2396 Cell super_classes = get ("SuperClasses").cell_value (); | 2271 Cell super_classes = get ("SuperClasses").cell_value (); |
2397 | 2272 |
2398 for (int i = 0; ! error_state && i < super_classes.numel (); i++) | 2273 for (int i = 0; i < super_classes.numel (); i++) |
2399 { | 2274 { |
2400 cdef_class cls = lookup_class (super_classes(i)); | 2275 cdef_class cls = lookup_class (super_classes(i)); |
2401 | 2276 |
2402 if (! error_state) | 2277 cls.get_rep ()->find_properties (props, |
2403 cls.get_rep ()->find_properties (props, | 2278 (mode == property_all |
2404 (mode == property_all ? | 2279 ? property_all |
2405 property_all : | 2280 : property_inherited)); |
2406 property_inherited)); | |
2407 else | |
2408 break; | |
2409 } | 2281 } |
2410 } | 2282 } |
2411 | 2283 |
2412 void | 2284 void |
2413 cdef_class::cdef_class_rep::find_names (std::set<std::string>& names, | 2285 cdef_class::cdef_class_rep::find_names (std::set<std::string>& names, |
2414 bool all) | 2286 bool all) |
2415 { | 2287 { |
2416 load_all_methods (); | 2288 load_all_methods (); |
2417 | 2289 |
2418 for (method_const_iterator it = method_map.begin (); | 2290 for (method_const_iterator it = method_map.begin (); |
2419 ! error_state && it != method_map.end(); ++it) | 2291 it != method_map.end(); ++it) |
2420 { | 2292 { |
2421 if (! it->second.is_constructor ()) | 2293 if (! it->second.is_constructor ()) |
2422 { | 2294 { |
2423 std::string nm = it->second.get_name (); | 2295 std::string nm = it->second.get_name (); |
2424 | 2296 |
2434 names.insert (nm); | 2306 names.insert (nm); |
2435 } | 2307 } |
2436 } | 2308 } |
2437 | 2309 |
2438 for (property_const_iterator it = property_map.begin (); | 2310 for (property_const_iterator it = property_map.begin (); |
2439 ! error_state && it != property_map.end (); ++it) | 2311 it != property_map.end (); ++it) |
2440 { | 2312 { |
2441 std::string nm = it->second.get_name (); | 2313 std::string nm = it->second.get_name (); |
2442 | 2314 |
2443 if (! all) | 2315 if (! all) |
2444 { | 2316 { |
2454 | 2326 |
2455 // Look into superclasses | 2327 // Look into superclasses |
2456 | 2328 |
2457 Cell super_classes = get ("SuperClasses").cell_value (); | 2329 Cell super_classes = get ("SuperClasses").cell_value (); |
2458 | 2330 |
2459 for (int i = 0; ! error_state && i < super_classes.numel (); i++) | 2331 for (int i = 0; i < super_classes.numel (); i++) |
2460 { | 2332 { |
2461 cdef_class cls = lookup_class (super_classes(i)); | 2333 cdef_class cls = lookup_class (super_classes(i)); |
2462 | 2334 |
2463 if (! error_state) | 2335 cls.get_rep ()->find_names (names, all); |
2464 cls.get_rep ()->find_names (names, all); | |
2465 else | |
2466 break; | |
2467 } | 2336 } |
2468 } | 2337 } |
2469 | 2338 |
2470 string_vector | 2339 string_vector |
2471 cdef_class::cdef_class_rep::get_names (void) | 2340 cdef_class::cdef_class_rep::get_names (void) |
2472 { | 2341 { |
2473 std::set<std::string> names; | 2342 std::set<std::string> names; |
2474 | 2343 |
2475 find_names (names, false); | 2344 find_names (names, false); |
2476 | 2345 |
2477 if (! error_state) | 2346 string_vector v (names.size ()); |
2478 { | 2347 |
2479 string_vector v (names.size ()); | 2348 int idx = 0; |
2480 | 2349 for (std::set<std::string>::const_iterator it = names.begin (); |
2481 int idx = 0; | 2350 it != names.end (); ++it, ++idx) |
2482 for (std::set<std::string>::const_iterator it = names.begin (); | 2351 v[idx] = *it; |
2483 it != names.end (); ++it, ++idx) | 2352 |
2484 v[idx] = *it; | 2353 return v.sort (true); |
2485 | |
2486 return v.sort (true); | |
2487 } | |
2488 | |
2489 return string_vector (); | |
2490 } | 2354 } |
2491 | 2355 |
2492 void | 2356 void |
2493 cdef_class::cdef_class_rep::delete_object (cdef_object obj) | 2357 cdef_class::cdef_class_rep::delete_object (cdef_object obj) |
2494 { | 2358 { |
2513 | 2377 |
2514 for (int i = 0; i < super_classes.numel (); i++) | 2378 for (int i = 0; i < super_classes.numel (); i++) |
2515 { | 2379 { |
2516 cdef_class cls = lookup_class (super_classes(i)); | 2380 cdef_class cls = lookup_class (super_classes(i)); |
2517 | 2381 |
2518 if (!error_state) | 2382 cls.delete_object (obj); |
2519 cls.delete_object (obj); | |
2520 } | 2383 } |
2521 } | 2384 } |
2522 | 2385 |
2523 octave_value_list | 2386 octave_value_list |
2524 cdef_class::cdef_class_rep::meta_subsref (const std::string& type, | 2387 cdef_class::cdef_class_rep::meta_subsref (const std::string& type, |
2601 default: | 2464 default: |
2602 error ("invalid meta.class indexing"); | 2465 error ("invalid meta.class indexing"); |
2603 break; | 2466 break; |
2604 } | 2467 } |
2605 | 2468 |
2606 if (! error_state) | 2469 if (type.length () > skip && idx.size () > skip && ! retval.empty ()) |
2607 { | 2470 retval = retval(0).next_subsref (nargout, type, idx, skip); |
2608 if (type.length () > skip && idx.size () > skip && ! retval.empty ()) | |
2609 retval = retval(0).next_subsref (nargout, type, idx, skip); | |
2610 } | |
2611 | 2471 |
2612 return retval; | 2472 return retval; |
2613 } | 2473 } |
2614 | 2474 |
2615 void | 2475 void |
2624 // Populate the object with default property values | 2484 // Populate the object with default property values |
2625 | 2485 |
2626 std::list<cdef_class> super_classes = lookup_classes ( | 2486 std::list<cdef_class> super_classes = lookup_classes ( |
2627 get ("SuperClasses").cell_value ()); | 2487 get ("SuperClasses").cell_value ()); |
2628 | 2488 |
2629 if (! error_state) | 2489 for (std::list<cdef_class>::iterator it = super_classes.begin (); |
2630 { | 2490 it != super_classes.end (); ++it) |
2631 for (std::list<cdef_class>::iterator it = super_classes.begin (); | 2491 it->initialize_object (obj); |
2632 ! error_state && it != super_classes.end (); ++it) | 2492 |
2633 it->initialize_object (obj); | 2493 for (property_const_iterator it = property_map.begin (); |
2634 | 2494 it != property_map.end (); ++it) |
2635 if (! error_state) | 2495 { |
2636 { | 2496 if (! it->second.get ("Dependent").bool_value ()) |
2637 for (property_const_iterator it = property_map.begin (); | 2497 { |
2638 ! error_state && it != property_map.end (); ++it) | 2498 octave_value pvalue = it->second.get ("DefaultValue"); |
2639 { | 2499 |
2640 if (! it->second.get ("Dependent").bool_value ()) | 2500 if (pvalue.is_defined ()) |
2641 { | 2501 obj.put (it->first, pvalue); |
2642 octave_value pvalue = it->second.get ("DefaultValue"); | 2502 else |
2643 | 2503 obj.put (it->first, octave_value (Matrix ())); |
2644 if (pvalue.is_defined ()) | 2504 } |
2645 obj.put (it->first, pvalue); | 2505 } |
2646 else | 2506 |
2647 obj.put (it->first, octave_value (Matrix ())); | 2507 refcount++; |
2648 } | 2508 obj.mark_for_construction (cdef_class (this)); |
2649 } | |
2650 | |
2651 if (! error_state) | |
2652 { | |
2653 refcount++; | |
2654 obj.mark_for_construction (cdef_class (this)); | |
2655 } | |
2656 } | |
2657 } | |
2658 } | 2509 } |
2659 | 2510 |
2660 void | 2511 void |
2661 cdef_class::cdef_class_rep::run_constructor (cdef_object& obj, | 2512 cdef_class::cdef_class_rep::run_constructor (cdef_object& obj, |
2662 const octave_value_list& args) | 2513 const octave_value_list& args) |
2663 { | 2514 { |
2664 octave_value_list empty_args; | 2515 octave_value_list empty_args; |
2665 | 2516 |
2666 for (std::list<cdef_class>::const_iterator it = implicit_ctor_list.begin (); | 2517 for (std::list<cdef_class>::const_iterator it = implicit_ctor_list.begin (); |
2667 ! error_state && it != implicit_ctor_list.end (); ++it) | 2518 it != implicit_ctor_list.end (); ++it) |
2668 { | 2519 { |
2669 cdef_class supcls = lookup_class (*it); | 2520 cdef_class supcls = lookup_class (*it); |
2670 | 2521 |
2671 if (! error_state) | 2522 supcls.run_constructor (obj, empty_args); |
2672 supcls.run_constructor (obj, empty_args); | 2523 } |
2673 } | |
2674 | |
2675 if (error_state) | |
2676 return; | |
2677 | 2524 |
2678 std::string cls_name = get_name (); | 2525 std::string cls_name = get_name (); |
2679 std::string ctor_name = get_base_name (cls_name); | 2526 std::string ctor_name = get_base_name (cls_name); |
2680 | 2527 |
2681 cdef_method ctor = find_method (ctor_name); | 2528 cdef_method ctor = find_method (ctor_name); |
2686 octave_value_list ctor_retval; | 2533 octave_value_list ctor_retval; |
2687 | 2534 |
2688 ctor_args.prepend (to_ov (obj)); | 2535 ctor_args.prepend (to_ov (obj)); |
2689 ctor_retval = ctor.execute (ctor_args, 1, true, "constructor"); | 2536 ctor_retval = ctor.execute (ctor_args, 1, true, "constructor"); |
2690 | 2537 |
2691 if (! error_state) | 2538 if (ctor_retval.length () == 1) |
2692 { | 2539 obj = to_cdef (ctor_retval(0)); |
2693 if (ctor_retval.length () == 1) | 2540 else |
2694 obj = to_cdef (ctor_retval(0)); | 2541 { |
2695 else | 2542 error ("%s: invalid number of output arguments for classdef constructor", |
2696 { | 2543 ctor_name.c_str ()); |
2697 error ("%s: invalid number of output arguments for classdef constructor", | 2544 return; |
2698 ctor_name.c_str ()); | |
2699 return; | |
2700 } | |
2701 } | 2545 } |
2702 } | 2546 } |
2703 | 2547 |
2704 obj.mark_as_constructed (wrap ()); | 2548 obj.mark_as_constructed (wrap ()); |
2705 } | 2549 } |
2707 octave_value | 2551 octave_value |
2708 cdef_class::cdef_class_rep::construct (const octave_value_list& args) | 2552 cdef_class::cdef_class_rep::construct (const octave_value_list& args) |
2709 { | 2553 { |
2710 cdef_object obj = construct_object (args); | 2554 cdef_object obj = construct_object (args); |
2711 | 2555 |
2712 if (! error_state && obj.ok ()) | 2556 if (obj.ok ()) |
2713 return to_ov (obj); | 2557 return to_ov (obj); |
2714 | 2558 |
2715 return octave_value (); | 2559 return octave_value (); |
2716 } | 2560 } |
2717 | 2561 |
2778 obj = cdef_object (new value_cdef_object ()); | 2622 obj = cdef_object (new value_cdef_object ()); |
2779 obj.set_class (wrap ()); | 2623 obj.set_class (wrap ()); |
2780 | 2624 |
2781 initialize_object (obj); | 2625 initialize_object (obj); |
2782 | 2626 |
2783 if (! error_state) | 2627 run_constructor (obj, args); |
2784 { | 2628 |
2785 run_constructor (obj, args); | 2629 return obj; |
2786 | |
2787 if (! error_state) | |
2788 return obj; | |
2789 } | |
2790 } | 2630 } |
2791 } | 2631 } |
2792 else | 2632 else |
2793 error ("cannot instantiate object for abstract class `%s'", | 2633 error ("cannot instantiate object for abstract class `%s'", |
2794 get_name ().c_str ()); | 2634 get_name ().c_str ()); |
2851 | 2691 |
2852 if (t->superclass_list ()) | 2692 if (t->superclass_list ()) |
2853 { | 2693 { |
2854 for (tree_classdef_superclass_list::iterator it = | 2694 for (tree_classdef_superclass_list::iterator it = |
2855 t->superclass_list ()->begin (); | 2695 t->superclass_list ()->begin (); |
2856 ! error_state && it != t->superclass_list ()->end (); ++it) | 2696 it != t->superclass_list ()->end (); ++it) |
2857 { | 2697 { |
2858 std::string sclass_name = (*it)->class_name (); | 2698 std::string sclass_name = (*it)->class_name (); |
2859 | 2699 |
2860 #if DEBUG_TRACE | 2700 #if DEBUG_TRACE |
2861 std::cerr << "superclass: " << sclass_name << std::endl; | 2701 std::cerr << "superclass: " << sclass_name << std::endl; |
2862 #endif | 2702 #endif |
2863 | 2703 |
2864 cdef_class sclass = lookup_class (sclass_name); | 2704 cdef_class sclass = lookup_class (sclass_name); |
2865 | 2705 |
2866 if (! error_state) | 2706 if (! sclass.get ("Sealed").bool_value ()) |
2707 slist.push_back (sclass); | |
2708 else | |
2867 { | 2709 { |
2868 if (! sclass.get ("Sealed").bool_value ()) | 2710 error ("`%s' cannot inherit from `%s', because it is sealed", |
2869 slist.push_back (sclass); | 2711 full_class_name.c_str (), sclass_name.c_str ()); |
2870 else | 2712 return retval; |
2871 { | |
2872 error ("`%s' cannot inherit from `%s', because it is sealed", | |
2873 full_class_name.c_str (), sclass_name.c_str ()); | |
2874 return retval; | |
2875 } | |
2876 } | 2713 } |
2877 else | |
2878 return retval; | |
2879 | 2714 |
2880 } | 2715 } |
2881 } | 2716 } |
2882 | 2717 |
2883 retval = ::make_class (full_class_name, slist); | 2718 retval = ::make_class (full_class_name, slist); |
2884 | 2719 |
2885 if (error_state) | |
2886 return cdef_class (); | |
2887 | |
2888 // Package owning this class | 2720 // Package owning this class |
2889 | 2721 |
2890 if (! t->package_name ().empty ()) | 2722 if (! t->package_name ().empty ()) |
2891 { | 2723 { |
2892 cdef_package pack = cdef_manager::find_package (t->package_name ()); | 2724 cdef_package pack = cdef_manager::find_package (t->package_name ()); |
2893 | 2725 |
2894 if (! error_state && pack.ok ()) | 2726 if (pack.ok ()) |
2895 retval.put ("ContainingPackage", to_ov (pack)); | 2727 retval.put ("ContainingPackage", to_ov (pack)); |
2896 } | 2728 } |
2897 | 2729 |
2898 // Class attributes | 2730 // Class attributes |
2899 | 2731 |
3200 | 3032 |
3201 args(0) = to_ov (obj); | 3033 args(0) = to_ov (obj); |
3202 | 3034 |
3203 args = execute_ov (get_fcn, args, 1); | 3035 args = execute_ov (get_fcn, args, 1); |
3204 | 3036 |
3205 if (! error_state) | 3037 retval = args(0); |
3206 retval = args(0); | |
3207 } | 3038 } |
3208 | 3039 |
3209 return retval; | 3040 return retval; |
3210 } | 3041 } |
3211 | 3042 |
3266 args(0) = to_ov (obj); | 3097 args(0) = to_ov (obj); |
3267 args(1) = val; | 3098 args(1) = val; |
3268 | 3099 |
3269 args = execute_ov (set_fcn, args, 1); | 3100 args = execute_ov (set_fcn, args, 1); |
3270 | 3101 |
3271 if (! error_state) | 3102 if (args.length () > 0 && args(0).is_defined ()) |
3272 { | 3103 { |
3273 if (args.length () > 0 && args(0).is_defined ()) | 3104 if (args (0).is_classdef_object ()) |
3274 { | 3105 { |
3275 if (args (0).is_classdef_object ()) | 3106 cdef_object new_obj = to_cdef (args(0)); |
3276 { | 3107 |
3277 cdef_object new_obj = to_cdef (args(0)); | 3108 obj = new_obj; |
3278 | |
3279 if (! error_state) | |
3280 obj = new_obj; | |
3281 } | |
3282 else | |
3283 ::warning ("set-method of property `%s' returned a non-classdef object", | |
3284 get_name ().c_str ()); | |
3285 } | 3109 } |
3110 else | |
3111 ::warning ("set-method of property `%s' returned a non-classdef object", | |
3112 get_name ().c_str ()); | |
3286 } | 3113 } |
3287 } | 3114 } |
3288 } | 3115 } |
3289 | 3116 |
3290 bool | 3117 bool |
3291 cdef_property::cdef_property_rep::check_get_access (void) const | 3118 cdef_property::cdef_property_rep::check_get_access (void) const |
3292 { | 3119 { |
3293 cdef_class cls (to_cdef (get ("DefiningClass"))); | 3120 cdef_class cls (to_cdef (get ("DefiningClass"))); |
3294 | 3121 |
3295 if (! error_state) | 3122 return ::check_access (cls, get ("GetAccess"), std::string (), |
3296 return ::check_access (cls, get ("GetAccess"), std::string (), | 3123 get_name (), false); |
3297 get_name (), false); | |
3298 | 3124 |
3299 return false; | 3125 return false; |
3300 } | 3126 } |
3301 | 3127 |
3302 bool | 3128 bool |
3303 cdef_property::cdef_property_rep::check_set_access (void) const | 3129 cdef_property::cdef_property_rep::check_set_access (void) const |
3304 { | 3130 { |
3305 cdef_class cls (to_cdef (get ("DefiningClass"))); | 3131 cdef_class cls (to_cdef (get ("DefiningClass"))); |
3306 | 3132 |
3307 if (! error_state) | 3133 return ::check_access (cls, get ("SetAccess"), std::string (), |
3308 return ::check_access (cls, get ("SetAccess"), std::string (), | 3134 get_name (), true); |
3309 get_name (), true); | |
3310 | 3135 |
3311 return false; | 3136 return false; |
3312 } | 3137 } |
3313 | 3138 |
3314 void | 3139 void |
3375 | 3200 |
3376 if (! get ("Abstract").bool_value ()) | 3201 if (! get ("Abstract").bool_value ()) |
3377 { | 3202 { |
3378 check_method (); | 3203 check_method (); |
3379 | 3204 |
3380 if (! error_state && function.is_defined ()) | 3205 if (function.is_defined ()) |
3381 { | 3206 retval = execute_ov (function, args, nargout); |
3382 retval = execute_ov (function, args, nargout); | |
3383 } | |
3384 } | 3207 } |
3385 else | 3208 else |
3386 error ("%s: cannot execute abstract method", | 3209 error ("%s: cannot execute abstract method", |
3387 get ("Name").string_value ().c_str ()); | 3210 get ("Name").string_value ().c_str ()); |
3388 | 3211 |
3406 | 3229 |
3407 if (! get ("Abstract").bool_value ()) | 3230 if (! get ("Abstract").bool_value ()) |
3408 { | 3231 { |
3409 check_method (); | 3232 check_method (); |
3410 | 3233 |
3411 if (! error_state && function.is_defined ()) | 3234 if (function.is_defined ()) |
3412 { | 3235 { |
3413 octave_value_list new_args; | 3236 octave_value_list new_args; |
3414 | 3237 |
3415 new_args.resize (args.length () + 1); | 3238 new_args.resize (args.length () + 1); |
3416 | 3239 |
3440 bool | 3263 bool |
3441 cdef_method::cdef_method_rep::check_access (void) const | 3264 cdef_method::cdef_method_rep::check_access (void) const |
3442 { | 3265 { |
3443 cdef_class cls (to_cdef (get ("DefiningClass"))); | 3266 cdef_class cls (to_cdef (get ("DefiningClass"))); |
3444 | 3267 |
3445 if (! error_state) | 3268 return ::check_access (cls, get ("Access"), get_name ()); |
3446 return ::check_access (cls, get ("Access"), get_name ()); | |
3447 | |
3448 return false; | |
3449 } | 3269 } |
3450 | 3270 |
3451 octave_value_list | 3271 octave_value_list |
3452 cdef_method::cdef_method_rep::meta_subsref | 3272 cdef_method::cdef_method_rep::meta_subsref |
3453 (const std::string& type, const std::list<octave_value_list>& idx, | 3273 (const std::string& type, const std::list<octave_value_list>& idx, |
3464 default: | 3284 default: |
3465 error ("invalid meta.method indexing"); | 3285 error ("invalid meta.method indexing"); |
3466 break; | 3286 break; |
3467 } | 3287 } |
3468 | 3288 |
3469 if (! error_state) | 3289 if (type.length () > 1 && idx.size () > 1 && ! retval.empty ()) |
3470 { | 3290 retval = retval(0).next_subsref (nargout, type, idx, 1); |
3471 if (type.length () > 1 && idx.size () > 1 && ! retval.empty ()) | |
3472 retval = retval(0).next_subsref (nargout, type, idx, 1); | |
3473 } | |
3474 | 3291 |
3475 return retval; | 3292 return retval; |
3476 } | 3293 } |
3477 | 3294 |
3478 static cdef_package | 3295 static cdef_package |
3662 { | 3479 { |
3663 if (o.is_function ()) | 3480 if (o.is_function ()) |
3664 { | 3481 { |
3665 octave_function* fcn = o.function_value (); | 3482 octave_function* fcn = o.function_value (); |
3666 | 3483 |
3667 if (! error_state) | 3484 // NOTE: the case where the package query is the last |
3485 // part of this subsref index is handled in the parse | |
3486 // tree, because there is some logic to handle magic | |
3487 // "end" that makes it impossible to execute the | |
3488 // function call at this stage. | |
3489 | |
3490 if (type.size () > 1 | |
3491 && ! fcn->is_postfix_index_handled (type[1])) | |
3668 { | 3492 { |
3669 // NOTE: the case where the package query is the last | 3493 octave_value_list tmp_args; |
3670 // part of this subsref index is handled in the parse | 3494 |
3671 // tree, because there is some logic to handle magic | 3495 retval = o.do_multi_index_op (nargout, |
3672 // "end" that makes it impossible to execute the | 3496 tmp_args); |
3673 // function call at this stage. | |
3674 | |
3675 if (type.size () > 1 | |
3676 && ! fcn->is_postfix_index_handled (type[1])) | |
3677 { | |
3678 octave_value_list tmp_args; | |
3679 | |
3680 retval = o.do_multi_index_op (nargout, | |
3681 tmp_args); | |
3682 } | |
3683 else | |
3684 retval(0) = o; | |
3685 | |
3686 if (type.size () > 1 && idx.size () > 1) | |
3687 retval = retval(0).next_subsref (nargout, type, | |
3688 idx, 1); | |
3689 } | 3497 } |
3498 else | |
3499 retval(0) = o; | |
3500 | |
3501 if (type.size () > 1 && idx.size () > 1) | |
3502 retval = retval(0).next_subsref (nargout, type, | |
3503 idx, 1); | |
3690 } | 3504 } |
3691 else if (type.size () > 1 && idx.size () > 1) | 3505 else if (type.size () > 1 && idx.size () > 1) |
3692 retval = o.next_subsref (nargout, type, idx, 1); | 3506 retval = o.next_subsref (nargout, type, idx, 1); |
3693 else | 3507 else |
3694 retval(0) = o; | 3508 retval(0) = o; |