August 08, 2005
In article <opsu538ejr23k2f5@nrage.netwin.co.nz>, Regan Heath says...
>
>On Mon, 8 Aug 2005 02:19:50 +0000 (UTC), AJG <AJG_member@pathlink.com> wrote:
>> # int i = 0;
>> # void f( inout int i, inout int j ) { i = 1; j = 2; }
>> # f(i, i);
>> # // Here i is 2.
>>
>> The results are quite predictable, IMHO. I don't think there is anything wrong with the language. How could this result be any different?
>
>Is it not possible that an optimisiton compiler might re-order these
>statements?
>Is it not possible that an optimising compiler might do these operations
>in parrallel on a multi cpu platform?

Good point.  Though I'm not sure that an optimizer could legally reorder these assignments, as it can't be sure poth pointers won't be referring to the same memory location.  I think this is one reason 'restrict' was added to the C spec--it allows the optimizer to do things it otherwise couldn't.

>Is there any guarantee that the operations are carried out in the order
>they have been typed? (if so, what is the point of the volatile block
>statement?)
>http://www.digitalmars.com/d/statement.html#volatile
>
>In other words, is it possible for i to be 1 or 2 depending on what the optimising compiler decides to do and/or the enviroment the code is running in.

I'm fairly sure that the IA-32 spec guarantees writes will occur in process order--it's reads and writes that might be arranged with respect to one another (the IA-32 spec isn't completely clear on this).  I suppose some architecture might not provide this guarantee, but I would think that two writes to the same memory location would still not be rearranged by such a CPU. And for what it's worth, 'volatile' is intended to prevent the optimizer from rearranging reads and writes in a code block, but it has no impact on CPU behavior.


Sean


August 08, 2005
In article <opsu6axdoj23k2f5@nrage.netwin.co.nz>, Regan Heath says...
>
>Notably:
>"Compilers can schedule, or reorder, instructions so that pipeline stalls
>occur less frequently."

They can, but this is superceded by the "as if" rule.  That is, the compiler can do whatever the heck it wants so long as the resulting code behaves in the intended fashion (assuming a single-threaded virtual machine).  As the two parameters for this function are pointers, the compiler must assume that both parameters could refer to the same memory location.


Sean


August 08, 2005
Derek Parnell wrote:

<snip>
> (A) Function name 'f' is not meaningful enough.
> (B) Argument 'i' is not meaningful enough for the context.
> (C) Argument 'j' is not meaningful enough for the context.

You mean the function's supposed to be meaningful?

> (D) Inconsistent spacing on lines 2 and 3. Use either     <identifer>=<expression>;   or     <identfier> = <expression>;
> (E) The opening brace should not be on the function declaration line.

That's a matter of personal preference.  D doesn't care what whitespace you put between which tokens.

> (F) The function body lines are not indented correctly. The standard calls
> for four spaces.
<snip>

What standard is this?

Stewart.

-- 
My e-mail is valid but not my primary mailbox.  Please keep replies on on the 'group where everyone may benefit.
August 08, 2005
On Mon, 08 Aug 2005 15:56:53 +0100, Stewart Gordon wrote:

> Derek Parnell wrote:
> 
> <snip>
>> (A) Function name 'f' is not meaningful enough.
>> (B) Argument 'i' is not meaningful enough for the context.
>> (C) Argument 'j' is not meaningful enough for the context.
> 
> You mean the function's supposed to be meaningful?
> 
>> (D) Inconsistent spacing on lines 2 and 3. Use either
>>     <identifer>=<expression>;
>>   or
>>     <identfier> = <expression>;
>> (E) The opening brace should not be on the function declaration line.
> 
> That's a matter of personal preference.  D doesn't care what whitespace you put between which tokens.
> 
>> (F) The function body lines are not indented correctly. The standard calls
>> for four spaces.
> <snip>
> 
> What standard is this?

Stewart, its a joke. I was only having a lend of Manfred. He asked for a 'review' so I gave a fictitious review in keeping with the tone of the original data. It was meant to be light-hearted and not to be taken seriously.

-- 
Derek Parnell
Melbourne, Australia
9/08/2005 2:17:37 AM
August 08, 2005
Derek Parnell <derek@psych.ward> wrote:
[...]
> I'm guessing that you are hinting that D has some really big security holes in it
[...]

You are right. And because I have learned in this group, that I have to talk until I am blue in the face when I present such a problem,  I now try the other way round: let all of you talk until you are blue in the face and do find the problem, which releases me of that burdon, or do not find the problem, which makes you aware of the fact that there might be a problem as your post shows.

If on the other hand nobody starts talking, then it is of no interest to the language and I have not wasted my time. So, because you got this pack running I answer your question as a representative of this group.


The problem with this function is indeed, that the outcome of giving the same variable to it, is undefined by design.

Therefore the task of any quality assurer is to reject this implementation: i.e. the outcome of step 2 is FAIL, with the reason above used for step 3.


So that piece of work comes back to the developing team.


Now the team has at least two choices from which this two are closest:

1) define the outcome
2) forbid this case

But according to the specs none of these can succesfully be implemented in D.

-manfred

August 08, 2005
In article <dd8360$2sm9$1@digitaldaemon.com>, Manfred Nowak says...
> 
>So that piece of work comes back to the developing team.
>
>
>Now the team has at least two choices from which this two are closest:
>
>1) define the outcome
>2) forbid this case
>
>But according to the specs none of these can succesfully be implemented in D.

Why not?  DBC should take care of both these problems:

# void f( inout int a, inout int b ) {
# in {
#     assert( &a != &b );
# }
# out {
#     assert( &a != &b || ( a == b && b == 2 ) );
# }
# body {
#     a = 1; b = 2;
# }

I grant that the in and out clauses are a bit contradictory, but I'm assuming that either one or the other would be implemented.  As for contracts not being included in release builds--some applications ship with contract checking in place.  If this is a system where lives hang in the balance, I would expect the contract code to remain (coupled with an improved assertion handler).


Sean


August 08, 2005
>The problem with this function is indeed, that the outcome of giving the same variable to it, is undefined by design.


Don't know what you are talking about.

Program statements are executed in serial order. So it is well defined order. This design is the same as in all languages that use out or inout parameter.

Sometimes it even makes sense to provide the same inout reference, for example when you are not interested in the results.

If you don't want something like this switch to a language that don't have this kind of side effects, there are enough of them. They come up with other problems in real world use, so just remember the famous saying "there is no silver bullet" in software engineering.



August 08, 2005
Sean Kelly <sean@f4.ca> wrote:

[...]
>>But according to the specs none of these can succesfully be implemented in D.
> 
> Why not?
[...]

Because the specs dont say what you get if you take the address of a formal inout parameter. This can be the address of the actual parameter as it is currently implemented in the reference compiler, but this is not guaranteed.

The same holds for the values of the formal inout parameters.

So: if you cannot change the interface and the specs stay as they are, you are lost.

To make clear what I mean:

<code>
int i= 0;

void f( inout int i){
  i= 2;
  assert( .i == i);
}

void main(){
  f( i);
}
</code>

may throw an exception according to the specs.

-manfred
August 08, 2005
llothar wrote:
>>The problem with this function is indeed, that the outcome of giving the same variable to it, is undefined by design.
> 
> 
> 
> Don't know what you are talking about. 
> 
> Program statements are executed in serial order. So it is well defined order.
> This design is the same as in all languages that use out or inout parameter.

Now this was not part of the topic, but that's not true, and the current design is flawed enough that I think it should be reexamined.

The other way to implement inout/out arguments is to read them on the function call, then write them after the call returns.  This is how any language with potential latency in message sends works (like CORBA), and it allows properties and opIndex to be used with inout parameters.  This lack of orthogonality is a problem.

The two are too different to interoperate.  If a current D function throws, any changes to an inout are stored; with a CORBA function they'd be scratched (this is the mechanically more useful option).  Then there's the fact that it removes pointer aliasing, which can be useful in some situations.

With CORBA it would be illegal to provide the same identifier to two inout parameters because of the identified but misapplied problem.  Then again, the language could just define that call evaluation order is undefined, but store evaluation order is well-defined.
August 08, 2005
llothar <llothar_member@pathlink.com> wrote:

[...]
> Program statements are executed in serial order. So it is well defined order.
[...]

Please read the specs.

Applying the same actual parameter to both formal parameters would render the first assignement in the function body useless.

And in D dead code is as illegal as expressions that do not have an effect.

Instead of undefined I also could have choosen the wording "illegal by design". Decide yourself what you will get from your boss when returning from your quality assurer with the message that you have tried to deliver illegal code.

-manfred