The KC3 Callable type is an or-type of Cfn and Fn.
In any case where you accept a Fn or Cfn as an argument
you should use Callable as the type.
The Cfn type and cfn syntax allows you to define C function
wrappers that are compatible with KC3 usual function calls.
To define a C function, use for example :
defmodule List
def map = cfn Tag "plist_map" (List, Callable, Result)
end
The Cfn will be named according to its first binding Ident and
its type also matches Callable.
The cfn_macro syntax introduces a Cfn (and thus also a Callable)
which behaves as a macro function.
The important rule to remember about macro functions is :
cfn_macro passes every argument to C unevaluated.
Therefore List.do(list_expression, pattern, do_block) must expose:
s_tag * plist_do (s_tag *list,
s_tag *pattern,
s_tag *do_block,
s_tag *dest);
with for example :
def do = cfn_macro Tag "plist_do" (Tag, Tag, Tag, Result)
The types in a cfn declaration describe values exchanged through the
C ABI. Scalar values are passed by value. Other values are passed as
pointers to their libkc3 representation.
| KC3 type | C type |
| --- | --- |
| Void | void |
| Bool | bool (uint8_t in the FFI ABI) |
| Character | u32 |
| S8 | s8 |
| S16 | s16 |
| S32 | s32 |
| S64 | s64 |
| Sw | sw |
| U8 | u8 |
| U16 | u16 |
| U32 | u32 |
| U64 | u64 |
| Uw | uw |
| F32 | f32 |
| F64 | f64 |
| F80 | f80 when enabled |
| F128 | f128 when enabled |
| Array | s_array * |
| Block | s_do_block * |
| Call | p_call * |
| Callable | p_callable * |
| Cfn | p_callable * |
| Fn | p_callable * |
| Fact | s_fact * |
| Ident | s_ident * |
| Integer | s_integer * |
| List | p_list * |
| Map | s_map * |
| Pointer | s_pointer * |
| Ptr | u_ptr_w * |
| PtrFree | u_ptr_w * |
| Ratio | s_ratio * |
| Str | s_str * |
| Struct | s_struct * |
| StructType | s_struct_type * |
| Sym | p_sym * |
| Tag | s_tag * |
| Time | s_time * |
| Tuple | p_tuple * |
| Var | p_var * |
Types ending in * in a KC3 declaration are typed C pointers. For
example, TLS* is passed as the underlying struct tls * pointer.
Result is not supplied by the KC3 caller. It asks KC3 to append a
pointer to the destination value. For example,
cfn Str "str_init" (Result, Str) receives an s_str * destination
and an s_str * input. The C function normally returns the destination
pointer as well.
When a Result argument is present, the returned C pointer is checked
after the call for mismatch :
Result destination is an ABI
error; KC3 reports the mismatch and the C function call fails;void and the destination is not used as the result;Result destination commits the value written
there and returns it to the KC3 caller.C functions using Result should therefore return the destination
pointer on success and NULL on an ordinary failure. They must not
return a different allocated pointer or that will be reported as an
error by the Cfn call evaluator.
The idea behind this is that if you put your Result first in a C
function and it matches a register size, then your first argument
will probably be rax or similar and smaller. If your result also is
the same register it matches most ISA as they return their register
sized result into the first one thus eliminating several machine
opcodes per function call. In a hot path that's why we use C or a
finely tunable or smart compiled language : it matters.
Top : KC3 documentation
Previous : 1.04 Bool
Next : 1.06 Call