better assertions and __FILE__ (compile time functions)

Bruce Adams tortoise_74 at yada.yahoo.yada.nospamme.co.uk
Sun Aug 19 18:31:27 PDT 2007


Lutger Wrote:

> Bruce Adams wrote:
> > 
> > Here are a few more things I've learned on my travels around the various D web-pages.
> > 
> > __FILE__ & __LINE__ are expanded by the tokeniser not the parser. This implies that they would not be available for use in mixins as they will already have been expanded. This is confirmed with a quick test. So what I'm trying to do is not currently possible.
> >
> 
> It's possible to use CTFE with string mixins to achieve this. I have 
> whipped up something quick, ugly as hell but could be improved using 
> std.metastrings.Format:
> 
> 
> char[] assertEqual(char[] actual, char[] expected)
> {
>      return  `if (` ~ actual ~ `!=` ~ expected ~ `) { `
>                  `writefln("Equality assertion failed in " ~ __FILE__ ~ 
> " at line " ~ std.metastrings.ToString!(__LINE__));`
>                  `writefln("expected value: '", ` ~ expected ~ `, "'");` 
> 
>                  `writefln("actual value:   '", ` ~ actual ~ `, "'");`
>                  `assert(false);}`;
> }
> 
> used as:
> 
> mixin(assertEqual("foo","bar"));
> 
> 
> If you can live with a) having to use 'mixin', b) ugliness of compile 
> time string manipulation and perhaps c) sometimes hard to follow error 
> messages, you can do most of anything you want with CTFE and string mixins.
> I think if one would make work of this most of the tediousness could be 
> solved with some boilerplate code.
> 

I'd rather live with A) - than without the option to do this at all.
B) is better than it was in C++. I'm already struggling with C) using DMD, if you'll pardon the pun.

I can see from using a variant of your example that is possible now.
I forgot we had CTFE. I was surprised it allows arbitrary strings to be compiled as I though mxins were supposed to use code segments that have been parsed already.
Anyway, I'm still struggling a bit with it. My main problem can be boiled
down to the following example.

char[] int2str(int foo_)
{
   return std.metastrings.ToString!(foo_);
}

Fails to compile with 

c:\dmd\bin\..\src\phobos\std\metastrings.d(102): Error: expression cast(long)foo
_ is not a valid template value argument
c:\dmd\bin\..\src\phobos\std\metastrings.d(85): Error: expression cast(long)foo_
 < 0L is not constant or does not evaluate to a bool

Without the shriek it also fails:

char[] int2str(int foo_)
{
   return std.metastrings.ToString(foo_);
}

dmd.exe -c UnitTest.d -ofUnitTest.do -cov
c:\dmd\bin\..\src\phobos\std\metastrings.d(74): template std.metastrings.ToStrin
g(ulong U) is not a function template
UnitTest.d(124): template std.metastrings.ToString(ulong U) cannot deduce templa
te function from argument types (int)
UnitTest.d(124): Error: cannot implicitly convert expression ((ToString(ulong U)
)(foo_)) of type int to char[]

Its not obvious to me what I'm doing wrong.

Incidentally is there a way of specifying you only want a function to be evaluated at compile time? Perhaps the static keyword?
My plan when this kind of thing comes up is to have one function for
the run-time portion and a seperate code generator for the compile time stuff.

Regards,

Bruce.


More information about the Digitalmars-d-learn mailing list