Bytecode précompilé

Compiler un script (lexer → parseur → codegen) a un coût. Pour un script qui change rarement mais est chargé à chaque démarrage de l'application hôte, YScript permet de précompiler une fois en bytecode et de ne charger que ce bytecode au démarrage, en s'épargnant l'analyse du texte source.

Précompiler (Dump)

Dump sérialise la fonction actuellement au sommet de la pile (donc après un Load réussi, avant de l'appeler) vers un flux :

using YScript.Runtime;

using var engine = new ScriptEngine();
engine.OpenLibs();

if (engine.Load(File.ReadAllText("script.ys"), "script.ys") == ScriptStatus.Ok)
{
    using var output = File.Create("script.ysc");
    engine.Dump(output, strip: true);   // strip = true : sans les informations de débogage
    engine.Pop();                        // la fonction chargée reste sur la pile après Dump
}

strip: true omet les informations de débogage (noms de variables locales, correspondance ligne/adresse...) : fichier plus compact, mais des erreurs survenant dans ce bytecode ne pourront plus être rapportées avec un numéro de ligne précis. Gardez strip: false tant que vous voulez des messages d'erreur exploitables depuis le bytecode livré.

Charger du bytecode précompilé

Load/LoadFile acceptent aussi bien du texte source que du bytecode : le premier octet du flux détermine automatiquement lequel des deux est en train d'être lu (signature binaire reconnue via IScript.Signature). Aucune API séparée n'est nécessaire côté appelant :

using var input = File.OpenRead("script.ysc");
var status = engine.Load(input, "script.ysc", FileMode.Binary);

Le paramètre FileMode (Text/Binary/BinaryOrText, ce dernier étant la valeur par défaut) sert de garde-fou plutôt que de sélecteur de format : passer FileMode.Binary fait échouer le chargement si le flux contient en fait du texte (et inversement pour FileMode.Text), ce qui permet de refuser explicitement l'un des deux formats plutôt que de laisser la détection automatique tout accepter — utile si l'hôte ne veut charger que du bytecode de confiance et jamais compiler du texte arbitraire à cet endroit, par exemple.

Le bytecode n'étant pas portable entre versions incompatibles du moteur ni vérifié par un sandbox — au même titre que du bytecode Lua précompilé — ne chargez comme Binary que du contenu produit par une version compatible de YScript et dans lequel vous avez confiance.

Sources de lecture (YScript.IO)

Load a trois surcharges, une par type de source :

Surcharge Usage
Load(ITextReader, name) Source texte déjà en mémoire/flux caractère (toujours compilée, jamais interprétée comme bytecode)
Load(Stream, name, mode) Flux brut, texte ou binaire selon mode
Load(IFileReader, name, mode) Un IFileReader du moteur (voir IScriptHost.OpenReadFile), texte ou binaire

LoadFile/DoFile passent par IScriptHost.OpenReadFile (donc par l'hôte configuré — voir hote.md) plutôt que par System.IO directement, pour rester cohérents avec le reste de l'accès fichier orchestré par l'hôte.

Les implémentations du namespace YScript.IO (StreamFileReader, TextFileReader, TextBinaryFileReader, PreloadedFileReader, ...) sont surtout des détails internes utilisés par le moteur et les hôtes fournis (DefaultHost/ConsoleHost) pour adapter un Stream/TextReader .NET à IFileReader/ITextReader ; un hôte personnalisé n'a normalement pas besoin d'en écrire de nouvelles, seulement d'implémenter IScriptHost.OpenReadFile/OpenFile en s'appuyant sur celles existantes (voir l'implémentation de DefaultHost comme référence).