Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Partial fix for multi-method dispatch regression.
  • Loading branch information
jnthn committed Apr 27, 2011
1 parent fef0b59 commit 6ca730b
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 7 deletions.
13 changes: 11 additions & 2 deletions src/HLL/SerializationContextBuilder.pm
Expand Up @@ -356,15 +356,24 @@ class HLL::Compiler::SerializationContextBuilder {
# Adds a method to the meta-object, and stores an event for the action.
# Note that methods are always subject to fixing up since the actual
# compiled code isn't available until compilation is complete.
method pkg_add_method($obj, $meta_method_name, $name, $method_past) {
method pkg_add_method($obj, $meta_method_name, $name, $method_past, $is_dispatcher) {
# See if we already have our compile-time dummy. If not,
# create it.
my $dummy;
if pir::defined($method_past<compile_time_dummy>) {
$dummy := $method_past<compile_time_dummy>;
}
else {
$dummy := pir::clone__PP($stub_code);
# What we create depends on whether it's a dispatcher or not.
# If it is a dispatcher, set the PMC type it uses and then use
# that for the dummy.
if $is_dispatcher {
$method_past.pirflags(':instanceof("DispatcherSub")');
$dummy := pir::assign__0PP(pir::new__Ps('DispatcherSub'), $stub_code);
}
else {
$dummy := pir::clone__PP($stub_code);
}
pir::assign__vPS($dummy, $name);
self.add_code($dummy);
$method_past<compile_time_dummy> := $dummy;
Expand Down
7 changes: 2 additions & 5 deletions src/NQP/Actions.pm
Expand Up @@ -814,17 +814,14 @@ class NQP::Actions is HLL::Actions {
my $name := ~$<private> ~ ~$<deflongname>[0].ast;
$past.name($name);

# If it's a proto, we'll mark it as such setting the sub PMC
# type to DispatcherSub.
if $*MULTINESS eq 'proto' { $past.pirflags(':instanceof("DispatcherSub")'); }

# If it is a multi, we need to build a type signature object for
# the multi-dispatcher to use.
if $*MULTINESS eq 'multi' { attach_multi_signature($past); }

# Insert it into the method table.
my $meta_meth := $*MULTINESS eq 'multi' ?? 'add_multi_method' !! 'add_method';
$*SC.pkg_add_method($*PACKAGE, $meta_meth, $name, $past);
my $is_dispatcher := $*MULTINESS eq 'proto';
$*SC.pkg_add_method($*PACKAGE, $meta_meth, $name, $past, $is_dispatcher);

# Install it in the package also if needed.
if $*SCOPE eq 'our' {
Expand Down
21 changes: 21 additions & 0 deletions src/pmc/dispatchersub.pmc
@@ -1,5 +1,6 @@
/* This extends the Parrot Sub PMC to add various pieces needed for
* multiple dispatch. */
#include "pmc_sub.h"
pmclass DispatcherSub extends Sub auto_attrs dynpmc group nqp {
ATTR PMC *dispatchees; /* Used if this code object is a dispatcher. */
ATTR PMC *dispatch_cache; /* Holds a (multi-)dispatch cache if needed. */
Expand All @@ -20,4 +21,24 @@ pmclass DispatcherSub extends Sub auto_attrs dynpmc group nqp {
SETATTR_DispatcherSub_dispatch_cache(interp, cloned, dispatch_cache);
return cloned;
}

VTABLE void assign_pmc(PMC *other) {
/* It's OK to assign another DispatcherSub or alternatively to
* assign a Parrot Sub (our immediate parent); */
if (other->vtable->base_type == SELF->vtable->base_type ||
other->vtable->base_type == enum_class_Sub) {
Parrot_Sub_attributes *my_sub;
Parrot_Sub_attributes *other_sub;

PMC_get_sub(INTERP, SELF, my_sub);
PMC_get_sub(INTERP, other, other_sub);

/* copy the sub struct */
memmove(my_sub, other_sub, sizeof (Parrot_Sub_attributes));
}
else
Parrot_ex_throw_from_c_args(INTERP, NULL,
EXCEPTION_INVALID_OPERATION,
"Can't assign a non-Sub type to a Sub");
}
}

0 comments on commit 6ca730b

Please sign in to comment.