Hello, Perl6'ers.
When dealing with objects, sometimes you'd like to keep outside code from running methods from your class. To this effect, I have tried to bring a semblance of the protected method to Perl6.
I can sum up much of the problem with the following few pieces of code.
role GTK::Roles::Protection {
has @!prefixes;
# cw: This is a HACK, but it should work with careful use.
method CALLING-METHOD($nf is copy = 3) {
my $c = callframe($nf).code;
while $c !~~ Routine {
my $cf = callframe(++$nf);
die 'Exceeded backtrace when searching for calling routine'
if $cf ~~ Failure;
$c = $cf.code;
# Special casing. It's (not) FUUUN!
next if $c.^name eq <NQPRoutine Block>.any;
# Special casing is hell! -- Allow for shortcircuit
$c.^name.say;
unless
$c.package.^name ne <
GLOBAL Any::IterateOneWithoutPhasers List
>.any
##||
#'is-hidden-from-backtrace' ∈ $c.^roles.map( .^name )
{
$c = False;
next;
}
}
"{ $c.package.^name }.{ $c.name }";
}
# Do NOT use this method unless you are adding a widget. If adding widgets,
# please be sure to use a discrete namespace for them.
#
# For example:
# - It is not sufficient to self.ADD-PREFIX('YourProject') if
# the YourProject:: code has non-GTK derivative code. In that case, it
# would be appreciated if you would put all widgets into the
# YourProject::Widgets namespace and then you can do:
# self.ADD-PREFIX('YourProject::Widgets::')
# in submethod BUILD.
#
# THANKS!
method ADD-PREFIX($p) {
@!prefixes.push: $p;
}
# Should never be called ouside of the GTK::Widget hierarchy, but
# how can the watcher watch itself?
method IS-PROTECTED {
# Really kinda violates someone's idea of "object-oriented" somewhere,
# but I am more results-oriened.
my $c = self.CALLING-METHOD;
# Must be done, otherwise error. Note: Regexes do not like attributes.
#my @p = @!prefixes;
my $t = False;
# Hardcoded 'GTK::'. There should be a better mechanism to do this, but
# we use what works.
for 'GTK::', |@!prefixes {
last if ( $t = $c.starts-with($_) );
}
die "Cannot call method from outside of a GTK:: object ({ $c })"
unless $t;
True;
}
}
The point of this piece of code is to use the callframe function to step back through the frames to find the first non-internal routine and check if its name is acceptable.
However I am now getting this error from a piece of code that uses this protection. I thought an --ll-exception would shed some light on the topic, but unfortunately, it does not.
perl6 --ll-exception -I../cairo-p6-paths/lib -I../p6-Pango/lib -I../p6-GtkPlus/lib -Ilib t/04-simple-ui.t Cannot resolve caller ACCEPTS(Routine:U: NQPRoutine); none of these signatures match:
(Mu:U: \topic, *%_)
(Mu:U: Mu:U \topic, *%_)
(Any:D: Mu:D \a, *%_)
(Any:D: Mu:U, *%_ --> Bool::False)
(Any:U: \topic, *%_ --> Bool)
(Code:D $self: Mu $topic is raw, *%_)
in method CALLING-METHOD at /home/cbwood/Projects/p6-WebkitGtk/../p6-GtkPlus/lib/GTK/Roles/Protection.pm6 (GTK::Roles::Protection) line 8
in method IS-PROTECTED at /home/cbwood/Projects/p6-WebkitGtk/../p6-GtkPlus/lib/GTK/Roles/Protection.pm6 (GTK::Roles::Protection) line 53
in method RESOLVE-UINT at /home/cbwood/Projects/p6-WebkitGtk/../p6-GtkPlus/lib/GTK/Roles/Types.pm6 (GTK::Roles::Types) line 80
in block at /home/cbwood/Projects/p6-WebkitGtk/../p6-GtkPlus/lib/GTK/Widget.pm6 (GTK::Widget) line 1169
in block <unit> at t/04-simple-ui.t line 76
Any ideas on how to sidestep or solve this problem?