4D v13.4Utilisation des directives de compilation |
|||||||||||||||||||||||
|
4D v13.4
Utilisation des directives de compilation
|
Booléen |
Alphanumérique (ou Chaîne fixe) |
Date |
Entier |
Entier long |
Graphe |
Heure |
Image |
Numérique (ou Réel) |
Pointeur |
Texte |
BLOB |
Pour les variables de type Tableau, vous disposez des 9 types suivants :
Tableau Booléen |
Tableau Alpha (ou Chaîne fixe) |
Tableau Date |
Tableau Entier |
Tableau Entier long |
Tableau Image |
Tableau Numérique (ou Réel) |
Tableau Pointeur |
Tableau Texte |
Note : A compter de la version 11 de 4D, il n'existe plus de différence entre les types de variables Alpha et Texte. Il est conseillé d'utiliser désormais le type Texte.
Lorsque vous travaillez avec 4D en mode interprété, une variable peut avoir plusieurs types. Cette tolérance se justifie parfaitement puisque vous êtes en mode interprété. En effet, à chaque ligne de code, 4D interprète l’instruction et comprend le contexte.
Lorsque vous travaillez en mode compilé, vous êtes dans une situation différente. Alors que l’interprétation agit ligne par ligne, la compilation s’intéresse à une base dans sa globalité.
La manière d’opérer du compilateur est la suivante :
Si le compilateur trouve un même nom de variable avec deux types différents, il n’a aucune raison de privilégier l’un par rapport à l’autre. En d’autres termes, avant de pouvoir ranger un objet, de lui donner une adresse mémoire, le compilateur a besoin de connaître l’identité exacte de cet objet, c’est-à-dire son nom et son type, le type permettant au compilateur de déduire sa taille. Ainsi, pour chaque application compilée, le compilateur crée un plan, contenant, pour chaque variable, son nom (ou identificateur), son emplacement (ou adresse mémoire) et la taille qu’elle occupe (représentée par son type). Ce “plan” s’appelle la table de symboles. Une option des Préférences vous permet de générer ou non cette table sous forme de fichier lors de la compilation.
Ce plan est également utilisé pour la génération automatique des méthodes compilateur.
Si vous voulez que le compilateur vérifie votre typage ou bien s’en charge lui-même, placer une directive de compilation est simple. Vous avez le choix entre deux possibilités, qui correspondent d’ailleurs à deux méthodes de travail :
Les directives de compilation sont utiles dans deux cas :
Par ailleurs, utiliser des directives de compilation peut vous permettre de réduire le temps de compilation.
Il arrive que le compilateur ne puisse pas déduire le type d’une variable, et cela pour plusieurs raisons. Il est impossible de recenser tous les cas de figure. Une chose est certaine, c’est qu’en cas d’impossibilité à compiler, le compilateur vous en donnera la raison précise ainsi que les moyens d’y remédier.
On peut cependant distinguer trois causes majeures d’hésitation pour le compilateur : l’ambiguïté proprement dite, l’ambiguïté sur une déduction forcée, et l’impossibilité totale de déduire un type.
L’ambiguïté proprement dite
L’ambiguïté sur le nom de la variable est généré dans le cas suivant : le compilateur choisit la première variable qu’il rencontre et assigne arbitrairement à la suivante, de même nom mais de type différent, le type qu’il a précédemment attribué. Prenons un exemple simple :
dans une méthode A,
LaVariable:=Vrai
LaVariable:="La lune est verte"
Dans le cas où la méthode A est compilée avant la méthode B, le compilateur considérera que LaVariable:="La lune est verte" est un changement de type d’une variable précédemment rencontrée. Il vous signalera qu’il y a retypage. Il génère une erreur qu’il vous appartient de corriger.
Ne vous inquiétez pas, le compilateur ne transformera pas votre variable LaVariable:="La lune est verte" en variable booléenne sans vous demander ce que vous en pensez !
L’ambiguïté sur une déduction forcéeDans le cas simple où l’objet n’est pas utilisé dans une méthode, le compilateur peut déduire son type sans ambiguïté et l’objet sera typé en tableau texte par défaut. En revanche, dans le cas où vous devez initialiser la position de votre tableau pour son affichage dans le formulaire, vous pouvez écrire les instructions suivantes dans la méthode formulaire :
Au cas ou
:(Evenement formulaire=Sur chargement)
MonPopUp:=2
...
Fin de cas
C’est dans ce cas que l’ambiguïté apparaît : lors de l’analyse des méthodes, le compilateur déduira par défaut le type Réel pour la variable MonPopUp. Dans ce cas très précis, vous devez explicitement déclarer le tableau dans une méthode compilateur ou dans la méthode formulaire :
Au cas ou
:(Evenement formulaire=Sur chargement)
TABLEAU TEXTE(MonPopUp;2)
MonPopUp:=2
...
Fin de cas
L’impossibilité totale de déduire un type
Dans ce cas, seule une directive de compilation peut orienter le compilateur. Le compilateur peut se trouver dans cette situation lorsqu’une variable est utilisée sans être déclarée et dans un cadre qui ne donne aucune information sur son type possible.
Le phénomène se produit principalement dans quatre cas :
Cas des pointeurs
Un pointeur étant un outil universel qui a donc pour première caractéristique la flexibilité, il est inutile d’espérer qu’il renvoie un type d’une manière ou d’une autre, hormis le sien propre.
Supposons que vous écriviez dans une méthode la séquence suivante :
LaVar1:=5,2(1)
LePointeur:=->LaVar1(2)
LaVar2:=LePointeur->(3)
Bien que la ligne (2) définisse le type de la variable pointée par le pointeur LePointeur, LaVar2 n’est pas pour autant typée. Lors de la compilation, le compilateur peut reconnaître un pointeur, mais n’a aucun moyen de savoir sur quel type de variable il pointe. Il ne peut donc pas déduire le type de LaVar2 ; une directive de compilation du type C_REEL(LaVar2) est donc indispensable.
Cas des commandes à syntaxe multiple
Lorsque vous utilisez une variable associée à la fonction Annee de, la variable ne peut être, compte tenu de la nature même de la fonction, que de type Date. En revanche, prenons un cas extrême : la commande LIRE PROPRIETES CHAMP admet deux syntaxes :
LIRE PROPRIETES CHAMP(NoTable;NoChamp;Type;Longueur;Indexée)
LIRE PROPRIETES CHAMP(Pointeur_Champ;Type;Longueur;Indexée)
Lorsque vous utilisez cette commande, le compilateur ne peut pas deviner quelle syntaxe et quels paramètres vous avez choisis. Il vous appartient alors d’orienter le compilateur par une directive de compilation.
Cas des commandes 4D ayant des paramètres optionnels de types différents
Lorsque vous utilisez une commande 4D qui accepte plusieurs paramètres optionnels de différents types, le compilateur ne peut pas deviner quels paramètres ont été passés.
Par exemple, la commande INFORMATION ELEMENT admet deux paramètres optionnels. Le premier est de type Entier long, le second est de type Booléen.
La commande peut donc être utilisée comme ceci :
INFORMATION ELEMENT(liste;position;num;texte;sous-liste;déployé)
ou comme cela :
INFORMATION ELEMENT(liste;position;num;texte;déployé)
Vous devez donc utiliser des directives de compilation pour typer les paramètres optionnels passés à la commande (s’ils n’ont pas déjà été typés suite à leur utilisation dans un autre endroit de la base).
Cas des méthodes appelées via un URL
Si vous écrivez des méthodes appelées via un URL, il est nécessaire de déclarer explicitement la variable Texte $1 dans vos méthodes, par l’intermédiaire de l’instruction C_TEXTE($1), dans le cas où vous n’utilisez pas $1 dans la méthode. En effet, le compilateur ne peut pas deviner qu’une méthode 4D va être appelée via un URL.
Si toutes les variables utilisées dans votre base sont explicitement déclarées, il n’est pas nécessaire que le compilateur refasse tout le typage. Dans ce cas, vous pouvez lui demander d’effectuer uniquement la phase de traduction de vos méthodes dans le chemin de compilation. Ainsi, vous économiserez environ 50 % du temps de compilation.
Les directives de compilation peuvent vous aider à accélérer vos méthodes. Pour plus de précision à ce sujet, reportez-vous à la section Conseils d’optimisation. Pour nous en tenir à un exemple simple dans cette section de présentation, imaginez que vous incrémentiez un compteur. Si vous n’avez pas déclaré la variable, le compilateur considérera par défaut qu’elle est de type Numérique (ou réel). Si vous prenez soin de préciser qu’il s’agit d’un Entier, l’exécution de la base compilée sera plus satisfaisante. En effet, un Réel occupe, sur PC par exemple, 8 octets en mémoire alors que si vous choisissez un type limitatif, Entier ou Entier long, le compteur n’en occupera que 4. Il est bien évident que l’incrémentation d’un compteur de 8 octets est plus longue que celle d’un compteur de 4 octets.
Vous avez deux possibilités selon que vous voulez que le compilateur vérifie ou non votre typage.
4D utilise trois catégories de variables :
Pour plus d'informations sur ce point, reportez-vous à la section Variables. Les variables process et les variables interprocess sont structurellement de même nature pour le compilateur.
Si vous voulez que le compilateur n’ait pas à vérifier votre typage, vous devez lui donner les clés de l’identification de ses objets.
La convention à respecter est la suivante : les directives de compilation des variables process ou interprocess, ainsi que les paramètres, devront être placées dans une ou plusieurs méthodes dont le nom commence par Compiler.
Par défaut, le compilateur vous permet de générer automatiquement cinq types de méthodes Compilateur regroupant les directives pour les variables, les tableaux et les paramètres des méthodes (pour plus d'informations sur ce point, reportez-vous au manuel Mode Développement).
Note : La déclaration des paramètres des méthodes obéit à la syntaxe suivante : Directive (nom de méthode; param). Cette syntaxe n’est pas exécutable en mode interprété.
Paramètres particuliers
C_ENTIER LONG($0)
Si(Evenement formulaire=Sur glisser)
$0:=0
...
Si($TypeDeDonnées=Est une image)
$0:=-1
Fin de si
...
Fin de si
La syntaxe de toutes les directives de compilation est extrêmement simple ; seule la commande C_ALPHA requiert une attention particulière puisqu’elle admet un paramètre supplémentaire : la longueur maximale de la chaîne.
C_ALPHA(Longueur;Var1{;Var2;…;VarN})
Par définition, C_ALPHA porte sur des chaînes fixes, il est donc naturel de donner la longueur de cette chaîne. A cet égard, il convient de rappeler une différence de comportement entre une base interprétée et une base compilée.
Dans une base interprétée, la séquence suivante :
LaLongueur:=15
C_ALPHA(LaLongueur;LaChaine)
serait parfaitement logique. 4D interpréterait LaLongueur puis remplacerait LaLongueur par sa valeur dans la directive.
En revanche, le compilateur utilise cette commande durant le typage des variables et en dehors de toute affectation particulière. Il ne peut donc pas savoir que LaLongueur est égale à 15. Ne connaissant pas la longueur de la chaîne, il ne peut pas lui réserver de place dans la table des symboles. Par conséquent, dans l’optique d’une compilation, il convient d’utiliser une constante pour spécifier la longueur de la chaîne de caractères déclarée. Cette déclaration se fera donc de la façon suivante :
C_ALPHA(15;LaChaine)
Il en va de même pour la déclaration de tableaux d’alphas par la commande :
TABLEAU ALPHA(LaLongueur;LeTableau;Nombre déléments)
Le paramètre indiquant la longueur des chaînes du tableau sera une constante.
En revanche, vous pouvez utiliser les constantes 4D ou des valeurs hexadécimales pour spécifier la longueur des chaînes dans ces deux directives de compilation. Exemple :
C_ALPHA(Constante4D;LaChaîne)
TABLEAU ALPHA(Constante4D;LeTableau;2)
C_ALPHA(0x000A;LaChaîne)
TABLEAU ALPHA(0x000A;LeTableau;2)
Ne confondez pas la longueur d’un champ Alphanumérique qui peut être au maximum de 80 caractères avec une variable Alphanumérique. La longueur d’une chaîne déclarée par la directive C_ALPHA ou appartenant à un TABLEAU ALPHA peut être comprise entre 1 et 255.
Note : La syntaxe de cette commande vous permet de déclarer plusieurs variables de même longueur en une seule ligne. Si vous souhaitez déclarer plusieurs chaînes fixes de longueur différente, il faudra le faire en plusieurs lignes.
Les directives de compilation lèvent toute ambiguïté sur les types. L’exigence de rigueur ne se fait pas pour autant intolérance.
S’il vous arrive d’utiliser un réel là où vous avez déclaré un entier, le compilateur ne considère pas qu’il y a conflit et suit simplement vos directives. Ainsi, si vous écrivez :
C_ENTIER(vEntier)
vEntier:=2,6
Le compilateur ne verra pas un conflit de types de nature à empêcher la compilation et prendra automatiquement en compte la partie entière arrondie du nombre affecté (3 au lieu de 2,6).
Produit : 4D
Thème : Compilateur
Nom intl. : Using Compiler Directives
Conseils d’optimisation
Guide du typage
Messages d'erreurs
Précisions de syntaxe