September 12, 2008
Hi i was messing around in D2 and noticed that the following always is saying that it is only at runtime even when the input is a constant... was wondering if there was a right way to do this.

import std.stdio;

void main(char[][] args)
{

	writefln("test");
	auto ct = test(cast(char[])"123");
	auto rt = test(args[0]);
	writefln(ct);
	writefln(rt);

}

pure char[] test(char[] src)
{
//	foo!(src);
	static if(__traits(compiles,foo!(src)/*check for something only available at compile time...*/))
	{
		return ((cast(char[])"argument available at compiletime of '")~src~cast(char[])"'");
	}
	else
	{
		return (cast(char[])"argument available at runtime of '")~src~(cast(char[])"'");
	}
}

pure template foo(char[] src)
{
	const uint foo = src.length;
}
September 12, 2008
bmeck wrote:
> Hi i was messing around in D2 and noticed that the following always is saying that it is only at runtime even when the input is a constant... was wondering if there was a right way to do this.

CTFE only kicks in when the function is called in a context which requires a compile-time constant, such as passing the return value from the function as the parameter to a template.

If you don't use the function in that context, then CTFE is *not* active.  Thus, your test() function is *not* compile-time evaluated.

The basic reason for this is that if you write a long-running scientific program with fixed inputs you don't want CTFE to kick in just because the inputs are hard-coded.
September 12, 2008
well any suggestion on how to determine if a parameter is constant at run time? that is my goal overall... right now it seems casting to invariant ruins anything I can come up with.
September 12, 2008
bmeck:

> well any suggestion on how to determine if a parameter is constant at run time?

How do you plan to use such information once you have it?

Bye,
bearophile
September 12, 2008
bmeck <bmeck@stedwards.edu> wrote:
> well any suggestion on how to determine if a parameter is constant at run time? that is my goal overall... right now it seems casting to invariant ruins anything I can come up with.

I cannot quite understand what are you trying to achieve here.  This is my solution if I got you right:

---
import std.stdio;

void main(string[] args)
{

	writefln("test");

	static if (__traits(compiles, CompileTime!("123")))
		writeln("123 compile");
	else
		writeln("123 run");

	static if (__traits(compiles, CompileTime!(args[0])))
		writeln("args[0] compile");
	else
		writeln("args[0] run");

}

template CompileTime(alias Expr)
{
}
---
September 12, 2008
I just get both at run time with your example. I was hoping to encapsulate it somehow so you could just have:

import std.stdio;

void main(string[] args)
{

        writefln("test");

        static if (CompileTimeAvailable!("123"))
                writeln("123 compile");
        else
                writeln("123 run");

        static if (CompileTimeAvailable!(args[0]))
                writeln("args[0] compile");
        else
                writeln("args[0] run");

}
template CompileTimeAvailable(alias expr)
{
    static if(__traits(compiles, CompileTime!(expr)))
        CompileTimeAvailable = false;
    else
        CompileTimeAvailable = false;
}
template CompileTime(alias Expr)
{
   auto CompileTime = Expr;//Need this to force it to check for CTFE
}

unfortunately args[0] is not constant so no go...
September 12, 2008
Well if it is available at CTFE I want to hash out as much as possible calculations and store the result, if its not, dont mess with the data and send it to a functions that does the same calculations and stores the result at run time but in a different manner, namely allowing pointers heap etc.

IE: if args = ["\w+$"] // gets last word

auto reg1 = Regex("\w+$"); // woot got enough to make the struct at Compile time , use structs as needed and hard code that sucker!
auto reg2 = Regex(args[0]); // uh oh, dont know at compile time, leave it to a run time call and use pointers and heap as needed!

September 12, 2008
bmeck <bmeck@stedwards.edu> wrote:
> I just get both at run time with your example.

Again I cannot understand what you are trying to say.  Does my example prints wrong results?  I'm using DMD 2.019 and get the following:

>dmd -run test.d
test
123 compile
args[0] run

so it says that "123" is available at run time, args[0] is not.  As expected.

> I was hoping to encapsulate it somehow so you could just have:
> 
> import std.stdio;
> 
> void main(string[] args)
> {
> 
>         writefln("test");
> 
>         static if (CompileTimeAvailable!("123"))
>                 writeln("123 compile");
>         else
>                 writeln("123 run");
> 
>         static if (CompileTimeAvailable!(args[0]))
>                 writeln("args[0] compile");
>         else
>                 writeln("args[0] run");
> 
> }
> template CompileTimeAvailable(alias expr)
> {
>     static if(__traits(compiles, CompileTime!(expr)))
>         CompileTimeAvailable = false;
>     else
>         CompileTimeAvailable = false;
> }
> template CompileTime(alias Expr)
> {
>    auto CompileTime = Expr;//Need this to force it to check for CTFE
> }
> 
> unfortunately args[0] is not constant so no go...

Are you sure you've posted the right example?  I can see no attempts at encapsulation.  Maybe you wanted

> void main(string[] args)
> {
> 	writeln("123 at compile time: ", CompileTimeAvailable!("123"));
> 	writeln("args[0] at compile time: ", CompileTimeAvailable!(args[0]));
> }
September 12, 2008
bmeck <bmeck@stedwards.edu> wrote:
> Well if it is available at CTFE I want to hash out as much as possible calculations and store the result, if its not, dont mess with the data and send it to a functions that does the same calculations and stores the result at run time but in a different manner, namely allowing pointers heap etc.

Got it.
This is the best I could come up with to the moment, but it works:

---
import std.stdio;

void main(string[] args)
{
	mixin CtfeIfPossible!( q{auto r1 =} , q{foo("test")} );
	mixin CtfeIfPossible!( q{auto r2 =} , q{foo(args[0])} );

	writeln(r1);
	writeln(r2);
}

string foo(string s)
{
	return s ~ "-modified";
}

template CompileTime(alias Expr)
{
	enum CompileTime = Expr;
}

template CtfeIfPossible(string Decl, string Expr)
{
	static if (__traits(compiles, CompileTime!(mixin(Expr))))
	{
		pragma(msg, "compile time ", Expr);
		mixin(Decl ~ "CompileTime!(" ~ Expr ~ ");");
	}
	else
	{
		pragma(msg, "runtime ", Expr);
		mixin(Decl ~ Expr ~ ";");
	}
}
---

It prints:

>dmd -run "test.d"
compile time foo("test")
runtime foo(args[0])
test-modified
C:\tmp\test.exe-modified
September 14, 2008
bmeck wrote:
> well any suggestion on how to determine if a parameter is constant at run time? that is my goal overall... right now it seems casting to invariant ruins anything I can come up with.

Remember that when a function is not run through CTFE, then it doesn't really know anything about the arguments that it is passed.  It could be called several times, sometimes with compile-time-constant args, and sometimes without.

In order to tell the difference, you have to take on the responsibility to specialize the function yourself.  One option is to make the function a template, and then pass the compile-time-constant arguments as template parameters:

	void myFunc(int CompileTime1, char[] CompileTime2)
	           (int runtime)

...but that only works if you know that the same args will be compile time args.
« First   ‹ Prev
1 2
Top | Discussion index | About this forum | D home