www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Checking if CTFE is used?

reply berni <someone somemail.de> writes:
Is there a way to check if a function is indeed executed at 
compile time or not? (Other than going through the whole 
executable binaries...)

I tried

 static this()
 {
   if (__ctfe) pragma(msg,"works");
   // some other stuff
 }
but unfortunatley this "if" is also executed at compile time, when I put it into a function that is only called at runtime. When I try "static if" instead the compiler complains about "__ctfe" being not known at compile time.
Dec 18 2018
next sibling parent Daniel Kozak <kozzi11 gmail.com> writes:
On Tue, Dec 18, 2018 at 1:25 PM berni via Digitalmars-d-learn <
digitalmars-d-learn puremagic.com> wrote:

 Is there a way to check if a function is indeed executed at
 compile time or not? (Other than going through the whole
 executable binaries...)

 I tried

 static this()
 {
   if (__ctfe) pragma(msg,"works");
   // some other stuff
 }
but unfortunatley this "if" is also executed at compile time, when I put it into a function that is only called at runtime. When I try "static if" instead the compiler complains about "__ctfe" being not known at compile time.
You could use __ctfeWrite But it seems __ctfe does not work anymore https://run.dlang.io/is/snckyV
Dec 18 2018
prev sibling next sibling parent reply Stefan Koch <uplink.coder googlemail.com> writes:
On Tuesday, 18 December 2018 at 12:21:44 UTC, berni wrote:
 Is there a way to check if a function is indeed executed at 
 compile time or not? (Other than going through the whole 
 executable binaries...)

 I tried

 static this()
 {
   if (__ctfe) pragma(msg,"works");
   // some other stuff
 }
but unfortunatley this "if" is also executed at compile time, when I put it into a function that is only called at runtime. When I try "static if" instead the compiler complains about "__ctfe" being not known at compile time.
Why would you need to know?
Dec 18 2018
parent reply berni <someone somemail.de> writes:
On Tuesday, 18 December 2018 at 13:53:01 UTC, Stefan Koch wrote:
 Why would you need to know?
Well, first out of curiosity. But there are also other reasons: I've got a large immutable array. Without CTFE I'd use some php script and add it as a large literal. With CTFE I don't need that php script nor do I need to put that large literal in the source code. But I need to know, that indeed the array is calculated by the compiler, else the solution with the php script would result in faster code.
 if(__ctfe) assert(0, "Yep, CTFE used");
That seems to work, but unfortunately, my script seems not to be evaluated at compile time... Here is a small example, similar to my code, where CTFE is not used:
 import std.stdio;

 class A
 {
     static immutable int[4] clue;
 
     static this()
     {
         if(__ctfe) assert(0, "Yep, CTFE used");
         foreach (i;0..4) clue[i] = i;
     }
 }
 void main()
 {
     auto tmp = new A();
     writeln(tmp.clue[2]);
 }
Can you help me, finding the problem here?
Dec 18 2018
next sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Tuesday, 18 December 2018 at 14:23:38 UTC, berni wrote:
 import std.stdio;

 class A
 {
     static immutable int[4] clue;
 
     static this()
     {
         if(__ctfe) assert(0, "Yep, CTFE used");
         foreach (i;0..4) clue[i] = i;
     }
 }
CTFE is used if and only if it MUST be used by context. That's a runtime function, so no ctfe. Do something like: int[4] generate() { int[4] tmp; foreach(i; 0..4) tmp[i] = i; return tmp; } static immutable int[4] clue = generate(); Since it is an immediate static immutable assign, ctfe MUST be used, and thus will be used. With your code, you used a runtime constructor on all runtime variables, so it did it at program startup. Generally: static immutable something = something; // must be ctfe enum something = something; // makes a ctfe literal (but not necessarily static storage) so those patterns force ctfe. While static immutable something; something = something; // NOT ctfe because it is a separate statement!
Dec 18 2018
parent reply berni <someone somemail.de> writes:
On Tuesday, 18 December 2018 at 14:32:29 UTC, Adam D. Ruppe wrote:
 CTFE is used if and only if it MUST be used by context. That's 
 a runtime function, so no ctfe.

 Do something like:

 int[4] generate() {
    int[4] tmp;
    foreach(i; 0..4) tmp[i] = i;
    return tmp;
 }


 static immutable int[4] clue = generate();
Great, that worked. :-) My reasoning was, that CTFE is somewhat greedy, that is, everything that can be evaluated at compile time will be evaluated at compile time... Many thanks for your replies. :-)
Dec 18 2018
parent Jonathan M Davis <newsgroup.d jmdavisprog.com> writes:
On Tuesday, December 18, 2018 9:20:11 AM MST berni via Digitalmars-d-learn 
wrote:
 On Tuesday, 18 December 2018 at 14:32:29 UTC, Adam D. Ruppe wrote:
 CTFE is used if and only if it MUST be used by context. That's
 a runtime function, so no ctfe.

 Do something like:

 int[4] generate() {

    int[4] tmp;
    foreach(i; 0..4) tmp[i] = i;
    return tmp;

 }


 static immutable int[4] clue = generate();
Great, that worked. :-) My reasoning was, that CTFE is somewhat greedy, that is, everything that can be evaluated at compile time will be evaluated at compile time... Many thanks for your replies. :-)
It's pretty much the opposite. CTFE is only ever done when the compiler needs the result at compile-time, and it's never done as an optimization, if nothing else because the compiler has no way of knowing whether the function is even CTFE-able until it actually tries. Having it attempt CTFE in a bunch of places and then give up (to then call the function at runtime instead) would likely have a very negative impact on compilation time - especially since CTFE isn't very efficient at the moment (though whenever the newCTFE that Stefan is working on finally lands, that should improve significantly). As things stand, you have complete control over when CTFE occurs, and it's usually pretty easy to figure out if it's happening or not. As long as you understand which things must be known at compile-time, it's straightforward. - Jonathan M Davis
Dec 18 2018
prev sibling parent MachineCode <jckj33 gmail.com> writes:
On Tuesday, 18 December 2018 at 14:23:38 UTC, berni wrote:
 On Tuesday, 18 December 2018 at 13:53:01 UTC, Stefan Koch wrote:
 Why would you need to know?
Well, first out of curiosity. But there are also other reasons: I've got a large immutable array. Without CTFE I'd use some php script and add it as a large literal. With CTFE I don't need that php script nor do I need to put that large literal in the source code. But I need to know, that indeed the array is calculated by the compiler, else the solution with the php script would result in faster code.
How is the items in the array generated? if the function can be called as following:
 enum myArr = generateArray();
then you know for sure you have a satic array of strings at compile time. I've used something similar, to generate a JSON string from all (I made the D output a string from the request by command line option). I did something like this: string getAvailableForms() { import extensions.enumeration : staticMembers; import asdf; // JSON serializer import std.traits : getUDAs, hasUDA; import externalPaths : ExternalAppPath, DisplayName; import std.algorithm : startsWith; import std.conv : to; FormDisplayNameObj[] output; static foreach(string fieldName; staticMembers!ExternalAppPath) {{ static if(hasUDA!(__traits(getMember, ExternalAppPath, fieldName), DisplayName)) { if(fieldName.startsWith(startKey)) { DisplayName dn = getUDAs!(__traits(getMember, ExternalAppPath, fieldName), DisplayName)[0]; string id = extractDigits(fieldName[startKey.length - 1 .. $]); int i = to!int(id); auto o = new FormDisplayNameObj(); o.value = dn.value; o.index = i; output ~= o; } } }} return output.serializeToJson; } then: enum s = getAvailableForms; writeln(s); I did consider at first make a script to generate that string but I managed to make it work with CTFE that way.
Dec 20 2018
prev sibling parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 12/18/18 7:21 AM, berni wrote:
 Is there a way to check if a function is indeed executed at compile time 
 or not? (Other than going through the whole executable binaries...)
 
 I tried
 
 static this()
 {
   if (__ctfe) pragma(msg,"works");
   // some other stuff
 }
but unfortunatley this "if" is also executed at compile time, when I put it into a function that is only called at runtime. When I try "static if" instead the compiler complains about "__ctfe" being not known at compile time.
Well, asserting would at least tell you that it's used. if(__ctfe) assert(0, "Yep, CTFE used"); But obviously, it couldn't be there for release purposes :) -Steve
Dec 18 2018