Lorsqu'on utilise des procédures, on ne peut pas savoir si un ON_ERROR_GOTO est en vigueur, et si oui, vers quel label. Or, on peut être conduit à gérer des erreurs dans une procédure, sans perturber la gestion des erreurs du module principal, et ceci devient encore plus complexe qi une procédure en appelle une autre, etc.
C'est pourquoi je propose 3 solutions à ce problème.
1ère proposition:Elle est de loin la plus élégante et la plus performante. Je propose une nouvelle commande LABEL_LOCAL sur le modèle de DIM_LOCAL. Tout comme une variable locale, un label local ne serait connu que dans le cadre d'une procédure. Et une gommande ON_ERROR_GOTO_LOCAL n'utiliserait que les labels locaux. On aurait donc:
LABEL_LOCAL N : ' définit un label N localement dans la procédure
ON_ERROR_GOTO_LOCAL N : ' active le label local N comme cible en cas d'erreur
OFF_ERROR_GOTO_LOCAL : ' désactive le ON_ERROR_GOTO_LOCAL
En cas d'erreur, on procède ainsi:
si un ON_ERROR_GOTO_LOCAL est actif, alors on y va
si un ON_ERROR_GOTO est actif, alors on y va
sinon, message d'erreur de Panoramic
Comme une procédure peut en appeler une autre avec à nouveau son propre traitement d'erreur, il faut bien sûr gérer ces labels d'erreur par une pile des labels qui se remplit à l'entrée dans une procédure et qui se vide par EXIT_SUB et END_SUB.
2ème solution:Je propose la création d'une "pile" de labels pour ON_ERROR_GOTO, cachée à l'intérieur de Panoramic, et manipulable par les nouvelles commandes suivantes:
PUSH_ERROR_GOTO : ' ajouter le label ON_ERROR_GOTO actuel sur la pile
P
OP_ERROR_GOTO : ' remplacer le label ON_ERROR_GOTO actuel par le haut de la pile
On pourrait ainsi écrire:
- Code:
-
label erreur_programme_principal
on_error_goto erreur_programme_principal
...
traitement()
...
erreur_programme_principal:
' ici, on ne traite que les erreurs du programme principal
...
end
sub traitement()
if label("erreur_traitement")=0 then label erreur_traitement
push_error_goto
on_error_goto erreur_traitement
...
pop_error_goto
exit_sub
erreur_traitement:
' ici, on ne traite que les erreurs de la procédure traitement()
...
pop_error_goto
end_sub
3ème proposition:cette proposition vise à utiliser une DLIST tout à fait banale pour mémoriser les labels des ON_ERROR_GOTO et de gérer ainsi soi-même cette fameuse pile. Pour cela, i faut une nouvelle variable système et une nouvelle commande:
nom$ =
GET_ERROR_GOTO$ : ' cette variable système contient le nom du label ON_ERROR_GOTO actuel
SET_ERROR_GOTO nom$ : ' comme ON_ERROR_GOTO, mais avec le label dans une variable string.
L'exemple ci-dessus deviendrait alors:
- Code:
-
label erreur_programme_principal
dim pile% : pile% = 17
dlist pile%
on_error_goto erreur_programme_principal
...
traitement()
...
erreur_programme_principal:
' ici, on ne traite que les erreurs du programme principal
...
end
sub traitement()
if label("erreur_traitement")=0 then label erreur_traitement
item_add pile%,get_error_goto$
on_error_goto erreur_traitement
...
set_error_goto item_read$(pile%,count(pile%))
item_delete pile%,count(pile%)
exit_sub
erreur_traitement:
' ici, on ne traite que les erreurs de la procédure traitement()
...
set_error_goto item_read$(pile%,count(pile%))
item_delete pile%,count(pile%)
end_sub