# D enters Tiobe top 20

Doc Andrew x at x.com
Tue Nov 12 19:05:19 UTC 2019

```On Tuesday, 12 November 2019 at 11:31:43 UTC, Walter Bright wrote:
>
> True, but D doesn't have a prover anyway :-)
>

...yet :)

But in one sense, we already do. The run-time behavior of
disabled assertions and checks basically just assumes you've
worked through a "proof" of the program using your unit-testing.

>
> I last tried Spark many years ago, and discovered its contract
> prover was so limited I concluded it had little practical
> value. (If I recall, it couldn't deduce things like odd and
> even.) I'm sure it has improved since, but how much, I have no
> idea.

You might be asking too much from some of the solvers. It's worth
slogging through some manual proofs with a proof assistant like
Coq (highly-recommended resource:
https://softwarefoundations.cis.upenn.edu/). After that, what an
SMT solver is able to do on it's own seems very nice :)

Having said that, SPARK still requires a frustrating amount of
hand-holding at times. You're able to do things like this now:

```
-------------------------------------------
-------------------------------------------
package double
with SPARK_Mode => On
is
type SomeArrayType is array (Positive range <>) of Natural;

function doubleArray(arr : in SomeArrayType) return
SomeArrayType
with
Global => null,
Depends => (doubleArray'Result => arr),
-- set arbitrary range here in precondition to avoid
overflow
Pre => (for all idx in arr'Range => arr(idx) in
0..20000),
-- prove that everything in the return array is even
Post => (for all idx in arr'Range =>
isEven(doubleArray'Result(idx)));

function isEven(num : in Natural) return Boolean with
Contract_Cases =>
(num rem 2 = 0 => isEven'Result = True,
num rem 2 /= 0 => isEven'Result = False);

end double;

-------------------------------------------
-------------------------------------------
package body double is

function doubleArray(arr : in SomeArrayType) return
SomeArrayType with
SPARK_Mode => On
is
doubled : SomeArrayType(arr'Range) := (others => 0);
begin
for i in arr'Range loop
doubled(i) := 2 * arr(i);

pragma Loop_Invariant(for all j in arr'First .. i =>
doubled(j) = 2 * arr(j));
end loop;

return doubled;
end doubleArray;

function isEven(num : in Natural) return Boolean with
SPARK_Mode => On
is
begin
if num rem 2 = 0 then
return True;
else
return False;
end if;
end isEven;
end double;

-------------------------------------------
-------------------------------------------

with double; use double;

procedure Main
with SPARK_Mode => On
is
arr : SomeArrayType := (3, 7, 8, 0, 1);
result : SomeArrayType := doubleArray(arr);
begin
for i in result'Range loop
end loop;
end Main;
```

The lame thing is the pragma Loop_Invaraiant. In order to be able
to
make any conclusions about the array as a whole, you've got to
explain how
the array looks at each point in the loop. Without that, the
prover can't
prove that your post-condition is true. My understanding is that
SPARK needs
a lot fewer of these than it used to, but it's still annoying.

Still, I think it's kind of neat that you can prove that kind of
behavior at compile-time, no run-time checks or unit-tests
required!

-Doc
```