December 10, 2005
Manfred Nowak wrote:
> Ivan Senji wrote:
> 
> [...]
> 
>>x.a().b().c() === c(b(a(x)));
> 
> [...]
> 
> Am I right, that you start to proof your claim that some of the currently illegal expressions should be made legal by an example that is in fact illegal and then stating that it should be legal?
> 

No. I am just trying to explain why the example you think is illegal is in fact legal.

So (to make sure) you are saying that x.a().b().c() is illegal?
Well if that is so, i think my proof is a good one :)
December 10, 2005
On Sat, 10 Dec 2005 11:33:39 +0000 (UTC), Manfred Nowak wrote:


Manfred,
you *must* be having a joke with us.

If one has

  x.a().b().c()

how can code for the call of c() be generated until such time as x.a().b()
has been evaluated by the compiler? Because to call c() the compiler would
have to know the vtable entry for it, and that means it would have to know
the class that b() returns. And to know that, it must work out what class
a() returns first. Thus the compiler must evaluate this as

   call the method a() from the vtable of class x.
   call the method b() from the vtable of the class from the previous call.
   call the method c() from the vtable of the class from the previous call.

There is no other sane way of doing it.

It can't call c() before it calls b(), and it can't call b() before it
calls a().

This isn't theory its practice.

-- 
Derek Parnell
Melbourne, Australia
11/12/2005 12:15:15 AM
December 10, 2005
Chris Sauls wrote:

[...]
> So which way is it?  Must values be reachable at compile time or not?  Clearly, not, just as you asserted previously, and I asserted recently.

Right. I had serious concern in writing about values, because I meant the _way_ how to reach the value instead of any knowledge on the value itself. Imitating the notation of the foregoing post seems to be secure, but it wasn't.

> As for postfix operators being lest-associative... it really just doesn't matter.

Postfix operators are not left associative in D.

[...]
> It doesn't make any sense any other way.

Agreed.

-manfred
December 10, 2005
Ivan Senji wrote:

[...]
> So (to make sure) you are saying that x.a().b().c() is illegal?

In case of your example: yes, its illegal. But that does not mean, that every string of postfixes is illegal.

-manfred
December 10, 2005
Manfred Nowak wrote:
> Ivan Senji wrote:
> 
> [...]
> 
>>So (to make sure) you are saying that x.a().b().c() is illegal?
> 
> 
> In case of your example: yes, its illegal. But that does not mean, that every string of postfixes is illegal.
> 

Can you please enlighten me and explain why is x.a().b().c() illegal?
December 10, 2005
Bruno Medeiros wrote:

[...]
> In other words: "the grammar is built to support the same precedence and associativity semantics as C/C++"

Look at the promise of not reordering (sub)expressions for the operators `+' and `*' in case one of their operands is a floating point value.

What a nuisance if reordering genrally does not take place.

-manfred
December 10, 2005
Derek Parnell wrote:

[...]
> you *must* be having a joke with us.
> 
> If one has
> 
>   x.a().b().c()
> 
> how can code for the call of c() be generated until such time as
> x.a().b() has been evaluated by the compiler?
[...]

Derek,

Chris Sauls finally got what I was talking of all the time.

His words in this thread:

"You are right insofar as the types being the important thing at compile time, however the types /are/ reachable in left-associative manner.  The /values/ are not, which means the order of evaluation at /runtime/ is different than the associativity, which is a /compile time/ property of expressions, not a /runtime/ one."

That means `x.a().b()' must be evaluated only as far as the type of this subexpression is of concern. That can be done by looking at the return types of `a()' and then `b()'. Nothing more has to be done.

After that at least the types of `x.a()', `x.a().b()' are on the stack in that order. Then the compiler writer might very well decide to generate the code for the function calls, when popping the types off the stack, thereby defining the evaluation order by `x.a().b().c()', then `x.a().b()' and then `x.a()'.

It is also possible, that the compiler assigns different cores for the code generation of the calls and combines the results to a linear code sequence in the order in which the generated fragments return to the main thread.

And so on ...

-manfred
December 10, 2005
In article <Xns97289C2827399svv1999hotmailcom@63.105.9.61>, Manfred Nowak says...
>
>Derek Parnell wrote:
>
>[...]
>> you *must* be having a joke with us.
>> 
>> If one has
>> 
>>   x.a().b().c()
>> 
>> how can code for the call of c() be generated until such time as
>> x.a().b() has been evaluated by the compiler?
>[...]
>
>Derek,
>
>Chris Sauls finally got what I was talking of all the time.
>
>His words in this thread:
>
>"You are right insofar as the types being the important thing at compile time, however the types /are/ reachable in left-associative manner.  The /values/ are not, which means the order of evaluation at /runtime/ is different than the associativity, which is a /compile time/ property of expressions, not a /runtime/ one."
>
>That means `x.a().b()' must be evaluated only as far as the type of this subexpression is of concern. That can be done by looking at the return types of `a()' and then `b()'. Nothing more has to be done.
>
>After that at least the types of `x.a()', `x.a().b()' are on the stack in that order. Then the compiler writer might very well decide to generate the code for the function calls, when popping the types off the stack, thereby defining the evaluation order by `x.a().b().c()', then `x.a().b()' and then `x.a()'.
>
This is completely ridiculous - it cannot evaluate  x.a().b().c() without
evaluating x.a() and x.a().b() first.

Is this a sick joke?


December 10, 2005
While I must concur with Kris and Derek that the whisper syntax is unambiguous, I disagree with its philosophy.

In article <dnck45$2sdj$1@digitaldaemon.com>, Kris says...

>These are aliased both as opCall() and opShl()/opShr(). Obviously, this supports the C++ iostream syntax:
>
>Writer write;
>
>Reader read;
>
>write << 10 << "green bottles";
>read >> count >> description.
>

One of the best things about D is type safe variadic arguments. Do we really need to go back to the bad old days of C++?

writef/readf accomplish all the goals of stream insertion, but do not suffer from the lack of atomicity. Consider the following example,

Thread 1:
write ("Thread 1:") ('a') ('b') ('c');

Thread 2:
write ("Thread 2:") (1) (2) (3);

The output could be any number of the following:
Thread 1:Thread2:12ab3c
Thread 2:12Thread 1:abc3
Thread 1:abThread 2:1c23
..

Now look at this example,
Thread 1:
writefln("Thread 1: %s %s %s", 'a', 'b', 'c');

Thread 2:
writefln("Thread 2: %d %d %d", 1, 2, 3);

The output is either
Thread 1: a b c
Thread 2: 1 2 3
--- or ---
Thread 2: 1 2 3
Thread 1: a b c

This makes the output much simpler, since writef can be synchronized. Moreover, writef and readf make it easier to specify things like formatting. Just add some format args, and you can spitout hex output or binary just as easily as decimal.

Ultimately, I believe the whisper syntax should be avoided since it seems redundant and error prone, not mention incongruous with the D style.


December 10, 2005
MWolf wrote:

[...]
>> thereby defining the evaluation order
>> by `x.a().b().c()', then `x.a().b()' and then `x.a()'.
> This is completely ridiculous - it cannot evaluate x.a().b().c() without evaluating x.a() and x.a().b() first.
[...]

Ooops. I meant
"thereby defining the evaluation order by `typeof(x.a().b()).c()',
then `typeof(x.a()).b()' and then `x.a()'."

You decide whether you want it fast or ordered. If you want it ordered use the provided ordering mechanisms.

-manfred