Aperçu technique
Comment fonctionne Loreline sous le capot ? Cet article donne quelques éléments de réponse, bien que tout ne puisse pas être décortiqué en détail ici !
Un langage à la croisée de deux disciplines
Construire un langage de script narratif demande de réunir deux compétences très différentes.
D'un côté, il faut travailler l'ergonomie du langage narratif : la syntaxe doit paraître naturelle aux autrices et auteurs, laisser la place à la créativité, et proposer les bonnes mécaniques pour exprimer une intention narrative (embranchements, variations, personnages, état) de manière lisible et intuitive.
De l'autre, chaque simplification, chaque choix de conception du langage, demande un vrai effort d'ingénierie logicielle : moins on a besoin d'écrire de symboles, plus le parseur doit être capable de comprendre l'intention derrière ce qui est écrit. Et tout cela doit fonctionner de manière identique sur un large éventail de plateformes et de moteurs de jeu, tout en offrant des outils d'édition (coloration syntaxique, suggestions automatiques, diagnostics en temps réel) qui accompagnent l'écriture.
Loreline reflète cette double nature à chaque niveau. Le langage paraît simple en surface parce que l'implémentation sous-jacente absorbe la complexité à la place de celles et ceux qui écrivent.
Écrit en Haxe, to transpile them all
L'essentiel de Loreline est écrit en Haxe, un langage de programmation à typage strict qui transpile vers de nombreuses cibles à partir d'un seul code source.
Le principe de la transpilation, c'est de convertir le code depuis un langage vers un autre. Haxe est spécialisé dans ce type d'opération : on peut transpiler du Haxe vers plein d'autres langages, rendant le code qu'on écrit très portable.
Ce choix découle d'une exigence fondamentale : Loreline doit fonctionner partout. Les moteurs de jeu utilisent C#, C++, GDScript, Java ou encore Lua. Les projets web utilisent JavaScript et TypeScript. Les scripts d'outillage peuvent aussi utiliser du Python. Plutôt que de maintenir des implémentations séparées qui finiraient inévitablement par diverger et nécessiteraient un énorme travail de maintenance, Haxe permet d'écrire l'intégralité de l'interpréteur, du parseur et du runtime une seule fois, puis de transpiler et compiler nativement pour chaque plateforme.
Le résultat : un seul jeu de tests, un seul parseur, un seul interpréteur, qui produisent du code spécifique à chaque cible avec des performances natives.
Pipeline de traitement
Pour être capable de jouer une histoire interactive, Loreline prend un texte source en entrée et le transforme sur plusieurs étapes afin de l'exécuter :
Lexer : Transforme le texte source en tokens. L'une de ses tâches les plus complexes est de déterminer si une ligne constitue du texte narratif ou une instruction du langage : c'est ce qui permet d'écrire du dialogue sans délimiteurs explicites.
Parseur : Analyse le flux de tokens et produit un AST (Abstract Syntax Tree, ou arbre syntaxique) représentant la structure complète du script : beats, dialogues, choix, alternatives, conditions, expressions, etc. Chaque nœud reçoit un identifiant unique de 64 bits encodant sa position dans la hiérarchie, conçu pour rester stable quand le script est modifié : une sauvegarde basée sur une version précédente reste valide même si des répliques sont ajoutées ou supprimées.
Interpréteur : Parcourt l'AST à l'exécution et appelle des callbacks lorsqu'un dialogue ou des choix doivent être présentés. L'application hôte fournit ces callbacks et contrôle la reprise de l'exécution.
Avec Loreline, il n'y a pas besoin de « pré-compiler » les scripts
.lordans un format intermédiaire. Le runtime est capable de directement lire, parser et exécuter un script au format texte. C'est un choix délibéré, qui simplifie l'intégration et ouvre la porte à des usages plus variés. Le Lexer est particulièrement optimisé pour être performant, le rendant tout à fait viable pour charger de nombreux fichiers à la volée.
Modèle d'exécution
Quand l'interpréteur atteint une ligne de dialogue ou un point de choix, il se met en pause et laisse l'application hôte (jeu, application web, outil) décider quand reprendre. Ce modèle en continuation-passing style (CPS) fonctionne aussi bien en synchrone qu'en asynchrone, et s'intègre naturellement dans n'importe quelle boucle de jeu ou système d'événements.
En interne, une pile de portées d'exécution garde la trace de la position dans le script, des variables actives et des beats imbriqués. C'est cette pile qui rend possible la sauvegarde et la restauration précises de l'état à n'importe quel moment.
Cibles de compilation
Loreline couvre un large éventail de langages et de plateformes, grâce à une base de code commune qui garantit le même comportement partout.
Une fine surcouche vient se greffer au code transpilé avec Haxe, pour que Loreline, en tant que bibliothèque, s'utilise naturellement sur chaque langage cible. Une personne qui utilise la version C# ou la version Java de Loreline n'a aucunement besoin de savoir utiliser Haxe. L'utilisation via Godot se fait simplement avec du GDScript, etc.
Cette architecture logicielle permet de modifier le langage (pour corriger un bug, apporter une amélioration...) simplement en modifiant le code source écrit en Haxe, et déployer cette modification sur l'ensemble des cibles, par défaut et de manière automatisée : c'est un gain de temps considérable pour la maintenance de Loreline dans la durée !
Des tests automatisés par centaines
Pour s'assurer de la robustesse du langage et éviter toute régression lorsqu'il est modifié, plusieurs centaines de tests sont exécutés, pour chaque langage cible (JS, Java, C#, C++, ...), afin de couvrir l'ensemble des fonctionnalités : alternatives, beats, personnages, choix, dialogues, expressions, fonctions, conditions, imports, insertions, localisation, sauvegarde/restauration, gestion d'état, syntaxe, balises et comptage de visites.
Ces tests sont cruciaux pour vérifier que le langage se comporte correctement, et construire sereinement son outillage et sa narration avec Loreline.
Creuser le sujet
Pour en apprendre plus sur la manière dont Loreline fonctionne, vous pouvez aussi explorer son code source sur Github.