v0.2.12
This commit is contained in:
365
chapters/020-operateurs.md
Normal file
365
chapters/020-operateurs.md
Normal file
@@ -0,0 +1,365 @@
|
||||
# 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 `operator` contracts :
|
||||
|
||||
- retournent directement leur valeur ;
|
||||
- ne retournent jamais `Result` ;
|
||||
- ne déclarent jamais `throws`.
|
||||
|
||||
Une faute de contrat du langage peut néanmoins déclencher une faute runtime déterministe.
|
||||
|
||||
## 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É EN PRINCIPE
|
||||
|
||||
```text
|
||||
OpPartialEqual<Lhs,Rhs>
|
||||
OpEqual<T>
|
||||
```
|
||||
|
||||
`OpEqual<T>` renforce :
|
||||
|
||||
```text
|
||||
OpPartialEqual<T,T>
|
||||
```
|
||||
|
||||
et garantit contractuellement une relation d'équivalence :
|
||||
|
||||
```text
|
||||
réflexive
|
||||
symétrique
|
||||
transitive
|
||||
```
|
||||
|
||||
`float*` n'est pas `OpEqual` au sens strict si NaN brise la réflexivité ; il relève de l'égalité partielle.
|
||||
|
||||
`!=` est toujours dérivé de `==`, jamais implémenté indépendamment.
|
||||
|
||||
Les classes ne reçoivent aucune comparaison champ-à-champ automatique : elles doivent choisir explicitement leur sémantique d'égalité si elles veulent supporter `==`.
|
||||
|
||||
## 20.6 Comparaison — V1 REQUIS — FIGÉ EN PRINCIPE
|
||||
|
||||
Core :
|
||||
|
||||
```text
|
||||
public enum Ordering {
|
||||
Less,
|
||||
Equal,
|
||||
Greater,
|
||||
Unordered
|
||||
}
|
||||
```
|
||||
|
||||
Interfaces :
|
||||
|
||||
```text
|
||||
OpPartialCompare<Lhs,Rhs>
|
||||
OpCompare<T>
|
||||
```
|
||||
|
||||
`OpCompare<T>` renforce `OpPartialCompare<T,T>` et garantit un ordre total, donc pas de `Ordering::Unordered`.
|
||||
|
||||
Les floats utilisent l'ordre partiel ; les entiers peuvent utiliser l'ordre total.
|
||||
|
||||
Le lien exact entre égalité et comparaison pour éviter deux contrats contradictoires sur une même paire doit être verrouillé dans la spécification finale des interfaces `Op`.
|
||||
|
||||
## 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 — DIRECTION FIGÉE
|
||||
|
||||
Direction recommandée :
|
||||
|
||||
```text
|
||||
Map<K,V>
|
||||
OpIndex<K,Option<V>>
|
||||
OpIndexMut<K,V>
|
||||
```
|
||||
|
||||
Lecture : absent -> `None` ; présent -> `Some(value)`.
|
||||
|
||||
Écriture : insertion si absent, remplacement si présent.
|
||||
|
||||
Une méthode `containsKey` peut compléter l'API sans être obligatoire avant toute lecture.
|
||||
|
||||
## 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
|
||||
```
|
||||
|
||||
---
|
||||
Reference in New Issue
Block a user