digitalmars.D.learn - Checking if CTFE is used?
- berni (8/13) Dec 18 2018 Is there a way to check if a function is indeed executed at
- Daniel Kozak (5/18) Dec 18 2018 You could use __ctfeWrite
- Stefan Koch (2/15) Dec 18 2018 Why would you need to know?
- berni (12/30) Dec 18 2018 Well, first out of curiosity. But there are also other reasons:
- Adam D. Ruppe (22/34) Dec 18 2018 CTFE is used if and only if it MUST be used by context. That's a
- berni (5/14) Dec 18 2018 Great, that worked. :-) My reasoning was, that CTFE is somewhat
- Jonathan M Davis (14/34) Dec 18 2018 It's pretty much the opposite. CTFE is only ever done when the compiler
- MachineCode (44/54) Dec 20 2018 How is the items in the array generated? if the function can be
- Steven Schveighoffer (5/20) Dec 18 2018 Well, asserting would at least tell you that it's used.
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 triedstatic 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
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 triedYou could use __ctfeWrite But it seems __ctfe does not work anymore https://run.dlang.io/is/snckyVstatic 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
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 triedWhy would you need to know?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
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
On Tuesday, 18 December 2018 at 14:23:38 UTC, berni 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(); 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!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; } }
Dec 18 2018
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
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: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 DavisCTFE 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
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:How is the items in the array generated? if the function can be called as following: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.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
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 triedWell, 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 :) -Stevestatic 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