I figured I'd post this as ATS is quite difficult. Nothing contained in this file is advisable, but by the time you can figure out what's wrong, you won't need it!
Here is our function that takes a filepath (given as a string) and returns the file's contents as a string:
#include "share/atspre_staload.hats"
%{^
#include "libats/libc/CATS/string.cats"
%}
staload "libats/ML/DATS/string.dats"
fun read_file(s: string) : string =
let
val ref = fileref_open_opt(s, file_mode_r)
val str: string =
case+ ref of
| ~Some_vt(x) =>
let
val s = strptr2string(fileref_get_file_string(x))
val _ = fileref_close(x)
in
s
end
| ~None_vt() => (println!("could not open file at " + s) ; "")
in
str
end
You can verify this compiles with:
$ patscc -DATS_MEMALLOC_LIBC file_read.dats -c -o file_read.o -cleanaft
There's a fair amount going on here. There are three ways of including foreign
code, though one is the #include
from C. So far, my approach has been to try to
staload
things when possible and #include
if the compiler complains.
Now we can examine the actual code. fileref_open_opt
returns a linear type
(discussed here), so
we pattern match using ~
. Note that we have to call fileref_close
manually; unfortunately ATS does not detect it if we fail to include that
line.
If this isn't totally straightforward, that's fine! This code is for you; you can write something faster later.