Instruction RPG full free · IBM i (AS/400) · Données et calculs
EVAL
Affecter le résultat d'une expression
Calcule une expression et range le résultat dans une zone, une sous-zone ou un élément de tableau ; en full free, le mot EVAL est facultatif.
Syntaxe
zone = expression;
EVAL zone = expression;
EVAL(H) zone = expression;
EVALR zone = expression;
zone += expression; (aussi -= *= /=)
zone- La cible : une variable, une sous-zone de structure, un élément de tableau… Elle reçoit le résultat, converti à son type et à sa longueur.
expression- Un calcul (
+ - * / **), une concaténation de chaînes avec+, un appel de fonction intégrée ou de procédure, une comparaison. (H)- Extension d'opération : arrondit le résultat au lieu de le tronquer, pour une cible numérique.
EVALR- Variante pour les chaînes : le résultat est cadré à droite dans la cible. Si la cible est trop courte, on perd le début et non la fin.
+= -= *= /=- Opérateurs d'affectation abrégés :
total += ht;équivaut àtotal = total + ht;. Pour une chaîne,+=ajoute à la fin. - Effet
- Modifie la zone cible, rien d'autre : ni %FOUND ni indicateur. Si le résultat est trop grand pour une cible numérique, le programme lève MCH1210 (que MONITOR peut intercepter) ou, sans surveillance, le message d'interrogation RNQ0103. Une chaîne trop longue, elle, est tronquée sans erreur.
À quoi ça sert
C'est l'instruction de base de tout programme : presque chaque ligne de calcul est une affectation. En full free, on écrit simplement ttc = ht * 1.2; ; le mot EVAL n'est utile que pour porter une extension, EVAL(H) ou EVALR.
Elle remplace d'un coup les opérations en colonnes ADD, SUB, MULT, DIV, MOVE, MOVEL, Z-ADD : un seul modèle pour le calcul et la conversion de type. Les opérateurs abrégés comme += évitent de répéter le nom de la zone et rendent les cumuls plus lisibles.
Exemple 1 : Calculs, += et EVALR
**free
// EVAL : affectation, operateurs, += et EVALR.
ctl-opt dftactgrp(*no) actgrp(*new);
dcl-s ht packed(9:2) inz(1250.50);
dcl-s ttc packed(9:2);
dcl-s total packed(9:2) inz(100);
dcl-s qte int(10) inz(7);
dcl-s reste int(10);
dcl-s puiss int(10);
dcl-s ville char(12);
dcl-s libelle varchar(40);
ttc = ht * 1.2; // eval est facultatif
eval reste = %rem(qte : 3);
total += ht; // total = total + ht
total -= 50;
snd-msg 'TTC : [' + %char(ttc) + ']';
snd-msg 'Reste : [' + %char(reste) + ']';
snd-msg 'Total : [' + %char(total) + ']';
puiss = 2 ** 10;
snd-msg 'Puiss. : [' + %char(puiss) + ']';
ville = 'Lyon';
snd-msg 'Eval : [' + ville + ']';
evalr ville = 'Lyon'; // cadre a droite
snd-msg 'Evalr : [' + ville + ']';
libelle = 'Client ' + 'Dupont SA';
libelle += ' - Montpellier';
snd-msg libelle;
*inlr = *on;
Résultat réel, compilé et exécuté sur IBM i 7.5 :
TTC : [1500.60]
Reste : [1]
Total : [1300.50]
Puiss. : [1024]
Eval : [Lyon ]
Evalr : [ Lyon]
Client Dupont SA - Montpellier
Le calcul du TTC, le reste d'une division avec %rem et la puissance 2 ** 10 sont des affectations ordinaires. Le total est cumulé avec += puis diminué avec -=.
La même chaîne 'Lyon' donne Lyon avec EVAL (cadrée à gauche) et Lyon avec EVALR (cadrée à droite). Une zone de longueur variable accumule les morceaux avec +=.
Exemple 2 : Troncature, arrondi et dépassement
**free
// EVAL : troncature silencieuse, arrondi (H) et depassement numerique.
ctl-opt dftactgrp(*no) actgrp(*new);
dcl-s nom char(8);
dcl-s court char(8);
dcl-s prix packed(7:2) inz(20.00);
dcl-s arr packed(7:1);
dcl-s trop packed(3:0);
dcl-s grand packed(5:0) inz(99999);
nom = 'Bernard Transports';
snd-msg 'Tronque : [' + nom + ']';
evalr court = 'Bernard Transports';
snd-msg 'Evalr : [' + court + ']';
arr = prix / 3;
snd-msg 'Sans H : [' + %char(arr) + ']';
eval(h) arr = prix / 3;
snd-msg 'Avec H : [' + %char(arr) + ']';
monitor;
trop = grand + 1;
snd-msg 'Trop : [' + %char(trop) + ']';
on-error;
snd-msg 'Depassement signale';
endmon;
trop = grand;
snd-msg 'Non atteint';
*inlr = *on;
Résultat réel, compilé et exécuté sur IBM i 7.5 :
Tronque : [Bernard ]
Evalr : [ansports]
Sans H : [6.6]
Avec H : [6.7]
Depassement signale
Erreur : RNQ0103 - (C G D F) Cible pour opération numérique trop petite pour contenir résultat.
Avec une cible char(8), EVAL garde le début de Bernard Transports (Bernard ) et EVALR la fin (ansports) : dans les deux cas, aucune erreur.
20 divisé par 3 donne 6,666… ; la cible a une décimale. Sans (H), le résultat est tronqué à 6,6 ; avec EVAL(H), il est arrondi à 6,7.
Pour un nombre, c'est différent : 99999 + 1 ne tient pas dans un packed(3:0). Le premier essai est dans un bloc MONITOR qui l'intercepte. Le second, hors surveillance, arrête le programme sur RNQ0103.
Le piège
Une chaîne trop longue est coupée sans prévenir. nom = 'Bernard Transports'; dans une zone de 8 caractères range Bernard et le programme continue. Aucun message, aucun indicateur : il faut comparer les longueurs soi-même ou utiliser une zone de longueur variable. Avec EVALR, c'est le début qui disparaît (ansports).
Le calcul décimal est tronqué, jamais arrondi : 20 / 3 dans une zone à une décimale donne 6,6. Pensez à EVAL(H) pour obtenir 6,7. Et pour un nombre trop grand pour sa cible, la tolérance est nulle : MCH1210 si vous surveillez, RNQ0103 sinon.