Skip to content

Commit

Permalink
Pull in rest of multi-dispatch code.
Browse files Browse the repository at this point in the history
  • Loading branch information
jnthn committed Feb 7, 2013
1 parent c8228f6 commit ac11f0c
Showing 1 changed file with 104 additions and 0 deletions.
104 changes: 104 additions & 0 deletions nqp-src/NQPCORE.setting
Expand Up @@ -247,6 +247,108 @@ my knowhow NQPRoutine {
return @result;
}

method dispatch($capture) {
# Count arguments.
my $num_args := nqp::captureposelems($capture);

# Get list and number of candidates, triggering a sort if there are none.
my @candidates := $!dispatch_order;
if nqp::isnull(@candidates) {
#pir::nqp_disable_sc_write_barrier__v();
@candidates := $!dispatch_order := self.sort_dispatchees();
#pir::nqp_enable_sc_write_barrier__v();
1;
}
my $num_candidates := nqp::elems(@candidates);

# Initialize dispatcher state.
my @possibles;

# Go thorugh candidates.
my $type_mismatch;
my $type_check_count;
my $i;
my $cur_idx := 0;
my $cur_candidate;
while 1 {
$cur_candidate := @candidates[$cur_idx];

if nqp::isnull($cur_candidate) {
# If we have some possible candidate(s), we're done in this loop.
if nqp::elems(@possibles) {
last;
}

# Otherwise, we keep looping and looking, unless we really hit the end.
$cur_idx++;
if nqp::isnull(@candidates[$cur_idx]) {
last;
}
else {
next;
}
}

# Check if it's admissable by arity.
if $num_args < $cur_candidate<min_arity> || $num_args > $cur_candidate<max_arity> {
$cur_idx++;
next;
}

# Check if it's admissable by type.
$type_check_count := $cur_candidate<num_types> > $num_args
?? $num_args
!! $cur_candidate<num_types>;
$type_mismatch := 0;
$i := 0;
while $i < $type_check_count {
my $param := nqp::captureposarg($capture, $i);
my $param_type := $param.WHAT;
my $type_obj := $cur_candidate<types>[$i];
my $definedness := $cur_candidate<definednesses>[$i];
unless nqp::eqaddr($param_type, $type_obj) || is_narrower_type($param_type, $type_obj) {
$type_mismatch := 1;
last;
}
if $definedness {
# Have a constraint on the definedness.
my $defined := nqp::isnull($param_type) ?? nqp::defined($param) !! nqp::isconcrete($param);
if (!$defined && $definedness == $DEFINED_ONLY) || ($defined && $definedness == $UNDEFINED_ONLY) {
$type_mismatch := 1;
last;
}
}
$i++;
}

if $type_mismatch {
$cur_idx++;
next;
}

# If we get here, it's an admissable candidate; add to list. */
nqp::push(@possibles, $cur_candidate);
$cur_idx++;
}

# Cache the result if there's a single chosen one and return it.
if nqp::elems(@possibles) == 1 {
my $result := @possibles[0]<sub>;
#pir::nqp_disable_sc_write_barrier__v();
$!dispatch_cache := nqp::multicacheadd($!dispatch_cache, $capture, $result);
#pir::nqp_enable_sc_write_barrier__v();
$result
}
elsif nqp::elems(@possibles) == 0 {
# XXX Include possible candidate signatures.
nqp::die("No applicable candidates found to dispatch to for '" ~ self.name ~ "'.")
}
else {
# XXX Include ambiguous candidate signatures.
nqp::die("Ambiguous dispatch to multi '" ~ self.name ~ "'.")
}
}

method clone() {
# Clone the underlying VM code ref.
my $do := nqp::clone($!do);
Expand Down Expand Up @@ -283,6 +385,8 @@ nqp::setboolspec(NQPRoutine, 5, nqp::null());
my knowhow NQPSignature {
has $!types;
has $!definednesses;
method types() { $!types }
method definednesses() { $!definednesses }
}

my knowhow NQPRegex {
Expand Down

0 comments on commit ac11f0c

Please sign in to comment.