• Aucun résultat trouvé

Expressions, agrégats et opérations sur les tableau

8.2 GÉNÉRALITÉS 1 Définitions

8.2.5 Expressions, agrégats et opérations sur les tableau

Les expressions d’un type tableau quelconque comprennent les constantes, variables, paramètres et agrégats. Dans le cas des tableaux unidimensionnels, il existe en plus la notion de tranche de tableau (§ 8.5.1). Comme pour les articles il faut insister sur la création d’agrégats qui, ici, sont formés d’une expression par valeur d’indice (exemple 8.4).

Le diagramme de la figure 8.1 ne l’indique pas mais un agrégat tableau doit être noté entièrement par position, ou entièrement par nom pour un indice donné. Le mélange des notations est ici interdit. Seule exception: others => est autorisé (mentionné à la fin de l’agrégat) si le reste est noté par position.

GÉNÉRALITÉS 171

Figure 8.1 Diagramme syntaxique définissant un agrégat de tableau.

Exemple 8.4 Agrégats tableaux.

-- Agregats du type T_Ligne ou T_Ligne_Bis (probablement)

(0..Max_Longueur_Ligne-1 => ' ')-- 80 espaces, notation par nom

(T_Long_Ligne => ' ') -- 80 espaces, notation par nom

-- Agregats du type T_Vecteur (probablement)

(0.0, 0.0, 1.0, 1.0) -- Vecteur a 4 composantes

(0.0, 0.0) -- Vecteur a 2 composantes

(1..6 => 0.0, 7 | 8 => 1.0, 9 => 1.0) -- Vecteur a 9 composantes -- Agregats du type T_Matrice (probablement)

( (0.0, 0.0), (1.0, 1.0) ) -- Matrice carree 2 x 2

( 1 => (0.0, 0.0), 2 => (1.0, 1.0) ) -- Matrice carree 2 x 2

( 1..3 => (0.0, 0.0) ) -- Matrice 3 x 2

( 1..3 => (1..2 => 0.0) ) -- Matrice 3 x 2

Les agrégats de tableaux peuvent paraître compliqués. Pour que le compilateur puisse vérifier leur validité et réserver de la mémoire pour les implémenter, il faut en effet toujours que leur longueur et leurs bornes soient bien définies (en particulier lorsque others est utilisé), ce qu’il faut constamment garder à l’esprit

pour bien comprendre les explications qui suivent. Un agrégat est toujours contigu car c’est un tableau même si la syntaxe ne le montre pas explicitement!

Comme pour les articles, le compilateur doit toujours connaître le type d’un

( Agrégat tableau expression ) , | => valeur d’indice others intervalle => expression expression ,

GÉNÉRALITÉS 172

agrégat tableau. Une bonne manière de procéder consiste en la qualification de l’agrégat (exemple 8.5) en le préfixant par un identificateur de type ou de sous-type suivi d’une apostrophe (sect. 3.10). Mais en plus il faut que l’intervalle de valeurs, pour chaque indice, soit défini et corresponde à celui du type de l’agrégat.

Exemple 8.5 Agrégats qualifiés.

-- Agregats du type T_Ligne

T_Ligne'(0..Max_Longueur_Ligne – 1 => ' ') T_Ligne'(T_Long_Ligne => ' ')

-- Agregats du type T_Vecteur

T_Vecteur'(0.0, 0.0, 1.0, 1.0) -- Vecteur a 4 composantes

T_Vecteur_2'(0.0, 0.0) -- Vecteur a 2 composantes

T_Vecteur_2'( others => 0.0) -- Vecteur a 2 composantes

-- Agregats du type T_Matrice

T_Matrice'( (0.0, 0.0), (1.0, 1.0) ) -- Matrice carree 2 x 2

T_Matrice'( 1 => (0.0, 0.0), -- Matrice carree 2 x 2

2 => (1.0, 1.0) )

T_Matrice_2_3'( 1..2 => (0.0, 0.0, 0.0) ) -- Matrice 2 x 3

Les règles définissant la validité ou non d’un agrégat, sa longueur et ses bornes se basent sur l’agrégat lui-même ainsi que sur son contexte, c’est-à-dire la situation où l’agrégat est utilisé. A des fins de simplicité, seuls des cas simples vont être pré- sentés. Pour plus de détails, la théorie complète peut être consultée dans [BAR 97]. Il faut préciser que lors d’une affectation, du passage en paramètre ou de l’attribution de la valeur par défaut, les bornes d’un agrégat n’ont pas besoin d’être identiques à celles de l’objet affecté, il y a conversion automatique des bornes de l’agrégat.

Exemple 8.6 Agrégats tableaux, longueurs et bornes.

-- Type tableau pour traiter des vecteurs de n'importe quelle -- taille

type T_Vecteur is array (Integer range <>) of Float;

---

-- pour traiter des vecteurs a deux composantes Nombre_Composantes : constant := 2;

subtype T_Vecteur_2 is T_Vecteur (1..Nombre_Composantes);

--- -- fonction qui retourne la norme de vecteurs a deux composantes

function Norme_2_Composantes (Vecteur : in T_Vecteur_2) return Float;

GÉNÉRALITÉS 173

-- fonction qui retourne la norme de n'importe quel vecteur de type -- T_Vecteur

function Norme (Vecteur : in T_Vecteur) return Float;

--- -- Dans ce qui suit, la longueur et la borne inferieure se

-- rapportent a l'agregat

--- -- Affectation: longueur 2, borne inferieure 1

Vecteur_1 : constant T_Vecteur_2 := (1.0, others => 0.0); Vecteur_2 : T_Vecteur_2 := (1.0, 2.0);

--- -- Passage en parametre: longueur 2, borne inferieure 1

L1 : Float := Norme_2_Composantes ( (1.0, 2.0) );

---

-- Passage en parametre: longueur 3,

-- borne inferieure Integer'First

L2 : Float := Norme ( (1.0, 2.0, 3.0) );

---

-- Passage en parametre: longueur 3,

-- borne inferieure 5

L2 := Norme ( (5 => 1.0, 6 => 2.0, 7 => 3.0) ); -- Qualification: longueur 2, borne inferieure 1 Vecteur_3 : T_Vecteur := T_Vecteur_2'(others =>0.0); Vecteur_3 := T_Vecteur_2'(1..2 => 0.0);

L3 : Float := Norme ( T_Vecteur_2'(others => 0.0) );

--- -- ATTENTION

---

-- Utilisation d'agregats interdite

Vecteur_4 : T_Vecteur := (others => 0.0); -- Longueur inconnue

L4 : Float := Norme ( (1.0, others => 0.0) ); -- Longueur inconnue -- Exception Constraint_Error levee

Vecteur_3 := (1..4 => 1.0); -- Longueurs differentes

Vecteur_3 := T_Vecteur_2'(2..3 => 1.0); -- Bornes differentes

L3 := Norme_2_Composantes ( (1..3 => 0.0) ); -- Longueurs differentes

Comme certains agrégats de l’exemple 8.6 l’ont peut-être suggéré, les valeurs d’indice ou les intervalles de la notation par nom doivent être statiques, sauf dans un seul cas: celui où l’agrégat est de la forme(intervalle => expression). Ici l’intervalle peut comporter des bornes dynamiques; un intervalle vide (§ 8.2.8), qui définit alors un agrégat ne contenant aucune valeur, est donc possible.

Une constante tableau se déclare donc en utilisant un agrégat comme valeur. Les agrégats servent également à donner la valeur initiale d’une variable tableau

GÉNÉRALITÉS 174

ou la valeur par défaut d’un paramètre tableau (exemple 8.6).

Les opérations possibles sur les tableaux (en plus de l’affectation et du passage en paramètre) sont l’égalité = et l’inégalité /=.

Il faut cependant relever que, lors du passage en paramètre (de sous- programme) d’un tableau, le paramètre formel hérite des bornes du paramètre effectif si le paramètre formel est d’un type (ou sous-type) tableau non contraint; dans le cas contraire, les bornes sont fixées par le type (ou sous-type) contraint lui- même. Comme l’héritage a lieu à l’exécution, la connaissance des bornes du paramètre formel ne peut se faire que par l’utilisation d’attributs comme First et Last (§ 8.2.7).

A noter que les tableaux unidimensionnels comportent des opérations sup- plémentaires (sect. 8.5).

8.2.6 Affectation

L’affectation se fait de manière habituelle mais la longueur de l’expression (ici un tableau), pour chaque indice, doit être identique à celle de la variable sinon l’ex- ception Constraint_Error sera levée (note 8.2). Par contre, les bornes corres- pondantes n’ont pas besoin d’être identiques (§ 8.2.5).

NOTE 8.2 Rôle des longueurs lors de l’affectation de tableaux.

Lors de l’affectation de tableaux, leurs longueurs doivent être identiques faute de quoi l’exception Constraint_Error sera levée (§ 6.3.2).

La figure 8.2 illustre l’affectation d’un tableau avec un agrégat, en rappelant que dans ce cas, l’agrégat est en fait un tableau.

Figure 8.2 Affectation d’un tableau avec un agrégat.