Files
saselang-bible/chapters/020-operateurs.md
2026-09-13 21:59:15 +02:00

391 lines
10 KiB
Markdown

# 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<T>
OpNegate<T>
OpAdd<Lhs,Rhs,Out>
OpSubtract<Lhs,Rhs,Out>
OpMultiply<Lhs,Rhs,Out>
OpDivide<Lhs,Rhs,Out>
OpRemainder<Lhs,Rhs,Out>
```
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<T>
OpBitAnd<Lhs,Rhs,Out>
OpBitOr<Lhs,Rhs,Out>
OpBitXor<Lhs,Rhs,Out>
OpShiftLeft<T,Out>
OpShiftRight<T,Out>
```
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<Lhs,Rhs>
OpEqual<T>
Equatable<T>
```
`OpEqual<T>` renforce :
```text
OpPartialEqual<T,T>
```
et garantit contractuellement une relation d'équivalence :
```text
réflexive
symétrique
transitive
```
`Equatable<T>` 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<T> extends OpEqual<T> {
}
```
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<T>` 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<float*>` 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<Lhs,Rhs>
-> PartialOrdering
OpCompare<T>
-> Ordering
```
`OpCompare<T>` 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<T>` et `Comparator<T>` 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<Index,Read>
OpIndexMut<Index,Write>
```
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<V>
```
`OpIndexMut<K,V>` 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<T>` — V1 REQUIS — FIGÉ EN PRINCIPE
```text
bitcast<T>(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<T>(...)` 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
```
---