www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - CTFE determination?

reply bmeck <bmeck stedwards.edu> writes:
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;
}
Sep 11 2008
parent reply Russell Lewis <webmaster villagersonline.com> writes:
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.
Sep 12 2008
parent reply bmeck <bmeck stedwards.edu> writes:
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.
Sep 12 2008
next sibling parent reply bearophile <bearophileHUGS lycos.com> writes:
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
Sep 12 2008
parent reply bmeck <bmeck stedwards.edu> writes:
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!
Sep 12 2008
parent Sergey Gromov <snake.scaly gmail.com> writes:
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"

runtime foo(args[0]) test-modified C:\tmp\test.exe-modified
Sep 12 2008
prev sibling next sibling parent reply Sergey Gromov <snake.scaly gmail.com> writes:
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) { } ---
Sep 12 2008
parent reply bmeck <bmeck stedwards.edu> writes:
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...
Sep 12 2008
parent Sergey Gromov <snake.scaly gmail.com> writes:
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

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]));
 }

Sep 12 2008
prev sibling parent reply Russell Lewis <webmaster villagersonline.com> writes:
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.
Sep 14 2008
parent reply bmeck <bmeck stedwards.edu> writes:
That might be the case that you have to specify programmaticly right now but I
still think it would be useful if there was a way to determine this since
somethings could be automated, making it easier for programmers and on large
calculations this could speed things up significantly if being used with mixins
to optimize structures.
Sep 14 2008
parent reply Russell Lewis <webmaster villagersonline.com> writes:
bmeck wrote:
 That might be the case that you have to specify programmaticly right now but I
still think it would be useful if there was a way to determine this since
somethings could be automated, making it easier for programmers and on large
calculations this could speed things up significantly if being used with mixins
to optimize structures.

You'll get no argument from me there. I'm a big fan of static analysis, although IMHO it would make more sense in a separate tool, rather than the compiler. Also, in any static analysis, you have to answer the (difficult) question of: "Is this analysis worth the cost? Would it be faster to just compile and run it?" That's always a hard one, and as a general rule, it's unanswerable...by the time that you are certain which path would be faster, you have already paid the cost of analysis. :( It's a thing worth considering, though.
Sep 15 2008
parent bmeck <bmeck stedwards.edu> writes:
Im not arguing that we should enforce this, just allow a static if and for some
things like gui driven programs that may use Regex a lot or physics
applications where large math problems can occur in somewhat repetitive order
it would make things a bit easier to manage if I could tell the compiler if you
have this at compile time, do it. I don't see why repetitive hard coded values
would be a problem, but as you said the price of analysis is a problem at many
times especially when you could be using pointers and your ctfe gets thrown
away almost immediately. The current state of the compiler has no option for
this static analysis but I do believe it should give the opportunity to have a
tool built onto it (D's CTFE is plenty if you could get a static if working to
see if params are available at compiletime) for such a thing. I hate the use of
multiple programs since you almost always end up writing a script to combine
them anyway, just give the thing an external API and good riddance :P.
Sep 15 2008