mixin does not work as expected

rempas rempas at tutanota.com
Wed Jan 5 08:40:15 UTC 2022


I'm trying to use mixins and enums to "expand" code in place but 
the results are not what I expected and I'm getting an weird 
error. I have created the smallest possible example to reproduce 
the error and it is the following:

```
enum base_digit(string ten, string sixteen, string two, string 
eight) = `
   if (base == 10)      i = ` ~ ten ~ `;
   else if (base == 16) i = ` ~ sixteen ~ `;
   else if (base == 2)  i = ` ~ two ~ `;
   else if (base == 8)  i = ` ~ eight ~ `;
`;

enum overflow_check(string type) = `
   if (num == ` ~ type ~ `) {
     min_num = true;
     ++num;
   }
`;

enum type_check(string which_if, string type, string signed,
     string ten, string sixteen, string two, string eight) =
   which_if ~ `(is_same!(num, ` ~ type ~ `)) {
     mixin(base_digit!("` ~ ten ~ `", "` ~ sixteen
           ~ `", "` ~ two ~ `", "` ~ eight ~ `"));
     static if (` ~ signed ~ `) {
       mixin(overflow_check!"` ~ type ~ `.min"); }
   }
`;

void test(bool signed)(int num, int base) {
   static if (signed) {
     mixin(type_check!("static if", "i8", "true", "5", "4", "10", 
"5"));
     mixin(type_check!("else static if", "i16", "true", "7", "6", 
"18", "8"));
     mixin(type_check!("else static if", "i32", "true", "12", 
"10", "34", "13"));
     mixin(type_check!("else", "i64", "true", "21", "18", "66", 
"24"));
   }

   else {
     mixin(type_check!("static if", "u8", "false", "4", "3", "9", 
"4"));
     mixin(type_check!("else static if", "u16", "false", "6", "5", 
"17", "7"));
     mixin(type_check!("else static if", "u32", "false", "11", 
"9", "33", "12"));
     mixin(type_check!("else", "u64", "false", "21", "17", "65", 
"23"));
   }
}

extern (C) void main() {
   test!true(10, 16);
}
```

In my normal code, the "test" function is actually part of an 
emum that is expanded from another function (told you, the whole 
code will just be to complicated for anyone to read). In the 
example, trying to compile will give the following error:

```
test.d-mixin-27(27): Error: template instance `is_same!(num, i8)` 
template `is_same` is not defined
test.d-mixin-28(28): Error: found `else` without a corresponding 
`if`, `version` or `debug` statement
test.d-mixin-29(29): Error: found `else` without a corresponding 
`if`, `version` or `debug` statement
test.d-mixin-30(30): Error: found `else` without a corresponding 
`if`, `version` or `debug` statement
test.d(42): Error: template instance `test.test!true` error 
instantiating
```

Now as you can see, there are three times this error occurs in 
the expansion of the mixin. The error will go away if we comment 
the three mixins in the first "static if" branch (as in our 
example, "signed" is set to true so the first branch will get 
compiled). So from me understanding, when a mixin is expanded, 
the compiler checks the code from the mixin SEPARATELY and sees 
if it makes sense. So for that reason, it sees as there is only 
an "else static if" without a "static if" before and thus it 
gives us the error. Tho this doesn't seem right because how can 
it see the other variables like "num" or "base" that were not 
defined INSIDE the enum as its parameters? So it may be another 
sneaky bug that I can't understand. Or like it has happened to 
the past, it may be something obvious that I'm so blind to see 
and someone will tell me and I'll get embarrassed again (this is 
why I don't like asking only for help fixing bugs)...


More information about the Digitalmars-d-learn mailing list