Created
May 21, 2022 06:45
-
-
Save cwfoo/c8f3d43b2177e866fa3458ae57332a00 to your computer and use it in GitHub Desktop.
Check syntax of Standard ML program using Poly/ML without executing the program
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
(* Check for syntax errors and type errors in a Standard ML file without | |
* executing the program. Tested in Poly/ML 5.9 on Ubuntu 20.04. | |
* | |
* To check for the existence of errors in a Standard ML file using Poly/ML, it | |
* is sufficient to use `PolyML.compiler (TextIO.input1 inStream, [])`. However, | |
* that will not show line and column numbers when there are errors or warnings. | |
* This program adds line and column numbers to the error and warning messages. | |
* | |
* Usage: | |
* poly --script this-file.sml file-to-check.sml | |
* | |
* Behavior: | |
* * Prints warnings and errors to standard output. | |
* * Exits with exit code 1 if there are errors, exits with exit code 0 | |
* otherwise. | |
* | |
* To print to standard error instead of standard output, add this to the | |
* compiler parameter list in the call to PolyML.compiler: | |
* PolyML.Compiler.CPOutStream (fn s => (TextIO.output (TextIO.stdErr, s); | |
* TextIO.flushOut TextIO.stdErr)) | |
* *) | |
fun getLineChars inStream = | |
(* Limitation: TextIO.inputLine will raise the "Size" exception if the line is | |
* longer than String.maxSize. *) | |
case TextIO.inputLine inStream of | |
NONE => NONE | |
| SOME s => SOME (explode s) | |
fun checkFile filePath = | |
let | |
val lineNum = ref 0 | |
val colNum = ref 0 | |
val curLine = ref [] | |
val ins = TextIO.openIn filePath | |
fun getChar () = | |
case !curLine of | |
[] => | |
(case getLineChars ins of | |
NONE => NONE | |
| SOME (c::cs) => | |
(curLine := cs; | |
lineNum := !lineNum + 1; | |
colNum := 1; | |
SOME c) | |
| SOME [] => | |
(lineNum := !lineNum + 1; | |
getChar ())) | |
| (c::cs) => | |
(curLine := cs; | |
colNum := !colNum + 1; | |
SOME c) | |
in | |
(ignore o PolyML.compiler) | |
(getChar, [PolyML.Compiler.CPFileName filePath, | |
PolyML.Compiler.CPLineNo (fn () => !lineNum), | |
PolyML.Compiler.CPLineOffset (fn () => !colNum)]) | |
end | |
val () = case CommandLine.arguments () of | |
["--script", _, fileToCheck] => checkFile fileToCheck | |
| _ => raise (Fail "Invalid command line arguments") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment