Erreurs et avertissements
ScriptStatus
La compilation (Load/LoadFile) et l'exécution protégée (PCall) renvoient un
YScript.ScriptStatus :
| Valeur | Signification |
|---|---|
Ok |
Succès |
Yield |
Le script s'est suspendu (coroutine) — pas une erreur |
ErrorSyntax |
Erreur de compilation (syntaxe invalide) |
ErrorRuntime |
Erreur levée pendant l'exécution du script |
ErrorFile |
Échec d'accès au fichier source (LoadFile/DoFile) |
ErrorDotnet |
Exception .NET non gérée remontée depuis du code hôte appelé par le script |
Destroyed |
Le moteur a été disposé |
Dans tous les cas d'erreur (Error*), le message d'erreur est poussé au sommet de la pile de
valeurs — c'est à l'appelant de le récupérer puis de le dépiler :
var status = engine.DoString(source, "mon-script");
if (status != ScriptStatus.Ok)
{
string message = engine.ToString(-1);
engine.Pop();
Console.Error.WriteLine(message);
}
Pour une trace d'appel complète plutôt qu'un simple message, utilisez TraceBack avant de dépiler
(c'est ce que fait l'interpréteur en ligne de commande pour afficher ses erreurs, voir
L'interpréteur) :
engine.TraceBack(engine, engine.ToString(-1), 1);
Console.Error.WriteLine(engine.ToString(-1));
engine.Pop(2);
Les types d'exception
Les échecs de compilation/exécution sont représentés par des sous-classes de
YScript.ScriptError, toutes porteuses d'un ErrorMessage :
SyntaxError— erreur de compilation ; expose en plusPosition(ligne/colonne) et la valeur d'erreur brute du script (Error, unScriptValue, pas juste unestring: un script peut lever n'importe quelle valeur, pas seulement du texte).RuntimeError— erreur levée pendant l'exécution (parerror()côté script, par une bibliothèque, ou par le moteur) ; expose de mêmeError(ScriptValue).FileError— échec d'ouverture/lecture d'un fichier source ; exposeFilename.
Ces types n'apparaissent en pratique côté hôte que si vous appelez l'API bas niveau directement
(Call non protégé, par exemple, propage l'exception .NET) ; PCall/DoString/DoFile les
capturent et les traduisent en ScriptStatus + valeur d'erreur sur la pile, ce qui est l'usage
recommandé pour exécuter du script venant d'une source non totalement fiable.
PCall : appel protégé
Exception error = engine.PCall(args, out int nResults, result: null, errorHandler: null);
if (error != null)
{
// engine.ToString(-1) contient le message d'erreur
engine.Pop();
}
PCall ne laisse jamais une exception traverser l'appelant : toute erreur (y compris une exception
.NET levée par une fonction hôte appelée depuis le script) est interceptée, transformée en valeur
d'erreur sur la pile, et retournée comme résultat de la méthode plutôt que levée. C'est la façon
d'exécuter du code script sans risquer de faire planter l'hôte sur une erreur de script.
errorHandler (optionnel) est l'index sur la pile d'une fonction de gestion d'erreur, appelée avec
la valeur d'erreur avant qu'elle ne soit renvoyée — utile pour enrichir le message (ex. ajouter une
trace d'appel) sans changer le flux de contrôle.
Avertissements (warn)
Le mécanisme d'avertissement (Context.WarningFunction, piloté par SetWarning) est distinct des
erreurs : un avertissement n'interrompt jamais l'exécution, c'est un canal d'information de bas
niveau écrit sur la sortie d'erreur de l'hôte.
ScriptEngine désactive les avertissements par défaut (SetWarning(WarnOff, this) dans
InitializeState) — un script qui appelle warn(...) ne produit rien tant que les avertissements ne
sont pas explicitement réactivés. Un script les active/désactive lui-même via les messages de
contrôle warn("@on")/warn("@off") :
warn("@on")
warn("ceci sera affiché sur la sortie d'erreur de l'hôte")
warn("@off")
Pour changer ce comportement par défaut, SetWarning accepte une fonction et une donnée utilisateur
arbitraires :
engine.SetWarning((userData, message, toContinue) =>
{
// toContinue: true si un autre appel à warn() suit pour compléter ce même message
Console.Error.WriteLine($"[warn] {message}");
}, engine);
Lever une erreur depuis une fonction hôte
Une fonction exposée au script (ExternalFunction) lève une erreur script en poussant la valeur
d'erreur puis en appelant Error(), ou via les méthodes d'aide ArgCheck/CheckXxx (qui font la
même chose pour les erreurs d'argument classiques) :
engine.Register(script =>
{
if (script.Top() < 1)
return script.Error("argument manquant"); // équivaut à PushString(...) puis Error()
...
}, "myFunc");