Nathan McCarty
b28b91d5d2
Idris 2 doesn't have a failing exit code in this context when it fails to compile an expr given at the command line, we need to check for an error message in the output
126 lines
3.2 KiB
Raku
126 lines
3.2 KiB
Raku
#| Utilities for interacting with the idris compiler and package manager
|
|
unit module IUtils::Compiler;
|
|
|
|
# Represents the output of an Expr that we need to run
|
|
enum ExprOutput is export <Unit Boolean Either>;
|
|
|
|
# Utility functions for pack
|
|
|
|
#| Invoke a pack command
|
|
sub pack-run(*@cmd) is export {
|
|
my $proc = run "pack", @cmd, :out, :err;
|
|
my $out = $proc.out.slurp(:close);
|
|
my $err = $proc.err.slurp(:close);
|
|
unless $proc {
|
|
die qq:to/END/;
|
|
Pack Failure!
|
|
Captured Output:
|
|
$out
|
|
|
|
Captured StdErr:
|
|
$err
|
|
END
|
|
}
|
|
}
|
|
|
|
#| Build a package with pack
|
|
sub pack-build($pkg) is export {
|
|
pack-run 'build', $pkg
|
|
}
|
|
|
|
#| Test a package with pack
|
|
sub pack-test($pkg) is export {
|
|
pack-run 'build', $pkg
|
|
}
|
|
|
|
#| Clean a package with pack
|
|
sub pack-clean($pkg) is export {
|
|
pack-run 'clean', $pkg
|
|
}
|
|
|
|
# Utility functions for idris
|
|
|
|
#| An error coming from the idris compiler
|
|
class IdrisError is Exception {
|
|
has Str $.out;
|
|
has Str $.err;
|
|
has Int $.exit-code;
|
|
has Str $.command;
|
|
|
|
method message {
|
|
qq:to/END/;
|
|
Error running idris command: $.command
|
|
Command exited with $.exit-code
|
|
StdOut:
|
|
{$.out.lines.map(*.indent: 2).join("\n")}
|
|
END
|
|
}
|
|
}
|
|
|
|
#| An error coming from a compiled expression
|
|
class ExpressionError is Exception is export {
|
|
has Str $.out;
|
|
has Str $.err;
|
|
has Int $.exit-code;
|
|
has Str $.expr;
|
|
|
|
method message {
|
|
qq:to/END/;
|
|
Error running expression: $.expr
|
|
Command exited with $.exit-code
|
|
END
|
|
}
|
|
}
|
|
|
|
#| Invoke an idris command
|
|
sub idris-run(*@cmd) is export {
|
|
my $proc = run "idris2", @cmd, :out, :err;
|
|
my $out = $proc.out.slurp(:close);
|
|
my $err = $proc.err.slurp(:close);
|
|
if !$proc || $out.contains("Error:") {
|
|
IdrisError.new(
|
|
out => $out, err => $err,
|
|
exit-code => $proc.exitcode, command => @cmd.Str)
|
|
.throw;
|
|
}
|
|
return $out;
|
|
}
|
|
|
|
my constant $bool-lambda =
|
|
'(\x => if x then exitSuccess else exitFailure)';
|
|
|
|
# TODO: Implemenent support for the Either case
|
|
# TODO: Use the ide protocol to drive this so we can avoid the user needing to import anything
|
|
#| Exec the expression with the given name in the given file
|
|
#|
|
|
#| Uses the provided $output-type to hook up an adaptor for tests returning a
|
|
#| non () value
|
|
sub idris-exec($expr, $file, $output-type? = Unit) is export {
|
|
# Have idris compile an executable for the expression,
|
|
given $output-type {
|
|
when Unit {
|
|
idris-run '--find-ipkg', '--client', ":c iutils_out $expr", $file;
|
|
}
|
|
when Boolean {
|
|
idris-run '--find-ipkg', '--client',
|
|
":c iutils_out ($expr >>= $bool-lambda)", $file;
|
|
}
|
|
default {
|
|
die "Unsupported output type encountered: $_";
|
|
}
|
|
}
|
|
# Run the expression
|
|
my $proc = run 'build/exec/iutils_out', :out, :err;
|
|
my $out = $proc.out.slurp(:close);
|
|
my $err = $proc.err.slurp(:close);
|
|
unless $proc {
|
|
ExpressionError.new(
|
|
out => $out, err => $err,
|
|
exit-code => $proc.exitcode, expr => $expr
|
|
).throw;
|
|
}
|
|
# Remove the output file
|
|
'build/exec/iutils_out'.IO.unlink;
|
|
return $out;
|
|
}
|