Skip to content

Commit

Permalink
Document and streamline raku-bind-assert dispatcher
Browse files Browse the repository at this point in the history
  • Loading branch information
lizmat committed Jan 20, 2024
1 parent 7972807 commit f651e9d
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 19 deletions.
6 changes: 6 additions & 0 deletions docs/dispatchers.md
Original file line number Diff line number Diff line change
Expand Up @@ -426,6 +426,12 @@ nqp::dispatch("raku-assign", $container, $value);
Assigns the given $value to the given $container, and produces the $container.

### raku-bind-assert
```
nqp::dispatch("raku-bind-assert", $value, $deconted, $type);
```
Returns the given $value if the $deconted value type matches against $type.
Otherwise throws.

### raku-boolify
### raku-call
### raku-call-simple
Expand Down
54 changes: 35 additions & 19 deletions src/vm/moar/dispatchers.nqp
Original file line number Diff line number Diff line change
Expand Up @@ -782,48 +782,64 @@ my int $MEGA-METH-CALLSITE-SIZE := 16;
});
}

# Binding type assertion dispatcher, used to do type checks of binds. Evaluates
# to the value itself when the type check passes, installing a guard along the
# way. Otherwise, throws.
#- raku-bind-assert ------------------------------------------------------------
# Binding type assertion dispatcher, used to do type checks of binds.
# Evaluates to the value itself when the type check passes, installing
# a guard along the way. Otherwise, throws.
{
sub bind-error($value, $type) {
# Helper sub to throw type check error
sub bind-error($got, $expected) {
Perl6::Metamodel::Configuration.throw_or_die(
'X::TypeCheck::Binding',
"Type check failed in binding; expected '" ~
nqp::how_nd($type).name($value) ~ "' but got '" ~
nqp::how_nd($value).name($value) ~ "'",
:got($value),
:expected($type)
"Type check failed in binding; expected '"
~ nqp::how_nd($expected).name($expected)
~ "' but got '"
~ nqp::how_nd($got).name($got)
~ "'",
:$got, :$expected
);
}

# The run-time checker
my $bind-check := -> $value, $value-decont, $type {
nqp::istype_nd($value-decont, $type) ?? $value !! bind-error($value, $type)
nqp::istype_nd($value-decont, $type)
?? $value
!! bind-error($value, $type)
}

# Actual dispatcher Expects the original value as the first argument,
# the deconted value as the second, and the type to be checked against
# as the third argument.
nqp::register('raku-bind-assert', -> $capture {
my $value-decont := nqp::captureposarg($capture, 1);
my $type := nqp::captureposarg($capture, 2);

# Nominal, so a type guard on the decont'd value will suffice,
# then produce the original value.
if nqp::how_nd($type).archetypes.nominal {

# Type is ok
if nqp::istype_nd($value-decont, $type) {
# Nominal, so a type guard on the decont'd value will suffice,
# then produce the original value.
nqp::guard('type', nqp::track('arg', $capture, 1));
nqp::guard('type', nqp::track('arg', $capture, 2));
nqp::delegate('boot-value', $capture);
}

# Not ok
else {
my $value := nqp::captureposarg($capture, 0);
bind-error($value, $type)
bind-error(nqp::captureposarg($capture, 0), $type);
}
}

# Not a nominal type, can't guard it, so set up a call to do the
# check late-bound.
else {
# Not a nominal type, can't guard it, so set up a call to do the
# check late-bound.
nqp::guard('type', nqp::track('arg', $capture, 2));
my $delegate := nqp::syscall('dispatcher-insert-arg-literal-obj',
$capture, 0, $bind-check);
nqp::delegate('boot-code-constant', $delegate);
nqp::delegate('boot-code-constant',
nqp::syscall('dispatcher-insert-arg-literal-obj',
$capture, 0, $bind-check
)
);
}
});
}
Expand Down

0 comments on commit f651e9d

Please sign in to comment.