Jump to page: 1 2
Thread overview
comparing pointers passed to and returned from funcs
Mar 01, 2011
spir
Mar 01, 2011
bearophile
Mar 01, 2011
bearophile
Mar 01, 2011
bearophile
Mar 02, 2011
spir
Mar 01, 2011
Bekenn
Mar 02, 2011
bearophile
Mar 02, 2011
Bekenn
Mar 02, 2011
bearophile
Mar 02, 2011
Bekenn
Mar 02, 2011
Bekenn
March 01, 2011
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

March 01, 2011
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
		push	EAX
		mov	CL,8[ESP]
		mov	[EAX],CL
		pop	ECX
		ret	4

_D4test3notFPS4test3FooZPS4test3Foo	comdat
L0:		push	EAX
		mov	ECX,offset FLAT:_D20TypeInfo_PS4test3Foo6__initZ
		push	EAX
		push	EBX
		push	1
		push	ECX
		call	near ptr __d_newarrayT
		add	ESP,8
		mov	EAX,EDX
		push	1
		call	near ptr _D4test3Foo6__ctorMFNcbZS4test3Foo
		cmp	EAX,8[ESP]
		jne	L3D
		mov	EDX,offset FLAT:_D20TypeInfo_PS4test3Foo6__initZ
		push	1
		push	EDX
		call	near ptr __d_newarrayT
		add	ESP,8
		mov	EAX,EDX
		push	0
		call	near ptr _D4test3Foo6__ctorMFNcbZS4test3Foo
		jmp short	L56
L3D:		mov	EBX,offset FLAT:_D20TypeInfo_PS4test3Foo6__initZ
		push	1
		push	EBX
		call	near ptr __d_newarrayT
		add	ESP,8
		mov	EAX,EDX
		push	1
		call	near ptr _D4test3Foo6__ctorMFNcbZS4test3Foo
L56:		pop	EBX
		add	ESP,8
		ret

__Dmain	comdat
L0:		push	EAX
		mov	EAX,offset FLAT:_D20TypeInfo_PS4test3Foo6__initZ
		push	EBX
		push	ESI
		push	1
		push	1
		push	EAX
		call	near ptr __d_newarrayT
		add	ESP,8
		mov	EAX,EDX
		call	near ptr _D4test3Foo6__ctorMFNcbZS4test3Foo
		mov	ECX,offset FLAT:_DATA
		push	EAX
		push	ECX
		call	near ptr _printf
		mov	EDX,offset FLAT:_D20TypeInfo_PS4test3Foo6__initZ
		push	0
		push	1
		push	EDX
		call	near ptr __d_newarrayT
		add	ESP,8
		mov	EAX,EDX
		call	near ptr _D4test3Foo6__ctorMFNcbZS4test3Foo
		mov	EBX,offset FLAT:_DATA
		push	EAX
		push	EBX
		call	near ptr _printf
		mov	ESI,offset FLAT:_D20TypeInfo_PS4test3Foo6__initZ
		push	1
		push	1
		push	ESI
		call	near ptr __d_newarrayT
		add	ESP,8
		mov	EAX,EDX
		call	near ptr _D4test3Foo6__ctorMFNcbZS4test3Foo
		call	near ptr _D4test3notFPS4test3FooZPS4test3Foo
		push	EAX
		push	EBX
		call	near ptr _printf
		push	1
		push	1
		push	ESI
		call	near ptr __d_newarrayT
		add	ESP,8
		mov	EAX,EDX
		call	near ptr _D4test3Foo6__ctorMFNcbZS4test3Foo
		call	near ptr _D4test3notFPS4test3FooZPS4test3Foo
		call	near ptr _D4test3notFPS4test3FooZPS4test3Foo
		push	EAX
		push	EBX
		call	near ptr _printf
		add	ESP,020h
		xor	EAX,EAX
		pop	ESI
		pop	EBX
		pop	ECX
		ret


My suspect is confirmed, DMD is acting as with enum associative arrays. This is a compiler bug. DMD has to act correctly and not create a struct every time, or it has to give a compile-time error. Not this mess.

Bye,
bearophile
March 01, 2011
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
March 01, 2011
http://d.puremagic.com/issues/show_bug.cgi?id=5678
March 01, 2011
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.
March 02, 2011
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
March 02, 2011
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...
March 02, 2011
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.

Bye,
bearophile
March 02, 2011
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...
March 02, 2011
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;
« First   ‹ Prev
1 2