an old topic (pun intended)

Davidson Corry davidsoncorry at comcast.net
Thu Oct 27 13:02:25 PDT 2011


Oooh! Now we're getting somewhere! You and bearophile have opened my eyes.

On 10/27/2011 1:17 AM, Timon Gehr wrote:
 > ...your example shows an extreme case and from that you
 > conclude a general statement. That almost never works.

I merely intended to show that my proposed syntax could *handle* the 
extreme case, not to prove that it was necessary. The "case" I presented 
was not only extreme but silly, and purely for purposes of illustration.

I was thinking less of syntax elegance and orthogonality, and more of 
easing the compiler's job. All the compiler would have to do would be to 
pluck (the underlined text)

     out(T preT = <some complete expression>)
         ===================================

from the out "argument list" and inject it into the head of the function 
body, as though by mixin. However, your syntax works too:

 > Often it is way more convenient to just write old(exp) than
 > 1. think of a nice name for capturing the prestate.
 > 2. change the signature of the out contract.
 > 3. move the cursor back to where you were before.
 > 4. write the name again.

Just look for phrases of the form 'out(some complete expression)' in the 
post-condition body, hoist out the 'some complete expression' and 
prepend an 'auto fresh_symbol_x = ', then mix that into the head of the 
function.

In fact, let us make the notation truly D-flavored:

     void foo(int n, string s)
     out {
         assert(count == old!count + 1, "count is wrong");
         assert(!old!(test_me(n, s, count)) || test_me(n, s, count), 
"implication fails");
     }
     body {
         // body of foo()...
     }

gets a lowering as

     void foo(int n, string s) {
         // prestate-capture injected "mixin"
         auto fresh_symbol_1 = count;
         auto fresh_symbol_2 = test_me(n, s, count);

         // body of foo()...

         // injected post-condition tests,
         //  with the fresh symbols substituted for the expressions
         assert(count == fresh_symbol_1 + 1, "count is wrong");
         assert(!fresh_symbol_2 || test_me(n, s, count), "implication 
fails");
     }

This approach does not allow you to explicitly declare the type of the 
prestate-capture-expression (all fresh_symbol_n's are auto) nor to name 
it. But as you say, it also relieves you of the *requirement* to name 
and type the expression. And to be honest, I can't think of a situation 
where you would truly *need* to name an old-expression.

Another advantage of the old!expression syntax is that we don't 
introduce an additional keyword 'old' into the language, nor do we 
prevent the programmer from using 'old()' as the name of a function, nor 
do we burden the out block with a funky "argument list".

Spiffy. Thanks, guys!

-- Davidson


More information about the Digitalmars-d mailing list