role Perl6::Metamodel::Nominalizable { method nominalizable_kind($obj) { Perl6::Metamodel::Configuration.throw_or_die( 'X::Nominalizable::NoKind', self.HOW.name(self) ~ " doesn't declare method 'nominalizable_kind'", :nominalizable(self) ); } method !find_wrappee($obj, %kind_of, :$lookup = 0) { unless %kind_of{self.nominalizable_kind} { my $my_wrappee := self."!wrappee"($obj); # .^wrappee without a named parameter returns our immediate wrappee return $my_wrappee unless nqp::elems(%kind_of); # If the immediate wrappee is a nominalizable then bypass the request return $my_wrappee.HOW."!find_wrappee"($my_wrappee, %kind_of, :$lookup) if $my_wrappee.HOW.archetypes($my_wrappee).nominalizable; # Don't be aggressive if it's about introspection purposes return nqp::null() if $lookup; # Otherwise the request cannot be completed Perl6::Metamodel::Configuration.throw_or_die( 'X::Nominalizable::NoWrappee', "Can't find requested wrappee on " ~ $*ORIG-NOMINALIZABLE ~ ": reached a nominal type " ~ $my_wrappee.HOW.name($my_wrappee), :nominalizable($*ORIG-NOMINALIZABLE), :kinds(%kind_of), ) } $obj } method wrappee($obj, *%kind_of) { my $*ORIG-NOMINALIZABLE := $obj; self."!find_wrappee"($obj, %kind_of) } method wrappee-lookup($obj, *%kind_of) { self."!find_wrappee"($obj, %kind_of, :lookup) } method coerce($obj, $value) { # In general, this method should be invoked via $type.^wrappee(:coercion). But this would complicate QAST # generated by parameter binding implementation in Actions. So, let it be here. Hopefully, it'd be possible to # remove it either with RakuAST or by implementing corresponding helper nqp:: Raku op for coercive parameter # binding. my $coercion_type := self.wrappee($obj, :coercion); $coercion_type.HOW.coerce($coercion_type, $value) } }