www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Is it possible to force CTFE?

reply "Tommi" <tommitissari hotmail.com> writes:
Three related questions:

1) Is there a way to force a function to be always executed at 
compile time (when it's possible to do so) no matter what context 
it's called in?

2) Is it possible to specialize a function based on whether or 
not the parameter that was passed in is a compile time constant?

3) Does any D compiler currently optimize out a conditional 
branch which _can_ be evaluated at compile time (but which isn't 
forced into CTFE)? Like:

int getValue(bool b)
{
     return b ? 123 : 456;
}

//...
    auto value = getValue(true);
Jun 10 2012
next sibling parent "jerro" <a a.com> writes:
 1) Is there a way to force a function to be always executed at 
 compile time (when it's possible to do so) no matter what 
 context it's called in?

No, but you could wrap it in a template to force it to always execute at compile time. Of course it could then only be called at compile time.
 2) Is it possible to specialize a function based on whether or 
 not the parameter that was passed in is a compile time constant?

No.
 3) Does any D compiler currently optimize out a conditional 
 branch which _can_ be evaluated at compile time (but which 
 isn't forced into CTFE)? Like:

 int getValue(bool b)
 {
     return b ? 123 : 456;
 }

 //...
    auto value = getValue(true);

DMD, LDC and GDC all do this when compiling with optimizations turned on. They all compile these functions to exactly the same code: auto foo() { return getValue(true); } auto bar() { return 123; }
Jun 10 2012
prev sibling next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 06/10/2012 09:04 AM, Tommi wrote:
 Three related questions:

 1) Is there a way to force a function to be always executed at compile
 time (when it's possible to do so) no matter what context it's called in?

No there is not. You could use a template that calls a private function at compile time instead. What is your use case?
 2) Is it possible to specialize a function based on whether or not the
 parameter that was passed in is a compile time constant?

This has been discussed before, but there is not. 1-2) could be introduced later when D gets AST macros.
 3) Does any D compiler currently optimize out a conditional branch which
 _can_ be evaluated at compile time (but which isn't forced into CTFE)?
 Like:

 int getValue(bool b)
 {
      return b ? 123 : 456;
 }

 //...
     auto value = getValue(true);

Yes, DMD/GDC/LDC should be able to do this to different extents.
Jun 10 2012
prev sibling next sibling parent "Tommi" <tommitissari hotmail.com> writes:
On Sunday, 10 June 2012 at 10:23:09 UTC, Timon Gehr wrote:
 No there is not. You could use a template that calls a private 
 function at compile time instead. What is your use case?

I was just thinking about a situation where a property accessor/mutator methods are not as simple as read/assign value, such as in this silly example: struct Flipping123 { private int m_number = 123; property bool isPositive() { return m_number >= 0; } property void isPositive(bool b) { m_number = b ? 123 : -123; } } //... Flipping123 fl; fl.isPositive = false; // I'd rather not have cond. branching in release mode
Jun 10 2012
prev sibling next sibling parent "Tommi" <tommitissari hotmail.com> writes:
On Sunday, 10 June 2012 at 10:16:23 UTC, jerro wrote:
 No, but you could wrap it in a template to force it to always
 execute at compile time.

So, I just realized, I could have just this one convenience template that I can use whenever I want to force an expression to be evaluated at compile-time. Like so: template ct(alias expr) { enum ct = expr; } int fun(int a, int b) { return a + b; } //... and use it like: ct!(fun(1, 2)) That's not *too* inconvenient. Although, best would be a function attribute that would force the compiler to apply ctfe aggressively whenever it can with calls to that function.
Sep 27 2012
prev sibling next sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Tommi:

 2) Is it possible to specialize a function based on whether or 
 not the parameter that was passed in is a compile time constant?

I am interested in this since some years. I think it's useful, but I don't know if it can be implemented. I don't remember people discussing about this much. Bye, bearophile
Sep 27 2012
next sibling parent Jacob Carlborg <doob me.com> writes:
On 2012-09-27 15:01, bearophile wrote:
 Tommi:

 2) Is it possible to specialize a function based on whether or not the
 parameter that was passed in is a compile time constant?

I am interested in this since some years. I think it's useful, but I don't know if it can be implemented. I don't remember people discussing about this much.

There's the if (__ctfe) hack. Also using only template parameters will force the function to be CTFE. -- /Jacob Carlborg
Sep 27 2012
prev sibling parent Don Clugston <dac nospam.com> writes:
On 27/09/12 15:01, bearophile wrote:
 Tommi:

 2) Is it possible to specialize a function based on whether or not the
 parameter that was passed in is a compile time constant?

I am interested in this since some years. I think it's useful, but I don't know if it can be implemented. I don't remember people discussing about this much. Bye, bearophile

It has been discussed very often, especially around the time that CTFE was first introduced. We never came up with a solution.
Oct 01 2012
prev sibling next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
Jacob Carlborg:

 I am interested in this since some years. I think it's useful, 
 but I don't know if it can be implemented. I don't remember
 people discussing about this much.

There's the if (__ctfe) hack. Also using only template parameters will force the function to be CTFE.

This is quite far from what I was discussing about here... Bye, bearophile
Sep 27 2012
prev sibling next sibling parent "Tommi" <tommitissari hotmail.com> writes:
One use case I can think of for specializing functions based on 
whether or not its arguments are compile-time evaluable:

// Big container that can't be accessed in constant time:
immutable cachedResults = init();

double getResult(<args>)
     if (areCompileTimeConstants!(<args>) == false)
{
     return cachedResults.at(<args>);
}

double getResult(<args>)
     if (areCompileTimeConstants!(<args>) == true)
{
     // Computing the result takes long time
     ...
     return computedResult;
}

Point being that A) cachedResults takes so much memory we don't 
want to evaluate it at compile-time and bloat the executable, and 
B) accessing cachedResults takes some non-trivial time, so we 
don't want to do that at runtime if it can be done at 
compile-time. Don't know how common this kind of thing would be 
though.


But, that made me think...
In a perfect world, I think, the compiler would always evaluate 
all possible functions at compile-time, given that doing so would 
produce a smaller (or equal size) executable than what 
not-evaluating-at-compile-time would produce. For example 
(assuming the following initialization functions are compile-time 
evaluable):

// The following wouldn't be evaluated at compile time,
// because that function call (probably) wouldn't take
// as much space in the executable as million ints:

int[1_000_000] bigArray = initBigArray();

// The following would be always evaluated at compile time,
// because a single int value would take less space in the
// executable than the function call:

int myValue = initMyValue();

Although, to speed up test compilations, we'd need a compiler 
flag to disable this "aggressive" CTFE behaviour.
Sep 28 2012
prev sibling parent "Tommi" <tommitissari hotmail.com> writes:
On Friday, 28 September 2012 at 17:52:55 UTC, Tommi wrote:
 In a perfect world, I think, the compiler would always evaluate 
 all possible functions at compile-time, given that doing so 
 would produce a smaller (or equal size) executable than what 
 not-evaluating-at-compile-time would produce.

Or, a simpler rule (for both the compiler and the coder): Have a compiler flag where you set a value (in bytes), and if a function returns a type that's size is not larger than the set value, the compiler would execute all calls to that function at compile-time (if possible).
Sep 28 2012