| 1 | val root = valOf (OS.Process.getEnv "SPAN_ROOT"); |
| 2 | val _ = use (root ^ "/.build/Span.Export/code/span.ML"); |
| 3 | |
| 4 | fun chars s = map (Span.ascii o IntInf.fromInt o Char.ord) (String.explode s); |
| 5 | fun text cs = String.implode (map (Char.chr o IntInf.toInt o Span.ordinal) cs); |
| 6 | |
| 7 | fun read path = |
| 8 | let |
| 9 | val stream = if path = "-" then TextIO.stdIn else TextIO.openIn path |
| 10 | val text = TextIO.inputN (stream, 1048577) |
| 11 | val _ = if path = "-" then () else TextIO.closeIn stream |
| 12 | in |
| 13 | if size text > 1048576 then raise Fail "input exceeds 1 MiB" else text |
| 14 | end; |
| 15 | |
| 16 | fun write path text = |
| 17 | let |
| 18 | val stream = BinIO.openOut path |
| 19 | val _ = BinIO.output (stream, Byte.stringToBytes text) |
| 20 | in BinIO.closeOut stream end; |
| 21 | |
| 22 | fun output (ok, message) = |
| 23 | (TextIO.output (if ok then TextIO.stdOut else TextIO.stdErr, text message); |
| 24 | OS.Process.exit (if ok then OS.Process.success else OS.Process.failure)); |
| 25 | |
| 26 | fun usage () = |
| 27 | (TextIO.output (TextIO.stdOut, |
| 28 | "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"); |
| 29 | OS.Process.exit OS.Process.success); |
| 30 | |
| 31 | fun run args = |
| 32 | case args of |
| 33 | [] => usage () |
| 34 | | ["--help"] => usage () |
| 35 | | ["disassemble", file] => output (Span.disassemble (chars (read file))) |
| 36 | | ["assemble", file, "-o", destination] => |
| 37 | let |
| 38 | val ((ok, bytes), report) = Span.artifact (chars (read file)) |
| 39 | in |
| 40 | if ok then |
| 41 | (write destination (text bytes); |
| 42 | output (true, report)) |
| 43 | else output (false, report) |
| 44 | end |
| 45 | | ["run", file] => output (Span.process (map chars ["run", "4096"]) (chars (read file))) |
| 46 | | ["run", file, fuel] => output (Span.process (map chars ["run", fuel]) (chars (read file))) |
| 47 | | [mode, file] => |
| 48 | if List.exists (fn x => x = mode) ["assemble", "trace", "list"] then |
| 49 | output (Span.process [chars mode] (chars (read file))) |
| 50 | else raise Fail "unknown command, use span --help" |
| 51 | | _ => raise Fail "invalid arguments, use span --help"; |
| 52 | |
| 53 | fun main () = run (CommandLine.arguments ()) |
| 54 | handle exn => |
| 55 | (TextIO.output (TextIO.stdErr, "span: " ^ General.exnMessage exn ^ "\n"); |
| 56 | OS.Process.exit OS.Process.failure); |