Re: comparing pointers passed to and returned from funcs

2011-03-02 Thread Steven Schveighoffer
On Tue, 01 Mar 2011 18:11:00 -0500, bearophile bearophileh...@lycos.com  
wrote:



http://d.puremagic.com/issues/show_bug.cgi?id=5678


I think there is a general bug where any time the compiler uses an enum,  
it simply replaces the expression declared for the enum.


So basically

enum TRUE = new DElement(true);

void main()
{
   auto delem1 = TRUE;
   auto delem2 = TRUE;
   assert(delem1 is delem2); // fails
}

gets morphed into this:

void main()
{
   auto delem1 = new Delement(true);
   auto delem2 = new Delement(true);
   assert(delem1 is delem2); // fails
}

Obviously this works great when the enum is a value type or a string  
literal (which is created at compile time).  However, it is not so great  
for things like AAs, array literals, objects, or structs.


I think there are a few of these bugs in bugzilla, and there should be at  
least a tracker, and if not, they should all be combined.  This is a  
serious problem in D, and really creates havoc (both performance-wise and  
semantically).  I don't anticipate there is an easy fix.


Essentially, I'd say enum is completely useless except for builtin types  
and strings.


-Steve


Re: comparing pointers passed to and returned from funcs

2011-03-02 Thread spir

On 03/02/2011 02:24 PM, Steven Schveighoffer wrote:

On Tue, 01 Mar 2011 18:11:00 -0500, bearophile bearophileh...@lycos.com wrote:


http://d.puremagic.com/issues/show_bug.cgi?id=5678


I think there is a general bug where any time the compiler uses an enum, it
simply replaces the expression declared for the enum.

So basically

enum TRUE = new DElement(true);

void main()
{
auto delem1 = TRUE;
auto delem2 = TRUE;
assert(delem1 is delem2); // fails
}

gets morphed into this:

void main()
{
auto delem1 = new Delement(true);
auto delem2 = new Delement(true);
assert(delem1 is delem2); // fails
}

Obviously this works great when the enum is a value type or a string literal
(which is created at compile time). However, it is not so great for things like
AAs, array literals, objects, or structs.

I think there are a few of these bugs in bugzilla, and there should be at least
a tracker, and if not, they should all be combined. This is a serious problem
in D, and really creates havoc (both performance-wise and semantically). I
don't anticipate there is an easy fix.

Essentially, I'd say enum is completely useless except for builtin types and
strings.


Thank you Steven  Bearophile. This solves my problem.
I first did not get Bearophile's answer about run/compile-time constants (I 
mean enums). I thought the time when they are created is irrelevant, isn't it?
Anyway, placing the constant defs inside a module's static this () {...} 
block does what I mean. It does, in fact, ensure *unicity*. But I don't really 
understand the relation with Steven's explanation above: why/how does the fact 
that a constant's def is inside static this() prevent the compiler to rewrite 
it like shown above? Also, I basically don't understand why dmd does that 
anyway: it's obviously un-ecological ;-)


Denis
--
_
vita es estrany
spir.wikidot.com



comparing pointers passed to and returned from funcs

2011-03-01 Thread spir

Hello,

It seems to be the kind of stupid issue that will make you laugh about me. But 
I cannot grasp and want to move forward anyway; so, let us be bold and take the 
risk ;-)


I'm modeling a little dynamic language. Elements (values, objects) are pointers 
to structs (actually tagged unions) allocated on the heap. I have a problem in 
passing and returning those pointers to and from primitive procedures.


Precisely, unlike in D, Logical (boolean) operations only accept Logical 
elements true/false (called TRUE/FALSE on implementation side for obvious reason):

enum TRUE = new DElement(true);
enum FALSE = new DElement(false);

 So, I thought I could write those operations by comparing pointers directly, 
eg:
Element not (Element operand) {
// checks type
operand.checkLogical()
return (operand == TRUE) ? FALSE : TRUE;
}
...
assert ( not(TRUE) == FALSE );

This fails! It even fails doubly...
When I call not(TRUE), TRUE (the pointer) inside the func is not equal to the 
global constant. Thus, not always returns FALSE. And in fact this is also 
wrong, because I have the same problem on the return value as well: the FALSE 
returned is not equal to the global FALSE.


But the pointed structs are ok. Each one holds a D boolean of the correct value 
(a member called 'logical'). Thus, the following succeeds:


Element not (Element operand) {
// checks type  returns the 'logical' member
auto log = operand.checkLogical();
return (log) ? FALSE : TRUE;
}
...
assert ( not(TRUE).logical == false );

Here, I operate on the structs instead of on the pointers, both to perform the 
operation and in the assert. What I understand is: all happens like if D would 
copy the pointed structs on parameter passing and on return. I thought D would 
only copy the pointers (in both directions), which would let me compare said 
pointers directly.

What do I miss?

It is not a serious problem since the workaround is easy and not very costly. 
But I wish to understand why I cannot operate on constant 'identity'. As said 
above, this must a trivial issue I simply cannot guess...


Thank you,
Denis
--
_
vita es estrany
spir.wikidot.com



Re: comparing pointers passed to and returned from funcs

2011-03-01 Thread bearophile
spir:

 It seems to be the kind of stupid issue that will make you laugh about me. 
 But 
 I cannot grasp and want to move forward anyway; so, let us be bold and take 
 the 
 risk ;-)

Be bold. Understanding things is much more important. I've being wrong hundreds 
of times on D newsgroups, but I'm getting better.

 This fails! It even fails doubly...

Reduced program (and Walter thinks that avoiding printf-related bugs is not 
important. He's wrong. I use printf often enough in D):


import core.stdc.stdio: printf;
struct Foo {
bool b;
this(bool b_) { this.b = b_; }
}
enum Foo* TRUE = new Foo(true);
enum Foo* FALSE = new Foo(false);
Foo* not(Foo* op) {
return (op == TRUE) ? FALSE : TRUE;
}
void main() {
//assert(not(TRUE) == FALSE);
printf(%x\n, TRUE);
printf(%x\n, FALSE);
printf(%x\n, not(TRUE));
printf(%x\n, not(not(TRUE)));
}


 Here, I operate on the structs instead of on the pointers, both to perform 
 the 
 operation and in the assert. What I understand is: all happens like if D 
 would 
 copy the pointed structs on parameter passing and on return. I thought D 
 would 
 only copy the pointers (in both directions), which would let me compare said 
 pointers directly.
 What do I miss?

DMD is not copying the structs, just pointers.

I think it's happening something like with enum associative arrays. Pointers 
are run-time things. You are asking for a new at compile-time. This is the asm 
produced by that program (-O -release):


_D4test3Foo6__ctorMFNcbZS4test3Foo  comdat
pushEAX
mov CL,8[ESP]
mov [EAX],CL
pop ECX
ret 4

_D4test3notFPS4test3FooZPS4test3Foo comdat
L0: pushEAX
mov ECX,offset FLAT:_D20TypeInfo_PS4test3Foo6__initZ
pushEAX
pushEBX
push1
pushECX
callnear ptr __d_newarrayT
add ESP,8
mov EAX,EDX
push1
callnear ptr _D4test3Foo6__ctorMFNcbZS4test3Foo
cmp EAX,8[ESP]
jne L3D
mov EDX,offset FLAT:_D20TypeInfo_PS4test3Foo6__initZ
push1
pushEDX
callnear ptr __d_newarrayT
add ESP,8
mov EAX,EDX
push0
callnear ptr _D4test3Foo6__ctorMFNcbZS4test3Foo
jmp short   L56
L3D:mov EBX,offset FLAT:_D20TypeInfo_PS4test3Foo6__initZ
push1
pushEBX
callnear ptr __d_newarrayT
add ESP,8
mov EAX,EDX
push1
callnear ptr _D4test3Foo6__ctorMFNcbZS4test3Foo
L56:pop EBX
add ESP,8
ret

__Dmain comdat
L0: pushEAX
mov EAX,offset FLAT:_D20TypeInfo_PS4test3Foo6__initZ
pushEBX
pushESI
push1
push1
pushEAX
callnear ptr __d_newarrayT
add ESP,8
mov EAX,EDX
callnear ptr _D4test3Foo6__ctorMFNcbZS4test3Foo
mov ECX,offset FLAT:_DATA
pushEAX
pushECX
callnear ptr _printf
mov EDX,offset FLAT:_D20TypeInfo_PS4test3Foo6__initZ
push0
push1
pushEDX
callnear ptr __d_newarrayT
add ESP,8
mov EAX,EDX
callnear ptr _D4test3Foo6__ctorMFNcbZS4test3Foo
mov EBX,offset FLAT:_DATA
pushEAX
pushEBX
callnear ptr _printf
mov ESI,offset FLAT:_D20TypeInfo_PS4test3Foo6__initZ
push1
push1
pushESI
callnear ptr __d_newarrayT
add ESP,8
mov EAX,EDX
callnear ptr _D4test3Foo6__ctorMFNcbZS4test3Foo
callnear ptr _D4test3notFPS4test3FooZPS4test3Foo
pushEAX
pushEBX
callnear ptr _printf
push1
push1
pushESI
callnear ptr __d_newarrayT
add ESP,8
mov EAX,EDX
callnear ptr _D4test3Foo6__ctorMFNcbZS4test3Foo
callnear ptr _D4test3notFPS4test3FooZPS4test3Foo
callnear ptr _D4test3notFPS4test3FooZPS4test3Foo
pushEAX
pushEBX
call 

Re: comparing pointers passed to and returned from funcs

2011-03-01 Thread bearophile
This seems to work:

import core.stdc.stdio: printf;
struct Foo {
bool b;
this(bool b_) { this.b = b_; }
}
const(Foo)* TRUE, FALSE;
static this() {
TRUE = new const(Foo)(true);
FALSE = new const(Foo)(false);
}
const(Foo)* not(const(Foo)* op) {
return (op == TRUE) ? FALSE : TRUE;
}
void main() {
assert(not(TRUE) == FALSE);
printf(%x\n, TRUE);
printf(%x\n, FALSE);
printf(%x\n, not(TRUE));
printf(%x\n, not(not(TRUE)));
}

Bye,
bearophile


Re: comparing pointers passed to and returned from funcs

2011-03-01 Thread Bekenn

On 3/1/11 3:00 PM, bearophile wrote:

const(Foo)* TRUE, FALSE;


I'd remove those parens; you don't want people modifying TRUE or FALSE.


Re: comparing pointers passed to and returned from funcs

2011-03-01 Thread bearophile
Bekenn:

 I'd remove those parens; you don't want people modifying TRUE or FALSE.

Please, show me working code that implements your idea :-)

Bye,
bearophile


Re: comparing pointers passed to and returned from funcs

2011-03-01 Thread Bekenn

On 3/1/11 4:12 PM, bearophile wrote:

Bekenn:


I'd remove those parens; you don't want people modifying TRUE or FALSE.


Please, show me working code that implements your idea :-)


Touche.  I'll have to test that out once I get back from work...


Re: comparing pointers passed to and returned from funcs

2011-03-01 Thread Bekenn

On 3/1/11 5:31 PM, bearophile wrote:

Bekenn:


Touche.  I'll have to test that out once I get back from work...


Sorry for that answer of mine, we are here to learn and cooperate, not to fight 
:-) It's just I sometimes have problems with const things in D, and sometimes 
DMD has problems with const things.


Hey, no problem; I thought it was funny...


Re: comparing pointers passed to and returned from funcs

2011-03-01 Thread Bekenn

On 3/1/2011 4:12 PM, bearophile wrote:

Bekenn:


I'd remove those parens; you don't want people modifying TRUE or FALSE.


Please, show me working code that implements your idea :-)

Bye,
bearophile


Here you go; I only changed the one line.  Compiles and works just fine 
in dmd 2.051.


const Foo* TRUE, FALSE;
instead of
const(Foo)* TRUE, FALSE;