www.digitalmars.com         C & C++   DMDScript  

D - some questions concerning D specs

reply "Pavel \"EvilOne\" Minayev" <evilone omen.ru> writes:
There are some things there that just aren't
clear enough...


Complex arrays. Judging by the specs, int[]* is a
pointer to array, int*[] is an array of pointers.
Is int[]*[] a legal way to declare an array of
pointers to arrays? Is int*[]* a legal way to
declare a pointer to array of pointers?


Static attribute. Are static local variables
supported?


Array slicing. What happens when I use the form
a[x..y], and x is greater than y?


Class model. It says that for each class XXXX, an
instance of Class is created, named ClassXXXX. What
is Class (RTTI, I believe), what functionality it
provides? If I have a reference to object, how
do I get the appropriate Class object? Is it possible
to construct an object without knowing its type
at compile-time, via its Class (like in Delphi)?


Distinguishing between . and ->
It is stated that there is no need for -> in D, since
it's clear to the compiler whether we access fields
directly or through pointer. But specification contains
the following definition:

    PostfixExpression:
        PrimaryExpression
    	PostfixExpression . Identifier
    	PostfixExpression -> Identifier     (!?)

A mistake?



Methods of base class. How do I access them? I believe
that super.method form is used to call methods of super
class. But how to call a method of an arbitrary class
in the hierarchy - super(class).method?


Static methods. Can they be overridden? Can they be
called in the same manner as non-static ones?


Modules. According to specification, "Modules have a one-
to-one correspondence with source files. The module name
is the file name with the path and extension stripped off."
Does this mean that module names are case-insensitive on
Windows and case-sensitive on *nix? If not, how is it
achieved?


... to be continued ... =)
Nov 07 2001
next sibling parent reply "Walter" <walter digitalmars.com> writes:
"Pavel "EvilOne" Minayev" <evilone omen.ru> wrote in message
news:9sb0c1$ceq$1 digitaldaemon.com...
 Complex arrays. Judging by the specs, int[]* is a
 pointer to array, int*[] is an array of pointers.
 Is int[]*[] a legal way to declare an array of
 pointers to arrays? Is int*[]* a legal way to
 declare a pointer to array of pointers?

Yes, yes!
 Static attribute. Are static local variables
 supported?

Yes.
 Array slicing. What happens when I use the form
 a[x..y], and x is greater than y?

If you have array bounds checking turned on, an array bounds exception gets thrown.
 Class model. It says that for each class XXXX, an
 instance of Class is created, named ClassXXXX. What
 is Class (RTTI, I believe), what functionality it
 provides?

A way to examine the type and offset of each member, access to the finalizer, and (in the future) access to any classes it depends on.
 If I have a reference to object, how
 do I get the appropriate Class object?

There's a member function to get it. Or a property. I can't decide which <g>.
 Is it possible
 to construct an object without knowing its type
 at compile-time, via its Class (like in Delphi)?

That sounds like a good idea.
 Distinguishing between . and ->
 It is stated that there is no need for -> in D, since
 it's clear to the compiler whether we access fields
 directly or through pointer. But specification contains
 the following definition:

     PostfixExpression:
         PrimaryExpression
     PostfixExpression . Identifier
     PostfixExpression -> Identifier     (!?)

 A mistake?

Yes.
 Methods of base class. How do I access them? I believe
 that super.method form is used to call methods of super
 class. But how to call a method of an arbitrary class
 in the hierarchy - super(class).method?

If class B is derived from A, you can also use: B b; b.A.foo();
 Static methods. Can they be overridden? Can they be
 called in the same manner as non-static ones?

Yes, yes.
 Modules. According to specification, "Modules have a one-
 to-one correspondence with source files. The module name
 is the file name with the path and extension stripped off."
 Does this mean that module names are case-insensitive on
 Windows and case-sensitive on *nix? If not, how is it
 achieved?

Module names are case sensitive. On windows, this means that you cannot have two modules that differ only in case. While not elegant, I doubt it will be a significant problem in practice.
 ... to be continued ... =)

Great questions!
Nov 08 2001
parent reply "Pavel \"EvilOne\" Minayev" <evilone omen.ru> writes:
"Walter" <walter digitalmars.com> wrote in message
news:9sdc1v$2167$1 digitaldaemon.com...

 Array slicing. What happens when I use the form
 a[x..y], and x is greater than y?

If you have array bounds checking turned on, an array bounds exception

 thrown.

And if not? I mean, since the copying code will, in general, be the loop (or am I wrong?), it simply won't do anything.
 Class model. It says that for each class XXXX, an
 instance of Class is created, named ClassXXXX. What
 is Class (RTTI, I believe), what functionality it
 provides?

A way to examine the type and offset of each member, access to the finalizer, and (in the future) access to any classes it depends on.

Ability to call methods of class by their name (a la IDispatch::Invoke)? Also, if those Class objects are unused, will they still be there (thus cluttering the program with unnecessary info like class and method names)?
 If I have a reference to object, how
 do I get the appropriate Class object?

There's a member function to get it. Or a property. I can't decide which <g>.

object.class, probably?
 Is it possible
 to construct an object without knowing its type
 at compile-time, via its Class (like in Delphi)?

That sounds like a good idea.

This, however, involves things like virtual constructors.
 Methods of base class. How do I access them? I believe
 that super.method form is used to call methods of super
 class. But how to call a method of an arbitrary class
 in the hierarchy - super(class).method?

If class B is derived from A, you can also use: B b; b.A.foo();

So, from withing B, I'd simply write: A.foo();
 Static methods. Can they be overridden? Can they be
 called in the same manner as non-static ones?

Yes, yes.

So the following: class A { static void B() { ... } } A a; A::B(); a.B(); // the same? is legal? If it is, will B() be aware that it is called in a different way?
Nov 08 2001
next sibling parent Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Pavel \"EvilOne\" Minayev wrote:

 And if not? I mean, since the copying code will, in general, be
 the loop (or am I wrong?), it simply won't do anything.

The copying code isn't the problem. It's the allocation code. Presumably, the compiler views all indices as unsigned values. Similarly, the size parameter in the compiler equivalent of malloc() is unsigned. So take 1-3, with both numbers viewed as (perhaps) unsigned 32 bit ints, what do you get? IIRC, something near 4 billion elements. So the compiler tries to allocate 4 billion elements * x bytes per element = many many many bytes. In most architectures, this ends up throwing an OutOfMemory exception. But in some...where you have access to multiple GB of virtual memory...we consume an unbelievable quantity of memory. :( -- The Villagers are Online! villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ]
Nov 08 2001
prev sibling parent reply "Walter" <walter digitalmars.com> writes:
"Pavel "EvilOne" Minayev" <evilone omen.ru> wrote in message
news:9sdfh6$253c$1 digitaldaemon.com...
 "Walter" <walter digitalmars.com> wrote in message
 news:9sdc1v$2167$1 digitaldaemon.com...
 Array slicing. What happens when I use the form
 a[x..y], and x is greater than y?


 thrown.

the loop (or am I wrong?), it simply won't do anything.

In general, if an exception will be thrown if checking is turned on, undefined behavior will result if checking is turned off.
 Class model. It says that for each class XXXX, an
 instance of Class is created, named ClassXXXX. What
 is Class (RTTI, I believe), what functionality it
 provides?

finalizer, and (in the future) access to any classes it depends on.


That's an open possibility.
 Also, if those Class objects are unused, will they still be there
 (thus cluttering the program with unnecessary info like class and
 method names)?

Yes.
 If I have a reference to object, how
 do I get the appropriate Class object?

<g>.


Or .classinfo. Something like that.
 Methods of base class. How do I access them? I believe
 that super.method form is used to call methods of super
 class. But how to call a method of an arbitrary class
 in the hierarchy - super(class).method?

B b; b.A.foo();

A.foo();

Yes.
 Static methods. Can they be overridden? Can they be
 called in the same manner as non-static ones?


class A { static void B() { ... } } A a; A::B(); a.B(); // the same?

Yes.
 is legal? If it is, will B() be aware that it is called in a
 different way?

Yes, yes.
Nov 09 2001
parent reply "Sean L. Palmer" <spalmer iname.com> writes:
 So the following:
     class A
     {
         static void B() { ... }
     }
     A a;
     A::B();
     a.B();    // the same?

Yes.

Are you saying that D supports use of the :: operator? Sean
Nov 09 2001
parent "Walter" <walter digitalmars.com> writes:
"Sean L. Palmer" <spalmer iname.com> wrote in message
news:9sh8nm$237g$1 digitaldaemon.com...
 So the following:
     class A
     {
         static void B() { ... }
     }
     A a;
     A::B();
     a.B();    // the same?

Yes.

Are you saying that D supports use of the :: operator? Sean

No, sorry, A::B() is not allowed. Use A.B()
Nov 09 2001
prev sibling next sibling parent reply "Pavel \"EvilOne\" Minayev" <evilone omen.ru> writes:
 ... to be continued ... =)

Here are some more: What is the default attribute for class members (private/protected/public)? Suppose I have the following declaration: int* x, y; Is y an int or a pointer to int? Once again, suppose there's a piece of code like that: void X() { ... } class B { void Y() { ... } } class C { void Y() { ... } } class A: B { void X() { ... } void Y() { C B; B.Y(); X(); } } Question #1: how do I call the global X() from A.Y() (since simply typing X() would invoke A.X())? Question #2: how do I access method Y() of class B from A.Y() (since B.Y() will invoke method Y() of object C)? ... to be continued ... =)
Nov 08 2001
next sibling parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Pavel \"EvilOne\" Minayev wrote:

 Once again, suppose there's a piece of code like that:

     void X() { ... }

     class B
     {
         void Y() { ... }
     }

     class C
     {
         void Y() { ... }
     }

     class A: B
     {
         void X() { ... }

         void Y()
         {
             C B;
             B.Y();
             X();
         }
     }

 Question #1: how do I call the global X() from A.Y() (since
 simply typing X() would invoke A.X())?

Since you know the module name, why not: <module>.X();
 Question #2: how do I access method Y() of class B from A.Y()
 (since B.Y() will invoke method Y() of object C)?

this.B.Y() This is just like in C++: class foo { int a; public: foo(int a) { this->a = a; }; } -- The Villagers are Online! villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ]
Nov 08 2001
parent reply "Pavel \"EvilOne\" Minayev" <evilone omen.ru> writes:
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:3BEAE349.BCF30DD7 deming-os.org...

 Question #1: how do I call the global X() from A.Y() (since
 simply typing X() would invoke A.X())?

Since you know the module name, why not: <module>.X();

And what if there's a local variable or class property with the same name as module?
 Question #2: how do I access method Y() of class B from A.Y()
 (since B.Y() will invoke method Y() of object C)?

this.B.Y() This is just like in C++: class foo { int a; public: foo(int a) { this->a = a; }; }

And what if B is not a local, but a class member? This way, this.B.Y() will still call the wrong method... What I'm in general trying to say is that I hate when there are some ambiguities. Like in C++, if I have a class Parser, I can declare objects as "Parser p". However if I have a variable called Parser, I have to use "class Parser p". The same case is here. Wouldn't it be better to provide some completely distinct way to call module globals (no ideas) and methods of base class (I propose super(class).method)? Not only it would ease the life of programmers (especially if you are working with others' code... A.B - is A a class or a variable? with super(A).B it's much clearer), but also helped the compiler as well.
Nov 09 2001
next sibling parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Pavel \"EvilOne\" Minayev wrote:

 "Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
 news:3BEAE349.BCF30DD7 deming-os.org...

 Question #1: how do I call the global X() from A.Y() (since
 simply typing X() would invoke A.X())?

Since you know the module name, why not: <module>.X();

And what if there's a local variable or class property with the same name as module?

Frankly, then you are a bad programmer :) Seriously, though, I suppose you have a point. It might be good to explicitly define syntax for such a circumstance. Some possibilities for ways to access global module data as opposed to class variables: module <moduleName>.X() module.<moduleName>.X() global.<moduleName>.X() -- The Villagers are Online! http://villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ]
Nov 09 2001
parent "Pavel \"EvilOne\" Minayev" <evilone omen.ru> writes:
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:3BEBCCF3.ABEBCB5 deming-os.org...

 Frankly, then you are a bad programmer :)  Seriously, though, I suppose

Definitely. However, we shouldn't discriminate =)
 you have a point.  It might be good to explicitly define syntax for such
 a circumstance.  Some possibilities for ways to access global module
 data as opposed to class variables:

 module <moduleName>.X()
 module.<moduleName>.X()
 global.<moduleName>.X()

I thought about it as well - since we have "this" to refer to current class, why not have something that refers to current module? "global" seems just fine to me, what about the others?
Nov 09 2001
prev sibling parent "Walter" <walter digitalmars.com> writes:
"Pavel "EvilOne" Minayev" <evilone omen.ru> wrote in message
news:9sg5vh$scq$1 digitaldaemon.com...
 "Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
 news:3BEAE349.BCF30DD7 deming-os.org...

 Question #1: how do I call the global X() from A.Y() (since
 simply typing X() would invoke A.X())?

Since you know the module name, why not: <module>.X();

And what if there's a local variable or class property with the same name as module?
 Question #2: how do I access method Y() of class B from A.Y()
 (since B.Y() will invoke method Y() of object C)?

this.B.Y() This is just like in C++: class foo { int a; public: foo(int a) { this->a = a; }; }

And what if B is not a local, but a class member? This way, this.B.Y() will still call the wrong method... What I'm in general trying to say is that I hate when there are some ambiguities. Like in C++, if I have a class Parser, I can declare objects as "Parser p". However if I have a variable called Parser, I have to use "class Parser p". The same case is here. Wouldn't it be better to provide some completely distinct way to call module globals (no ideas) and methods of base class (I propose super(class).method)? Not only it would ease the life of programmers (especially if you are working with others' code... A.B - is A a class or a variable? with super(A).B it's much clearer), but also helped the compiler as well.

Hmm. It might be a good idea to use the "." as meaning "at the module level", as in: .B(); The problem, though, is the . is almost invisible. Maybe: module.B();
Nov 09 2001
prev sibling parent reply "Walter" <walter digitalmars.com> writes:
"Pavel "EvilOne" Minayev" <evilone omen.ru> wrote in message
news:9sdigb$2715$1 digitaldaemon.com...
 What is the default attribute for class members
 (private/protected/public)?

Public. I always thought that C++'s way just made for annoying extra typing when banging out quick code. A production quality class should always say it explicitly.
 Suppose I have the following declaration:
     int* x, y;
 Is y an int or a pointer to int?

An int. I didn't break away from C on that one. I can be persuaded otherwise.
 Once again, suppose there's a piece of code like that:
     void X() { ... }
     class B
     {
         void Y() { ... }
     }
     class C
     {
         void Y() { ... }
     }
     class A: B
     {
         void X() { ... }

         void Y()
         {
             C B;
             B.Y();
             X();
         }
     }

 Question #1: how do I call the global X() from A.Y() (since
 simply typing X() would invoke A.X())?

Prefix it with the module name. Assume the module name is foo: foo.X()
 Question #2: how do I access method Y() of class B from A.Y()
 (since B.Y() will invoke method Y() of object C)?

A.B.Y()
Nov 09 2001
next sibling parent reply "Pavel \"EvilOne\" Minayev" <evilone omen.ru> writes:
"Walter" <walter digitalmars.com> wrote in message
news:9sh1ca$1pn2$2 digitaldaemon.com...

 Suppose I have the following declaration:
     int* x, y;
 Is y an int or a pointer to int?

An int. I didn't break away from C on that one. I can be persuaded otherwise.

Yes, yes! Should we start collecting votes for a petition? =)
 Question #2: how do I access method Y() of class B from A.Y()
 (since B.Y() will invoke method Y() of object C)?

A.B.Y()

I mentioned it already, but... What if class A contains variable B? Will the above code do what we expect it to?
Nov 09 2001
parent reply "Walter" <walter digitalmars.com> writes:
"Pavel "EvilOne" Minayev" <evilone omen.ru> wrote in message
news:9sh2a9$1qsq$1 digitaldaemon.com...
 "Walter" <walter digitalmars.com> wrote in message
 news:9sh1ca$1pn2$2 digitaldaemon.com...
 Suppose I have the following declaration:
     int* x, y;
 Is y an int or a pointer to int?

otherwise.

Should we start collecting votes for a petition? =)

I'm more interested in compelling arguments (!)
 Question #2: how do I access method Y() of class B from A.Y()
 (since B.Y() will invoke method Y() of object C)?


What if class A contains variable B? Will the above code do what we expect it to?

A.super.Y()
Nov 09 2001
next sibling parent reply "Pavel \"EvilOne\" Minayev" <evilone omen.ru> writes:
"Walter" <walter digitalmars.com> wrote in message
news:9si4hs$2ved$3 digitaldaemon.com...

 What if class A contains variable B? Will the above code do
 what we expect it to?

A.super.Y()

This works if A is a direct successor of B. However, the example is simplified, but in general assume there are many other classes between A and B in the hierarchy. Now what? =)
Nov 09 2001
parent "Walter" <walter digitalmars.com> writes:
"Pavel "EvilOne" Minayev" <evilone omen.ru> wrote in message
news:9sik3l$7e8$1 digitaldaemon.com...
 "Walter" <walter digitalmars.com> wrote in message
 news:9si4hs$2ved$3 digitaldaemon.com...

 What if class A contains variable B? Will the above code do
 what we expect it to?

A.super.Y()

This works if A is a direct successor of B. However, the example is simplified, but in general assume there are many other classes between A and B in the hierarchy. Now what? =)

A.super.dee.duper.B() <g>
Nov 10 2001
prev sibling next sibling parent a <a b.c> writes:
Walter wrote:
 
 "Pavel "EvilOne" Minayev" <evilone omen.ru> wrote in message
 "Walter" <walter digitalmars.com> wrote in message
 Suppose I have the following declaration:
     int* x, y;
 Is y an int or a pointer to int?

otherwise.

Should we start collecting votes for a petition? =)

I'm more interested in compelling arguments (!)

How about I call my family in New Jersey? :-) Seriously though, in the above example you would think <type> <var1>, <var2>; where var1 and var2 are both of type. Anyone who is not "used" to C's interesting interpretation of this sort of declaration (and may who are used to it) will get burned. The syntax definite isn't too clean nor too popular to be tampered with. I'd try harder to argue, but it looks like others are doing a good job of convincing you. Dan
Nov 10 2001
prev sibling parent reply "Pavel \"EvilOne\" Minayev" <evilone omen.ru> writes:
"Walter" <walter digitalmars.com> wrote in message
news:9si4hs$2ved$3 digitaldaemon.com...

 I'm more interested in compelling arguments  (!)

Suppose we have the following code: int*[]* x, y; "Old" way: x is pointer to array of pointers, y is an array of pointers. The first asterisk applies to both, the second is applied only to x. Not only it's weird, but just try to define a _clear_ rule (say, for the specification) that strictly defines meaning of asterisk. New way: both are pointers to array of pointers. Anything that's on the left is part of the type and is applied to all variables on the line, no special cases and exceptions. I vote for the new one...
Nov 11 2001
next sibling parent reply "Roberto Mariottini" <rmariottini lycosmail.com> writes:
"Pavel "EvilOne" Minayev" <evilone omen.ru> wrote in
news:9slgrh$241h$1 digitaldaemon.com...
 "Walter" <walter digitalmars.com> wrote in message
 news:9si4hs$2ved$3 digitaldaemon.com...

 I'm more interested in compelling arguments  (!)

Suppose we have the following code: int*[]* x, y; "Old" way: x is pointer to array of pointers, y is an array of pointers. The first asterisk applies to both, the second is applied only to x. Not only it's weird, but just try to define a _clear_ rule (say, for the specification) that strictly defines meaning of asterisk. New way: both are pointers to array of pointers. Anything that's on the left is part of the type and is applied to all variables on the line, no special cases and exceptions. I vote for the new one...

PLEASE don't do that! Don't change the meaning while keeping the sintax! I think the ',' in declarations is useless, and error prone, so it's best to remove it. Write: int*[]* x; int*[]* y; And it works in C, C++, and D. Ciao
Nov 12 2001
parent "Pavel \"EvilOne\" Minayev" <evilone omen.ru> writes:
"Roberto Mariottini" <rmariottini lycosmail.com> wrote in message
news:9so8hl$rln$1 digitaldaemon.com...

 I think the ',' in declarations is useless, and error prone, so it's best

 remove it.

Never ever!
 Write:

 int*[]* x;
 int*[]* y;

 And it works in C, C++, and D.

First, it won't work in C/C++ since they don't support dynamic arrays. And if you are concerned about compatibility, you can write this way of course, but why forbid the other ways?
Nov 12 2001
prev sibling next sibling parent Roland <rv ronetech.com> writes:
me too

Roland


Pavel \"EvilOne\" Minayev a écrit :

 "Walter" <walter digitalmars.com> wrote in message
 news:9si4hs$2ved$3 digitaldaemon.com...

 I'm more interested in compelling arguments  (!)

Suppose we have the following code: int*[]* x, y; "Old" way: x is pointer to array of pointers, y is an array of pointers. The first asterisk applies to both, the second is applied only to x. Not only it's weird, but just try to define a _clear_ rule (say, for the specification) that strictly defines meaning of asterisk. New way: both are pointers to array of pointers. Anything that's on the left is part of the type and is applied to all variables on the line, no special cases and exceptions. I vote for the new one...

Nov 12 2001
prev sibling parent reply "Walter" <walter digitalmars.com> writes:
"Pavel "EvilOne" Minayev" <evilone omen.ru> wrote in message
news:9slgrh$241h$1 digitaldaemon.com...
 "Walter" <walter digitalmars.com> wrote in message
 news:9si4hs$2ved$3 digitaldaemon.com...

 I'm more interested in compelling arguments  (!)

Suppose we have the following code: int*[]* x, y; "Old" way: x is pointer to array of pointers, y is an array of pointers. The first asterisk applies to both, the second is applied only to x. Not only it's weird, but just try to define a _clear_ rule (say, for the specification) that strictly defines meaning of asterisk. New way: both are pointers to array of pointers. Anything that's on the left is part of the type and is applied to all variables on the line, no special cases and exceptions. I vote for the new one...

I think you're right.
Nov 29 2001
parent reply "Robert W. Cunningham" <rwc_2001 yahoo.com> writes:
Walter wrote:

 "Pavel "EvilOne" Minayev" <evilone omen.ru> wrote in message
 news:9slgrh$241h$1 digitaldaemon.com...
 "Walter" <walter digitalmars.com> wrote in message
 news:9si4hs$2ved$3 digitaldaemon.com...

 I'm more interested in compelling arguments  (!)

Suppose we have the following code: int*[]* x, y; "Old" way: x is pointer to array of pointers, y is an array of pointers. The first asterisk applies to both, the second is applied only to x. Not only it's weird, but just try to define a _clear_ rule (say, for the specification) that strictly defines meaning of asterisk. New way: both are pointers to array of pointers. Anything that's on the left is part of the type and is applied to all variables on the line, no special cases and exceptions. I vote for the new one...

I think you're right.

Seconded! You know, it seems like about half of the bugs mentioned in those PC-Lint ads descend from just this issue. Let's kill it dead in D! However, I'd like to make it even more stringent: "A single declaration can create variables of only a single type." Let's eliminate all the cousins of the above, such as: int*[]* x, y, *z; This should be an error! The "correct" form should require z to be on a separate line. Pretty please? -BobC
Nov 29 2001
next sibling parent reply Ben Cohen <bc skygate.co.uk> writes:
On Fri, 30 Nov 2001 04:31:11 +0000, Robert W. Cunningham wrote:

 Let's eliminate all the cousins of the above, such as:
 
      int*[]* x, y, *z;
 
 This should be an error!  The "correct" form should require z to be on a
 separate line.

Yes, I agree with this, for several reasons. It simplifies the language and makes reading the code easier. I think there would be less confusion with the C syntax. And you can rewrite the above declaration as: int*[] *x, y, *z; This is admittedly foolish, but certainly not implausible. It looks like x and z are of the same type when actually x and y are. (Unless you count the space as a delimiter, which isn't nice.)
Nov 30 2001
parent reply Roland <rv ronetech.com> writes:
      int*[]* x, y, *z;

 This should be an error!  The "correct" form should require z to be on a
 separate line.


Yes: pointers are types. so the '*' must be after the pointed type, NOT before the pointer name: int* pointer; <- correct int *pointer; <- NOT correct so int* p1,p2,p3; <- correct, all are pointers int *p1,p2,p3; <- NOT correct Roland
Nov 30 2001
parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Roland wrote:

 int* p1,p2,p3;    <- correct, all are pointers

 int *p1,p2,p3;    <- NOT correct

Are you stating that it currently is a syntax error, or that you think it should be? Certainly, the latter syntax is confusing...but I think that it is legal currently. I would very much want to encourage the former syntax...but I would hate to make D more limiting than C when it comes to parsing the tokens. A warning, perhaps? -- The Villagers are Online! villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ]
Nov 30 2001
parent reply nancyetroland <nancyetroland free.fr> writes:
Russ Lewis a écrit :

 Roland wrote:

 int* p1,p2,p3;    <- correct, all are pointers

 int *p1,p2,p3;    <- NOT correct

Are you stating that it currently is a syntax error, or that you think it should be?

Should be. With the new style for pointer declaration there is no more use to let the '*' front of the data name instead of back the pointed type. So pointer declaration syntax is standard now: Type instance1[instance2,..]; If we considere for example 'int*' as a type. Roland
Nov 29 2001
parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
The key issue to me here is the parsing of tokens.  As I understand C parsing,
whitespace is only used to delimit tokens which cannot be otherwise
differentiated,
most notably strings of characters that make up keywords and identifiers. 
Where the
differentiation is clear by the character sequence, whitespace is not needed. 
What I
mean is that the following lines are all viewed as identical to the C compiler:
    int* ptr;
    int *ptr;
    int*ptr;

Each is parsed into four tokens: 'int' '*' 'ptr' ';'

In order to do what you suggest, we must put artificial and very un-C-like
restrictions on the parser.  IMHO, that is very undesirable as is starts us
down a
path of special case rules and a buggy parser.  The syntax you suggest is
good...I
will use it in my D programs.  But I don't think that we can require it.

--
The Villagers are Online! http://villagersonline.com

.[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
.[ (a version.of(English).(precise.more)) is(possible) ]
?[ you want.to(help(develop(it))) ]
Nov 30 2001
parent reply nancyetroland <nancyetroland free.fr> writes:
Russ Lewis a écrit :

 The key issue to me here is the parsing of tokens.  As I understand C parsing,
 whitespace is only used to delimit tokens which cannot be otherwise
differentiated,
 most notably strings of characters that make up keywords and identifiers. 
Where the
 differentiation is clear by the character sequence, whitespace is not needed. 
What I
 mean is that the following lines are all viewed as identical to the C compiler:
     int* ptr;
     int *ptr;
     int*ptr;

 Each is parsed into four tokens: 'int' '*' 'ptr' ';'

 In order to do what you suggest, we must put artificial and very un-C-like
 restrictions on the parser.  IMHO, that is very undesirable as is starts us
down a
 path of special case rules and a buggy parser.  The syntax you suggest is
good...I
 will use it in my D programs.  But I don't think that we can require it.

I thought whitespaces were separators un C. I agree the goal is not to add special cases but to supress them. What i suggested is to standardize the fact that all type information must be at the left of the instance name. In the same spirit as arrays declaration: int[] array_of_int_instance; //D style, type is declared completely before instance name instead of int array_of_int_instance[]; //C style, from left to right: it is a 'int' named 'array_of_int_instance' but in fact it is an array: '[]' And standardize the fact that all instances declared at the right of the type declaration, separated by ',' , should be of this type: int* p1,p2; //D style: all type 'int*' Instead of; int *p1,p2; // C style: mixed types. p1 is a 'int*' , p2 is a int Pavel \"EvilOne\" Minayev a écrit :
 Suppose we have the following code:

     int*[]* x, y;

 "Old" way: x is pointer to array of pointers, y is an array of
     pointers. The first asterisk applies to both, the second
     is applied only to x. Not only it's weird, but just try to
     define a _clear_ rule (say, for the specification) that
     strictly defines meaning of asterisk.

 New way: both are pointers to array of pointers. Anything
     that's on the left is part of the type and is applied to
     all variables on the line, no special cases and
     exceptions.

 I vote for the new one...

Me too Roland
Dec 01 2001
parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
I agree with the sentiment.  It will just need comments from some more
knowledge able
people (are you lurking, Walter?) about whether it is technically feasible
without specail
cases in the parser.

--
The Villagers are Online! http://villagersonline.com

.[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
.[ (a version.of(English).(precise.more)) is(possible) ]
?[ you want.to(help(develop(it))) ]
Dec 01 2001
parent reply "Walter" <walter digitalmars.com> writes:
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:3C08E404.67B8A193 deming-os.org...
 I agree with the sentiment.  It will just need comments from some more

 people (are you lurking, Walter?) about whether it is technically feasible

 cases in the parser.

I have run into some problems with it. Specifically, pointers to functions. C: int (*fp)(args); // ugly, but servicable D: int (*)(args) fp; // ?? int (args)* fp; // ?? arrgh
Dec 01 2001
next sibling parent reply "Pavel Minayev" <evilone omen.ru> writes:
"Walter" <walter digitalmars.com> wrote in message
news:9ubqoj$1lh7$1 digitaldaemon.com...

 I have run into some problems with it. Specifically, pointers to

 C:
     int (*fp)(args);    // ugly, but servicable

 D:
     int (*)(args) fp;    // ??
     int (args)* fp;    // ?? arrgh

Solution: int(args) fp; No need for * here anyhow, since we can only have pointers to functions, not function variables by themselves.
Dec 02 2001
parent reply "Pavel Minayev" <evilone omen.ru> writes:
And for pointers to methods, I'd suggest
the following:

    int.(args) mp;
Dec 02 2001
next sibling parent reply "Walter" <walter digitalmars.com> writes:
"Pavel Minayev" <evilone omen.ru> wrote in message
news:9ucq38$2o5m$1 digitaldaemon.com...
 And for pointers to methods, I'd suggest
 the following:
     int.(args) mp;

I'm trying to avoid pointers to members <g>.
Dec 02 2001
next sibling parent reply "Pavel Minayev" <evilone omen.ru> writes:
"Walter" <walter digitalmars.com> wrote in message
news:9uctpk$2rvp$3 digitaldaemon.com...
 "Pavel Minayev" <evilone omen.ru> wrote in message
 news:9ucq38$2o5m$1 digitaldaemon.com...
 And for pointers to methods, I'd suggest
 the following:
     int.(args) mp;

I'm trying to avoid pointers to members <g>.

A question then. Since D doesn't have macroses, it would be hard to define a simple syntax for message maps. Pointers to members are not supported. If I want to write a GUI library for D, what other ways could I use then? WndProc and switch() (aka back to the WinAPI days)? nah, totally ditches the idea... anything else? Just to make this all clearer, a code that could be part of a GUI library: // =================================================== // using pointers to methods, if they were implemented class Button { void.() OnClick int WndProc(uint uMsg, WPARAM wParam, LPARAM lParam) { if (uMsg == WM_LBUTTONDOWN) OnClick() } } class MyForm { Button cmdOk; this() { cmdOk.OnClick = cmdOk_Click; } void cmdOk_Click() { // do something useful... } } // ============================================= // using map tables, if there were macroses in D class MyForm { BEGIN_MESSAGE_MAP(MyForm) ON_NOTIFY(IDC_CMDOK, BN_CLICKED, cmdOk_Click) END_MESSAGE_MAP() void cmdOk_Click() { // do something useful... } } // ======================================== // using if() or switch(), already possible class MyForm { int WndProc(uint uMsg, WPARAM wParam, LPARAM lParam) { if (uMsg == WM_COMMAND && hiword(wParam) == IDC_CMDOK) cmdOk_Click(); } void cmdOk_Click() { // do something useful... } }
Dec 02 2001
next sibling parent reply "Walter" <walter digitalmars.com> writes:
"Pavel Minayev" <evilone omen.ru> wrote in message
news:9ucvsu$2u60$1 digitaldaemon.com...
 Since D doesn't have macroses, it would be hard to define
 a simple syntax for message maps. Pointers to members
 are not supported. If I want to write a GUI library for
 D, what other ways could I use then? WndProc and switch()
 (aka back to the WinAPI days)? nah, totally ditches the
 idea... anything else?

What you could do is create an array of function pointers, indexed by the message number. A default one is provided by the gui library. You could write an associative array that contains just the messages you want to dispatch on. So, you test your local associative array, if it's there, dispatch. Otherwise, use the default array, and dispatch to that one. Member function pointers are not necessary, just use a static member function.
Dec 03 2001
parent reply "Sean L. Palmer" <spalmer iname.com> writes:
Been there, done that, in Pascal and C.  Interfacing to Windows User.  That
just brings us back around to how to ease the passing of control back into a
real actual object, the transmission of the this pointer has to be done
somehow, and that just makes the programmer write forwarding functions with
an extra object pointer parameter.

It can be argued that anything beyond the goto, test, and addition and
negation is not "necessary" because we can build it ourselves from more
primitive tools.  I don't want to have to build language tools to be able to
get basic work done.  You'd think that a language designed today would
function to make our lives easier.  I guess some kind of a member function
pointer bundled with a this pointer would be a good enough replacement, if
that is any less problematic.  Callbacks to objects is the main goal here I
think.

Sean

"Walter" <walter digitalmars.com> wrote in message
news:9ufg0t$2i1n$1 digitaldaemon.com...
 "Pavel Minayev" <evilone omen.ru> wrote in message
 news:9ucvsu$2u60$1 digitaldaemon.com...
 Since D doesn't have macroses, it would be hard to define
 a simple syntax for message maps. Pointers to members
 are not supported. If I want to write a GUI library for
 D, what other ways could I use then? WndProc and switch()
 (aka back to the WinAPI days)? nah, totally ditches the
 idea... anything else?

What you could do is create an array of function pointers, indexed by the message number. A default one is provided by the gui library. You could write an associative array that contains just the messages you want to dispatch on. So, you test your local associative array, if it's there, dispatch. Otherwise, use the default array, and dispatch to that one. Member function pointers are not necessary, just use a static member function.

Dec 03 2001
parent reply "Pavel Minayev" <evilone omen.ru> writes:
"Sean L. Palmer" <spalmer iname.com> wrote in message
news:9ufhqn$2jsd$1 digitaldaemon.com...
 Been there, done that, in Pascal and C.  Interfacing to Windows User.

 just brings us back around to how to ease the passing of control back into

 real actual object, the transmission of the this pointer has to be done
 somehow, and that just makes the programmer write forwarding functions

 an extra object pointer parameter.

Exactly! Suppose we have an MDI application. In this case, you'd probably want each event to be handled by the appropriate object, associated with the child window, not by a static function shared by all objects. This is just an additional headache for the user of the library, since there are no macroses to simplify it.
 It can be argued that anything beyond the goto, test, and addition and
 negation is not "necessary" because we can build it ourselves from more
 primitive tools.  I don't want to have to build language tools to be able

 get basic work done.  You'd think that a language designed today would
 function to make our lives easier.  I guess some kind of a member function
 pointer bundled with a this pointer would be a good enough replacement, if
 that is any less problematic.  Callbacks to objects is the main goal here

 think.

Yes. Since window is represented by an object of a specific class, and there can be several objects of that class, each window should handle its events separately, without additional layers (that have to be manually coded by the end-user!) like static functions. I can't really understand what's bad with the idea? What are the arguments against having it in D?
Dec 03 2001
parent reply "Walter" <walter digitalmars.com> writes:
"Pavel Minayev" <evilone omen.ru> wrote in message
news:9ug6ai$815$1 digitaldaemon.com...
 I can't really understand what's bad with the idea? What are the
 arguments against having it in D?

Member function pointers are confusing (to me, anyway), and there's some significant complexity involved with getting them implemented right.
Dec 03 2001
parent reply "Pavel Minayev" <evilone omen.ru> writes:
"Walter" <walter digitalmars.com> wrote in message
news:9uhjh9$1fhs$5 digitaldaemon.com...

 "Pavel Minayev" <evilone omen.ru> wrote in message
 news:9ug6ai$815$1 digitaldaemon.com...
 I can't really understand what's bad with the idea? What are the
 arguments against having it in D?

Member function pointers are confusing (to me, anyway), and there's some

I agree that _C++_ method pointers are confusing. But what's wrong with Delphi-like ones that I propose? In fact, what they allow is to treat methods just like you treat global functions when dealing with callbacks. What's confusing in it?
 significant complexity involved with getting them implemented right.

Not sure what it can be... could you give an example? BTW due to the fact I needed them badly and C++ don't have them, I've implemented method pointers using templated class and some hacks... and the code was quite small.
Dec 03 2001
parent reply "Walter" <walter digitalmars.com> writes:
"Pavel Minayev" <evilone omen.ru> wrote in message
news:9uhsjq$1lb3$1 digitaldaemon.com...
 significant complexity involved with getting them implemented right.


You have to generate things like thunks. Ugh.
 BTW due to the fact I needed them badly and C++ don't have them,
 I've implemented method pointers using templated class and some
 hacks... and the code was quite small.

But C++ does have pointers to member functions.
Dec 04 2001
parent "Pavel Minayev" <evilone omen.ru> writes:
"Walter" <walter digitalmars.com> wrote in message
news:9ui1i8$1q67$1 digitaldaemon.com...

 But C++ does have pointers to member functions.

I've probably explained the thing badly. Yes, C++ has pointers to methods. However, they point to method of some _class_ rather than to method of some _object_. These are very different things. Of course, you can store pointer to object elsewhere, but not only it looks clumsy from the POV of end-user, there is also a stupid limitation of method belonging to exact given class, not even its child classes - and no workaround for the problem. Such pointers are completely useless in context of GUI library: void (CForm::*OnClick)(int x, y); ... class CMyForm: public CForm { public: void Click(int x, y); } MyForm; OnClick = CMyForm::Click; // oops, won't work! On other hand, Delphi pointers do point to method of one concrete object, and they absolutely don't care of its class - they simply treat method as a function which has a context "this" pointer associated with it: var OnClick: procedure(x,y: integer) of object; ... type TMyForm = class(TForm); public procedure Click(x,y: integer); end; var MyForm: TMyForm; begin OnClick := MyForm.Click; // everything's fine end;
Dec 04 2001
prev sibling next sibling parent reply Roland <rv ronetech.com> writes:
Pavel Minayev a écrit :

 A question then.

 Since D doesn't have macroses, it would be hard to define
 a simple syntax for message maps. Pointers to members
 are not supported. If I want to write a GUI library for
 D, what other ways could I use then? WndProc and switch()
 (aka back to the WinAPI days)? nah, totally ditches the
 idea... anything else?

 Just to make this all clearer, a code that could be part
 of a GUI library:

     // ===================================================
     // using pointers to methods, if they were implemented

     class Button
     {
         void.() OnClick

         int WndProc(uint uMsg, WPARAM wParam, LPARAM lParam)
         {
             if (uMsg == WM_LBUTTONDOWN)
                 OnClick()
         }
     }

     class MyForm
     {
         Button cmdOk;

         this()
         {
             cmdOk.OnClick = cmdOk_Click;
         }

         void cmdOk_Click()
         {
             // do something useful...
         }
     }

Yes, this is a common problem having an object that trap events or calls, and just dispatch them to an other object. It can be done with a pointer function as you sugest or in theory with a pointer to the destination object: class CmdOkButton { MyForm* dest; this(MyForm* frm): dest(frm) { } int WndProc(uint uMsg, WPARAM wParam, LPARAM lParam) { if (uMsg == WM_LBUTTONDOWN) dest.cmdOk_Click() } } In practice it's boring: create a class for all message, and writing functions that just transfer the call to an other object. I suggest (i know, it's easier to sugest than to implement): class Button { void.OnClick() //note OnClick is a normal member function int WndProc(uint uMsg, WPARAM wParam, LPARAM lParam) { if (uMsg == WM_LBUTTONDOWN) OnClick() } } class MyForm { Button cmdOk; this() { cmdOk.OnClick = cmdOk_Click; //yes !, see below } void cmdOk_Click() { // do something useful... } } Button::OnClick is a normal (virtual) function. cmdOk.OnClick = cmdOk_Click writes in cmdOk Virtual Table !!?? Yes. It's ok if cmdOk have its _own_ virtual table. Overwriting a member function of a class, should instruct the compiler that this class is what can be called a "Transfer Class". Transfer Classes properties: - All objects of this type have ther _own_ Virtual Table duplicated from the Type's one, - they also have a table for 'this' pointer translation so that for example cmdOk_Click function recieve a 'this' pointer pointing on the MyForm object, NOT on the MyForm object :: cmdOk. Advantages: - no more pointers to member, - its fast Inconvenients: - memory consumption (cheap now), - is it in D spirit ? If this not too complicate to implement, i think that is the easiest way to do the job, and after all, at low level, virtual functions are functions pointers isn't it ? Roland
Dec 11 2001
parent reply "Pavel Minayev" <evilone omen.ru> writes:
"Roland" <rv ronetech.com> wrote in message
news:3C16714A.FB186A1F ronetech.com...

 Button::OnClick is a normal (virtual) function.
 cmdOk.OnClick = cmdOk_Click writes in cmdOk Virtual Table !!??
 Yes. It's ok if cmdOk have its _own_ virtual table.

 Overwriting a member function of a class, should instruct the compiler
 that this class is what can be
 called a "Transfer Class".

The problem here is that it's not very easy to find out if some _object_ of that class gets its vtable changed: Control cmdOk; // note: not a Button! cmdOk = new Button; cmdOk.OnClick = cmdOk_Click;
 Transfer Classes properties:

 - All objects of this type have ther _own_ Virtual Table duplicated from
 the Type's one,
 - they also have a table for 'this' pointer translation so that for
 example cmdOk_Click function
 recieve a 'this' pointer pointing on the MyForm object, NOT on the
 MyForm object :: cmdOk.

I don't see the actual difference between this and pointers to methods. Both here and there, you store pointer to object together with pointer to function, only in your case they're separated into two tables. Making vtables dynamic (Delphi term, vtables are per object rather than per class) uses much more memory especially with complex class hierarchy while not providing any advantages (it's not faster, and - IMHO - not easier to implement).
 to do the job, and after all, at low level, virtual functions
 are functions pointers isn't it ?

Yes but we were talking about pointers to methods, right? And these are different...
Dec 12 2001
parent reply NancyEtRoland <nancyetroland free.fr> writes:
Pavel Minayev a écrit :

 The problem here is that it's not very easy to find out if some
 _object_ of that class gets its vtable changed:

     Control cmdOk;    // note: not a Button!
     cmdOk = new Button;
     cmdOk.OnClick = cmdOk_Click;

object must switch from static to dynamic virtual table at run time
 I don't see the actual difference between this and pointers to methods.
 Both here and there, you store pointer to object together with pointer
 to function, only in your case they're separated into two tables.
 Making vtables dynamic (Delphi term, vtables are per object rather than
 per class) uses much more memory especially with complex class hierarchy
 while not providing any advantages (it's not faster, and - IMHO - not
 easier to implement).

Franckly, if i understand well the concept, i had to remind pointer to methodes syntax in C++, as i never used them. First impression: not a very nice syntax, may be usefull, i should use them. But they had already been rejected for D. I would try to suggest a replacement, something clean, before the boss come. class Button { void.OnClick() { <default action> } int WndProc(uint uMsg, WPARAM wParam, LPARAM lParam) { if (uMsg == WM_LBUTTONDOWN) OnClick() } } class MyForm { Button cmdOk; this() { cmdOk.OnClick = cmdOk_Click; //<-------- here } void cmdOk_Click() { // do something useful... } } MyForm myform; The goal is: - a click event on myform.cmdOk calls myform.cmdOk_Click, - of course, in cmdOk_Click, 'this' points on myform, NOT on myform.cmdOk I sugest for that, just write: cmdOk.OnClick = cmdOk_Click I think this syntax is simple and that can replace pointer to member functions. But: - it must not be too complicate to implement, - it must not slow down normal virtual function call. //------------------------------------------------------ Inthe way for implementation: A little deeper inside the machine: Lets translate from D to C to show how virtuals are: //- - - - - - - - - //Button struct Button_VT { //virtual table of Button type, created by compliler in C++/D void *OnClick(); }; struct Button { Button_VT* vt; //hidden pointer to virtual table, created and initialized by compliler in C++/D }; void virtual_Button_OnClick(Button* this) { //virtual function call mechanism (inlined) this->vt->OnClick(this); } void.Button_OnClick(Button* this) { <default action> } //- - - - - - - - - //MyForm struct MyForm_VT { //virtual table of MyForm type, created by compliler in C++/D void *cmdOk_Click(); }; struct MyForm { MyForm_VT* vt; //hidden pointer to virtual table, created and initialized by compliler in C++/D Button cmdOk; } void virtual_MyForm_cmdOk_Click(MyForm* this) { //virtual function call mechanism (inlined) this->vt->cmdOk_Click(this); } void MyForm_cmdOk_Click(MyForm* this) { do something useful... } //- - - - - - - - - //declare objects: static Button_VT button_VT; static MyForm_VT myform_VT; MyForm myform; //click event on myform.cmdOk: same as a call to: virtual_Button_OnClick(&myform.cmdOk); //------------------------------- Now lets translate from D to C "myform.cmdOk.OnClick = myform.cmdOk_Click" statement: 1° in D: "myform.cmdOk.OnClick = myform.cmdOk_Click" statement: => myform.cmdOk.vt->OnClick = MyForm_cmdOk_Click not good: - all object of class MyForm will be affected - in MyForm_cmdOk_Click, 'this' will point on myform.cmdOk instead of myform. 2° in D: "myform.cmdOk.OnClick = myform.cmdOk_Click" statement: => allocate a new Button_VT: new_Button_VT => copy button_VT to new_Button_VT => set new_Button_VT.OnClick = MyForm_cmdOk_Click => set myform.cmdOk.vt = new_Button_VT solve the first problem: myform.cmdOk switches from a static VT to a dynamic VT. the other one is a little more complicate. 3° lets create a new struct: struct Button_VT2: Button_VT { void* onclickthis; Button_VT ivt; }; and a new function: void.Button_VT2_OnClick(Button* buttonp) { ((Button_VT2*)buttonp->vt)->ivt->OnClick(((Button_VT2*)buttonp->vt)->onclickthis); } now: in D: "myform.cmdOk.OnClick = myform.cmdOk_Click" statement: => allocate a new Button_VT2: new_Button_VT2 => copy button_VT to new_Button_VT2.ivt => set new_Button_VT2.ivt.OnClick = MyForm_cmdOk_Click => set new_Button_VT2.OnClick = Button_VT2_OnClick => set new_Button_VT2.onclickthis = &myform => set myform.cmdOk.vt = new_Button_VT2 okay, it work like this: event: virtual_Button_OnClick(&myform.cmdOk) => myform.cmdOk.vt->OnClick(&myform.cmdOk) => Button_VT2_OnClick(&myform.cmdOk) => ((Button_VT2*)myform.cmdOk.vt)->ivt->OnClick(((Button_VT2*)myform.cmdOk.vt)->destobject) => MyForm_cmdOk_Click(&myform) done a little slow but acceptable Everything seems too nice. There must be something wrong there. but what ? Roland
Dec 22 2001
parent reply "Pavel Minayev" <evilone omen.ru> writes:
"NancyEtRoland" <nancyetroland free.fr> wrote in message
news:3C251BB2.F4053844 free.fr...

 I sugest for that, just write:

 cmdOk.OnClick = cmdOk_Click

 I think this syntax is simple and that can replace pointer to member
 functions.

Exactly what I proposed.
 Everything seems too nice. There must be something wrong there. but what ?

IMHO there's no need to mess with virtuals at all. In other words, once you bind the function to the event slot, you bind the _concrete function_ by its pointer-to-code, bypassing vtable. As the result, you don't have to mess with all the vtable stuff - just store the pointer to object and pointer to function itself, 8 bytes total, and call them simply. In C, that'd look like: struct event { void* object; void (*method)(void*, ...); } event; event.method(event.object, arg1, arg2, arg3);
Dec 23 2001
parent NancyEtRoland <nancyetroland free.fr> writes:
Pavel Minayev a écrit :

 IMHO there's no need to mess with virtuals at all. In other
 words, once you bind the function to the event slot, you
 bind the _concrete function_ by its pointer-to-code, bypassing
 vtable. As the result, you don't have to mess with all the
 vtable stuff - just store the pointer to object and pointer
 to function itself, 8 bytes total, and call them simply. In
 C, that'd look like:

     struct event
     {
         void* object;
         void (*method)(void*, ...);
     } event;

     event.method(event.object, arg1, arg2, arg3);

Putting those pointers to vtable is in fact exactely the same (even if it *looks* more messy) but this way there is no need for "pointers to member function" type. Roland
Dec 26 2001
prev sibling parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Pavel makes a critical point here that must be noted.  Callbacks, very
often should not be targeted at the objects that created them.  That is,
you note that the Button object is what "receives" the OnClick
message...but it is a function in MyForm that must process it.  If we go
the traditional C++ route (but don't use macros) then we are left with
this terrible code:

//declared by the API
class Button;

// user code
class MyForm
{
    void cmdOk_Click();

    class MyForm_Button : public Button
    {
    private:
        MyForm *form;
    public:
        MyForm_Button(MyForm *form) { this->form = form; };
    public:
        void OnClick() { return form->cmdOk_Click(); };
    };

    MyForm_Button okButton;
    ...
};

Then the constructor for MyForm must pass a pointer to itself to the
constructor for okButton, and so on.  It gets worse.

The point here is that, in old C++, you can't easily declare an object
that delegates its callbacks to the encapsulating object.  It would be a
Good Thing if D allowed this.



A Side Note:

It's possible to do more flexible callbacks with C++ using templates;
you force the compiler to, under the covers, create a wrapper function
that calls the right member function of the right class.  But it's a
 #$(*% pain, and won't work in D since we don't have templates there.

--
The Villagers are Online! http://villagersonline.com

.[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
.[ (a version.of(English).(precise.more)) is(possible) ]
?[ you want.to(help(develop(it))) ]
Dec 25 2001
parent reply NancyEtRoland <nancyetroland free.fr> writes:
Russ Lewis a écrit :

 Pavel makes a critical point here that must be noted.  Callbacks, very
 often should not be targeted at the objects that created them.  That is,
 you note that the Button object is what "receives" the OnClick
 message...but it is a function in MyForm that must process it.  If we go
 the traditional C++ route (but don't use macros) then we are left with
 this terrible code:

 //declared by the API
 class Button;

 // user code
 class MyForm
 {
     void cmdOk_Click();

     class MyForm_Button : public Button
     {
     private:
         MyForm *form;
     public:
         MyForm_Button(MyForm *form) { this->form = form; };
     public:
         void OnClick() { return form->cmdOk_Click(); };
     };

     MyForm_Button okButton;
     ...
 };

That is some kind of code we all do and i would apreciate a compiler do for me: it's boring
 It's possible to do more flexible callbacks with C++ using templates;
 you force the compiler to, under the covers, create a wrapper function
 that calls the right member function of the right class.  But it's a
  #$(*% pain, and won't work in D since we don't have templates there.

I tried too: not nicer. Next time i try to do it with pointers to methode.. in C++. Roland
Dec 26 2001
parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
NancyEtRoland wrote:

 I tried too: not nicer.

 Next time i try to do it with pointers to methode.. in C++.

I have implemented the following in C++: struct Handler { ... }; struct ArgType { ... }; Handler MakeHandler(ArgType (*func)()); Handler MakeHandler(ArgType (*func)(ArgType)); template <class X> Handler MakeHandler(ArgType (X::*func)()); template <class X> Handler MakeHandler(ArgType (X::*func)(ArgType)); Handler overloads operator(), which takes a single ArgType value and returns an ArgType. The point here is that, using templates, I can create an arbitrary structure (kind of like a generic pointer-to-function or pointer-to-member-function) that you can then use like a function pointer. Unfortunately, my company hasn't (yet) released the source code to open source, though I'm hoping they will. Fortunately, I developed this based on stuff I found freely on the web. -- The Villagers are Online! http://villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ]
Dec 26 2001
parent reply "Pavel Minayev" <evilone omen.ru> writes:
"Russ Lewis" <spamhole-2001-07-16 deming-os.org> wrote in message
news:3C2A5F43.C58C4EEB deming-os.org...

 I have implemented the following in C++:

 struct Handler { ... };
 struct ArgType { ... };

 Handler MakeHandler(ArgType (*func)());
 Handler MakeHandler(ArgType (*func)(ArgType));

 template <class X>
 Handler MakeHandler(ArgType (X::*func)());
 template <class X>
 Handler MakeHandler(ArgType (X::*func)(ArgType));

 Handler overloads operator(), which takes a single ArgType value and

 ArgType.  The point here is that, using templates, I can create an

 structure (kind of like a generic pointer-to-function or
 pointer-to-member-function) that you can then use like a function pointer.

I've came to the same solution; however, I couldn't make Visual C++ to work with that sort of templates. Borland C++, on other hand, did the job just fine. So I've made it more general (and less typesafe): template <class X> Handler MakeHandler(X func); IMO, all these efforts are a fine example of why having such a construct built-in into language would be really great!
Dec 26 2001
parent Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
My code has to be portable between gcc on Linux and MSVC on Windows.  The simple
design, which works on gcc, failed on MSVC because the compiler was too
simpleminded to handle it.  But it can be done...I hope someday to post the MSVC
solution. :(

As you say, it would be a great thing to have in the language.  I even posted a
C-compatible solution for member function pointers in a previous post called
"Member Function Pointers" (8/20/01)

--
The Villagers are Online! http://villagersonline.com

.[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
.[ (a version.of(English).(precise.more)) is(possible) ]
?[ you want.to(help(develop(it))) ]
Dec 26 2001
prev sibling parent reply "Sean L. Palmer" <spalmer iname.com> writes:
I am not sure why you would want to avoid pointers to member functions...
they sure can be useful sometimes.

Declaration syntax could be:

class Foo
{
  void Fn1(int a);
  void Fn2(int a);
}

void Foo:(int) memfuncptr = Foo.Fn1.

Calling syntax could then be:

object.memfuncptr:(args);

Which kinda matches the declaration syntax I proposed.

Ok, so I can't think of a decent syntax either.  ;(  But I'd still like to
see them included in D.

Sean



"Walter" <walter digitalmars.com> wrote in message
news:9uctpk$2rvp$3 digitaldaemon.com...
 I'm trying to avoid pointers to members <g>.

Dec 02 2001
next sibling parent "Pavel Minayev" <evilone omen.ru> writes:
"Sean L. Palmer" <spalmer iname.com> wrote in message
news:9ud1c0$2vqm$1 digitaldaemon.com...

 I am not sure why you would want to avoid pointers to member functions...
 they sure can be useful sometimes.

 Declaration syntax could be:

 class Foo
 {
   void Fn1(int a);
   void Fn2(int a);
 }

 void Foo:(int) memfuncptr = Foo.Fn1.

 Calling syntax could then be:

 object.memfuncptr:(args);

 Which kinda matches the declaration syntax I proposed.

 Ok, so I can't think of a decent syntax either.  ;(  But I'd still like to
 see them included in D.

Yeah, syntax is a question. Still I'd like to see them in D, especially if they are able to hold pointer to object together with pointer to method, as I've stated before =)
Dec 02 2001
prev sibling parent a <a b.c> writes:
"Sean L. Palmer" wrote:
 
 I am not sure why you would want to avoid pointers to member functions...
 they sure can be useful sometimes.

So can operator overloading. So can the preprocesser. So can multiple inheritance. So can templates. The better question might be, what (if anything) will be in D to replace the functionality? Dan
Dec 02 2001
prev sibling parent reply Charles Hixson <charleshixsn earthlink.net> writes:
Pavel Minayev wrote:

 ...
 And for pointers to methods, I'd suggest
 the following:
 
     int.(args) mp;
...

I assume that in a real example the args would be spelled out? How do you feel one should list a method that required a method argument? int.(.op(int.val1, float.val2) int.val1, float.val2) theFunc; Perhaps?
Dec 03 2001
parent "Pavel Minayev" <evilone omen.ru> writes:
"Charles Hixson" <charleshixsn earthlink.net> wrote in message
news:3C0BF296.6010808 earthlink.net...

 I assume that in a real example the args would be spelled out?
 How do you feel one should list a method that required a method
 argument?
    int.(.op(int.val1, float.val2) int.val1, float.val2) theFunc;

int.(int.(int) method1, void.(float, float), char[]) theFunc; Dot should always go to the right. Or to the left - whichever you prefer =)
Dec 03 2001
prev sibling parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Walter wrote:

 C:
     int (*fp)(args);    // ugly, but servicable

 D:
     int (*)(args) fp;    // ??
     int (args)* fp;    // ?? arrgh

A couple of other brainstorms: int (*function)(args) fp1,fp2; // requires new keyword 'function' int func-ptr(args) fp1,fp2; // requires new keyword 'func-ptr' int (* fp1,fp2)(args); // really ugly :( -- The Villagers are Online! villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ]
Dec 03 2001
parent Roland <rv ronetech.com> writes:
Russ Lewis a écrit :

 Walter wrote:

 C:
     int (*fp)(args);    // ugly, but servicable

 D:
     int (*)(args) fp;    // ??
     int (args)* fp;    // ?? arrgh

A couple of other brainstorms: int (*function)(args) fp1,fp2; // requires new keyword 'function' int func-ptr(args) fp1,fp2; // requires new keyword 'func-ptr' int (* fp1,fp2)(args); // really ugly :(

int function(args)* fp1,fp2; // requires new keyword 'function' //pointed type is defined before '*' Roland
Dec 04 2001
prev sibling parent "Walter" <walter digitalmars.com> writes:
"Robert W. Cunningham" <rwc_2001 yahoo.com> wrote in message
news:3C070B8E.984C6418 yahoo.com...
 Let's eliminate all the cousins of the above, such as:

      int*[]* x, y, *z;

 This should be an error!  The "correct" form should require z to be on a
 separate line.

Yeah, that should be an error. -Walter
Nov 30 2001
prev sibling next sibling parent Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
 Suppose I have the following declaration:
     int* x, y;
 Is y an int or a pointer to int?

An int. I didn't break away from C on that one. I can be persuaded otherwise.

Persuade, persuade, persuade, persuade. Is that enough, or do we need more? -- The Villagers are Online! villagersonline.com .[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ] .[ (a version.of(English).(precise.more)) is(possible) ] ?[ you want.to(help(develop(it))) ]
Nov 09 2001
prev sibling next sibling parent Russell Borogove <kaleja estarcion.com> writes:
Walter wrote:
 
 "Pavel "EvilOne" Minayev" <evilone omen.ru> wrote in message
 news:9sdigb$2715$1 digitaldaemon.com...
 What is the default attribute for class members
 (private/protected/public)?

Public. I always thought that C++'s way just made for annoying extra typing when banging out quick code. A production quality class should always say it explicitly.

I'd personally lobby for the default attribute be "compilererror". That's just me though. _R
Nov 09 2001
prev sibling next sibling parent reply "Sean L. Palmer" <spalmer iname.com> writes:
"Walter" <walter digitalmars.com> wrote in message
news:9sh1ca$1pn2$2 digitaldaemon.com...
 What is the default attribute for class members
 (private/protected/public)?

Public. I always thought that C++'s way just made for annoying extra

 when banging out quick code. A production quality class should always say

 explicitly.

Agreed. I suppose inheritance is also by default public?
 Suppose I have the following declaration:
     int* x, y;
 Is y an int or a pointer to int?

An int. I didn't break away from C on that one. I can be persuaded otherwise.

Since you're changing the type specifiers anyway... may as well fix this legacy crap. I can't tell you how many times this has burned me. If someone wants two different types of variables, s/he can make two separate declarations. This goes hand-in-hand with the idea to keep the type specifier all together in one place, parseable right to left. If you start letting people put part of the type off somewhere else, the problem comes back such that type specifiers aren't complete, and people get confused.
 Prefix it with the module name. Assume the module name is foo:

     foo.X()

What if someone made a local variable or member function named foo also? Yes they're bad... maybe we could allow some syntax like this: ().X() or static.X() Some way to unambiguously get to the "global" scope (current module). Maybe you could import foo; again, right there in the function, which overrides the local foo.
Nov 09 2001
parent "Walter" <walter digitalmars.com> writes:
"Sean L. Palmer" <spalmer iname.com> wrote in message
news:9sh8ic$233l$1 digitaldaemon.com...
 "Walter" <walter digitalmars.com> wrote in message
 news:9sh1ca$1pn2$2 digitaldaemon.com...
 What is the default attribute for class members
 (private/protected/public)?


 when banging out quick code. A production quality class should always


 it
 explicitly.


Yes.
 Suppose I have the following declaration:
     int* x, y;
 Is y an int or a pointer to int?

otherwise.

legacy crap. I can't tell you how many times this has burned me. If someone wants two different types of variables, s/he can make two separate declarations. This goes hand-in-hand with the idea to keep the type specifier all together in one place, parseable right to left. If you

 letting people put part of the type off somewhere else, the problem comes
 back such that type specifiers aren't complete, and people get confused.

I think you're right.
 What if someone made a local variable or member function named foo also?

Don't do that. It doesn't seem to be a significant problem in C.
Nov 09 2001
prev sibling next sibling parent la7y6nvo shamko.com writes:
I would argue in favor of breaking with tradition on the 'int *x, y;'
question.  Try listing out some arguments on each side:


For breaking with tradition:
----------------------------

  1) The C way is frequently misunderstood by beginners.

  2) The C way often leads to bugs (even if they are usually caught
     by the compiler, they are still bugs).

  3) The C way associates the * with the variable rather than the
     type;  does anyone really want to be able to have 'int *x, y, *z;'?

  4) The C way requires more typing, admittedly only one more character
     per variable, but more is more.

  5) If one is reading C code and sees 'int *x, y;', there is always
     the nagging feeling that the person who wrote it made a mistake.

  6) In writing actual code, I sometimes want to declare two pointer
     variables;  I almost never want to declare both a pointer and
     a non-pointer.


For staying with tradition:
---------------------------

  1) Compatibility.

  2) It turns out that there is a case where both a pointer and a
     non-pointer are declared simultaneously that occurs fairly
     often, and that is typedef.  For example

	 typedef struct Foo_tag  *FooPointer, Foo;

     (Substitute Hungarian notation for 'FooPointer' if that is your
     preference.)  So the old C way is used sometimes in ways that
     are at least semi-reasonable.


On balance the arguments for breaking with tradition seem stronger
than those for staying with tradition.  Or are there some important
arguments that are missing?



"Walter" <walter digitalmars.com> writes:

 "Pavel "EvilOne" Minayev" <evilone omen.ru> wrote in message

 Suppose I have the following declaration:
     int* x, y;
 Is y an int or a pointer to int?

An int. I didn't break away from C on that one. I can be persuaded otherwise.

Nov 10 2001
prev sibling parent reply Axel Kittenberger <axel dtone.org> writes:
Walter wrote:

 
 "Pavel "EvilOne" Minayev" <evilone omen.ru> wrote in message
 news:9sdigb$2715$1 digitaldaemon.com...
 What is the default attribute for class members
 (private/protected/public)?

Public. I always thought that C++'s way just made for annoying extra typing when banging out quick code. A production quality class should always say it explicitly.

I say private would be better for quality code. Argueing for this is quite simple, if there is nothing standing there you can suppose that programmer simply forgot about the access attribute. If he actually ment private, but public is default, he gets no compiler errors/warnings. If he actually ment public, but private is default, the compiler will point him on the failure. - Axel -- |D) http://www.dtone.org
Nov 12 2001
next sibling parent "Roberto Mariottini" <rmariottini lycosmail.com> writes:
"Axel Kittenberger" <axel dtone.org> wrote in
news:9so2i6$nhi$1 digitaldaemon.com...
 Walter wrote:

 "Pavel "EvilOne" Minayev" <evilone omen.ru> wrote in message
 news:9sdigb$2715$1 digitaldaemon.com...
 What is the default attribute for class members
 (private/protected/public)?

Public. I always thought that C++'s way just made for annoying extra typing when banging out quick code. A production quality class should always say it explicitly.

I say private would be better for quality code. Argueing for this is quite simple, if there is nothing standing there you can suppose that programmer simply forgot about the access attribute. [snip]

I think the compiler shouldn't compile a class with no 'public', 'private' or 'protected' at all. The user clearly forgotten to specify. Ciao
Nov 12 2001
prev sibling parent "Pavel \"EvilOne\" Minayev" <evilone omen.ru> writes:
"Axel Kittenberger" <axel dtone.org> wrote in message
news:9so2i6$nhi$1 digitaldaemon.com...
 Walter wrote:

 I say private would be better for quality code.

 Argueing for this is quite simple, if there is nothing standing there you
 can suppose that programmer simply forgot about the access attribute.

 If he actually ment private, but public is default, he gets no compiler
 errors/warnings.
 If he actually ment public, but private is default, the compiler will

 him on the failure.

The thing is, when you omit the attribute at all, you get all members private, and the result is that class is completely useless. As for "actually ment private" - I believe that when declaring classes, it's better to define public members first, since there are more people who want to know the interface of the cass than those that are interested in implementation.
Nov 12 2001
prev sibling next sibling parent reply "Pavel \"EvilOne\" Minayev" <evilone omen.ru> writes:
What is the default calling convention for D functions -
cdecl, stdcall, pascal, fastcall?


BTW I wonder why you define stdcall convention as
extern(Windows)? It's not WinAPI-only, there are
stdcall specifiers in C, C++ and Pascal, and I believe
that most programmers know it as stdcall. And in
general, although convention is not a keyword, as
stated in the specs, it looks like that, so - IMHO -
it should be in lower-case. The same for extern(Pascal) -
extern(pascal) seems to look better and more familiar
especially to those who, like me, are used to Borland's
compilers.
Nov 08 2001
next sibling parent reply "Sean L. Palmer" <spalmer iname.com> writes:
Don't you find it the least bit presumptuous to make a calling convention
used only by Windows that is called "stdcall"?  If there were such a thing
as an industry standard, I guess that's it, a de facto one, I guess naming
it stdcall probably helped.  ;)

I'm not sure a language spec should define platform-specific runtime
behavior; the programs should (in theory) be agnostic to the choice of
platform.  If you're curious as to Walter's first D compiler's default for
the initial platform, Windows... well that seems to be a valid question.

Sean


"Pavel "EvilOne" Minayev" <evilone omen.ru> wrote in message
news:9sdiqf$2721$1 digitaldaemon.com...
 What is the default calling convention for D functions -
 cdecl, stdcall, pascal, fastcall?


 BTW I wonder why you define stdcall convention as
 extern(Windows)? It's not WinAPI-only, there are
 stdcall specifiers in C, C++ and Pascal, and I believe
 that most programmers know it as stdcall. And in
 general, although convention is not a keyword, as
 stated in the specs, it looks like that, so - IMHO -
 it should be in lower-case. The same for extern(Pascal) -
 extern(pascal) seems to look better and more familiar
 especially to those who, like me, are used to Borland's
 compilers.

Nov 08 2001
parent "Pavel \"EvilOne\" Minayev" <evilone omen.ru> writes:
"Sean L. Palmer" <spalmer iname.com> wrote in message
news:9sdpc1$2b9f$1 digitaldaemon.com...

 Don't you find it the least bit presumptuous to make a calling convention
 used only by Windows that is called "stdcall"?  If there were such a thing
 as an industry standard, I guess that's it, a de facto one, I guess naming
 it stdcall probably helped.  ;)

Yes, I know that it isn't actually "std". But it is well known as such, why rename?
 I'm not sure a language spec should define platform-specific runtime
 behavior; the programs should (in theory) be agnostic to the choice of
 platform.  If you're curious as to Walter's first D compiler's default for
 the initial platform, Windows... well that seems to be a valid question.

If compiler is to be of any use on Windows, it has to support at least stdcall in any way. BTW specs don't define any calling conventions other than C and D, so support for stdcall and pascal is purely implementation- dependent.
Nov 08 2001
prev sibling parent reply "Walter" <walter digitalmars.com> writes:
None of them. I intend to have it (the default D calling convention)
unspecified, so the compiler will be free to use whatever works best for the
code gen for that particular function. This makes interprocedural
optimizations possible. I strongly dislike the pointless proliferation of
calling conventions found in win32.

Since D must interface with existing C code, it must support them. Hence,
the extern(spec) construct.

Microsoft doesn't exactly use the stdcall for Windows API calls - first of
all, it varies (pascal on 16 bit machines, syscall on OS/2), and second,
they mangle the names differently than stdcall for system calls. After all,
they are windows API calling conventions, and who (besides the compiler
implementor) really cares what it is, so why not call it the "windows"
calling convention? It's easy to remember <g>.

I called it "Pascal" rather than "pascal" because it is conventionally
capitalized, just like fortran is normally "FORTRAN". I suppose it doesn't
matter one way or the other.

"Pavel "EvilOne" Minayev" <evilone omen.ru> wrote in message
news:9sdiqf$2721$1 digitaldaemon.com...
 What is the default calling convention for D functions -
 cdecl, stdcall, pascal, fastcall?


 BTW I wonder why you define stdcall convention as
 extern(Windows)? It's not WinAPI-only, there are
 stdcall specifiers in C, C++ and Pascal, and I believe
 that most programmers know it as stdcall. And in
 general, although convention is not a keyword, as
 stated in the specs, it looks like that, so - IMHO -
 it should be in lower-case. The same for extern(Pascal) -
 extern(pascal) seems to look better and more familiar
 especially to those who, like me, are used to Borland's
 compilers.

Nov 09 2001
next sibling parent reply "Pavel \"EvilOne\" Minayev" <evilone omen.ru> writes:
"Walter" <walter digitalmars.com> wrote in message
news:9sgcul$10f4$1 digitaldaemon.com...

 None of them. I intend to have it (the default D calling convention)
 unspecified, so the compiler will be free to use whatever works best for

 code gen for that particular function. This makes interprocedural
 optimizations possible. I strongly dislike the pointless proliferation of
 calling conventions found in win32.

Optimizations are good, but what about assembler routines? I believe that order of arguments on stack is not really important since you can use their names instead, but who should clean the stack - callee or caller? BTW, another syntactic sugar suggestion - a short way to declare assembler rountines: make it so that body of function can consist of a single asm block: void DrawLine(int x1, int y1, int x2, int y2, int color) asm { // assembler code goes here } Or an "asm" attibute: void asm DrawLine(int x1, int y1, int x2, int y2, int color) { ... } This way, the only thing generated by the compiler itsel would be the typical entry code, everything else is on programmer's part. Could be handy.
 Microsoft doesn't exactly use the stdcall for Windows API calls - first of
 all, it varies (pascal on 16 bit machines, syscall on OS/2), and second,
 they mangle the names differently than stdcall for system calls. After

 they are windows API calling conventions, and who (besides the compiler
 implementor) really cares what it is, so why not call it the "windows"
 calling convention? It's easy to remember <g>.

Okay, I give up. You can be very persuasive, you know. =) Concerning name mangling. Are you going to define a single scheme that must be used by each and any compiler, or is it implementation- defined?
Nov 09 2001
parent reply "Walter" <walter digitalmars.com> writes:
"Pavel "EvilOne" Minayev" <evilone omen.ru> wrote in message
news:9sglrt$1ae5$1 digitaldaemon.com...
 Optimizations are good, but what about assembler routines? I believe that
 order of arguments on stack is not really important since you can use
 their names instead, but who should clean the stack - callee or caller?

If you are writing assembler routines, the options are: 1) use the inline assembler, where you don't care about call/return conventions 2) declare the external assembler function with C call/return conventions
 Concerning name mangling. Are you going to define a single scheme
 that must be used by each and any compiler, or is it implementation-
 defined?

I'll define a scheme and recommend that people use it, though it won't be part of the language spec.
Nov 09 2001
parent reply "Pavel \"EvilOne\" Minayev" <evilone omen.ru> writes:
"Walter" <walter digitalmars.com> wrote in message
news:9si4hr$2ved$1 digitaldaemon.com...

 If you are writing assembler routines, the options are:
 1) use the inline assembler, where you don't care about call/return
 conventions
 2) declare the external assembler function with C call/return conventions

BTW what's the point in caller cleaning the stack? I always thought that callee, using RET n on x86, for example, can do it faster. Since you aren't going to support C-style varargs...
Nov 09 2001
parent "Walter" <walter digitalmars.com> writes:
"Pavel "EvilOne" Minayev" <evilone omen.ru> wrote in message
news:9sik7a$7ed$1 digitaldaemon.com...
 "Walter" <walter digitalmars.com> wrote in message
 news:9si4hr$2ved$1 digitaldaemon.com...

 If you are writing assembler routines, the options are:
 1) use the inline assembler, where you don't care about call/return
 conventions
 2) declare the external assembler function with C call/return


 BTW what's the point in caller cleaning the stack? I always thought
 that callee, using RET n on x86, for example, can do it faster. Since
 you aren't going to support C-style varargs...

The code generator can be clever and avoid any stack cleanups at all, which of course is faster.
Nov 10 2001
prev sibling parent reply Russell Borogove <kaleja estarcion.com> writes:
Walter wrote:
 
 None of them. I intend to have it (the default D calling convention)
 unspecified, so the compiler will be free to use whatever works best for the
 code gen for that particular function. This makes interprocedural
 optimizations possible. I strongly dislike the pointless proliferation of
 calling conventions found in win32.

So any external code that calls into D code can only safely do so to a D function that is defined with a non-default calling convention? I guess that lets you control the entry points... -RB
Nov 09 2001
parent "Walter" <walter digitalmars.com> writes:
"Russell Borogove" <kaleja estarcion.com> wrote in message
news:3BEC2016.D83E8ED3 estarcion.com...
 Walter wrote:
 None of them. I intend to have it (the default D calling convention)
 unspecified, so the compiler will be free to use whatever works best for


 code gen for that particular function. This makes interprocedural
 optimizations possible. I strongly dislike the pointless proliferation


 calling conventions found in win32.

so to a D function that is defined with a non-default calling convention? I guess that lets you control the entry points...

Yes. <g> I want to leave the door open for aggressive interprocedural optimizations.
Nov 09 2001
prev sibling next sibling parent reply "Ben Cohen" <bc skygate.co.uk> writes:
In article <9sb0c1$ceq$1 digitaldaemon.com>, "Pavel \EvilOne\ Minayev"
<evilone omen.ru> wrote:

 Static attribute. Are static local variables supported?

If you have public and private (etc.) attributes, you no longer appear to need static to make items private to a module. Of course, you still need them in functions and classes, but is there any other requirement for them at the top-level? (Especially for functions.)
Nov 08 2001
parent "Pavel \"EvilOne\" Minayev" <evilone omen.ru> writes:
"Ben Cohen" <bc skygate.co.uk> wrote in message
news:9sdsmg$2dca$1 digitaldaemon.com...

 Static attribute. Are static local variables supported?


LOL =)
 If you have public and private (etc.) attributes, you no longer appear to
 need static to make items private to a module.  Of course, you still need
 them in functions and classes, but is there any other requirement for them
 at the top-level?  (Especially for functions.)

Nov 08 2001
prev sibling next sibling parent reply "Pavel \"EvilOne\" Minayev" <evilone omen.ru> writes:
I believe that extern() property states that function
has no body, so the following is illegal:

    extern(Windows) int WindowProc() { }

Is it so? If it is, how about WinAPI callbacks?



Is it legal to define names for parameters of extern
function? Is it legal to omit names of parameters
of implemented function? Like that:

    extern(Windows) int LineTo(HDC hDc, int x, int y);
    void TimerProc(HWND, uint, uint id, uint) { switch (id) { ... } }



How are function pointers declared? I remember a discussion
of this topic not long ago, but what is the official way?



Are pointers to methods supported? Are they like in Delphi (kewl)
or in C++ (almost useless)?
Nov 09 2001
parent reply "Walter" <walter digitalmars.com> writes:
"Pavel "EvilOne" Minayev" <evilone omen.ru> wrote in message
news:9sglru$1ae5$2 digitaldaemon.com...
 I believe that extern() property states that function
 has no body, so the following is illegal:

     extern(Windows) int WindowProc() { }

 Is it so? If it is, how about WinAPI callbacks?

It is legal, despite what the doc says (!).
 Is it legal to define names for parameters of extern
 function? Is it legal to omit names of parameters
 of implemented function? Like that:

     extern(Windows) int LineTo(HDC hDc, int x, int y);
     void TimerProc(HWND, uint, uint id, uint) { switch (id) { ... } }

Yes.
 How are function pointers declared? I remember a discussion
 of this topic not long ago, but what is the official way?

I haven't done that yet.
 Are pointers to methods supported?

No. Pointers to methods are nothing but confusion.
 Are they like in Delphi (kewl)
 or in C++ (almost useless)?

How do they work in Delphi?
Nov 09 2001
parent reply "Pavel \"EvilOne\" Minayev" <evilone omen.ru> writes:
"Walter" <walter digitalmars.com> wrote in message
news:9si93q$o4$2 digitaldaemon.com...

 How are function pointers declared? I remember a discussion
 of this topic not long ago, but what is the official way?

I haven't done that yet.

My suggestion would be something like: int(int x, int y) OnMouseMove;
 Are pointers to methods supported?

No. Pointers to methods are nothing but confusion.

Disagreed. They are really useful for writing callback- based event-driven system - GUI toolkits are a typical example of this. Compare VCL, which relies on pointers to methods, and MFC, which uses map tables. Which one is easier?
 Are they like in Delphi (kewl)
 or in C++ (almost useless)?

How do they work in Delphi?

type TButton = class OnMouseMove: procedure(x, y: integer) of object; end; TMyForm = class(TForm) cmdOk: TButton; ... constructor Create; procedure cmdOk_MouseMove(x, y: integer); end; constructor TMyForm.Create; begin cmdOk.OnMouseMove := cmdOk_MouseMove; end; procedure TMyForm.cmdOk_MouseMove(x, y: integer) begin ... end; In other words, in Delphi pointer to method is universal - it can point to any method of any class, whose parameters and return type matches the declaration. Also, unlike C++ one, it does store the pointer to object to which method belongs! But these are technical details, what it gives to programmers is ability to define callbacks for methods in absolutely the same way as for global functions, and compiler takes care of the rest. Nothing close compared to weird and useless C++ method pointers. The entire VCL library is built on this system - and I believe it's one of the easiest, yet powerful, GUI toolkits for Windows.
Nov 09 2001
next sibling parent "Pavel \"EvilOne\" Minayev" <evilone omen.ru> writes:
BTW in C++Builder, pointers to methods are declared
using __closure keyword. Isn't that funny =)
Nov 10 2001
prev sibling next sibling parent "Pavel \"EvilOne\" Minayev" <evilone omen.ru> writes:
On second thought, I came to an idea that it'd be nice
if all function pointers would be "universal" - that is,
able to point to global function as well to method.
Internally, it would be represented by a simple struct:

    struct
    {
        Object object;
        void* function;
    }

If pointer is to global function, the .object field
is null, otherwise, its value is used as "this" pointer
when calling method.

This requires twice as large memory for function pointers...
But memory isn't an issue nowadays, especially considering
that there aren't many function pointers in programs, and
it is very unlikely to have arrays of them. On other hand,
methods could be used in any situation where callback is
required, which can be damn useful.

As an example, consider WindowProc callback. In MDI application,
there are several (child) windows which are represented by
instances of a single class. It would be great if I could use
a method as a WindowProc, but no, I have to define a single
static method, make a linked-list of all windows and scan
through it each time I get a message to determine which window
should handle it... of course, nothing can be done here, but
at least similar situations in libraries written in D could be
prevented.
Nov 10 2001
prev sibling parent reply "Pavel \"EvilOne\" Minayev" <evilone omen.ru> writes:
Sooo?
Nov 13 2001
parent "OddesE" <OddesE_XYZ hotmail.com> writes:
"Pavel "EvilOne" Minayev" <evilone omen.ru> wrote in message
news:9srips$pi$1 digitaldaemon.com...
 Sooo?

I am with this on Pavel. They are *very* usefull, I know so from experience. MFC message maps suck :( -- Stijn OddesE_XYZ hotmail.com http://OddesE.cjb.net __________________________________________ Remove _XYZ from my address when replying by mail
Feb 05 2002
prev sibling parent reply "Pavel \"EvilOne\" Minayev" <evilone omen.ru> writes:
If module B imports module C, and module A
imports B, does A import C?
Nov 10 2001
parent reply "Walter" <walter digitalmars.com> writes:
"Pavel "EvilOne" Minayev" <evilone omen.ru> wrote in message
news:9sjljv$v8m$1 digitaldaemon.com...
 If module B imports module C, and module A
 imports B, does A import C?

Scoping issues aside, yes.
Nov 10 2001
parent reply "Pavel \"EvilOne\" Minayev" <evilone omen.ru> writes:
"Walter" <walter digitalmars.com> wrote in message
news:9skeha$1dh9$2 digitaldaemon.com...

 "Pavel "EvilOne" Minayev" <evilone omen.ru> wrote in message
 news:9sjljv$v8m$1 digitaldaemon.com...
 If module B imports module C, and module A
 imports B, does A import C?

Scoping issues aside, yes.

So there's no way to import a module for my own, "private" use? Something like that: import vector; // this is visible to everybody private import math; // this is used internally and thus is visible only to myself And then, forbid any constants and types from private- imported modules to be used in public declarations?
Nov 11 2001
parent reply "Walter" <walter digitalmars.com> writes:
Hmm, private imports. That might be a good idea!

"Pavel "EvilOne" Minayev" <evilone omen.ru> wrote in message
news:9slg8k$23nj$1 digitaldaemon.com...
 "Walter" <walter digitalmars.com> wrote in message
 news:9skeha$1dh9$2 digitaldaemon.com...

 "Pavel "EvilOne" Minayev" <evilone omen.ru> wrote in message
 news:9sjljv$v8m$1 digitaldaemon.com...
 If module B imports module C, and module A
 imports B, does A import C?

Scoping issues aside, yes.

So there's no way to import a module for my own, "private" use? Something like that: import vector; // this is visible to everybody private import math; // this is used internally and thus is visible only to myself And then, forbid any constants and types from private- imported modules to be used in public declarations?

Nov 19 2001
parent reply Ben Cohen <bc skygate.co.uk> writes:
On Mon, 19 Nov 2001 09:44:01 +0000, Walter wrote:

 Hmm, private imports. That might be a good idea!
 

Actually, could you explain why public imports are a good idea (in particular as a default)?
Nov 20 2001
next sibling parent "Pavel Minayev" <evilone omen.ru> writes:
"Ben Cohen" <bc skygate.co.uk> wrote in message
news:9td75g$4ep$1 digitaldaemon.com...
 On Mon, 19 Nov 2001 09:44:01 +0000, Walter wrote:

 Hmm, private imports. That might be a good idea!

Actually, could you explain why public imports are a good idea (in particular as a default)?

I agree. Module imports must be private by default. This would provide better control over them.
Nov 20 2001
prev sibling parent reply "Walter" <walter digitalmars.com> writes:
"Ben Cohen" <bc skygate.co.uk> wrote in message
news:9td75g$4ep$1 digitaldaemon.com...
 On Mon, 19 Nov 2001 09:44:01 +0000, Walter wrote:
 Hmm, private imports. That might be a good idea!

particular as a default)?

We obviously are approaching this from different directions :-)
Nov 20 2001
parent reply Ben Cohen <bc skygate.co.uk> writes:
On Tue, 20 Nov 2001 17:38:05 +0000, Walter wrote:

 Hmm, private imports. That might be a good idea!

particular as a default)?

We obviously are approaching this from different directions :-)

Yes, I think so too. OK then, first I'll explain why I think private imports would be a better default :-) Suppose you have a module A which imports other modules B, C, and D. I think that it is more likely that you don't want all the names in B, C and D to be imported into an application when you import A. (E.g., A = http library, B = networking, etc.) Not importing B, C and D when the calling application imports A would be better software engineering; otherwise you would have names added to your namespace which you didn't expect. Public imports are a bit like inheritance (and you don't make "public" the default attribute for class members). Of course, perhaps you are writing an application which needs to use module B independently (e.g., it uses http, and also an extra networking protocol); you can then "import A, B;" in your application. In the presumably less common case where importing A always requires the application to import B explicitly, then you do need a public import. (E.g., the application has to open the connection itself for the http library to work?) But I think the private import is the more common and natural default.
Nov 21 2001
next sibling parent Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
Overall, I like this idea a lot.  However, I would note that, unlike
inheritance,
if you privately import a library and then another module imports the same
library, we don't want duplicate symbols of everything.  It seems to me that we
should have only one copy of the module, no matter how many of the chains of
modules import it.

Thus, it really isn't a "private" import...it's more of an "extern/intern"
issue.
I would suggest that the "public" import syntax then be:

extern import A,B;

while the "private" syntax is just:

import C,D;



Also, a side effect of less namespace pollution is that you don't have as many
dependencies at build time.  Say module A imports B&C privately, and D imports
A.
If you modify B, then A will need to be rebuilt...but D does not.  If all
imports
are public, then a modification to B causes a rebuild of D.  On the other hand,
if
A also includes a (public) import of E, then modifying E causes rebuilds of
both A
and D, since both contain the names & types in it.

--
The Villagers are Online! villagersonline.com

.[ (the fox.(quick,brown)) jumped.over(the dog.lazy) ]
.[ (a version.of(English).(precise.more)) is(possible) ]
?[ you want.to(help(develop(it))) ]
Nov 21 2001
prev sibling parent reply "Walter" <walter digitalmars.com> writes:
"Ben Cohen" <bc skygate.co.uk> wrote in message
news:9tfs9k$1uhi$1 digitaldaemon.com...
 Public imports are a bit like inheritance (and you don't make "public" the
 default attribute for class members).

Actually, D does <g>. The idea is to minimize the fluff for quick & dirty programs, while providing the facilities for the more carefully engineered production code.
Nov 22 2001
parent reply Ben Cohen <bc skygate.co.uk> writes:
On Fri, 23 Nov 2001 00:28:09 +0000, Walter wrote:


 "Ben Cohen" <bc skygate.co.uk> wrote in message
 news:9tfs9k$1uhi$1 digitaldaemon.com...
 Public imports are a bit like inheritance (and you don't make "public"
 the default attribute for class members).

Actually, D does <g>. The idea is to minimize the fluff for quick & dirty programs, while providing the facilities for the more carefully engineered production code.

Oh, I missed that -- so the keyword "public" would be redundant for class members? That means either that protected (say) should be the default for classes, or else my argument doesn't work any more, depending on which way you look at it. ;)
Nov 23 2001
parent "Walter" <walter digitalmars.com> writes:
"Ben Cohen" <bc skygate.co.uk> wrote in message
news:9tl3ju$1jdj$1 digitaldaemon.com...
 On Fri, 23 Nov 2001 00:28:09 +0000, Walter wrote:
 "Ben Cohen" <bc skygate.co.uk> wrote in message
 news:9tfs9k$1uhi$1 digitaldaemon.com...
 Public imports are a bit like inheritance (and you don't make "public"
 the default attribute for class members).

Actually, D does <g>. The idea is to minimize the fluff for quick & dirty programs, while providing the facilities for the more carefully engineered production code.

members?

It is the default, but is not redundant. For example, if you switch to private, with public you can switch back again.
 That means either that protected (say) should be the default for classes,
 or else my argument doesn't work any more, depending on which way you look
 at it.  ;)

<g>
Nov 23 2001