ffi
C’s types as values, and an effect’s operations that C functions do:
a description, which the compiler reads where it compiles the
program for C, and makes the provider’s side of — how an operation’s
fields are given to the function, what its result is made into, and
the dispatch — in place of the same written by hand in the module’s
M.provider.c. The C compiler is given, with the glue, the types
described, held to the function’s own as its header declares it: a
function described as taking an int where it takes a size_t does
not build.
This is how a module gives the program the host’s types — what a
FILE * is to it, with what lets it go — and nothing more: an
operation stays an effect’s, done when a handler handles it; the
program itself never calls C. A function of no effect (libm’s sin,
a hash) is a primitive of the runtime’s or the library’s, not
described here: C cannot be trusted to say it is pure.
A description is a definition of type Described in the effect’s
module (std.time’s timeInC), of the operations C does: each a
constructor’s name, and the function, with its C type as values of
CType, as Racket’s ffi has them. An operation Op a b (r -> x)
described fun "f" [ta, tb] (Gives tr) is f(a, b), its result
made an r as tr says; one whose last field is x itself gives
void. What the module’s M.provider.c does by hand is still its
own: its heff_provider_M hands an operation it does not do to
heff_described_M, the glue; a module all of whose operations are
described needs no M.provider.c. In JavaScript a description means
nothing: the module’s M.provider.js is the whole of the effect there.
CType
data CType = CInteger String | CDouble | CBool | CString | CText | COwnedString | CBytes | COwnedBytes | CPointer String String | CVoidA C type, by what crosses as it:
CInteger "int", an integer type by its C name (int,int64_t,size_t,mode_t: a typedef’s name, so that its width is the system’s, not guessed), of anInt;CDouble, aFloat64;CBool, aBool(C’sbool);CString,const char *: aString’s bytes, a NUL after them (a path, content);CText, the same made valid UTF-8 (a name);COwnedString, a result only: achar *malloc’d by C, copied and freed;CBytes, aBytes, NULs and all: as an argument two of C’s, its bytes’const unsigned char *and their count, asize_t; as a resultconst unsigned char *, the count put by the function in asize_t *given after its arguments, the bytes copied;COwnedBytes, a result only: the same,unsigned char *malloc’d by C, copied and freed;CPointer "FILE" "fclose", a pointer to the named type (FILE *), held by the program as a foreign value of whatever type the operation says (adataof no constructors), and let go of by the named function when the program drops its last reference;CVoid, a result only:Unit.
CResult
data CResult = Gives CType | GivesOrErrno CType | DoneOrErrnoWhat a function’s result is made into:
Gives t, the result as the operation’s answer (ofCVoid, the operation’sxitself, orMkUnitto its function);NULLof a string, bytes or a pointer fails the program (no bytes are given as a pointer still, their count 0);GivesOrErrno t,Either Errno a: the system’s way of failing,-1of an integer orNULLof a string, bytes or a pointer witherrnoset,Leftof it, elseRightthe result;DoneOrErrno,Either Errno Unit: anint, 0 or-1witherrno.
Errno
type Errno = { code : Int, name : String, message : String }Why a call of the system failed: errno, its name (ENOENT,
EACCES; the same on every system, where the number is not), and
what the system says of it. (std.filesystem’s FileError is one,
and the path it was of.)
Function
type Function = { name : String, args : List CType, result : CResult }A C function: its name, as the header the module includes declares
it (or as the module’s M.provider.c defines it), what it takes,
and what it gives.
Operation
type Operation = { op : String, fun : Function }An operation done by a C function: the constructor’s name, and the function, which is given the operation’s fields but its last, in order.
Described
data Described = Describe (List String) (List Operation)An effect’s operations in C: the headers the functions are declared
in ("<stdio.h>", as written after #include; none for a function
of M.provider.c), and the operations.
Links
type Links = { pkgConfig : List String = [] , libs : List String = [] , frameworks : List String = [] }What a module’s C needs beyond the runtime to be built and linked, said by a definition of this type in the module, so that every program importing it is built so:
pkgConfig, packages by their pkg-config names, whosepkg-config --cflagsand--libsare given to the C compiler;libs, libraries by their names, each-lNAME;frameworks, macOS frameworks by their names, each-framework NAME, where the program is built for macOS (nowhere else, where a provider does without them).
Where a library is found, if neither pkg-config nor the C compiler
knows, is the program’s build to say (its includeDirs and
libDirs), not the module’s.
int
int : CTypeint.
int64
int64 : CTypeint64_t.
long
long : CTypelong.
size
size : CTypesize_t.
integer
integer : String -> CTypeAn integer type by its C name: integer "mode_t".
double
double : CTypedouble.
bool
bool : CTypebool.
string
string : CTypeconst char *, a string’s bytes.
text
text : CTypeconst char *, text.
ownedString
ownedString : CTypechar * malloc’d by C, a result.
bytes
bytes : CTypeA Bytes: const unsigned char * and size_t, an argument; as a
result, the count by a size_t * after the arguments.
ownedBytes
ownedBytes : CTypeunsigned char * malloc’d by C, its count by a size_t * after the
arguments, a result.
pointer
pointer : String -> String -> CTypeA pointer to the named type, let go of by the named function:
pointer "FILE" "fclose".
void
void : CTypevoid, a result.
gives
gives : CType -> CResultThe result as the answer.
givesOrErrno
givesOrErrno : CType -> CResultThe result, or Left errno where it is -1 or NULL.
doneOrErrno
doneOrErrno : CResultRight MkUnit of 0, Left errno otherwise.
fun
fun : String -> List CType -> CResult -> FunctionA C function described.
>>> (fun "chmod" [string, integer "mode_t"] doneOrErrno).name"chmod"operation
operation : String -> Function -> OperationAn operation done by a function.
>>> (operation "Sleep" (fun "heff_sleep_ms" [int64] (gives void))).op"Sleep"describe
describe : List String -> List Operation -> DescribedThe operations C does, with the headers their functions are declared in.
instanceShowErrno
instance instanceShowErrno : Show ErrnoAs a system’s tools say it: the name, and what it is.
>>> show ({ code = 2, name = "ENOENT", message = "No such file or directory" } : Errno)"ENOENT: No such file or directory"