www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Expanding CTFE code during compilation

reply Azi Hassan <azi.hassan live.fr> writes:
Hello,

Apologies in advance if this has been asked before. I can't find 
the right words to express what I'm looking for, but essentially, 
I'm wondering if the offers has the option of executing the parts 
that can be evaluated at compile time and then replacing them 
with the result of this evaluation. The C equivalent would be 
compiling with the -E flag as explained here : 
https://stackoverflow.com/questions/4900870/can-gcc-output-c-code-after-preprocessing

For example :

```
//main.d
import std;

void main()
{
     enum x = iota(1, 5).reduce!"a * b";
     x.writeln();
}
```

Then after running something like

```
dmd --expand-ctfe main.d -o expanded.d
cat expanded.d
```

We'd get :

```
//expanded.d
import std;

void main()
{
     24.writeln();
}
```

Just in case this is a consequence of the XY problem, the reason 
why I'm looking for this is to make sure that the code I wrote 
did evaluate to what I'm expecting it to. Right now I do this 
with an enum assignment followed by static asserts, but I'd love 
it for there to be some sort of visual feedback.

Thanks in advance
Jul 19 2022
next sibling parent reply Dennis <dkorpel gmail.com> writes:
On Tuesday, 19 July 2022 at 21:43:01 UTC, Azi Hassan wrote:
 I'm wondering if the offers has the option of executing the 
 parts that can be evaluated at compile time and then replacing 
 them with the result of this evaluation.
Try the `-vcg-ast` flag: ```D import object; import std; void main() { enum int x = 24; writeln(24); return 0; } // ... and a bunch of template instances ```
Jul 19 2022
parent reply Azi Hassan <azi.hassan live.fr> writes:
On Tuesday, 19 July 2022 at 22:27:56 UTC, Dennis wrote:
 On Tuesday, 19 July 2022 at 21:43:01 UTC, Azi Hassan wrote:
 I'm wondering if the offers has the option of executing the 
 parts that can be evaluated at compile time and then replacing 
 them with the result of this evaluation.
Try the `-vcg-ast` flag: ```D import object; import std; void main() { enum int x = 24; writeln(24); return 0; } // ... and a bunch of template instances ```
Thanks a lot, this is exactly what I had in mind. Where did you find it though ? I checked dmd --help and man dmd before making this thread, but to no avail.
Jul 19 2022
parent reply Dennis <dkorpel gmail.com> writes:
On Wednesday, 20 July 2022 at 00:33:06 UTC, Azi Hassan wrote:
 Where did you find it though ? I checked dmd --help and man dmd 
 before making this thread, but to no avail.
It was implemented as an internal debugging tool, not a documented feature: https://github.com/dlang/dmd/pull/6556 It turned out to be useful for users as well though, and got exposure through the "AST" button on https://run.dlang.io/ Maybe it's time to document it, currently there's only this: https://wiki.dlang.org/DMD_Source_Guide#View_emitted_templates_instances_and_string.2Fmixins
Jul 20 2022
parent Azi Hassan <azi.hassan live.fr> writes:
On Wednesday, 20 July 2022 at 14:11:52 UTC, Dennis wrote:
 On Wednesday, 20 July 2022 at 00:33:06 UTC, Azi Hassan wrote:
 Where did you find it though ? I checked dmd --help and man 
 dmd before making this thread, but to no avail.
It was implemented as an internal debugging tool, not a documented feature: https://github.com/dlang/dmd/pull/6556 It turned out to be useful for users as well though, and got exposure through the "AST" button on https://run.dlang.io/ Maybe it's time to document it, currently there's only this: https://wiki.dlang.org/DMD_Source_Guide#View_emitted_templates_instances_and_string.2Fmixins
I see, thanks. I'll be sure to check the wiki next time.
Jul 22 2022
prev sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 7/19/22 5:43 PM, Azi Hassan wrote:

 Just in case this is a consequence of the XY problem, the reason why I'm 
 looking for this is to make sure that the code I wrote did evaluate to 
 what I'm expecting it to. Right now I do this with an enum assignment 
 followed by static asserts, but I'd love it for there to be some sort of 
 visual feedback.
 
 Thanks in advance
```d template printEnum(alias x, string file = __FILE__, size_t line = __LINE__) { enum printEnum = x; pragma(msg, file, "(", int(line), "): ", printEnum); } enum x = printEnum!(iota(1, 5).reduce!"a * b"); ``` This will spit out the file, line, and value for the declaration. Assuming this is useful for your double-checking you could do this, and then switch it back when you have verified that it's correct. -Steve
Jul 19 2022
parent reply Azi Hassan <azi.hassan live.fr> writes:
On Tuesday, 19 July 2022 at 22:41:43 UTC, Steven Schveighoffer 
wrote:
 On 7/19/22 5:43 PM, Azi Hassan wrote:

 Just in case this is a consequence of the XY problem, the 
 reason why I'm looking for this is to make sure that the code 
 I wrote did evaluate to what I'm expecting it to. Right now I 
 do this with an enum assignment followed by static asserts, 
 but I'd love it for there to be some sort of visual feedback.
 
 Thanks in advance
```d template printEnum(alias x, string file = __FILE__, size_t line = __LINE__) { enum printEnum = x; pragma(msg, file, "(", int(line), "): ", printEnum); } enum x = printEnum!(iota(1, 5).reduce!"a * b"); ``` This will spit out the file, line, and value for the declaration. Assuming this is useful for your double-checking you could do this, and then switch it back when you have verified that it's correct. -Steve
Nice, a compile time console.log. Thanks a lot, this will come in handy. I wonder if it can be combined with version(debug) to only run the pragma line if compiled with -g, this way we can keep the printEnum! line as it is. Then again, the code would become polluted by debugging logic
Jul 19 2022
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 7/19/22 8:33 PM, Azi Hassan wrote:
 
 Nice, a compile time console.log. Thanks a lot, this will come in handy. 
 I wonder if it can be combined with version(debug) to only run the 
 pragma line if compiled with -g, this way we can keep the printEnum! 
 line as it is. Then again, the code would become polluted by debugging 
 logic
Yep: ```d debug template printEnum(...) { ... // everything we already did } else enum printEnum(alias x) = x; ``` There's a slight bloat in the compiler symbol table when but other than that it should be effective. -Steve
Jul 19 2022
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 7/19/22 8:57 PM, Steven Schveighoffer wrote:

 There's a slight bloat in the compiler symbol table when  but other than 
 that it should be effective.
Obviously I didn't finish that thought... "when `-debug` isn't used on the command line" -Steve
Jul 19 2022
parent reply Azi Hassan <azi.hassan live.fr> writes:
On Wednesday, 20 July 2022 at 01:15:44 UTC, Steven Schveighoffer 
wrote:
 On 7/19/22 8:57 PM, Steven Schveighoffer wrote:

 There's a slight bloat in the compiler symbol table when  but 
 other than that it should be effective.
Obviously I didn't finish that thought... "when `-debug` isn't used on the command line" -Steve
Oh, interesting syntax. I was thinking something along the lines of ```D template printEnum(...) { version(debug) { ... // everything we already did } else { enum printEnum(alias x) = x; } } ``` But I like yours better.
Jul 22 2022
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 7/22/22 3:22 PM, Azi Hassan wrote:

 Oh, interesting syntax. I was thinking something along the lines of
 
 ```D
 template printEnum(...) {
      version(debug) {
          ... // everything we already did
      } else {
          enum printEnum(alias x) = x;
      }
 }
 ```
 
 But I like yours better.
`version(debug)` isn't valid syntax, `debug` is a keyword. -Steve
Jul 22 2022
parent reply Azi Hassan <azi.hassan live.fr> writes:
On Saturday, 23 July 2022 at 00:56:39 UTC, Steven Schveighoffer 
wrote:
 On 7/22/22 3:22 PM, Azi Hassan wrote:

 Oh, interesting syntax. I was thinking something along the 
 lines of
 
 ```D
 template printEnum(...) {
      version(debug) {
          ... // everything we already did
      } else {
          enum printEnum(alias x) = x;
      }
 }
 ```
 
 But I like yours better.
`version(debug)` isn't valid syntax, `debug` is a keyword. -Steve
I stand corrected, I must've got it confused with version(unittest)
Jul 23 2022
parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 7/23/22 2:27 PM, Azi Hassan wrote:
 On Saturday, 23 July 2022 at 00:56:39 UTC, Steven Schveighoffer wrote:
 On 7/22/22 3:22 PM, Azi Hassan wrote:

 Oh, interesting syntax. I was thinking something along the lines of

 ```D
 template printEnum(...) {
      version(debug) {
          ... // everything we already did
      } else {
          enum printEnum(alias x) = x;
      }
 }
 ```

 But I like yours better.
`version(debug)` isn't valid syntax, `debug` is a keyword.
I stand corrected, I must've got it confused with version(unittest)
And *I* stand corrected! `unittest` is also a keyword, so clearly that's not disqualifying. Indeed, the grammar specifically includes `version(unittest)` and `version(assert)`. However, because `debug` is exactly like `version` in how it operates, `version(debug)` would make little sense. -Steve
Jul 25 2022