"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/Perl6/Metamodel/MultiMethodContainer.nqp" between
rakudo-2020.09.tar.gz and rakudo-2020.10.tar.gz

About: Rakudo is a compiler for the Raku Pogramming Language (formerly known as Perl 6).

MultiMethodContainer.nqp  (rakudo-2020.09):MultiMethodContainer.nqp  (rakudo-2020.10)
role Perl6::Metamodel::MultiMethodContainer { role Perl6::Metamodel::MultiMethodContainer {
# Set of multi-methods to incorporate. Not just the method handles; # Set of multi-methods to incorporate. Not just the method handles;
# each is a hash containing keys name and body. # each is a hash containing keys name and body.
has @!multi_methods_to_incorporate; has @!multi_methods_to_incorporate;
has %!multi_candidate_names; has %!multi_candidate_names;
# The proto we'll clone. # The proto we'll clone.
my $autogen_proto; my $autogen_method_proto;
my $autogen_submethod_proto;
# Sets the proto we'll auto-gen based on. # Sets the proto we'll auto-gen based on.
method set_autogen_proto($proto) { method set_autogen_proto($method_proto, $submethod_proto) {
$autogen_proto := $proto $autogen_method_proto := $method_proto;
$autogen_submethod_proto := $submethod_proto;
} }
# We can't incorporate multis right away as we don't know all parents # We can't incorporate multis right away as we don't know all parents
# yet, maybe, which influences whether we even can have multis, need to # yet, maybe, which influences whether we even can have multis, need to
# generate a proto and so forth. So just queue them up in a todo list and # generate a proto and so forth. So just queue them up in a todo list and
# we handle it at class composition time. # we handle it at class composition time.
method add_multi_method($obj, $name, $code_obj) { method add_multi_method($obj, $name, $code_obj) {
# Represents a multi candidate to incorporate. # Represents a multi candidate to incorporate.
my class MultiToIncorporate { my class MultiToIncorporate {
has $!name; has $!name;
skipping to change at line 44 skipping to change at line 46
# Gets the multi methods that are to be incorporated. # Gets the multi methods that are to be incorporated.
method multi_methods_to_incorporate($obj) { method multi_methods_to_incorporate($obj) {
@!multi_methods_to_incorporate @!multi_methods_to_incorporate
} }
# Incorporates the multi candidates into the appropriate proto. Need to # Incorporates the multi candidates into the appropriate proto. Need to
# implement proto incorporation yet. # implement proto incorporation yet.
method incorporate_multi_candidates($obj) { method incorporate_multi_candidates($obj) {
my $num_todo := +@!multi_methods_to_incorporate; my $num_todo := +@!multi_methods_to_incorporate;
my $i := 0; my $i := 0;
my $submethod_type := Perl6::Metamodel::Configuration.submethod_type;
my @new_protos; my @new_protos;
while $i != $num_todo { while $i != $num_todo {
# Get method name and code. # Get method name and code.
my $name := @!multi_methods_to_incorporate[$i].name; my $name := @!multi_methods_to_incorporate[$i].name;
my $code := @!multi_methods_to_incorporate[$i].code; my $code := @!multi_methods_to_incorporate[$i].code;
# Do we have anything in the methods table already in # Do we have anything in the methods table already in
# this class? # this class?
my %meths := nqp::hllize(self.method_table($obj)); my $is_submethod := nqp::istype(nqp::what($code), $submethod_type);
my $method_table := $is_submethod
?? 'submethod_table'
!! 'method_table';
my $autogen_proto := $is_submethod
?? $autogen_submethod_proto
!! $autogen_method_proto;
my %meths := nqp::hllize(self."$method_table"($obj));
if nqp::existskey(%meths, $name) { if nqp::existskey(%meths, $name) {
# Yes. Only or dispatcher, though? If only, error. If # Yes. Only or dispatcher, though? If only, error. If
# dispatcher, simply add new dispatchee. # dispatcher, simply add new dispatchee.
my $dispatcher := %meths{$name}; my $dispatcher := %meths{$name};
if $dispatcher.is_dispatcher { if $dispatcher.is_dispatcher {
$dispatcher.add_dispatchee($code); $dispatcher.add_dispatchee($code);
} }
else { else {
nqp::die("Cannot have a multi candidate for '" ~ $name ~ nqp::die("Cannot have a multi candidate for '" ~ $name ~
"' when an only method is also in the package '" ~ "' when an only method is also in the package '" ~
self.name($obj) ~ "'"); self.name($obj) ~ "'");
} }
} }
else { else {
# Go hunting in the MRO for a proto.
my @mro := self.mro($obj);
my $j := 1;
my $found := 0; my $found := 0;
while $j != +@mro && !$found { unless $is_submethod {
my $parent := @mro[$j]; # Go hunting in the MRO for a method proto. Note that we don
my %meths := nqp::hllize($parent.HOW.method_table($parent)); 't traverse MRO for submethods.
if nqp::existskey(%meths, $name) { my @mro := self.mro($obj);
# Found a possible - make sure it's a dispatcher, not my $j := 1;
# an only. while $j != +@mro && !$found {
my $dispatcher := %meths{$name}; my $parent := @mro[$j];
if $dispatcher.is_dispatcher { my %meths := nqp::hllize($parent.HOW."$method_table"($pa
# Clone it and install it in our method table. rent));
my $copy := $dispatcher.derive_dispatcher(); if nqp::existskey(%meths, $name) {
$copy.add_dispatchee($code); # Found a possible - make sure it's a dispatcher, no
self.add_method($obj, $name, $copy); t
nqp::push(@new_protos, $copy); # an only.
$found := 1; my $dispatcher := %meths{$name};
if $dispatcher.is_dispatcher {
# Clone it and install it in our method table.
my $copy := $dispatcher.derive_dispatcher();
$copy.add_dispatchee($code);
self.add_method($obj, $name, $copy);
nqp::push(@new_protos, $copy);
$found := 1;
}
} }
$j := $j + 1;
} }
$j := $j + 1;
} }
unless $found { unless $found {
# No proto found, so we'll generate one here. # No proto found, so we'll generate one here.
unless $autogen_proto { unless $autogen_proto {
nqp::die("Cannot auto-generate a proto method for '$name ' in the setting"); nqp::die("Cannot auto-generate a proto method for '$name ' in the setting");
} }
my $proto := $autogen_proto.instantiate_generic( my $proto := $autogen_proto.instantiate_generic(
nqp::hash('T', $obj)); nqp::hash('T', $obj));
$proto.set_name($name); $proto.set_name($name);
$proto.add_dispatchee($code); $proto.add_dispatchee($code);
 End of changes. 8 change blocks. 
22 lines changed or deleted 37 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)