Thread overview
String Mixins & Compile Time Evaluation
Nov 17, 2009
Travis Boucher
Nov 17, 2009
Don
Nov 17, 2009
Travis Boucher
Nov 17, 2009
Bill Baxter
Nov 17, 2009
Bill Baxter
Nov 17, 2009
Don
Nov 17, 2009
Bill Baxter
Nov 17, 2009
Don
Nov 28, 2009
Kuba Ober
November 17, 2009
I've been playing with string mixins, and they are very powerful.

One thing I can't figure out is what exactly can and cannot be evaluated at compile time.

For example:

----
char[] myFunc1() {
    return "int a = 1;";
}

char[] myFunc2() {
    char[] myFunc3() {
        return "int b = 2;";
    }
    return myFunc3();
}

void main() {
    mixin(myFunc1());
    mixin(myFunc2());
}
----

myFunc1() can be used as a string mixin.
myFunc2() can't be.

Another (slightly more complex) example is using an ExpressionTuple.

----
template DataGenerator(T, M...) {
	char[] data() {
		char[] rv;
		foreach (m; M) rv ~= T.stringof ~ " " ~ m ~ ";";
		return rv;
	}
}

alias DataGenerator!(int, "r", "g", "b") ColorRGBgen;

writefln(ColorRGBgen.data()); // int R; int G; int B;

struct Color {
	mixin(ColorRGBgen.data()); // Can't evaluate at compile time
}
----


I'm sure there are other things that I'll run into, but I figure there is some simple set of rules of what can and can't be used as a string mixin and other compile time evaluations.
November 17, 2009
Travis Boucher wrote:
> I've been playing with string mixins, and they are very powerful.
> 
> One thing I can't figure out is what exactly can and cannot be evaluated at compile time.
> 
> For example:
> 
> ----
> char[] myFunc1() {
>     return "int a = 1;";
> }
> 
> char[] myFunc2() {
>     char[] myFunc3() {
>         return "int b = 2;";
>     }
>     return myFunc3();
> }
> 
> void main() {
>     mixin(myFunc1());
>     mixin(myFunc2());
> }
> ----
> 
> myFunc1() can be used as a string mixin.
> myFunc2() can't be.

I think you're using an old version of DMD. It's been working since DMD1.047. Please upgrade to the latest version, you'll find it a lot less frustrating.
The bottom of "function.html" in the spec gives the rules.
Though it says nested functions aren't supported, but they are.
November 17, 2009
Don wrote:
> Travis Boucher wrote:
>> I've been playing with string mixins, and they are very powerful.
>>
>> One thing I can't figure out is what exactly can and cannot be evaluated at compile time.
>>
>> For example:
>>
>> ----
>> char[] myFunc1() {
>>     return "int a = 1;";
>> }
>>
>> char[] myFunc2() {
>>     char[] myFunc3() {
>>         return "int b = 2;";
>>     }
>>     return myFunc3();
>> }
>>
>> void main() {
>>     mixin(myFunc1());
>>     mixin(myFunc2());
>> }
>> ----
>>
>> myFunc1() can be used as a string mixin.
>> myFunc2() can't be.
> 
> I think you're using an old version of DMD. It's been working since DMD1.047. Please upgrade to the latest version, you'll find it a lot less frustrating.
> The bottom of "function.html" in the spec gives the rules.
> Though it says nested functions aren't supported, but they are.

Yeah, I am running 1.020 with gdc (freebsd default for gdc package).  I found a few work arounds, just trying to see what can be done.

For now I'll take it as a work in progress and once I start doing anything real with it I'll upgrade to the latest version of dmd.

Thanks,
Travis Boucher
November 17, 2009
On Tue, Nov 17, 2009 at 2:07 AM, Don <nospam@nospam.com> wrote:
> Travis Boucher wrote:
>>
>> I've been playing with string mixins, and they are very powerful.
>>
>> One thing I can't figure out is what exactly can and cannot be evaluated at compile time.
>>
>> For example:
>>
>> ----
>> char[] myFunc1() {
>>    return "int a = 1;";
>> }
>>
>> char[] myFunc2() {
>>    char[] myFunc3() {
>>        return "int b = 2;";
>>    }
>>    return myFunc3();
>> }
>>
>> void main() {
>>    mixin(myFunc1());
>>    mixin(myFunc2());
>> }
>> ----
>>
>> myFunc1() can be used as a string mixin.
>> myFunc2() can't be.
>
> I think you're using an old version of DMD. It's been working since
> DMD1.047. Please upgrade to the latest version, you'll find it a lot less
> frustrating.
> The bottom of "function.html" in the spec gives the rules.
> Though it says nested functions aren't supported, but they are.

Ah, forgot about that list.  Good point.
But still Travis should know that the list is not exhaustive.
For instance the other day I found that this didn't work for some reason:

   while(i < a - b) { ... }

Instead I had to do

   int limit = a-b;
   while(i < limit) { ... }

--bb
November 17, 2009
On Mon, Nov 16, 2009 at 8:25 PM, Travis Boucher <boucher.travis@gmail.com> wrote:
> Don wrote:
>>
>> Travis Boucher wrote:
>>>
>>> I've been playing with string mixins, and they are very powerful.
>>>
>>> One thing I can't figure out is what exactly can and cannot be evaluated at compile time.
>>>
>>> For example:
>>>
>>> ----
>>> char[] myFunc1() {
>>>    return "int a = 1;";
>>> }
>>>
>>> char[] myFunc2() {
>>>    char[] myFunc3() {
>>>        return "int b = 2;";
>>>    }
>>>    return myFunc3();
>>> }
>>>
>>> void main() {
>>>    mixin(myFunc1());
>>>    mixin(myFunc2());
>>> }
>>> ----
>>>
>>> myFunc1() can be used as a string mixin.
>>> myFunc2() can't be.
>>
>> I think you're using an old version of DMD. It's been working since
>> DMD1.047. Please upgrade to the latest version, you'll find it a lot less
>> frustrating.
>> The bottom of "function.html" in the spec gives the rules.
>> Though it says nested functions aren't supported, but they are.
>
> Yeah, I am running 1.020 with gdc (freebsd default for gdc package).  I found a few work arounds, just trying to see what can be done.

Ohhhh, well yeh, Don's been smashing CTFE bugs like crazy lately.  I think the version you're using doesn't even have the useful error message fix that tells you what can't be CTFE'd.

So definitely upgrade before you try to do anything serious with CTFE.

--bb
November 17, 2009
Bill Baxter wrote:
> On Tue, Nov 17, 2009 at 2:07 AM, Don <nospam@nospam.com> wrote:
>> Travis Boucher wrote:
>>> I've been playing with string mixins, and they are very powerful.
>>>
>>> One thing I can't figure out is what exactly can and cannot be evaluated
>>> at compile time.
>>>
>>> For example:
>>>
>>> ----
>>> char[] myFunc1() {
>>>    return "int a = 1;";
>>> }
>>>
>>> char[] myFunc2() {
>>>    char[] myFunc3() {
>>>        return "int b = 2;";
>>>    }
>>>    return myFunc3();
>>> }
>>>
>>> void main() {
>>>    mixin(myFunc1());
>>>    mixin(myFunc2());
>>> }
>>> ----
>>>
>>> myFunc1() can be used as a string mixin.
>>> myFunc2() can't be.
>> I think you're using an old version of DMD. It's been working since
>> DMD1.047. Please upgrade to the latest version, you'll find it a lot less
>> frustrating.
>> The bottom of "function.html" in the spec gives the rules.
>> Though it says nested functions aren't supported, but they are.
> 
> Ah, forgot about that list.  Good point.
> But still Travis should know that the list is not exhaustive.
> For instance the other day I found that this didn't work for some reason:
> 
>    while(i < a - b) { ... }
> 
> Instead I had to do
> 
>    int limit = a-b;
>    while(i < limit) { ... }

I can't reproduce it. Do you have a complete test case?
November 17, 2009
On Tue, Nov 17, 2009 at 4:17 AM, Don <nospam@nospam.com> wrote:
> Bill Baxter wrote:
>>
>> On Tue, Nov 17, 2009 at 2:07 AM, Don <nospam@nospam.com> wrote:
>>>
>>> Travis Boucher wrote:
>>>>
>>>> I've been playing with string mixins, and they are very powerful.
>>>>
>>>> One thing I can't figure out is what exactly can and cannot be evaluated at compile time.
>>>>
>>>> For example:
>>>>
>>>> ----
>>>> char[] myFunc1() {
>>>>   return "int a = 1;";
>>>> }
>>>>
>>>> char[] myFunc2() {
>>>>   char[] myFunc3() {
>>>>       return "int b = 2;";
>>>>   }
>>>>   return myFunc3();
>>>> }
>>>>
>>>> void main() {
>>>>   mixin(myFunc1());
>>>>   mixin(myFunc2());
>>>> }
>>>> ----
>>>>
>>>> myFunc1() can be used as a string mixin.
>>>> myFunc2() can't be.
>>>
>>> I think you're using an old version of DMD. It's been working since
>>> DMD1.047. Please upgrade to the latest version, you'll find it a lot less
>>> frustrating.
>>> The bottom of "function.html" in the spec gives the rules.
>>> Though it says nested functions aren't supported, but they are.
>>
>> Ah, forgot about that list.  Good point.
>> But still Travis should know that the list is not exhaustive.
>> For instance the other day I found that this didn't work for some reason:
>>
>>   while(i < a - b) { ... }
>>
>> Instead I had to do
>>
>>   int limit = a-b;
>>   while(i < limit) { ... }
>
> I can't reproduce it. Do you have a complete test case?

Doh!  Now I can't either.  Maybe it was just a typo that I didn't notice.

How about C functions?  Any chance those'll ever work?  Particularly C stdlib functions.  They're one of the major things I'm finding prevents std.string functions from being used CTFE.

--bb
November 17, 2009
Bill Baxter wrote:
> On Tue, Nov 17, 2009 at 4:17 AM, Don <nospam@nospam.com> wrote:
>> Bill Baxter wrote:
>>> On Tue, Nov 17, 2009 at 2:07 AM, Don <nospam@nospam.com> wrote:
>>>> Travis Boucher wrote:
>>>>> I've been playing with string mixins, and they are very powerful.
>>>>>
>>>>> One thing I can't figure out is what exactly can and cannot be evaluated
>>>>> at compile time.
>>>>>
>>>>> For example:
>>>>>
>>>>> ----
>>>>> char[] myFunc1() {
>>>>>   return "int a = 1;";
>>>>> }
>>>>>
>>>>> char[] myFunc2() {
>>>>>   char[] myFunc3() {
>>>>>       return "int b = 2;";
>>>>>   }
>>>>>   return myFunc3();
>>>>> }
>>>>>
>>>>> void main() {
>>>>>   mixin(myFunc1());
>>>>>   mixin(myFunc2());
>>>>> }
>>>>> ----
>>>>>
>>>>> myFunc1() can be used as a string mixin.
>>>>> myFunc2() can't be.
>>>> I think you're using an old version of DMD. It's been working since
>>>> DMD1.047. Please upgrade to the latest version, you'll find it a lot less
>>>> frustrating.
>>>> The bottom of "function.html" in the spec gives the rules.
>>>> Though it says nested functions aren't supported, but they are.
>>> Ah, forgot about that list.  Good point.
>>> But still Travis should know that the list is not exhaustive.
>>> For instance the other day I found that this didn't work for some reason:
>>>
>>>   while(i < a - b) { ... }
>>>
>>> Instead I had to do
>>>
>>>   int limit = a-b;
>>>   while(i < limit) { ... }
>> I can't reproduce it. Do you have a complete test case?
> 
> Doh!  Now I can't either.  Maybe it was just a typo that I didn't notice.
> 
> How about C functions?  Any chance those'll ever work?  Particularly C
> stdlib functions.  They're one of the major things I'm finding
> prevents std.string functions from being used CTFE.

I don't think it could ever work. CTFE needs to have the source available.
If we really needed to, a few C stdlib functions could be made into CTFE intrinsics. But in general, no.
Some form of if(__ctfe) will happen, though.
November 28, 2009
Don wrote:
> Bill Baxter wrote:
>> On Tue, Nov 17, 2009 at 4:17 AM, Don <nospam@nospam.com> wrote:
>>> Bill Baxter wrote:
>>>> On Tue, Nov 17, 2009 at 2:07 AM, Don <nospam@nospam.com> wrote:
>>>>> Travis Boucher wrote:
>>>>>> I've been playing with string mixins, and they are very powerful.
>>>>>>
>>>>>> One thing I can't figure out is what exactly can and cannot be evaluated
>>>>>> at compile time.
>> How about C functions?  Any chance those'll ever work?  Particularly C
>> stdlib functions.  They're one of the major things I'm finding
>> prevents std.string functions from being used CTFE.
> 
> I don't think it could ever work. CTFE needs to have the source available.
> If we really needed to, a few C stdlib functions could be made into CTFE intrinsics. But in general, no.
> Some form of if(__ctfe) will happen, though.

What about having compile-time access to dynamic libraries, implemented
via dlopen() etc? Basically a compile-time FFI? There's nothing fundamentally unkosher about that, or so it seems to me. It would certainly be a big jaw-dropper feature for a C-like language. LISP has
it, right? :)

Cheers, Kuba