Very interesting code, in more ways than one (I didn’t know
about -D_GNU_SOURCE or rawmemchr).
I’m ashamed to say I got nearly all the way through backporting to ATS1 but
one line in particular is keeping it from typechecking (if commented out it
typechecks). Having a bit of trouble exactly interpreting the error.
/media/RAID5/share/ATS_learning/wclines.dats: 2707(line=133, offs=30) –
2709(line=133, offs=32): error(3): unsolved constraint: C3STRprop(main;
S2Eeqeq(S2Eapp(S2Ecst(add_addr_int_addr); S2EVar(2437), S2Eint(1)),
S2Eapp(S2Ecst(add_addr_int_addr); S2EVar(2436), S2Eapp(S2Ecst(sizeof);
S2EVar(2434)))))
type-checking has failed: there are some unsolved constraints: please
inspect the above reported error message(s) for information.
exit(ATS): uncaught exception:
_2fhome_2ffac2_2fhwxi_2fresearch_2fATS_2fIMPLEMENT_2fGeizella_2fAnairiats_2fsvn_2fats_2dlang_2fsrc_2fats_error_2esats__FatalErrorException(1233)
staload _(anon) = “libc/SATS/stdio.sats”
//
staload _(anon) = "prelude/DATS/array.dats"
staload _(anon) = “prelude/DATS/array0.dats”
//
staload _(anon) = "prelude/DATS/list.dats"
staload _(anon) = "prelude/DATS/list0.dats"
staload _(anon) = “prelude/DATS/list_vt.dats”
//
staload _(anon) = "prelude/DATS/matrix.dats"
staload _(anon) = “prelude/DATS/matrix0.dats”
//
staload _(anon) = "prelude/DATS/option.dats"
staload _(anon) = “prelude/DATS/option0.dats”
//
staload _(anon) = “prelude/DATS/pointer.dats”
//
staload _(anon) = “prelude/DATS/reference.dats”
//
(* ****** ****** *)
staload
UN = “prelude/SATS/unsafe.sats”
(* ****** ****** *)
staload “libc/SATS/stdio.sats”
(* ****** ****** *)
viewdef bytes_v (l:addr, n:int) = bytes (n) @ l
extern
fun ptr0_add_bytesize (p: ptr, ofs: size_t):<> ptr
implement
ptr0_add_bytesize(p,ofs) = p+ofs
symintr ptr_succ
extern
fun
ptr0_succ (p: ptr):<> ptr
overload ptr_succ with ptr0_succ
extern
fun
ptr1_succ {l:addr} (p: ptr l):<> ptr (l+1)
overload ptr_succ with ptr1_succ
implement
ptr1_succ {l} § =
$UN.cast{ptr(l+1)}(ptr0_succ §)
implement
ptr0_succ § = ptr0_add_bytesize (p, 1)
extern
praxi
bytes_v_unsplit
{l:addr}{n1,n2:int}
(pf1: (bytes_v (l, n1), bytes_v (l+n1, n2))): bytes_v (l, n1+n2)
// end of [bytes_v_unsplit]
(* ****** ****** *)
%{^
extern
void
*rawmemchr(const void *s, int c);
#define atslib_rawmemchr rawmemchr
%}
extern
fun rawmemchr
{l:addr}{m:int}
(
pf: bytes_v (l, m) | p: ptr l, c: int
) : [l2:addr | l+m > l2]
(
bytes_v (l, l2-l), bytes_v (l2, l+m-l2) | ptr l2
) = “mac#atslib_rawmemchr” // end of [rawmemchr]
(* ****** ****** *)
#define BUFSZ 16384
(* ****** ****** *)
extern fun fread1 {l:addr} {n:nat} {f:fm} (pf_mod: file_mode r
| dest: ptr l, sz: size_t 1, count: size_t n, fil: FILEref)
: [m:nat] size_t m = “mac#fread”
extern
fun freadc // read bytes and then add [c] at the end
{b:nat}
{l:addr}
(
pf: !bytes_v (l, BUFSZ) | inp: FILEref, p: ptr l, c: char, b: size_t b
) : size_t // end of [freadc]
implement
freadc (pf | inp, p, c, b) = let
val [m:int] m = fread1(file_mode_r | p, 1, b, inp)
val () = assertloc (p > null)
// val _ = if p <> null then
val () = $UN.ptrset (p+m, c)
// else ()
in
m
end (* end of [freadc] *)
(* ****** ****** *)
extern
fun wclbuf
{l:addr}{n:int}
(
pf: !bytes_v (l, n) | p: ptr l, pz: ptr, c: int, res: int
) : int // end of [wclbuf]
implement
wclbuf (pf | p, pz, c, res) =
(
if p < pz then let
val (pf1, pf2 | p2) = rawmemchr (pf | p, c)
prval (pf21, pf22) = array_v_uncons (pf2)
val _ = $showtype p
val p2 = ptr_succ(p2)
val _ = $showtype p
val res = wclbuf (pf22 | p2, pz, c, res + 1)
prval () = pf2 := array_v_cons (pf21, pf22)
prval () = pf := bytes_v_unsplit (pf1, pf2)
in
res
end else
res
// end of [if]
) // end of [wcbuf]
(* ****** ****** *)
extern
fun wclfil{l:addr}
(
pf: !bytes_v (l, BUFSZ) | inp: FILEref, p: ptr l, c: int
) : int // end of [wclfil]
implement
wclfil{l}
(pf | inp, p, c) = let
//
fun loop
(
pf: !bytes_v (l, BUFSZ)
| inp: FILEref, p: ptr l, c: int, res: int
) : int = let
//
val n = freadc (pf | inp, p, $UN.cast{char}©, size1_of_int1(BUFSZ-1))
//
in
//
if n > 0 then let
//val pz = ptr_add (p, n)
val pz = p+n
val res = wclbuf (pf | p, pz, c, res)
in
loop (pf | inp, p, c, res)
end else res (* end of [if] )
//
end // end of [loop]
//
in
loop (pf | inp, p, c, 0(res))
end ( end of [wclfil] *)
(* ****** ****** *)
implement
main {n} (argc, argv) = () where
{
var inp: FILEref = stdin_ref
val () =
(
if argc >= 2 then
inp := fopen_ref_exn (argv[1], file_mode_r)
// end of [if]
)
//
val (
pfopt | p
) = malloc_ngc (BUFSZ)
val () = assert_errmsg (p > null, #LOCATION)
prval malloc_v_succ (pf_ngc, pf_buf) = pfopt
prval () = pf_buf := bytes_v_of_b0ytes_v (pf_buf)
val res = wclfil (pf_buf | inp, p, $UN.cast2int(’\n’))
val () = free_ngc (pf_ngc, pf_buf | p)
//
val () = println! ("wclines: number of lines = ", res)
//
val () = if argc >= 2 then fclose_exn (inp)
} (* end of [main0] *)
(* ****** ****** *)
(* end of [wclines.dats] *)