How can I define a subtype
of String
that allows only hex characters to be used? Here is my attempt, but I fail at the subtype definition:
subtype Hex_Character is Character
with Static_Predicate => Hex_Character in
'A' .. 'F' | 'a' .. 'f' | '0' .. '9';
subtype Hex_String is String ...;
You could add a dynamic predicate and leverage the dynamic semantics of the membership test. From RM 4.5.2 (29/4):
An individual membership test yields the result True if:
- [...]
- The membership_choice is a subtype_mark, the tested type is scalar, the value of the tested_simple_expression belongs to the range of the named subtype, and the value satisfies the predicates of the named subtype.
For example:
main.adb
procedure Main with SPARK_Mode is
subtype Hex_Character is Character
with Static_Predicate => Hex_Character in
'A' .. 'F' | 'a' .. 'f' | '0' .. '9';
subtype Hex_String is String
with Dynamic_Predicate =>
(for all Char of Hex_String => Char in Hex_Character);
S1 : Hex_String := "ABCDEF1234567890"; -- Line 11
S2 : Hex_String := "Foo"; -- Line 12
begin
null;
end Main;
output (GNATprove)
$ gnatprove -Pdefault.gpr -u main.adb --level=1 --report=all
Phase 1 of 3: generation of data representation information ...
Phase 2 of 3: generation of Global contracts ...
Phase 3 of 3: flow analysis and proof ...
main.adb:11:23: info: predicate check proved
main.adb:12:23: medium: predicate check might fail, cannot prove Char in Hex_Character
12 | S2 : Hex_String := "Foo";
| ^~~~~
in inlined predicate at main.adb:9
Summary logged in ./obj/gnatprove/gnatprove.out