www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Mixin Expressions, can't evalutate string variable

reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
I think this should work:

string s = "int x;";
mixin(s);

void main()
{
    
}

But I get:
testtest.d(11): Error: argument to mixin must be a string, not (s)

I get a similar error with the template example from the docs:

template GenStruct(string Name, string M1)
{
    string GenStruct = "struct " ~ Name ~ "{ int " ~ M1 ~ "; }";
}

mixin(GenStruct!("Foo", "bar"));

void main() { }

testtest.d(27): Error: argument to mixin must be a string, not (GenStruct)


This is really weird, I swear it worked for me a couple of days ago. :s
Maybe I accidentally modified a library file, so I'll have a look. Meanwhile
can someone succesfully compile these?
Aug 05 2010
parent reply Tomek =?UTF-8?B?U293acWEc2tp?= <just ask.me> writes:
Andrej Mitrovic napisał:

 I think this should work:
 
 string s = "int x;";
 mixin(s);
 
 void main()
 {
     
 }
 
 But I get:
 testtest.d(11): Error: argument to mixin must be a string, not (s)
 
 I get a similar error with the template example from the docs:
 
 template GenStruct(string Name, string M1)
 {
     string GenStruct = "struct " ~ Name ~ "{ int " ~ M1 ~ "; }";
 }
 
 mixin(GenStruct!("Foo", "bar"));
 
 void main() { }
 
 testtest.d(27): Error: argument to mixin must be a string, not (GenStruct)
 
 
 This is really weird, I swear it worked for me a couple of days ago. :s
 Maybe I accidentally modified a library file, so I'll have a look.
 Meanwhile can someone succesfully compile these?
template GenStruct(string Name, string M1) { immutable string GenStruct = "struct " ~ Name ~ "{ int " ~ M1 ~ "; }"; } It must be immutable to be seen as a template expression. Otherwise it's one mutable string declaration that happens to be named same as the enclosing template. Tomek
Aug 05 2010
next sibling parent Tomek =?UTF-8?B?U293acWEc2tp?= <just ask.me> writes:
Tomek Sowiński napisał:

 Andrej Mitrovic napisał:
 
 I think this should work:
 
 string s = "int x;";
 mixin(s);
 
 void main()
 {
     
 }
 
 But I get:
 testtest.d(11): Error: argument to mixin must be a string, not (s)
 
 I get a similar error with the template example from the docs:
 
 template GenStruct(string Name, string M1)
 {
     string GenStruct = "struct " ~ Name ~ "{ int " ~ M1 ~ "; }";
 }
 
 mixin(GenStruct!("Foo", "bar"));
 
 void main() { }
 
 testtest.d(27): Error: argument to mixin must be a string, not
 (GenStruct)
 
 
 This is really weird, I swear it worked for me a couple of days ago. :s
 Maybe I accidentally modified a library file, so I'll have a look.
 Meanwhile can someone succesfully compile these?
template GenStruct(string Name, string M1) { immutable string GenStruct = "struct " ~ Name ~ "{ int " ~ M1 ~ "; }"; } It must be immutable to be seen as a template expression. Otherwise it's one mutable string declaration that happens to be named same as the enclosing template.
To avoid the WTF you may find CTFE useful (and easier on the eye): string GenStruct(string Name, string M1) { return "struct " ~ Name ~ "{ int " ~ M1 ~ "; }"; } mixin(GenStruct("Foo", "bar")); Tomek
Aug 05 2010
prev sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Hmm.. ok. Adding immutable helps. I'm still a bit confused tho,
 because this will not compile:

string input2 = "int y;";
mixin(input2);

But this will compile:

immutable string input2 = "int y;";
mixin(input2);

And this too will compile:

string returnString(string input)
{
    return input;
}

mixin(returnString("int y;"));

Tomek Sowiński Wrote:

 Andrej Mitrovic napisał:
 
 I think this should work:
 
 string s = "int x;";
 mixin(s);
 
 void main()
 {
     
 }
 
 But I get:
 testtest.d(11): Error: argument to mixin must be a string, not (s)
 
 I get a similar error with the template example from the docs:
 
 template GenStruct(string Name, string M1)
 {
     string GenStruct = "struct " ~ Name ~ "{ int " ~ M1 ~ "; }";
 }
 
 mixin(GenStruct!("Foo", "bar"));
 
 void main() { }
 
 testtest.d(27): Error: argument to mixin must be a string, not (GenStruct)
 
 
 This is really weird, I swear it worked for me a couple of days ago. :s
 Maybe I accidentally modified a library file, so I'll have a look.
 Meanwhile can someone succesfully compile these?
template GenStruct(string Name, string M1) { immutable string GenStruct = "struct " ~ Name ~ "{ int " ~ M1 ~ "; }"; } It must be immutable to be seen as a template expression. Otherwise it's one mutable string declaration that happens to be named same as the enclosing template. Tomek
Aug 05 2010
next sibling parent reply Tomek =?UTF-8?B?U293acWEc2tp?= <just ask.me> writes:
Andrej Mitrovic napisał:

 Hmm.. ok. Adding immutable helps. I'm still a bit confused tho,
  because this will not compile:
 
 string input2 = "int y;";
 mixin(input2);
input2 is mutable, so theoretically there's no telling what value it holds.
 But this will compile:
 
 immutable string input2 = "int y;";
 mixin(input2);
And good.
 And this too will compile:
 
 string returnString(string input)
 {
     return input;
 }
 
 mixin(returnString("int y;"));
Because the function is *nice*, compiler can evaluate the call at compile-time (see my other post). Somewhere on the D page (Lang. Ref. > Functions ?) there's a largish explanation what's *nice*. Tomek
Aug 05 2010
parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 05 Aug 2010 15:34:44 -0400, Tomek Sowiński <just ask.me> wrote:

 Andrej Mitrovic napisał:

 Hmm.. ok. Adding immutable helps. I'm still a bit confused tho,
  because this will not compile:

 string input2 = "int y;";
 mixin(input2);
input2 is mutable, so theoretically there's no telling what value it holds.
Before you respond with more WTF, there is a subtlety here :) A string is aliased to immutable(char)[]. This means that the *data* pointed at is immutable but the *array* is mutable. You can reassign a string to point at some other immutable data, or change the length of the array. To illustrate this: string input2 = "int y;"; static this() { input2 = "int x;"; // perfectly legal } mixin(input2); // what does this do? Now, immutable string means: immutable(immutable(char)[]), which reduces to immutable(char[]), meaning both the data pointed at *and* the array are immutable (note the distinction of where the parentheses are). This can be used in CTFE and mixins because the compiler knows the value is completely defined at compile-time. strings (the kind where the array part is mutable) can be used as mixins as long as they are rvalues, such as the returns from functions which are CTFE capable. -Steve
Aug 05 2010
next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Thanks, Steven!

You don't want to know what I'm up to :p.

I'm using some traits to find out what kind of parameters a function takes.
I'm also using a demangler from phobos to find out the name of the function
(But I can't find any straightforward way to get a name of a function
without getting back "1D_5std_5funcName" etc, so I just take a hardcoded
slice).

Anyway, I have a template function which takes as it's parameters a functio=
n
(aliased to func), and some arguments (right now just one in my hardcoded
code). It then creates a string which can be compiled via the mixin. It
constructs the string by checking the parameter types of func, and for any
ref or out parameter it detects it appends something like this to a string:
"long var1; long var2; long var3; ".

For any non-out/ref parameters it constructs another string which will call
that func (here is where I'm using the demangler to get the real name of th=
e
function). So the other string would eventually look like so:
"funcName(argN.., var1, var2, var3);

It then concatenates both strings and returns it, creating the whole
shebang:
"int var1; double var2; funcName(argN..., var1, var2, var3);"

This can then be used with mixin() at the calling site. I was inspiried to
try this out when bearophile wanted some new tuple syntax assignment in D.

So anyway, at the calling site I have this:

mixin(unpack!(getTimes)(r"C:\\cookies"));

getTimes() is a Phobos function with the signature:
getTimes(in char[] name, out d_time ftc, out d_time fta, out d_time ftm)

And now I automatically have var1, var2, and var3 at my disposal.

It was just an exercise for fun but it's cool that things like this are
possible in D. It would be nice if I could get the actual names of the
parameters the function takes + the clear name of the function itself, that
way I'd actually get back variables "ftc, fta, ftm" back).

Right now the code is a big mess but I could fix it up a lot and post it
here if anyone cares.

On Thu, Aug 5, 2010 at 9:48 PM, Steven Schveighoffer <schveiguy yahoo.com>w=
rote:

 On Thu, 05 Aug 2010 15:34:44 -0400, Tomek Sowi=C5=84ski <just ask.me> wro=
te:
  Andrej Mitrovic napisa=C5=82:
  Hmm.. ok. Adding immutable helps. I'm still a bit confused tho,
  because this will not compile:

 string input2 =3D "int y;";
 mixin(input2);
input2 is mutable, so theoretically there's no telling what value it holds.
Before you respond with more WTF, there is a subtlety here :) A string is aliased to immutable(char)[]. This means that the *data* pointed at is immutable but the *array* is mutable. You can reassign a string to point at some other immutable data, or change the length of the array. To illustrate this: string input2 =3D "int y;"; static this() { input2 =3D "int x;"; // perfectly legal } mixin(input2); // what does this do? Now, immutable string means: immutable(immutable(char)[]), which reduces to immutable(char[]), meaning both the data pointed at *and* the array are immutable (note the distinct=
ion
 of where the parentheses are).  This can be used in CTFE and mixins becau=
se
 the compiler knows the value is completely defined at compile-time.

 strings (the kind where the array part is mutable) can be used as mixins =
as
 long as they are rvalues, such as the returns from functions which are CT=
FE
 capable.

 -Steve
Aug 05 2010
prev sibling next sibling parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
On Thu, Aug 5, 2010 at 22:24, Andrej Mitrovic <andrej.mitrovich gmail.com>wrote:

 Thanks, Steven!

 You don't want to know what I'm up to :p.
Yes, yes, wo do!
 I'm using some traits to find out what kind of parameters a function takes.
 I'm also using a demangler from phobos to find out the name of the function
 (But I can't find any straightforward way to get a name of a function
 without getting back "1D_5std_5funcName" etc, so I just take a hardcoded
 slice).
You can get the name of an alias using __traits(identifier, aliasName), like this for example: template Name(alias a) { enum string Name = __traits(identifier, a); } int foo(int i) { return 0;} import std.stdio; void main() { writeln(Name!foo); // "foo", not "a". } As for demangling, how do you do to get mangled names in the first place?
 Anyway, I have a template function which takes as it's parameters a
 function (aliased to func), and some arguments (right now just one in my
 hardcoded code). It then creates a string which can be compiled via the
 mixin. It constructs the string by checking the parameter types of func, and
 for any ref or out parameter it detects it appends something like this to a
 string:
 "long var1; long var2; long var3; ".
How can you know if a parameter is ref or out? I remember seeing something about it in Phobos svn, are you using it?
 So anyway, at the calling site I have this:

 mixin(unpack!(getTimes)(r"C:\\cookies"));

 getTimes() is a Phobos function with the signature:
 getTimes(in char[] name, out d_time ftc, out d_time fta, out d_time ftm)

 And now I automatically have var1, var2, and var3 at my disposal.
That's fun :)
 It was just an exercise for fun but it's cool that things like this are
 possible in D. It would be nice if I could get the actual names of the
 parameters the function takes + the clear name of the function itself, that
 way I'd actually get back variables "ftc, fta, ftm" back)
I'm pretty sure I saw some code to do this. But maybe that was a D1 thing, using mangled names, too. in dsource/scrapple? Philippe
Aug 05 2010
prev sibling next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On Thu, Aug 5, 2010 at 11:29 PM, Philippe Sigaud
<philippe.sigaud gmail.com>wrote:

 On Thu, Aug 5, 2010 at 22:24, Andrej Mitrovic
<andrej.mitrovich gmail.com>wrote:

 Thanks, Steven!

 You don't want to know what I'm up to :p.
Yes, yes, wo do!
 I'm using some traits to find out what kind of parameters a function
 takes. I'm also using a demangler from phobos to find out the name of the
 function (But I can't find any straightforward way to get a name of a
 function without getting back "1D_5std_5funcName" etc, so I just take a
 hardcoded slice).
You can get the name of an alias using __traits(identifier, aliasName), like this for example: template Name(alias a) { enum string Name = __traits(identifier, a); } int foo(int i) { return 0;} import std.stdio; void main() { writeln(Name!foo); // "foo", not "a". } As for demangling, how do you do to get mangled names in the first place?
I was using mangledName!() from std.straits. __traits works prefectly, Thanks!
 Anyway, I have a template function which takes as it's parameters a
 function (aliased to func), and some arguments (right now just one in my
 hardcoded code). It then creates a string which can be compiled via the
 mixin. It constructs the string by checking the parameter types of func, and
 for any ref or out parameter it detects it appends something like this to a
 string:
 "long var1; long var2; long var3; ".
How can you know if a parameter is ref or out? I remember seeing something about it in Phobos svn, are you using it?
Not svn, it's in 2.047 (maybe in earlier ones as well) in std.traits: ParameterTypeTuple!(alias) - for the types ParameterStorageClassTuple!(alias) - for the storage class
 So anyway, at the calling site I have this:

 mixin(unpack!(getTimes)(r"C:\\cookies"));

 getTimes() is a Phobos function with the signature:
 getTimes(in char[] name, out d_time ftc, out d_time fta, out d_time ftm)

 And now I automatically have var1, var2, and var3 at my disposal.
That's fun :)
 It was just an exercise for fun but it's cool that things like this are
 possible in D. It would be nice if I could get the actual names of the
 parameters the function takes + the clear name of the function itself, that
 way I'd actually get back variables "ftc, fta, ftm" back)
I'm pretty sure I saw some code to do this. But maybe that was a D1 thing, using mangled names, too. in dsource/scrapple? Philippe
Dunno, I haven't been using D1 really (actually I tried it some years ago with Tango but it left me wanting more so I never stuck around much). But D2 is super-fun.
Aug 05 2010
parent reply Jacob Carlborg <doob me.com> writes:
On 2010-08-05 23:50, Andrej Mitrovic wrote:
 On Thu, Aug 5, 2010 at 11:29 PM, Philippe Sigaud
 <philippe.sigaud gmail.com <mailto:philippe.sigaud gmail.com>> wrote:



     On Thu, Aug 5, 2010 at 22:24, Andrej Mitrovic
     <andrej.mitrovich gmail.com <mailto:andrej.mitrovich gmail.com>> wrote:

         Thanks, Steven!

         You don't want to know what I'm up to :p.


     Yes, yes, wo do!


         I'm using some traits to find out what kind of parameters a
         function takes. I'm also using a demangler from phobos to find
         out the name of the function (But I can't find any
         straightforward way to get a name of a function without getting
         back "1D_5std_5funcName" etc, so I just take a hardcoded slice).


     You can get the name of an alias using __traits(identifier,
     aliasName), like this for example:

     template Name(alias a)
     {
        enum string Name = __traits(identifier, a);
     }

     int foo(int i) { return 0;}

     import std.stdio;
     void main()
     {
        writeln(Name!foo); // "foo", not "a".
     }


     As for demangling, how do you do to get mangled names in the first
     place?


 I was using mangledName!() from std.straits. __traits works prefectly,
 Thanks!
You know there is a .mangleof property for all symbols.
         Anyway, I have a template function which takes as it's
         parameters a function (aliased to func), and some arguments
         (right now just one in my hardcoded code). It then creates a
         string which can be compiled via the mixin. It constructs the
         string by checking the parameter types of func, and for any ref
         or out parameter it detects it appends something like this to a
         string:
         "long var1; long var2; long var3; ".


     How can you know if a parameter is ref or out?
     I remember seeing something about it in Phobos svn, are you using it?


 Not svn, it's in 2.047 (maybe in earlier ones as well) in std.traits:

 ParameterTypeTuple!(alias) - for the types
 ParameterStorageClassTuple!(alias) - for the storage class

         So anyway, at the calling site I have this:

         mixin(unpack!(getTimes)(r"C:\\cookies"));

         getTimes() is a Phobos function with the signature:
         getTimes(in char[] name, out d_time ftc, out d_time fta, out
         d_time ftm)

         And now I automatically have var1, var2, and var3 at my disposal.


     That's fun :)


         It was just an exercise for fun but it's cool that things like
         this are possible in D. It would be nice if I could get the
         actual names of the parameters the function takes + the clear
         name of the function itself, that way I'd actually get back
         variables "ftc, fta, ftm" back)


     I'm pretty sure I saw some code to do this. But maybe that was a D1
     thing, using mangled names, too.
     in dsource/scrapple?

     Philippe


 Dunno, I haven't been using D1 really (actually I tried it some years
 ago with Tango but it left me wanting more so I never stuck around
 much). But D2 is super-fun.
-- /Jacob Carlborg
Aug 06 2010
next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
I've already tried that. But .mangleof on an aliased symbol just returns
"alias" as a string.


On Fri, Aug 6, 2010 at 10:44 AM, Jacob Carlborg <doob me.com> wrote:

 On 2010-08-05 23:50, Andrej Mitrovic wrote:

 On Thu, Aug 5, 2010 at 11:29 PM, Philippe Sigaud
 <philippe.sigaud gmail.com <mailto:philippe.sigaud gmail.com>> wrote:



    On Thu, Aug 5, 2010 at 22:24, Andrej Mitrovic
    <andrej.mitrovich gmail.com <mailto:andrej.mitrovich gmail.com>>
 wrote:

        Thanks, Steven!

        You don't want to know what I'm up to :p.


    Yes, yes, wo do!


        I'm using some traits to find out what kind of parameters a
        function takes. I'm also using a demangler from phobos to find
        out the name of the function (But I can't find any
        straightforward way to get a name of a function without getting
        back "1D_5std_5funcName" etc, so I just take a hardcoded slice).


    You can get the name of an alias using __traits(identifier,
    aliasName), like this for example:

    template Name(alias a)
    {
       enum string Name = __traits(identifier, a);
    }

    int foo(int i) { return 0;}

    import std.stdio;
    void main()
    {
       writeln(Name!foo); // "foo", not "a".
    }


    As for demangling, how do you do to get mangled names in the first
    place?


 I was using mangledName!() from std.straits. __traits works prefectly,
 Thanks!
You know there is a .mangleof property for all symbols. Anyway, I have a template function which takes as it's
        parameters a function (aliased to func), and some arguments
        (right now just one in my hardcoded code). It then creates a
        string which can be compiled via the mixin. It constructs the
        string by checking the parameter types of func, and for any ref
        or out parameter it detects it appends something like this to a
        string:
        "long var1; long var2; long var3; ".


    How can you know if a parameter is ref or out?
    I remember seeing something about it in Phobos svn, are you using it?


 Not svn, it's in 2.047 (maybe in earlier ones as well) in std.traits:

 ParameterTypeTuple!(alias) - for the types
 ParameterStorageClassTuple!(alias) - for the storage class

        So anyway, at the calling site I have this:

        mixin(unpack!(getTimes)(r"C:\\cookies"));

        getTimes() is a Phobos function with the signature:
        getTimes(in char[] name, out d_time ftc, out d_time fta, out
        d_time ftm)

        And now I automatically have var1, var2, and var3 at my disposal.


    That's fun :)


        It was just an exercise for fun but it's cool that things like
        this are possible in D. It would be nice if I could get the
        actual names of the parameters the function takes + the clear
        name of the function itself, that way I'd actually get back
        variables "ftc, fta, ftm" back)


    I'm pretty sure I saw some code to do this. But maybe that was a D1
    thing, using mangled names, too.
    in dsource/scrapple?

    Philippe


 Dunno, I haven't been using D1 really (actually I tried it some years
 ago with Tango but it left me wanting more so I never stuck around
 much). But D2 is super-fun.
-- /Jacob Carlborg
Aug 06 2010
prev sibling next sibling parent Jonathan M Davis <jmdavisprog gmail.com> writes:
On Friday, August 06, 2010 08:08:03 Andrej Mitrovic wrote:
 I've already tried that. But .mangleof on an aliased symbol just returns
 "alias" as a string.
That sounds like a bug report in the making. - Jonathan M Davis
Aug 06 2010
prev sibling next sibling parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
Andrej:


 It was just an exercise for fun but it's cool that things like this are
 possible in D. It would be nice if I could get the actual names of the
 parameters the function takes + the clear name of the function itself, that
 way I'd actually get back variables "ftc, fta, ftm" back)
There, found it again, while answering another thread: int foo(int i, double d) { return 0;} writeln(typeof(&foo).stringof); // "int function(int i, double d)" <-- Look Ma, arguments names! But it's a quirk of .stringof, I'm not sure it's a good idea to rely on it too much. from there, using compile-time search in a string, you can extract the arguments (those are between ( and ) ) -> "int i, double d" and from there, extracting i and d. I don't what will happen for overloaded functions, methods names, constructors, ... Philippe
Aug 06 2010
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Slightly OT: I've noticed you're often missing the word "know" in your posts
(e.g. "I don't what", that should be "I don't know what"). Is something
filtering your posts? :)

And yeah, I've noticed your other thread with the argument names. With a
little bit of regex I could easily extract the variable names. I think this
template could be useful in cases when you just want to try out a function
which happens to writes some state in the parameters that are passed to it
(out/ref params), without having to inspect the function signature and
declare the proper variable types. Unfortunately there's no way to pass auto
variables as parameters, but that's more of a Python territory, I guess.

On the other hand, the template introduces new identifiers silently into the
calling site (you can't see it in the code), so it's not all that practical
I guess, not to mention a little dangerous. :p

On Fri, Aug 6, 2010 at 10:22 PM, Philippe Sigaud
<philippe.sigaud gmail.com>wrote:

 Andrej:



 It was just an exercise for fun but it's cool that things like this are
 possible in D. It would be nice if I could get the actual names of the
 parameters the function takes + the clear name of the function itself, that
 way I'd actually get back variables "ftc, fta, ftm" back)
There, found it again, while answering another thread: int foo(int i, double d) { return 0;} writeln(typeof(&foo).stringof); // "int function(int i, double d)" <-- Look Ma, arguments names! But it's a quirk of .stringof, I'm not sure it's a good idea to rely on it too much. from there, using compile-time search in a string, you can extract the arguments (those are between ( and ) ) -> "int i, double d" and from there, extracting i and d. I don't what will happen for overloaded functions, methods names, constructors, ... Philippe
Aug 06 2010
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On Fri, Aug 6, 2010 at 8:40 PM, Jonathan M Davis <jmdavisprog gmail.com>wrote:

 On Friday, August 06, 2010 08:08:03 Andrej Mitrovic wrote:
 I've already tried that. But .mangleof on an aliased symbol just returns
 "alias" as a string.
That sounds like a bug report in the making. - Jonathan M Davis
No I was wrong, it won't allow me to use .mangleof on an alias of a function inside a template because that automatically calls the function (and that means I have to pass valid arguments to it). The mangledName!() template works just fine though. But I don't need mangled names, I was only using it as a workaround.
Aug 06 2010
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Actually I better report this, it might lead to unexpected behavior
otherwise. See, this will compile:

import std.stdio;

auto template_func(alias func, T...)(T args)
{
    return func.mangleof;
}

void test() {}

unittest
{
    writeln(template_func!(test, int)(1));
}

void main() { }


And this won't:

import std.stdio;

auto template_func(alias func, T...)(T args)
{
    return func.mangleof;
}

void test(int x) {}

unittest
{
    writeln(template_func!(test, int)(1));
}

void main() { }

(I've added a parameter to test()). The problem is the first code actually
called func, and succeeded silently since it takes no parameters. I don't
think this is an expected behavior?

On Sat, Aug 7, 2010 at 3:10 AM, Andrej Mitrovic
<andrej.mitrovich gmail.com>wrote:

 On Fri, Aug 6, 2010 at 8:40 PM, Jonathan M Davis <jmdavisprog gmail.com>wrote:

 On Friday, August 06, 2010 08:08:03 Andrej Mitrovic wrote:
 I've already tried that. But .mangleof on an aliased symbol just returns
 "alias" as a string.
That sounds like a bug report in the making. - Jonathan M Davis
No I was wrong, it won't allow me to use .mangleof on an alias of a function inside a template because that automatically calls the function (and that means I have to pass valid arguments to it). The mangledName!() template works just fine though. But I don't need mangled names, I was only using it as a workaround.
Aug 06 2010
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Damn regexe(s|n).

I almost never need them, but when I do, I have to spend an hour trying to
remember the syntax (+ I'm really used to doing regexes in Python and then
there's the whole "regex objects in lang x work different than in lang y"
thing). But I digress..

I think a better way is to pass strings which will be used to name the
variables to be constructed and initialized (+ return an error when there's
too few). And then at least you'll know there are some new local variables
at your disposal by looking at the call. That way we solve both problems.

On Sat, Aug 7, 2010 at 12:12 AM, Andrej Mitrovic <andrej.mitrovich gmail.com
 wrote:
 Slightly OT: I've noticed you're often missing the word "know" in your
 posts (e.g. "I don't what", that should be "I don't know what"). Is
 something filtering your posts? :)

 And yeah, I've noticed your other thread with the argument names. With a
 little bit of regex I could easily extract the variable names. I think this
 template could be useful in cases when you just want to try out a function
 which happens to writes some state in the parameters that are passed to it
 (out/ref params), without having to inspect the function signature and
 declare the proper variable types. Unfortunately there's no way to pass auto
 variables as parameters, but that's more of a Python territory, I guess.

 On the other hand, the template introduces new identifiers silently into
 the calling site (you can't see it in the code), so it's not all that
 practical I guess, not to mention a little dangerous. :p


 On Fri, Aug 6, 2010 at 10:22 PM, Philippe Sigaud <
 philippe.sigaud gmail.com> wrote:

 Andrej:



 It was just an exercise for fun but it's cool that things like this are
 possible in D. It would be nice if I could get the actual names of the
 parameters the function takes + the clear name of the function itself, that
 way I'd actually get back variables "ftc, fta, ftm" back)
There, found it again, while answering another thread: int foo(int i, double d) { return 0;} writeln(typeof(&foo).stringof); // "int function(int i, double d)" <-- Look Ma, arguments names! But it's a quirk of .stringof, I'm not sure it's a good idea to rely on it too much. from there, using compile-time search in a string, you can extract the arguments (those are between ( and ) ) -> "int i, double d" and from there, extracting i and d. I don't what will happen for overloaded functions, methods names, constructors, ... Philippe
Aug 06 2010
prev sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
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.

On Sat, Aug 7, 2010 at 4:04 AM, Andrej Mitrovic
<andrej.mitrovich gmail.com>wrote:

 Damn regexe(s|n).

 I almost never need them, but when I do, I have to spend an hour trying to
 remember the syntax (+ I'm really used to doing regexes in Python and then
 there's the whole "regex objects in lang x work different than in lang y"
 thing). But I digress..

 I think a better way is to pass strings which will be used to name the
 variables to be constructed and initialized (+ return an error when there's
 too few). And then at least you'll know there are some new local variables
 at your disposal by looking at the call. That way we solve both problems.


 On Sat, Aug 7, 2010 at 12:12 AM, Andrej Mitrovic <
 andrej.mitrovich gmail.com> wrote:

 Slightly OT: I've noticed you're often missing the word "know" in your
 posts (e.g. "I don't what", that should be "I don't know what"). Is
 something filtering your posts? :)

 And yeah, I've noticed your other thread with the argument names. With a
 little bit of regex I could easily extract the variable names. I think this
 template could be useful in cases when you just want to try out a function
 which happens to writes some state in the parameters that are passed to it
 (out/ref params), without having to inspect the function signature and
 declare the proper variable types. Unfortunately there's no way to pass auto
 variables as parameters, but that's more of a Python territory, I guess.

 On the other hand, the template introduces new identifiers silently into
 the calling site (you can't see it in the code), so it's not all that
 practical I guess, not to mention a little dangerous. :p


 On Fri, Aug 6, 2010 at 10:22 PM, Philippe Sigaud <
 philippe.sigaud gmail.com> wrote:

 Andrej:



 It was just an exercise for fun but it's cool that things like this are
 possible in D. It would be nice if I could get the actual names of the
 parameters the function takes + the clear name of the function itself, that
 way I'd actually get back variables "ftc, fta, ftm" back)
There, found it again, while answering another thread: int foo(int i, double d) { return 0;} writeln(typeof(&foo).stringof); // "int function(int i, double d)" <-- Look Ma, arguments names! But it's a quirk of .stringof, I'm not sure it's a good idea to rely on it too much. from there, using compile-time search in a string, you can extract the arguments (those are between ( and ) ) -> "int i, double d" and from there, extracting i and d. I don't what will happen for overloaded functions, methods names, constructors, ... Philippe
Aug 07 2010
parent reply "Nick Sabalausky" <a a.a> writes:
"Andrej Mitrovic" <andrej.mitrovich gmail.com> wrote in message 
news:mailman.175.1281208901.13841.digitalmars-d 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).
Aug 07 2010
next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Cool stuff! I'll have a look later. Thanks.

On Sat, Aug 7, 2010 at 9:53 PM, Nick Sabalausky <a a.a> wrote:

 "Andrej Mitrovic" <andrej.mitrovich gmail.com> wrote in message
 news:mailman.175.1281208901.13841.digitalmars-d 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).
Aug 07 2010
prev sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
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 gmail.com>wrote:

 Cool stuff! I'll have a look later. Thanks.


 On Sat, Aug 7, 2010 at 9:53 PM, Nick Sabalausky <a a.a> wrote:

 "Andrej Mitrovic" <andrej.mitrovich gmail.com> wrote in message
 news:mailman.175.1281208901.13841.digitalmars-d 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).
Aug 07 2010
prev sibling next sibling parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
On Thu, Aug 5, 2010 at 23:50, Andrej Mitrovic <andrej.mitrovich gmail.com>wrote:
 As for demangling, how do you do to get mangled names in the first place?
I was using mangledName!() from std.straits. __traits works prefectly, Thanks!
Oh, oh, lots of shiny new things in std.traits! I didn't specifically look at this module for 2.047, my mistake. And, demange(mangledName!foo) gives back a qualified name, nice! I was looking as a way to get that, not two hours ago. *goes play with it* Ah, it doesn't work with templates names, though. Thanks Andrej! Philippe
Aug 05 2010
prev sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Hope you have fun with it!

Anyway, here's a much cleaner edition of my magic little template function.
There's probably a host of errors and silly mistakes, but this is just a
proof of concept more than anything else, really:

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

import std.stdio;

// Note:
// Errors are messy, since the function returns an arbitrary string ready to
be
// mixed in.
//
// If there are not enough arguments in args to make the call, autoCall
// will re-send the same argument value for each one missing in func's
signature.
// (this is by accident, not design)
//
// Tests could be added to make sure there are enough arguments in the
// args tuple however.
auto autoCall(alias func, T...)(T args)
{
    alias ParameterStorageClass STC;                // storage class enum
    alias ParameterTypeTuple!(func) types;          // types of parameters
    alias ParameterStorageClassTuple!(func) params; // storage class of
parameters

    string declString, callString;
    callString = __traits(identifier, func) ~ "(";  // funcName(

    foreach (int i, param; params)
    {
        if (param == STC.OUT || param == STC.REF)
        {
            // e.g. "int var1; "
            declString ~= types[i].stringof ~ " var" ~ i.stringof ~ "; ";

            // e.g. "funcName(" ~= " var1,"
            callString ~= " var" ~ i.stringof ~ ",";
        }
        else
        {
            // The non-out & non-ref parameter to func is already present in
args,
            // fetch it's value and append it to the call string.

            // need to use static if due to DMD complaints about array
bounds
            // in the else clause
            static if (args.length == 1)
            {
                // e.g. "funcName(" ~= "r'filename', "
                callString ~= '"' ~ to!string(args) ~ '"' ~ ",";
            }
            else
            {
                callString ~= '"' ~ to!string(args[i]) ~ '"' ~ ",";
            }
        }
    }

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

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

void testMe(string x, string y)
{
    writeln(x, y);
}

unittest
{
    mixin(autoCall!(getTimes)(r"C:\\cookies"));
    mixin(autoCall!(testMe)("test"));

    writefln("var1: %s, var2: %s, var3: %s", var1, var2, var3);
}

void main() { }



You'll have to replace the string in the first mixin ("cookies") to some
file on your drive. I'm not sure if the Linux version of getTimes works the
same way though.


On Fri, Aug 6, 2010 at 12:05 AM, Philippe Sigaud
<philippe.sigaud gmail.com>wrote:

 On Thu, Aug 5, 2010 at 23:50, Andrej Mitrovic
<andrej.mitrovich gmail.com>wrote:
 As for demangling, how do you do to get mangled names in the first place?
I was using mangledName!() from std.straits. __traits works prefectly, Thanks!
Oh, oh, lots of shiny new things in std.traits! I didn't specifically look at this module for 2.047, my mistake. And, demange(mangledName!foo) gives back a qualified name, nice! I was looking as a way to get that, not two hours ago. *goes play with it* Ah, it doesn't work with templates names, though. Thanks Andrej! Philippe
Aug 05 2010
prev sibling parent "Nick Sabalausky" <a a.a> writes:
"Andrej Mitrovic" <andrej.mitrovich gmail.com> wrote in message 
news:i3f3a0$25fv$1 digitalmars.com...
 Hmm.. ok. Adding immutable helps. I'm still a bit confused tho,
The key is that the argument to mixin() must be known at compile-time. When the compiler reaches a mixin(...), it looks at the argument to mixin and tries to evaluate it at compile-time, which may or may not be successful.
 because this will not compile:

 string input2 = "int y;";
 mixin(input2);
"string input2" is a run-time variable. When the compiler sees "mixin(input2)" it tries to evaluate the expression "input2" at compile-time. When it does that, it notices that input2 is mutable (ie, What if in between those two lines there was: "if(args.length > 3) input2 = someOtherString"?). Since the value can change at run-time, the compiler doesn't know at compile-time what the value will be. So it can't mix it in. True, in this particular case it could figure it out, but not in the general case, so it doesn't bother.
 But this will compile:

 immutable string input2 = "int y;";
 mixin(input2);
The compiler sees "mixin(input2)". It tries to evaluate the expression "input2" at compile-time. It sees that "input2" is immutable so it goes "Ah ha! That's *never* going to change, so I know exactly what the value is always going to be, so I can just plop it right in." Doing "enum input2" would also work for the same reason.
 And this too will compile:

 string returnString(string input)
 {
    return input;
 }

 mixin(returnString("int y;"));
The compiler reaches the mixin and tries to evaluate "returnString("int y;")" at compile-time. Thanks to CTFE, it's able to, so this works.
Aug 05 2010