Execute compile time-compiled regex at compile time

334 views Asked by At

I get a compile error when I try to compile this code:

import std.regex;
enum truth = "baba".matchFirst(ctRegex!`[ab]+$`) ? true : false;
void main() {}

/usr/local/Cellar/dmd/2.067.1/include/d2/std/regex/package.d(671): Error: malloc cannot be interpreted at compile time, because it has no available source code

How to get around this?

1

There are 1 answers

0
Adam D. Ruppe On BEST ANSWER

You can't, the regex can be compiled at compile time, but not run. You'll have to write the match some other way, maybe a combination of indexOf or other simpler functions. (The reason isn't because regex is too complicated, it is actually because it internally calls malloc for efficiency, which is not supported at compile time since it is an external C function.)

Understanding ctRegex needs some explanation Phobos' regular expression engine. It works in two steps: given a regular expression, it first compiles that into some bytecode, then to match it on a string, it runs that code.

In the ordinary regex, both those steps happen at runtime. When you construct the regex object, it compiles it into the bytecode. Then, when you match on a string, it runs that code.

With ctRegex, the first part happens at compile time, but the second part still happens at runtime. So it compiles the regex into bytecode when the D is compiled... then shoves that bytecode through the rest of the D compiler to be optimized to fully native code. So that's the benefit it can offer. (BTW the difference often doesn't really matter, you should benchmark for your input strings to see which one is better.)

Normally, CTFE (compile-time function evaluation) means runtime code can be run at compile time too, but only if the source is available. That's not the case for malloc which is why the error says that.


So the answer will depend on just what your regex is. You'll probably want to simplify it and rewrite it in terms of other string and/or std.algorithm functions.

...or rewrite the std.regex source code to get rid of those malloc calls. Replace them with new and if(_ctfe) to start. I've tried doing this before though, and unless the code has been refactored since then, you'll just hit another problem: for runtime performance, std.regex also uses things like unions, which also aren't supported in ctfe... you'd have to rewrite a bunch of it and be careful not to compromise the runtime performance in the process.

Probably easier to just handle your specific case with other functions.