Skip to content

Instantly share code, notes, and snippets.

@zoffixznet
Created January 15, 2018 14:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zoffixznet/17fb70a6cccdf0231f74e0ff180acf5e to your computer and use it in GitHub Desktop.
Save zoffixznet/17fb70a6cccdf0231f74e0ff180acf5e to your computer and use it in GitHub Desktop.
diff --git a/src/Perl6/Actions.nqp b/src/Perl6/Actions.nqp
index ed0fee780..8365e7461 100644
--- a/src/Perl6/Actions.nqp
+++ b/src/Perl6/Actions.nqp
@@ -8906,12 +8906,23 @@ class Perl6::Actions is HLL::Actions does STDActions {
my $wStr := $*W.find_symbol: ['Str'], :setting-only;
my $wNum := $*W.find_symbol: ['Num'], :setting-only;
+ my $pos := 0;
for %info<post_constraints> {
my $var-qast := QAST::Var.new: :$name, :scope<local>;
my $wval := QAST::WVal.new: :value($_);
my $what := nqp::what($_);
$var.push: QAST::ParamTypeCheck.new:
- nqp::eqaddr($what, $wInt)
+ nqp::istype($_, NQPArray)
+ ?? nqp::stmts(
+ # we have an optimized where setup; grab optimized
+ # qast from second element of the array and then
+ # swap the array into the first element, which
+ # contains a Code object for the slow binder path
+ $_[1].ann('optimized-where').name($name),
+ (my $qast := $_[1]),
+ (%info<post_constraints>[$pos] := $_[0]),
+ $qast)
+ !! nqp::eqaddr($what, $wInt)
?? QAST::Op.new(:op<if>,
QAST::Op.new(:op<isconcrete>, $var-qast),
QAST::Op.new(:op<iseq_I>, $wval,
@@ -8934,7 +8945,8 @@ class Perl6::Actions is HLL::Actions does STDActions {
?? QAST::Op.new(:op<p6capturelex>,
QAST::Op.new: :op<callmethod>, :name<clone>, $wval)
!! $wval,
- $var-qast
+ $var-qast;
+ $pos++;
}
}
@@ -9159,6 +9171,7 @@ class Perl6::Actions is HLL::Actions does STDActions {
# Build a block that'll smartmatch the topic against the
# expression.
check_smartmatch($/,$expr);
+ my $where := optimized-where-block($/, $expr, $operand);
my $past := QAST::Block.new(
QAST::Stmts.new(
QAST::Var.new( :name('$_'), :scope('lexical'), :decl('var') )
@@ -9178,9 +9191,42 @@ class Perl6::Actions is HLL::Actions does STDActions {
my $sig := $*W.create_signature(nqp::hash('parameter_objects',
[$*W.create_parameter($/, $param)]));
add_signature_binding_code($past, $sig, [$param]);
- $*W.create_code_object($past, 'Block', $sig)
+ my $block := $*W.create_code_object($past, 'Block', $sig);
+ $where ?? nqp::list($block, $where) !! $block
+ }
+
+ sub optimized-where-block($/, $expr, $operand) {
+ if nqp::istype($expr, QAST::WVal) { # a single typecheck?
+ # we don't declare this var; in post-constraints, we'll change the
+ # name to the name of the actual param in the typecheck
+ my $var := QAST::Var.new: :scope<local>, :name<optimized-where-var>;
+ my $qast := QAST::Op.new: :op<istype>, $var, $expr;
+ $qast.annotate: 'optimized-where', $var;
+ return $qast;
+ }
+ elsif nqp::istype($expr, QAST::Op) # an "or" junction with types only?
+ && $expr.op eq 'call' && $expr.name eq '&infix:<|>' {
+ return 0 unless nqp::istype($_, QAST::WVal) for @($expr);
+ # we don't declare this var; in post-constraints, we'll change the
+ # name to the name of the actual param in the typecheck
+ my $var := QAST::Var.new: :scope<local>, :name<optimized-where-var>;
+ my $op := my $qast := QAST::Stmts.new;
+ for @($expr) {
+ $op.push: my $new-op := QAST::Op.new: :op<unless>,
+ QAST::Op.new: :op<istype>, $var, $_;
+ $op := $new-op;
+ }
+ # rewrite last `unless` into `istype` in the second branch of
+ # parent `unless` (or just the top node, if we only got one WVal)
+ $op.op: 'istype'; $op.push: $op[0][1]; $op[0] := $op[0][0];
+ $qast := $qast[0]; # toss Stmts, we no longer need 'em;
+ $qast.annotate: 'optimized-where', $var;
+ return $qast;
+ }
+ 0
}
+
sub when_handler_helper($when_block) {
unless nqp::existskey(%*HANDLERS, 'SUCCEED') {
%*HANDLERS<SUCCEED> := QAST::Op.new(
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment