Re: Pretty fields string

2012-02-29 Thread Andrej Mitrovic
On 2/29/12, Andrej Mitrovic  wrote:
> Just noticed it doesn't work ok if there's a nested template
> declaration in a struct. It would say "Error: cannot resolve type for
> t.temp(T)".

Correction: it was the unittest block that was problematic. I've filed
it http://d.puremagic.com/issues/show_bug.cgi?id=7613


Re: Pretty fields string

2012-02-29 Thread Andrej Mitrovic
On 2/29/12, Philippe Sigaud  wrote:
> Nice. What does it give for:
>
> - function overloads (PITA that)?
> - type aliase (alias int Int;)?
> - function aliases or member aliases?
> - inner templates (struct template, etc, not pure template as these are not
> allowed in a struct)?
> - unittests inside the structs?
>

Well I was mainly interested in printing fields that take memory in a
struct/class instance, not functions or other things. :)

Just noticed it doesn't work ok if there's a nested template
declaration in a struct. It would say "Error: cannot resolve type for
t.temp(T)".

Then I've tried using a static if + __traits(compiles) to work around
it (and even is(typeof)), and before you know it..
Assertion failure: 'type' on line 6695 in file 'expression.c'

lol. :p


Re: Pretty fields string

2012-02-29 Thread Andrej Mitrovic
On 2/29/12, Jacob Carlborg  wrote:
> Seems like what I have in my serialization library Orange:

Sweet. I was gonna take a look at Orange for just this purpose. Thanks.


Re: Pretty fields string

2012-02-29 Thread Jacob Carlborg

On 2012-02-29 10:58, Andrej Mitrovic wrote:

I've done this a couple of times before but I always had issues, e.g.
functions and property calls would be mixed in. But I think I have a
good go-to function now:

import std.algorithm;
import std.conv;
import std.string;
import std.stdio;
import std.range;

struct Foo
{
 int one = 1;
 @property int test() { return 1; }
 int three = 3;
 string[string] aa;
 string toString() { return prettyFieldsString(this); }
}

string prettyFieldsString(T)(T t)
 if (is(T == struct) || is(T == class))
{
 Appender!string result;
 Appender!(string[]) fields;
 Appender!(string[]) values;

 foreach (member; __traits(allMembers, T))
 {
 mixin("
 static if (!is( FunctionTypeOf!(t." ~ member ~ ") ))
 {
 static if (member != " ~ `"toString"` ~ ")
 {
 fields.put(member);
 values.put(to!string(__traits(getMember, t, " ~ `"` ~
member ~ `"` ~ ")));
 }
 }
 ");
 }

 size_t spaceLen = 1;
 foreach (field; fields.data)  // should use reduce!() here..
 spaceLen = max(spaceLen, field.length);

 alias std.array.replicate replicate;
 string spaceString = replicate(" ", spaceLen);

 foreach (field, value; lockstep(fields.data, values.data))
 result.put(format("%s: %s%s\n", field, replicate(" ", spaceLen
- field.length), value));

 return result.data;
}

void main()
{
 Foo foo;
 foo.aa["foo"] = "bar";
 writeln(foo);
}

Sample output: http://paste.pocoo.org/show/558492/

I've had to put everything into one foreach loop since there are still
some CTFE bugs I run into. I also had to add a check against toString,
otherwise I get an infinite loop in the toString() call.

Anyway, feel free to use/improve this function.


Seems like what I have in my serialization library Orange:

https://github.com/jacob-carlborg/orange/blob/master/orange/util/Reflection.d

"fieldsOf" and "getValueOfField". These work only on instance variables 
and don't care if the variable is public or not.


--
/Jacob Carlborg


Re: Pretty fields string

2012-02-29 Thread Philippe Sigaud
> I've done this a couple of times before but I always had issues, e.g.
> functions and property calls would be mixed in. But I think I have a
> good go-to function now:

Nice. What does it give for:

- function overloads (PITA that)?
- type aliase (alias int Int;)?
- function aliases or member aliases?
- inner templates (struct template, etc, not pure template as these are not
allowed in a struct)?
- unittests inside the structs?


Re: Pretty fields string

2012-02-29 Thread Andrej Mitrovic
Just noticed there's an std.traits import missing. I hate how D
silently ignores that FunctionTypeOf is left undefined.


Pretty fields string

2012-02-29 Thread Andrej Mitrovic
I've done this a couple of times before but I always had issues, e.g.
functions and property calls would be mixed in. But I think I have a
good go-to function now:

import std.algorithm;
import std.conv;
import std.string;
import std.stdio;
import std.range;

struct Foo
{
int one = 1;
@property int test() { return 1; }
int three = 3;
string[string] aa;
string toString() { return prettyFieldsString(this); }
}

string prettyFieldsString(T)(T t)
if (is(T == struct) || is(T == class))
{
Appender!string result;
Appender!(string[]) fields;
Appender!(string[]) values;

foreach (member; __traits(allMembers, T))
{
mixin("
static if (!is( FunctionTypeOf!(t." ~ member ~ ") ))
{
static if (member != " ~ `"toString"` ~ ")
{
fields.put(member);
values.put(to!string(__traits(getMember, t, " ~ `"` ~
member ~ `"` ~ ")));
}
}
");
}

size_t spaceLen = 1;
foreach (field; fields.data)  // should use reduce!() here..
spaceLen = max(spaceLen, field.length);

alias std.array.replicate replicate;
string spaceString = replicate(" ", spaceLen);

foreach (field, value; lockstep(fields.data, values.data))
result.put(format("%s: %s%s\n", field, replicate(" ", spaceLen
- field.length), value));

return result.data;
}

void main()
{
Foo foo;
foo.aa["foo"] = "bar";
writeln(foo);
}

Sample output: http://paste.pocoo.org/show/558492/

I've had to put everything into one foreach loop since there are still
some CTFE bugs I run into. I also had to add a check against toString,
otherwise I get an infinite loop in the toString() call.

Anyway, feel free to use/improve this function.