1 //////////////////////////////////////////////////////////////////////// 2 // 3 // Copyright (C) 2012-2021 The Octave Project Developers 4 // 5 // See the file COPYRIGHT.md in the top-level directory of this 6 // distribution or <https://octave.org/copyright/>. 7 // 8 // This file is part of Octave. 9 // 10 // Octave is free software: you can redistribute it and/or modify it 11 // under the terms of the GNU General Public License as published by 12 // the Free Software Foundation, either version 3 of the License, or 13 // (at your option) any later version. 14 // 15 // Octave is distributed in the hope that it will be useful, but 16 // WITHOUT ANY WARRANTY; without even the implied warranty of 17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 // GNU General Public License for more details. 19 // 20 // You should have received a copy of the GNU General Public License 21 // along with Octave; see the file COPYING. If not, see 22 // <https://www.gnu.org/licenses/>. 23 // 24 //////////////////////////////////////////////////////////////////////// 25 26 #if defined (HAVE_CONFIG_H) 27 # include "config.h" 28 #endif 29 30 #include "cdef-manager.h" 31 #include "cdef-utils.h" 32 #include "interpreter.h" 33 #include "ov-classdef.h" 34 35 namespace octave 36 { 37 static octave_value make_fcn_handle(octave_builtin::fcn ff,const std::string & nm)38 make_fcn_handle (octave_builtin::fcn ff, const std::string& nm) 39 { 40 octave_value fcn (new octave_builtin (ff, nm)); 41 42 return octave_value (new octave_fcn_handle (fcn)); 43 } 44 45 static octave_value_list class_get_properties(const octave_value_list & args,int)46 class_get_properties (const octave_value_list& args, int /* nargout */) 47 { 48 octave_value_list retval; 49 50 if (args.length () == 1 && args(0).type_name () == "object") 51 { 52 cdef_class cls (to_cdef (args(0))); 53 54 retval(0) = cls.get_properties (); 55 } 56 57 return retval; 58 } 59 60 static octave_value_list class_get_methods(const octave_value_list & args,int)61 class_get_methods (const octave_value_list& args, int /* nargout */) 62 { 63 octave_value_list retval; 64 65 if (args.length () == 1 && args(0).type_name () == "object") 66 { 67 cdef_class cls (to_cdef (args(0))); 68 69 retval(0) = cls.get_methods (); 70 } 71 72 return retval; 73 } 74 75 static octave_value_list class_get_superclasses(const octave_value_list & args,int)76 class_get_superclasses (const octave_value_list& args, int /* nargout */) 77 { 78 octave_value_list retval; 79 80 if (args.length () == 1 && args(0).type_name () == "object" 81 && args(0).class_name () == "meta.class") 82 { 83 cdef_class cls (to_cdef (args(0))); 84 85 Cell classes = cls.get ("SuperClasses").cell_value (); 86 87 retval(0) = to_ov (lookup_classes (classes)); 88 } 89 90 return retval; 91 } 92 93 static octave_value_list class_get_inferiorclasses(const octave_value_list & args,int)94 class_get_inferiorclasses (const octave_value_list& args, int /* nargout */) 95 { 96 octave_value_list retval; 97 98 if (args.length () == 1 && args(0).type_name () == "object" 99 && args(0).class_name () == "meta.class") 100 { 101 cdef_class cls (to_cdef (args(0))); 102 103 Cell classes = cls.get ("InferiorClasses").cell_value (); 104 105 retval(0) = to_ov (lookup_classes (classes)); 106 } 107 108 return retval; 109 } 110 111 static octave_value_list class_fromName(const octave_value_list & args,int)112 class_fromName (const octave_value_list& args, int /* nargout */) 113 { 114 octave_value_list retval; 115 116 if (args.length () != 1) 117 error ("fromName: invalid number of parameters"); 118 119 std::string name = args(0).xstring_value ("fromName: CLASS_NAME must be a string"); 120 121 retval(0) = to_ov (lookup_class (name, false)); 122 123 return retval; 124 } 125 126 static octave_value_list class_fevalStatic(const octave_value_list & args,int nargout)127 class_fevalStatic (const octave_value_list& args, int nargout) 128 { 129 if (args.length () <= 1 || args(0).type_name () != "object") 130 error ("fevalStatic: first argument must be a meta.class object"); 131 132 cdef_class cls (to_cdef (args(0))); 133 134 std::string meth_name = args(1).xstring_value ("fevalStatic: method name must be a string"); 135 136 cdef_method meth = cls.find_method (meth_name); 137 138 if (! meth.ok ()) 139 error ("fevalStatic: method not found: %s", meth_name.c_str ()); 140 141 if (! meth.is_static ()) 142 error ("fevalStatic: method '%s' is not static", meth_name.c_str ()); 143 144 return meth.execute (args.splice (0, 2), nargout, true, "fevalStatic"); 145 } 146 147 static octave_value_list class_getConstant(const octave_value_list & args,int)148 class_getConstant (const octave_value_list& args, int /* nargout */) 149 { 150 octave_value_list retval; 151 152 if (args.length () != 2 || args(0).type_name () != "object" 153 || args(0).class_name () != "meta.class") 154 error ("getConstant: first argument must be a meta.class object"); 155 156 cdef_class cls = to_cdef (args(0)); 157 158 std::string prop_name = args(1).xstring_value ("getConstant: property name must be a string"); 159 160 cdef_property prop = cls.find_property (prop_name); 161 162 if (! prop.ok ()) 163 error ("getConstant: property not found: %s", 164 prop_name.c_str ()); 165 166 if (! prop.is_constant ()) 167 error ("getConstant: property '%s' is not constant", 168 prop_name.c_str ()); 169 170 retval(0) = prop.get_value (true, "getConstant"); 171 172 return retval; 173 } 174 175 #define META_CLASS_CMP(OP, CLSA, CLSB, FUN) \ 176 static octave_value_list \ 177 class_ ## OP (const octave_value_list& args, int /* nargout */) \ 178 { \ 179 octave_value_list retval; \ 180 \ 181 if (args.length () != 2 \ 182 || args(0).type_name () != "object" \ 183 || args(1).type_name () != "object" \ 184 || args(0).class_name () != "meta.class" \ 185 || args(1).class_name () != "meta.class") \ 186 error (#OP ": invalid arguments"); \ 187 \ 188 cdef_class clsa = to_cdef (args(0)); \ 189 \ 190 cdef_class clsb = to_cdef (args(1)); \ 191 \ 192 retval(0) = FUN (CLSA, CLSB); \ 193 \ 194 return retval; \ 195 } 196 META_CLASS_CMP(lt,clsb,clsa,is_strict_superclass)197 META_CLASS_CMP (lt, clsb, clsa, is_strict_superclass) 198 META_CLASS_CMP (le, clsb, clsa, is_superclass) 199 META_CLASS_CMP (gt, clsa, clsb, is_strict_superclass) 200 META_CLASS_CMP (ge, clsa, clsb, is_superclass) 201 META_CLASS_CMP (eq, clsa, clsb, operator==) 202 META_CLASS_CMP (ne, clsa, clsb, operator!=) 203 204 static octave_value_list 205 property_get_defaultvalue (const octave_value_list& args, int /* nargout */) 206 { 207 octave_value_list retval; 208 209 if (args.length () == 1 && args(0).type_name () == "object") 210 { 211 cdef_property prop (to_cdef (args(0))); 212 213 retval(0) = prop.get ("DefaultValue"); 214 215 if (! retval(0).is_defined ()) 216 error_with_id ("Octave:class:NoDefaultDefined", 217 "no default value for property '%s'", 218 prop.get_name ().c_str ()); 219 } 220 221 return retval; 222 } 223 224 static octave_value_list handle_delete(const octave_value_list &,int)225 handle_delete (const octave_value_list& /* args */, int /* nargout */) 226 { 227 octave_value_list retval; 228 229 // FIXME: implement this. Wait, what is this supposed to do? 230 231 return retval; 232 } 233 234 static octave_value_list package_get_classes(const octave_value_list & args,int)235 package_get_classes (const octave_value_list& args, int /* nargout */) 236 { 237 octave_value_list retval (1, Matrix ()); 238 239 if (args.length () == 1 && args(0).type_name () == "object" 240 && args(0).class_name () == "meta.package") 241 { 242 cdef_package pack (to_cdef (args(0))); 243 244 retval(0) = pack.get_classes (); 245 } 246 247 return retval; 248 } 249 250 static octave_value_list package_get_functions(const octave_value_list & args,int)251 package_get_functions (const octave_value_list& args, int /* nargout */) 252 { 253 octave_value_list retval (1, Matrix ()); 254 255 if (args.length () == 0 && args(0).type_name () == "object" 256 && args(0).class_name () == "meta.package") 257 { 258 cdef_package pack (to_cdef (args(0))); 259 260 retval(0) = pack.get_functions (); 261 } 262 263 return retval; 264 } 265 266 static octave_value_list package_get_packages(const octave_value_list & args,int)267 package_get_packages (const octave_value_list& args, int /* nargout */) 268 { 269 octave_value_list retval (1, Matrix ()); 270 271 if (args.length () == 0 && args(0).type_name () == "object" 272 && args(0).class_name () == "meta.package") 273 { 274 cdef_package pack (to_cdef (args(0))); 275 276 retval(0) = pack.get_packages (); 277 } 278 279 return retval; 280 } 281 282 static octave_value_list package_getAllPackages(interpreter & interp,const octave_value_list &,int)283 package_getAllPackages (interpreter& interp, 284 const octave_value_list& /* args */, int /* nargout */) 285 { 286 std::map<std::string, cdef_package> toplevel_packages; 287 288 load_path& lp = interp.get_load_path (); 289 290 std::list<std::string> names = lp.get_all_package_names (); 291 292 cdef_manager& cdm = interp.get_cdef_manager (); 293 294 toplevel_packages["meta"] = cdm.find_package ("meta", false, false); 295 296 for (const auto& nm : names) 297 toplevel_packages[nm] = cdm.find_package (nm, false, true); 298 299 Cell c (toplevel_packages.size (), 1); 300 301 int i = 0; 302 303 for (const auto& nm_pkg : toplevel_packages) 304 c(i++,0) = to_ov (nm_pkg.second); 305 306 return octave_value_list (octave_value (c)); 307 } 308 309 static octave_value_list package_fromName(const octave_value_list & args,int)310 package_fromName (const octave_value_list& args, int /* nargout */) 311 { 312 octave_value_list retval; 313 314 if (args.length () != 1) 315 error ("fromName: invalid number of parameters"); 316 317 std::string name = args(0).xstring_value ("fromName: PACKAGE_NAME must be a string"); 318 319 retval(0) = to_ov (lookup_package (name, false)); 320 321 return retval; 322 } 323 cdef_manager(interpreter & interp)324 cdef_manager::cdef_manager (interpreter& interp) 325 : m_interpreter (interp), m_all_classes (), m_all_packages (), 326 m_meta_class (), m_meta_property (), m_meta_method (), 327 m_meta_package (), m_meta () 328 { 329 type_info& ti = m_interpreter.get_type_info (); 330 331 octave_classdef::register_type (ti); 332 333 // bootstrap 334 cdef_class tmp_handle = make_class ("handle"); 335 336 m_meta_class = make_meta_class ("meta.class", tmp_handle); 337 338 tmp_handle.set_class (m_meta_class); 339 m_meta_class.set_class (m_meta_class); 340 341 // meta classes 342 m_meta_property = make_meta_class ("meta.property", tmp_handle); 343 344 m_meta_method = make_meta_class ("meta.method", tmp_handle); 345 346 m_meta_package = make_meta_class ("meta.package", tmp_handle); 347 348 cdef_class tmp_meta_event 349 = make_meta_class ("meta.event", tmp_handle); 350 351 cdef_class tmp_meta_dynproperty 352 = make_meta_class ("meta.dynamicproperty", tmp_handle); 353 354 // meta.class properties 355 m_meta_class.install_property 356 (make_attribute (m_meta_class, "Abstract")); 357 358 m_meta_class.install_property 359 (make_attribute (m_meta_class, "ConstructOnLoad")); 360 361 m_meta_class.install_property 362 (make_property (m_meta_class, "ContainingPackage")); 363 364 m_meta_class.install_property 365 (make_property (m_meta_class, "Description")); 366 367 m_meta_class.install_property 368 (make_property (m_meta_class, "DetailedDescription")); 369 370 m_meta_class.install_property 371 (make_property (m_meta_class, "Events")); 372 373 m_meta_class.install_property 374 (make_attribute (m_meta_class, "HandleCompatible")); 375 376 m_meta_class.install_property 377 (make_attribute (m_meta_class, "Hidden")); 378 379 m_meta_class.install_property 380 (make_property (m_meta_class, "InferiorClasses", 381 make_fcn_handle (class_get_inferiorclasses, 382 "meta.class>get.InferiorClasses"), 383 "public", Matrix (), "private")); 384 385 m_meta_class.install_property 386 (make_property (m_meta_class, "Methods", 387 make_fcn_handle (class_get_methods, 388 "meta.class>get.Methods"), 389 "public", Matrix (), "private")); 390 391 m_meta_class.install_property 392 (make_property (m_meta_class, "MethodList", 393 make_fcn_handle (class_get_methods, 394 "meta.class>get.MethodList"), 395 "public", Matrix (), "private")); 396 397 m_meta_class.install_property (make_attribute (m_meta_class, "Name")); 398 399 m_meta_class.install_property 400 (make_property (m_meta_class, "Properties", 401 make_fcn_handle (class_get_properties, 402 "meta.class>get.Properties"), 403 "public", Matrix (), "private")); 404 405 m_meta_class.install_property 406 (make_property (m_meta_class, "PropertyList", 407 make_fcn_handle (class_get_properties, 408 "meta.class>get.PropertyList"), 409 "public", Matrix (), "private")); 410 411 m_meta_class.install_property (make_attribute (m_meta_class, "Sealed")); 412 413 m_meta_class.install_property 414 (make_property (m_meta_class, "SuperClasses", 415 make_fcn_handle (class_get_superclasses, 416 "meta.class>get.SuperClasses"), 417 "public", Matrix (), "private")); 418 419 m_meta_class.install_property 420 (make_property (m_meta_class, "SuperclassList", 421 make_fcn_handle (class_get_superclasses, 422 "meta.class>get.SuperclassList"), 423 "public", Matrix (), "private")); 424 425 // FIXME: Matlab supports this property under "SuperclassList". 426 // Octave, however, has supported this under "SuperClassList". 427 // Alias the property. Remove in Octave version 8.1. 428 m_meta_class.install_property 429 (make_property (m_meta_class, "SuperClassList", 430 make_fcn_handle (class_get_superclasses, 431 "meta.class>get.SuperclassList"), 432 "public", Matrix (), "private")); 433 434 // meta.class methods 435 m_meta_class.install_method 436 (make_method (m_meta_class, "fromName", class_fromName, "public", true)); 437 438 m_meta_class.install_method 439 (make_method (m_meta_class, "fevalStatic", class_fevalStatic, "public", 440 false)); 441 442 m_meta_class.install_method 443 (make_method (m_meta_class, "getConstant", class_getConstant, "public", 444 false)); 445 446 m_meta_class.install_method (make_method (m_meta_class, "eq", class_eq)); 447 m_meta_class.install_method (make_method (m_meta_class, "ne", class_ne)); 448 m_meta_class.install_method (make_method (m_meta_class, "lt", class_lt)); 449 m_meta_class.install_method (make_method (m_meta_class, "le", class_le)); 450 m_meta_class.install_method (make_method (m_meta_class, "gt", class_gt)); 451 m_meta_class.install_method (make_method (m_meta_class, "ge", class_ge)); 452 453 // meta.method properties 454 m_meta_method.install_property 455 (make_attribute (m_meta_method, "Abstract")); 456 457 m_meta_method.install_property 458 (make_attribute (m_meta_method, "Access")); 459 460 m_meta_method.install_property 461 (make_attribute (m_meta_method, "DefiningClass")); 462 463 m_meta_method.install_property 464 (make_attribute (m_meta_method, "Description")); 465 466 m_meta_method.install_property 467 (make_attribute (m_meta_method, "DetailedDescription")); 468 469 m_meta_method.install_property 470 (make_attribute (m_meta_method, "Hidden")); 471 472 m_meta_method.install_property 473 (make_attribute (m_meta_method, "Name")); 474 475 m_meta_method.install_property 476 (make_attribute (m_meta_method, "Sealed")); 477 478 m_meta_method.install_property 479 (make_attribute (m_meta_method, "Static")); 480 481 // meta.property properties 482 m_meta_property.install_property 483 (make_attribute (m_meta_property, "Name")); 484 485 m_meta_property.install_property 486 (make_attribute (m_meta_property, "Description")); 487 488 m_meta_property.install_property 489 (make_attribute (m_meta_property, "DetailedDescription")); 490 491 m_meta_property.install_property 492 (make_attribute (m_meta_property, "Abstract")); 493 494 m_meta_property.install_property 495 (make_attribute (m_meta_property, "Constant")); 496 497 m_meta_property.install_property 498 (make_attribute (m_meta_property, "GetAccess")); 499 500 m_meta_property.install_property 501 (make_attribute (m_meta_property, "SetAccess")); 502 503 m_meta_property.install_property 504 (make_attribute (m_meta_property, "Dependent")); 505 506 m_meta_property.install_property 507 (make_attribute (m_meta_property, "Transient")); 508 509 m_meta_property.install_property 510 (make_attribute (m_meta_property, "Hidden")); 511 512 m_meta_property.install_property 513 (make_attribute (m_meta_property, "GetObservable")); 514 515 m_meta_property.install_property 516 (make_attribute (m_meta_property, "SetObservable")); 517 518 m_meta_property.install_property 519 (make_attribute (m_meta_property, "GetMethod")); 520 521 m_meta_property.install_property 522 (make_attribute (m_meta_property, "SetMethod")); 523 524 m_meta_property.install_property 525 (make_attribute (m_meta_property, "DefiningClass")); 526 527 m_meta_property.install_property 528 (make_property (m_meta_property, "DefaultValue", 529 make_fcn_handle (property_get_defaultvalue, 530 "meta.property>get.DefaultValue"), 531 "public", Matrix (), "private")); 532 533 m_meta_property.install_property 534 (make_attribute (m_meta_property, "HasDefault")); 535 536 // meta.property events 537 // FIXME: add events 538 539 // handle methods 540 541 tmp_handle.install_method 542 (make_method (tmp_handle, "delete", handle_delete)); 543 544 // meta.package properties 545 546 m_meta_package.install_property 547 (make_attribute (m_meta_package, "Name")); 548 549 m_meta_package.install_property 550 (make_property (m_meta_package, "ContainingPackage")); 551 552 m_meta_package.install_property 553 (make_property (m_meta_package, "ClassList", 554 make_fcn_handle (package_get_classes, 555 "meta.package>get.ClassList"), 556 "public", Matrix (), "private")); 557 558 m_meta_package.install_property 559 (make_property (m_meta_package, "Classes", 560 make_fcn_handle (package_get_classes, 561 "meta.package>get.Classes"), 562 "public", Matrix (), "private")); 563 564 m_meta_package.install_property 565 (make_property (m_meta_package, "FunctionList", 566 make_fcn_handle (package_get_functions, 567 "meta.package>get.FunctionList"), 568 "public", Matrix (), "private")); 569 570 m_meta_package.install_property 571 (make_property (m_meta_package, "Functions", 572 make_fcn_handle (package_get_functions, 573 "meta.package>get.Functions"), 574 "public", Matrix (), "private")); 575 576 m_meta_package.install_property 577 (make_property (m_meta_package, "PackageList", 578 make_fcn_handle (package_get_packages, 579 "meta.package>get.PackageList"), 580 "public", Matrix (), "private")); 581 582 m_meta_package.install_property 583 (make_property (m_meta_package, "Packages", 584 make_fcn_handle (package_get_packages, 585 "meta.package>get.Packages"), 586 "public", Matrix (), "private")); 587 588 m_meta_package.install_method 589 (make_method (m_meta_package, "fromName", package_fromName, 590 "public", true)); 591 592 m_meta_package.install_method 593 (make_method (m_meta_package, "getAllPackages", package_getAllPackages, 594 "public", true)); 595 596 // create "meta" package 597 cdef_package package_meta 598 = m_meta 599 = make_package ("meta"); 600 601 package_meta.install_class (m_meta_class, "class"); 602 package_meta.install_class (m_meta_property, "property"); 603 package_meta.install_class (m_meta_method, "method"); 604 package_meta.install_class (m_meta_package, "package"); 605 package_meta.install_class (tmp_meta_event, "event"); 606 package_meta.install_class (tmp_meta_dynproperty, "dynproperty"); 607 608 symbol_table& symtab = m_interpreter.get_symbol_table (); 609 610 // install built-in classes into the symbol table 611 symtab.install_built_in_function 612 ("meta.class", m_meta_class.get_constructor_function ()); 613 614 symtab.install_built_in_function 615 ("meta.method", m_meta_method.get_constructor_function ()); 616 617 symtab.install_built_in_function 618 ("meta.property", m_meta_property.get_constructor_function ()); 619 620 symtab.install_built_in_function 621 ("meta.package", m_meta_package.get_constructor_function ()); 622 623 // FIXME: meta.event and meta.dynproperty are not implemented 624 // and should not be installed into symbol table. 625 626 // symtab.install_built_in_function 627 // ("meta.event", tmp_meta_event.get_constructor_function ()); 628 629 // symtab.install_built_in_function 630 // ("meta.dynproperty", tmp_meta_dynproperty.get_constructor_function ()); 631 } 632 633 cdef_class find_class(const std::string & name,bool error_if_not_found,bool load_if_not_found)634 cdef_manager::find_class (const std::string& name, bool error_if_not_found, 635 bool load_if_not_found) 636 { 637 auto it = m_all_classes.find (name); 638 639 if (it == m_all_classes.end ()) 640 { 641 if (load_if_not_found) 642 { 643 octave_value ov_cls; 644 645 std::size_t pos = name.rfind ('.'); 646 647 if (pos == std::string::npos) 648 ov_cls = m_interpreter.find (name); 649 else 650 { 651 std::string pack_name = name.substr (0, pos); 652 653 cdef_package pack = find_package (pack_name, false, true); 654 655 if (pack.ok ()) 656 ov_cls = pack.find (name.substr (pos+1)); 657 } 658 659 if (ov_cls.is_defined ()) 660 it = m_all_classes.find (name); 661 } 662 } 663 664 if (it == m_all_classes.end ()) 665 { 666 if (error_if_not_found) 667 error ("class not found: %s", name.c_str ()); 668 } 669 else 670 { 671 cdef_class cls = it->second; 672 673 if (! cls.is_builtin ()) 674 cls = lookup_class (cls); 675 676 if (cls.ok ()) 677 return cls; 678 else 679 m_all_classes.erase (it); 680 } 681 682 return cdef_class (); 683 } 684 685 octave_value find_method_symbol(const std::string & method_name,const std::string & class_name)686 cdef_manager::find_method_symbol (const std::string& method_name, 687 const std::string& class_name) 688 { 689 cdef_class cls = find_class (class_name, false, false); 690 691 if (cls.ok ()) 692 { 693 cdef_method meth = cls.find_method (method_name); 694 695 if (meth.ok ()) 696 return octave_value (new octave_classdef_meta (meth)); 697 } 698 699 return octave_value (); 700 } 701 702 cdef_package find_package(const std::string & name,bool error_if_not_found,bool load_if_not_found)703 cdef_manager::find_package (const std::string& name, bool error_if_not_found, 704 bool load_if_not_found) 705 { 706 cdef_package retval; 707 708 std::map<std::string, cdef_package>::const_iterator it 709 = m_all_packages.find (name); 710 711 if (it != m_all_packages.end ()) 712 { 713 retval = it->second; 714 715 if (! retval.ok ()) 716 error ("invalid package '%s'", name.c_str ()); 717 } 718 else 719 { 720 load_path& lp = m_interpreter.get_load_path (); 721 722 if (load_if_not_found && lp.find_package (name)) 723 { 724 std::size_t pos = name.rfind ('.'); 725 726 if (pos == std::string::npos) 727 retval = make_package (name, ""); 728 else 729 { 730 std::string parent_name = name.substr (0, pos); 731 732 retval = make_package (name, parent_name); 733 } 734 } 735 else if (error_if_not_found) 736 error ("unknown package '%s'", name.c_str ()); 737 } 738 739 return retval; 740 } 741 742 octave_value find_package_symbol(const std::string & pack_name)743 cdef_manager::find_package_symbol (const std::string& pack_name) 744 { 745 cdef_package pack = find_package (pack_name, false); 746 747 if (pack.ok ()) 748 return octave_value (new octave_classdef_meta (pack)); 749 750 return octave_value (); 751 } 752 753 cdef_class make_class(const std::string & name,const std::list<cdef_class> & super_list)754 cdef_manager::make_class (const std::string& name, 755 const std::list<cdef_class>& super_list) 756 { 757 cdef_class cls (name, super_list); 758 759 cls.set_class (meta_class ()); 760 761 cls.put ("Abstract", false); 762 cls.put ("ConstructOnLoad", false); 763 cls.put ("ContainingPackage", Matrix ()); 764 cls.put ("Description", ""); 765 cls.put ("DetailedDescription", ""); 766 cls.put ("Events", Cell ()); 767 cls.put ("Hidden", false); 768 cls.put ("InferiorClasses", Cell ()); 769 cls.put ("Methods", Cell ()); 770 cls.put ("Properties", Cell ()); 771 cls.put ("Sealed", false); 772 773 if (name == "handle") 774 { 775 cls.put ("HandleCompatible", true); 776 cls.mark_as_handle_class (); 777 } 778 else if (super_list.empty ()) 779 { 780 cls.put ("HandleCompatible", false); 781 } 782 else 783 { 784 bool all_handle_compatible = true; 785 bool has_handle_class = false; 786 787 for (const auto& cl : super_list) 788 { 789 all_handle_compatible = all_handle_compatible 790 && cl.get ("HandleCompatible").bool_value (); 791 792 has_handle_class = has_handle_class || cl.is_handle_class (); 793 } 794 795 if (has_handle_class && ! all_handle_compatible) 796 error ("%s: cannot mix handle and non-HandleCompatible classes", 797 name.c_str ()); 798 799 cls.put ("HandleCompatible", all_handle_compatible); 800 if (has_handle_class) 801 cls.mark_as_handle_class (); 802 } 803 804 if (! name.empty ()) 805 register_class (cls); 806 807 return cls; 808 } 809 810 cdef_class make_class(const std::string & name,const cdef_class & super)811 cdef_manager::make_class (const std::string& name, 812 const cdef_class& super) 813 { 814 return make_class (name, std::list<cdef_class> (1, super)); 815 } 816 817 cdef_class make_meta_class(const std::string & name,const cdef_class & super)818 cdef_manager::make_meta_class (const std::string& name, 819 const cdef_class& super) 820 { 821 cdef_class cls = make_class (name, super); 822 823 cls.put ("Sealed", true); 824 cls.mark_as_meta_class (); 825 826 return cls; 827 } 828 829 cdef_property make_property(const cdef_class & cls,const std::string & name,const octave_value & get_method,const std::string & get_access,const octave_value & set_method,const std::string & set_access)830 cdef_manager::make_property (const cdef_class& cls, const std::string& name, 831 const octave_value& get_method, 832 const std::string& get_access, 833 const octave_value& set_method, 834 const std::string& set_access) 835 { 836 cdef_property prop (name); 837 838 prop.set_class (meta_property ()); 839 840 prop.put ("Description", ""); 841 prop.put ("DetailedDescription", ""); 842 prop.put ("Abstract", false); 843 prop.put ("Constant", false); 844 prop.put ("GetAccess", get_access); 845 prop.put ("SetAccess", set_access); 846 prop.put ("Dependent", false); 847 prop.put ("Transient", false); 848 prop.put ("Hidden", false); 849 prop.put ("GetObservable", false); 850 prop.put ("SetObservable", false); 851 prop.put ("GetMethod", get_method); 852 prop.put ("SetMethod", set_method); 853 prop.put ("DefiningClass", to_ov (cls)); 854 prop.put ("DefaultValue", octave_value ()); 855 prop.put ("HasDefault", false); 856 857 std::string class_name = cls.get_name (); 858 859 if (! get_method.isempty ()) 860 make_function_of_class (class_name, get_method); 861 if (! set_method.isempty ()) 862 make_function_of_class (class_name, set_method); 863 864 return prop; 865 } 866 867 cdef_property make_attribute(const cdef_class & cls,const std::string & name)868 cdef_manager::make_attribute (const cdef_class& cls, const std::string& name) 869 { 870 return make_property (cls, name, Matrix (), "public", Matrix (), "private"); 871 } 872 873 cdef_method make_method(const cdef_class & cls,const std::string & name,const octave_value & fcn,const std::string & m_access,bool is_static)874 cdef_manager::make_method (const cdef_class& cls, const std::string& name, 875 const octave_value& fcn, 876 const std::string& m_access, bool is_static) 877 { 878 cdef_method meth (name); 879 880 meth.set_class (meta_method ()); 881 882 meth.put ("Abstract", false); 883 meth.put ("Access", m_access); 884 meth.put ("DefiningClass", to_ov (cls)); 885 meth.put ("Description", ""); 886 meth.put ("DetailedDescription", ""); 887 meth.put ("Hidden", false); 888 meth.put ("Sealed", true); 889 meth.put ("Static", is_static); 890 891 if (fcn.is_defined ()) 892 make_function_of_class (cls, fcn); 893 894 meth.set_function (fcn); 895 896 if (is_dummy_method (fcn)) 897 meth.mark_as_external (cls.get_name ()); 898 899 return meth; 900 } 901 902 cdef_method make_method(const cdef_class & cls,const std::string & name,octave_builtin::fcn ff,const std::string & m_access,bool is_static)903 cdef_manager::make_method (const cdef_class& cls, const std::string& name, 904 octave_builtin::fcn ff, 905 const std::string& m_access, bool is_static) 906 { 907 octave_value fcn (new octave_builtin (ff, name)); 908 909 return make_method (cls, name, fcn, m_access, is_static); 910 } 911 912 cdef_method make_method(const cdef_class & cls,const std::string & name,octave_builtin::meth mm,const std::string & m_access,bool is_static)913 cdef_manager::make_method (const cdef_class& cls, const std::string& name, 914 octave_builtin::meth mm, 915 const std::string& m_access, bool is_static) 916 { 917 octave_value fcn (new octave_builtin (mm, name)); 918 919 return make_method (cls, name, fcn, m_access, is_static); 920 } 921 922 cdef_package make_package(const std::string & nm,const std::string & parent)923 cdef_manager::make_package (const std::string& nm, const std::string& parent) 924 { 925 cdef_package pack (nm); 926 927 pack.set_class (meta_package ()); 928 929 if (parent.empty ()) 930 pack.put ("ContainingPackage", Matrix ()); 931 else 932 pack.put ("ContainingPackage", to_ov (find_package (parent))); 933 934 if (! nm.empty ()) 935 register_package (pack); 936 937 return pack; 938 } 939 940 octave_value find_method(const std::string & class_name,const std::string & name) const941 cdef_manager::find_method (const std::string& class_name, 942 const std::string& name) const 943 { 944 cdef_class cls = lookup_class (class_name); 945 946 return cls.get_method (name); 947 } 948 } 949