# 20. Opérateurs ## 20.1 Principe — V1 REQUIS — FIGÉ Les opérateurs utilisateur ne peuvent être fournis que via un ensemble fermé d'interfaces Core compiler-known préfixées `Op`. L'utilisateur ne peut pas inventer de nouveaux symboles opérateurs. Les contrats `operator` : - retournent directement leur valeur ; - ne retournent jamais `Result` ; - ne déclarent jamais `throws` ; - peuvent produire des `Fault` unchecked lorsque le contrat de l'opération le prévoit ; - peuvent documenter ces faults par une clause `faults`. Une opération dont la précondition est statiquement prouvée fausse est rejetée à la compilation lorsque la règle du langage permet cette preuve. Une violation seulement dynamique produit le `Fault` correspondant. ## 20.2 Interfaces arithmétiques — V1 REQUIS — FIGÉ ```text OpPositive OpNegate OpAdd OpSubtract OpMultiply OpDivide OpRemainder ``` Les opérations binaires peuvent être hétérogènes. Exemples légitimes : ```text Vector3 * float64 -> Vector3 Matrix * Vector3 -> Vector3 Timestamp + Duration -> Timestamp Timestamp - Timestamp -> Duration ``` L'ordre compte : `A op B` est distinct de `B op A`. ## 20.3 Interfaces bitwise — V1 REQUIS — FIGÉ ```text OpBitNot OpBitAnd OpBitOr OpBitXor OpShiftLeft OpShiftRight ``` Pour les primitives numériques, `& | ^` exigent les mêmes types primitifs exacts, sans promotion implicite. Les shifts primitifs utilisent initialement `uint32` comme type de count. Count hors largeur : ```text statique -> erreur compilation dynamique -> faute runtime ``` `>>` : ```text unsigned -> logical zero-fill signed -> arithmetic sign extension ``` Pas de `>>>`. ## 20.4 Logique booléenne — V1 REQUIS — FIGÉ Short-circuit : ```text !a a && b a || b ``` Eager : ```text a & b a | b a ^ b ``` `&&`, `||` et `!` ne sont pas surchargeables. `&`, `|`, `^` ont une sémantique intrinsèque eager pour `bool`, bitwise pour les primitives entières et peuvent utiliser les contrats `OpBit...` sur types utilisateur. Pas de NAND/NOR natifs. ## 20.5 Égalité — V1 REQUIS — FIGÉ ```text OpPartialEqual OpEqual Equatable ``` `OpEqual` renforce : ```text OpPartialEqual ``` et garantit contractuellement une relation d'équivalence : ```text réflexive symétrique transitive ``` `Equatable` est la capacité Core destinée aux APIs génériques qui ont besoin de cette égalité totale. Elle réutilise l'implémentation opérateur canonique et n'introduit ni seconde méthode `equals()` ni deuxième définition de `==` : ```text interface Equatable extends OpEqual { } ``` Ainsi, la règle générale reste inchangée : les opérateurs utilisateur sont définis uniquement via les interfaces compiler-known `Op...`, tandis que `Equatable` permet d'exprimer une contrainte sémantique de haut niveau sans dupliquer l'opération. Les `float*` conservent les comparaisons IEEE de la version normative adoptée. Comme `NaN == NaN` est faux, ils ne satisfont pas directement `Equatable` et relèvent de l'égalité partielle générale. `!=` est toujours la négation logique de `==`, jamais une implémentation indépendante. Les classes ne reçoivent aucune comparaison champ-à-champ automatique : elles doivent choisir explicitement leur sémantique d'égalité si elles veulent supporter `==`. L'identité de référence universelle reste distincte et s'obtient par `Object::sameIdentity(...)`. ## 20.6 Comparaison — V1 REQUIS — FIGÉ EN PRINCIPE Core distingue l'ordre partiel de l'ordre total : ```text public enum PartialOrdering { Less, Equal, Greater, Unordered } public enum Ordering { Less, Equal, Greater } ``` Interfaces opérateur : ```text OpPartialCompare -> PartialOrdering OpCompare -> Ordering ``` `OpCompare` garantit un ordre total. Les floats utilisent l'ordre partiel pour leurs opérateurs généraux en raison de `NaN`; les entiers peuvent utiliser l'ordre total. `Ordering::Equal` signifie équivalence dans la relation d'ordre considérée. Il ne doit pas être confondu automatiquement avec l'égalité générale `==`. Les contrats applicatifs `Comparable` et `Comparator` des collections ordonnées utilisent `Ordering` et sont définis au chapitre 22. ## 20.7 Comparaisons hétérogènes — V1 REQUIS — FIGÉ EN PRINCIPE Saselang doit conserver la possibilité d'égalité/comparaison hétérogène. La forme exacte des paramètres génériques et les règles de symétrie automatique doivent encore être formalisées pour éviter les implémentations concurrentes incohérentes. ## 20.8 Ownership des implémentations opérateur — V1 REQUIS — FIGÉ EN PRINCIPE Direction : - normalement l'implémentation appartient au type nominal de gauche ; - si le LHS est une primitive/Core sealed non extensible, le type nominal de droite peut fournir une forme inverse explicitement permise ; - un troisième package ne peut pas définir arbitrairement un opérateur entre deux types externes ; - une seule implémentation canonique par `(operator,Lhs,Rhs)`. Les détails doivent être alignés sur le resolver des packages. ## 20.9 Indexation — V1 REQUIS — FIGÉ ```text OpIndex OpIndexMut ``` Les deux contrats sont indépendants. Syntaxe : ```text container[index] container[index] = value ``` Les séquences standard utilisent initialement `uint64` comme index. D'autres index numériques pourront être supportés ultérieurement sans modifier la largeur de `uint64`. Un type utilisateur peut utiliser n'importe quel type d'index pertinent. ## 20.10 Map — V1 REQUIS — FIGÉ EN PRINCIPE Le contrat des maps est défini au chapitre 22. L'indexation est stricte : ```text map[key] -> V ``` La clé doit exister ; une absence dynamique produit `KeyNotFoundFault`. L'accès conditionnel est explicite et distinct : ```text map::get(key) -> Option ``` `OpIndexMut` remplace uniquement la valeur d'une clé existante ; l'affectation indexée n'insère jamais implicitement une nouvelle clé. ## 20.11 Affectation — V1 REQUIS — FIGÉ `=` n'est pas une expression. Interdits : ```text if (a = b) { ... } x = (a = b); a = b = c; ``` ## 20.12 Affectations composées — V1 REQUIS — FIGÉ ```text += -= *= /= %= &= |= ^= <<= >>= ``` Elles n'ont aucun `Op...` propre et ne sont donc pas surchargeables directement. Elles sont composées de : ```text lecture + opérateur fondamental surchargeable + réaffectation ``` Le résultat de l'opération doit être assignable exactement à la destination. Aucune conversion implicite ne doit être inventée pour rendre l'affectation composée valide. ## 20.13 `is` — V1 REQUIS — FIGÉ `is` teste l'appartenance d'une valeur à un type polymorphe ou à l'un de ses sous-types runtime. ```text value is Type ``` Pour une instance runtime de `Labrador` avec `Labrador extends Dog` et `Dog extends Animal` : ```text value is Animal // true value is Dog // true value is Labrador // true ``` `is` est utilisable sur les classes et les interfaces lorsqu'un polymorphisme runtime existe. Il est interdit sur les types sans polymorphisme runtime tels que les primitives numériques, `char`, les structs, les enums, les tuples ou les unions. `is` n'est pas surchargeable. Dans une branche dont la condition positive prouve `value is Type`, le compilateur raffine `value` vers `Type` dans le scope correspondant. Le raffinement cesse avec ce scope. Saselang n'introduit pas `is not` : la négation générale s'écrit explicitement : ```text !(value is Type) ``` ## 20.14 `instanceof` — V1 REQUIS — FIGÉ `instanceof` teste le **type de classe runtime exact**. ```text value instanceof ConcreteClass ``` Pour une instance runtime exacte de `Labrador` : ```text value instanceof Animal // false value instanceof Dog // false value instanceof Labrador // true ``` `instanceof` est utilisable uniquement avec une classe concrète non abstraite. Il est interdit avec une interface, une classe abstraite et tout type sans identité de classe runtime. `instanceof` n'est pas surchargeable. Une branche positive raffine la valeur vers la classe concrète testée et établit en plus que son type runtime est exactement cette classe. Saselang n'introduit pas `not instanceof` : ```text !(value instanceof ConcreteClass) ``` `is` et `instanceof` coexistent parce qu'ils ont deux sémantiques différentes : appartenance à une hiérarchie pour `is`, identité exacte de classe runtime pour `instanceof`. ## 20.15 `bitcast` — V1 REQUIS — FIGÉ EN PRINCIPE ```text bitcast(value) ``` est un intrinsic compiler-known, pas un opérateur. Il préserve exactement les bits et exige des tailles compatibles. Il ne réalise aucune conversion numérique. Certains bitcasts sont sûrs lorsque tout motif de bits destination est valide ; d'autres nécessiteront `unsafe`. Le tableau exact doit être lié au modèle mémoire. ## 20.16 Appel `()` — V1 REQUIS — FIGÉ EN PRINCIPE `()` est une construction d'appel du langage, pas un opérateur utilisateur. Il n'est pas prévu de fournir un `OpCall` général. Les fonctions, closures/lambdas futures seront appelables par définition de leur type, pas en surchargeant arbitrairement `()` sur n'importe quel objet. ## 20.17 Précédence — V1 REQUIS — FIGÉ Du plus fort au plus faible : ```text 1. qualification / membre . :: 2. appel / indexation () [] 3. préfixes +x -x !x ~x 4. multiplicatifs * / % 5. additifs + - 6. shifts << >> 7. relation / type < <= > >= is instanceof 8. égalité == != 9. bitwise AND & 10. bitwise XOR ^ 11. bitwise OR | 12. logique short-circuit AND && 13. logique short-circuit OR || ``` `bitcast(...)` suit la syntaxe d'appel et n'a pas sa propre précédence. `=` et les affectations composées ne figurent pas dans cette hiérarchie puisqu'elles ne produisent pas de valeur. ## 20.18 Associativité — V1 REQUIS — FIGÉ Les opérateurs binaires arithmétiques/bitwise/logiques sont associatifs syntaxiquement à gauche. Les préfixes s'imbriquent depuis la droite. Les comparaisons sont non associatives : ```text a < b < c -> interdit a == b == c -> interdit ``` Écrire explicitement : ```text a < b && b < c ``` ---