digitalmars.D.learn - Forcing compile time evaluation of pure functions
- scarrow (16/16) Jun 29 2011 Hey all,
- scarrow (9/9) Jun 29 2011 Oh, I also wanted to mention that although ideally I'd be able to invoke...
- bearophile (33/43) Jun 30 2011 Walter has decided that he doesn't like the D compiler to arbitrary run ...
- scarrow (4/4) Jul 14 2011 I think invoking a template to call the pure function (StaticEval!(Hash(...
- bearophile (6/7) Jul 14 2011 In GCC there is a way to (sometimes) do it, see the __builtin_constant_p...
- bearophile (4/6) Jul 14 2011 Google code search gives about 8,100 answers:
- Simen Kjaeraas (6/23) Jun 30 2011 Actually, there might. Pure functions are allowed to depend upon the
Hey all, I'd like to embed hashed strings into my code. The C++ version of this engine ran an external tool to preprocess the files. In D my strongly pure function is only evaluated if I assign it to something like an enum or invoke it from a template. So the following generate compile time hashes: enum blort = Hash("foo"); f(CHash!("foo")); Annoyingly, however, I can't do the following at compile time: f(Hash("foo")); I'm not sure what the point is in distinguishing between these two cases. If it is a properly pure function there should be no harm in doing a compile time evaluation. Ideally (and maybe this is being purposely avoided) I want to be able to write: string s = "bar"; f(Hash("foo")); // invoke the compile time version and pass a constant to f f(Hash(s)); // invoke the runtime version and pass the result to f
Jun 29 2011
Oh, I also wanted to mention that although ideally I'd be able to invoke the compile time and runtime versions identically and have it automatically select, I'm also worried about accidentally invoking the runtime version when I should have been using the compile time version. I can't think of a way to make it: string s = "foo"; auto h = Hash("foo"); // I'd like it to fail but doesn't auto i = CHash!("foo"); // works fine (compile time) auto j = Hash(s); // works fine (runtime) auto k = CHash!(s); // fails as it should
Jun 29 2011
scarrow:Annoyingly, however, I can't do the following at compile time: f(Hash("foo")); I'm not sure what the point is in distinguishing between these two cases.Walter has decided that he doesn't like the D compiler to arbitrary run at compile time arbitrary long to run code. This is named partial compilation and it has some traps. In theory I agree with you that I'd like the compiler to be smarter, but in practice Walter prefers control here, so DMD runs compile-time functions only if you explicitly ask their result to be known at compile-time. Note that in D you are able to run at compile time functions that are pure just in the execution path that's used at compile-time, even if on the whole they are not pure. This works: int x; int foo(bool b, int y) { if (b) return x; else return y; } enum result = foo(false, 10);I want to be able to write: string s = "bar"; f(Hash("foo")); // invoke the compile time version and pass a constant to f f(Hash(s)); // invoke the runtime version and pass the result to fIs this good enough? /** To execute a function at compile time. */ template StaticEval(A...) { enum typeof(A[0]) StaticEval = A[0]; } void f(size_t) {} size_t Hash(string s) { return 0U; } void main() { f(Hash("foo")); f(StaticEval!(Hash("foo"))); } The second Hash runs at compile-time, there is only one call to _D4test4HashFAyaZk (compiled with -O -release, without -inline): __Dmain comdat L0: push EAX push dword ptr FLAT:_DATA[0Ch] push dword ptr FLAT:_DATA[08h] call near ptr _D4test4HashFAyaZk call near ptr _D4test1fFkZv xor EAX,EAX call near ptr _D4test1fFkZv xor EAX,EAX pop ECX ret Bye, bearophile
Jun 30 2011
I think invoking a template to call the pure function (StaticEval!(Hash("foo")) isn't much different from StaticHash!("foo"). You still have to explicitly know whether you're dealing with a compile time constant or not. I'd really like to figure out how to have Hash("foo") be static and Hash(variable) be dynamic.
Jul 14 2011
scarrow:I'd really like to figure out how to have Hash("foo") be static and Hash(variable) be dynamic.In GCC there is a way to (sometimes) do it, see the __builtin_constant_p here: http://www.delorie.com/gnu/docs/gcc/gcc_81.html Time ago I have asked for something similar in D too, because I think it allows to implement a poor's man manual "partial compilation" using templates. Maybe it's worth asking about this in the main D newsgroup. But before asking, it's better to have few use cases examples :-) Bye, bearophile
Jul 14 2011
In GCC there is a way to (sometimes) do it, see the __builtin_constant_p here: http://www.delorie.com/gnu/docs/gcc/gcc_81.htmlGoogle code search gives about 8,100 answers: http://www.google.com/codesearch#search/&q=%22__builtin_constant_p%22&type=cs Bye, bearophile
Jul 14 2011
On Thu, 30 Jun 2011 07:11:44 +0200, scarrow <shawn.baird gmail.com> wrote:Hey all, I'd like to embed hashed strings into my code. The C++ version of this engine ran an external tool to preprocess the files. In D my strongly pure function is only evaluated if I assign it to something like an enum or invoke it from a template. So the following generate compile time hashes: enum blort = Hash("foo"); f(CHash!("foo")); Annoyingly, however, I can't do the following at compile time: f(Hash("foo")); I'm not sure what the point is in distinguishing between these two cases. If it is a properly pure function there should be no harm in doing a compile time evaluation.Actually, there might. Pure functions are allowed to depend upon the immutable global variables, whose values may be calculated at startup (see static this) -- Simen
Jun 30 2011