264 lines
9.4 KiB
Markdown
264 lines
9.4 KiB
Markdown
# 24. Casts et conversions
|
|
|
|
## 24.1 Principe général — V1 REQUIS — FIGÉ EN PRINCIPE
|
|
|
|
Saselang distingue explicitement :
|
|
|
|
```text
|
|
conversion de valeur
|
|
cast de hiérarchie nominale
|
|
bitcast de représentation binaire
|
|
```
|
|
|
|
Ces mécanismes ne sont pas des alias.
|
|
|
|
`bitcast<T>(value)` est défini au chapitre 20 et ne constitue jamais une conversion numérique.
|
|
|
|
## 24.2 Conversions implicites numériques — V1 REQUIS — FIGÉ
|
|
|
|
Il n'existe aucune promotion numérique implicite générale entre deux valeurs déjà typées de types primitifs différents.
|
|
|
|
```text
|
|
int8 small = ...;
|
|
int32 large = small; // ERROR
|
|
int32 explicitLarge = small::toInt32(); // OK
|
|
```
|
|
|
|
Le typage contextuel d'un littéral non encore typé reste une règle distincte.
|
|
|
|
## 24.3 Upcast — V1 REQUIS — FIGÉ
|
|
|
|
Un upcast compatible dans une hiérarchie de classes ou vers une interface satisfaite est une assignation de sous-typage normale et ne nécessite pas une syntaxe de cast dédiée.
|
|
|
|
```text
|
|
Dog dog = ...;
|
|
Animal animal = dog;
|
|
Serializable serializable = dog;
|
|
```
|
|
|
|
## 24.4 Downcast et raffinement — V1 REQUIS — FIGÉ EN PRINCIPE
|
|
|
|
Le mécanisme canonique de downcast V1 est le test `is` suivi du raffinement de type dans le scope positif.
|
|
|
|
```text
|
|
Animal animal = ...;
|
|
|
|
if (animal is Dog) {
|
|
// animal est raffiné en Dog ici.
|
|
}
|
|
```
|
|
|
|
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
|
|
|
|
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 :
|
|
|
|
```text
|
|
toTarget()
|
|
conversion exacte et totale
|
|
|
|
tryToTarget()
|
|
conversion exacte pour la valeur courante, récupérable si impossible
|
|
|
|
roundToTarget()
|
|
perte de précision explicitement acceptée, conversion totale
|
|
|
|
tryRoundToTarget()
|
|
perte de précision explicitement acceptée, mais conversion pouvant échouer
|
|
|
|
saturateToTarget()
|
|
saturation explicite lorsqu'aucun arrondi supplémentaire n'est nécessaire
|
|
|
|
saturatingRoundToTarget()
|
|
arrondi + saturation explicitement annoncés
|
|
|
|
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.
|
|
|
|
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.
|
|
|
|
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
|
|
|
|
Un flottant ne possède jamais un simple `toIntXX()` ou `toUintXX()`.
|
|
|
|
La conversion exacte stricte utilise :
|
|
|
|
```text
|
|
tryToIntXX()
|
|
tryToUintXX()
|
|
```
|
|
|
|
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(...))`.
|
|
|
|
Les politiques mathématiques de traitement de la partie fractionnaire restent des opérations Core séparées :
|
|
|
|
```text
|
|
floor()
|
|
ceil()
|
|
round()
|
|
truncate()
|
|
```
|
|
|
|
Elles se composent avec la conversion :
|
|
|
|
```text
|
|
value::floor()::tryToInt32()
|
|
value::ceil()::tryToInt32()
|
|
value::round()::tryToInt32()
|
|
value::truncate()::tryToInt32()
|
|
```
|
|
|
|
Saselang n'introduit donc pas les alias redondants `tryFloorToInt32()`, `tryCeilToInt32()`, `tryRoundToInt32()` ou `tryTruncateToInt32()` lorsque ces compositions possèdent exactement la même sémantique.
|
|
|
|
Les politiques de dépassement de domaine suivent la même règle :
|
|
|
|
```text
|
|
value::floor()::trySaturateToInt32()
|
|
value::round()::tryWrapToInt32()
|
|
```
|
|
|
|
`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`.
|
|
|
|
`tryWrapToIntXX()` exige également une valeur finie et mathématiquement entière, puis applique le wrapping entier modulo `2^N` défini par Saselang.
|
|
|
|
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.
|
|
|
|
Aucun comportement de conversion ne dépend d'un profil, d'un linter ou d'un backend.
|
|
|
|
## 24.7 `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 :
|
|
|
|
```text
|
|
NaN -> NaN
|
|
+Infinity -> +Infinity
|
|
-Infinity -> -Infinity
|
|
+0 -> +0
|
|
-0 -> -0
|
|
```
|
|
|
|
Pour `NaN`, la conversion garantit uniquement que la destination reste `NaN`.
|
|
|
|
Elle ne garantit pas lors d'une conversion de valeur :
|
|
|
|
```text
|
|
payload NaN
|
|
quiet/signaling bit
|
|
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.
|
|
|
|
`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 :
|
|
|
|
```text
|
|
tryToFloatXX()
|
|
exige une représentation exacte
|
|
|
|
tryRoundToFloatXX()
|
|
accepte l'arrondi canonique
|
|
refuse une valeur finie hors 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.
|
|
|
|
## 24.8 `NumericConversionError` — 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.
|
|
|
|
Les catégories sémantiques V1 sont :
|
|
|
|
```text
|
|
NotFinite
|
|
NotIntegral
|
|
OutOfRange
|
|
Inexact
|
|
```
|
|
|
|
Sens :
|
|
|
|
```text
|
|
NotFinite
|
|
NaN ou +/-Infinity lorsqu'une valeur finie est requise
|
|
|
|
NotIntegral
|
|
float -> integer alors que la valeur n'est pas mathématiquement entière
|
|
|
|
OutOfRange
|
|
valeur mathématique hors du domaine de la destination
|
|
|
|
Inexact
|
|
valeur dans le domaine destination mais non représentable exactement
|
|
alors que l'opération exige l'exactitude
|
|
```
|
|
|
|
`NumericConversionError` reste volontairement généraliste et minimal. Il n'ajoute pas automatiquement :
|
|
|
|
```text
|
|
sourceType
|
|
targetType
|
|
sourceValue
|
|
timestamp
|
|
backend
|
|
roundingMode
|
|
```
|
|
|
|
au-delà de l'état commun fourni par `ResultError`.
|
|
|
|
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É
|
|
|
|
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.
|
|
|
|
Pour une destination non signée, les valeurs négatives suffisent généralement à rendre les politiques checked, saturating et wrapping distinctes.
|
|
|
|
La matrice exhaustive en annexe est normative sur ce point.
|
|
|
|
## 24.10 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.
|
|
|
|
L'absence d'une instruction matérielle native ne justifie pas l'absence d'une conversion si une émulation logicielle conforme est raisonnablement possible.
|
|
|
|
Un target réduit peut ne pas supporter un type fondamental donné. Dans ce cas l'indisponibilité porte sur le type/capacité fondamentale, pas sur une sélection arbitraire de ses méthodes de conversion.
|
|
|
|
Voir également le chapitre 40.
|
|
|
|
## 24.11 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.
|
|
|
|
Voir :
|
|
|
|
```text
|
|
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.
|
|
|
|
---
|