- Resumption is actually a syscall,
dispatch-resume
. Any arguments to it become the resumption arguments. The found dispatcher to resume at becomes an implicit guard. - The
redispatch
syscall takes a dispatcher name. It obtains the arguments passed to the current call and gives them to the mentioned dispatcher. The name of the dispatcher must be a literal string constant. - Both of these mechanisms involve hanging an inline cache sublist off the chosen outcome in the dispatch program.
It is keyed on the bytecode address of the place doing the
dispatch-resume
orredispatch
. callsame
doesnqp::dispatch('dispatch-resume')
, andnextsame
is similar except that it throws a return control exception.callwith
doesnqp::dispatch('redispatch', 'dispatch-resume')
, which passes the current set of args todispatch-resume
. It's a single entry point to the dispatch mechanism, and so the result hangs off the same index.- An onlystar
proto
with a signature that isn't|
will get invoked, to enforce the proto's signature. The{*}
will compile intodispatch-resume
, which will then call the first candidate based on dispatch state. - A
proto
with a body also callsdispatch-resume
, and has the same kind of thing happen. - Signature binds that we cannot compile today will still run the binder, but in the "just result" mode, and if it errors, will trigger the bind failed assertion. This means we have a uniform interface to reporting binder failures. Yes, it'll make errors more costly in the case we really must report them. The RakuAST goal is to Compile All The Signatures anyway...
- A
dispatch-resume-on-bind-failure
syscall will be used to indicate that a bind failure will be treated as a resumption of the enclosing dispatcher. These implicit resumes also hang off the inline cache of the outcome, and can thus stack up the guards indicating the next thing to try. We'll still peel the callframe off somehow, I guess...
Point 9 means that:
multi fac(Int $x where 0) {
1
}
multi fac(Int $x) {
$x * fac($x - 1)
}
fac($foo)
Then we could potentially have the specializer inline the first candidate and then rewrite the bind assert failure into
a call to the second (and also inline it), or some such, which means we can get close enough to turning a multiple
dispatch with where
clauses and a small body into something about as efficient as a single call with an if
statement.