Jump to page: 1 2
Thread overview
CTFE question
Aug 28, 2012
Danny Arends
Aug 28, 2012
Chris Cain
Aug 28, 2012
Danny Arends
Aug 28, 2012
Chris Cain
Aug 28, 2012
Danny Arends
Aug 28, 2012
bearophile
Aug 28, 2012
Philippe Sigaud
Sep 03, 2012
Don Clugston
Sep 03, 2012
Philippe Sigaud
Sep 03, 2012
bearophile
Sep 03, 2012
Philippe Sigaud
August 28, 2012
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
August 28, 2012
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").
August 28, 2012
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").


August 28, 2012
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.
August 28, 2012
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
August 28, 2012
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
August 28, 2012
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.
September 03, 2012
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?
September 03, 2012
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?
September 03, 2012
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
« First   ‹ Prev
1 2