Index: src/pmc/pmcproxy.pmc =================================================================== --- src/pmc/pmcproxy.pmc (revision 45246) +++ src/pmc/pmcproxy.pmc (working copy) @@ -318,15 +318,12 @@ */ VTABLE INTVAL does(STRING *role_name) { - Parrot_Class_attributes *_class = PARROT_CLASS(SELF); - INTVAL id = _class->id; - PMC *proxied = Parrot_pmc_new(interp, id); - - if (VTABLE_does(interp, proxied, role_name)) + Parrot_Class_attributes * const attrs = PARROT_CLASS(SELF); + const INTVAL id = attrs->id; + const INTVAL type_does = Parrot_pmc_type_does(INTERP, role_name, id); + if (type_does) return 1; - - return VTABLE_isa(interp, proxied, role_name); - + return VTABLE_isa(INTERP, SELF, role_name); } /* Index: src/pmc/default.pmc =================================================================== --- src/pmc/default.pmc (revision 45246) +++ src/pmc/default.pmc (working copy) @@ -280,52 +280,6 @@ return prop; } -/* - -=item C - -Compares C<*method> and C<*what>. -Returns true (1) if B is found in B, false (0) otherwise. - -=cut - -*/ - -static INTVAL -does_isa(PARROT_INTERP, ARGIN(const STRING *method), ARGIN(const STRING *what)) -{ - const INTVAL length = Parrot_str_byte_length(interp, what); - INTVAL pos = 0; - - do { - INTVAL len; - INTVAL idx = Parrot_str_find_index(interp, what, method, (INTVAL)pos); - - if (idx < 0) - return 0; - - pos = idx; - - if (pos >= length) - return 0; - - len = Parrot_str_byte_length(interp, method); - - if (pos && Parrot_str_indexed(interp, what, pos - 1) != 32) { - pos += len; - continue; - } - - if (pos + len < length && Parrot_str_indexed(interp, what, pos + len) != 32) { - pos += len; - continue; - } - - return 1; - } while (1); -} - pmclass default abstract { /* @@ -919,7 +873,7 @@ */ VTABLE INTVAL does(STRING *_interface) { - return does_isa(INTERP, _interface, SELF->vtable->provides_str); + return Parrot_pmc_type_does(INTERP, _interface, SELF->vtable->base_type); } /* Index: src/pmc.c =================================================================== --- src/pmc.c (revision 45246) +++ src/pmc.c (working copy) @@ -963,6 +963,53 @@ /* +=item C + +Checks to see if PMCs of the given type does the given role. Checks +C<provides_str>> to find a match. +Returns true (1) if B is found, false (0) otherwise. + +=cut + +*/ + +INTVAL +Parrot_pmc_type_does(PARROT_INTERP, ARGIN(STRING *role), INTVAL type) +{ + INTVAL pos = 0; + STRING * const what = interp->vtables[type]->provides_str; + INTVAL length = Parrot_str_byte_length(interp, what); + + do { + INTVAL len; + INTVAL idx = Parrot_str_find_index(interp, what, role, (INTVAL)pos); + + if (idx < 0) + return 0; + + pos = idx; + + if (pos >= length) + return 0; + + len = Parrot_str_byte_length(interp, role); + + if (pos && Parrot_str_indexed(interp, what, pos - 1) != 32) { + pos += len; + continue; + } + + if (pos + len < length && Parrot_str_indexed(interp, what, pos + len) != 32) { + pos += len; + continue; + } + + return 1; + } while (1); +} + +/* + =back =head1 SEE ALSO Index: include/parrot/pmc.h =================================================================== --- include/parrot/pmc.h (revision 45246) +++ include/parrot/pmc.h (working copy) @@ -148,6 +148,12 @@ PMC * Parrot_pmc_new_temporary(PARROT_INTERP, INTVAL base_type) __attribute__nonnull__(1); +INTVAL Parrot_pmc_type_does(PARROT_INTERP, + ARGIN(STRING *method), + INTVAL type) + __attribute__nonnull__(1) + __attribute__nonnull__(2); + #define ASSERT_ARGS_Parrot_pmc_create_mro __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ PARROT_ASSERT_ARG(interp)) #define ASSERT_ARGS_Parrot_pmc_destroy __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ @@ -203,6 +209,9 @@ PARROT_ASSERT_ARG(interp)) #define ASSERT_ARGS_Parrot_pmc_new_temporary __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ PARROT_ASSERT_ARG(interp)) +#define ASSERT_ARGS_Parrot_pmc_type_does __attribute__unused__ int _ASSERT_ARGS_CHECK = (\ + PARROT_ASSERT_ARG(interp) \ + , PARROT_ASSERT_ARG(method)) /* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */ /* HEADERIZER END: src/pmc.c */ Index: t/pmc/handle.t =================================================================== --- t/pmc/handle.t (revision 45246) +++ t/pmc/handle.t (working copy) @@ -20,14 +20,36 @@ .sub main :main .include 'test_more.pir' - plan(1) + plan(2) + 'test_create'() + 'test_does_tt_1473'() +.end + +.sub 'test_create' push_eh cant_instantiate $P0 = new 'Handle' - print "not " + ok(0, "Can instantiate an abstract type") + pop_eh + goto create_end cant_instantiate: - say "ok 1" + ok(1, "Cannot instantiate an abstract type") + pop_eh + create_end: .end +.sub 'test_does_tt_1473' + push_eh cant_do_does + $P0 = get_class 'Handle' + $I0 = does $P0, 'Handle' + ok($I0, "Handle does Handle") + goto does_end + cant_do_does: + ok(0, "Does throws an exception") + does_end: + pop_eh +.end + + # Local Variables: # mode: pir # fill-column: 100