Modular C
Code unrolling

Synopsis:
#pragma CMOD foreach NAME = EL0 EL1 ....
#pragma CMOD done
#pragma CMOD do NAME = [ START ] END [ OPERATION ]
#pragma CMOD done

foreach

This feature allows us to repeat code a fixed number of times such that at each copy ${NAME} is replace by the words EL0, EL1 etc. E.g to create a type generic maximum macro:

#pragma CMOD module max = proj∷max
#pragma CMOD composer —
#pragma CMOD declaration
#pragma CMOD foreach T = float double unsigned signed
inline
${T} max—${T}(${T} a, ${T} b) {
return a < b ? b ? a;
}
#pragma CMOD done
#define max(A, B) _Generic((A)+(B), \
default: max—double, \
float: max—float, \
unsigned:max—unsigned, \
signed: max—signed) \
((A), (B))

This creates four functions and a type generic interface macro.

The foreach directive is not limited to executable code. It unrolls every programming text:

#pragma CMOD foreach T = float double unsigned signed
struct pair—${T} { ${T} v; };
#pragma CMOD done
static double A[] = {
#pragma CMOD foreach X = 0 1 2 3 4 5 6 7 8 9
${X}*${X},
#pragma CMOD done
}

Here to declare four different types and to statically initialize an array with 10 different computed values.

do

A do directive is another possibility to expand code a fixed number of times. The difference to foreach is that the domain is arithmetic. The last foreach directive could be replaced as follows:

static double A[] = {
#pragma CMOD do X = 0 10 +1
${X}*${X},
#pragma CMOD done
}

where the 0 and +1 are even optional and

static double A[] = {
#pragma CMOD do X = 10
${X}*${X},
#pragma CMOD done
}

would be equivalent.

The rules for the indices are "C-like". If not specified, the START value is 0 and END is an exclusive upper or lower bound. The permitted operators in OPERATIONS are +, -, * and /. The update operation is to perform NAME = NAME OPERATION so in our example it would correspond to X = X +1. If the operation in OPERATION is + or *, END is taken as an upper bound, if it is - or / it is a lower bound.

So

#pragma CMOD do P = 1 16 *2
something
#pragma CMOD done

expands the inner code block 4 times, for values of P of 1, 2, 4 and 8.

#pragma CMOD do P = 8 0 /2
something
#pragma CMOD done

iterates over the same values but in different order, for values of P is set to 8, 4, 2, and then 1.