0

I've got a procedure in a SPARK package that calls some functions from a none SPARK package.

procedure do_monitoring is
   U_C1 : constant Float := Sim.Get_U_C1;
   I_L1 : constant Float := Sim.Get_I_L1;
   U_C2 : constant Float := Sim.Get_U_C2;
   I_L2 : constant Float := Sim.Get_I_L2;
begin
   pragma Assert (U_C1 in Float_Signed1000);
   pragma Assert (I_L1 in Float_Signed1000);
   pragma Assert (U_C2 in Float_Signed1000);
   pragma Assert (I_L2 in Float_Signed1000);
   --  Monitor PFC intermediate voltage
   monitor_signal (monitor_pfc_voltage, U_C1);
   --  Monitor PFC inductor current
   monitor_signal (monitor_pfc_current, I_L1);
   --  Monitor output voltage
   monitor_signal (monitor_output_voltage, U_C2);
   --  Monitor output inductor current
   monitor_signal (monitor_output_current, I_L2);
end do_monitoring;

GNAT provides me with info: implicit function contract not available for proof (<function_name> may not return) for all four declaration lines where I call functions from global protected types.

The protected types functions are defined in a non SPARK package as follows and use the record Sim_Out which is declared within the protected types private section. All of the records values are initialised with 0.0.

function Get_I_L1 return Float is
begin
   return Sim_Out.I_L1;
end Get_I_L1;

function Get_U_C1 return Float is
begin
   return Sim_Out.U_C1;
end Get_U_C1;

function Get_I_L2 return Float is
begin
   return Sim_Out.I_L2;
end Get_I_L2;

function Get_U_C2 return Float is
begin
   return Sim_Out.U_C2;
end Get_U_C2;

What are the alternatives to solve this? I did already add some pragmas to provide the prover with additional information subtype Float_Signed1000 is Float range -1_000.0 .. 1_000.0 but that didn't work out as I expected.

I'd like to here your advice on this topic.

Simon
  • 594
  • 1
  • 6
  • 13
  • I'd follow up the hint "function may not return" ... we don't have the source for Sim_Get_* but you do. Are there any paths through these that don't return? –  Jan 23 '18 at 21:12
  • @BrianDrummond Wait a sec, I'll quickly edit my question. – Simon Jan 23 '18 at 21:13
  • I just googled "implicit function contract not available for proof" (without the quotes; with the quotes I just get this question) and the seventh answer looks pretty relevant; in the last section. Google ranked this hit higher when I added "spark2014". – Simon Wright Jan 23 '18 at 21:20
  • @SimonWright I would be grateful if you pasted the URL :-) – Simon Jan 23 '18 at 21:24
  • 1
    Try [this](https://docs.adacore.com/spark2014-docs/html/ug/en/source/how_to_write_subprogram_contracts.html#subprogram-termination) ... – Simon Wright Jan 23 '18 at 22:11
  • @SimonWright Chapter 7.4 was actually nowhere on my first three google result pages :-/ but I skimmed through that chapter before :-/ thats painful. Would you prefer adding an answer yourself our leaving the job to me? – Simon Jan 23 '18 at 22:17
  • aaah ... from the sidelines. The problem isn't that they don't terminate, it's that being not-Spark, they can't be proven to terminate. So you need to to something like redirect them through a Spark package that provides the terminate annotation (and then probably just renames the functions) right? –  Jan 23 '18 at 22:29
  • @BrianDrummond You're probably right because they are the only functions that are neither in my package nor in a standard library package. The given part of the user guide is about a SPARK_Mode package. Which solution would you recommend if I wouldn't be able to edit the referenced package? – Simon Jan 23 '18 at 22:40
  • Caveat : I am not a SPARK user, I'm learning by watching here. I'm speculating something like `package wrappers is ... function Get_I_L1 return Float; pragma Annotate (...Get_I_L1);` (following Simon's link) and a `renames` in the package body to the real (non-Spark) function you can't edit. Maybe Ada-2012 will allow the renaming in the package spec. –  Jan 23 '18 at 22:53

1 Answers1

3

If I'm allowed to edit the Sim package, I can say for example

package Sim
with SPARK_Mode
is
   function Get return Float
   with Annotate => (Gnatprove, Terminating);
end Sim;

(that’s using AdaCore’s spark2017 version), and follow up with a non-SPARK body

package body Sim is
   function Get return Float is (42.0);
end Sim;

The report shows that Sim.Get has been skipped.

How later releases of SPARK2014 will react to this I don't know, because the implication from the User Guide is that Annotate sets up a goal for the prover, and yet we’ve not allowed it to look into the body of Sim to check.

Maybe there’s some more in the Reference Manual - go to adacore.com, select Resources/Documentation/SPARK.

Simon Wright
  • 25,108
  • 2
  • 35
  • 62
  • Isn't there a possibility to tell SPARK that I have tested the function guarantee that it terminates? How do you solve problems like this, when you have a package that can not be in SPARK mode, because it uses features not allowed in SPARK, whose subprograms are called by a SPARK package. Is Brian Drummonds wrapper package a viable alternative? – Simon Jan 24 '18 at 10:37
  • How would the prover know, next year, that that was still true? I think there has to be some point at which you have to justify this sort of thing - in a validation report, perhaps. Brian’s suggestion would help if you couldn’t change the `Sim` package, for instance, but down at the bottom there’s still going to be that unprovability. I have a feeling that the prover reports when it sees a `pragma Assume`, would be nice if that worked here too (that way you’d know which parts you had to justify "by hand"). – Simon Wright Jan 24 '18 at 19:50
  • I've chosen to go with the annotation to justify the message. I found some more information in the [user guide](https://docs.adacore.com/spark2014-docs/html/ug/en/source/how_to_use_gnatprove_in_a_team.html?highlight=annotate#justifying-check-messages) and I tried it by adding `pragma Annotate (GNATprove, False_Positive, "may not return", "checked by Simon")` below each of the marked lines. It didn't work though, probably because it is not an error or warning but an info. Any suggestions? – Simon Jan 26 '18 at 21:32
  • The link I gave above to [7.4.6](https://docs.adacore.com/spark2014-docs/html/ug/en/source/how_to_write_subprogram_contracts.html#subprogram-termination) shows that you need a different form of `pragma Annotate` for this purpose (or the aspect I showed in the answer; this annotation is specific to the named subprogram, whereas the one you’ve tried to use is specific to the place in the code). – Simon Wright Jan 26 '18 at 23:13
  • Thanks man, that totally worked. I activated SPARK in the callees package specification and added the suggested annotation with the `with` keyword. I already tried it short after you gave the answer but I had an active warning about a non initialised array that made GNATprove terminate and not checking other things. I didn't know that and thought the annotation just didn't work. GNATprove went on checking the rest of the source in succession to me fixing the arrays initialisation and the annotation worked. – Simon Jan 27 '18 at 16:00