[Spark2014-discuss] SPARK 2014 strings. Basic I/O

Yannick Moy moy at adacore.com
Wed Jul 2 21:57:59 CEST 2014

Hi David,

> 1. What is the preferred way (i.e. most easily provable) to define such array of strings in SPARK 2014 where strings can be a different size (but statically known at compile time)?

First, you need your type of strings to be "definite" so that you can make it the element of an array. A "definite" type is one for which the compiler knows the size, which is essential for array elements. So it cannot be "String" which is indefinite, but only:
1) String(1..256)
2) Bounded_String (after you instantiate the corresponding generic package)
3) Unbounded_String

Option (3) is not really feasible in SPARK, because the standard Unbounded_String is defined as a controlled type:

   type Unbounded_String is new AF.Controlled with record
      Reference : String_Access := Null_String'Access;
      Last      : Natural       := 0;
   end record;

Controlled types are not in SPARK, even if private (which is the case of Unbounded_String), as they involve additional operations to be inserted by the compiler (when creating/copying/removing the variable), and this would have to be taken into account in the formal verification tool as well. So it will probably remain out of SPARK for some time.

Option (1) is quite feasible, except you have to pad yourself strings with whitespace characters. But this was for example the way that strings were manipulated in the Tokeneer code (originally in SPARK 2005, see http://www.adacore.com/sparkpro/tokeneer/)

Option (2) is probably the most appropriate. Bounded_String is a discriminant record, with a maximal size given by the value of the discriminant:

    type Bounded_String is new Superbounded.Super_String (Max_Length);

    type Super_String (Max_Length : Positive) is record
      Current_Length : Natural := 0;
      Data           : String (1 .. Max_Length);

You can use the standard version of bounded strings, or create your own. If you use the standard version, beware that the complete generic unit Ada.Strings.Bounded is not completely in SPARK, so you cannot instantiate it in code that is marked SPARK_Mode=>On, otherwise you get errors such as

strarr.ads:8:04: instantiation error at a-strbou.ads:232
strarr.ads:8:04: "Character_Mapping_Function" is not allowed in SPARK
strarr.ads:8:04: violation of aspect SPARK_Mode at line 4

on parameters of type access to subprogram (pointer to subprogram). Instead, you should instantiate the package Generic_Bounded_Length defined inside Ada.Strings.Bounded in a separate unit not marked SPARK_Mode=>On (so it defaults to SPARK_Mode=>Auto, which means that you can use entities from it whose declaration is compatible with SPARK). I have attached an example of such a use.

Note that you'll get warnings on this code because it is then calling standard library subprograms without Global contract, for which the tool does not generate a Global contract (which it does on your code), so it warns you about it:

strarr.adb:10:10: warning: no Global contract available for "Put_Line"
strarr.adb:10:10: warning: assuming "Put_Line" has no effect on global items

You can either ignore these warnings, use --warnings=off to silence them (you might miss useful ones) or (better) define a wrapper package for these subprograms with a spec in SPARK, and a body marked SPARK_Mode=>Off.

> 2. In the same way, what are recommended input/output procedures to use in a SPARK 2014 program?

You can use the standard Ada.Text_IO unit, or a SPARK-compatible custom wrapper, for example the SPARK.Text_IO units that were created by Trevor Jennings from Altran, and that you can find in your SPARK distribution under share/examples/spark/spark_io.

> 3. What is the recommended type to use to define string variables in a SPARK 2014 program? "String(1..255)"?

All the following should be equivalent:

   X : String := "hello";

   X : String(1 .. 5) := "hello";

   subtype Small is Integer range 1 .. 5;
   X : String(Small) := "hello";

   subtype Small is Integer range 1 .. 5;
   subtype Small_String is String (Small);
   X : Small_String := "hello";

So it's up to you!
Yannick Moy, Senior Software Engineer, AdaCore

-------------- next part --------------
A non-text attachment was scrubbed...
Name: strbnd.ads
Type: application/octet-stream
Size: 104 bytes
Desc: not available
URL: <http://lists.forge.open-do.org/pipermail/spark2014-discuss/attachments/20140702/217ced7e/attachment-0003.obj>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: strarr.ads
Type: application/octet-stream
Size: 275 bytes
Desc: not available
URL: <http://lists.forge.open-do.org/pipermail/spark2014-discuss/attachments/20140702/217ced7e/attachment-0004.obj>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: strarr.adb
Type: application/octet-stream
Size: 245 bytes
Desc: not available
URL: <http://lists.forge.open-do.org/pipermail/spark2014-discuss/attachments/20140702/217ced7e/attachment-0005.obj>
-------------- next part --------------

More information about the Spark2014-discuss mailing list