$extfcall allows external functions to be conveniently
called inside ATS code.
When translating ATS code into C, one may want to make
extensive use of $extfcall during the first phase. Let
me use a example to show how $extfcall is typically used.
Say that you want to print out the content of the enviroment
variable HOME, and you know that the function getenv in stdlib.h
can do the work. The following code calls [getenv] externally:
(* ****** ****** *)
//
#include
"share/atspre_staload.hats"
//
(* ****** ****** *)
staload "libc/SATS/stdlib.sats"
(* ****** ****** *)
implement
main0 () =
{
//
val HOME =
$extfcall(string, "getenv", "HOME")
//
val ((*void*)) = println! ("${HOME} = ", HOME)
//
} (* end of [main0] *)
(* ****** ****** *)
Essentially, the expression $extfcall(string, "getenv", "HOME")
translates into getenv("HOME"), and its type is *assumed* to be
string.
Say that you realize later that getenv may return a NULL pointer
(in the case where HOME is undefined). Then you can change a bit:
$extfcall(Stropt0, "getenv", "HOME")
This change may result in type-errors that need to be fixed.
If you read the doc on getenv carefully, then you probably realize that what is returned by
getenv is not a stropt-value in the usual (functional) sense. A common way to handle it is
to assign it the following linear type vStrptr0:
vtypedef vStrptr(l:addr) = [l:addr] (strptr(l) -<prf> void | strptr(l))
Basically, vStrptr0 means a "borrowed string". The above code can now be written as follows:
implement
main0 () =
{
//
val (fpf | HOME) =
$extfcall(vStrptr0, "getenv", "HOME")
//
val () = assertloc(isneqz(HOME)) // HOME is not NULL
//
val ((*void*)) = println! ("${HOME} = ", HOME)
//
prval ((*void*)) = fpf (HOME) // returning the borrowed string
//
} (* end of [main0] *)
After introducing the following declaration:
extern fun getenv : string -> vStrptr0 = "mac#"
you can replace $exfcall(...) with getenv("HOME")