Skip to content

Commit

Permalink
Implement nextcallee for methods in new dispatcher
Browse files Browse the repository at this point in the history
  • Loading branch information
jnthn committed Sep 28, 2021
1 parent 734ecd2 commit b635940
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 19 deletions.
5 changes: 3 additions & 2 deletions src/Perl6/Actions.nqp
Expand Up @@ -6541,15 +6541,16 @@ class Perl6::Actions is HLL::Actions does STDActions {
}
}
elsif $op eq 'dispatch' {
# We generally want to send unboxed string values in for dispatch
# We generally want to send unboxed string/int values in for dispatch
# arguments (although leave normal ones alone); we can't really
# know which are which, but if we're writing out an `nqp::op`
# just assume that they should all be unboxed; most situations
# will see the dispatch op generated anyway.
my int $i := 0;
my int $n := nqp::elems($past.list);
while $i < $n {
if nqp::istype($past[$i], QAST::Want) && $past[$i][1] eq 'Ss' {
if nqp::istype($past[$i], QAST::Want) &&
($past[$i][1] eq 'Ss' || $past[$i][1] eq 'Ii') {
$past[$i] := $past[$i][2];
}
$i++;
Expand Down
12 changes: 10 additions & 2 deletions src/core.c/control.pm6
Expand Up @@ -151,7 +151,7 @@ sub callsame() is raw {

sub new-disp-callsame() is raw {
$/ := nqp::getlexcaller('$/');
nqp::dispatch('boot-resume-caller')
nqp::dispatch('boot-resume-caller', 0)
}

sub nextsame() is raw {
Expand All @@ -164,18 +164,26 @@ sub nextsame() is raw {

sub new-disp-nextsame() is raw {
$/ := nqp::getlexcaller('$/');
nqp::throwpayloadlexcaller(nqp::const::CONTROL_RETURN, nqp::dispatch('boot-resume-caller'))
nqp::throwpayloadlexcaller(nqp::const::CONTROL_RETURN, nqp::dispatch('boot-resume-caller', 0))
}

sub lastcall(--> True) {
nqp::p6finddispatcher('lastcall').last();
}

sub new-disp-lastcall(--> True) {
nqp::dispatch('boot-resume-caller', 2)
}

sub nextcallee() {
my Mu $dispatcher := nqp::p6finddispatcher('nextcallee');
$dispatcher.exhausted ?? Nil !! $dispatcher.shift_callee()
}

sub new-disp-nextcallee() {
nqp::dispatch('boot-resume-caller', 3)
}

sub samewith(|c) {
$/ := nqp::getlexcaller('$/');
my Mu $ctx := nqp::ctxcaller(nqp::ctx());
Expand Down
50 changes: 35 additions & 15 deletions src/vm/moar/dispatchers.nqp
Expand Up @@ -715,9 +715,16 @@ nqp::dispatch('boot-syscall', 'dispatcher-register', 'raku-meth-call-resolved',
nqp::dispatch('boot-syscall', 'dispatcher-delegate', 'raku-invoke', $delegate_capture);
}
},
# Resumption. The capture's first two arguments are the that we initially
# did a method dispatch against and the method name respectively.
# Resumption. The capture itself has a first argument indicating the kind
# of resumption operation we're doing. The resume init capture's first two
# arguments are the type that we initially did a method dispatch against
# and the method name respectively.
-> $capture {
# Guard on the kind of resume we're doing, and get that flag.
my $track_kind := nqp::dispatch('boot-syscall', 'dispatcher-track-arg', $capture, 0);
nqp::dispatch('boot-syscall', 'dispatcher-guard-literal', $track_kind);
my int $kind := nqp::captureposarg_i($capture, 0);

# Work out the next method to call, if any. This depends on if we have
# an existing dispatch state (that is, a method deferral is already in
# progress).
Expand Down Expand Up @@ -785,21 +792,34 @@ nqp::dispatch('boot-syscall', 'dispatcher-register', 'raku-meth-call-resolved',

# If we found a next method...
if nqp::isconcrete($next_method) {
# Invoke it. We drop the first two arguments (which are only there
# for resumption), add the code object to invoke, and then leave it
# to the invoke dispatcher.
my $just_args := nqp::dispatch('boot-syscall', 'dispatcher-drop-arg',
nqp::dispatch('boot-syscall', 'dispatcher-drop-arg', $init, 0),
0);
my $delegate_capture := nqp::dispatch('boot-syscall',
'dispatcher-insert-arg-literal-obj', $just_args, 0, $next_method);
if nqp::istype($next_method, Routine) && $next_method.is_dispatcher {
nqp::dispatch('boot-syscall', 'dispatcher-delegate', 'raku-multi',
$delegate_capture);
# Check the kind of deferral requested.
if $kind == 0 {
# Call with same (that is, original) arguments. Invoke with those.
# We drop the first two arguments (which are only there for the
# resumption), add the code object to invoke, and then leave it
# to the invoke dispatcher.
my $just_args := nqp::dispatch('boot-syscall', 'dispatcher-drop-arg',
nqp::dispatch('boot-syscall', 'dispatcher-drop-arg', $init, 0),
0);
my $delegate_capture := nqp::dispatch('boot-syscall',
'dispatcher-insert-arg-literal-obj', $just_args, 0, $next_method);
if nqp::istype($next_method, Routine) && $next_method.is_dispatcher {
nqp::dispatch('boot-syscall', 'dispatcher-delegate', 'raku-multi',
$delegate_capture);
}
else {
nqp::dispatch('boot-syscall', 'dispatcher-delegate', 'raku-invoke',
$delegate_capture);
}
}
elsif $kind == 3 {
# We just want method itself, not to invoke it.
nqp::dispatch('boot-syscall', 'dispatcher-delegate', 'boot-constant',
nqp::dispatch('boot-syscall', 'dispatcher-insert-arg-literal-obj',
$capture, 0, $next_method));
}
else {
nqp::dispatch('boot-syscall', 'dispatcher-delegate', 'raku-invoke',
$delegate_capture);
nqp::die('Unimplemented resumption kind in method dispatch');
}
}
else {
Expand Down

0 comments on commit b635940

Please sign in to comment.