Différences avec Lua

YScript suit d'assez près la syntaxe et la sémantique de Lua (5.3/5.4), mais ce n'est pas une implémentation de Lua : quelques comportements observés dans le moteur diffèrent de Lua standard. Cette page les rassemble ; chacun est aussi mentionné dans la page thématique correspondante.

0 et 0.0 sont des valeurs fausses

En Lua, seuls nil et false sont des valeurs fausses — tout le reste, y compris 0, est vrai. En YScript, l'entier 0 et le flottant 0.0 sont également traités comme faux par if, while, repeat...until, and, or et not :

if 0 then print("vrai") else print("faux") end   --> faux en YScript, "vrai" en Lua standard

Choix délibéré, pas un oubli : contrairement à Lua, YScript aligne ici sa notion de valeur fausse sur la convention la plus répandue dans les langages généralistes (C, C++, JavaScript, Python, PHP, ...), où 0/0.0 sont également faux.

Voir Types et valeurs.

// entre deux entiers utilise la troncature .NET, pas l'arrondi vers -∞

/ produit toujours un flottant, même entre deux entiers (7 / 2 vaut 3.5), comme en Lua 5.3+ — YScript dispose d'un opérateur dédié à la division entière (//), donc / n'a pas besoin de doubler comme division entière et suit ici exactement la sémantique Lua. // (division entière explicite), en revanche, utilise la division entière .NET (troncature vers zéro) plutôt qu'un arrondi vers -∞ comme en Lua : le résultat peut différer pour des opérandes de signes opposés (-7 // 2 vaut -3 en YScript, -4 en Lua).

Voir Expressions.

% entre deux entiers suit le signe du dividende

En Lua, % est défini comme a - floor(a/b)*b : le résultat a toujours le signe de b (-5 % 3 vaut 1 en Lua). En YScript, % entre deux entiers utilise l'opérateur modulo natif, dont le résultat a le signe de a (-5 % 3 vaut -2). Le comportement entre deux flottants suit la même logique.

Choix délibéré, pas un oubli : YScript suit ici le comportement natif .NET (%, signe du dividende), jugé plus standard que celui de Lua parmi les langages généralistes.

Échappements \x/\u : longueurs différentes de Lua

YScript accepte \xHH et \uHHHH (majuscule ou minuscule) sans accolades obligatoires, avec jusqu'à 4 chiffres hexadécimaux — l'échappement produit directement une unité de code UTF-16, pas un octet brut comme le \xXX de Lua (chaîne = tableau d'octets en Lua, texte Unicode natif en YScript). La forme avec accolades \x{H...}/\u{H...} (nombre variable de chiffres hexadécimaux, comme le \u{XXX} de Lua) est également acceptée pour les deux, et accepte tout point de code Unicode valide (jusqu'à U+10FFFF), encodé en paire de substitution UTF-16 au-delà de U+FFFF. Les échappements décimaux (\ddd) acceptent jusqu'à 5 chiffres (au lieu de 3 en Lua), et l'échappement octal (\0ooo) n'est disponible qu'en préfixant par 0, avec jusqu'à 6 chiffres octaux.

Choix délibéré, pas un oubli : ces longueurs sont adaptées pour couvrir n'importe quelle unité de code UTF-16 (jusqu'à 65535) directement via ces échappements courts, plutôt que de se limiter à un octet (0-255) comme en Lua.

Voir Types et valeurs.

self est une pseudo-variable dynamique, pas seulement un nom de paramètre

En Lua standard, self n'a strictement rien de spécial : function t:m(a) ... end n'est qu'un sucre syntaxique qui ajoute self en tête de la liste de paramètres au moment de la déclaration — une fois compilée, la fonction ne se distingue en rien d'une fonction ordinaire portant un paramètre nommé self. Référencer self dans une fonction qui ne l'a pas déclaré comme paramètre (qu'elle ait été définie avec : ou non) est un lookup global ordinaire, toujours nil sauf si une variable globale self existe par ailleurs — la façon dont la fonction est appelée (obj:f(...) ou obj.f(obj, ...)) n'y change rien.

YScript va plus loin : self, quand ce n'est ni un paramètre déclaré ni une variable locale/upvalue du même nom, résout vers une valeur portée dynamiquement par la pile d'appel — définie par l'appel courant s'il s'agit d'un appel-méthode (obj:f(...)), sinon héritée du self de la fermeture englobante (une fonction imbriquée dans une méthode voit le self de cette méthode même sans être elle-même déclarée avec :). Concrètement, une fonction déclarée avec . (ou sans nom de table du tout) peut lire un self non-nil si elle est appelée via :, ce qui ne peut pas arriver en Lua standard.

Choix délibéré, pas un oubli : un des axes d'amélioration du langage par rapport à Lua visé dès le départ. Voir Fonctions pour le détail du mécanisme (deux règles de repli, ordre de priorité) et un exemple.

Pas de bibliothèque utf8

Lua expose une bibliothèque utf8 (utf8.char, utf8.codepoint, utf8.len, utf8.offset, utf8.codes, utf8.charpattern) parce que ses chaînes sont des tableaux d'octets bruts sans notion d'encodage : cet outillage est nécessaire pour interpréter un contenu UTF-8 stocké dans une chaîne Lua. Les chaînes YScript sont du texte .NET nativement Unicode (UTF-16) dès la lecture du source : il n'y a pas de distinction octet/caractère à combler par une bibliothèque dédiée. Ce choix est délibéré, pas une lacune — YScript ne prévoit pas d'ajouter de bibliothèque utf8 telle quelle.

Le besoin réel qui subsiste malgré tout (une unité UTF-16 n'est pas toujours un caractère complet — voir string) est couvert par un ajout ciblé à string plutôt qu'un portage de utf8.* : string.char accepte désormais un point de code complet au-delà du plan de base (encodé en paire de substitution), et string.ucodepoint/ string.ulen/string.uoffset/string.ucodes couvrent respectivement les rôles de utf8.codepoint/utf8.len/utf8.offset/utf8.codes, en positions UTF-16 plutôt qu'en octets. utf8.charpattern n'a pas d'équivalent, faute de sens : il n'y a pas de flux d'octets UTF-8 à matcher dans une chaîne déjà Unicode.