Re: comparing pointers passed to and returned from funcs
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
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
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
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
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
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
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
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
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
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;