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 :

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");