What jumps out to me is the difference between a normal method and a
metamethod; the latter might not do sufficient validation, so you're
catching the exception from trying to invoke .gist. And that just happens
to do the right thing in your case; if you're getting a VMNull from an
implementation-internal name (possibly something in NQP which leads to a
VMNull if you try to treat it as a P6 object), that would be likely.

On Mon, Oct 29, 2018 at 10:37 PM Joseph Brenner <doom...@gmail.com> wrote:

> I've got a weird one here... a line that looks like it does
> nothing significant is needed for the code to work.
> If the line below marked "The Mystery Line" is commented out,
> you just get the error:
>
>    ===SORRY!===
>    Cannot look up attributes in a VMNull type object
>
> Augment::Util:
>
> class Recomposer {
>     method recompose_core {
>         my @type_symbols = (|CORE::).grep({ .key eq .value.^name
> }).map( *.value );
>         for @type_symbols -> $type_symbol {
>             my $type_symbol_name = $type_symbol.^name;
>             try {
>                 my $nada = $type_symbol.gist;  # The Mystery Line
>                 $type_symbol.^compose;
>                 # if there's no ^.compose method, just skip to next
> type symbol object
>                 CATCH {
>                     default { }
>                 }
>             }
>         }
>     }
> }
>
>
> The problem seems to be local to that "recompose_core" routine,
> though just to be complete I'll tack on the rest of my code...
> sorry about the length, it's hard to strip it down much further
> than this.
>
> The goal here is to be able to start the repl with the command:
>
>   perl6 -Mmethod-menu
>
> And have a new method (something like .^methods) named simply .m
> available everywhere.
>
>
> method-menu:
>
> use Object::Examine;
> use Augment::Util;
> use MONKEY-TYPING;
> augment class Any does Introspector {
>     method m {
>         return self.menu;
>     }
>     Recomposer.recompose_core();
> }
>
>
> Object::Examine:
>
> role Introspector {
>     method menu {
>         my @seen_methods = ();
>         my @levels  = self.^mro; # better than ^parents: current class and
> above
>         my $report = '';
>         my @data;
>         for @levels -> $l {
>             my $level_name     = $l.^name;
>             my @current_methods  = clean_methods( methods_for( $l ) );
>             my @child_methods = ( @current_methods (-) @seen_methods
> ).keys;
>             # saving up the data...
>             for @child_methods -> $cm {
>                 @data.push([$cm, $level_name]);
>             }
>             @seen_methods = ( @seen_methods (+) @current_methods ).keys;
>         }
>         my @lines = @data.sort({ $_[0] });
>         for @lines -> $l {
>             my $fmt = "%-25s %-25s\n";
>             $report ~= sprintf $fmt, $l[0], $l[1];
>         }
>         return $report;
>     }
>     sub methods_for(Mu $obj) {
>         my @raws = $obj.^methods(:local);  # or :all?
>     }
>     sub clean_methods (@raws) {
>         my @strs = @raws.map({ .gist });
>         my @ways = @strs.sort;
>         my @unis = @ways.unique;
>         # filter out methods 'Method+{is-nodal}.new' and 'menu'
>         my @trim = @unis.grep({ ! /^ Method\+\{is\-nodal\}\.new /
> }).grep({ ! / ^ (menu) \s* $ / });
>     }
> }
>
> 01-method-menu.t:
>
> use v6;
> use Test;
> use method-menu;
> my $test_case = "'use method-menu;' and the 'm' method";
> subtest {
>   my $report1 = (Array).m;
>   my @report1 = $report1.lines;
>   my $l1 = @report1.elems;  # 203
>   cmp-ok($l1, '>', 24, "report1 shows over 24 methods: $l1");
> }, $test_case;
> done-testing();
>


-- 
brandon s allbery kf8nh
allber...@gmail.com

Reply via email to