val root = valOf (OS.Process.getEnv "SPAN_ROOT");
val _ = use (root ^ "/.build/Span.Export/code/span.ML");
fun chars s = map (Span.ascii o IntInf.fromInt o Char.ord) (String.explode s);
fun text cs = String.implode (map (Char.chr o IntInf.toInt o Span.ordinal) cs);
fun read path =
let
val stream = if path = "-" then TextIO.stdIn else TextIO.openIn path
val text = TextIO.inputN (stream, 1048577)
val _ = if path = "-" then () else TextIO.closeIn stream
in
if size text > 1048576 then raise Fail "input exceeds 1 MiB" else text
end;
fun write path text =
let
val stream = BinIO.openOut path
val _ = BinIO.output (stream, Byte.stringToBytes text)
in BinIO.closeOut stream end;
fun output (ok, message) =
(TextIO.output (if ok then TextIO.stdOut else TextIO.stdErr, text message);
OS.Process.exit (if ok then OS.Process.success else OS.Process.failure));
fun usage () =
(TextIO.output (TextIO.stdOut,
"usage: span assemble file [-o binary]\n span trace file\n span list file\n span run file [fuel]\n span disassemble binary\n\nuse - to read standard input\n");
OS.Process.exit OS.Process.success);
fun run args =
case args of
[] => usage ()
| ["--help"] => usage ()
| ["disassemble", file] => output (Span.disassemble (chars (read file)))
| ["assemble", file, "-o", destination] =>
let
val input = chars (read file)
val (ok, bytes) = Span.binary input
in
if ok then
(write destination (text bytes);
output (Span.process [chars "assemble"] input))
else output (false, bytes)
end
| ["run", file] => output (Span.process (map chars ["run", "4096"]) (chars (read file)))
| ["run", file, fuel] => output (Span.process (map chars ["run", fuel]) (chars (read file)))
| [mode, file] =>
if List.exists (fn x => x = mode) ["assemble", "trace", "list"] then
output (Span.process [chars mode] (chars (read file)))
else raise Fail "unknown command, use span --help"
| _ => raise Fail "invalid arguments, use span --help";
fun main () = run (CommandLine.arguments ())
handle exn =>
(TextIO.output (TextIO.stdErr, "span: " ^ General.exnMessage exn ^ "\n");
OS.Process.exit OS.Process.failure);