-
-
Save masak/f4cfdc9abc2a579ec531 to your computer and use it in GitHub Desktop.
Translate nice solver code to ugly code that actually solves
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
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