i'm an amateur programmer that just started learning C. i like most of the 
features, specially the c preprocessor that it comes packed with. it's an 
extremely portable way of implementing metaprogramming in C.

though i've always thought it lacked a single feature -- an "evaluation" 
feature.

say i have these definitions:
#define MACRO_1               (x/y)*y
#define MACRO_2               sqrt(a)
#define MACRO_3               calc13()
....
#define MACRO_15         (a + b)/c


now, all throughout the codebase, whenever and whichever of MACRO_1, or MACRO_2 
(or so forth) needs to be called, they are conveniently "indexed" by another 
macro expansion:

#define CONCAT(a, b)                  a##b
#define CONCAT_VAR(a, b)           CONCAT(a, b)

#define MASTER_MACRO(N)         CONCAT_VAR(MACRO_, N)

now, if we use MASTER_MACRO with a "direct" value:

MASTER_MACRO(10)
or
#define N              10
MASTER_MACRO(10)
both will work.


but substitute this with:

#define N                                    ((5*a)/c + (10*b)/c + ((5*a) % c + 
(10*b) % c)/c)

and MASTER_MACRO expands to:
MACRO_((5*a)/c + (10*b)/c + ((5*a) % c + (10*b) % c)/c)

which, of course is wrong.
there are other workarounds or many times this scheme can be avoided altogether.
but it can be made to work (elegantly) by adding an "eval" preprocessor 
operation:

so we redefine MASTER_MACRO this way:
#define MASTER_MACRO(N)         CONCAT_VAR(MACRO_, eval(N))
which evaluates correctly.

this nifty trick (though a bit extended than what i elaborated above) can also 
be used to *finally* have increments and decrements (among others).
since "eval" forces the evaluation of an *arithmetic* expression (for now), it 
will force the evaluation of an expression, then define it to itself.
this will of course trigger a redefinition flag from our beloved preprocessor, 
but the defined effect would be:

#define X             (((14*x)/y)/z)    /* say this evaluates to simply 3 */

incrementing X, will simply be:
#define X             eval(eval(X) + 1)    /* 1) will be evaluated as 4 before 
any token substitution */
#define X             eval(eval(X) + 1)    /* 2) will be evaluated as 5 before 
any token substitution */

that easy.

to suppress the redef warnings, we can have another directive like force_redef 
(which can only work in conjunction with eval)
#force_redef  X             eval(eval(X) + 1)

i'm just confused :-S...
why hasn't this been suggested? i would love to have this incorporated (even 
just on test builds) to gcc.
it would make my code so, so much more manageable and virtually extensible to 
more platforms.

i would love to have a go at it and probably modify the gcc preprocessor, but i 
since i know nothing of it's implementation details, i don't know where to 
begin. i was hoping that this being a gnu implementation, it's been heavily 
modularized (the fact that gcc was heavily revised back then to use abstract 
syntax trees, gimple, etc, past version 2.95 -- ???). so i can easily 
"interrupt" the parsing operation (i wouldn't dare implement a 
pre-preprocessing operation, being big and redundant), then substitute the 
eval, then make the whole prasing go again.

any advice for a novice? thnx.
                                          

Reply via email to