Thread overview
int to char at compile time
Mar 20, 2007
Hendrik Renken
Mar 20, 2007
BCS
Mar 20, 2007
Hendrik Renken
Mar 20, 2007
Frits van Bommel
Mar 21, 2007
torhu
Mar 21, 2007
Hendrik Renken
Mar 21, 2007
Hendrik Renken
March 20, 2007
hello,

i am trying something like that:

char[] foo(int level, char[] msg)
{
    static c = toString(level);
    return "writefln(\"%d: %s\""~ c ~", \"" ~ msg ~ "\");";
}


int main(char[][] args)
{
   mixin(foo(100, "Test"));
   return 1;
}

but gdmd complaints that toString() cannot be evaluated at compile time. is there a way to convert the int to char at compile time?

regards,
Hendrik
March 20, 2007
Reply to Hendrik,

> hello,
> 
> i am trying something like that:
> 
> char[] foo(int level, char[] msg)
> {
> static c = toString(level);
> return "writefln(\"%d: %s\""~ c ~", \"" ~ msg ~ "\");";
> }
> int main(char[][] args)
> {
> mixin(foo(100, "Test"));
> return 1;
> }
> but gdmd complaints that toString() cannot be evaluated at compile
> time. is there a way to convert the int to char at compile time?
> 
> regards,
> Hendrik


Don Clugston's decimaldigit and itoa, see http://trac.dsource.org/projects/ddl/browser/trunk/meta/conv.d

template decimalDigit(int n)
{
 const char[] decimalDigit = "0123456789"[n..n+1];
} 

template itoa(long n)
{    static if (n < 0)
    const char[] itoa = "-" ~ itoa!(-n);   else static if (n < 10)
    const char[] itoa = decimalDigit!(n);  else
    const char[] itoa = itoa!(n/10L) ~ decimalDigit!(n%10L); }


March 20, 2007
BCS wrote:
> Reply to Hendrik,
> 
>> hello,
>>
>> i am trying something like that:
>>
>> char[] foo(int level, char[] msg)
>> {
>> static c = toString(level);
>> return "writefln(\"%d: %s\""~ c ~", \"" ~ msg ~ "\");";
>> }
>> int main(char[][] args)
>> {
>> mixin(foo(100, "Test"));
>> return 1;
>> }
>> but gdmd complaints that toString() cannot be evaluated at compile
>> time. is there a way to convert the int to char at compile time?
> 
> 
> Don Clugston's decimaldigit and itoa, see http://trac.dsource.org/projects/ddl/browser/trunk/meta/conv.d


this doesn't work for variables like "level", just with directly wrote numbers.

char[] foo(int level, char[] msg)
{
    char[] c = itoa!(level); //does not work
    char[] c = itoa!(100);   //does work
}

is there no chance, to get this variable value converted?
March 20, 2007
Hendrik Renken wrote:
> BCS wrote:
>> Reply to Hendrik,
>>
>>> i am trying something like that:
>>>
>>> char[] foo(int level, char[] msg)
>>> {
>>> static c = toString(level);

You can't make it static, since parameters aren't known when the function is compiled. Remember the function is also compiled for regular run-time use. It needs to make sense as such.
Also, std.string.toString(int) unfortunately isn't compile-time executable.

>>> return "writefln(\"%d: %s\""~ c ~", \"" ~ msg ~ "\");";
>>> }
>>> int main(char[][] args)
>>> {
>>> mixin(foo(100, "Test"));
>>> return 1;
>>> }
>>> but gdmd complaints that toString() cannot be evaluated at compile
>>> time. is there a way to convert the int to char at compile time?

Yes, see below

>> Don Clugston's decimaldigit and itoa, see http://trac.dsource.org/projects/ddl/browser/trunk/meta/conv.d

Doesn't work for CTFE parameters.

> this doesn't work for variables like "level", just with directly wrote numbers.
> 
> char[] foo(int level, char[] msg)
> {
>     char[] c = itoa!(level); //does not work
>     char[] c = itoa!(100);   //does work
> }
> 
> is there no chance, to get this variable value converted?

---
import std.stdio;

char[] ctfe_itoa(int value) {
	if (value < 0) return "-" ~ ctfe_itoa(-value);
	if (value < 10) return "0123456789"[value .. value+1];
	return ctfe_itoa(value / 10) ~ ctfe_itoa(value % 10);
}

char[] foo(int level, char[] msg)
{
    auto c = ctfe_itoa(level);
    return "writefln(\"%d: %s\","~ c ~", \"" ~ msg ~ "\");";
}

int main(char[][] args)
{
   pragma(msg, foo(42u, "The answer"));
   pragma(msg, foo(int.max, "int.max"));
   mixin(foo(100, "Test"));
   return 1;
}
---

I originally wrote that function to be more efficient (so it could also reasonably be used at runtime) by using a stack-based buffer and returning buffer.dup, without any recursion. Unfortunately CTFE didn't like it :(.
This version will of course still work at runtime, but will perform way too many allocations for a function like this. (I'm not sure if this will be a problem at compile time).
March 21, 2007
Hendrik Renken wrote:

> but gdmd complaints that toString() cannot be evaluated at compile time. is there a way to convert the int to char at compile time?


std.metastrings has a couple of ways of doing this.
March 21, 2007
torhu wrote:
> Hendrik Renken wrote:
> 
>> but gdmd complaints that toString() cannot be evaluated at compile time. is there a way to convert the int to char at compile time?
> 
> 
> std.metastrings has a couple of ways of doing this.

just for the records: with std.metastrings i am running in the same problems having with DDL.

the ctfe_itoa function from Frits van Bommel works great. Thanks again.


another little problem/maybe-bug i ran into:
since i currently only have defined int values for "level", i use a switch-Statement to get propper String representations.

const int CORE = 100;

char[] foo(int level, char[] msg)
{
    char[] name;
    switch(level)
    {
	case CORE:
		name = "CORE"; /******* important line ********/

		break;
	default:
		name = "TEST";
	}
    return "writefln(\"%s: %s\", "~ name ~", \"" ~ msg ~ "\");";
}


int main(char[][] args)
{
   mixin(foo(CORE, "Testmsg"));
   return 1;
}


using
name = "CORE";
writes to the console

100: Testmsg


using
name = "\"CORE\"";
gives me what i want

CORE: Testmsg

shouldnt it also work with "CORE"? or am i missing something here?

regards
Hendrik
March 21, 2007
--------8< snip code 8<----------
> 
> using
> name = "CORE";
> writes to the console
> 
> 100: Testmsg
> 
> 
> using
> name = "\"CORE\"";
> gives me what i want
> 
> CORE: Testmsg
> 
> shouldnt it also work with "CORE"? or am i missing something here?

sorry for bothering, answered the question myself.

Code:
"writefln(\"%s: %s\", "~ name ~", \"" ~ msg ~ "\");"


using name = "CORE";
gives us the line
"writefln(\"%s: %s\", CORE, "Testmsg");"

note: around ~msg~ i inserted " with \"

so this is not "CORE", instead is uses the defined int variable, which has (of course) the value 100. giving

100: Testmsg