www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - CTFE question

reply "Danny Arends" <Danny.Arends gmail.com> writes:
I have the following code:

------------------------------------

import std.stdio;
import std.metastrings;

pure int[] testCTFE(){
   int[] r;
   pragma(msg, "Testing CTFE");
   foreach(i; 0 .. 360){
     r ~= i;
     pragma(msg, Format!("Loop: %d",i));
   }
   pragma(msg, "Done CTFE test");
   return r;
}

immutable CTFEdata = testCTFE();

void main(string[] args){ }

----------------------------------

I expected this would compile and during compilation print:
Loop: 1 Loop:2, etc
However, I get a compilation error:

ctfe.d(9): Error: variable i cannot be read at compile time

Is this a bug or am I doing something wrong ??

Danny Arends
http://www.dannyarends.nl
Aug 28 2012
parent reply "Chris Cain" <clcain uncg.edu> writes:
On Tuesday, 28 August 2012 at 11:13:40 UTC, Danny Arends wrote:
 Is this a bug or am I doing something wrong ??

 Danny Arends
 http://www.dannyarends.nl
You're doing something wrong, but I can see why the error message would confuse you. Your problem is using those pragma(msg, ...) lines... They produce a message while something is being compiled, right? The CTFE function is ran _after_ it has been compiled. Hence i can't be read while the CTFE function is compiled. So, to be clear, doing this: ----- import std.stdio; import std.metastrings; pure int[] testCTFE(){ int[] r; pragma(msg, "Testing CTFE"); foreach(i; 0 .. 360){ r ~= i; //pragma(msg, Format!("Loop: %d",i)); } pragma(msg, "Done CTFE test"); return r; } immutable CTFEdata = testCTFE(); immutable CTFEdata2 = testCTFE(); void main(string[] args){ } ---- Produces just one output: Testing CTFE Done CTFE test Because the pragmas are done _as it's compiled_, not as it's ran (even though CTFE is done "at compile time").
Aug 28 2012
parent reply "Danny Arends" <Danny.Arends gmail.com> writes:
Ahhh I understand...

As a follow up, is it then possible to 'track' filling a
large enum / immutable on compile time by outputting a msg
every for ?

I'm generating rotation matrices for yaw, pitch and roll
at compile time which can take a long time depending on
how fine grained I create them.

Gr,
Danny Arends
http://www.dannyarends.nl

On Tuesday, 28 August 2012 at 11:29:32 UTC, Chris Cain wrote:
 On Tuesday, 28 August 2012 at 11:13:40 UTC, Danny Arends wrote:
 Is this a bug or am I doing something wrong ??

 Danny Arends
 http://www.dannyarends.nl
You're doing something wrong, but I can see why the error message would confuse you. Your problem is using those pragma(msg, ...) lines... They produce a message while something is being compiled, right? The CTFE function is ran _after_ it has been compiled. Hence i can't be read while the CTFE function is compiled. So, to be clear, doing this: ----- import std.stdio; import std.metastrings; pure int[] testCTFE(){ int[] r; pragma(msg, "Testing CTFE"); foreach(i; 0 .. 360){ r ~= i; //pragma(msg, Format!("Loop: %d",i)); } pragma(msg, "Done CTFE test"); return r; } immutable CTFEdata = testCTFE(); immutable CTFEdata2 = testCTFE(); void main(string[] args){ } ---- Produces just one output: Testing CTFE Done CTFE test Because the pragmas are done _as it's compiled_, not as it's ran (even though CTFE is done "at compile time").
Aug 28 2012
parent reply "Chris Cain" <clcain uncg.edu> writes:
On Tuesday, 28 August 2012 at 11:39:20 UTC, Danny Arends wrote:
 Ahhh I understand...

 As a follow up, is it then possible to 'track' filling a
 large enum / immutable on compile time by outputting a msg
 every for ?

 I'm generating rotation matrices for yaw, pitch and roll
 at compile time which can take a long time depending on
 how fine grained I create them.
I'm pretty sure there isn't. However, if you're just trying to develop/test your algorithm, you could write a program that runs it as a normal function (and just use writeln) as you develop it. After it's done, you remove the writelns, mark the function as pure and it should work exactly the same in CTFE.
Aug 28 2012
next sibling parent reply "Danny Arends" <Danny.Arends gmail.com> writes:
On Tuesday, 28 August 2012 at 12:07:07 UTC, Chris Cain wrote:
 On Tuesday, 28 August 2012 at 11:39:20 UTC, Danny Arends wrote:
 I'm pretty sure there isn't. However, if you're just trying to 
 develop/test your algorithm, you could write a program that 
 runs it as a normal function (and just use writeln) as you 
 develop it. After it's done, you remove the writelns, mark the 
 function as pure and it should work exactly the same in CTFE.
Well it just seems some compilation runs take way longer (and more memory) then others..Googling I found that I just got to wait for: https://github.com/D-Programming-Language/dmd/pull/692 to be accepted. Seems a bit strange that a discussion about yes/no newline is keeping this from getting into DMD. Just basic ctfewrite support would help me a lot. Gr, Danny Arends
Aug 28 2012
parent "bearophile" <bearophileHUGS lycos.com> writes:
Danny Arends:

 Seems a bit strange that a discussion about yes/no
 newline is keeping this from getting into DMD.
The ending newline is bad, because it unnecessarily kills some use cases for this feature. But I think the newline is not what is keeping it out of DMD. It's just there are about a hundred open patches, and Walter is currently implementing 64bits on Windows. Bye, bearophile
Aug 28 2012
prev sibling parent reply Philippe Sigaud <philippe.sigaud gmail.com> writes:
On Tue, Aug 28, 2012 at 2:07 PM, Chris Cain <clcain uncg.edu> wrote:
 On Tuesday, 28 August 2012 at 11:39:20 UTC, Danny Arends wrote:
 Ahhh I understand...

 As a follow up, is it then possible to 'track' filling a
 large enum / immutable on compile time by outputting a msg
 every for ?

 I'm generating rotation matrices for yaw, pitch and roll
 at compile time which can take a long time depending on
 how fine grained I create them.
I'm pretty sure there isn't. However, if you're just trying to develop/test your algorithm, you could write a program that runs it as a normal function (and just use writeln) as you develop it. After it's done, you remove the writelns, mark the function as pure and it should work exactly the same in CTFE.
Godd adivce, except beware of using ++ and --, they don't work at compile-time. I'm regularly caught unaware by this, particularly while looping. Danny is also using 0..360, which is a runtime value. There exists a compile-time version of foreach which is automatically invoked whenever you use foreach on a compile-time 'range' (aka, typetuple) So: template Loop(T...) { /* some code */ foreach(i,Type; T) pragma(msg, i); } will work. So, a way to get what the OP wanted is to create a tuple of the required length. Since integers are valid template arguments, we can use them directly like this: template staticRange(uint upto) { static if (upto == 0) alias TypeTuple!() staticRange; else alias TypeTuple!(staticRange!(upto-1), upto-1) staticRange; } So staticRange!3 is the tuple 0,1,2. (staticRange!0 is empty) You can foreach on it: pure int[] testCTFE(){ int[] r; pragma(msg, "Testing CTFE"); foreach(i; staticRange!360){ r ~= i; pragma(msg, i); } pragma(msg, "Done CTFE test"); return r; } Of course, that means knowing the upper value at compile-time.
Aug 28 2012
parent reply Don Clugston <dac nospam.com> writes:
On 28/08/12 19:40, Philippe Sigaud wrote:
 On Tue, Aug 28, 2012 at 2:07 PM, Chris Cain <clcain uncg.edu> wrote:
 On Tuesday, 28 August 2012 at 11:39:20 UTC, Danny Arends wrote:
 Ahhh I understand...

 As a follow up, is it then possible to 'track' filling a
 large enum / immutable on compile time by outputting a msg
 every for ?

 I'm generating rotation matrices for yaw, pitch and roll
 at compile time which can take a long time depending on
 how fine grained I create them.
I'm pretty sure there isn't. However, if you're just trying to develop/test your algorithm, you could write a program that runs it as a normal function (and just use writeln) as you develop it. After it's done, you remove the writelns, mark the function as pure and it should work exactly the same in CTFE.
Godd adivce, except beware of using ++ and --, they don't work at compile-time. I'm regularly caught unaware by this, particularly while looping.
Really? That's scary. Is there a bug report for this?
Sep 03 2012
parent reply Philippe Sigaud <philippe.sigaud gmail.com> writes:
On Mon, Sep 3, 2012 at 1:27 PM, Don Clugston <dac nospam.com> wrote:


 Godd adivce, except beware of using ++ and --, they don't work at
 compile-time. I'm regularly caught unaware by this, particularly while
 looping.
Really? That's scary. Is there a bug report for this?
I re-tried this and I was mistaken: it's not ++ or --, it's changing an iteration index at compile-time. My bad. int[] indices(string s) { int[] store; foreach(i,ch; s[0..$-1]) { store ~= i; if (s[i..i+2] == "aa") i += 1; // also ++i or i++, no difference here } return store; } void main() { enum result1 = indices("aaabc"); auto result2 = indices("aaabc"); writeln(result1); // [0,1,2,3] writeln(result2); // [0,2,3] } I know changing 'i' while iterating is not a good idea, but at least in this case, CT-executed and RT-execution give a different result. All my other tests with ++ and -- give correct results, sorry for the bad publicity. Worth a bug report?
Sep 03 2012
parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Philippe Sigaud:

 Worth a bug report?
Yeah. CTFE must give the same results when CTFE works. A simpler test case for Bugzilla: import std.stdio; int[] foo(int[] data) { foreach (i, ref x; data) { x++; i++; } return data; } void main() { enum result1 = foo([10, 20, 30, 40]); auto result2 = foo([10, 20, 30, 40]); writeln(result1); // [11, 21, 31, 41] writeln(result2); // [11, 20, 31, 40] } Bye, bearophile
Sep 03 2012
parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
On Mon, Sep 3, 2012 at 4:08 PM, bearophile <bearophileHUGS lycos.com> wrote:

 Worth a bug report?
Yeah. CTFE must give the same results when CTFE works.
http://d.puremagic.com/issues/show_bug.cgi?id=8614
Sep 03 2012