Implement partial support for #define objects#302
Conversation
There was a problem hiding this comment.
Pull request overview
Adds partial handling for object-like #define macros that expand to C braced initializer lists (e.g. {1,2}), so dstep can preserve that initializer information in generated D output (as a placeholder with a FIXME marker).
Changes:
- Extend the macro expression AST with a new braced-initializer expression node (
ObjectExpr). - Parse
{ ... }token sequences as a standalone expression inMacroParser. - Translate this expression into a placeholder D value while retaining the original braced text in a
FIXMEcomment.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
dstep/translator/TypeInference.d |
Treats the new braced-initializer expression as Generic during type inference. |
dstep/translator/MacroParser.d |
Introduces ObjectExpr and parsing logic for { ... } object-style macro bodies. |
dstep/translator/MacroDefinition.d |
Adds translation support for ObjectExpr into a placeholder value with a FIXME marker. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
|
Is it possible to determine that it's an initializer and have DStep do the translation? |
```
struct S
{
int a;
int b;
};
#define S_INIT { 1, 2 }
int main()
{
struct S s = S_INIT;
}
```
Currently dstep will ignore `S_INIT` which loses this "init" information.
This PR implements partial support so that it becomes:
```
enum S_INIT = null /* FIXME: {1,2} */;
```
Which allows to create simple shell script with `sed` command to afterwards fix up these case with something like this:
```
$ sed -iE 's|null; /* FIXME: {\([^}]*\)}|S(\1)|g' file.d
```
Which will make final version to be:
```
enum S_INIT = S(1,2);
```
Unfortunately not really possible because:
Eg. consider struct s1 {
int *p1;
int *p2;
};
struct s2 {
struct s1 a;
int b;
int c;
};
#define INITIALIZER(x, y) { {{NULL}, {NULL}}, x, y }
// Use this like struct s2 d = INITIALIZER(1, 2);(none of files have actual usage so you can't know what type it maps to) extern (D) auto INITIALIZER(T1, T2)(auto ref T1 x, auto ref T2 y)
{
return s2(s1.init, x, y);
}You have to know that it's INITIALIZER: s2So you would create this mapping file manually and pass it to dstep so it would know to map it to this type. Also FYI I improved this PR and added tests. |
Consider common C pattern like:
Currently
dstepwill ignoreS_INITwhich loses this "init" information.This PR implements partial support so that
Will be produced, which allows to create simple shell script with simple
sedcommand to afterwards fix up these case with something like this:$ sed -iE 's|null; // FIXME: {\([^}]*\)}|S(\1)|g' file.dWhich will make final version to be:
And that will work correctly when
S_INITis used.Unfortunately this 2nd step with
sedor another processing tool is needed because implementing usage-aware processing insidedstepis not trivial and would require significant effort to also parse macro usages so that's why I'm settling on this partial support.