1/* 2Copyright (C) 2001-2014, Parrot Foundation. 3 4=head1 NAME 5 6src/pmc/role.pmc - Role PMC 7 8=head1 DESCRIPTION 9 10This class implements the Role PMC, a unit of class composition as outlined in 11F<docs/pdds/pdd15_objects.pod>. 12 13Role is not derived from any other PMC. 14 15=head2 Structure 16 17The Role PMC structure (C<Parrot_Role>) consists of five items: 18 19=over 4 20 21=item C<name> 22 23The name of the role -- a STRING. 24An empty STRING is allocated during initialization. 25 26=item C<namespace> 27 28The namespace the role is associated with, if any. 29A Null PMC is allocated during initialization. 30 31=item C<roles> 32 33The list of roles from which this role is composed, if any. 34An empty ResizablePMCArray is allocated during initialization. 35 36=item C<methods> 37 38The directory of method names and methods this role implements. 39An empty Hash PMC is allocated during initialization. 40 41=item C<attrib_metadata> 42 43The directory of attribute names and attribute metadata this role contains. 44An empty Hash PMC is allocated during initialization. 45 46=cut 47 48*/ 49 50#include "pmc/pmc_namespace.h" 51 52/* HEADERIZER HFILE: none */ 53/* HEADERIZER BEGIN: static */ 54/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */ 55 56static void init_role_from_hash(PARROT_INTERP, 57 ARGIN(PMC *self), 58 ARGIN(PMC *info)) 59 __attribute__nonnull__(1) 60 __attribute__nonnull__(2) 61 __attribute__nonnull__(3); 62 63#define ASSERT_ARGS_init_role_from_hash __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ 64 PARROT_ASSERT_ARG(interp) \ 65 , PARROT_ASSERT_ARG(self) \ 66 , PARROT_ASSERT_ARG(info)) 67/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */ 68/* HEADERIZER END: static */ 69 70/* 71 72=item C<static void init_role_from_hash(PARROT_INTERP, PMC *self, PMC *info)> 73 74Takes a hash and initializes the role based on it. 75 76=cut 77 78*/ 79 80static void 81init_role_from_hash(PARROT_INTERP, ARGIN(PMC *self), ARGIN(PMC *info)) 82{ 83 ASSERT_ARGS(init_role_from_hash) 84 Parrot_Role_attributes * const role = PARROT_ROLE(self); 85 STRING * const ns_string = CONST_STRING(interp, "NameSpace"); 86 STRING * const name_str = CONST_STRING(interp, "name"); 87 STRING * const namespace_str = CONST_STRING(interp, "namespace"); 88 STRING * const set_class_str = CONST_STRING(interp, "set_class"); 89 STRING * const roles_str = CONST_STRING(interp, "roles"); 90 STRING * const attributes_str = CONST_STRING(interp, "attributes"); 91 STRING * const methods_str = CONST_STRING(interp, "methods"); 92 93 int have_name, have_ns; 94 PMC *old_ns; 95 int i; 96 97 /* Ensure we actually have some initialization info. */ 98 if (PMC_IS_NULL(info)) 99 return; 100 101 /* Check if we have a name and/or a namespace. */ 102 have_name = VTABLE_exists_keyed_str(interp, info, name_str); 103 104 have_ns = VTABLE_exists_keyed_str(interp, info, namespace_str); 105 106 /* Take a copy of the current namespace the role is attached to. */ 107 old_ns = role->_namespace; 108 109 /* Let's roll (no pun intended!) If we have a namespace and a name, 110 * set both. */ 111 if (have_name && have_ns) { 112 /* If we weren't passed a NameSpace PMC, assume it's something we have 113 * to look one up with and do so. */ 114 PMC *_namespace = VTABLE_get_pmc_keyed_str(interp, info, namespace_str); 115 if (!VTABLE_isa(interp, _namespace, ns_string)) 116 _namespace = Parrot_ns_make_namespace_autobase(interp, _namespace); 117 118 /* If we get something null back it's an error; otherwise, store it. */ 119 if (!PMC_IS_NULL(_namespace)) 120 role->_namespace = _namespace; 121 else 122 Parrot_ex_throw_from_c_noargs(interp, EXCEPTION_GLOBAL_NOT_FOUND, 123 "Namespace not found"); 124 125 /* Set a (string) name. */ 126 role->name = VTABLE_get_string_keyed_str(interp, info, name_str); 127 } 128 129 /* Otherwise, we may just have a name. */ 130 else if (have_name) { 131 /* Set the name. */ 132 role->name = VTABLE_get_string_keyed_str(interp, info, name_str); 133 134 /* Namespace is nested in the current namespace and with the name of 135 * the role. */ 136 role->_namespace = Parrot_ns_make_namespace_keyed_str(interp, 137 Parrot_pcc_get_namespace(interp, CURRENT_CONTEXT(interp)), role->name); 138 } 139 140 /* Otherwise, we may just have a namespace. */ 141 else if (have_ns) { 142 /* If we weren't passed a NameSpace PMC, assume it's something we have 143 * to look one up with and do so. */ 144 PMC *_namespace = VTABLE_get_pmc_keyed_str(interp, info, namespace_str); 145 if (!VTABLE_isa(interp, _namespace, ns_string)) 146 _namespace = Parrot_ns_make_namespace_autobase(interp, _namespace); 147 148 /* If we get something null back it's an error; otherwise, store it. */ 149 if (PMC_IS_NULL(_namespace)) 150 Parrot_ex_throw_from_c_noargs(interp, EXCEPTION_GLOBAL_NOT_FOUND, 151 "Namespace not found"); 152 153 role->_namespace = _namespace; 154 /* Name is that of the most nested part of the namespace. */ 155 role->name = VTABLE_get_string(interp, _namespace); 156 } 157 158 /* If we were attached to a namespce and are now attached to a new one, 159 * need to unset ourselves in the old namespace. */ 160 if (!PMC_IS_NULL(old_ns) && role->_namespace != old_ns) { 161 Parrot_pcc_invoke_method_from_c_args(interp, old_ns, set_class_str, "P->", PMCNULL); 162 } 163 164 /* Link namespace to this role, if there is one. */ 165 if (!PMC_IS_NULL(role->_namespace)) { 166 Parrot_pcc_invoke_method_from_c_args(interp, role->_namespace, set_class_str, "P->", self); 167 } 168 169 /* Initialize roles, if we have any. */ 170 if (VTABLE_exists_keyed_str(interp, info, roles_str)) { 171 /* Loop over roles array and compose them. */ 172 PMC * const role_list = VTABLE_get_pmc_keyed_str(interp, info, roles_str); 173 const int role_count = VTABLE_elements(interp, role_list); 174 175 for (i = 0; i < role_count; ++i) { 176 PMC * const cur_role = VTABLE_get_pmc_keyed_int(interp, role_list, i); 177 VTABLE_add_role(interp, self, cur_role); 178 } 179 } 180 181 /* Initialize attributes, if we have any. */ 182 if (VTABLE_exists_keyed_str(interp, info, attributes_str)) { 183 /* Loop over attributes array and add them. */ 184 PMC * const attrib_name_list = VTABLE_get_pmc_keyed_str(interp, info, attributes_str); 185 186 const int attrib_count = VTABLE_elements(interp, attrib_name_list); 187 188 for (i = 0; i < attrib_count; ++i) { 189 STRING * const attrib_name = VTABLE_get_string_keyed_int(interp, 190 attrib_name_list, i); 191 VTABLE_add_attribute(interp, self, attrib_name, PMCNULL); 192 } 193 } 194 195 /* Initialize methods, if we have any. */ 196 if (VTABLE_exists_keyed_str(interp, info, methods_str)) { 197 /* Get the methods hash. */ 198 PMC * const methods = VTABLE_get_pmc_keyed_str(interp, info, methods_str); 199 200 /* Iterate over the list of methods. */ 201 PMC * const iter = VTABLE_get_iter(interp, methods); 202 203 while (VTABLE_get_bool(interp, iter)) { 204 /* Add the method. */ 205 STRING * const method_name = VTABLE_shift_string(interp, iter); 206 PMC * const method_pmc = 207 VTABLE_get_pmc_keyed_str(interp, methods, method_name); 208 VTABLE_add_method(interp, self, method_name, method_pmc); 209 } 210 } 211 212 /* Extract any methods from the namespace */ 213 Parrot_oo_extract_methods_from_namespace(interp, self, role->_namespace); 214} 215 216/* 217 218=back 219 220=head2 Functions 221 222=over 4 223 224=cut 225 226*/ 227 228pmclass Role auto_attrs { 229 ATTR STRING *name; /* The name of the role. */ 230 ATTR PMC *_namespace; /* The namespace it's linked to, if any. */ 231 ATTR PMC *roles; /* Roles from which this role is composed. */ 232 ATTR PMC *methods; /* Hash of method names to methods. */ 233 ATTR PMC *attrib_metadata; /* Hash of attributes to hashes metadata. */ 234 235/* 236 237=item C<void init()> 238 239Initializes a Role PMC. 240 241=item C<void init_pmc(PMC *init_data)> 242 243Creates a Role and initializes it using the settings from the Hash passed in 244C<init_data>. 245 246=cut 247 248*/ 249 250 VTABLE void init() { 251 Parrot_Role_attributes * const role = 252 (Parrot_Role_attributes *) PMC_data(SELF); 253 254 /* Set flags for custom GC mark. */ 255 PObj_custom_mark_SET(SELF); 256 257 /* Set up the object. */ 258 role->name = CONST_STRING(INTERP, ""); 259 role->_namespace = PMCNULL; 260 role->roles = Parrot_pmc_new(INTERP, enum_class_ResizablePMCArray); 261 role->methods = Parrot_pmc_new(INTERP, enum_class_Hash); 262 role->attrib_metadata = Parrot_pmc_new(INTERP, enum_class_Hash); 263 } 264 265 VTABLE void init_pmc(PMC *init_data) { 266 /* Create the role. */ 267 SELF.init(); 268 269 /* Initialize the role with the supplied data. */ 270 init_role_from_hash(INTERP, SELF, init_data); 271 } 272 273/* 274 275=item C<void mark()> 276 277Mark referenced strings and PMCs in the structure as live. 278 279=cut 280 281*/ 282 283 VTABLE void mark() :no_wb { 284 Parrot_Role_attributes * const role = PARROT_ROLE(SELF); 285 286 Parrot_gc_mark_STRING_alive(INTERP, role->name); 287 Parrot_gc_mark_PMC_alive(INTERP, role->_namespace); 288 Parrot_gc_mark_PMC_alive(INTERP, role->roles); 289 Parrot_gc_mark_PMC_alive(INTERP, role->methods); 290 Parrot_gc_mark_PMC_alive(INTERP, role->attrib_metadata); 291 } 292 293/* 294 295=item C<void add_attribute(STRING *name, PMC *type)> 296 297Adds the given attribute with an optional type. 298Enters the attribute in the C<attributes> array. 299 300=cut 301 302*/ 303 304 VTABLE void add_attribute(STRING *name, PMC *type) { 305 Parrot_Role_attributes * const role = PARROT_ROLE(SELF); 306 PMC * const new_attribute = Parrot_pmc_new(INTERP, enum_class_Hash); 307 308 /* Set name and type. */ 309 VTABLE_set_string_keyed_str(INTERP, new_attribute, CONST_STRING(INTERP, "name"), name); 310 311 if (!PMC_IS_NULL(type)) 312 VTABLE_set_pmc_keyed_str(INTERP, new_attribute, CONST_STRING(INTERP, "type"), type); 313 314 /* Enter the attribute in the attributes array. */ 315 VTABLE_set_pmc_keyed_str(INTERP, role->attrib_metadata, 316 name, new_attribute); 317 } 318 319/* 320 321=item C<void add_method(STRING *name, PMC *sub)> 322 323Adds the given sub PMC as a method with the given name. 324 325=cut 326 327*/ 328 329 VTABLE void add_method(STRING *name, PMC *sub) { 330 Parrot_Role_attributes * const role = PARROT_ROLE(SELF); 331 332 /* If we have already added a method with this name... */ 333 if (VTABLE_exists_keyed_str(INTERP, role->methods, name)) { 334 /* XXX Need to handle multi methods here. */ 335 Parrot_ex_throw_from_c_noargs(INTERP, EXCEPTION_UNIMPLEMENTED, 336 "Currently, adding multiple methods of the same name" 337 " is not supported."); 338 } 339 else { 340 /* Enter it into the table. */ 341 VTABLE_set_pmc_keyed_str(INTERP, role->methods, name, sub); 342 } 343 } 344 345/* 346 347=item C<void remove_method(STRING *name, PMC *sub)> 348 349Removes the method with the given name. 350 351=cut 352 353*/ 354 VTABLE void remove_method(STRING *name) { 355 Parrot_Role_attributes * const role = PARROT_ROLE(SELF); 356 if (VTABLE_exists_keyed_str(INTERP, role->methods, name)) 357 VTABLE_delete_keyed_str(INTERP, role->methods, name); 358 else 359 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION, 360 "No method named '%S' to remove in role '%S'.", 361 name, VTABLE_get_string(INTERP, SELF)); 362 } 363 364/* 365 366=item C<void add_role(PMC *role)> 367 368Composes the supplied Role PMC into this role, provided there are no 369conflicts. 370 371=cut 372 373*/ 374 375 VTABLE void add_role(PMC *role) { 376 Parrot_Role_attributes * const this_role = PARROT_ROLE(SELF); 377 378 /* Do the composition. */ 379 Parrot_ComposeRole(INTERP, role, PMCNULL, 0, PMCNULL, 0, 380 this_role->methods, this_role->roles); 381 } 382 383 384/* 385 386=item C<PMC *inspect_str(STRING *what)> 387 388Provides introspection of a specific piece of information about the role. The 389available information is: 390 391=over 4 392 393=item name - String PMC containing the name of the role 394 395=item namespce - NameSpace PMC of the namespace attached to the role 396 397=item attributes - Hash keyed on attribute name, value is hash describing it 398 399=item methods - Hash keyed on method name, value is an invokable PMC. Includes 400methods composed in from roles. 401 402=item roles - Array of Role PMCs. Includes roles done by the roles that were 403composed into this role. 404 405=back 406 407=cut 408 409*/ 410 411 VTABLE PMC *inspect_str(STRING *what) :no_wb { 412 Parrot_Role_attributes * const role = PARROT_ROLE(SELF); 413 414 /* What should we return? */ 415 PMC *found; 416 417 if (STRING_equal(INTERP, what, CONST_STRING(INTERP, "name"))) { 418 found = Parrot_pmc_new(INTERP, enum_class_String); 419 VTABLE_set_string_native(INTERP, found, role->name); 420 } 421 else if (STRING_equal(INTERP, what, CONST_STRING(INTERP, "namespace"))) { 422 /* Don't clone the namespace, as it's not part of our state. */ 423 return role->_namespace; 424 } 425 else if (STRING_equal(INTERP, what, CONST_STRING(INTERP, "attributes"))) { 426 found = role->attrib_metadata; 427 } 428 else if (STRING_equal(INTERP, what, CONST_STRING(INTERP, "methods"))) { 429 found = role->methods; 430 } 431 else if (STRING_equal(INTERP, what, CONST_STRING(INTERP, "roles"))) { 432 found = role->roles; 433 } 434 else { 435 Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_INVALID_OPERATION, 436 "Unknown introspection value '%S'", what); 437 } 438 439 /* Clone and return. */ 440 if (PMC_IS_NULL(found)) { return PMCNULL; } 441 if (found->vtable->base_type == enum_class_Hash) { 442 /* for Hash return values, create and return a shallow 443 * clone because the VTABLE_clone does a deep clone */ 444 PMC * const hash = Parrot_pmc_new(INTERP, enum_class_Hash); 445 PMC * const iter = VTABLE_get_iter(INTERP, found); 446 while (VTABLE_get_bool(INTERP, iter)) { 447 STRING * const key = VTABLE_shift_string(INTERP, iter); 448 PMC * const value = VTABLE_get_pmc_keyed_str(INTERP, found, key); 449 VTABLE_set_pmc_keyed_str(INTERP, hash, key, value); 450 } 451 return hash; 452 } 453 return VTABLE_clone(INTERP, found); 454 } 455 456 457/* 458 459=item C<PMC *inspect()> 460 461Returns a Hash describing the role, with key/value pairs as described in 462inspect_str. 463 464=cut 465 466*/ 467 468 VTABLE PMC *inspect() :no_wb { 469 /* Create a hash, then use inspect_str to get all of the data to 470 * fill it up with. */ 471 PMC * const metadata = Parrot_pmc_new(INTERP, enum_class_Hash); 472 473 STRING * const name = CONST_STRING(INTERP, "name"); 474 STRING * const _namespace = CONST_STRING(INTERP, "namespace"); 475 STRING * const attributes = CONST_STRING(INTERP, "attributes"); 476 STRING * const methods = CONST_STRING(INTERP, "methods"); 477 STRING * const roles = CONST_STRING(INTERP, "roles"); 478 479 VTABLE_set_pmc_keyed_str(INTERP, metadata, name, 480 VTABLE_inspect_str(INTERP, SELF, name)); 481 482 VTABLE_set_pmc_keyed_str(INTERP, metadata, _namespace, 483 VTABLE_inspect_str(INTERP, SELF, _namespace)); 484 485 VTABLE_set_pmc_keyed_str(INTERP, metadata, attributes, 486 VTABLE_inspect_str(INTERP, SELF, attributes)); 487 488 VTABLE_set_pmc_keyed_str(INTERP, metadata, methods, 489 VTABLE_inspect_str(INTERP, SELF, methods)); 490 491 VTABLE_set_pmc_keyed_str(INTERP, metadata, roles, 492 VTABLE_inspect_str(INTERP, SELF, roles)); 493 return metadata; 494 } 495 496/* 497 498=item C<STRING *get_string()> 499 500Return the name of the role (without the HLL namespace). 501 502=cut 503 504*/ 505 506 VTABLE STRING *get_string() :no_wb { 507 const Parrot_Role_attributes * const role = PARROT_ROLE(SELF); 508 PMC * const _namespace = role->_namespace; 509 510 if (!PMC_IS_NULL(_namespace)) { 511 /* Call the 'get_name' method on the role's associated namespace 512 * to retrieve a fully qualified list of names, then join the list 513 * with a semicolon. 514 */ 515 PMC * const names = Parrot_ns_get_name(INTERP, _namespace); 516 517 if (!PMC_IS_NULL(names)) { 518 /* remove the HLL namespace name */ 519 VTABLE_shift_string(INTERP, names); 520 return Parrot_str_join(INTERP, CONST_STRING(INTERP, ";"), names); 521 } 522 } 523 524 /* Otherwise, copy the stored string name of the class. */ 525 return role->name; 526 } 527 528/* 529 530=item C<INTVAL does(STRING *rolename)> 531 532Returns whether the class does the role with the given C<*rolename>. 533 534=cut 535 536*/ 537 VTABLE INTVAL does(STRING *role_name) :no_wb { 538 const Parrot_Role_attributes * const role = PARROT_ROLE(SELF); 539 INTVAL i, count; 540 541 if (STRING_equal(INTERP, role->name, role_name)) 542 return 1; 543 544 count = VTABLE_elements(INTERP, role->roles); 545 for (i = 0; i < count; ++i) { 546 PMC * const cur_role = VTABLE_get_pmc_keyed_int(INTERP, role->roles, i); 547 if (VTABLE_does(INTERP, cur_role, role_name)) 548 return 1; 549 } 550 551 return 0; 552 } 553 554/* 555 556=item C<INTVAL does_pmc(PMC *role)> 557 558Returns whether the class does the given C<*role>. 559 560=cut 561 562*/ 563 VTABLE INTVAL does_pmc(PMC *role) :no_wb { 564 const Parrot_Role_attributes * const this_role = PARROT_ROLE(SELF); 565 INTVAL i, count; 566 567 if (role == SELF) 568 return 1; 569 570 count = VTABLE_elements(INTERP, this_role->roles); 571 for (i = 0; i < count; ++i) { 572 PMC * const cur_role = VTABLE_get_pmc_keyed_int(INTERP, this_role->roles, i); 573 if (VTABLE_does_pmc(INTERP, cur_role, role)) 574 return 1; 575 } 576 577 return 0; 578 } 579 580 /* 581 * Below here are methods that eventually will go in a role 582 * that is composed into here to optionally give a nice interface from 583 * PIR (ParrotRole isa Role does RoleMethods or something like this). 584 */ 585 586 587/* 588 589=back 590 591=head2 Methods 592 593=over 4 594 595=item C<METHOD 596 name(STRING *name :optional, int got_name :opt_flag)> 597 598Sets the name of the role, and updates the namespace accordingly. 599 600=cut 601 602*/ 603 604 METHOD name(STRING *name :optional, int got_name :opt_flag) { 605 Parrot_Role_attributes *role = PARROT_ROLE(SELF); 606 STRING *ret_name = NULL; 607 608 if (got_name) { 609 /* We'll build a hash just containing the name, then give this to 610 * init_role_from_hash - saves some code duplication. */ 611 PMC * const naming_hash = Parrot_pmc_new(INTERP, enum_class_Hash); 612 VTABLE_set_string_keyed_str(INTERP, naming_hash, CONST_STRING(INTERP, "name"), name); 613 init_role_from_hash(INTERP, SELF, naming_hash); 614 } 615 616 ret_name = role->name; 617 RETURN(STRING *ret_name); 618 } 619 620 621/* 622 623=item C<METHOD 624 get_namespace()> 625 626Gets the namespace associated with this role, if any. 627 628=cut 629 630*/ 631 632 METHOD get_namespace() :no_wb { 633 PMC * const ret_namespace = PARROT_ROLE(SELF)->_namespace; 634 RETURN(PMC *ret_namespace); 635 } 636 637 638/* 639 640=item C<METHOD 641 attributes()> 642 643Return a hash where the keys are attribute names and the values are hashes 644providing a set of key/value pairs describing the attribute. 645 646=cut 647 648*/ 649 METHOD attributes() :no_wb { 650 PMC * const ret_attrib_metadata = VTABLE_inspect_str(INTERP, SELF, CONST_STRING(INTERP, "attributes")); 651 RETURN(PMC *ret_attrib_metadata); 652 } 653 654 655/* 656 657=item C<METHOD 658 add_attribute(STRING *attribute_name, 659 PMC *attribute_type :optional, int got_type :opt_flag)> 660 661Add an attribute to the role. Requires a name and, optionally, a type. 662 663=cut 664 665*/ 666 METHOD add_attribute(STRING *attribute_name, 667 PMC *attribute_type :optional, int got_type :opt_flag) { 668 VTABLE_add_attribute(INTERP, SELF, attribute_name, 669 got_type ? attribute_type : PMCNULL); 670 } 671 672 673/* 674 675=item C<METHOD methods()> 676 677Return a hash where the keys are method names and the values are methods. 678 679=cut 680 681*/ 682 METHOD methods() :no_wb { 683 PMC * const ret_methods = VTABLE_inspect_str(INTERP, SELF, CONST_STRING(INTERP, "methods")); 684 RETURN(PMC *ret_methods); 685 } 686 687 688/* 689 690=item C<METHOD add_method(STRING *name, PMC *sub)> 691 692Adds the given sub PMC as a method with the given name. 693 694=cut 695 696*/ 697 METHOD add_method(STRING *name, PMC *sub) { 698 VTABLE_add_method(INTERP, SELF, name, sub); 699 } 700 701/* 702 703=item C<void remove_method(STRING *name)> 704 705Removes the method with the given name. 706 707=cut 708 709*/ 710 METHOD remove_method(STRING *name) { 711 VTABLE_remove_method(INTERP, SELF, name); 712 } 713 714 715/* 716 717=item C<METHOD roles()> 718 719Return the roles array PMC. 720 721=cut 722 723*/ 724 METHOD roles() :no_wb { 725 PMC * const ret_roles = VTABLE_inspect_str(INTERP, SELF, CONST_STRING(INTERP, "roles")); 726 RETURN(PMC *ret_roles); 727 } 728 729 730/* 731 732=item C<METHOD 733 add_role(PMC *role, 734 PMC *exclude_method :optional :named("exclude_method"), 735 int got_exclude_method :opt_flag, 736 PMC *alias_method :optional :named("alias_method"), 737 int got_alias_method :opt_flag)> 738 739Compose the given role into this one, using the given exclusions and aliases. 740 741=cut 742 743*/ 744 METHOD add_role(PMC *role, 745 PMC *exclude_method :optional :named("exclude_method"), 746 int got_exclude_method :opt_flag, 747 PMC *alias_method :optional :named("alias_method"), 748 int got_alias_method :opt_flag) { 749 Parrot_Role_attributes *role_info = PARROT_ROLE(SELF); 750 STRING *s_name = NULL; 751 STRING *r_name = NULL; 752 753 (STRING *s_name) = PCCINVOKE(INTERP, SELF, "name"); 754 (STRING *r_name) = PCCINVOKE(INTERP, role, "name"); 755 UNUSED(s_name); 756 UNUSED(r_name); 757 758 Parrot_ComposeRole(INTERP, role, exclude_method, got_exclude_method, 759 alias_method, got_alias_method, 760 role_info->methods, role_info->roles); 761 } 762 763/* 764 765=item C<void inspect(STRING *what :optional)> 766 767Gets all introspection data for the role or, if the optional string 768parameter is supplied, a particular item of introspection data. 769 770=cut 771 772*/ 773 METHOD inspect(STRING *what :optional, int got_what :opt_flag) :no_wb { 774 PMC *found; 775 776 /* Just delegate to the appropriate vtable. */ 777 if (got_what) 778 found = VTABLE_inspect_str(INTERP, SELF, what); 779 else 780 found = VTABLE_inspect(INTERP, SELF); 781 782 RETURN(PMC *found); 783 } 784 785/* 786 787=item C<void does(STRING *role)> 788 789Returns true if this role (or any role composed into this one) performs the 790named role. This will recurse through all roles as far back as it can. 791 792=cut 793 794*/ 795 796 METHOD does(STRING *name) :no_wb { 797 const INTVAL does = VTABLE_does(INTERP, SELF, name); 798 RETURN(INTVAL does); 799 } 800 801} /* end pmclass Role */ 802 803 804/* 805 806=back 807 808=head1 STABILITY 809 810Unstable. This PMC is under active development; major portions of the 811interface have not yet been completed. 812 813=head1 SEE ALSO 814 815F<docs/pdds/pdd15_objects.pod>. 816 817=cut 818 819*/ 820 821/* 822 * Local variables: 823 * c-file-style: "parrot" 824 * End: 825 * vim: expandtab shiftwidth=4 cinoptions='\:2=2' : 826 */ 827