Floating Insertions¶
A floating insertion is a string containing C/C++ code which is literally inserted into the C++ that Felix generates.
Insertion Locations¶
There are two locations for the insertion:
- header insertions go near the top of the generated header file
- body insertions go near the top of the generated body file after #include directives, but before any definitions generated by Felix
header '#include "interface"`;
body 'void implementation() {}';
Polymorphic Insertions¶
There are two kinds of insertions:
- plain insertions
- polymorphic insertions
A plain insertion is inserted as written. A polymorphic insertion is inserted as written except that it may contain type parameters written using the ?9 kind of notation. Polymorphic insertions must be named and dummy parameters specified, as with a C type binding:
//$ In place list reversal: unsafe!
// second arg is a dummy to make overload work
proc rev[T,PLT=&list[T]] : &list[T] = "_rev($1,(?1*)0);" requires _iprev_[T,PLT];
body _iprev_[T,PLT]=
"""
static void _rev(?2 plt, ?1*) // second arg is a dummy
{ // in place reversal
struct node_t { void *tail; ?1 elt; };
void *nutail = 0;
void *cur = *plt;
while(cur)
{
void *oldtail = ((node_t*)FLX_VNP(cur))->tail; // save old tail in temp
((node_t*)FLX_VNP(cur))->tail = nutail; // overwrite current node tail
nutail = cur; // set new tail to current
cur = oldtail; // set current to saved old tail
}
*plt = nutail; // overwrite
}
"""
;
In this example we defined a function _rev in C++, used to reverse a list in place. The insertion containing it, _iprev_[T,PLT] is polymorphic, the actuual types are specified in the C bindings for rev.
Requires Clause¶
C bindings may specify a requires clause with a list of requirements. For floating insertions there are three options:
- require literally given header
- require literally given body
- require by insertion tag name
Insertions themselves may have requirements.
Tag names¶
Insertion tag names are scoped by classes and may require explicit qualification. However the tag namespace is independent of ordinary definitions.
Any number of insertions may have the same tag name.
Closure Formation¶
When a named requirement is triggered, all the insertions with that tag name, and any insertions they themselves require, recursively, will be inserted. Requiring a non-existant tag is an error.
Circular references are permitted.
Order of Insertion¶
Insertion of the same kind defined in the same Felix file retain their order in the generated output, in otherwords, they’re emitted in the order of writing, not the order of dependence.
If a text has been emitted, it will not be emitted again: duplication is eliminated. Note this rule applies to polymorphic insertions after substitution of types.
Global Insertions¶
An unnamed insertion specified by a requires statement is taken as a requirement of all C bindings and floating insertions in the class containing it, including any nested classes.
Triggering Insertions¶
Insertions are only triggered if the C binding or insertion they’re attached to is actually used in the final program. This reduces the output to what is actually needed.