This commit is contained in:
2026-09-13 10:20:16 +02:00
parent 019c8ad335
commit b72193d656
38 changed files with 1523 additions and 837 deletions

View File

@@ -20,7 +20,7 @@ Il n'existe aucune promotion numérique implicite générale entre deux valeurs
```text
int8 small = ...;
int32 large = small; // ERROR
int32 large = small; // ERROR
int32 explicitLarge = small::toInt32(); // OK
```
@@ -48,63 +48,140 @@ if (animal is Dog) {
}
```
Lorsqu'un test du type runtime **exact** est nécessaire, `instanceof` est utilisé.
Lorsqu'un test du type runtime exact est nécessaire, `instanceof` est utilisé.
Saselang n'introduit pas pour le moment de syntaxe générale concurrente telle que `(Dog)value`, `value as Dog` ou `cast<Dog>(value)`. Une telle opération ne pourra être ajoutée que si un besoin distinct de `is`/`instanceof` + refinement est démontré et si son contrat d'échec est explicite.
## 24.5 API numérique du Core — V1 REQUIS — DIRECTION FIGÉE
## 24.5 API numérique du Core — V1 REQUIS — FIGÉ EN PRINCIPE
Les conversions numériques sont exposées comme membres standard des primitives définis par le Core. Les noms de méthodes ne sont pas des mots-clés du langage.
Le compilateur connaît les règles nécessaires pour typer, vérifier, constant-fold et abaisser ces opérations vers Sase IR, mais l'inventaire exhaustif de la surface API appartient au Core.
Principe de nommage :
L'introduction de `Fault` supprime l'obligation historique de créer une variante `try... -> Result<T,NumericConversionError>` uniquement parce qu'une conversion directe peut échouer.
Principe de nommage V1 :
```text
toTarget()
conversion exacte et totale
tryToTarget()
conversion exacte pour la valeur courante, récupérable si impossible
conversion exacte
totale si tout le domaine source est représentable
sinon valeur directe + faults NumericConversionFault
roundToTarget()
perte de précision explicitement acceptée, conversion totale
tryRoundToTarget()
perte de précision explicitement acceptée, mais conversion pouvant échouer
perte de précision / arrondi explicitement accepté
peut fault si une autre précondition reste violée, par exemple le domaine fini destination
saturateToTarget()
saturation explicite lorsqu'aucun arrondi supplémentaire n'est nécessaire
saturation explicite lorsque la politique de plage est le seul ajustement demandé
saturatingRoundToTarget()
arrondi + saturation explicitement annoncés
arrondi + saturation explicitement annoncés lorsque les deux sont nécessaires
wrapToTarget()
wrapping entier explicite
```
Une forme n'existe que si elle apporte une sémantique observable différente d'une autre forme déjà disponible pour la paire source/destination.
Une opération n'existe que si elle apporte une sémantique observable différente d'une autre forme disponible pour la paire source/destination.
Ainsi, lorsqu'un `toTarget()` exact et total existe, les variantes `tryToTarget()`, `saturateToTarget()` ou `wrapToTarget()` qui produiraient exactement le même résultat pour tout le domaine source sont absentes.
Le Core ne duplique pas mécaniquement :
```text
toTarget()
tryToTarget()
```
lorsque la seule différence serait que la seconde transporte le même échec dans `Result`.
Une API spécialisée peut toujours choisir volontairement `Result` si l'échec doit devenir une donnée normale du domaine, mais cela ne fait pas partie de la matrice canonique des conversions primitives.
Règle de composition : deux opérations Core ne sont fusionnées dans un même nom que si leur séparation en opérations successives modifierait la sémantique, perdrait de l'information ou empêcherait d'exprimer le même contrat.
Lorsqu'une composition existante est strictement équivalente, aucun alias combiné n'est ajouté au Core.
## 24.6 `float -> integer` — V1 REQUIS — DIRECTION FIGÉE
## 24.6 Entier -> entier — V1 REQUIS — FIGÉ EN PRINCIPE
Un flottant ne possède jamais un simple `toIntXX()` ou `toUintXX()`.
La conversion exacte stricte utilise :
Si toutes les valeurs source sont représentables exactement dans la destination :
```text
tryToIntXX()
tryToUintXX()
toTarget() -> Target
```
Elle réussit uniquement si la valeur source est finie, mathématiquement entière et représentable exactement dans le type destination. Sinon elle retourne `Result::Err(NumericConversionError(...))`.
est total et ne déclare aucun `NumericConversionFault` lié à la plage.
Les politiques mathématiques de traitement de la partie fractionnaire restent des opérations Core séparées :
Lorsque certaines valeurs source ne sont pas représentables :
```text
toTarget() -> Target
faults NumericConversionFault
```
avec `OutOfRange` lorsque la valeur courante n'entre pas dans le domaine destination.
Les politiques alternatives restent explicites :
```text
saturateToTarget()
wrapToTarget()
```
Elles ne sont présentes que lorsqu'elles peuvent produire un résultat différent de `toTarget()` pour cette paire.
Aucun wrapping ni saturation n'est implicite.
## 24.7 Entier -> flottant — V1 REQUIS — FIGÉ EN PRINCIPE
`toFloatXX()` exige une représentation exacte de la valeur entière.
```text
toFloatXX() -> floatXX
faults NumericConversionFault
```
n'a une clause `faults` que lorsque certaines valeurs source peuvent être inexactes ou hors du domaine fini destination.
`roundToFloatXX()` accepte explicitement l'arrondi canonique `nearest, ties to even` :
```text
roundToFloatXX() -> floatXX
```
Il peut encore produire `OutOfRange` si une valeur entière finie dépasse le domaine fini de la destination.
Lorsque l'arrondi et la saturation doivent être annoncés ensemble :
```text
saturatingRoundToFloatXX()
```
borne une magnitude finie trop grande au plus grand fini de même signe puis applique la précision destination.
Il n'existe pas de `wrapToFloatXX()`.
## 24.8 `float -> integer` — V1 REQUIS — FIGÉ EN PRINCIPE
La conversion stricte utilise désormais directement :
```text
toIntXX() -> intXX
faults NumericConversionFault
toUintXX() -> uintXX
faults NumericConversionFault
```
Elle réussit uniquement si la valeur source est :
```text
finie
mathématiquement entière
dans le domaine de la destination
exactement représentable comme entier destination
```
Sinon le fault porte la catégorie appropriée.
Les politiques mathématiques de traitement de la partie fractionnaire restent des opérations séparées :
```text
floor()
@@ -116,30 +193,38 @@ truncate()
Elles se composent avec la conversion :
```text
value::floor()::tryToInt32()
value::ceil()::tryToInt32()
value::round()::tryToInt32()
value::truncate()::tryToInt32()
value::floor()::toInt32()
value::ceil()::toInt32()
value::round()::toInt32()
value::truncate()::toInt32()
```
Saselang n'introduit donc pas les alias redondants `tryFloorToInt32()`, `tryCeilToInt32()`, `tryRoundToInt32()` ou `tryTruncateToInt32()` lorsque ces compositions possèdent exactement la même sémantique.
Saselang n'introduit pas les alias redondants `floorToInt32()`, `ceilToInt32()`, `roundToInt32()` ou `truncateToInt32()` lorsque ces compositions possèdent exactement la même sémantique.
Les politiques de dépassement de domaine suivent la même règle :
Les politiques de dépassement de domaine se composent de la même façon :
```text
value::floor()::trySaturateToInt32()
value::round()::tryWrapToInt32()
value::floor()::saturateToInt32()
value::round()::wrapToInt32()
```
`trySaturateToIntXX()` exige une valeur finie et mathématiquement entière, puis sature aux bornes du type destination. Les échecs qui ne relèvent pas de la plage, par exemple `NaN`, une infinité ou une valeur fractionnaire, restent des `NumericConversionError`.
Pour `float -> integer` :
`tryWrapToIntXX()` exige également une valeur finie et mathématiquement entière, puis applique le wrapping entier modulo `2^N` défini par Saselang.
```text
saturateToTarget()
exige encore une valeur finie et mathématiquement entière
faults NotFinite / NotIntegral si nécessaire
sature uniquement la plage
Une méthode combinée reste admise lorsqu'une décomposition changerait le contrat ou perdrait l'information nécessaire. C'est notamment le cas de `saturatingRoundToFloat32()` pour certains narrowings flottants : un `roundToFloat32()` séparé pourrait échouer avant que la saturation ne puisse être appliquée.
wrapToTarget()
exige encore une valeur finie et mathématiquement entière
faults NotFinite / NotIntegral si nécessaire
applique le wrapping modulo 2^N à l'entier mathématique fini
```
Aucun comportement de conversion ne dépend d'un profil, d'un linter ou d'un backend.
Une méthode combinée reste admise uniquement lorsqu'une décomposition changerait le contrat ou perdrait l'information nécessaire.
## 24.7 `float -> float`, valeurs IEEE spéciales — V1 REQUIS — FIGÉ
## 24.9 `float -> float`, valeurs IEEE spéciales — V1 REQUIS — FIGÉ
Toute conversion de valeur flottante préserve les catégories sémantiques suivantes lorsque la destination est un type flottant Saselang :
@@ -162,30 +247,33 @@ signe du NaN
représentation binaire exacte
```
Ces propriétés relèvent d'un éventuel contrat binaire distinct ; `bitcast<T>` ne peut les préserver que lorsque ses propres contraintes, notamment de taille, sont satisfaites.
Ces propriétés relèvent d'un contrat binaire distinct.
`tryToFloatXX()` traite `NaN` et les infinités comme des valeurs sémantiques représentables du type flottant destination. Le mot « exact » désigne ici l'exactitude de la valeur sémantique Saselang, pas l'identité bit-à-bit d'un payload NaN.
Pour une valeur finie :
Pour une réduction de format :
```text
tryToFloatXX()
exige une représentation exacte
toFloatXX()
exige l'exactitude de la valeur sémantique
faults Inexact ou OutOfRange pour une valeur finie si nécessaire
tryRoundToFloatXX()
roundToFloatXX()
accepte l'arrondi canonique
refuse une valeur finie hors domaine fini destination
faults OutOfRange si une valeur finie dépasse le domaine fini destination
saturatingRoundToFloatXX()
accepte l'arrondi canonique
sature une valeur finie hors domaine vers +/-Target::Max
```
Les infinités ne sont pas saturées puisqu'elles sont déjà des valeurs représentables du format flottant destination.
`NaN` et les infinities sont déjà représentables dans les formats flottants Saselang et ne sont donc pas saturés.
## 24.8 `NumericConversionError` — V1 REQUIS — NOM DE TRAVAIL / CODES FIGÉS
## 24.10 `NumericConversionFault` — V1 REQUIS — NOM DE TRAVAIL / CODES FIGÉS
`NumericConversionError` est retenu comme nom de travail du `ResultError` Core utilisé par les conversions numériques récupérables.
`NumericConversionFault` est retenu comme nom de travail du `Fault` Core utilisé par les conversions numériques directes dont les préconditions runtime peuvent échouer.
```text
NumericConversionFault extends Fault
```
Les catégories sémantiques V1 sont :
@@ -213,7 +301,7 @@ Inexact
alors que l'opération exige l'exactitude
```
`NumericConversionError` reste volontairement généraliste et minimal. Il n'ajoute pas automatiquement :
`NumericConversionFault` reste volontairement minimal. Il n'ajoute pas automatiquement :
```text
sourceType
@@ -224,21 +312,19 @@ backend
roundingMode
```
au-delà de l'état commun fourni par `ResultError`.
au-delà de l'état commun fourni par `Error`/`Fault`.
Le nom concret et la représentation numérique interne des codes pourront encore être ajustés avant stabilisation publique, mais les catégories sémantiques ci-dessus font partie du contrat V1.
## 24.9 Réduction anti-doublon par paire — V1 REQUIS — FIGÉ
## 24.11 Réduction anti-doublon par paire — V1 REQUIS — FIGÉ
La matrice examine chaque paire `Source -> Target` et n'expose que les opérations dont le comportement peut réellement être distingué sur le domaine source.
Ainsi, pour une paire `float -> integer` dont toutes les valeurs finies mathématiquement entières sont déjà dans le domaine signé destination, `trySaturateToTarget()` et `tryWrapToTarget()` seraient des doublons de `tryToTarget()` et n'existent pas.
Lorsqu'une opération directe est totale pour toute la paire, elle ne déclare aucun fault inutile.
Pour une destination non signée, les valeurs négatives suffisent généralement à rendre les politiques checked, saturating et wrapping distinctes.
Lorsqu'une politique `saturate` ou `wrap` ne peut jamais différer de la conversion exacte sur cette paire, elle est absente.
La matrice exhaustive en annexe est normative sur ce point.
La disparition des variantes `try...` ne modifie pas cette règle de non-redondance ; elle supprime seulement les duplications qui ne différaient que par le canal d'échec `ResultError` versus valeur directe.
## 24.10 Disponibilité Core et target — V1 REQUIS — FIGÉ EN PRINCIPE
## 24.12 Disponibilité Core et target — V1 REQUIS — FIGÉ EN PRINCIPE
Les conversions fondamentales de la matrice sont des capacités Core obligatoires dès lors que les types source et destination sont supportés par le target.
@@ -248,9 +334,9 @@ Un target réduit peut ne pas supporter un type fondamental donné. Dans ce cas
Voir également le chapitre 40.
## 24.11 Matrice exhaustive — ANNEXE NORMATIVE EN COURS DE GEL
## 24.13 Matrice exhaustive — ANNEXE NORMATIVE EN COURS DE GEL
L'inventaire source destination des opérations de conversion est maintenu séparément afin d'éviter les oublis, doublons et incohérences.
L'inventaire source -> destination des opérations de conversion est maintenu séparément afin d'éviter les oublis, doublons et incohérences.
Voir :
@@ -258,6 +344,6 @@ Voir :
annexes/A-numeric-conversions.md
```
L'annexe doit lister le maximum de possibilités sémantiquement distinctes avant réduction finale de l'API Core.
L'annexe liste les possibilités sémantiquement distinctes après suppression des variantes `try...` purement liées à l'ancien canal `ResultError`.
---