hello I am trying to write proof annotations from this function .. this is written using the Spark programming language
function Read_Sensor_Majority return Sensor_Type is
count1:Integer:=0;
count2:Integer:=0;
count3:Integer:=0;
overall:Sensor_Type;
begin
for index in Integer range 1..3 loop
if State(index) = Proceed then
count1:=count1+1;
elsif State (index) = Caution then
count2:=count2+1;
elsif State (index)=Danger then
count3:=count3+1;
end if;
end loop;
if count1>=2 then
overall:=Proceed;
elsif count2>=2 then
overall:=Caution;
elsif count3>=2 then
overall:=Danger;
else
overall:=Undef;
end if;
return overall;
end Read_Sensor_Majority;
begin -- initialization
State:= Sensordata'(Sensor_Index_Type => Undef);
end Sensors;
this is the .ads file
package Sensors
--# own State;
--# initializes State;
is
type Sensor_Type is (Proceed, Caution, Danger, Undef);
subtype Sensor_Index_Type is Integer range 1..3;
procedure Write_Sensors(Value_1, Value_2, Value_3: in Sensor_Type);
--# global in out State;
--# derives State from State ,Value_1, Value_2, Value_3;
function Read_Sensor(Sensor_Index: in Sensor_Index_Type) return Sensor_Type;
--# global in State;
function Read_Sensor_Majority return Sensor_Type;
--# global in State;
--# return overall => (count1>=2 -> overall=Proceed) and
--# (count2>=2 -> overall=Caution) and
--# (count3>=2 -> overall=Danger);
end Sensors;
these are the errors I am getting after examining the file using the spark examiner
Examiner Semantic Error 1 - The identifier count1 is either undeclared or not visible at this point. <b>34:27</b> Semantic Error 1 - The identifier count1 is either undeclared or not visible at this point. Examiner
Sensors.ads:34:27
Semantic Error 1 - The identifier count1 is either undeclared or not visible at this point.
You have to declare identifiers before you can reference them (with some exceptions).
Most important of all, it is a basic principle in both SPARK and Ada that specifications can be processed without any knowledge whatsoever of possible matching implementations.
As neither overall, nor count1, count2 or count3 are declared in the specification, you can't reference them there either.
Two small side notes:
Please use the same identifier style as in the language reference manual. (Leading upper-case, underscores separating words.)
Why is Sensor_Index_Type a subtype of Integer?
Just playing with SPARK myself so this is not a complete answer.
(It's worth mentioning which SPARK as there are different versions and SPARK-2014 seems to be quite a bit different from the others) I currently only have the 2006 edition of Barnes which doesn't cover the latest versions.
The basic problem is quite obvious : having provided an abstract view of the package's state --# own State; in the spec, you cannot then reach in and observe the specifics.
What to do about it is not completely clear to me, but has the outline form:
provide a more abstract form of the postconditions for Read_Sensor_Majority in the specification, and move the concrete form to the body.
One approach adopted in Ada-2012 (I don't know how applicable to Spark-2005) is to provide an additional function in the spec function satisfies_conditions (...) return boolean; which can be called in the annotations, and whose body contains the concrete implementation.
Barnes (ed. above) p.278 does show "proof functions" which can be declared in the annotations for this purpose. Their bodies then have access to the internal state to perform the concrete checks.
Given that you are showing the .ads and .adb files, I note that the proof in the .ads file is referencing items in the body. Could it be that the prover cannot reach into the body and pull these variables? (i.e. an issue of visibility.)
The message:
The identifier count1 is either undeclared or not visible at this point.
Seems to indicate that this is the case.
I don't know SPARK, so that's my best-guess.
Related
Assume having the following setup:
type My is new Integer;
type My_Acc is access My;
procedure Replace(Self : in out My_Acc; New_Int : Integer)
with Pre => New_Int /= Self.all, Post => Self'Old.all /= Self.all;
Note: Code above might not be fully valid, but I hope the concept is understandable.
Now what happens if Unchecked_Deallocation() is used on Self inside Replace
and a new Integer is allocated and set to Self (This should result in Self'Old pointing to a now invalid memory location)?
Does Ada keep kind of a snapshot where Self'Old points to the previous memory location, but before Unchecked_Deallocation() is executed?
If Self'Old would get invalid for use in the Post contract, how could you still access the previous value? Is it possible to create a manual snapshot in the Pre contract that can then be used in Post? Maybe it can be achieved using Ghost_Code?
I want to make everything in Spark, in case that changes something.
Edit: Fixed Self to in out as mentioned by Simon Wright.
Edit: Fixed type of Self to allow null
It may be that the latest versions of SPARK support access types; it used not to, at all.
First, your Not_Null_My_Acc needs to be a subtype of My_Acc, unless you meant it to be a type in its own right.
Second, you can’t deallocate Self inside Replace and allocate a new value; Self is in-mode, & hence not writable.
Third, you can’t apply ’Old to Self, because
warning: attribute "Old" applied to constant has no effect
What you can say is
Post => Self.all'Old /= Self.all;
In ARM 6.1.1(26ff) it says
Each X'Old in a postcondition expression that is enabled denotes a constant that is implicitly declared at the beginning of the subprogram body, entry body, or accept statement.
The implicitly declared entity denoted by each occurrence of X'Old is declared as follows:
...
X'Old : constant S := X;
... in other words, nothing fancy is expected, just a straight copy of (in this case) Self: not Self.all.
So, if your Replace deallocates Self, then Self’Old is a dangling reference, and erroneous.
I suggested previously that changing the postcondition to
Post => Self.all'Old /= Self.all;
would be safe; why wouldn’t that meet your requirements? is there something going on you haven’t told us about?
Note the subtle difference between Self’Old.all and Self.all’Old. The first one takes a copy of Self as it was before the call, which gets dereferenced after the call (by which time it’s pointing into hyperspace), while the second one dereferences the prior Self and copies the integer value it finds there; on return that’s still valid.
Generally speaking, Ada will raise a Constraint_Error if you attempt to dereference a null pointer (access type). However, this behavior is disabled if, for example, you have pragma Suppress (all_checks) in use.
Given this scenario, how would one go about checking to see if the access type points to 0x0 (null)?
Consider the following:
type My_Access_Type is access all My_Type'Class;
procedure myProcedure ( myAccess : in My_Access_Type ) is
begin
-- need to have check in here
end
if myAccess = null then
...
end if;
Although it won't necessarily point to 0x0. Access types are not pointers, and may be implemented in a different way than plain addresses.
Another option, that can help you, is to declare the pointer as "not null".
type My_Access is not null access My_Type;
this prevents the declaration of not initialized My_Access types.
X : My_Access; -- compile error
This solution as some disadvantages (see https://en.wikibooks.org/wiki/Ada_Programming/Types/access#Null_exclusions) and its correct usage depends on your needs.
I needed the result of a rather complex calculation to define a private type, something like this:
generic
top_m : Positive;
package Mystic is
type T is private;
private
type Table is array (Positive range <>) of Positive;
function reallyComplicatedFunction(x : Positive) return Table;
mytable : constant Table := reallyComplicatedFunction(top_m);
-- I will need mytable for calculations later
type T is array (mytable'Range) of Natural;
-- T is very different from Table, except they share their Range
end Mystic;
I needed the type T to depend on generic parameter top_m in a really complicated way, embodied by reallyComplicatedFunction(.). The function is defined in the body of package Mystic, but it does not use anything else declared by the package.
To my surprise this setup works just fine. Maybe I'm just lucky, because as far as I can tell from decyphering the ARM, this kind of invocation of the function is merely 'legal' but it is not guaranteed not to throw a Program_Error. I interpret this as "it would be too restrictive to forbid this sort of stuff entirely, but the compiler can't be expected to determine its feasibility in all cases either, so we'll just allow you to experiment with it". And then there's the rather significant possibility that I'm completely misreading the reference manual. Anyway, books on Ada give rather stern warnings about this sort of thing, typically around the discussion of pragma Elaborate et al., such that I almost didn't try this solution.
I've also tried to put the function in a private child package of Mystic, but I could not resolve circularities between the child implicitly depending on the parent and the parent specification depending on the child. Anyway, this function is not an extension of Mystic but a necessary code to initialize it.
My question would then be: where is the proper place for such a function?
ETA: at the request of Simon Wright, here's the part of the ARM I struggle with: http://www.ada-auth.org/standards/12rm/html/RM-3-11.html entries 9, 10/1 and 14:
For a construct that attempts to use a body, a check
(Elaboration_Check) is performed, as follows:
For a call to a (non-protected) subprogram that has an explicit body, a check is made that the body is already elaborated. This check
and the evaluations of any actual parameters of the call are done in
an arbitrary order.
...
The exception Program_Error is raised if any of these checks fails.
As far as I understand, the construct mytable : constant Table := etc. tries to use the body of reallyComplicatedFunction, so it must check whether it was elaborated or not. I assume - this is a weak point in my reasoning but this is what I understood - that elaboration of the body of reallyComplicatedFunction only occurs during the elaboration of the body of package Mystic, so my function won't be elaborated at the time it is called from the private part of the package specification. Nonetheless, I don't receive the Program_Error as promised when using (an instance of) the package.
ETA2: following a remark from trashgod, I've tried turning package Mystic into a non-generic one; made top_m into a visible constant and removed the genericity part. The compiler now catches the circularity I was worried about from the beginning and the program exits with Program_Error: access before elaboration. It's as if the body of a generic package was elaborated before the first instantiation, or rather before the elaboration of the specification of said package during instantiation. Since I'd expect Ada to cater to this kind of need (of hiding complex calculations needed to instantiate a package in the body of said package), I'd not be surprised if it worked as per the standard, but I don't recall reading anything like this anywhere and would like to know the exact rules. Something very smart is going on because if I make the body of the function dependent on type T, the compiler warns about 'call to Tt may occur before body is seen' at the point of package instantiation (I guess 'Tt' is some internality of type T), and when the program is run, it throws a Program_Error complaining about access before elaboration, pointing to the first place where an object of type T is instantiated by another function I have called by reallyComplicatedFunction for testing purposes.
Edit, reflecting the comment that explain why reallyComplicatedFunction should not be public.
If I understand correctly, the function does not really not depend on Mystic, but reallyComplicatedFunction should be private. In that case, I'd try putting it elsewhere, and keep the dependency on top_m. I have assumed that Table could also be moved, even though formally it is creating a dependence of reallyComplicatedFunction, Table being in its parameter profile.
To resolve, a new private place is created in a hierarchy, a private sibling gets the declarations and will only be used in the private part of original Mystic. Hence, private with in the latter's context clause.
package Top is end;
private generic
top_m : Positive;
package Top.Outsourced is
type Table is array (Positive range <>) of Positive;
function reallyComplicatedFunction(x : Positive) return Table;
end Top.Outsourced;
private with Top.Outsourced;
generic
Top_M : Positive;
package Top.Mystic is
type T is private;
private
package Initializer is new Top.Outsourced (top_m);
subtype Table is Initializer.Table;
mytable : constant Table := Initializer.reallyComplicatedFunction (top_m);
-- I will need mytable for calculations later
type T is array (mytable'Range) of Natural;
-- T is very different from Table, except they share their Range
end Top.Mystic;
package body Top.Outsourced is
function reallyComplicatedFunction(x : Positive) return Table is
Limit : Positive;
begin
Limit := Positive'Min (top_m, 1) + x/2;
return Result : Table (1 .. Limit);
end reallyComplicatedFunction;
end Top.Outsourced;
Assuming (since you didn't specify it) the array returned from reallyComplicatedFunction has the range 1..top_m, you could define a new subtype and use that as the range for both arrays:
subtype My_Range is Positive range 1..m_top
type Table is array (My_Range) of Positive;
type T is array (My_Range) of Natural;
and move both my_table and reallyComplicatedFunction inside the package body.
Compiling the following program without optimization, and then running it, I see Program_Error,
raised PROGRAM_ERROR : addreq.adb:16 explicit raise
or, updating in view of Simon Wright's answer,
raised PROGRAM_ERROR : using address
This happens when using GNAT GPL 2014 on either Mac OS X or on GNU/Linux x84_64, on Linux, strangely, only for my program. Other versions of GNAT produce code that doesn't raise, older compilers do not accept (access-to-function parameters being more recent, I'm not surprised). Since my program needs to identify addresses of subprograms, I was hoping for a definitive statement in the RM; 13.3 (11) has ramifications that grow waivers, IINM. So, referring to the program below, would
Yes_no.all'Address = No'Adress
be a true statement if interpreted by the LRM? Legit? Is Yes_No.all actually a proper way to refer to the function No (if taking the 'Address)? As there is indirection through different pointer types, one having deeper accessibility, does this change the picture? I was thinking that Yes_No.all should yield the same 'Address as No, but apparently not, with some compilers.
with System;
procedure Addreq is
function No (Ignored : Integer) return Boolean is
begin
return False;
end No;
procedure Taking
(Yes_No : access function (N : Integer) return Boolean)
is
use type System.Address;
begin
if Yes_No.all'Address /= No'Address then
raise Program_Error;
end if;
end Taking;
begin
Taking (No'Access);
end Addreq;
One more update: if I make Addreq a package and have another subprogram call Taking, thus
with Addreq; -- now a package
procedure Driver is
use Addreq;
begin
Taking (No'Access);
end Driver;
then no exception is raised.
I think it must depend on your OS and compiler. Using FSF GCC 5.1.0 on Mac OS X, your code doesn’t raise the exception.
That said, I think it’d be more natural to avoid .all’Address (I was told by one of the Ada 95 Distinguished Reviewers that he’d got into the habit of saying .all’Access when what was really needed was an appropriate type conversion). This extension of your code doesn’t raise the exception for either case.
with Ada.Text_IO; use Ada.Text_IO;
with System;
procedure Addreq is
function No (Ignored : Integer) return Boolean is
begin
return False;
end No;
procedure Taking
(Yes_No : access function (N : Integer) return Boolean)
is
use type System.Address;
begin
if Yes_No.all'Address /= No'Address then
raise Program_Error with "using address";
end if;
Put_Line ("using address was OK");
if Yes_No /= No'Access then
raise Program_Error with "using access";
end if;
Put_Line ("using access was OK");
end Taking;
begin
Taking (No'Access);
end Addreq;
(later)
I rewrote this to not use exceptions ...
with Ada.Text_IO; use Ada.Text_IO;
with System;
procedure Addreq is
function No (Ignored : Integer) return Boolean is
begin
return False;
end No;
procedure Taking
(Yes_No : access function (N : Integer) return Boolean)
is
use type System.Address;
begin
Put_Line
((if Yes_No.all'Address /= No'Address
then "using address failed"
else "using address was OK"));
Put_Line
((if Yes_No /= No'Access
then "using access failed"
else "using access was OK"));
end Taking;
begin
Taking (No'Access);
end Addreq;
With GNAT GPL 2014 on Mac OS X, this gives
$ ./addreq
using address failed
using access was OK
If Yes_No.all'Address is not equal to No'Address, then most likely Yes_No.all'Address is the address of some kind of wrapper code.
No is a function nested inside a procedure. If you say No'access, the compiler generally cannot simply create a one-word pointer whose value is the address of No. The reason is that when the code makes an indirect call through the access value, the code has to do something special so that No can access local variables belonging to addreq, which will be somewhere on the stack. For example, one way to provide this access is to pass a static link as a parameter to No; this is an extra pointer that points to addreq's stack frame, which will contain its local variables (or something along those lines). Thus, when an indirect call is made through the access, the caller has to know what the static link is. One solution is to make nested access-to-function types dope vectors, that contain the function address and the static link. Another is to generate wrapper code. The wrapper code is responsible for calling the called subprogram with the static link parameter, and the access value is then simply a one-word pointer, which is the address of the wrapper code. I believe GNAT takes this approach. The advantage is that it makes it possible to pass My_Function'access as a parameter to a C function, for use as a callback. When the C code calls through the function pointer, it calls the wrapper function which then calls the nested function with the correct static link. There is a significant amount of public Ada code that depends on this mechanism. (GtkAda relies heavily on it.)
However, if the access value points to a wrapper, instead of the actual function, then The_Access.all'Address won't return what you think it should. When the code executes The_Access.all'Address, if The_Access is a single word with an address in it, that's all the attribute can return--the address in the pointer.
More: I don't know whether the original code is part of a larger example or just a test to see what the compiler does. But comparing 'Address values to see if a subprogram-access parameter refers to a specific subprogram strikes me a poor design, and comparing 'Access is no better. I would avoid doing that even in C. There's likely to be a more object-oriented solution to the problem (note that you can use tagged types to cause indirect subprogram calls to take place, because tagged type operations are dispatching). E.g.
type Boolean_Function_Object is abstract tagged null record;
function Apply (Obj : Boolean_Function_Object; N : Integer) return boolean;
function Is_Constant_False (Obj : Boolean_Function_Object) return boolean;
type No_Function is new Boolean_Function_Object with null record;
overriding
function Apply (Obj : No_Function; N : Integer) return boolean is (False);
overriding
function Is_Constant_False (Obj : No_Function) return boolean is (True);
procedure Taking (Func : Boolean_Function_Object) is
begin
if not Func.Is_Constant_False then
raise Program_Error;
end if;
end Taking;
Might not be the best design in all cases, but something like this should be considered if there seems to be a need to check a subprogram address to a particular subprogram. For one thing, this is more flexible; a programmer can define another derived type where Apply always return False but does something else, such as writing the argument to a log file.
So when playing with access types on an Ada compiler which turns out to be Ada 2005, I try the following classic example:
type Node is record
next: access Node;
end record;
function reverselist(input: access Node) return access Node is
result: access Node := null;
this: access Node := input;
next: access Node := null;
begin
while this /= null loop
next := this.next;
this.next := result; -- [*]
result := this;
this := next;
end loop;
return result; -- [*]
end;
The two starred lines produce compilation errors because Ada 2005's analysis thinks I might be leaking a local pointer. (I know that Ada 2012 has better analysis and will accept this. However, I don't have an Ada 2012 compiler.)
Okay, so this can be easily solved by using a named pool access instead of the anonymous access Node; by using a pool access I tell the compiler that the pointers can't be referring to stack objects. That works fine.
However, then I tried using a named general access:
type Node;
type List is access Node;
type Node is record
next: List;
end record;
function reverselist(input: List) return access Node is
result: List := null;
this: List := input;
next: List := null;
begin
while this /= null loop
next := this.next;
this.next := result;
result := this;
this := next;
end loop;
return result;
end;
General access types can point at stack objects as well as heap objects; so why doesn't the compiler reject the second example for the same reasons that it rejected the first?
(I was also slightly surprised that anonymous access integer variables seem to end up with general access semantics. Why don't I have to use access all integer for anonymous general accesses?)
Although in general a general access type can point at non-heap objects (both global and stack), there are rules that would prevent a List from pointing to the stack. In this case, since List is not declared inside any subprogram, it cannot be made to point to a stack variable:
function reverselist(input: List) return access Node is
result: List := null;
this: List := input;
next: List := null;
Dummy : aliased Node;
begin
result := Dummy'Access; -- a compile-time error would occur at this point
while this /= null loop
next := this.next;
this.next := result;
result := this;
this := next;
end loop;
return result;
end;
Since the rules "ensure" that a List can never point to a stack variable, there's no need for the compiler to reject any of the other statements. (I put "ensure" in quotes because you could use 'Unchecked_Access to get around them, as well as Unchecked_Conversion or a number of other ways to get around the type system.)
If an access type is declared inside a subprogram, it can point to stack variables inside that subprogram. This is because no objects of that access type can be declared outside the subprogram and therefore it's not possible (barring unchecked tricks) for any object of this type to live after the subprogram is completed. It can also point to globals, or to heap objects. But it can't point to stack variables in a nested subprogram.
procedure Proc is
type Node is ...
type Acc is access all Node;
N1 : aliased Node;
procedure Nested_Proc is
N2 : aliased Node;
X : Acc;
begin
X := N1'Access; -- legal
X := N2'Access; -- illegal. N2 is too deep for this access type.
end;
So it's at the point where 'Access is used that the compiler makes sure that dangling references to no-longer-existing variables can't be created.
All this is governed by the accessibility rules, which are clearly spelled out in RM 3.10.2. (I'm kidding. 3.10.2 is very difficult to understand and tends to produce migraines and borderline insanity in those who try to read it.)
Edit: To follow up on your comment: Basically, I don't think the compiler is doing any sort of "robust analysis". Most of the rules are actually simpler than I made it sound. In Ada 2005, most access types, including most anonymous ones, have a "level" that depend on where the type is declared. If an access object's type is level L, it can't take an access value whose level is "deeper" (more nested) than L. Each anonymous access declares a new type, whose level usually depends on where it's declared. In your example that uses anonymous access types, the type of the next record field is library level since it's outside any procedure; the type of the result is deeper than that since it's inside a procedure. this.next := result is illegal because result, being deeper, could point to a stack variable, and this.next has a shallower level and thus this isn't allowed. For the named access type case, this.next := result is legal because result is just as shallow as the next field, and result wouldn't be allowed to point to a stack variable in the first place. In Ada 2012, I think it's different because the anonymous access objects have to keep track at runtime of the level of the thing they're point to. So this.next := result is legal, but (I think) will raise an exception at runtime if result points to a stack variable. In Ada 2012, these access objects will need some extra data to allow them to do this check; in Ada 2005, they could all be just simple pointers. (I could be wrong about some of the Ada 2012 changes.) But hopefully that isn't too complicated. The complications in 3.10.2 have to do with anonymous access parameters, anonymous access discriminants, and some other special cases that your example doesn't have anything to do with.
One solution is to restructure the code a bit; using an extended-return might do it for you:
type Node is record
next: access Node;
end record;
function reverse_list(input: access Node) return access Node is
this: access Node := input;
next: access Node := null;
begin
Return result: access Node := null do
while this /= null loop
next := this.next;
this.next := result;
result := this;
this := next;
end loop;
end return;
end reverse_list;
While accessibility-checks can get frustrating, I have an overall good opinion of them: we do not want dangling pointers.