# Ada Programming/Type System – Wikibooks, open books for an open world

Ada’s kind system permits the programmer to assemble highly effective abstractions that symbolize the actual world, and to offer worthwhile data to the compiler, in order that the compiler can discover many logic or design errors earlier than they turn into bugs. It’s on the coronary heart of the language, and good Ada programmers be taught to make use of it to nice benefit. 4 ideas govern the sort system:

• Robust typing: sorts are incompatible with each other, so it’s not potential to combine apples and oranges. There are, nonetheless, methods to transform between sorts.
• Static typing: kind checked whereas compiling, this enables kind errors to be discovered earlier.
• Abstraction: sorts symbolize the actual world or the issue at hand; not how the pc represents the info internally. There are methods to specify precisely how a kind have to be represented on the bit stage, however we’ll defer that dialogue to a different chapter.
• Title equivalence, versus structural equivalence utilized in most different languages. Two sorts are suitable if and provided that they’ve the identical identify; not if they simply occur to have the identical measurement or bit illustration. You possibly can thus declare two integer sorts with the identical ranges which can be completely incompatible, or two report sorts with precisely the identical parts, however that are incompatible.

Varieties are incompatible with each other. Nevertheless, every kind can have any variety of subtypes, that are suitable with their base kind and could also be suitable with each other. See beneath for examples of subtypes that are incompatible with each other.

## Predefined sorts

There are a number of predefined sorts, however most programmers want to outline their very own, application-specific sorts. However, these predefined sorts are very helpful as interfaces between libraries developed independently. The predefined library, clearly, makes use of these sorts too.

These sorts are predefined within the Normal bundle:

Integer
This kind covers not less than the vary

${displaystyle -2^{15}+1}$

..

${displaystyle +2^{15}-1}$

(RM 3.5.4 (21) (Annotated)). The Normal additionally defines `Pure` and `Constructive` subtypes of this kind.

Float
There’s solely a really weak implementation requirement on this kind (RM 3.5.7 (14) (Annotated)); more often than not you’ll outline your personal floating-point sorts, and specify your precision and vary necessities.
Length
A hard and fast level kind used for timing. It represents a time frame in seconds (RM A.1 (43) (Annotated)).
Character
A particular type of Enumerations. There are three predefined sorts of character sorts: 8-bit characters (known as `Character`), 16-bit characters (known as `Wide_Character`), and 32-bit characters (`Wide_Wide_Character`). `Character` has been current for the reason that first model of the language (Ada 83), `Wide_Character` was added in Ada 95, whereas the sort `Wide_Wide_Character` is accessible with Ada 2005.
String
Three indefinite array sorts, of `Character`, `Wide_Character`, and `Wide_Wide_Character` respectively. The usual library incorporates packages for dealing with strings in three variants: mounted size (`Ada.Strings.Mounted`), with various size beneath a sure higher certain (`Ada.Strings.Bounded`), and unbounded size (`Ada.Strings.Unbounded`). Every of those packages has a `Wide_` and a `Wide_Wide_` variant.
Boolean
A `Boolean` in Ada is an Enumeration of `False` and `True` with particular semantics.

Packages `System` and `System.Storage_Elements` predefine some sorts that are primarily helpful for low-level programming and interfacing to {hardware}.

System.Handle
An handle in reminiscence.
System.Storage_Elements.Storage_Offset
An offset, which may be added to an handle to acquire a brand new handle. You can even subtract one handle from one other to get the offset between them. Collectively, `Handle`, `Storage_Offset` and their related subprograms present for handle arithmetic.
System.Storage_Elements.Storage_Count
A subtype of `Storage_Offset` which can’t be unfavorable, and represents the reminiscence measurement of an information construction (much like C’s `size_t`).
System.Storage_Elements.Storage_Element
In most computer systems, this can be a byte. Formally, it’s the smallest unit of reminiscence that has an handle.
System.Storage_Elements.Storage_Array
An array of `Storage_Element`s with none which means, helpful when doing uncooked reminiscence entry.

## The Kind Hierarchy

Varieties are organized hierarchically. A sort inherits properties from sorts above it within the hierarchy. For instance, all scalar sorts (integer, enumeration, modular, fixed-point and floating-point sorts) have operators “<“, “>” and arithmetic operators outlined for them, and all discrete sorts can function array indexes.

Here’s a broad overview of every class of sorts; please observe the hyperlinks for detailed explanations. Inside parenthesis there are equivalences in C and Pascal for readers accustomed to these languages.

Signed Integers (int, INTEGER)
Signed Integers are outlined by way of the vary of values wanted.
Unsigned Integers (unsigned, CARDINAL)
Unsigned Integers are known as Modular Varieties. Aside from being unsigned additionally they have wrap-around performance.
Enumerations (enum, char, bool, BOOLEAN)
Ada Enumeration sorts are a separate kind household.
Floating level (float, double, REAL)
Floating level sorts are outlined by the digits wanted, the relative error certain.
Strange and Decimal Mounted Level (DECIMAL)
Mounted level sorts are outlined by their delta, absolutely the error certain.
Arrays ( [ ], ARRAY [ ] OF, STRING )
Arrays with each compile-time and run-time decided measurement are supported.
Report (struct, class, RECORD OF)
A report is a composite kind that teams a number of fields.
Entry (*, ^, POINTER TO)
Ada’s Entry sorts could also be greater than only a easy reminiscence handle.
Activity & Protected (no equivalence in C or Pascal)
Activity and Protected sorts permit the management of concurrency
Interfaces (no equivalence in C or Pascal)
New in Ada 2005, these sorts are much like the Java interfaces.

### Classification of Varieties

Ada’s sorts may be categorised as follows.

Particular vs. Class-wide

````kind` T `is` ...  -- a particular kind
T'Class      -- the corresponding class-wide kind (exists just for tagged sorts)
```

`T'Class` and `T'Class'Class` are the identical.

Primitive operations with parameters of particular sorts are non-dispatching, these with parameters of class-wide sorts are dispatching.

New sorts may be declared by deriving from particular sorts; primitive operations are inherited by derivation. You can’t derive from class-wide sorts.

Constrained vs. Unconstrained

````kind` I `is` `vary` 1 .. 10;           -- constrained
`kind` AC `is` `array` (1 .. 10) `of` ...  -- constrained
```
````kind` AU `is` `array` (I `vary` <>) `of` ...          -- unconstrained
`kind` R (X: Discriminant [:= Default]) `is` ...  -- unconstrained
```

By giving a constraint to an unconstrained subtype, a subtype or object turns into constrained:

````subtype` RC `is` R (Worth);  -- constrained subtype of R
OC: R (Worth);            -- constrained object of nameless constrained subtype of R
OU: R;                    -- unconstrained object
```

Declaring an unconstrained object is simply potential if a default worth is given within the kind declaration above. The language doesn’t specify how such objects are allotted. GNAT allocates the utmost measurement, in order that measurement adjustments which may happen with discriminant adjustments current no drawback. One other chance is implicit dynamic allocation on the heap and re-allocation adopted by a deallocation when the dimensions adjustments.

Particular vs. Indefinite

````kind` I `is` `vary` 1 .. 10;                     -- particular
`kind` RD (X: Discriminant := Default) `is` ...  -- particular
```
````kind` T (<>) `is` ...                    -- indefinite
`kind` AU `is` `array` (I `vary` <>) `of` ...  -- indefinite
`kind` RI (X: Discriminant) `is` ...      -- indefinite
```

Particular subtypes permit the declaration of objects with out preliminary worth, since objects of particular subtypes have constraints which can be identified at creation-time. Object declarations of indefinite subtypes want an preliminary worth to provide a constraint; they’re then constrained by the constraint delivered by the preliminary worth.

```OT: T  := Expr;                       -- some preliminary expression (object, perform name, and many others.)
OA: AU := (3 => 10, 5 => 2, 4 => 4);  -- index vary is now 3 .. 5
OR: RI := Expr;                       -- once more some preliminary expression as above
```

Unconstrained vs. Indefinite

Be aware that unconstrained subtypes are usually not essentially indefinite as may be seen above with RD: it’s a particular unconstrained subtype.

## Concurrency Varieties

The Ada language makes use of sorts for yet one more goal along with classifying knowledge
+ operations. The sort system integrates concurrency (threading, parallelism).
Programmers will use sorts for expressing the concurrent
threads of management of their applications.

The core items of this a part of the sort system, the job sorts and
the protected sorts are defined in larger depth in

## Restricted Varieties

Limiting a kind means disallowing task.
The “concurrency sorts” described above are all the time restricted.
Programmers can outline their very own sorts to be restricted, too, like this:

````kind` T `is` `restricted` …;
```

(The ellipsis stands for `personal`, or for a `report` definition,
see the corresponding subsection on this web page.)
A restricted kind additionally would not have
an equality operator until the programmer defines one.

You possibly can be taught extra within the restricted sorts chapter.

## Defining new sorts and subtypes

You possibly can outline a brand new kind with the next syntax:

````kind` T `is`...
```

adopted by the outline of the sort, as defined intimately in every class of kind.

Formally, the above declaration creates a kind and its first subtype named `T`. The sort itself, appropriately known as the “kind of T”, is nameless; the RM refers to it as `T` (in italics), however usually speaks sloppily in regards to the kind T. However that is an instructional consideration; for many functions, it’s enough to consider `T` as a kind.
For scalar sorts, there’s additionally a base kind known as `T'Base`, which encompasses all values of T.

For signed integer sorts, the kind of T contains the (full) set of mathematical integers. The bottom kind is a sure {hardware} kind, symmetric round zero (aside from presumably one additional unfavorable worth), encompassing all values of T.

As defined above, all sorts are incompatible; thus:

````kind` Integer_1 `is` `vary` 1 .. 10;
`kind` Integer_2 `is` `vary` 1 .. 10;
A : Integer_1 := 8;
B : Integer_2 := A; -- unlawful!
```

is prohibited, as a result of `Integer_1` and `Integer_2` are completely different and incompatible sorts. It’s this characteristic which permits the compiler to detect logic errors at compile time, similar to including a file descriptor to a lot of bytes, or a size to a weight. The truth that the 2 sorts have the identical vary doesn’t make them suitable: that is identify equivalence in motion, versus structural equivalence. (Under, we’ll see how one can convert between incompatible sorts; there are strict guidelines for this.)

### Creating subtypes

You can even create new subtypes of a given kind, which will probably be suitable with one another, like this:

````kind` Integer_1 `is` `vary` 1 .. 10;
`subtype` Integer_2 `is` Integer_1      `vary` 7 .. 11;  -- dangerous
`subtype` Integer_3 `is` Integer_1'Base `vary` 7 .. 11;  -- OK
A : Integer_1 := 8;
B : Integer_3 := A; -- OK
```

The declaration of `Integer_2` is dangerous as a result of the constraint `7 .. 11` is just not suitable with `Integer_1`; it raises `Constraint_Error` at subtype elaboration time.

`Integer_1` and `Integer_3` are suitable as a result of they’re each subtypes of the identical kind, particularly `Integer_1'Base`.

It’s not mandatory that the subtype ranges overlap, or be included in each other. The compiler inserts a run-time vary test once you assign A to B; if the worth of A, at that time, occurs to be exterior the vary of `Integer_3`, this system raises `Constraint_Error`.

There are a number of predefined subtypes that are very helpful:

````subtype` Pure  `is` Integer `vary` 0 .. Integer'Final;
`subtype` Constructive `is` Integer `vary` 1 .. Integer'Final;
```

### Derived sorts

A derived kind is a brand new, full-blown kind created from an current one. Like another kind, it’s incompatible with its dad or mum; nonetheless, it inherits the primitive operations outlined for the dad or mum kind.

````kind` Integer_1 `is` `vary` 1 .. 10;
`kind` Integer_2 `is` `new` Integer_1 `vary` 2 .. 8;
A : Integer_1 := 8;
B : Integer_2 := A; -- unlawful!
```

Right here each sorts are discrete; it’s obligatory that the vary of the derived kind be included within the vary of its dad or mum. Distinction this with subtypes. The reason being that the derived kind inherits the primitive operations outlined for its dad or mum, and these operations assume the vary of the dad or mum kind. Right here is an illustration of this characteristic:

````process` Derived_Types `is`

`bundle` Pak `is`
`kind` Integer_1 `is` `vary` 1 .. 10;
`process` P (I: `in` Integer_1); -- primitive operation, assumes 1 .. 10
`kind` Integer_2 `is` `new` Integer_1 `vary` 8 .. 10; -- should not break P's assumption
-- process P (I: in Integer_2);  inherited P implicitly outlined right here
`finish` Pak;

`bundle` `physique` Pak `is`
-- omitted
`finish` Pak;

`use` Pak;
A: Integer_1 := 4;
B: Integer_2 := 9;

`start`

P (B); -- OK, name the inherited operation

`finish` Derived_Types;
```

After we name `P (B)`, the parameter B is transformed to `Integer_1`; this conversion in fact passes for the reason that set of acceptable values for the derived kind (right here, 8 .. 10) have to be included in that of the dad or mum kind (1 .. 10). Then P is known as with the transformed parameter.

Contemplate nonetheless a variant of the instance above:

````process` Derived_Types `is`

`bundle` Pak `is`
`kind` Integer_1 `is` `vary` 1 .. 10;
`process` P (I: `in` Integer_1; J: `out` Integer_1);
`kind` Integer_2 `is` `new` Integer_1 `vary` 8 .. 10;
`finish` Pak;

`bundle` `physique` Pak `is`
`process` P (I: `in` Integer_1; J: `out` Integer_1) `is`
`start`
J := I - 1;
`finish` P;
`finish` Pak;

`use` Pak;

A: Integer_1 := 4;  X: Integer_1;
B: Integer_2 := 8;  Y: Integer_2;

`start`

P (A, X);
P (B, Y);

`finish` Derived_Types;
```

When `P (B, Y)` is known as, each parameters are transformed to `Integer_1`. Thus the vary test on J (7) within the physique of P will move. Nevertheless on return parameter Y is transformed again to `Integer_2` and the vary test on Y will in fact fail.

With the above in thoughts, you will note why within the following program Constraint_Error will probably be known as at run time, earlier than `P` is even known as.

````process` Derived_Types `is`

`bundle` Pak `is`
`kind` Integer_1 `is` `vary` 1 .. 10;
`process` P (I: `in` Integer_1; J: `out` Integer_1);
`kind` Integer_2 `is` `new` Integer_1'Base `vary` 8 .. 12;
`finish` Pak;

`bundle` `physique` Pak `is`
`process` P (I: `in` Integer_1; J: `out` Integer_1) `is`
`start`
J := I - 1;
`finish` P;
`finish` Pak;

`use` Pak;

B: Integer_2 := 11;  Y: Integer_2;

`start`

P (B, Y);

`finish` Derived_Types;
```

## Subtype classes

Ada helps numerous classes of subtypes which have completely different talents. Right here is an outline in alphabetical order.

### Nameless subtype

A subtype which doesn’t have a reputation assigned to it. Such a subtype is created with a variable declaration:

```X : String (1 .. 10) := (`others` => ' ');
```

Right here, (1 .. 10) is the constraint. This variable declaration is equal to:

````subtype` Anonymous_String_Type `is` String (1 .. 10);

X : Anonymous_String_Type := (`others` => ' ');
```

### Base kind

In Ada, all sorts are nameless and solely subtypes could also be named.
For scalar sorts, there’s a particular subtype of the nameless kind, known as the base kind, which is nameable with the ‘Base attribute.
The bottom kind contains all values of the first subtype. Some examples:

``` `kind` Int `is` `vary` 0 .. 100;
```

The bottom kind `Int'Base` is a {hardware} kind chosen by the compiler that contains the values of `Int`. Thus it might have the vary -27 .. 27-1 or -215 .. 215-1 or another such kind.

``` `kind` Enum  `is` (A, B, C, D);
`kind` Quick `is` `new` Enum `vary` A .. C;
```

`Enum'Base` is similar as `Enum`, however `Quick'Base` additionally holds the literal `D`.

### Constrained subtype

A subtype of an indefinite subtype that provides constraints. The next instance defines a 10 character string sub-type.

``` `subtype` String_10 `is` String (1 .. 10);
```

You can’t partially constrain an unconstrained subtype:

``` `kind` My_Array `is` `array` (Integer `vary` <>, Integer `vary` <>) `of` Some_Type;

-- `subtype` Constr `is` My_Array (1 .. 10, Integer `vary` <>);  unlawful

`subtype` Constr `is` My_Array (1 .. 10, -100 .. 200);
```

Constraints for all indices have to be given, the result’s essentially a particular subtype.

### Particular subtype

A particular subtype is a subtype whose measurement is thought at compile-time. All subtypes which aren’t indefinite subtypes are, by definition, particular subtypes.

Objects of particular subtypes could also be declared with out further constraints.

### Indefinite subtype

An indefinite subtype is a subtype whose measurement is just not identified at compile-time however is dynamically calculated at run-time. An indefinite subtype doesn’t by itself present sufficient data to create an object; a further constraint or specific initialization expression is important as a way to calculate the precise measurement and due to this fact create the article.

```X : String := "It is a string";
```

`X` is an object of the indefinite (sub)kind `String`. Its constraint is derived implicitly from its preliminary worth. `X` might change its worth, however not its bounds.

It needs to be famous that it’s not essential to initialize the article from a literal. You can even use a perform. For instance:

```X : String := Ada.Command_Line.Argument (1);
```

This assertion reads the primary command-line argument and assigns it to `X`.

A subtype of an indefinite subtype that doesn’t add a constraint solely introduces a brand new identify for the unique subtype (a form of renaming below a distinct notion).

``` `subtype` My_String `is` String;
```

My_String and String are interchangeable.

### Named subtype

A subtype which has a reputation assigned to it. “First subtypes” are created with the key phrase `kind` (keep in mind that sorts are all the time nameless, the identify in a kind declaration is the identify of the primary subtype), others with the key phrase `subtype`. For instance:

````kind` Count_To_Ten `is` `vary` 1 .. 10;
```

`Count_to_Ten` is the primary subtype of an acceptable integer base kind.
Nevertheless, if you want to make use of this as an index constraint on `String`, the next declaration is prohibited:

````subtype` Ten_Characters `is` String (Count_to_Ten);
```

It’s because `String` has `Constructive` as its index, which is a subtype of `Integer` (these declarations are taken from bundle `Normal`):

````subtype` Constructive `is` Integer `vary` 1 .. Integer'Final;

`kind` String `is` (Constructive `vary` <>) `of` Character;
```

So you need to use the next declarations:

````subtype` Count_To_Ten `is` Integer `vary` 1 .. 10;
`subtype` Ten_Characters `is` String (Count_to_Ten);
```

Now `Ten_Characters` is the identify of that subtype of `String` which is constrained to `Count_To_Ten`.
You see that posing constraints on sorts versus subtypes has very completely different results.

### Unconstrained subtype

Any indefinite kind can also be an unconstrained subtype. Nevertheless, unconstrainedness and indefiniteness are usually not the identical.

``` `kind` My_Enum `is` (A, B, C);
`kind` My_Record (Discriminant: My_Enum) `is` ...;

My_Object_A: My_Record (A);
```

This kind is unconstrained and indefinite as a result of you must give an precise discriminant for object declarations; the article is constrained to this discriminant which can not change.

When nonetheless a default is supplied for the discriminant, the sort is particular but unconstrained; it permits to outline each, constrained and unconstrained objects:

``` `kind` My_Enum `is` (A, B, C);
`kind` My_Record (Discriminant: My_Enum := A) `is` ...;

My_Object_U: My_Record;      -- unconstrained object
My_Object_B: My_Record (B);  -- constrained to discriminant B like above
```

Right here, My_Object_U is unconstrained; upon declaration, it has the discriminant A (the default) which nonetheless might change.

### Incompatible subtypes

``` `kind` My_Integer `is` `vary` -10 .. + 10;
`subtype` My_Positive `is` My_Integer `vary` + 1 .. + 10;
`subtype` My_Negative `is` My_Integer `vary` -10 .. -  1;
```

These subtypes are in fact incompatible.

One other instance are subtypes of a discriminated report:

``` `kind` My_Enum `is` (A, B, C);
`kind` My_Record (Discriminant: My_Enum) `is` ...;
`subtype` My_A_Record `is` My_Record (A);
`subtype` My_C_Record `is` My_Record (C);
```

## Certified expressions

Usually, the compiler is ready to infer the kind of an expression; for instance:

````kind` Enum `is` (A, B, C);
E : Enum := A;
```

Right here the compiler is aware of that `A` is a price of the sort `Enum`. However contemplate:

````process` Unhealthy `is`
`kind` Enum_1 `is` (A, B, C);
`process` P (E : `in` Enum_1) `is`... -- omitted
`kind` Enum_2 `is` (A, X, Y, Z);
`process` P (E : `in` Enum_2) `is`... -- omitted
`start`
P (A); -- unlawful: ambiguous
`finish` Unhealthy;
```

The compiler can’t select between the 2 variations of `P`; each can be equally legitimate. To take away the anomaly, you employ a certified expression:

```   P (Enum_1'(A)); -- OK
```

As seen within the following instance, this syntax is usually used when creating new objects. For those who attempt to compile the instance, it would fail with a compilation error for the reason that compiler will decide that 256 is just not in vary of `Byte`.

````with` Ada.Text_IO;

`process` Convert_Evaluate_As `is`
`kind` Byte     `is` `mod` 2**8;
`kind` Byte_Ptr `is` `entry` Byte;

`bundle` T_IO `renames` Ada.Text_IO;
`bundle` M_IO `is` `new` Ada.Text_IO.Modular_IO (Byte);

A : `fixed` Byte_Ptr := `new` Byte'(256);
`start`
T_IO.Put ("A = ");
M_IO.Put (Merchandise  => A.all,
Width =>  5,
Base  => 10);
`finish` Convert_Evaluate_As;
```

You need to use certified expression when getting a string literal’s size.

```"foo"'Size                  -- compilation error: prefix of attribute have to be a reputation
--                    qualify expression to show it into a reputation
String'("foo" & "bar")'Size -- 6
```

## Kind conversions

Information don’t all the time come within the format you want them. You should, then, face the duty of changing them. As a real multi-purpose language with a particular emphasis on “mission important”, “system programming” and “security”, Ada has a number of conversion methods. Essentially the most troublesome half is choosing the proper one, so the next checklist is sorted so as of utility. You need to attempt the primary one first; the final method is a final resort, for use if all others fail. There are additionally a number of associated methods that you simply would possibly select as a substitute of really changing the info.

Since an important side is just not the results of a profitable conversion, however how the system will react to an invalid conversion, all examples additionally reveal defective conversions.

### Express kind conversion

An specific kind conversion seems very like a perform name; it doesn’t use the tick (apostrophe, ‘) just like the certified expression does.

```Type_Name (Expression)
```

The compiler first checks that the conversion is authorized, and whether it is, it inserts a run-time test on the level of the conversion; therefore the identify checked conversion. If the conversion fails, this system raises Constraint_Error. Most compilers are very good and optimise away the constraint checks; so, you needn’t fear about any efficiency penalty. Some compilers can even warn {that a} constraint test will all the time fail (and optimise the test with an unconditional increase).

Express kind conversions are authorized:

• between any two numeric sorts
• between any two subtypes of the identical kind
• between any two sorts derived from the identical kind (word particular guidelines for tagged sorts)
• between array sorts below sure circumstances (see RM 4.6(24.2/2..24.7/2))
• and nowhere else

(The principles turn into extra complicated with class-wide and nameless entry sorts.)

```I: Integer := Integer (10);  -- Pointless specific kind conversion
J: Integer := 10;            -- Implicit conversion from common integer
Ok: Integer := Integer'(10);  -- Use the worth 10 of kind Integer: certified expression
-- (qualification not mandatory right here).
```

This instance illustrates specific kind conversions:

````with` Ada.Text_IO;

`process` Convert_Checked `is`
`kind` Quick `is` `vary` -128 .. +127;
`kind` Byte  `is` `mod` 256;

`bundle` T_IO `renames` Ada.Text_IO;
`bundle` I_IO `is` `new` Ada.Text_IO.Integer_IO (Quick);
`bundle` M_IO `is` `new` Ada.Text_IO.Modular_IO (Byte);

A : Quick := -1;
B : Byte;
`start`
B := Byte (A);  -- vary test will result in Constraint_Error
T_IO.Put ("A = ");
I_IO.Put (Merchandise  =>  A,
Width =>  5,
Base  => 10);
T_IO.Put (", B = ");
M_IO.Put (Merchandise  =>  B,
Width =>  5,
Base  => 10);
`finish` Convert_Checked;
```

Express conversions are potential between any two numeric sorts: integers, fixed-point and floating-point sorts. If one of many sorts concerned is a fixed-point or floating-point kind, the compiler not solely checks for the vary constraints (thus the code above will increase Constraint_Error), but in addition performs any lack of precision mandatory.

Instance 1: the lack of precision causes the process to solely ever print “0” or “1”, since `P / 100` is an integer and is all the time zero or one.

````with` Ada.Text_IO;
`process` Naive_Explicit_Conversion `is`
`kind` Proportion `is` `digits` 4 `vary` 0.0 .. 1.0;
`kind` Proportion `is` `vary` 0 .. 100;
`perform` To_Proportion (P : `in` Proportion) `return` Proportion `is`
`start`
`return` Proportion (P / 100);
`finish` To_Proportion;
`start`
`finish` Naive_Explicit_Conversion;
```

Instance 2: we use an intermediate floating-point kind to ensure the precision.

````with` Ada.Text_IO;
`process` Explicit_Conversion `is`
`kind` Proportion `is` `digits` 4 `vary` 0.0 .. 1.0;
`kind` Proportion `is` `vary` 0 .. 100;
`perform` To_Proportion (P : `in` Proportion) `return` Proportion `is`
`kind` Prop `is` `digits` 4 `vary` 0.0 .. 100.0;
`start`
`return` Proportion (Prop (P) / 100.0);
`finish` To_Proportion;
`start`
`finish` Explicit_Conversion;
```

You would possibly ask why you need to convert between two subtypes of the identical kind. An instance will illustrate this.

````subtype` String_10 `is` String (1 .. 10);
X: String := "A line lengthy sufficient to make the instance legitimate";
Slice: `fixed` String := String_10 (X (11 .. 20));
```

Right here, `Slice` has bounds 1 and 10, whereas `X (11 .. 20)` has bounds 11 and 20.

### Change of Illustration

Kind conversions can be utilized for packing and unpacking of information or arrays.

````kind` Unpacked `is` `report`
-- any parts
`finish` `report`;

`kind` Packed `is` `new` Unpacked;
`for`  Packed `use` `report`
-- part clauses for some or for all parts
`finish` `report`;
```
```P: Packed;
U: Unpacked;

P := Packed (U);  -- packs U
U := Unpacked (P);  -- unpacks P
```

### Checked conversion for non-numeric sorts

The examples above all revolved round conversions between numeric sorts; it’s potential to transform between any two numeric sorts on this manner. However what occurs between non-numeric sorts, e.g. between array sorts or report sorts? The reply is two-fold:

• you may convert explicitly between a kind and kinds derived from it, or between sorts derived from the identical kind,
• and that is all. No different conversions are potential.

Why would you wish to derive a report kind from one other report kind? Due to illustration clauses. Right here we enter the realm of low-level programs programming, which isn’t for the faint of coronary heart, neither is it helpful for desktop purposes. So maintain on tight, and let’s dive in.

Suppose you have got a report kind which makes use of the default, environment friendly illustration. Now you wish to write this report to a tool, which makes use of a particular report format. This particular illustration is extra compact (makes use of fewer bits), however is grossly inefficient. You wish to have a layered programming interface: the higher layer, supposed for purposes, makes use of the environment friendly illustration. The decrease layer is a tool driver that accesses the {hardware} straight and makes use of the inefficient illustration.

````bundle` Device_Driver `is`
`kind` Size_Type `is` `vary` 0 .. 64;
`kind` Register `is` `report`
A, B : Boolean;
Dimension : Size_Type;
`finish` `report`;

`process` Learn (R : `out` Register);
`process` Write (R : `in` Register);
`finish` Device_Driver;
```

The compiler chooses a default, environment friendly illustration for `Register`. For instance, on a 32-bit machine, it might in all probability use three 32-bit phrases, one for A, one for B and one for Dimension. This environment friendly illustration is sweet for purposes, however at one level we wish to convert the whole report to simply Eight bits, as a result of that is what our {hardware} requires.

````bundle` `physique` Device_Driver `is`
`kind` Hardware_Register `is` `new` Register; -- Derived kind.
`for` Hardware_Register `use` `report`
A `at` 0 `vary` 0 .. 0;
B `at` 0 `vary` 1 .. 1;
Dimension `at` 0 `vary` 2 .. 7;
`finish` `report`;

`perform` Get `return` Hardware_Register; -- Physique omitted
`process` Put (H : `in` Hardware_Register); -- Physique omitted

`process` Learn (R : `out` Register) `is`
H : Hardware_Register := Get;
`start`
R := Register (H); -- Express conversion.
`finish` Learn;

`process` Write (R : `in` Register) `is`
`start`
Put (Hardware_Register (R)); -- Express conversion.
`finish` Write;
`finish` Device_Driver;
```

Within the above instance, the bundle physique declares a derived kind with the inefficient, however compact illustration, and converts to and from it.

This illustrates that kind conversions may end up in a change of illustration.

### View conversion, in object-oriented programming

Inside object-oriented programming you need to distinguish between particular sorts and class-wide sorts.

With particular sorts, solely conversions within the path to the basis are potential, which in fact can’t fail. There are not any conversions in the wrong way (the place would you get the additional parts from?); extension aggregates have for use as a substitute.

With the conversion itself, no parts of the supply object that aren’t current within the goal object are misplaced, they’re simply hidden from visibility. Subsequently, this type of conversion is known as a view conversion because it supplies a view of the supply object as an object of the goal kind (particularly it doesn’t change the article’s tag).

It’s a frequent idiom in object oriented programming to rename the results of a view conversion. (A renaming declaration doesn’t create a brand new object; it solely provides a brand new identify to one thing that already exists.)

````kind` Parent_Type `is` `tagged` `report`
;
`finish` `report`;
`kind` Child_Type `is` `new` Parent_Type `with` `report`
;
`finish` `report`;

Child_Instance : Child_Type;
Parent_View    : Parent_Type `renames` Parent_Type (Child_Instance);
Parent_Part    : Parent_Type := Parent_Type (Child_Instance);
```

`Parent_View` is just not a brand new object, however one other identify for `Child_Instance` seen because the dad or mum, i.e. solely the dad or mum parts are seen, the child-specific parts are hidden. `Parent_Part`, nonetheless, is an object of the dad or mum kind, which in fact has no storage for the child-specific parts, so they’re misplaced with the task.

All sorts derived from a tagged kind `T` kind a tree rooted at `T`. The category-wide kind `T'Class` can maintain any object inside this tree. With class-wide sorts, conversions in any path are potential; there’s a run-time tag test that raises `Constraint_Error` if the test fails. These conversions are additionally view conversions, no knowledge is created or misplaced.

```Object_1 : Parent_Type'Class := Parent_Type'Class (Child_Instance);
Object_2 : Parent_Type'Class `renames` Parent_Type'Class (Child_Instance);
```

`Object_1` is a brand new object, a replica; `Object_2` is only a new identify. Each objects are of the class-wide kind. Conversions to any kind throughout the given class are authorized, however are tag-checked.

```Success : Child_Type := Child_Type (Parent_Type'Class (Parent_View));
Failure : Child_Type := Child_Type (Parent_Type'Class (Parent_Part));
```

The primary conversion passes the tag test and each objects `Child_Instance` and `Success` are equal. The second conversion fails the tag test. (Conversion assignments of this type will not often be used; dispatching will do that robotically, see object oriented programming.)

You possibly can carry out these checks your self with membership checks:

````if` Parent_View `in` Child_Type `then` ...
`if` Parent_View `in` Child_Type'`Class` `then` ...
```

There’s additionally the bundle `Ada.Tags`.

### Handle conversion

Ada’s entry kind isn’t just a reminiscence location (a skinny pointer). Relying on implementation and the entry kind used, the entry would possibly maintain further data (a fats pointer). For instance GNAT retains two reminiscence addresses for every entry to an indefinite object — one for the info and one for the constraint informations (Dimension, First, Final).

If you wish to convert an entry to a easy reminiscence location you should use the bundle `System.Address_To_Access_Conversions`.
Be aware nonetheless that an handle and a fats pointer can’t be transformed reversibly into each other.

The handle of an array object is the handle of its first part. Thus the bounds get misplaced in such a conversion.

````kind` My_Array `is` `array` (Constructive `vary` <>) `of` One thing;
A: My_Array (50 .. 100);

A'Handle = A(A'First)'Handle
```

### Unchecked conversion

One of many nice criticisms of Pascal was “there is no such thing as a escape”. The rationale was that generally you need to convert the incompatible. For this goal, Ada has the generic perform Unchecked_Conversion:

````generic`
`kind` Supply (<>) `is` `restricted` `personal`;
`kind` Goal (<>) `is` `restricted` `personal`;
`perform` Ada.Unchecked_Conversion (S : Supply) `return` Goal;
```

`Unchecked_Conversion` will bit-copy the supply knowledge and reinterpret them below the goal kind with none checks. It’s your chore to ensure that the necessities on unchecked conversion as acknowledged in RM 13.9 (Annotated) are fulfilled; if not, the result’s implementation dependent and will even result in irregular knowledge. Use the ‘Legitimate attribute after the conversion to test the validity of the info in problematic circumstances.

A perform name to (an occasion of) `Unchecked_Conversion` will copy the supply to the vacation spot. The compiler may additionally do a conversion in place (each occasion has the conference Intrinsic).

To make use of `Unchecked_Conversion` you must instantiate the generic.

Within the instance beneath, you may see how that is performed. When run, the instance will output `A = -1, B = 255`. No error will probably be reported, however is that this the outcome you anticipate?

````with` Ada.Text_IO;
`with` Ada.Unchecked_Conversion;

`process` Convert_Unchecked `is`

`kind` Quick `is` `vary` -128 .. +127;
`kind` Byte  `is` `mod` 256;

`bundle` T_IO `renames` Ada.Text_IO;
`bundle` I_IO `is` `new` Ada.Text_IO.Integer_IO (Quick);
`bundle` M_IO `is` `new` Ada.Text_IO.Modular_IO (Byte);

`perform` Convert `is` `new` Ada.Unchecked_Conversion (Supply => Quick,
Goal => Byte);

A : `fixed` Quick := -1;
B : Byte;

`start`

B := Convert (A);
T_IO.Put ("A = ");
I_IO.Put (Merchandise  =>  A,
Width =>  5,
Base  => 10);
T_IO.Put (", B = ");
M_IO.Put (Merchandise  =>  B,
Width =>  5,
Base  => 10);

`finish` Convert_Unchecked;
```

There’s in fact a variety test within the task `B := Convert (A);`. Thus if `B` have been outlined as `B: Byte vary 0 .. 10;`, `Constraint_Error` can be raised.

### Overlays

If the copying of the results of `Unchecked_Conversion` is an excessive amount of waste by way of efficiency, then you may attempt overlays, i.e. handle mappings. By utilizing overlays, each objects share the identical reminiscence location. For those who assign a price to 1, the opposite adjustments as properly. The syntax is:

````for` Goal'Handle `use` expression;
`pragma` Import (Ada, Goal);
```

the place expression defines the handle of the supply object.

Whereas overlays would possibly look extra elegant than `Unchecked_Conversion`, you need to be conscious that they’re much more harmful and have even larger potential for doing one thing very unsuitable. For instance if `Supply'Dimension < Goal'Dimension` and also you assign a price to Goal, you would possibly inadvertently write into reminiscence allotted to a distinct object.

It’s a must to take care additionally of implicit initializations of objects of the goal kind, since they might overwrite the precise worth of the supply object. The Import pragma with conference Ada can be utilized to stop this, because it avoids the implicit initialization, RM B.1 (Annotated).

The instance beneath does the identical as the instance from “Unchecked Conversion”.

````with` Ada.Text_IO;

`process` Convert_Address_Mapping `is`
`kind` Quick `is` `vary` -128 .. +127;
`kind` Byte  `is` `mod` 256;

`bundle` T_IO `renames` Ada.Text_IO;
`bundle` I_IO `is` `new` Ada.Text_IO.Integer_IO (Quick);
`bundle` M_IO `is` `new` Ada.Text_IO.Modular_IO (Byte);

A : `aliased` Quick;
B : `aliased` Byte;

`for` B'Handle `use` A'Handle;
`pragma` Import (Ada, B);

`start`
A := -1;
T_IO.Put ("A = ");
I_IO.Put (Merchandise  =>  A,
Width =>  5,
Base  => 10);
T_IO.Put (", B = ");
M_IO.Put (Merchandise  =>  B,
Width =>  5,
Base  => 10);
`finish` Convert_Address_Mapping;
```

### Export / Import

Only for the report: There’s nonetheless one other technique utilizing the Export and Import pragmas. Nevertheless, since this technique fully undermines Ada’s visibility and kind ideas much more than overlays, it has no place right here on this language introduction and is left to specialists.

## Elaborated Dialogue of Varieties for Signed Integer Varieties

As defined earlier than, a kind declaration

````kind` T `is` `vary` 1 .. 10;
```

declares an nameless kind `T` and its first subtype `T` (please word the italicization). `T` encompasses the whole set of mathematical integers. Static expressions and named numbers make use of this truth.

All numeric integer literals are of kind `Universal_Integer`. They’re transformed to the suitable particular kind the place wanted. `Universal_Integer` itself has no operators.

Some examples with static named numbers:

``` S1: `fixed` := Integer'Final + Integer'Final;       -- "+" of Integer
S2: `fixed` := Long_Integer'Final + 1;             -- "+" of Long_Integer
S3: `fixed` := S1 + S2;                           -- "+" of root_integer
S4: `fixed` := Integer'Final + Long_Integer'Final;  -- unlawful
```

Static expressions are evaluated at compile-time on the suitable sorts with no overflow checks, i.e. mathematically actual (solely restricted by pc retailer). The result’s then implicitly transformed to `Universal_Integer`.

The literal 1 in `S2` is of kind `Universal_Integer` and implicitly transformed to `Long_Integer`.

`S3` implicitly converts the summands to `root_integer`, performs the calculation and converts again to `Universal_Integer`.

`S4` is prohibited as a result of it mixes two differing kinds. You possibly can nonetheless write this as

``` S5: `fixed` := Integer'Pos (Integer'Final) + Long_Integer'Pos (Long_Integer'Final);  -- "+" of root_integer
```

the place the Pos attributes convert the values to `Universal_Integer`, that are then additional implicitly transformed to `root_integer`, added and the outcome transformed again to `Universal_Integer`.

`root_integer` is the nameless biggest integer kind representable by the {hardware}. It has the vary `System.Min_Integer .. System.Max_Integer`. All integer sorts are rooted at `root_integer`, i.e. derived from it. `Universal_Integer` may be seen as `root_integer'Class`.

Throughout run-time, computations in fact are carried out with vary checks and overflow checks on the suitable subtype. Intermediate outcomes might nonetheless exceed the vary limits. Thus with `I, J, Ok` of the subtype `T` above, the next code will return the right outcome:

```I := 10;
J :=  8;
Ok := (I + J) - 12;
-- I := I + J;  -- vary test would fail, resulting in Constraint_Error
```

Actual literals are of kind `Universal_Real`, and related guidelines as those above apply accordingly.

## Relations between sorts

Varieties may be created from different sorts. Array sorts, for instance, are created from two sorts, one for the arrays’ index and one for the arrays’ parts. An array, then, expresses an affiliation, particularly that between one worth of the index kind and a price of the part kind.

``` `kind` Coloration `is` (Purple, Inexperienced, Blue);
`kind` Depth `is` `vary` 0 .. 255;

`kind` Colored_Point `is` `array` (Coloration) `of` Depth;
```

The sort Coloration is the index kind and the sort Depth is the part kind of the array kind Colored_Point. See array.