Les expressions
Les expressions sont constituées d'opérateurs et d'opérandes. La plupart des opérateurs Turbo Pascal sont binaires ; ils prennent deux opérandes. Les autres sont unaires et ne prennent qu'un seul opérande. Les opérateurs binaires utilisent le format algébrique habituelle (par exemple, A + B). Un opérateur unaire précède toujours son opérande (par exemple, -B). Dans les expressions plus complexes, les règles de priorité clarifient l'ordre dans lequel les opérations sont effectuées.
Opérateurs | Priorité | Catégories |
---|---|---|
@, not | Premier (haute) | Opérateurs unaires |
*, /, div, mod, and, shl, shr | Deuxième | Opérateurs multiplicateurs |
+, - , or, xor | Troisième | Ajout d'opérateurs |
=, <>, <, >, <=, >=, in | Quatrième (basse) | Opérateurs relationnels |
Il existe 3 règles de préséance de base :
- Un opérande entre deux opérateurs de priorité différente est lié à l'opérateur de priorité plus élevée.
- Un opérande entre deux opérateurs égaux est lié à celui de gauche.
- Les expressions entre parenthèses sont évaluées avant d'être traitées comme un seul opérande.
Les opérations avec une priorité égale sont normalement effectuées de gauche à droite, bien que le compilateur puisse réorganiser les opérandes pour générer un code optimal.
Syntaxe d'expression
Les règles de priorité découlent de la syntaxe des expressions, étant construites à partir de facteurs, de termes et d'expressions simples. La syntaxe d'un facteur est la suivante :
Un appel de fonction active une fonction et indique la valeur renvoyée par la fonction. Un constructeur d'ensemble désigne une valeur d'un type d'ensemble. Un transtypage de valeur change le type d'une valeur. Un facteur d'adresse calcule l'adresse d'une variable, d'une procédure, d'une fonction ou d'une méthode. Une constante non signée a la syntaxe suivante :
Voici quelques exemples de facteurs :
Les termes appliquent les opérateurs multiplicateurs aux facteurs :
Voici quelques exemples de termes :
Des expressions simples appliquent l'ajout d'opérateurs et de signes aux termes :
Voici quelques exemples d'expressions simples :
- X + Y
- -X
- Hue1 + Hue2
- I * J + 1
Une expression applique les opérateurs relationnels à des expressions simples :
Voici quelques exemples d'expressions :
- x = 1.5
- Done <> Error
- (I < J) = (J < K)
- C in Huel
Les opérateurs
Les opérateurs sont classés en opérateurs arithmétiques, opérateurs logiques, opérateurs de chaîne de caractères, opérateurs de pointeur de caractère, opérateurs d'ensemble, opérateurs relationnels et opérateur @.
Opérateurs arithmétiques
Les tableaux suivants présentent les types d'opérandes et les résultats des opérations arithmétiques binaires et unaires.
Opérateur | Opération | Types d'opérandes | Type de résultat |
---|---|---|---|
+ | Addition | Type d'entier Type de réel |
Type d'entier Type de réel |
- | Soustraction | Type d'entier Type de réel |
Type d'entier Type de réel |
* | Multiplication | Type d'entier Type de réel |
Type d'entier Type de réel |
/ | Division | Type de réel | Type de réel |
DIV | Division entière | Type d'entier | Type d'entier |
MOD | Restant de division | Type d'entier | Type d'entier |
+ | Identité de signe | Type d'entier Type de réel |
Type d'entier Type de réel |
- | Identité de signe | Type d'entier Type de réel |
Type d'entier Type de réel |
Tout opérande dont le type est une sous-gamme d'un type ordinal est traité comme s'il était de type ordinal. Si les deux opérandes d'un opérateur +, -, *, div ou mod sont de type entier, le type de résultat est du type commun aux deux opérandes. Si un ou les deux opérandes d'un opérateur +, - ou * sont de type réel, le type du résultat est Real dans l'état {$N-} ou Extended dans l'état {$N+}.
Si l'opérande de l'opérateur d'identité de signe ou de négation de signe est de type entier, le résultat est du même type entier. Si l'opérateur est de type réel, le type du résultat est Real ou Extended. La valeur de X / Y est toujours de type Real ou Extended quels que soient les types d'opérandes. Une erreur d'exécution se produit si Y est égal à zéro.
La valeur de I div J est le quotient mathématique de I / J, arrondi dans le sens zéro à une valeur de type entier. Une erreur d'exécution se produit si J est égal à zéro. L'opérateur mod renvoie le reste obtenu en divisant ses deux opérandes ; C'est par exemple :
Le signe du résultat de mod est le même que le signe de I. Une erreur d'exécution se produit si J est égal à zéro.
Opérateurs logiques
Les types d'opérandes et les résultats des opérations logiques sont indiqués dans le tableau suivant :
Opérateur | Opération | Types d'opérandes | Type de résultat |
---|---|---|---|
NOT | Négation binaire | Type entier | Boolean |
AND | Et binaire | Type entier | Boolean |
OR | Ou binaire | Type entier | Boolean |
XOR | Ou exclusif binaire | Type entier | Boolean |
SHL | Décalage vers la gauche | Type entier | Boolean |
SHR | Décalage vers la droite | Type entier | Boolean |
Si l'opérande de l'opérateur NOT est de type entier, le résultat est du même type entier. Si les deux opérandes d'un opérateur AND, OR, ou XOR sont de type entier, le type de résultat est le type commun des deux opérandes. Les opérations I shl J et I shr J décalent la valeur de I vers la gauche à droite de J bits. Le type de résultat est le même que le type de I.
Opérateurs booléens
Les types d'opérandes et les résultats des opérations booléennes sont indiqués dans le tableau suivant :
Opérateur | Opération | Types d'opérandes | Type de résultat |
---|---|---|---|
NOT | Négation | Type booléen | Boolean |
AND | Et logique | Type booléen | Boolean |
OR | Ou logique | Type booléen | Boolean |
XOR | Ou exclusif logique | Type booléen | Boolean |
La logique booléenne normale régit les résultats de ces opérations. Par exemple, A et B sont vrais uniquement si A et B sont TRUE. Le Turbo Pascal prend en charge deux modèles différents de génération de code pour les opérateurs AND et OR : évaluation complète et évaluation (partielle) de court-circuit.
Une évaluation complète signifie que chaque opérande d'une expression booléenne construite à partir des opérateurs et et ou est assuré d'être évalué, même lorsque le résultat de l'expression entière est déjà connu. Ce modèle est pratique lorsqu'un ou plusieurs opérandes d'une expression sont des fonctions avec des effets secondaires qui modifient le sens du programme.
L'évaluation en court-circuit garantit une évaluation stricte de gauche à droite et cette évaluation s'arrête dès que le résultat de l'expression entière devient évident. Ce modèle est pratique dans la plupart des cas car il garantit un temps d'exécution minimum et généralement une taille de code minimum. L'évaluation en court-circuit permet également l'évaluation de constructions n'étant pas légales autrement. Par exemple :
Dans les deux cas, le deuxième test n'est pas évalué si le premier test est FALSE. Le modèle d'évaluation est contrôlé par la directive du compilateur $B. L'état par défaut est {$B-}, et dans cet état, le compilateur génère un code d'évaluation de court-circuit. Dans l'état {$B+}, le compilateur génère une évaluation complète. Étant donné que le Pascal standard ne spécifie pas quel modèle doit être utilisé pour l'évaluation des expressions booléennes, les programmes dépendant de l'un ou l'autre modèle ne sont pas vraiment portables. Vous pouvez cependant décider que sacrifier la portabilité vaut le gain de vitesse d'exécution et de simplicité fourni par le modèle de court-circuit.
Opérateur de chaîne de caractères
Les types d'opérandes et les résultats pour l'opération de chaîne de caractères sont indiqués dans le tableau suivant :
Opérateur | Opération | Types d'opérandes | Type de résultat |
---|---|---|---|
+ | Concaténation | Type STRING, Type CHAR ou un type PACKED STRING | Type chaîne de caractères |
Le Turbo Pascal permet à l'opérateur + d'être utilisé pour concaténer deux opérandes de chaîne de caractères. Le résultat de l'opération 5 + T, où S et T sont d'un type chaîne de caractères, d'un type Char ou d'un type chaîne de caractères compactée, est la concaténation de S et T. Le résultat est compatible avec n'importe quel type de chaîne (mais pas avec Char types et types de chaînes compactées). Si la chaîne de caractères résultante dépasse 255 caractères, elle est tronquée après le caractère 255.
Opérateurs de pointeur de caractère
La syntaxe étendue (activée à l'aide d'une directive de compilateur {$X+}) prend en charge un certain nombre d'opérations de pointeur de caractère. Les opérateurs plus (+) et moins (-) peuvent être utilisés pour incrémenter et décrémenter la partie décalée d'une valeur de pointeur, et l'opérateur moins peut être utilisé pour calculer la distance (différence) entre les parties décalées de deux pointeurs de caractères. En supposant que P et Q sont des valeurs de type PChar et I une valeur de type de données Word, ces constructions sont autorisées :
Opération | Résultat |
---|---|
P + I | Ajouter I à la partie déplacée de P |
I + P | Ajouter I à la partie déplacée de P |
P - I | Soustraire I de la partie déplacée de P |
P - Q | Soustraire la partie déplacée de Q de la partie déplacée de P |
Les opérations P + I et I + P ajoutent I à l'adresse donnée par P, produisant un pointeur pointant I caractères après P. L'opération P - I soustrait I de l'adresse donnée par P, produisant un pointeur pointant I caractères avant P. L'opération P - Q calcule la distance entre Q (l'adresse inférieure) et P (l'adresse supérieure), résultant en une valeur de type Word donnant le nombre de caractères entre Q et P. Cette opération suppose que P et Q pointent dans le même tableau de caractères. Si les deux pointeurs de caractères pointent vers des tableaux de caractères différents, le résultat n'est pas défini.
Opérateurs SET
Les types d'opérandes pour les opérations d'ensembles sont indiqués dans le tableau suivants :
Opérateur | Opération | Types d'opérande |
---|---|---|
+ | Union | Compatible au types SET |
- | Différence | Compatible au types SET |
* | Intersection | Compatible au types SET |
Les résultats des opérations d'ensembles sont conformes aux règles de la logique ensemble :
- Une valeur ordinale C n'est dans A + B que si C est dans A ou B.
- Une valeur ordinale C n'est dans A - B que si C est dans A et non dans B.
- Une valeur ordinale C n'est dans A * B que si C est à la fois dans A et B.
Si la plus petite valeur ordinale membre du résultat d'une opération ensembliste est A et la plus grande est B, alors le type du résultat est l'ensemble A..B.
Opérateurs relationnels
Les types d'opérandes et les résultats des opérations relationnelles sont indiqués dans le tableau suivant :
Opérateur | Opération | Types d'opérandes | Type de résultat |
---|---|---|---|
= | Égalité | Types compatibles simple, pointeur, ensemble, chaîne de caractères ou PACKED STRING | Boolean |
<> | Pas d'égalité | Types compatibles simple, pointeur, ensemble, chaîne de caractères ou PACKED STRING | Boolean |
< | Inférieur à | Types compatibles simple, chaîne de caractères, PACKED STRING ou PChar | Boolean |
> | Supérieur à | Types compatibles simple, chaîne de caractères, PACKED STRING ou PChar | Boolean |
<= | Inférieur ou égale à | Types compatibles simple, chaîne de caractères, PACKED STRING ou PChar | Boolean |
>= | Supérieur ou égale à | Types compatibles simple, chaîne de caractères, PACKED STRING ou PChar | Boolean |
<= | Sous-ensemble de | Types compatible d'ensemble | Boolean |
>= | Super-ensemble de | Types compatible d'ensemble | Boolean |
IN | Membre de | Opérande gauche, tout type ordinal T ; opérande droit, ensemble dont la base est compatible avec T | Boolean |
Comparer des types simples
Lorsque les opérandes =, <>, <, >, >= ou <= sont de types simples, ils doivent être de types compatibles ; cependant, si un opérande est de type réel, l'autre peut être de type entier.
Comparer des chaînes de caractères
Les opérateurs relationnels =, <>, <, >, >= et <= comparent les chaînes de caractères en fonction de l'ordre de l'ensemble de caractères ASCII étendu. Deux valeurs de chaîne de caractères peuvent être comparées car toutes les valeurs de chaîne de caractères sont compatibles.
Une valeur de type caractère est compatible avec une valeur de type chaîne de caractères. Lorsque les deux sont comparés, la valeur de type caractère est traitée comme une valeur de type chaîne de caractères de longueur 1. Lorsqu'une valeur de type chaîne de caractères PACKED avec N composantes est comparée à une valeur de type chaîne de caractères, elle est traitée comme une valeur de type chaîne de caractères de longueur N.
Comparer des chaînes de caractères PACKED
Les opérateurs relationnels =, <>, <, >, >= et <= peuvent également être utilisés pour comparer deux valeurs de type chaîne de caractères PACKED si les deux ont le même nombre de composantes. Si le nombre de composantes est N, alors l'opération correspond à la comparaison de deux chaînes de caractères, chacune de longueur N.
Comparer des pointeurs
Les opérateurs = et <> peuvent être utilisés sur des opérandes de type pointeur compatibles. Deux pointeurs ne sont égaux que s'ils pointent sur le même objet.
Comparer les pointeurs de caractères
La syntaxe étendue (activée à l'aide d'une directive de compilateur {$X+}) permet aux opérateurs >, <, >= et <= d'être appliqués aux valeurs PChar. Notez, cependant, que ces tests relationnels supposent que les deux pointeurs comparés pointent dans le même tableau de caractères, et pour cette raison, les opérateurs ne comparent que les parties décalées des deux valeurs de pointeur. Si les deux pointeurs de caractères pointent vers des tableaux de caractères différents, le résultat n'est pas défini.
Comparer des ensembles
Si A et B sont des opérandes d'ensembles, leurs comparaisons produisent les résultats suivants :
- A = B n'est vrai que si A et B contiennent exactement les mêmes membres ; sinon, A <> B.
- A <= B n'est vrai que si chaque membre de A est également membre de B.
- A >= B n'est vrai que si chaque membre de B est également membre de A.
Appartenance à l'ensemble de test
L'opérateur in renvoie True lorsque la valeur de l'opérande de type ordinal est membre de l'opérande de type set ; sinon, il renvoie False.
L'opérateur @
L'opérateur @ est utilisé dans un facteur d'adresse pour calculer l'adresse d'une variable, d'une procédure, d'une fonction ou d'une méthode.
L'opérateur @ renvoie l'adresse de son opérande, c'est-à-dire qu'il construit une valeur de pointeur pointant vers l'opérande.
@ avec une variable
Lorsqu'il est appliqué à une référence de variable, @ renvoie un pointeur vers la variable. Le type de la valeur de pointeur résultante est contrôlé par la directive du compilateur $T : dans l'état {$T-} (par défaut), le type de résultat est Pointer. En d'autres termes, le résultat est un pointeur non typé, étant compatible avec tous les autres types de pointeur. Dans l'état {$T+}, le type du résultat est ^T, où T est le type de la référence de la variable. En d'autres termes, le résultat est d'un type n'étant compatible qu'avec d'autres pointeurs sur le type de la variable.
Vous pouvez appliquer @ à une procédure, une fonction ou une méthode pour produire un pointeur vers le point d'entrée de la routine. Le type du pointeur résultant est toujours Pointer, quel que soit l'état de la directive du compilateur $T. En d'autres termes, le résultat est toujours un pointeur non typé, étant compatible avec tous les autres types de pointeur.
Lorsque @ est appliqué à une méthode, la méthode doit être spécifiée via un identificateur de méthode qualifié (un identificateur de type objet, suivi d'un point, suivi d'un identificateur de méthode).
Appels de fonction
Un appel de fonction active une fonction spécifiée par un identificateur de fonction, un indicateur de méthode, un indicateur de méthode qualifié ou une référence de variable de type procédural. L'appel de fonction doit avoir une liste de paramètres réels si la déclaration de fonction correspondante contient une liste de paramètres formels.
Voici quelques exemples d'appels de fonction :
Dans le mode de syntaxe étendue {$X+}, les appels de fonction peuvent être utilisés comme des instructions ; c'est-à-dire que le résultat d'un appel de fonction peut être ignoré.
Les constructeurs d'ensemble
Un constructeur d'ensemble désigne une valeur de type ensemble et est formé en écrivant des expressions entre crochets ([]). Chaque expression désigne une valeur de l'ensemble.
La notation [ ] désigne l'ensemble vide, étant compatible avec l'affectation avec chaque type d'ensemble. Tout groupe de membres X..Y désigne comme membres de l'ensemble toutes les valeurs de l'intervalle X..Y. Si X est supérieur à Y, alors X..Y ne désigne aucun membre et [X..Y] désigne l'ensemble vide. Toutes les valeurs d'expression dans les groupes membres d'un constructeur d'ensemble particulier doivent être du même type ordinal. Voici quelques exemples de constructeurs d'ensembles :
Castre de valeur
Le type d'une expression peut être changé en un autre type via un castre (transtypage) de valeur.
Le type d'expression et le type spécifié doivent tous deux être des types ordinaux ou des types pointeurs. Pour les types ordinaux, la valeur résultante est obtenue en convertissant l'expression. La conversion peut impliquer une troncature ou une extension de la valeur d'origine si la taille du type spécifié est différente de celle de l'expression. Dans les cas où la valeur est étendue, le signe de la valeur est toujours conservé ; c'est-à-dire que la valeur est étendue par le signe.
La syntaxe d'un castre de valeur est presque identique à celle d'un castre de variable. Les castres de valeurs opèrent sur des valeurs, mais pas sur des variables, et par conséquent, ils ne peuvent pas participer aux références de variables ; c'est-à-dire qu'un castre de valeur ne peut pas être suivi de qualificateurs. En particulier, les castres de valeur ne peuvent pas apparaître sur le côté gauche d'une instruction d'affectation.
Voici quelques exemples de castre (transtypages) de valeurs :
Types procéduraux dans les expressions
Généralement, l'utilisation d'une variable procédurale dans une instruction ou une expression appelle la procédure ou la fonction entreposée dans la variable. Il y a une exception : lorsque le compilateur voit une variable procédurale sur le côté gauche d'une instruction d'affectation, il sait que le côté droit doit représenter une valeur procédurale. Par exemple, considérons le programme suivant :
La première instruction dans le programme principal affecte la valeur procédurale (adresse de) ReadInt à la variable procédurale F, où la deuxième instruction appelle ReadInt et affecte la valeur renvoyée à N. La distinction entre obtenir la valeur procédurale ou appeler la fonction est faite par le type de la variable affectée (F ou N). Malheureusement, il existe des situations où le compilateur ne peut pas déterminer l'action souhaitée à partir du contexte. Par exemple, dans l'instruction suivante, il n'y a aucun moyen évident pour le compilateur de savoir s'il doit comparer la valeur procédurale de F à la valeur procédurale de ReadInt pour déterminer si F pointe actuellement vers ReadInt, ou s'il doit appeler F et ReadInt, puis comparer les valeurs renvoyées.
La syntaxe Pascal standard, cependant, spécifie que l'occurrence d'un identificateur de fonction dans une expression dénote un appel à cette fonction, donc l'effet de l'instruction précédente est d'appeler F et ReadInt, puis de comparer les valeurs renvoyées. Pour comparer la valeur procédurale de F à la valeur procédurale de ReadInt, la construction suivante doit être utilisée :
Lorsqu'il est appliqué à une variable procédurale ou à un identifiant de procédure ou de fonction, l'opérateur d'adresse (@) empêche le compilateur d'appeler la procédure et convertit en même temps le paramètre en un pointeur. @F convertit F en une variable pointeur non typée contenant une adresse, et @ReadInt renvoie l'adresse de ReadInt ; les deux valeurs de pointeur peuvent ensuite être comparées pour déterminer si F se réfère actuellement à ReadInt. L'opérateur @ est souvent utilisé lors de l'affectation d'une valeur de pointeur non typée à une variable procédurale. Voici un exemple :
Pour obtenir l'adresse mémoire d'une variable procédurale plutôt que l'adresse y étant entreposée, utilisez un opérateur double adresse (@@). Par exemple, où @P signifie convertir P en une variable pointeur non typée, @@P signifie retourner l'adresse physique de la variable P.