Skip to content

Instantly share code, notes, and snippets.

@masak
Created May 25, 2015 20:24
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 masak/f4cfdc9abc2a579ec531 to your computer and use it in GitHub Desktop.
Save masak/f4cfdc9abc2a579ec531 to your computer and use it in GitHub Desktop.
Translate nice solver code to ugly code that actually solves
grammar Solver::Syntax {
token TOP { <statement>* }
proto token statement {*}
token statement:sym<use> {
<sym> \s+ ([\w | '::']+) ';' \s*
}
token statement:sym<my> {
<sym> \s+ \S+ \s* '=' \s* <!before 'amb'> <-[;]>+ ';' \s*
}
token statement:sym<solve> {
<sym> \s+ ('{' \s*) <statement>* ('}' \s*)
}
token statement:sym<guard> {
<sym> \s+ (<-[;]>+ ';' \s*)
}
token statement:sym<say> {
<sym> \s+ <-[;]>+ ';' \s*
}
token statement:amb-my {
'my' \s+ (\S+) \s* '=' \s* 'amb' \s+ (<-[;]>+) ';' \s*
<statement>*
}
}
class Solver::Actions {
method TOP($/) {
make $<statement>».ast.join;
}
method statement:sym<use>($/) {
make $0 eq "Hypothetical::Solver" ?? "" !! ~$/;
}
method statement:sym<my>($/) {
make ~$/;
}
method statement:sym<solve>($/) {
make $0 ~ $<statement>».ast.join ~ $1;
}
method statement:sym<guard>($/) {
make "next unless " ~ $0;
}
method statement:sym<say>($/) {
make ~$/;
}
method statement:amb-my ($/) {
make "for ($1).list -> $0 \{\n" ~ $<statement>».ast.join.indent(4) ~ "\}\n";
}
}
sub process($code) {
my $actions = Solver::Actions.new;
Solver::Syntax.parse($code, :$actions)
or die "couldn't parse";
return $/.ast;
}
multi MAIN() {
my $code = "send-macros.p6".IO.slurp;
say process($code);
}
multi MAIN('test') {
use Test;
is process(""), "", "empty program";
is process("use Hypothetical::Solver;"), "", "remove the fake use";
is process("use Keep::This;"), "use Keep::This;", "keep every other use";
is process("my @digits = 0..9;"), "my @digits = 0..9;", "ordinary assignment";
is process(q[solve { }]), q[{ }], "empty solve block";
is process("solve \{\n my \$foo = 42;\n}"),
"\{\n my \$foo = 42;\n}", "solve block with statement";
is process("solve \{\n my \$foo = 42;\n my \$bar = 0;\n}"),
"\{\n my \$foo = 42;\n my \$bar = 0;\n}", "solve block with two statements";
is process("guard 2 + 2 == 4;"), "next unless 2 + 2 == 4;", "guard";
is process("say 'OH HAI';"), "say 'OH HAI';", "say statement";
is process("my \$x = amb 1, 2, 3;"), q:to 'OUTPUT', "amb assignment";
for (1, 2, 3).list -> $x {
}
OUTPUT
is process(q:to 'INPUT'), q:to 'OUTPUT', "amb assignment + ordinary assignment";
my $s = amb 5, 6, 7;
my $e = 18;
INPUT
for (5, 6, 7).list -> $s {
my $e = 18;
}
OUTPUT
is process(q:to 'INPUT'), q:to 'OUTPUT', "nesting amb assignments";
my $s = amb 5, 6, 7;
my $e = amb 3, 2, 1;
use Bar;
INPUT
for (5, 6, 7).list -> $s {
for (3, 2, 1).list -> $e {
use Bar;
}
}
OUTPUT
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment