Another way to do CTFE

Ary Borenszweig via Digitalmars-d digitalmars-d at puremagic.com
Tue Jun 17 12:41:58 PDT 2014


CTFE is really nice but has its limitations: you can't do anything you 
want, and since it's interpreted it requires an interpreter and it's 
generally slow. Nimrod does the same thing, and now they are 
implementing a VM to run the interpreted code faster. Is this really the 
way to go?

In our language we are thinking about allowing code generation at 
compile time but in a different way. The idea is, at compile time, to 
compile and execute another program that would generate the code that 
would be mixed into the current program. This program could receive the 
execution context as arguments, along with any AST nodes that are passed 
to the program.

So right now in D you can do ctRegex:

auto ctr = ctRegex!(`^.*/([^/]+)/?$`);

I don't know what the syntax could be, but the idea is to have a file 
ct_regex.d. This file would receive the string as an argument and must 
generate the code that would be mixed in the program. Since this program 
is a program (compiled and executed), it has no limits on what it can 
do. Then you would do something like this:

mixin(compile_time_execute("ct_regex.d", `^.*/([^/]+)/?$`));

The compiler could be smart and cache the executable so that anytime it 
has to expand it it just needs to invoke it (skip the compile phase).

What do you think?

I know, I know. The first answer I'll get is: "Oh, no! But that way I 
could download a program, compile it and suddenly all my files are 
gone". My reply is: If you downloaded and compiled that program, weren't 
you going to execute it afterwards? At that point the program could do 
something harmful, so what's the difference?. You must either way check 
the source code to see that something fishy isn't happening there.

Just as a reference that something like this is possible, in our 
language you can already do this:

build_date = {{ system("date").stringify }}
puts build_date

That generates a program that has the build date embedded in it. We can 
also get the git hash of a repo and stick it into the executable without 
an additional Makefile or some build process. "system" is our first step 
towards doing this compile-time things. The next thing would be do do:

ct_regex = {{ run("ct_regex", "^.*/([^/]+)/?$") }}


More information about the Digitalmars-d mailing list