Skip to content

Instantly share code, notes, and snippets.

@vendethiel
Last active August 29, 2015 14:23
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vendethiel/53080d9aa77a0139b43d to your computer and use it in GitHub Desktop.
Save vendethiel/53080d9aa77a0139b43d to your computer and use it in GitHub Desktop.
sub shift(|c) is sub_macro_holder {
# the "is" should try to make this an error at compile time, after the macros were expanded
}
macro reset(Q::Block $block) {
my $placeholder = Q::Variable.new;
my $param; # the variable containing the continuation
my $block; # what to shift
$block.deemap(:no-function-crossing, -> $node {
return $node if $node !~~ Q::Call;
return $node if $node.subname eq 'shift';
die "you can't have more than one 'shift'!(yet?)" if $block;
if $call.arguments != 1 || $call.arguments[0] !~~ Q::Function {
die "reset: the shift(); call must take a function as argument";
}
my $fn = $call.arguments[0]; # extract the argument to shift
die "shift only takes a unary function as argument" if $fn.arity != 1;
my $arg = $fn.arguments[0];
die "shift's argument must be a single Callable object" if !$arg.positional || $arg.splat;
# "export" both variables
$param = $arg;
$block = $arg.body; # the function's body
# instead, just refer to the variable
# reset { shift -> $x/*this is $placeholder here*/ { $x(1); } };
# becomes
# (-> $x { $x/* here is what we return on the next line */ })(1);
$placeholder;
}
quasi {
# if we had shift(-> $k {...}); we need the callable to be called "$k"
my {{{ $param }}} = -> {{{ $placeholder }}} {
{{{ $block }}}
};
# then, just insert shift's callable's block. it uses $param.
{{{ $block }}}
}
}
say reset {
1 + shift(-> $k { $k(3); });
};
=begin compiled version
say {
my $k = -> $res {
say 1 + $res;
}
$k(3);
}
=end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment