Skip to content

Instantly share code, notes, and snippets.

@vendethiel
Last active August 29, 2015 14:25
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save vendethiel/bff772fc084ca88bb253 to your computer and use it in GitHub Desktop.
subset UnaryCallWithFn where :(&block);
macro supply($block where Q::Call) {
my $var =Q::Var.new(:name<supply>); #<- this should take care of hygiene-ish stuff ;-) (as in, two pass variable naming)
$block.traverse(-> $block {
return $block unless $block ~~ Q::Call;
given {
when any <emit done> {
Q::Call(:obj($var), :method($_), :arguments($block.arguments));
}
when 'whenever' {
# whenever(SUPPLY, -> VAR { BLOCK })
unless $block.arguments != 2 || $block.arguments[1] !~~ UnaryCallWithFn {
die "whenever must be called with a ";
}
my ($supply, $loopfn) = $block.arguments;
my $loopvar = $loopfn.arguments[1].variable;
my $loopblock = &?ROUTINE($loopfn.arguments[0].block); # ???????????????
#TODO should this "wait"?
quasi {
# !!! this below needs to declare variable. same issue as "$var" above
my $supply = {{{$supply}}}; # <- this should be hygienic ;-)
while (my {{{$loopvar}}}) = $supply.drip() {
{{{ $loopblock }}}
}
}
}
default {
&?ROUTINE5($block); # recurse! yay!
}
}
});
quasi {
my {{{$var}}};
{{{$block}}}
};
}
# code:
my $other = Supply.new();
supply {
if True {
emit 1;
emit emit();
}
whenever $other, -> $val {
emit $val;
}
done;
}
# output:
my $other = Supply.new();
{ #<- macro-induced scope
my $supplyMACROVAR;
if True {
$supplyMACROVAR.emit(1);
$supplyMACROVAR.emit(emit());
}
{ #<- macro-induced scope
my $supplyMACROVAR-PRIME = $other; # the -PRIME is just the hygiene kicking in ... or is it? I'd like it like that
while (my $val) = $other.drip() {
$supplyMACROVAR.emit($val);
}
}
$supplyMACROVAR.done();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment