Mixin Expressions, can't evalutate string variable

Andrej Mitrovic andrej.mitrovich at gmail.com
Sat Aug 7 13:14:12 PDT 2010


Anyway, I've updated autoCall(), so now you can pass arguments like usual
but also specify the names of any ref/out variables that will be created. It
will also check to make sure the number of arguments matches for the call to
the function. Of course, arguments have to be evaluable at compile time (You
can't just pass a string, it has to be immutable). Here's the code:

import std.file;        // getTimes()
import std.conv;        // to!string()
import std.traits;      // Parameter types, storage, introspection

import std.stdio;

// Notes:
//  Currently it only works with simple built-in types:
//    Integrals, strings, but not objects.
//
//  It will throw a compiler error and a message if there are unmatched
//  number of arguments for the call to func().
//  Arguments have to be evaluable at compile time.
auto autoCall(alias func, T...)(T args)
{
    alias ParameterStorageClass STC;                // storage class enum
    alias ParameterTypeTuple!(func) paramTypes;          // types of
parameters
    alias ParameterStorageClassTuple!(func) storageTypes; // storage class
of parameters


    static if (paramTypes.length != args.length)
    {
        pragma(msg, "autoCall: Template Error: Unmatched number of arguments
for call to " ~ __traits(identifier, func) ~ "()");
        static assert(0);
    }

    string declString, callString;

    // eg: callString = "funcName("
    callString = __traits(identifier, func) ~ "(";

    foreach (int i, storageType; storageTypes)
    {
        if (storageType == STC.OUT || storageType == STC.REF)
        {
            // eg: declString ~= "int newParamName; "
            declString ~= paramTypes[i].stringof ~ " " ~ args[i] ~ "; ";

            // eg: callString = "funcName(" ~ "newParamName,"
            callString ~= " " ~ args[i] ~ ",";
        }
        else
        {
            // Fetch the value of args or args[i] and expand it to
callString.
            // We cannot use the actual names of the arguments since that
would
            // not work with literals (unless we added tests and more
branching)

            // need to use static if here due to array bounds checking
            static if (args.length == 1)
            {
                // eg: callString = "funcName(args, newParamName,"
                callString ~= '"' ~ to!string(args) ~ '"' ~ ",";
            }
            else
            {
                // eg: callString = "funcName(args[i], newParamName,"
                callString ~= '"' ~ to!string(args[i]) ~ '"' ~ ",";
            }
        }
    }

    // remove the extra comma and close the call string
    callString = callString[0 .. $ - 1] ~ ");";

    // return joined strings ready to be used with mixin()
    return declString ~= callString;
}

void testMe(string x, ref int z, string y)
{
    writeln(x, y);
    z = 5;
}

unittest
{
    immutable string var1 = "foo";
    immutable string var2 = "bar";

    mixin(autoCall!(testMe)(var1, "newvar", var2));
    assert(newvar == 5);
}

void main() { }

Fun stuff, right? :p

On Sat, Aug 7, 2010 at 9:57 PM, Andrej Mitrovic
<andrej.mitrovich at gmail.com>wrote:

> Cool stuff! I'll have a look later. Thanks.
>
>
> On Sat, Aug 7, 2010 at 9:53 PM, Nick Sabalausky <a at a.a> wrote:
>
>> "Andrej Mitrovic" <andrej.mitrovich at gmail.com> wrote in message
>> news:mailman.175.1281208901.13841.digitalmars-d at puremagic.com...
>> > You know, I just had an idea. It would be really cool to have some sort
>> of
>> > generalized template function which can test other functions in various
>> > ways. You could pass strings as options, where you might choose the type
>> > of
>> > testing being done, such as verification tests or performance tests.. Or
>> > if
>> > a function is designed to write a file on disk, maybe you'd want to have
>> > an
>> > option for the maximum number of tests to run on that function (you
>> don't
>> > want to be left with 10000 files written in some temp directory
>> > somewhere..), or a test to see if a function will fail with invalid
>> input,
>> > etc.
>> >
>> > Well it's just an idea, I better take a look at the existing test
>> > frameworks
>> > and see how it's done there.
>> >
>>
>> Probably not quite as fancy as what you're talking about, but my SemiTwist
>> D
>> Tools library has a module that includes something that's similar to
>> assert
>> but:
>>
>> - Allows to you verify that a particular statement throws a particular
>> type
>> of exception.
>> - Properly reports if an expression throws (and you didn't expect it to).
>> - Doesn't abort the program on failure.
>> - Reports "expected" expression and "actual" value.
>>
>>
>> http://www.dsource.org/projects/semitwist/browser/trunk/src/semitwist/apps/tests/deferAssertTest/main.d
>>
>> http://www.dsource.org/projects/semitwist/browser/trunk/src/semitwist/util/deferAssert.d
>>
>> It does need some clean-up and improvements, but it at least works.
>> (Although, trunk is currently in the process of switching from D1/Tango to
>> D2/Phobos, so the latest revisions might be broken and it definitely
>> doesn't
>> take advantage of D2-specific features yet. But the version included with
>> Goldie 0.3 does work fine on D1/Tango though).
>>
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puremagic.com/pipermail/digitalmars-d/attachments/20100807/a2db62a8/attachment.html>


More information about the Digitalmars-d mailing list