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:

  1. header insertions go near the top of the generated header file
  2. 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:

  1. plain insertions
  2. 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:

  1. require literally given header
  2. require literally given body
  3. 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.