1.1 C Bindings.
Felix is particularly good at allowing you to reuse your favourite C and C++ libraries. Mapping C types and functions into Felix is called binding.
1.1.1 Binding types and functions
Here's a simple example:
type Metres = "double"; // bind the type to C ctor Metres: double = "$1"; // constructors ctor double: Metres = "$1"; fun str(x:Metres)=> str (double x) + "m"; // format as string type SquareMetres = "double"; // bind the type to C ctor SquareMetres: double = "$1"; // constructors ctor double: SquareMetres = "$1"; fun str(x:SquareMetres)=> str (double x)+"m^2"; // format as string fun +: Metres * Metres -> Metres = "$1+$2"; fun *: Metres * double -> Metres = "$1*$2"; fun *: double * Metres -> Metres = "$1*$2"; fun *: Metres * Metres-> SquareMetres = "$1*$2"; val a = 1.2; val x = Metres 42.0; val y = 3.0.Metres; println$ str x + "*" + str y + " = " + str (x * y); println$ str a + "*" + str x + " = " + str (a * x);
In the C encoding {$1}, {$2} represent the first and second components of the argument tuple, respectively.
There are some shortcuts for special cases where the names agree:
begin ctypes int, long, double; fun f: int -> int; end
This is equivalent to:
begin type int="int"; type long="long"; type double="double"; fun f: int * int -> int = "f($1,$2)"; end
1.1.2 Binding constants
You can also bind constants and expressions:
const metre : Metres = "1.0"; const pi2 : double = "PI*PI";
1.1.3 Binding enumerations
There's a special shorthand for binding numeric enumerations:
cenum MyEnum = zero, one, two;
This construction binds the type, the enumeration constants, and also provides an equality operator.
1.1.4 Binding flags
Another construction is useful binding enumerations which are used as flags:
cflags MyFlags = none, bit1, bit2, allbits;
This construction binds the type, the enumeration constants, provides an equality operator, and provides bitwise arithmetic operations {\&}, {\|}, {\^}, {~}, {^=}, {&=}, and {|=}.
1.1.5 Binding structs
There is a simple shorthand for binding C structs:
header " "; cstruct X {a:int; b:int; }; val z = X(1,2); println$ z.b;
Note that a definition of the {cstruct X} is not emitted,
instead it is used to model an existing C struct
,
in this case we created it in the header
literally,
usually you will be modelling structures used in C libraries.
Your model does need to be complete because Felix synthesises a constuctor for the structure from a tuple. The names of the structure members must match.