0

The behavior i want

#define E() E2(k)
#define E2(k) printf("%d", k);

#define A A2(__COUNTER__)
#define A2(k) E()
A

I would like to E() expands FIRTS to E2(k) in the line #define A2(k) E(). Then the result would be printf("%d", some_number);

The real problem

Actually, im working on my college assignment and i need to simulate a language that only accepts:

V = V + 1
V = V - 1
if (V != 0) goto LABEL

We can create as many variables as we want. All the variables have the initial value equal 0. We cant use functions or nothing else. But we should use macros to re-use the code. For example, look what a macro that resets a variable value to zero looks like:

#define L(i, k) L1(i, k, __LINE__)
#define L1(i, k, l) L2(i, k, l)
#define L2(i, k, l) L_##i##k##_##l

#define ZERO(x) ZERO2(x, __COUNTER__)
#define ZERO2(x, k) \
                    goto L(B, k); \
        L(A, k):    x = x - 1; \
        L(B, k):    if (x != 0) goto L(A, k);

Note that this macro looks much more complicated then should be. Right? But all that bunch of thing are necessary. Let me explain. The simplified macro for this should looks like this:

#define ZERO(x) \
            goto B; \
        A:  x = x - 1; \
        B:  if (x != 0) goto A;

But the problem it won't be possible to call more than one ZERO(v) macro. Because the labels A and B world be declared more than one time. To fix this we have to modify this macro to:

#define L(i) L1(i, __LINE__)
#define L1(i, l) L2(i, l)
#define L2(i, l) L_##i##_##l

#define ZERO(x) \
            goto L(B); \
        L(A):   x = x - 1; \
        L(B):   if (x != 0) goto L(A);

Now we can call multiple ZERO(v) as long as we don't call more than one ZERO macro per line. But we still have one problem with this code. We cant call multiple ZERO macros inside another macro because the labels would get the same LINE index and would cause conflict. Look:

#define 2ZERO(x, y) \
                ZERO(x) \
                ZERO(y)

To fix this we need to pass another index for the labels inside each ZERO macro:

#define L(i, k) L1(i, k, __LINE__)
#define L1(i, k, l) L2(i, k, l)
#define L2(i, k, l) L_##i##k##_##l

#define ZERO(x) ZERO2(x, __COUNTER__)
#define ZERO2(x, k) \
                    goto L(B, k); \
        L(A, k):    x = x - 1; \
        L(B, k):    if (x != 0) goto L(A, k);

Now everything works. But the thing is, i dont want to write L(label, k), i would like to write just L(label) and this macro automatically should be changed to L(label, k) and everything should works.

Full Code (if some how helps)

#define L(i, k) L1(i, k, __LINE__)
#define L1(i, k, l) L2(i, k, l)
#define L2(i, k, l) L_##i##k##_##l

#define VARD(v, k) VARD1(v, k)
#define VARD1(v, k) int v##_##k = 0;

#define VAR(v, k) VAR1(v, k)
#define VAR1(v, k) v##_##k

#define END(k) END1(k, __LINE__)
#define END1(k, l) END2(k, l)
#define END2(k, l) L_##k##_##l

#define ZERO(x) ZERO2(x, __COUNTER__)
#define ZERO2(x, k) \
                            goto L(B, k); \
                L(A, k):    x = x - 1; \
                L(B, k):    if (x != 0) goto L(A, k);

#define ASSIGN(y, x) ASSIGN2(y, x, __COUNTER__)
#define ASSIGN2(y, x, k) \
                            VARD(u1, k) \
                            ZERO(y); \
                L(A, k):    if (x != 0) goto L(B, k); \
                            goto L(C, k); \
                L(B, k):    x = x - 1; \
                            y = y + 1; \
                            VAR(u1, k) = VAR(u1, k) + 1; \
                            goto L(A, k); \
                L(C, k):    if (VAR(u1, k) != 0) goto L(D, k); \
                            goto END(k); \
                L(D, k):    VAR(u1, k) = VAR(u1, k) - 1; \
                            x = x + 1; \
                            goto L(C, k); \
                END(k):     

#define ADD(y, x) ADD2(y, x, __COUNTER__)
#define ADD2(y, x, k)   \
                            VARD(u1, k) \
                            ASSIGN(VAR(u1, k), x) \
                L(A, k):    if (VAR(u1, k) != 0) goto L(B, k); \
                            goto END(k); \
                L(B, k):    VAR(u1, k) = VAR(u1, k) - 1; \
                            y = y + 1; \
                            goto L(A, k); \
                END(k):

I don't know if this behavior that i want is possible using only macros. But i found some interesting links that might help: https://learn.microsoft.com/en-us/cpp/preprocessor/preprocessor-experimental-overview?view=msvc-170

  • Why have you `#define`d `E` twice? Wouldn't it make more sense to use two different names? – Paul Sanders Aug 12 '23 at 14:28
  • My fault, they can be different. i fixed it. @PaulSanders – user22379832 Aug 12 '23 at 14:34
  • OK, but, dude, macro hell!! That's never a good sign, have you considered tackling this some other way? – Paul Sanders Aug 12 '23 at 14:50
  • *i need to simulate a language...:* -- Isn't that what tokenization, lexer, semantic analysis, etc. supposed to be used for? What's all this with the macros? How is your assignment any different than the usual "create a language, and here is the syntax for this language", where in those assignments, you create the tokenizer, lexer, etc.? – PaulMcKenzie Aug 12 '23 at 14:53
  • 1
    Before you continue, read [why are preprocessor macros evil](https://stackoverflow.com/questions/14041453/why-are-preprocessor-macros-evil-and-what-are-the-alternatives). And then learn about (variadic) template functions and try to do at least most of your work using them. Share this with your teacher, in fact I'd like to have a word with him. Preprocessor should only be used if there is no other alternative – Pepijn Kramer Aug 12 '23 at 15:01
  • Maybe you understood "But we should use macros to re-use the code." incorrectly. Are you sure it is about C++ macros and not about "macros in your new language"? Did you get some "formal grammar" like a BNF? If so you need to build a parse tree and make some function calls to your C++ code to execute them or you need an interpreter doing the same. – Pepijn Kramer Aug 12 '23 at 15:03
  • Can you please include the full and complete assignment text in your question? With all limitations and requirements? – Some programmer dude Aug 12 '23 at 15:12
  • Guys, i know that macros shouldnt be used like this in a normal code and i know that i can achieve this language requirements using tokenization, lexer, semantic analysis... but the thing is, i want something as simple as possible. The macros that a wrote ALREADY achieve the requirements and restrictions, but its ugly because of the ", k);" sufix in almost every macro. I just would like to deliver a little cleaner code. – user22379832 Aug 12 '23 at 15:25
  • Well, good luck maintaining (and indeed debugging) this code. It really isn't the right way to do something that can be achieved by more straightforward means. – Paul Sanders Aug 12 '23 at 15:36
  • Bury that instructor alive. – Red.Wave Aug 13 '23 at 10:14

0 Answers0