digitalmars.D.learn - comparing pointers passed to and returned from funcs
- spir (48/48) Mar 01 2011 Hello,
- bearophile (123/133) Mar 01 2011 Reduced program (and Walter thinks that avoiding printf-related bugs is ...
- bearophile (23/23) Mar 01 2011 This seems to work:
- bearophile (1/1) Mar 01 2011 http://d.puremagic.com/issues/show_bug.cgi?id=5678
- Steven Schveighoffer (29/30) Mar 02 2011 I think there is a general bug where any time the compiler uses an enum,...
- spir (15/43) Mar 02 2011 Thank you Steven & Bearophile. This solves my problem.
- Bekenn (2/3) Mar 01 2011 I'd remove those parens; you don't want people modifying TRUE or FALSE.
- bearophile (4/5) Mar 01 2011 Please, show me working code that implements your idea :-)
- Bekenn (2/5) Mar 01 2011 Touche. I'll have to test that out once I get back from work...
- bearophile (4/5) Mar 01 2011 Sorry for that answer of mine, we are here to learn and cooperate, not t...
- Bekenn (2/5) Mar 01 2011 Hey, no problem; I thought it was funny...
- Bekenn (6/11) Mar 01 2011 Here you go; I only changed the one line. Compiles and works just fine
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
Mar 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
Mar 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
Mar 01 2011
http://d.puremagic.com/issues/show_bug.cgi?id=5678
Mar 01 2011
On Tue, 01 Mar 2011 18:11:00 -0500, bearophile <bearophileHUGS lycos.com> wrote:http://d.puremagic.com/issues/show_bug.cgi?id=5678I 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
Mar 02 2011
On 03/02/2011 02:24 PM, Steven Schveighoffer wrote:On Tue, 01 Mar 2011 18:11:00 -0500, bearophile <bearophileHUGS lycos.com> wrote: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.comhttp://d.puremagic.com/issues/show_bug.cgi?id=5678I 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.
Mar 02 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.
Mar 01 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
Mar 01 2011
On 3/1/11 4:12 PM, bearophile wrote:Bekenn:Touche. I'll have to test that out once I get back from work...I'd remove those parens; you don't want people modifying TRUE or FALSE.Please, show me working code that implements your idea :-)
Mar 01 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
Mar 01 2011
On 3/1/11 5:31 PM, bearophile wrote:Bekenn:Hey, no problem; I thought it was funny...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.
Mar 01 2011
On 3/1/2011 4:12 PM, bearophile wrote:Bekenn: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;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
Mar 01 2011