Created
April 14, 2014 06:18
-
-
Save masak/10620845 to your computer and use it in GitHub Desktop.
Simulating CPS in Perl 6 - code that can be paused and resumed in the middle
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## Test | |
my $point_1_reached = False; | |
my $point_2_reached = False; | |
my $point_3_reached = False; | |
class Event1 {} | |
class Event2 {} | |
class Event3 {} | |
my $workflow = q[[[ | |
expect Event1; | |
$point_1_reached = True; | |
expect Event2; | |
$point_2_reached = True; | |
expect Event3; | |
$point_3_reached = True; | |
]]]; | |
register($workflow); | |
use Test; | |
ok not($point_1_reached), "no code run yet"; | |
broadcast(Event1); | |
ok $point_1_reached, "point 1 reached..."; | |
ok not $point_2_reached, "...but not point 2 yet"; | |
broadcast(Event2); | |
ok $point_2_reached, "point 2 reached..."; | |
ok not $point_3_reached, "...but not point 3 yet"; | |
broadcast(Event3); | |
ok $point_3_reached, "point 3 reached"; | |
done; | |
## Implementation | |
my %listeners; | |
sub register($workflow) { | |
my grammar Workflow { | |
regex TOP { <immediate> <delayed>? } | |
regex immediate { | |
<expect> | |
<statements> | |
} | |
regex delayed { | |
<expect> | |
(.*) | |
} | |
regex expect { \s* 'expect' \s* (\w+) \s* ';' } | |
regex statements { [<!before <expect>> .]* } | |
} | |
die "Could not parse: $workflow" | |
unless Workflow.parse($workflow); | |
my $body = ~$<immediate><statements>; | |
my $unevaluated_part = ""; | |
if $<delayed> { | |
sub escape($s) { $s.subst(/\'/, q[\\'], :g) } | |
my $remaining_workflow = ~$<delayed>; | |
my $escaped = escape( $remaining_workflow ); | |
$unevaluated_part = qq[; register('$escaped')]; | |
} | |
my $fn_str = 'sub {' ~ $body ~ $unevaluated_part ~ '}'; | |
my $fn = EVAL($fn_str); | |
my $event = EVAL(~$<immediate><expect>[0]); | |
%listeners{$event.WHICH} = $fn; | |
} | |
sub broadcast($event) { | |
my $listener = %listeners{$event.WHICH}; | |
if $listener { | |
$listener(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment