Commit d67b72bf authored by CHAMONT David's avatar CHAMONT David
Browse files

Reorganisation des tutos

parent fb7e5e82
DIRS=clauses-de-representation serveur-web-avec-aws tableaux entiers-et-sous-types hello_world generic
all clean distclean:
set -e && \
for i in $(DIRS);do make -C $$i $@;done
ada-graph.png:ada-graph.dot
cat $^ | dot -T png -o $@
Un petit commentaire de l'administrateur du dépôt.
Bienvenue à la piscine. Le bonnet est optionnel. La porte est ouverte. La parole est libre.
digraph G
{
hello_world [shape=box;label="Hello World"];
entiers_sous_types [shape=box;label="Entiers et Sous Types"];
serveur_web [shape=box;label="Serveur Web avec AWS"];
enumeratifs [shape=box;label="Types Enumeratifs"];
generics [shape=box;label="Generics"];
tableaux [shape=box;label="Tableaux"];
clauses_representations [shape=box;label="Clauses de représentations"];
hello_world -> entiers_sous_types;
hello_world -> serveur_web;
entiers_sous_types -> enumeratifs;
entiers_sous_types -> tableaux;
entiers_sous_types -> clauses_representations;
tableaux -> generics;
}
\ No newline at end of file
all:
gprbuild -s example_representations_clauses_1.adb -cargs -gnatwae -gnaty -gnatyM122
gprbuild -s example_representations_clauses_2.adb -cargs -gnatwae -gnaty -gnatyM122
clean:
gnatclean -c example_representations_clauses_1.adb
gnatclean -c example_representations_clauses_2.adb
find . -name "*~" -delete
rm -f b__*.ad[sb] b__*.o b__*.ali *.bexch *.cswi auto.cgpr
distclean:clean
gnatclean example_representations_clauses_1
gnatclean example_representations_clauses_2
# Les clauses de représentation
Yann Aubert, Jean-Louis Coacolo, Nicolas Dosme, Hadrien Grasland, **Xavier Grave <xavier.grave@csnsm.in2p3.fr>**, Patrick Le Jeannic, Eric Legay
*Ce plongeon fait partie d'une série sur le langage Ada. Nous y supposons que vous avez préalablement effectué le plongeon d'introduction, qui pose les bases de ce langage.*
## Explorer le code bas niveau d'un flottant 64 bits
On peut déclarer des types au plus près de la définition du standard (ici un réel 64 bits) :
* un type exposant sur 11 bits
* un type mantisse sur 52 bits
```
type Exponent_Type is mod 2 ** 11;
type Mantissa_Type is mod 2 ** 52;
```
Ensuite on utilise un type "record" (équivalent de struct en C) :
```
type Representation_Type is record
Mantissa : Mantissa_Type;
Exponent : Exponent_Type;
Is_Negative : Boolean;
end record;
```
Il est intéressant de noter que le bit de signe est un booléen. On fixe ensuite la taille en bits de notre record.
```
for Representation_Type'Size use 64;
```
Pour finir par la représentation bas niveau :
```
for Representation_Type use record
Mantissa at 0 range 0 .. 51;
Exponent at 0 range 52 .. 62;
Is_Negative at 0 range 63 .. 63;
end record;
```
Chaque élément du record est placé au bit près dans la structure de 64 bits.
La représentation alternative du réel 64 bits est présente dans [long_float_representation.ads](ada-clauses-de-representation/long_float_representation.ads) et son utilisation dans [example_representations_clauses_1.adb](ada-clauses-de-representation/example_representations_clauses_1.adb).
## Exploiter le résultat de la commande assembleur "cpuid" sans masques et décalages de bits
La commande assembleur cpuid permet de collecter beaucoup d'information sur un processeur de la famille x86. Mais l'information est placée "en vrac" dans des registres 32 bits. On se propose ici grâce au clauses de représentation de ne pas utiliser
de masques de bits pour y accéder.
Le code de [cpu_id.ads](ada-clauses-de-representation/cpu_id.ads) est une spécification qui permet d'utiliser les abstractions de l'appel à cpuid pour les niveaux 0 et 1.
```
subtype Vendor_ID_String_Type is String (1 .. 12);
procedure Assembly_Call (Eax : in out Interfaces.Unsigned_32;
Ebx : out Interfaces.Unsigned_32;
Ecx : in out Interfaces.Unsigned_32;
Edx : out Interfaces.Unsigned_32) is
begin
System.Machine_Code.Asm (Template => "cpuid",
Inputs => (Interfaces.Unsigned_32'Asm_Input ("0", Eax),
Interfaces.Unsigned_32'Asm_Input ("2", Ecx)),
Outputs => (Interfaces.Unsigned_32'Asm_Output ("=a", Eax),
Interfaces.Unsigned_32'Asm_Output ("=b", Ebx),
Interfaces.Unsigned_32'Asm_Output ("=c", Ecx),
Interfaces.Unsigned_32'Asm_Output ("=d", Edx)));
end Assembly_Call;
```
Le niveau 0 renvoie une chaîne de 12 caractères :
```
function Vendor_ID return Vendor_ID_String_Type is
Eax, Ebx, Ecx, Edx : Interfaces.Unsigned_32 := 0;
begin
Assembly_Call (Eax, Ebx, Ecx, Edx);
declare
Ebx_Image : String (1 .. 4);
for Ebx_Image'Address use Ebx'Address;
Ecx_Image : String (1 .. 4);
for Ecx_Image'Address use Ecx'Address;
Edx_Image : String (1 .. 4);
for Edx_Image'Address use Edx'Address;
begin
return Ebx_Image & Edx_Image & Ecx_Image;
end;
end Vendor_ID;
```
Le niveau 1 renvoie une structure de 128 bits qui est détaillée dans [cpu_id.ads](ada-clauses-de-representation/cpu_id.ads).
## Pour compiler :
> make
## Pour "nettoyer" le répertoire :
> make clean ou make distclean
\ No newline at end of file
with System.Machine_Code;
package body CPU_ID is
procedure Assembly_Call (Eax : in out Interfaces.Unsigned_32;
Ebx : out Interfaces.Unsigned_32;
Ecx : in out Interfaces.Unsigned_32;
Edx : out Interfaces.Unsigned_32) is
begin
System.Machine_Code.Asm (Template => "cpuid",
Inputs => (Interfaces.Unsigned_32'Asm_Input ("0", Eax),
Interfaces.Unsigned_32'Asm_Input ("2", Ecx)),
Outputs => (Interfaces.Unsigned_32'Asm_Output ("=a", Eax),
Interfaces.Unsigned_32'Asm_Output ("=b", Ebx),
Interfaces.Unsigned_32'Asm_Output ("=c", Ecx),
Interfaces.Unsigned_32'Asm_Output ("=d", Edx)));
end Assembly_Call;
function Vendor_ID return Vendor_ID_String_Type is
Eax, Ebx, Ecx, Edx : Interfaces.Unsigned_32 := 0;
begin
Assembly_Call (Eax, Ebx, Ecx, Edx);
declare
Ebx_Image : String (1 .. 4);
for Ebx_Image'Address use Ebx'Address;
Ecx_Image : String (1 .. 4);
for Ecx_Image'Address use Ecx'Address;
Edx_Image : String (1 .. 4);
for Edx_Image'Address use Edx'Address;
begin
return Ebx_Image & Edx_Image & Ecx_Image;
end;
end Vendor_ID;
function Maximum_Input_Value return Interfaces.Unsigned_32 is
Eax, Ebx, Ecx, Edx : Interfaces.Unsigned_32 := 0;
begin
Assembly_Call (Eax, Ebx, Ecx, Edx);
return Eax;
end Maximum_Input_Value;
function Get_Level_1_Information return Level_1_Information_Type is
Registers : array (1 .. 4) of Interfaces.Unsigned_32 := (1 => 1, others => 0);
begin
Assembly_Call (Registers (1), Registers (2), Registers (3), Registers (4));
declare
Information : Level_1_Information_Type;
for Information'Address use Registers (Registers'First)'Address;
begin
return Information;
end;
end Get_Level_1_Information;
end CPU_ID;
with Interfaces;
package CPU_ID is
type Unsigned_4 is mod 2 ** 4;
type Unsigned_2 is mod 2 ** 2;
subtype Vendor_ID_String_Type is String (1 .. 12);
function Vendor_ID return Vendor_ID_String_Type;
procedure Assembly_Call (Eax : in out Interfaces.Unsigned_32;
Ebx : out Interfaces.Unsigned_32;
Ecx : in out Interfaces.Unsigned_32;
Edx : out Interfaces.Unsigned_32);
function Maximum_Input_Value return Interfaces.Unsigned_32;
type Level_1_Information_Type is record
Stepping_ID : Unsigned_4; -- in Eax
Model : Unsigned_4;
Family_ID : Unsigned_4;
Processor_Type : Unsigned_2;
Extended_Model_ID : Unsigned_4;
Extended_Family_ID : Interfaces.Unsigned_8;
Brand_Index : Interfaces.Unsigned_8; -- in Ebx
CLFLUSH : Interfaces.Unsigned_8;
Max_Addr_ID : Interfaces.Unsigned_8;
Initial_APIC_ID : Interfaces.Unsigned_8;
Sse3 : Boolean; -- in Ecx
Pclmulqdq : Boolean;
Dtes64 : Boolean;
Monitor : Boolean;
Ds_Cpl : Boolean;
Vmx : Boolean;
Smx : Boolean;
Est : Boolean;
Tm2 : Boolean;
Ssse3 : Boolean;
Cnxt_Id : Boolean;
Sdbg : Boolean;
Fma : Boolean;
Cx16 : Boolean;
Xtpr : Boolean;
Pdcm : Boolean;
Pcid : Boolean;
Dca : Boolean;
Sse4_1 : Boolean;
Sse4_2 : Boolean;
X2apic : Boolean;
Movbe : Boolean;
Popcnt : Boolean;
Tsc_Deadline : Boolean;
Aes : Boolean;
Xsave : Boolean;
Osxsave : Boolean;
Avx : Boolean;
F16c : Boolean;
Rdrnd : Boolean;
Hypervisor : Boolean;
Fpu : Boolean; -- in Edx
Vme : Boolean;
De : Boolean;
Pse : Boolean;
Tsc : Boolean;
Msr : Boolean;
Pae : Boolean;
Mce : Boolean;
Cx8 : Boolean;
Apic : Boolean;
Sep : Boolean;
Mtrr : Boolean;
Pge : Boolean;
Mca : Boolean;
Cmov : Boolean;
Pat : Boolean;
Pse_36 : Boolean;
Psn : Boolean;
Clfsh : Boolean;
Ds : Boolean;
Acpi : Boolean;
Mmx : Boolean;
Fxsr : Boolean;
Sse : Boolean;
Sse2 : Boolean;
Ss : Boolean;
Htt : Boolean;
Tm : Boolean;
Ia64 : Boolean;
Pbe : Boolean;
end record;
for Level_1_Information_Type'Size use 128;
for Level_1_Information_Type use record
Stepping_ID at 0 range 0 .. 3;
Model at 0 range 4 .. 7;
Family_Id at 1 range 0 .. 3;
Processor_Type at 1 range 4 .. 5;
Extended_Model_ID at 2 range 0 .. 3;
Extended_Family_ID at 2 range 4 .. 11;
Brand_Index at 4 range 0 .. 7;
CLFLUSH at 5 range 0 .. 7;
Max_Addr_ID at 6 range 0 .. 7;
Initial_APIC_ID at 7 range 0 .. 7;
Sse3 at 8 range 0 .. 0;
Pclmulqdq at 8 range 1 .. 1;
Dtes64 at 8 range 2 .. 2;
Monitor at 8 range 3 .. 3;
Ds_Cpl at 8 range 4 .. 4;
Vmx at 8 range 5 .. 5;
Smx at 8 range 6 .. 6;
Est at 8 range 7 .. 7;
Tm2 at 9 range 0 .. 0;
Ssse3 at 9 range 1 .. 1;
Cnxt_Id at 9 range 2 .. 2;
Sdbg at 9 range 3 .. 3;
Fma at 9 range 4 .. 4;
Cx16 at 9 range 5 .. 5;
Xtpr at 9 range 6 .. 6;
Pdcm at 9 range 7 .. 7;
Pcid at 10 range 1 .. 1;
Dca at 10 range 2 .. 2;
Sse4_1 at 10 range 3 .. 3;
Sse4_2 at 10 range 4 .. 4;
X2apic at 10 range 5 .. 5;
Movbe at 10 range 6 .. 6;
Popcnt at 10 range 7 .. 7;
Tsc_Deadline at 11 range 0 .. 0;
Aes at 11 range 1 .. 1;
Xsave at 11 range 2 .. 2;
Osxsave at 11 range 3 .. 3;
Avx at 11 range 4 .. 4;
F16c at 11 range 5 .. 5;
Rdrnd at 11 range 6 .. 6;
Hypervisor at 11 range 7 .. 7;
Fpu at 12 range 0 .. 0;
Vme at 12 range 1 .. 1;
De at 12 range 2 .. 2;
Pse at 12 range 3 .. 3;
Tsc at 12 range 4 .. 4;
Msr at 12 range 5 .. 5;
Pae at 12 range 6 .. 6;
Mce at 12 range 7 .. 7;
Cx8 at 13 range 0 .. 0;
Apic at 13 range 1 .. 1;
Sep at 13 range 3 .. 3;
Mtrr at 13 range 4 .. 4;
Pge at 13 range 5 .. 5;
Mca at 13 range 6 .. 6;
Cmov at 13 range 7 .. 7;
Pat at 14 range 0 .. 0;
Pse_36 at 14 range 1 .. 2;
Psn at 14 range 3 .. 3;
Clfsh at 14 range 4 .. 4;
Ds at 14 range 5 .. 5;
Acpi at 14 range 6 .. 6;
Mmx at 14 range 7 .. 7;
Fxsr at 15 range 0 .. 0;
Sse at 15 range 1 .. 1;
Sse2 at 15 range 2 .. 2;
Ss at 15 range 3 .. 3;
Htt at 15 range 4 .. 4;
Tm at 15 range 5 .. 5;
Ia64 at 15 range 6 .. 6;
Pbe at 15 range 7 .. 7;
end record;
function Get_Level_1_Information return Level_1_Information_Type;
end CPU_ID;
with Ada.Text_IO;
with Long_Float_Representation;
procedure Example_Representations_Clauses_1 is
A_Real : constant Long_Float := Long_Float_Representation.Enter_Real;
A_Real_Alernative_Representation : constant Long_Float_Representation.Representation_Type :=
Long_Float_Representation.To_Representation (A_Real);
A_Real_Alernative_Representation_Bis : Long_Float_Representation.Representation_Type;
for A_Real_Alernative_Representation_Bis'Address use A_Real'Address;
begin
if A_Real_Alernative_Representation.Is_Negative then
Ada.Text_IO.Put_Line (A_Real'Img & " is negative");
else
Ada.Text_IO.Put_Line (A_Real'Img & " is positive");
end if;
if A_Real_Alernative_Representation_Bis.Is_Negative then
Ada.Text_IO.Put_Line (A_Real'Img & " is negative / second check");
else
Ada.Text_IO.Put_Line (A_Real'Img & " is positive / second check");
end if;
Ada.Text_IO.Put_Line ("exponent value :" & A_Real_Alernative_Representation.Exponent'Img);
Ada.Text_IO.Put_Line ("mantissa value :" & A_Real_Alernative_Representation.Mantissa'Img);
end Example_Representations_Clauses_1;
with Ada.Text_IO;
with Interfaces;
with CPU_ID;
procedure Example_Representations_Clauses_2 is
Vendor_ID : constant String := CPU_ID.Vendor_ID;
Maximum_Input_Value : constant Interfaces.Unsigned_32 := CPU_ID.Maximum_Input_Value;
Informations : constant CPU_ID.Level_1_Information_Type := CPU_ID.Get_Level_1_Information;
begin
Ada.Text_IO.Put_Line ("vendor ID : " & Vendor_ID & " - maximum value" & Maximum_Input_Value'Img);
Ada.Text_IO.Put_Line ("stepping ID :" & Informations.Stepping_ID'Img);
Ada.Text_IO.Put_Line ("Model :" & Informations.Model'Img);
Ada.Text_IO.Put_Line ("Family ID :" & Informations.Family_ID'Img);
Ada.Text_IO.Put_Line ("Processor type :" & Informations.Processor_Type'Img);
Ada.Text_IO.Put_Line ("Extended Model :" & Informations.Extended_Model_ID'Img);
Ada.Text_IO.Put_Line ("Extended Family ID :" & Informations.Extended_Family_ID'Img);
Ada.Text_IO.Put_Line ("Brand_Index :" & Informations.Brand_Index'Img);
Ada.Text_IO.Put_Line ("CLFLUSH :" & Informations.CLFLUSH'Img);
Ada.Text_IO.Put_Line ("Max_Addr_ID :" & Informations.Max_Addr_ID'Img);
Ada.Text_IO.Put_Line ("Initial_APIC_ID :" & Informations.Initial_APIC_ID'Img);
Ada.Text_IO.Put_Line ("Sse3 : " & Informations.Sse3'Img);
Ada.Text_IO.Put_Line ("Pclmulqdq : " & Informations.Pclmulqdq'Img);
Ada.Text_IO.Put_Line ("Dtes64 : " & Informations.Dtes64'Img);
Ada.Text_IO.Put_Line ("Monitor : " & Informations.Monitor'Img);
Ada.Text_IO.Put_Line ("Ds-Cpl : " & Informations.Ds_Cpl'Img);
Ada.Text_IO.Put_Line ("Vmx : " & Informations.Vmx'Img);
Ada.Text_IO.Put_Line ("Smx : " & Informations.Smx'Img);
Ada.Text_IO.Put_Line ("Est : " & Informations.Est'Img);
Ada.Text_IO.Put_Line ("Tm2 : " & Informations.Tm2'Img);
Ada.Text_IO.Put_Line ("Ssse3 : " & Informations.Ssse3'Img);
Ada.Text_IO.Put_Line ("Cnxt-Id : " & Informations.Cnxt_Id'Img);
Ada.Text_IO.Put_Line ("Sdbg : " & Informations.Sdbg'Img);
Ada.Text_IO.Put_Line ("Fma : " & Informations.Fma'Img);
Ada.Text_IO.Put_Line ("Cx16 : " & Informations.Cx16'Img);
Ada.Text_IO.Put_Line ("Xtpr : " & Informations.Xtpr'Img);
Ada.Text_IO.Put_Line ("Pdcm : " & Informations.Pdcm'Img);
Ada.Text_IO.Put_Line ("Pcid : " & Informations.Pcid'Img);
Ada.Text_IO.Put_Line ("Dca : " & Informations.Dca'Img);
Ada.Text_IO.Put_Line ("Sse4.1 : " & Informations.Sse4_1'Img);
Ada.Text_IO.Put_Line ("Sse4.2 : " & Informations.Sse4_2'Img);
Ada.Text_IO.Put_Line ("X2apic : " & Informations.X2apic'Img);
Ada.Text_IO.Put_Line ("Movbe : " & Informations.Movbe'Img);
Ada.Text_IO.Put_Line ("Popcnt : " & Informations.Popcnt'Img);
Ada.Text_IO.Put_Line ("Tsc-Deadline : " & Informations.Tsc_Deadline'Img);
Ada.Text_IO.Put_Line ("Aes : " & Informations.Aes'Img);
Ada.Text_IO.Put_Line ("Xsave : " & Informations.Xsave'Img);
Ada.Text_IO.Put_Line ("Osxsave : " & Informations.Osxsave'Img);
Ada.Text_IO.Put_Line ("Avx : " & Informations.Avx'Img);
Ada.Text_IO.Put_Line ("F16c : " & Informations.F16c'Img);
Ada.Text_IO.Put_Line ("Rdrnd : " & Informations.Rdrnd'Img);
Ada.Text_IO.Put_Line ("Hypervisor : " & Informations.Hypervisor'Img);
Ada.Text_IO.Put_Line ("sep : " & Informations.Sep'Img);
Ada.Text_IO.Put_Line ("mtrr : " & Informations.Mtrr'Img);
Ada.Text_IO.Put_Line ("pge : " & Informations.Pge'Img);
Ada.Text_IO.Put_Line ("mca : " & Informations.Mca'Img);
Ada.Text_IO.Put_Line ("cmov : " & Informations.Cmov'Img);
Ada.Text_IO.Put_Line ("pat : " & Informations.Pat'Img);
Ada.Text_IO.Put_Line ("pse-36 : " & Informations.Pse_36'Img);
Ada.Text_IO.Put_Line ("psn : " & Informations.Psn'Img);
Ada.Text_IO.Put_Line ("clfsh : " & Informations.Clfsh'Img);
Ada.Text_IO.Put_Line ("ds : " & Informations.Ds'Img);
Ada.Text_IO.Put_Line ("acpi : " & Informations.Acpi'Img);
Ada.Text_IO.Put_Line ("mmx : " & Informations.Mmx'Img);
Ada.Text_IO.Put_Line ("fxsr : " & Informations.Fxsr'Img);
Ada.Text_IO.Put_Line ("sse : " & Informations.Sse'Img);
Ada.Text_IO.Put_Line ("sse2 : " & Informations.Sse2'Img);
Ada.Text_IO.Put_Line ("ss : " & Informations.Ss'Img);
Ada.Text_IO.Put_Line ("htt : " & Informations.Htt'Img);
Ada.Text_IO.Put_Line ("tm : " & Informations.Tm'Img);
Ada.Text_IO.Put_Line ("ia64 : " & Informations.Ia64'Img);
Ada.Text_IO.Put_Line ("pbe : " & Informations.Pbe'Img);
end Example_Representations_Clauses_2;
with Ada.IO_Exceptions;
with Ada.Text_IO;
package body Long_Float_Representation is
package Long_Float_IO is new Ada.Text_IO.Float_IO (Long_Float);
function Enter_Real return Long_Float is
begin
loop
declare
Value : Long_Float;
begin
Ada.Text_IO.Put_Line ("enter a value ");
Long_Float_IO.Get (Value);
return Value;
exception
when Ada.IO_Exceptions.Data_Error =>
Ada.Text_IO.Put_Line ("you should enter a real");
Ada.Text_IO.Skip_Line;
end;
end loop;
end Enter_Real;
end Long_Float_Representation;
with Ada.Unchecked_Conversion;
package Long_Float_Representation is
type Exponent_Type is mod 2 ** 11;
type Mantissa_Type is mod 2 ** 52;
type Representation_Type is record
Mantissa : Mantissa_Type;
Exponent : Exponent_Type;
Is_Negative : Boolean;
end record;
for Representation_Type'Size use 64;
for Representation_Type use record
Mantissa at 0 range 0 .. 51;
Exponent at 0 range 52 .. 62;
Is_Negative at 0 range 63 .. 63;
end record;
function Enter_Real return Long_Float;
function To_Representation is new Ada.Unchecked_Conversion (Long_Float, Representation_Type);
end Long_Float_Representation;
.PHONY:all
all:
-gprbuild -p -P entiers_et_sous_types.gpr
clean:
find . -name "*~" -delete
gnatclean -c -P entiers_et_sous_types.gpr
distclean:clean
-gnatclean -P entiers_et_sous_types.gpr
-rmdir bin obj
# Types entiers, sous-types et prédicats
**Hadrien Grasland (grasland@lal.in2p3.fr)**, Xavier Grave, Eric Legay, Jean-Louis Coacolo, Nicolas Dosme, Patrick Le Jeannic, Yann Aubert
*Ce plongeon fait partie d'une série sur le langage Ada. Nous y supposons que vous avez préalablement effectué le plongeon d'introduction, qui pose les bases de ce langage.*
## Déclaration d'un type entier
En Ada, il est possible de déclarer un type entier en utilisant la syntaxe
type <nom> is range <min> .. <max>;
`<nom>` est le nom du type `<min>` est le plus petit entier représentable par le type, et `<max>` est le plus grand. Par exemple, pour définir un type entier "Mon_Entier" pouvant contenir des entiers entre -3 et 42, on écrirait :
type Mon_Entier is range -3 .. 42;
Pouvoir créer ainsi un type entier offre un certain nombre d'avantages par rapport aux langages de programmation où l'on ne peut utiliser que des types entiers prédéfinis :
- La portabilité du programme entre machines est garantie par le compilateur Ada. Si ce dernier est capable de produire un programme pour la machine cible, alors on peut être sûr que ses types entiers sont bien capables de stocker les valeurs attendues. Ce n'est pas le cas dans les langages où la plage de valeur des types entiers prédéfinis est laissée au choix de l'implémentation (C, C++...).
- La performance est optimale quelle que soit la machine cible. Le type Mon_Entier ci-dessus sera implémenté comme un entier 16 bit sur une machine 16 bit, un entier 32 bit sur une machine 32-bit, et ainsi de suite. Ce n'est pas le cas dans les langages où la taille des types prédéfinis est fixée par le standard (Java, Rust...).
- On peut définir la plage de valeurs autorisées comme on le souhaite, et non en fonction de bornes arbitraires imposées par le langage. Cela permet d'adapter ces dernières au problème que l'on cherche à résoudre. Par exemple, un type destiné à contenir des mesures physiques peut exclure des valeurs aberrantes de ces dernières, et l'implémentation Ada se chargera alors de vérifier que les données saisies sont cohérentes.
On voit donc que les types entiers d'Ada permettent d'écrire des programmes dont les capacités sont définies par des spécifications, et non par les caractéristiques des machines utilisées lors de leur développement. Ce mode de fonctionnement aide les développeurs à se concentrer sur la conception de leurs programmes plutôt que sur leur implémentation.
Le programme [`declaration_entier.adb`](src/declaration_entier.adb) fournit un exemple de déclaration d'un type entier représentant des températures, et de quelques variables entières dont une contient une faute de frappe. Notez que grâce à un type entier bien spécifié, le compilateur Ada est capable de détecter cette erreur à la compilation.
Il n'est cependant pas toujours possible de détecter ce genre d'erreur à la compilation, notamment quand on traite des valeurs saisies par l'utilisateur. Dans ce cas, le compilateur insère, par défaut, des tests à l'éxécution qui permettent de s'assurer que les entiers saisis respectent leur type, sous peine de lever une exception telle que `Constraint_Error`. Ces tests peuvent cependant être désactivés au cas par cas, une fois le bon fonctionnement du programme validé, si ils entraînent des problèmes de performance.
## Littérales entières
Ada offre une certaine flexibilité dans l'écriture de nombres entiers. Par exemple, il est possible de séparer les chiffres d'un grand nombre avec des underscores afin d'améliorer sa lisibilité :
type Dollars is range 0 .. 1_000_000_000_000_000;
One_Million_Dollars : constant Dollars := 1_000_000;
One_Hundred_Billion_Dollars : constant Dollars := 100_000_000_000;
Ceci dit, malgré cette astuce, j'en vois encore dans le fond de la salle dont les yeux commencent à saigner alors qu'ils essaient de compter les zéros. Qu'ils soient rassurés : on peut aussi utiliser des puissances.
type Meters is range 0 .. 10**9;