Description of the semantics of primitives, to be used for optimization purposes.
"No effects" means that the primitive does not change the observable state of the world. For example, it must not write to any mutable storage, call arbitrary external functions or change control flow (e.g. by raising an exception). Note that allocation is not "No effects" (see below).
It is assumed in the compiler that applications of primitives with no effects, whose results are not used, may be eliminated. It is further assumed that applications of primitives with no effects may be duplicated (and thus possibly executed more than once).
(Exceptions arising from allocation points, for example "out of memory" or exceptions propagated from finalizers or signal handlers, are treated as "effects out of the ether" and thus ignored for our determination here of effectfulness. The same goes for floating point operations that may cause hardware traps on some platforms.)
"Only generative effects" means that a primitive does not change the observable state of the world save for possibly affecting the state of the garbage collector by performing an allocation. Applications of primitives that only have generative effects and whose results are unused may be eliminated by the compiler. However, unlike "No effects" primitives, such applications will never be eligible for duplication.
"Arbitrary effects" covers all other primitives.
"No coeffects" means that the primitive does not observe the effects (in the sense described above) of other expressions. For example, it must not read from any mutable storage or call arbitrary external functions.
It is assumed in the compiler that, subject to data dependencies, expressions with neither effects nor coeffects may be reordered with respect to other expressions.
val for_primitive : Clambda_primitives.primitive -> effects * coeffects
Describe the semantics of a primitive. This does not take into account of the (non-)(co)effectfulness of the arguments in a primitive application. To determine whether such an application is (co)effectful, the arguments must also be analysed.
val return_type_of_primitive : Clambda_primitives.primitive -> return_type