v0.2.17
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
# Bible Saselang 0.2.16
|
||||
# Bible Saselang 0.2.17
|
||||
|
||||
> **Statut : pré-spécification normative de Saselang V1.**
|
||||
>
|
||||
@@ -7,7 +7,7 @@
|
||||
>
|
||||
> La V2 visera principalement la réécriture/self-hosting de la toolchain V1 en Saselang lui-même. Les extensions majeures de cibles et d'écosystème sont prévues à partir de V3+.
|
||||
>
|
||||
> **Révision 0.2.16 :** formalisation des arrays/slices et de leur initialisation, hiérarchie de capacités de collections (`Collection`, `List`, `SettableList`, `ResizableList`), sous-chaînes à stockage partageable et politique des bibliothèques officielles `.saselib`.
|
||||
> **Révision 0.2.17 :** introduction normative de `Fault` comme troisième branche d’`Error`, ajout de `fault` / `faults`, indépendance de `throws` vis-à-vis du type de retour, simplification des conversions numériques/Unicode, fermeture des contrats `Map`/`Set`/`View`/`Iterator` et des collections ordonnées.
|
||||
|
||||
## Organisation de cette distribution
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Sommaire — Bible Saselang 0.2.16
|
||||
# Sommaire — Bible Saselang 0.2.17
|
||||
|
||||
## Chapitres
|
||||
|
||||
|
||||
@@ -1,4 +1,30 @@
|
||||
# Changelog documentaire — 0.2.16
|
||||
# Changelog documentaire — 0.2.17
|
||||
|
||||
## 0.2.17
|
||||
|
||||
- hiérarchie `Error` étendue à trois branches sœurs : `ResultError`, `Exception`, `Fault` ;
|
||||
- `Exception` reste checked via `throw` / `throws`, tandis que `Fault` est unchecked, capturable et documentable par `faults` ;
|
||||
- ajout du statement `fault` réservé aux descendants de `Fault` ;
|
||||
- `catch` limité aux branches `Exception` et `Fault`, jamais `Error` ou `ResultError` ;
|
||||
- `faults` défini comme clause optionnelle, non exhaustive et sans propagation obligatoire ;
|
||||
- `throws` rendu indépendant du type de retour : une callable retournant directement `T` peut déclarer des exceptions checked ;
|
||||
- suppression du principe « toute opération faillible doit retourner `Result` » ; `Result` reste réservé aux échecs explicitement transportés comme valeurs ;
|
||||
- suppression des duplications automatiques `op()` / `tryOp()` lorsqu'elles ne diffèrent que par le canal d'échec ;
|
||||
- conversions numériques canoniques migrées vers valeur directe + `NumericConversionFault` ;
|
||||
- `NumericConversionError` remplacé par `NumericConversionFault`, avec `NotFinite`, `NotIntegral`, `OutOfRange`, `Inexact` ;
|
||||
- conversions Unicode invalidables migrées vers valeur directe + `UnicodeEncodingFault`, sans familles `tryFrom`/`tryTo` parallèles mécaniques ;
|
||||
- `PartialOrdering` séparé de `Ordering`; `Ordering` contient uniquement `Less`, `Equal`, `Greater` ;
|
||||
- `Comparable<T>` et `Comparator<T>` retenus pour l'ordre naturel/principal et l'ordre externe ; un comparator explicite gagne toujours ;
|
||||
- `Iterable<T>::iterator()` et `Iterator<T>::next() -> Option<T>` figés ; `Iterator<T>` reste distinct d'`Iterable<T>` ;
|
||||
- ajout de `View<T> extends Iterable<T>` avec `count()` / `isEmpty()` et sans `contains()` obligatoire ;
|
||||
- `Set<T>` / `ResizableSet<T>` fermés, avec `clear() -> uint64` ;
|
||||
- `Map<K,V>` n'est pas directement `Iterable`; `keys()` / `values()` / `entries()` retournent des vues ;
|
||||
- indexation map stricte `map[key] -> V`, `get(key) -> Option<V>`, affectation indexée limitée au remplacement d'une clé existante ;
|
||||
- `ResizableMap` utilise `insert`, `remove`, `clear`, avec faults stricts au lieu de variantes `tryInsert` / `tryRemove` mécaniques ;
|
||||
- `MapEntry<K,V>` reste une valeur de lecture et non un proxy mutable vers la map ;
|
||||
- `SortedSet<T>`, `SortedMap<K,V>`, `TreeSet<T>` et `TreeMap<K,V>` définis en principe ; création par factories `natural()` / `withComparator()` ;
|
||||
- les garanties concurrentes de collections restent orthogonales et relèvent du SDK (`ConcurrentMap`, etc.) sans symétrie artificielle ;
|
||||
- le chapitre mémoire identifie désormais explicitement le sous-modèle pointeurs : références de classe, slices, pointeurs Saselang, raw/FFI et function pointers.
|
||||
|
||||
## 0.2.16
|
||||
|
||||
|
||||
130
MANIFEST.toml
130
MANIFEST.toml
@@ -1,65 +1,153 @@
|
||||
format = 1
|
||||
version = "0.2.16"
|
||||
version = "0.2.17"
|
||||
distribution = "delta"
|
||||
base_version = "0.2.15"
|
||||
base_version = "0.2.16"
|
||||
documentation_layout = "multifile"
|
||||
|
||||
[[modified]]
|
||||
path = "000-README.md"
|
||||
sha256 = "4b4d422dcc52991e38c6cb1b7b92aeb391ca0b7d6bc1c8da0de4de6169c93b7a"
|
||||
sha256 = "ca87a3caaadb1a618f0a35620a2e62e406bd8e186de0a7282e606a38f9f541ca"
|
||||
|
||||
[[modified]]
|
||||
path = "001-SUMMARY.md"
|
||||
sha256 = "2cf8811903512dc58739c4d16e2696d10bcb36f2b767d3e5eccf038013ef1a66"
|
||||
sha256 = "88f6f80b7233900491f15d818cebbfdb3fc83f02667cfa137cb3ed6a17f86edf"
|
||||
|
||||
[[modified]]
|
||||
path = "003-CHANGELOG.md"
|
||||
sha256 = "0f78fefe1d630ebc0587b7bb0865f77c34b9782562bf47af6d86e82cac8bf738"
|
||||
sha256 = "ccc7116c032fc68b6a91fba447674673d0a6141229498e1db3d00a246d11df0f"
|
||||
|
||||
[[modified]]
|
||||
path = "annexes/A-numeric-conversions.md"
|
||||
sha256 = "cc13423ccf18bbfac922f6e9a9afe422d438bd1f4aeea10919941a55c3d9dc98"
|
||||
|
||||
[[modified]]
|
||||
path = "annexes/B-unicode-encoding-conversions.md"
|
||||
sha256 = "c26a957419e4b60706b61c9f482380a5cd496de2fe685beb33bc86927a287ee4"
|
||||
|
||||
[[modified]]
|
||||
path = "chapters/002-principes-generaux-du-langage.md"
|
||||
sha256 = "63b26e729bac07ee2395634698c54f33c0f16d6f121571e9bc6096bd05cfa40f"
|
||||
|
||||
[[modified]]
|
||||
path = "chapters/004-couches-de-lecosysteme-v1.md"
|
||||
sha256 = "5d6bfbc9e9d7c5253fbe470c114a2b2394c16cf62a5cd7efd3d9f40252ae0106"
|
||||
sha256 = "18c0b82d5b2b55dab17a2197dc2635d1d050ac4b06b6c3fc1dc34e12e5978bb6"
|
||||
|
||||
[[modified]]
|
||||
path = "chapters/011-tuples.md"
|
||||
sha256 = "8008f930e37a69980ccf39af0261d5af63efb136268c4793e1899da1fc58a523"
|
||||
|
||||
[[modified]]
|
||||
path = "chapters/013-interfaces.md"
|
||||
sha256 = "330f2d231ed7d6ffbbbd8a1703c8f27f17b2c9c2b372d5c5c663fa4b6ae3a43d"
|
||||
|
||||
[[modified]]
|
||||
path = "chapters/015-fonctions-methodes-et-clsmethod.md"
|
||||
sha256 = "e15da7b6f0b86fcadfa7d0ec4c5b4877ed97580d7292aa13dfab3a271b3b2468"
|
||||
|
||||
[[modified]]
|
||||
path = "chapters/018-result-erreurs-et-exceptions.md"
|
||||
sha256 = "d2e08f85e0f077ece4e5f15d3dc47ce552608376001b128f222230070ed23726"
|
||||
|
||||
[[modified]]
|
||||
path = "chapters/019-controle-de-flux.md"
|
||||
sha256 = "34ec610fd03ac339504d48a265793fdb2c146404d38285b9bada72683f88361d"
|
||||
|
||||
[[modified]]
|
||||
path = "chapters/020-operateurs.md"
|
||||
sha256 = "59119759c87babc9dc0d852fcdfcda6d527fcb475c6c22d26cd0fe546d50f0df"
|
||||
|
||||
[[modified]]
|
||||
path = "chapters/021-strings-unicode-et-encodages.md"
|
||||
sha256 = "3350f8581eb43343136caf7cf808b25da4543edac6b176ad61d3e40292b19d76"
|
||||
sha256 = "c8e5ea1e1fce5fe3128d7dd1eb73ddd784b71d3fa24298de9bfabc1d44e05327"
|
||||
|
||||
[[modified]]
|
||||
path = "chapters/022-collections-et-iteration.md"
|
||||
sha256 = "a60534eef7f12201b238c7a4899b46c8be4df3535f293978e05471cc210c3d7a"
|
||||
sha256 = "e7459c2db8d0fe0cdf573d25f888c1791b6d03a9de6f51ae849991039abc4328"
|
||||
|
||||
[[modified]]
|
||||
path = "chapters/037-dependances-et-scopes.md"
|
||||
sha256 = "64335ed6b00a8133718384e49b34be0f362569b9b177a35da963543abe603a9a"
|
||||
path = "chapters/024-casts-et-conversions.md"
|
||||
sha256 = "e6cd16e5e4b65c2f05bac57a5410cb7aaa74253d2572f969b4fcf1dbf3618e93"
|
||||
|
||||
[[modified]]
|
||||
path = "chapters/026-async-et-concurrence.md"
|
||||
sha256 = "65ab9ddcfa155130daf913d9f24ebf8583fca92e3fbd4325d3b5ef86729b998a"
|
||||
|
||||
[[modified]]
|
||||
path = "chapters/027-memoire-references-et-unsafe.md"
|
||||
sha256 = "c82271a7b7b179b49a963c1f00b1e5179c71c4d9839a50d4ca541b9b6c604215"
|
||||
|
||||
[[modified]]
|
||||
path = "chapters/028-defer-et-nettoyage.md"
|
||||
sha256 = "d2d9d9e5b2faa7a238931f80a3247b735e9a1a1c5967a3920b3649da6a6bfd32"
|
||||
|
||||
[[modified]]
|
||||
path = "chapters/041-artifacts-exports-profils-et-reservation-des-formats-futurs.md"
|
||||
sha256 = "bbec66e98338765dfb85b22e941811eedc2f1c7bd11ab9ccc86483f3ea4c3ec2"
|
||||
|
||||
[[modified]]
|
||||
path = "chapters/042-main-et-exitcode.md"
|
||||
sha256 = "c8466a02c19df25d3a792fc289e774f1f4f790137389b6c9e0a9905f0cf28bcc"
|
||||
|
||||
[[modified]]
|
||||
path = "chapters/043-documentation-et-tests-de-conformite.md"
|
||||
sha256 = "3769820873793f73f75030c0d54c8194cbdc2a9a0428ccfd6707e3284f194003"
|
||||
|
||||
[[modified]]
|
||||
path = "chapters/048-inventaire-des-points-v1-encore-ouverts.md"
|
||||
sha256 = "3c99a2d2901e5843b4ea40b26c541203c907a809ad2004fd93c0ad4a94a68413"
|
||||
sha256 = "908856acb0472c2c4eee3d03b8260f21b5b6495d342053f371b00e54158ed2d1"
|
||||
|
||||
[[modified]]
|
||||
path = "chapters/051-invariants-de-conception.md"
|
||||
sha256 = "05c23658ea2b127c023b5d75630bd79096934d21f04f67f01375486fd35386e4"
|
||||
sha256 = "c41f6c977c613631147b7d61c837afccc9b1c6807d62ade8175865f5108bf915"
|
||||
|
||||
[[modified]]
|
||||
path = "examples/002-principes-generaux-du-langage-examples.md"
|
||||
sha256 = "42b5758d733563c0bdabad9f6005f5818ccb42513e599bc878142db6b4298e10"
|
||||
|
||||
[[modified]]
|
||||
path = "examples/004-couches-de-lecosysteme-v1-examples.md"
|
||||
sha256 = "3b37dee80e15c28fde237d208da3b16885c3190603f074b3bf4fabc21cda13e8"
|
||||
sha256 = "2731f6e5861d041801bf831a936c59c6df854ac55b858500e32542e64105bb8a"
|
||||
|
||||
[[modified]]
|
||||
path = "examples/013-interfaces-examples.md"
|
||||
sha256 = "2338543b0551c291dea59ebbd394a35d9e560d817b9e2d92eaa62c02d6ee3bd0"
|
||||
|
||||
[[modified]]
|
||||
path = "examples/015-fonctions-methodes-et-clsmethod-examples.md"
|
||||
sha256 = "0760c83e732d77942b48339135a146d98a60f6dd2c60fc06bc8b093fdf026058"
|
||||
|
||||
[[modified]]
|
||||
path = "examples/018-result-erreurs-et-exceptions-examples.md"
|
||||
sha256 = "47f50de6f6bf327e9f00de9a5a4e9470839d6e5e4d0ee570e432441d2924c6bb"
|
||||
|
||||
[[modified]]
|
||||
path = "examples/020-operateurs-examples.md"
|
||||
sha256 = "717035959ea34130d7eeed2af8d3945afb10772b3015f6031c4462494076fec3"
|
||||
|
||||
[[modified]]
|
||||
path = "examples/021-strings-unicode-et-encodages-examples.md"
|
||||
sha256 = "e065baa54cd9203f9b37883f5c418baea27ffc0fe4d28e97ff349a1b66f8adc7"
|
||||
sha256 = "6ed3cd078599b329b5f8f42ceda323eadc954f3d7d566e177adca56451a2345b"
|
||||
|
||||
[[modified]]
|
||||
path = "examples/022-collections-et-iteration-examples.md"
|
||||
sha256 = "86749fa6c85fbfbc2cd18643ad1da639af76222845ebf4418e62f7744cb76003"
|
||||
sha256 = "f3546d35335937506044a697ff1610da20823bf29334c307d6cf7a53122d8ce3"
|
||||
|
||||
[[modified]]
|
||||
path = "examples/037-dependances-et-scopes-examples.md"
|
||||
sha256 = "a384f5a4c624f75f7a52186c731fc95890fb0ee5067788b4f93b90b0989774e1"
|
||||
path = "examples/024-casts-et-conversions-examples.md"
|
||||
sha256 = "47a4d0e0e7fd822995be140d62432f48642da237d026551fc922f011776d1b8b"
|
||||
|
||||
[[modified]]
|
||||
path = "examples/048-inventaire-des-points-v1-encore-ouverts-examples.md"
|
||||
sha256 = "069383c40e74b495cdd3ccbebd87850654fa1ef4b6095e93a4eab14acb5d1f3d"
|
||||
path = "examples/026-async-et-concurrence-examples.md"
|
||||
sha256 = "0a206a6b7ee2818a1e743b0dc1a033b27ebd75f543b9979d9c7fa37150c30255"
|
||||
|
||||
[[modified]]
|
||||
path = "examples/051-invariants-de-conception-examples.md"
|
||||
sha256 = "307da7506d8411f033cfcfbf5fc555651175e28e64119e248a1c4d341afa487f"
|
||||
path = "examples/027-memoire-references-et-unsafe-examples.md"
|
||||
sha256 = "acadba49f317caa4805e8770c5732a029071559921a6c0a05281cfb026ef98e6"
|
||||
|
||||
[[modified]]
|
||||
path = "examples/028-defer-et-nettoyage-examples.md"
|
||||
sha256 = "121e51d8cef0c2de89005d895aa05dfb8c52e9c69991dac411d1ceb7dbb00b05"
|
||||
|
||||
[[modified]]
|
||||
path = "examples/041-artifacts-exports-profils-et-reservation-des-formats-futurs-examples.md"
|
||||
sha256 = "673a51f5c919b22ab1ec72b95f79ce17afd64ab0ec70bfaba260fc245a1f51d2"
|
||||
|
||||
@@ -1,32 +1,29 @@
|
||||
# Saselang — Annexe A — Matrice des conversions numériques
|
||||
|
||||
**Version documentaire : 0.2.12. Statut : inventaire de conception Core, destiné à devenir normatif après validation.**
|
||||
**Version documentaire : 0.2.17. Statut : inventaire de conception Core destiné à devenir normatif après validation.**
|
||||
|
||||
Cette annexe est le listing exhaustif de travail des conversions numériques Core.
|
||||
Son objectif est d'énumérer le maximum de conversions numériques sémantiquement distinctes sans introduire d'alias ou de doublons inutiles.
|
||||
Cette annexe inventorie les conversions numériques Core sémantiquement distinctes sans créer d'alias ou de doublons inutiles.
|
||||
|
||||
## A.1. Répartition des responsabilités
|
||||
|
||||
Les conversions numériques sont exposées comme capacités de l'API Core des primitives. Elles ne deviennent pas chacune une construction grammaticale du compilateur.
|
||||
Les conversions numériques sont des capacités de l'API Core des primitives, pas des constructions grammaticales distinctes.
|
||||
|
||||
```text
|
||||
Bible langage / compilateur
|
||||
définit les règles de typage, d'appel, d'intrinsic, de target et de lowering
|
||||
définit typage, contrats, faults, targets et lowering
|
||||
|
||||
Core
|
||||
expose les membres numériques concrets
|
||||
ex. int32::tryToInt8(), float64::tryRoundToFloat32()
|
||||
ex. int32::toInt8(), float64::roundToFloat32()
|
||||
|
||||
Annexe Core
|
||||
liste exhaustivement les opérations disponibles par paire de types
|
||||
liste les opérations disponibles par paire de types
|
||||
|
||||
Compilateur / Sase IR / backend
|
||||
valide et abaisse l'opération Core sans que chaque nom devienne de la grammaire
|
||||
valide et abaisse les opérations Core
|
||||
```
|
||||
|
||||
Une capacité Core peut être conditionnée par un target ou une plateforme lorsque cela est réellement nécessaire. L'absence d'une capacité demandée doit être diagnostiquée à la compilation pour le target choisi, et non découverte tardivement dans le backend.
|
||||
|
||||
Les conversions numériques fondamentales entre primitives standard sont destinées à constituer le socle Core commun ; le mécanisme de capacités existe surtout pour les opérations qui ne peuvent raisonnablement pas être garanties partout.
|
||||
Si les types source et destination sont supportés par un target, les conversions fondamentales non redondantes sont Core-required. Une implémentation logicielle conforme est admise lorsqu'une instruction matérielle n'existe pas.
|
||||
|
||||
## A.2. Règle de non-redondance
|
||||
|
||||
@@ -34,68 +31,86 @@ Une variante n'existe que si elle apporte une sémantique observable différente
|
||||
|
||||
Exemple :
|
||||
|
||||
```saselang
|
||||
```text
|
||||
int8 value = ...;
|
||||
int32 larger = value::toInt32();
|
||||
```
|
||||
|
||||
Puisque toutes les valeurs `int8` sont représentables exactement dans `int32`, les formes suivantes n'ont aucune raison d'exister :
|
||||
Toutes les valeurs `int8` sont exactement représentables dans `int32`; il n'existe donc pas de variantes inutiles `saturateToInt32()` ou `wrapToInt32()`.
|
||||
|
||||
Pour `int32 -> int8`, les trois contrats suivants sont distincts :
|
||||
|
||||
```text
|
||||
tryToInt32()
|
||||
saturateToInt32()
|
||||
wrapToInt32()
|
||||
toInt8() // exact, peut fault OutOfRange
|
||||
saturateToInt8()
|
||||
wrapToInt8()
|
||||
```
|
||||
|
||||
En revanche, pour `int32 -> int8`, `tryToInt8()`, `saturateToInt8()` et `wrapToInt8()` ont trois contrats différents et peuvent coexister.
|
||||
|
||||
|
||||
Une règle de composition complète cette non-redondance :
|
||||
Règle de composition :
|
||||
|
||||
> Deux opérations ne sont fusionnées dans un même nom que si leur séparation en opérations Core successives modifierait la sémantique, perdrait de l'information ou empêcherait d'exprimer le même contrat.
|
||||
|
||||
Ainsi `value::floor()::tryToInt32()` rend inutile un alias `tryFloorToInt32()` si les deux formes sont strictement équivalentes.
|
||||
Ainsi :
|
||||
|
||||
## A.3. Nomenclature générale
|
||||
```text
|
||||
value::floor()::toInt32()
|
||||
```
|
||||
|
||||
rend inutile un alias `floorToInt32()` si les deux formes sont strictement équivalentes.
|
||||
|
||||
## A.3. Canal d'échec V1
|
||||
|
||||
Les anciennes variantes `try... -> Result<T,NumericConversionError>` ne font plus partie de la matrice canonique uniquement pour transporter un échec de conversion.
|
||||
|
||||
La conversion directe retourne la destination attendue et peut déclarer :
|
||||
|
||||
```text
|
||||
faults NumericConversionFault
|
||||
```
|
||||
|
||||
lorsque sa précondition runtime n'est pas totale.
|
||||
|
||||
`NumericConversionFault` est unchecked et capturable. Une API spécialisée peut toujours choisir explicitement `Result` si son domaine veut représenter l'échec comme une valeur normale, mais cela ne crée pas une seconde famille automatique `try...` dans le Core numérique.
|
||||
|
||||
## A.4. Nomenclature générale
|
||||
|
||||
| Code | Famille | Contrat |
|
||||
|---|---|---|
|
||||
| `T` | `toTarget()` | Exacte et totale pour toutes les valeurs valides du type source. |
|
||||
| `E` | `tryToTarget()` | Exacte pour la valeur courante ; retourne `Err` si l'exactitude ou la représentabilité échoue. |
|
||||
| `R` | `roundToTarget()` | Perte de précision explicitement acceptée ; conversion totale pour cette paire de types. |
|
||||
| `TR` | `tryRoundToTarget()` | Arrondi explicitement accepté, mais la valeur peut être hors du domaine destination. |
|
||||
| `S` | `saturateToTarget()` | Conversion totale par saturation lorsqu'aucun arrondi supplémentaire n'est nécessaire. |
|
||||
| `SR` | `saturatingRoundToTarget()` | Arrondi canonique + saturation explicites pour une destination flottante lorsque les deux peuvent être nécessaires. |
|
||||
| `W` | `wrapToTarget()` | Conversion entière modulo `2^N`, avec interprétation selon le type entier destination. |
|
||||
| `E` | `toTarget()` | Exacte pour la valeur courante ; `faults NumericConversionFault` si impossible. |
|
||||
| `R` | `roundToTarget()` | Perte de précision explicitement acceptée ; totale pour cette paire. |
|
||||
| `FR` | `roundToTarget()` | Arrondi accepté ; peut fault si la valeur est hors du domaine destination. |
|
||||
| `S` | `saturateToTarget()` | Saturation explicite lorsqu'aucun arrondi supplémentaire n'est nécessaire. |
|
||||
| `SR` | `saturatingRoundToTarget()` | Arrondi canonique + saturation explicites. |
|
||||
| `W` | `wrapToTarget()` | Conversion entière modulo `2^N`. |
|
||||
| `—` | aucune | Même type ou opération sans sémantique distincte utile. |
|
||||
|
||||
`NumericConversionError` est retenu comme nom de travail Core. Il pourra être renommé avant stabilisation de la spécification si nécessaire.
|
||||
Aucune de ces opérations n'autorise une conversion implicite entre deux valeurs déjà typées.
|
||||
|
||||
Les formes `try...` retournent conceptuellement :
|
||||
|
||||
```saselang
|
||||
Result<Target, NumericConversionError>
|
||||
```
|
||||
|
||||
Aucune de ces opérations n'autorise une conversion implicite entre deux variables déjà typées.
|
||||
|
||||
## A.4. Flottants : hypothèses de représentation
|
||||
## A.5. Flottants : hypothèses de représentation
|
||||
|
||||
| Type | Précision significative `p` | Exposant maximal fini |
|
||||
|---|---|---|
|
||||
|---|---:|---:|
|
||||
| `float16` | 11 bits | 15 |
|
||||
| `float32` | 24 bits | 127 |
|
||||
| `float64` | 53 bits | 1023 |
|
||||
| `float128` | 113 bits | 16383 |
|
||||
|
||||
Les conversions avec arrondi utilisent par défaut la règle canonique **round to nearest, ties to even**. Cette règle ne dépend ni du linter, ni du profil, ni du backend.
|
||||
Les conversions avec arrondi utilisent la règle canonique **round to nearest, ties to even**. Cette règle ne dépend ni du linter, ni du profil, ni du backend.
|
||||
|
||||
## A.5. Entier -> entier
|
||||
## A.6. Entier -> entier
|
||||
|
||||
Légende :
|
||||
|
||||
- `T` = `toTarget()` uniquement ;
|
||||
- `E+S+W` = `tryToTarget()` + `saturateToTarget()` + `wrapToTarget()`.
|
||||
```text
|
||||
T
|
||||
toTarget() total
|
||||
|
||||
E+S+W
|
||||
toTarget() faults OutOfRange
|
||||
saturateToTarget()
|
||||
wrapToTarget()
|
||||
```
|
||||
|
||||
| Source \ Destination | int8 | int16 | int32 | int64 | int128 | int256 | uint8 | uint16 | uint32 | uint64 | uint128 | uint256 |
|
||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
||||
@@ -114,95 +129,104 @@ Légende :
|
||||
|
||||
Règles :
|
||||
|
||||
- si le domaine source est entièrement inclus dans le domaine destination, seule la forme `to...` existe ;
|
||||
- sinon `tryTo...` effectue une conversion exacte conditionnelle ;
|
||||
- `saturateTo...` borne à `Target::Min` / `Target::Max` ; pour un signé vers non signé, toute valeur négative sature à `0` ;
|
||||
- `wrapTo...` utilise une définition mathématique modulo `2^N`, indépendante de la représentation machine du backend ;
|
||||
- domaine source entièrement inclus -> `to...` total ;
|
||||
- sinon `to...` reste exact mais peut produire `OutOfRange` ;
|
||||
- `saturateTo...` borne à `Target::Min` / `Target::Max`, avec `0` pour un négatif vers non signé ;
|
||||
- `wrapTo...` utilise une définition mathématique modulo `2^N` ;
|
||||
- aucun wrapping ni saturation n'est implicite.
|
||||
|
||||
## A.6. Entier -> flottant
|
||||
## A.7. Entier -> flottant
|
||||
|
||||
Légende :
|
||||
|
||||
- `T` = `toFloatXX()` uniquement ;
|
||||
- `E+R` = `tryToFloatXX()` + `roundToFloatXX()` ;
|
||||
- `E+TR+SR` = `tryToFloatXX()` + `tryRoundToFloatXX()` + `saturatingRoundToFloatXX()`.
|
||||
```text
|
||||
T
|
||||
toFloatXX() total et exact
|
||||
|
||||
E+R
|
||||
toFloatXX() exact, peut fault Inexact
|
||||
roundToFloatXX() total
|
||||
|
||||
E+FR+SR
|
||||
toFloatXX() exact, peut fault Inexact/OutOfRange
|
||||
roundToFloatXX() peut fault OutOfRange
|
||||
saturatingRoundToFloatXX() total
|
||||
```
|
||||
|
||||
| Source \ Destination | float16 | float32 | float64 | float128 |
|
||||
|---|---|---|---|---|
|
||||
| int8 | T | T | T | T |
|
||||
| int16 | E+R | T | T | T |
|
||||
| int32 | E+TR+SR | E+R | T | T |
|
||||
| int64 | E+TR+SR | E+R | E+R | T |
|
||||
| int128 | E+TR+SR | E+R | E+R | E+R |
|
||||
| int256 | E+TR+SR | E+TR+SR | E+R | E+R |
|
||||
| int32 | E+FR+SR | E+R | T | T |
|
||||
| int64 | E+FR+SR | E+R | E+R | T |
|
||||
| int128 | E+FR+SR | E+R | E+R | E+R |
|
||||
| int256 | E+FR+SR | E+FR+SR | E+R | E+R |
|
||||
| uint8 | T | T | T | T |
|
||||
| uint16 | E+TR+SR | T | T | T |
|
||||
| uint32 | E+TR+SR | E+R | T | T |
|
||||
| uint64 | E+TR+SR | E+R | E+R | T |
|
||||
| uint128 | E+TR+SR | E+TR+SR | E+R | E+R |
|
||||
| uint256 | E+TR+SR | E+TR+SR | E+R | E+R |
|
||||
| uint16 | E+FR+SR | T | T | T |
|
||||
| uint32 | E+FR+SR | E+R | T | T |
|
||||
| uint64 | E+FR+SR | E+R | E+R | T |
|
||||
| uint128 | E+FR+SR | E+FR+SR | E+R | E+R |
|
||||
| uint256 | E+FR+SR | E+FR+SR | E+R | E+R |
|
||||
|
||||
Contrats :
|
||||
Exemple :
|
||||
|
||||
- `toFloatXX()` existe seulement si **toute** valeur source est exactement représentable ;
|
||||
- `tryToFloatXX()` exige une représentation exacte de la valeur courante ;
|
||||
- `roundToFloatXX()` existe seulement lorsque toute valeur source reste dans le domaine fini destination, mais qu'une perte de précision peut être nécessaire ;
|
||||
- `tryRoundToFloatXX()` accepte l'arrondi canonique mais retourne `Err` si la magnitude finie dépasse le domaine destination ;
|
||||
- `saturatingRoundToFloatXX()` est réservé aux paires pour lesquelles un débordement de domaine est possible : une valeur finie trop grande est bornée au plus grand fini de même signe, puis la précision destination s'applique selon l'arrondi canonique ;
|
||||
- il n'existe pas de `wrapToFloatXX()`.
|
||||
|
||||
Exemple distinct :
|
||||
|
||||
```saselang
|
||||
```text
|
||||
int64 value = ...;
|
||||
|
||||
Result<float64, NumericConversionError> exact = value::tryToFloat64();
|
||||
float64 exact = value::toFloat64();
|
||||
float64 approximated = value::roundToFloat64();
|
||||
```
|
||||
|
||||
`tryToFloat64()` et `roundToFloat64()` ne sont pas des alias : le premier refuse toute perte de précision, le second l'accepte explicitement.
|
||||
La première opération exige l'exactitude et peut produire `NumericConversionFault::Inexact`; la seconde accepte explicitement la perte de précision.
|
||||
|
||||
## A.7. Flottant -> flottant
|
||||
## A.8. Flottant -> flottant
|
||||
|
||||
Légende :
|
||||
|
||||
- `T` = `toFloatXX()` uniquement ;
|
||||
- `E+TR+SR` = `tryToFloatXX()` + `tryRoundToFloatXX()` + `saturatingRoundToFloatXX()`.
|
||||
```text
|
||||
T
|
||||
toFloatXX() total et exact
|
||||
|
||||
E+FR+SR
|
||||
toFloatXX() exact, peut fault
|
||||
roundToFloatXX() accepte l'arrondi, peut fault OutOfRange fini
|
||||
saturatingRoundToFloatXX() total
|
||||
```
|
||||
|
||||
| Source \ Destination | float16 | float32 | float64 | float128 |
|
||||
|---|---|---|---|---|
|
||||
| float16 | — | T | T | T |
|
||||
| float32 | E+TR+SR | — | T | T |
|
||||
| float64 | E+TR+SR | E+TR+SR | — | T |
|
||||
| float128 | E+TR+SR | E+TR+SR | E+TR+SR | — |
|
||||
| float32 | E+FR+SR | — | T | T |
|
||||
| float64 | E+FR+SR | E+FR+SR | — | T |
|
||||
| float128 | E+FR+SR | E+FR+SR | E+FR+SR | — |
|
||||
|
||||
Règles :
|
||||
|
||||
- l'élargissement de format est exact au niveau de la valeur IEEE et utilise uniquement `toFloatXX()` ;
|
||||
- la réduction de format propose `tryToFloatXX()` pour exiger l'exactitude, `tryRoundToFloatXX()` pour accepter la perte de précision mais pas le débordement fini, et `saturatingRoundToFloatXX()` pour obtenir une opération totale sur le domaine flottant ;
|
||||
- `NaN`, `+Infinity`, `-Infinity`, `+0` et `-0` restent des catégories IEEE valides dans la destination ;
|
||||
- pour `NaN`, seule la propriété sémantique `isNaN(destination) == true` est garantie ; payload, signe et quiet/signaling bit ne sont pas garantis par une conversion de valeur ;
|
||||
- `tryToFloatXX()` accepte `NaN` et les infinities lorsque la destination est un type flottant Saselang, car ces catégories y sont représentables ;
|
||||
- `saturatingRoundToFloatXX()` ne transforme pas une infinité en valeur finie puisque l'infinité est elle-même représentable dans le format destination ; la saturation explicite concerne les valeurs **finies** hors du domaine fini destination ;
|
||||
- la conservation exacte d'une représentation binaire relève d'un contrat binaire distinct et de `bitcast` lorsque ses propres contraintes sont compatibles.
|
||||
- l'élargissement de format utilise `toFloatXX()` total ;
|
||||
- la réduction exacte utilise `toFloatXX()` avec fault si nécessaire ;
|
||||
- `roundToFloatXX()` accepte la perte de précision mais pas un débordement fini ;
|
||||
- `saturatingRoundToFloatXX()` sature seulement les valeurs finies hors domaine fini ;
|
||||
- `NaN`, `+Infinity`, `-Infinity`, `+0` et `-0` restent des catégories valides ;
|
||||
- pour `NaN`, seule la propriété sémantique `isNaN(destination) == true` est garantie.
|
||||
|
||||
## A.8. Flottant -> entier : composition des politiques
|
||||
|
||||
Il n'existe jamais de simple `toIntXX()` ou `toUintXX()` depuis un flottant.
|
||||
## A.9. Flottant -> entier : composition des politiques
|
||||
|
||||
La conversion stricte canonique est :
|
||||
|
||||
```text
|
||||
tryToIntXX()
|
||||
tryToUintXX()
|
||||
toIntXX()
|
||||
toUintXX()
|
||||
```
|
||||
|
||||
Elle réussit uniquement si la valeur flottante est finie, mathématiquement entière, dans le domaine de la destination et exactement représentable comme entier destination. Sinon elle retourne `Err(NumericConversionError(...))`.
|
||||
avec :
|
||||
|
||||
### A.8.1. Politiques mathématiques séparées
|
||||
```text
|
||||
faults NumericConversionFault
|
||||
```
|
||||
|
||||
Les opérations Core :
|
||||
lorsque la valeur peut être non finie, non entière ou hors plage.
|
||||
|
||||
### A.9.1. Politiques mathématiques séparées
|
||||
|
||||
```text
|
||||
floor()
|
||||
@@ -211,67 +235,56 @@ round()
|
||||
truncate()
|
||||
```
|
||||
|
||||
restent des opérations sur le flottant et définissent chacune une politique mathématique unique.
|
||||
restent des opérations sur le flottant. Elles se composent ensuite avec la conversion :
|
||||
|
||||
Elles se composent ensuite avec les conversions :
|
||||
|
||||
```saselang
|
||||
value::floor()::tryToInt32()
|
||||
value::ceil()::tryToInt32()
|
||||
value::round()::tryToInt32()
|
||||
value::truncate()::tryToInt32()
|
||||
```text
|
||||
value::floor()::toInt32()
|
||||
value::ceil()::toInt32()
|
||||
value::round()::toInt32()
|
||||
value::truncate()::toInt32()
|
||||
```
|
||||
|
||||
Cette composition remplace les alias redondants `tryFloorTo...`, `tryCeilTo...`, `tryRoundTo...` et `tryTruncateTo...`.
|
||||
Aucun alias combiné n'est ajouté lorsqu'il serait strictement équivalent.
|
||||
|
||||
`round()` utilise la règle canonique **nearest, ties to even**.
|
||||
|
||||
### A.8.2. Dépassement de domaine
|
||||
|
||||
Les politiques de dépassement restent séparées de la politique mathématique.
|
||||
### A.9.2. Dépassement de domaine
|
||||
|
||||
Pour chaque destination entière, le Core peut exposer :
|
||||
|
||||
```text
|
||||
tryToTarget()
|
||||
trySaturateToTarget()
|
||||
tryWrapToTarget()
|
||||
toTarget()
|
||||
saturateToTarget()
|
||||
wrapToTarget()
|
||||
```
|
||||
|
||||
avec les contrats suivants :
|
||||
|
||||
| Opération | Préconditions non liées à la plage | Politique de plage |
|
||||
| Opération | Préconditions hors plage | Politique de plage |
|
||||
|---|---|---|
|
||||
| `tryToTarget()` | valeur finie et mathématiquement entière | `Err` si hors plage |
|
||||
| `trySaturateToTarget()` | valeur finie et mathématiquement entière | borne à `Target::Min` / `Target::Max` |
|
||||
| `tryWrapToTarget()` | valeur finie et mathématiquement entière | modulo `2^N` selon le type entier destination |
|
||||
| `toTarget()` | valeur finie et mathématiquement entière | `OutOfRange` si hors plage |
|
||||
| `saturateToTarget()` | valeur finie et mathématiquement entière | borne à `Target::Min` / `Target::Max` |
|
||||
| `wrapToTarget()` | valeur finie et mathématiquement entière | modulo `2^N` |
|
||||
|
||||
Les politiques se composent :
|
||||
`NotFinite` et `NotIntegral` restent possibles pour les trois familles lorsqu'elles s'appliquent.
|
||||
|
||||
```saselang
|
||||
value::floor()::trySaturateToInt32()
|
||||
value::round()::trySaturateToUint16()
|
||||
Exemples :
|
||||
|
||||
value::truncate()::tryWrapToInt8()
|
||||
value::ceil()::tryWrapToUint64()
|
||||
```text
|
||||
value::floor()::saturateToInt32()
|
||||
value::round()::saturateToUint16()
|
||||
value::truncate()::wrapToInt8()
|
||||
value::ceil()::wrapToUint64()
|
||||
```
|
||||
|
||||
Il n'existe pas de variantes combinées telles que `trySaturatingFloorToInt32()` ou `tryWrappingRoundToInt32()` lorsque la composition ci-dessus possède exactement la même sémantique.
|
||||
|
||||
### A.8.3. Matrice flottant -> entier après élimination des doublons
|
||||
|
||||
Pour chaque paire, la matrice conserve uniquement les politiques dont le résultat peut réellement différer sur une valeur source admissible.
|
||||
### A.9.3. Matrice flottant -> entier après élimination des doublons
|
||||
|
||||
Légende :
|
||||
|
||||
```text
|
||||
C
|
||||
tryToTarget() uniquement
|
||||
toTarget() uniquement
|
||||
|
||||
CSW
|
||||
tryToTarget()
|
||||
trySaturateToTarget()
|
||||
tryWrapToTarget()
|
||||
toTarget()
|
||||
saturateToTarget()
|
||||
wrapToTarget()
|
||||
```
|
||||
|
||||
| Source \ Destination | int8 | int16 | int32 | int64 | int128 | int256 | uint8 | uint16 | uint32 | uint64 | uint128 | uint256 |
|
||||
@@ -281,75 +294,37 @@ CSW
|
||||
| float64 | CSW | CSW | CSW | CSW | CSW | CSW | CSW | CSW | CSW | CSW | CSW | CSW |
|
||||
| float128 | CSW | CSW | CSW | CSW | CSW | CSW | CSW | CSW | CSW | CSW | CSW | CSW |
|
||||
|
||||
Justification :
|
||||
|
||||
- toutes les valeurs finies et mathématiquement entières de `float16` tiennent dans `int32` et les entiers signés plus larges ; saturation et wrapping n'apportent donc rien pour ces paires ;
|
||||
- toutes les valeurs finies et mathématiquement entières de `float32` tiennent dans `int256`, mais pas dans `int128` ou plus petit ;
|
||||
- pour toute destination non signée, les valeurs négatives rendent checked, saturation et wrapping distincts, même lorsque toute magnitude positive finie tient dans la destination ;
|
||||
- `float64` et `float128` disposent de valeurs finies dépassant le domaine de tous les entiers Saselang V1.
|
||||
|
||||
Cas particuliers :
|
||||
|
||||
- `+0` et `-0` donnent l'entier zéro ;
|
||||
- `NaN`, `+Infinity` et `-Infinity` échouent dans ces familles car ils ne satisfont pas la précondition de valeur finie et mathématiquement entière ;
|
||||
- pour une destination non signée, la saturation d'une valeur négative entière donne `0` ;
|
||||
- pour une destination signée, la saturation utilise `Target::Min` / `Target::Max` ;
|
||||
- le wrapping est appliqué au résultat entier mathématique fini selon modulo `2^N`.
|
||||
- `+0` et `-0` donnent zéro ;
|
||||
- `NaN` et les infinities produisent `NotFinite` ;
|
||||
- une valeur fractionnaire produit `NotIntegral` avant la politique de plage ;
|
||||
- vers un non signé, la saturation d'une valeur négative entière donne `0` ;
|
||||
- le wrapping s'applique à l'entier mathématique fini modulo `2^N`.
|
||||
|
||||
## A.9. `bitcast` reste hors de cette matrice
|
||||
## A.10. `bitcast` reste hors de cette matrice
|
||||
|
||||
`bitcast<T>(value)` n'est pas une conversion numérique. Il conserve les bits et change leur interprétation sous les contraintes de taille et de validité déjà définies par le langage.
|
||||
`bitcast<T>(value)` conserve les bits et change leur interprétation sous ses propres contraintes. Il ne constitue jamais une alternative implicite à `to...`, `round...`, `saturate...` ou `wrap...`.
|
||||
|
||||
Il ne constitue jamais une alternative implicite à `to...`, `try...`, `round...`, `saturate...` ou `wrap...`.
|
||||
|
||||
## A.10. Typage contextuel des littéraux
|
||||
## A.11. Typage contextuel des littéraux
|
||||
|
||||
Le typage contextuel d'un littéral reste distinct de toute conversion de valeur déjà typée.
|
||||
|
||||
```saselang
|
||||
int32 a = 42; // contextualisation du littéral
|
||||
```text
|
||||
int32 a = 42;
|
||||
|
||||
int8 small = ...;
|
||||
int32 b = small; // ERROR : pas de conversion implicite
|
||||
int32 b = small; // ERROR
|
||||
int32 c = small::toInt32(); // OK
|
||||
```
|
||||
|
||||
## A.11. Core, targets et capacités
|
||||
|
||||
Les membres de conversion appartiennent au Core des primitives. Le compilateur doit pouvoir reconnaître leur contrat via les métadonnées/Core intrinsics nécessaires sans transformer chaque membre en syntaxe spéciale.
|
||||
|
||||
Pour les conversions fondamentales de cette matrice :
|
||||
|
||||
> si les types source et destination sont supportés par le target, les opérations non redondantes définies par la matrice sont Core-required.
|
||||
|
||||
L'absence d'une instruction matérielle native ne rend pas l'opération optionnelle lorsqu'une émulation logicielle conforme est raisonnablement possible.
|
||||
|
||||
Un target réduit peut ne pas exposer un type fondamental donné. Dans ce cas, l'indisponibilité doit porter sur le type/capacité fondamentale, pas sur une sélection arbitraire de ses conversions.
|
||||
|
||||
La nomenclature générale des capabilities et leurs niveaux sont définis au chapitre 40.
|
||||
|
||||
## A.12. Hiérarchie documentaire cible
|
||||
|
||||
La documentation Saselang est destinée à être organisée par niveaux :
|
||||
## A.12. `NumericConversionFault`
|
||||
|
||||
```text
|
||||
Language / Compiler Specification
|
||||
ce que le compilateur doit accepter, refuser et produire
|
||||
|
||||
Saselang + Core Specification
|
||||
langage + environnement Core normatif
|
||||
|
||||
Saselang Platform Documentation
|
||||
langage + Core + SDKs + extensions de plateforme
|
||||
NumericConversionFault extends Fault
|
||||
```
|
||||
|
||||
Depuis `0.2.12`, la Bible est distribuée sous forme d'une archive multifichier structurée avec sommaire, chapitres séparés, exemples/DO-DON'T par chapitre et annexes référencées.
|
||||
|
||||
## A.13. `NumericConversionError`
|
||||
|
||||
`NumericConversionError` est le nom de travail du `ResultError` Core des conversions récupérables.
|
||||
|
||||
Les codes sémantiques V1 sont :
|
||||
Codes sémantiques V1 :
|
||||
|
||||
```text
|
||||
NotFinite
|
||||
@@ -358,19 +333,20 @@ OutOfRange
|
||||
Inexact
|
||||
```
|
||||
|
||||
L'erreur reste minimale et ne transporte pas automatiquement la valeur source, les types source/destination, le backend, un timestamp ou un mode d'arrondi.
|
||||
Le fault reste minimal et ne transporte pas automatiquement la valeur source, les types source/destination, le backend, un timestamp ou un mode d'arrondi.
|
||||
|
||||
## A.14. État de l'annexe
|
||||
## A.13. État de l'annexe
|
||||
|
||||
Les principes sémantiques de la matrice sont désormais largement figés :
|
||||
Principes largement figés :
|
||||
|
||||
```text
|
||||
non-redondance par paire
|
||||
composition plutôt qu'alias combinés
|
||||
Fault direct à la place des anciens try... purement mécaniques
|
||||
règles float -> integer
|
||||
règles NaN / infinities / signed zero
|
||||
NumericConversionError
|
||||
disponibilité Core pour les types supportés
|
||||
NumericConversionFault
|
||||
Core-required pour les types supportés
|
||||
émulation logicielle lorsque raisonnable
|
||||
```
|
||||
|
||||
@@ -378,5 +354,5 @@ Restent principalement à auditer lors de l'implémentation Core :
|
||||
|
||||
1. le listing mécanique exhaustif des membres concrets exposés par chaque primitive ;
|
||||
2. les noms définitifs des constantes/membres Core associés ;
|
||||
3. la représentation interne exacte des codes `NumericConversionError` ;
|
||||
3. la représentation interne exacte des codes `NumericConversionFault` ;
|
||||
4. les tests de conformité couvrant toutes les cellules de la matrice.
|
||||
|
||||
@@ -9,8 +9,9 @@ Elle applique les mêmes principes que la matrice numérique :
|
||||
```text
|
||||
aucune conversion implicite
|
||||
aucun mélange de types dans les opérations textuelles
|
||||
to... uniquement pour une conversion totale et sûre
|
||||
tryFrom... / tryTo... lorsqu'une validation ou une condition peut échouer
|
||||
conversion directe vers la valeur attendue
|
||||
faults UnicodeEncodingFault lorsqu'une validation runtime peut échouer
|
||||
aucune variante try... parallèle si elle ne change que le canal d'échec
|
||||
aucun alias redondant
|
||||
conversion explicite d'abord, opération ensuite
|
||||
```
|
||||
@@ -106,8 +107,8 @@ Ces transcodages sont totaux.
|
||||
UTF-8 :
|
||||
|
||||
```text
|
||||
Utf8Char::tryFrom(uint8)
|
||||
Utf8Char::tryFrom(StaticArray<uint8, N>)
|
||||
Utf8Char::from(uint8) faults UnicodeEncodingFault
|
||||
Utf8Char::from(StaticArray<uint8, N>) faults UnicodeEncodingFault
|
||||
```
|
||||
|
||||
`N` utile : 1 à 4. Le contenu doit représenter exactement un scalar UTF-8 valide.
|
||||
@@ -115,8 +116,8 @@ Utf8Char::tryFrom(StaticArray<uint8, N>)
|
||||
UTF-16 :
|
||||
|
||||
```text
|
||||
Utf16Char::tryFrom(uint16)
|
||||
Utf16Char::tryFrom(StaticArray<uint16, 2>)
|
||||
Utf16Char::from(uint16) faults UnicodeEncodingFault
|
||||
Utf16Char::from(StaticArray<uint16, 2>) faults UnicodeEncodingFault
|
||||
```
|
||||
|
||||
Un surrogate isolé est invalide.
|
||||
@@ -124,7 +125,7 @@ Un surrogate isolé est invalide.
|
||||
UTF-32 :
|
||||
|
||||
```text
|
||||
Utf32Char::tryFrom(uint32)
|
||||
Utf32Char::from(uint32) faults UnicodeEncodingFault
|
||||
```
|
||||
|
||||
La valeur doit être <= `0x10FFFF` et hors de la plage surrogate.
|
||||
@@ -132,15 +133,17 @@ La valeur doit être <= `0x10FFFF` et hors de la plage surrogate.
|
||||
Le nom de travail de l'erreur est :
|
||||
|
||||
```text
|
||||
UnicodeEncodingError extends ResultError
|
||||
UnicodeEncodingFault extends Fault
|
||||
```
|
||||
|
||||
Le Core ne fournit pas simultanément une variante `tryFrom... -> Result` ayant exactement la même validation. Si un domaine applicatif souhaite transporter l'échec comme valeur, il peut encapsuler explicitement la construction dans son propre `Result`.
|
||||
|
||||
## B.7. `UtfXChar` -> code unit brute
|
||||
|
||||
| Source | Destination | Opération | Raison |
|
||||
|---|---|---|---|
|
||||
| `Utf8Char` | `uint8` | `tryToUint8()` | 1 à 4 unités possibles |
|
||||
| `Utf16Char` | `uint16` | `tryToUint16()` | 1 ou 2 unités possibles |
|
||||
| `Utf8Char` | `uint8` | `toUint8() faults UnicodeEncodingFault` | 1 à 4 unités possibles |
|
||||
| `Utf16Char` | `uint16` | `toUint16() faults UnicodeEncodingFault` | 1 ou 2 unités possibles |
|
||||
| `Utf32Char` | `uint32` | `toUint32()` | exactement 1 unité |
|
||||
|
||||
Les séquences complètes de code units sont accessibles via `codeUnits()`. Le type concret de vue retourné sera fixé avec les collections/slices.
|
||||
@@ -176,9 +179,9 @@ Tous ces transcodages sont explicites et totaux.
|
||||
Conceptuellement :
|
||||
|
||||
```text
|
||||
Utf8String::tryFrom(Array<uint8>)
|
||||
Utf16String::tryFrom(Array<uint16>)
|
||||
Utf32String::tryFrom(Array<uint32>)
|
||||
Utf8String::from(Array<uint8>) faults UnicodeEncodingFault
|
||||
Utf16String::from(Array<uint16>) faults UnicodeEncodingFault
|
||||
Utf32String::from(Array<uint32>) faults UnicodeEncodingFault
|
||||
```
|
||||
|
||||
Le type exact accepté pourra inclure des slices/vues lors de leur définition.
|
||||
@@ -283,5 +286,5 @@ les opérations mutantes sont interdites via `text`, mais un autre alias mutable
|
||||
3. nom exact de l'API de décodage depuis un offset de code unit ;
|
||||
4. API précise de concaténation et ses opérateurs ;
|
||||
5. builders/buffers et leurs relations avec les strings valides ;
|
||||
6. codes définitifs de `UnicodeEncodingError` ;
|
||||
6. codes définitifs de `UnicodeEncodingFault` ;
|
||||
7. localisation Core/SDK des opérations Unicode avancées : graphemes, normalisation, case folding, collation.
|
||||
|
||||
@@ -22,6 +22,8 @@ Principe directeur :
|
||||
|
||||
> **boring but working** : une règle stable et prévisible vaut mieux qu'une syntaxe plus courte mais ambiguë.
|
||||
|
||||
Lorsqu'une forme légèrement plus longue supprime un implicite ou une ambiguïté réelle, Saselang privilégie l'explicite. La concision n'est pas un objectif supérieur à la lisibilité du contrat.
|
||||
|
||||
## 2.2 Mots-clés — V1 REQUIS — FIGÉ
|
||||
|
||||
Les mots-clés du langage sont en anglais.
|
||||
|
||||
@@ -17,7 +17,7 @@ unions
|
||||
tuples
|
||||
generics
|
||||
contrôle de flux
|
||||
erreurs/exceptions
|
||||
erreurs/exceptions/faults
|
||||
opérateurs
|
||||
unsafe
|
||||
scope
|
||||
@@ -42,6 +42,7 @@ Result<T,E>
|
||||
Error
|
||||
ResultError
|
||||
Exception
|
||||
Fault
|
||||
Option<T>
|
||||
Nullable<T>
|
||||
Range<T>
|
||||
@@ -50,10 +51,18 @@ RangeStep<T,Step>
|
||||
RangeReverse<T>
|
||||
RangeReverseStep<T,Step>
|
||||
RangeProgression<T,Step>
|
||||
PartialOrdering
|
||||
Ordering
|
||||
Comparable<T>
|
||||
Comparator<T>
|
||||
Op...
|
||||
Iterable<T>
|
||||
Iterator<T>
|
||||
View<T>
|
||||
Collection<T>
|
||||
List<T>
|
||||
Set<T>
|
||||
Map<K,V>
|
||||
Array<T>
|
||||
StaticArray<T,N>
|
||||
TypeInfo
|
||||
@@ -71,7 +80,7 @@ Une capacité Core peut être conditionnée par un target lorsqu'elle ne peut ra
|
||||
Le SDK fournit les fonctionnalités de bibliothèque qui ne justifient pas une sémantique spéciale du compilateur :
|
||||
|
||||
```text
|
||||
collections
|
||||
collections concrètes/spécialisées au-delà des contrats fondamentaux Core
|
||||
encodages explicites
|
||||
regex
|
||||
filesystem
|
||||
|
||||
@@ -49,6 +49,6 @@ Si tous les éléments permettent l'égalité pertinente, le tuple peut être co
|
||||
|
||||
Si tous les éléments sont comparables, l'ordre du tuple est lexicographique.
|
||||
|
||||
Si un composant comparé retourne `Ordering::Unordered`, le tuple est `Unordered`.
|
||||
Si un composant comparé retourne `PartialOrdering::Unordered`, le résultat de comparaison du tuple est `PartialOrdering::Unordered`.
|
||||
|
||||
---
|
||||
|
||||
@@ -41,10 +41,12 @@ type de retour
|
||||
visibilité
|
||||
fallibilité / Result
|
||||
throws
|
||||
contraintes génériques pertinentes
|
||||
qualification const et contraintes génériques pertinentes
|
||||
modificateurs contractuels pertinents
|
||||
```
|
||||
|
||||
`faults` reste visible dans la déclaration et dans la documentation, mais sa nature optionnelle/non exhaustive signifie qu'il n'impose pas la même compatibilité d'override que `throws`.
|
||||
|
||||
Les futurs pré/post-contrats formels, s'ils existent, devront également participer à cette notion.
|
||||
|
||||
## 13.5 Conflits d'héritage multiple — V1 REQUIS — FIGÉ
|
||||
|
||||
@@ -9,37 +9,42 @@ clsmethod méthode de classe
|
||||
operator implémentation d'un contrat opérateur
|
||||
```
|
||||
|
||||
## 15.2 Retours directs et `Result` — V1 REQUIS — FIGÉ
|
||||
## 15.2 Retours directs, `Result`, `throws` et `faults` — V1 REQUIS — FIGÉ
|
||||
|
||||
L'ancienne règle « toute fonction/méthode retourne `Result` » est supprimée.
|
||||
Le type de retour et le mécanisme d'échec sont des dimensions distinctes.
|
||||
|
||||
Règle V1 :
|
||||
Une callable peut retourner directement `T` même si elle peut produire une `Exception` checked ou un `Fault` unchecked :
|
||||
|
||||
```text
|
||||
opération infaillible
|
||||
-> retourne directement T
|
||||
func readConfig(String path) -> Config
|
||||
throws IOException
|
||||
|
||||
opération pouvant produire une erreur récupérable
|
||||
-> retourne Result<T>
|
||||
ou Result<T,E>
|
||||
method elementAt(uint64 index) -> T
|
||||
faults IndexOutOfBoundsFault
|
||||
```
|
||||
|
||||
Exemples infaillibles :
|
||||
`Result<T,E>` est utilisé lorsque l'échec doit être transporté explicitement comme une valeur et inspecté par l'appelant :
|
||||
|
||||
```text
|
||||
method length() -> uint64
|
||||
method containsKey(K key) -> bool
|
||||
Object::sameInstance(Object other) -> bool
|
||||
func min(int32 a, int32 b) -> int32
|
||||
func parseExternalInput(String input) -> Result<Value, ParseError>
|
||||
```
|
||||
|
||||
Exemples faillibles :
|
||||
Les combinaisons sont indépendantes :
|
||||
|
||||
```text
|
||||
func readFile(String path) -> Result<String, IoError>
|
||||
method parse(String input) -> Result<Value, ParseError>
|
||||
T
|
||||
T throws SomeException
|
||||
T faults SomeFault
|
||||
T throws SomeException faults SomeFault
|
||||
Result<T,E>
|
||||
Result<T,E> throws SomeException
|
||||
Result<T,E> faults SomeFault
|
||||
```
|
||||
|
||||
Saselang ne force donc plus une callable à retourner `Result` uniquement parce qu'elle peut échouer. À l'inverse, une API ne doit pas remplacer systématiquement un échec normal du domaine par un `Fault` si `Option` ou `Result` exprime mieux le contrat.
|
||||
|
||||
Le Core ne crée pas mécaniquement des paires `op()` / `tryOp()` ayant pour seule différence « valeur directe avec fault » versus « même opération dans Result ». Deux opérations distinctes doivent porter des sémantiques réellement distinctes.
|
||||
|
||||
## 15.3 Retour explicite — V1 REQUIS — FIGÉ
|
||||
|
||||
Pas de retour implicite de dernière expression.
|
||||
|
||||
@@ -1,25 +1,33 @@
|
||||
# 18. `Result`, erreurs et exceptions
|
||||
# 18. `Result`, erreurs, exceptions et faults
|
||||
|
||||
## 18.1 Hiérarchie Core — V1 REQUIS — FIGÉ
|
||||
|
||||
La hiérarchie d'erreurs V1 est :
|
||||
La hiérarchie V1 est :
|
||||
|
||||
```text
|
||||
Object
|
||||
└── Error
|
||||
├── ResultError
|
||||
└── Exception
|
||||
├── Exception
|
||||
└── Fault
|
||||
```
|
||||
|
||||
Les trois classes racines sont abstraites et ne sont donc jamais instanciées directement.
|
||||
Les quatre classes racines sont abstraites et ne sont jamais instanciées directement.
|
||||
|
||||
`Error` est la racine abstraite commune des erreurs Saselang. Elle ne détermine pas à elle seule le mécanisme de propagation.
|
||||
`Error` est la racine commune. Elle ne choisit pas à elle seule le mécanisme de propagation.
|
||||
|
||||
`ResultError` représente exclusivement la famille des erreurs transportables par `Result<T,E>`.
|
||||
```text
|
||||
ResultError
|
||||
échec transporté explicitement comme une valeur dans Result<T,E>
|
||||
|
||||
`Exception` représente exclusivement la famille des erreurs propagées par `throw` / `throws` / `try` / `catch` / `finally`.
|
||||
Exception
|
||||
échec checked propagé par throw / throws
|
||||
|
||||
`ResultError` et `Exception` sont des branches sœurs. Une classe utilisateur destinée à un `Result` hérite directement ou indirectement de `ResultError`. Une exception utilisateur hérite directement ou indirectement de `Exception`.
|
||||
Fault
|
||||
échec unchecked, capturable, pouvant être documenté par faults
|
||||
```
|
||||
|
||||
Les trois branches sont sœurs. Aucune n'est implicitement convertible vers une autre.
|
||||
|
||||
Exemple :
|
||||
|
||||
@@ -29,9 +37,12 @@ public final class ParseError extends ResultError {
|
||||
|
||||
public final class FileNotFoundException extends Exception {
|
||||
}
|
||||
|
||||
public final class IndexOutOfBoundsFault extends Fault {
|
||||
}
|
||||
```
|
||||
|
||||
L'interface `Throwable` ne fait pas partie de Saselang V1. Elle pourra être réintroduite ultérieurement si un besoin réel apparaît sans modifier la règle fondamentale : `Result` transporte des `ResultError`, tandis que `throw` transporte des `Exception`.
|
||||
Il n'existe pas d'interface `Throwable` en V1.
|
||||
|
||||
## 18.2 Informations communes de `Error` — V1 REQUIS — FIGÉ EN PRINCIPE
|
||||
|
||||
@@ -51,7 +62,7 @@ message
|
||||
|
||||
cause
|
||||
erreur causale purement informative
|
||||
peut contenir un ResultError ou une Exception
|
||||
peut contenir un ResultError, une Exception ou un Fault
|
||||
n'est pas automatiquement propagée
|
||||
|
||||
i18nMessage
|
||||
@@ -59,13 +70,11 @@ i18nMessage
|
||||
ne contient pas un tableau de traductions
|
||||
```
|
||||
|
||||
`cause` est de type `Option<Error>` et non `Nullable<Error>` : l'absence de cause est une absence sémantique. Une cause de type statique `Error` ne peut pas être passée directement à `throw`; il faut d'abord prouver par `is` qu'elle est une `Exception`, ou l'encapsuler explicitement dans une nouvelle exception.
|
||||
`cause` n'accorde aucun droit de propagation. Une valeur statiquement typée `Error` ne peut être utilisée ni avec `throw` ni avec `fault` sans preuve préalable de sa branche exacte.
|
||||
|
||||
`message`, `cause` et `i18nMessage` sont initialisés lors de la construction et ne sont pas publiquement mutables.
|
||||
|
||||
`Error` ne porte pas de propriétés universelles supplémentaires telles que timestamp, thread id, process id, host, severity ou code plateforme. Ces informations appartiennent aux sous-classes, SDKs ou couches de logging/diagnostic lorsqu'elles sont pertinentes.
|
||||
|
||||
Le type exact `I18nMessage`, sa clé et la représentation de ses paramètres seront finalisés avec Core/SDK et le système de formatting/i18n.
|
||||
`Error` ne porte pas de propriétés universelles supplémentaires telles que timestamp, thread id, process id, host, severity ou code plateforme. Ces informations appartiennent aux sous-classes, au SDK ou aux couches de logging/diagnostic lorsqu'elles sont pertinentes.
|
||||
|
||||
## 18.3 `ResultError` et code machine-readable — V1 REQUIS — FIGÉ EN PRINCIPE
|
||||
|
||||
@@ -83,21 +92,26 @@ message -> humain, canonique / fallback
|
||||
i18nMessage -> localisation externe
|
||||
```
|
||||
|
||||
La représentation exacte de `ResultErrorCode` sera finalisée avec Core/SDK. `Exception` n'a pas de code obligatoire.
|
||||
La représentation exacte de `ResultErrorCode` sera finalisée avec Core/SDK.
|
||||
|
||||
## 18.4 `Exception` et stack trace — V1 REQUIS — FIGÉ EN PRINCIPE
|
||||
Ni `Exception` ni `Fault` n'ont de code universel obligatoire ; leurs sous-types peuvent naturellement en définir lorsqu'il est utile.
|
||||
|
||||
`Exception` reste généraliste. Elle peut recevoir des informations de stack trace liées à sa propagation.
|
||||
## 18.4 Diagnostic de `Exception` et `Fault` — V1 REQUIS — FIGÉ EN PRINCIPE
|
||||
|
||||
La création d'un objet `Exception` ne doit pas obligatoirement capturer immédiatement une stack trace. Le contexte de propagation peut être attaché ou capturé lors de :
|
||||
`Exception` et `Fault` peuvent recevoir des informations de stack trace liées à leur propagation runtime.
|
||||
|
||||
La création de l'objet ne doit pas obligatoirement capturer immédiatement une stack trace. Le contexte peut être attaché ou capturé lors de :
|
||||
|
||||
```text
|
||||
throw exception;
|
||||
fault someFault;
|
||||
```
|
||||
|
||||
La représentation exacte (`StackTrace`, `StackFrame`, capture lazy ou autre optimisation) relève de Core/runtime. Cette information reste diagnostique et n'intervient pas dans la sélection des `catch`.
|
||||
ou lorsqu'un `Fault` est produit intrinsèquement par le runtime/Core.
|
||||
|
||||
`Error` et `ResultError` n'ont pas de stack trace automatique obligatoire.
|
||||
La représentation exacte (`StackTrace`, `StackFrame`, capture lazy ou autre optimisation) relève du Core/runtime. Cette information reste diagnostique et n'intervient pas dans la sélection des `catch`.
|
||||
|
||||
`ResultError` n'a pas de stack trace automatique obligatoire.
|
||||
|
||||
## 18.5 `Result<T,E>` — V1 REQUIS — FIGÉ
|
||||
|
||||
@@ -127,6 +141,7 @@ Sont invalides :
|
||||
```text
|
||||
Result<Data,Error>
|
||||
Result<Data,Exception>
|
||||
Result<Data,Fault>
|
||||
Result<Data,FileNotFoundException>
|
||||
```
|
||||
|
||||
@@ -142,7 +157,7 @@ est équivalente à :
|
||||
Result<T,ResultError>
|
||||
```
|
||||
|
||||
`Result<Void,E>` et `Result<Void>` sont autorisés pour représenter un succès sans payload utile. `Option<Void>` reste interdit.
|
||||
`Result<Void,E>` et `Result<Void>` sont autorisés. `Option<Void>` reste interdit.
|
||||
|
||||
Il n'existe aucune conversion implicite de `T` vers `Result<T,E>` ni de `E` vers `Result<T,E>` :
|
||||
|
||||
@@ -151,73 +166,72 @@ return Result::Ok(value);
|
||||
return Result::Err(error);
|
||||
```
|
||||
|
||||
sont explicites.
|
||||
restent explicites.
|
||||
|
||||
`Result` suit les règles générales des enums algébriques. Son inspection et l'extraction sûre de ses payloads utilisent `match` avec bindings typés. V1 n'introduit ni `unwrap`, ni opérateur `?`, ni extraction implicite d'une variante.
|
||||
`Result` suit les règles générales des enums algébriques. V1 n'introduit ni `unwrap`, ni opérateur `?`, ni extraction implicite d'une variante.
|
||||
|
||||
Des helpers Core futurs tels que :
|
||||
## 18.6 Choix du mécanisme d'échec — V1 REQUIS — FIGÉ EN PRINCIPE
|
||||
|
||||
Les trois branches ne sont pas trois orthographes du même concept.
|
||||
|
||||
```text
|
||||
result::expectOk(...)
|
||||
result::expectErr(...)
|
||||
ResultError / Result
|
||||
l'échec est une donnée normale du résultat et l'appelant doit l'inspecter explicitement
|
||||
|
||||
Exception
|
||||
l'échec appartient au contrat checked de la callable et doit être capturé ou propagé par throws
|
||||
|
||||
Fault
|
||||
l'échec est unchecked ; l'appelant peut le capturer mais n'y est pas obligé
|
||||
```
|
||||
|
||||
peuvent être étudiés si un besoin réel apparaît. Ils resteraient une API de `Result`, pas une syntaxe du langage, et leur comportement d'échec devrait être explicitement spécifié.
|
||||
Une API directe n'est donc plus obligée de retourner `Result` uniquement parce qu'elle peut échouer.
|
||||
|
||||
## 18.6 Séparation `ResultError` / `Exception` — V1 REQUIS — FIGÉ
|
||||
|
||||
Aucune conversion automatique n'existe entre les deux branches :
|
||||
Exemple :
|
||||
|
||||
```text
|
||||
ResultError -> Exception
|
||||
Exception -> ResultError
|
||||
method elementAt(uint64 index) -> T
|
||||
faults IndexOutOfBoundsFault
|
||||
```
|
||||
|
||||
La traduction d'un mécanisme vers l'autre se fait par encapsulation explicite dans une nouvelle erreur de la branche cible, éventuellement en conservant l'erreur source dans `cause`.
|
||||
peut retourner directement `T`.
|
||||
|
||||
Exemples conceptuels :
|
||||
Inversement, lorsqu'une absence ou un échec constitue une donnée normale du domaine, `Option` ou `Result` reste préférable :
|
||||
|
||||
```text
|
||||
throw ParseException(..., Option::Some(parseError));
|
||||
map::get(key) -> Option<V>
|
||||
parseExternalInput(...) -> Result<Value, ParseError>
|
||||
```
|
||||
|
||||
ou :
|
||||
Le Core ne doit pas créer mécaniquement un couple `op()` / `tryOp()` uniquement pour offrir d'un côté une valeur directe et de l'autre un `Result`. Deux opérations coexistantes doivent avoir des sémantiques réellement distinctes.
|
||||
|
||||
```text
|
||||
catch (FileNotFoundException error) {
|
||||
return Result::Err(FileResultError(..., Option::Some(error)));
|
||||
}
|
||||
```
|
||||
|
||||
Un simple cast ne transforme pas un `ResultError` en `Exception` ni l'inverse.
|
||||
Aucune conversion automatique n'existe entre `ResultError`, `Exception` et `Fault`. Une traduction entre branches se fait par encapsulation explicite, éventuellement via `cause`.
|
||||
|
||||
## 18.7 `throws` — V1 REQUIS — FIGÉ
|
||||
|
||||
`throws` est interdit sur une `func` / `method` / `clsmethod` à retour direct. Il n'est permis que si le retour est `Result<T>` ou `Result<T,E>`.
|
||||
`throws` est indépendant du type de retour.
|
||||
|
||||
Sont valides :
|
||||
|
||||
```text
|
||||
T + throws -> interdit
|
||||
Result<T,E> -> valide sans throws
|
||||
Result<T,E> + throws -> valide
|
||||
T
|
||||
T throws SomeException
|
||||
Result<T,E>
|
||||
Result<T,E> throws SomeException
|
||||
Void throws SomeException
|
||||
```
|
||||
|
||||
Tout type déclaré dans `throws` doit être `Exception` ou un descendant de `Exception`.
|
||||
|
||||
Une callable doit déclarer toute famille d'exception susceptible d'atteindre sa frontière sans être gérée localement. Cette obligation est transitive : une exception déclarée par une callable appelée doit être soit capturée localement, soit couverte par le `throws` de l'appelant.
|
||||
|
||||
Un type déclaré dans `throws` couvre ses descendants. Une clause :
|
||||
Un type déclaré dans `throws` couvre ses descendants. Une même clause ne doit pas contenir de types redondants lorsqu'un type déclaré couvre déjà entièrement un autre type de la liste.
|
||||
|
||||
```text
|
||||
throws IOException
|
||||
```
|
||||
|
||||
peut donc couvrir `FileNotFoundException` si cette dernière hérite de `IOException`.
|
||||
|
||||
Une même clause `throws` ne doit pas contenir de types redondants lorsqu'un type déclaré couvre déjà entièrement un autre type de la liste.
|
||||
`Fault`, `Error` et `ResultError` sont interdits dans `throws`.
|
||||
|
||||
## 18.8 `throws` dans les contrats, interfaces et overrides — V1 REQUIS — FIGÉ
|
||||
|
||||
`throws` ne fait pas partie de la signature d'overload. Il fait partie du contrat de la callable.
|
||||
`throws` ne fait pas partie de la signature d'overload. Il fait partie du contrat checked de la callable.
|
||||
|
||||
Un override ou une implémentation peut :
|
||||
|
||||
@@ -229,21 +243,20 @@ gérer localement tout ou partie des exceptions du contrat parent
|
||||
|
||||
Il ne peut jamais ajouter une exception non couverte par le contrat parent ni élargir une famille déclarée.
|
||||
|
||||
La même règle s'applique aux contrats d'interface. Lorsque plusieurs interfaces portent la même signature, l'implémentation doit satisfaire simultanément tous leurs contrats `throws`. Une implémentation sans exception sortante est toujours compatible avec un contrat qui en autorise.
|
||||
La même règle s'applique aux contrats d'interface. Une implémentation sans exception sortante est toujours compatible avec un contrat qui en autorise.
|
||||
|
||||
## 18.9 `throw` — V1 REQUIS — FIGÉ
|
||||
|
||||
`throw` ne peut lancer qu'une valeur dont le type statique est `Exception` ou un descendant de `Exception`.
|
||||
|
||||
```text
|
||||
throw FileNotFoundException(...); // valide
|
||||
throw ParseError(...); // erreur
|
||||
throw Error(...); // erreur
|
||||
throw FileNotFoundException(...); // OK
|
||||
throw ParseError(...); // ERROR
|
||||
throw IndexOutOfBoundsFault(...); // ERROR
|
||||
throw Error(...); // ERROR
|
||||
```
|
||||
|
||||
Les racines abstraites `Error`, `ResultError` et `Exception` ne sont jamais instanciables directement.
|
||||
|
||||
La forme de repropagation reste explicite :
|
||||
La repropagation reste explicite :
|
||||
|
||||
```text
|
||||
catch (IOException error) {
|
||||
@@ -253,7 +266,69 @@ catch (IOException error) {
|
||||
|
||||
Il n'existe pas de forme spéciale `throw;` en V1.
|
||||
|
||||
## 18.10 `try` / `catch` / `finally` — V1 REQUIS — FIGÉ
|
||||
## 18.10 `fault` et `faults` — V1 REQUIS — FIGÉ EN PRINCIPE
|
||||
|
||||
`fault` produit explicitement un `Fault` :
|
||||
|
||||
```text
|
||||
fault InvalidStateFault(...);
|
||||
```
|
||||
|
||||
Le type statique de la valeur doit être `Fault` ou un descendant de `Fault`.
|
||||
|
||||
```text
|
||||
fault InvalidStateFault(...); // OK
|
||||
fault FileNotFoundException(...); // ERROR
|
||||
fault ParseError(...); // ERROR
|
||||
```
|
||||
|
||||
Une callable peut documenter des faults significatifs directement dans sa signature :
|
||||
|
||||
```text
|
||||
method elementAt(uint64 index) -> T
|
||||
faults IndexOutOfBoundsFault
|
||||
```
|
||||
|
||||
Plusieurs familles peuvent être listées explicitement :
|
||||
|
||||
```text
|
||||
faults FirstFault, SecondFault
|
||||
```
|
||||
|
||||
Chaque type listé doit être `Fault` ou un descendant de `Fault`; une liste ne doit pas contenir de famille redondante déjà couverte par un parent déclaré.
|
||||
|
||||
La clause `faults` est **optionnelle et non exhaustive**.
|
||||
|
||||
Elle signifie que les faults listés font explicitement partie du contrat/documentation utile de l'API. Elle ne signifie pas qu'aucun autre fault runtime ne peut survenir.
|
||||
|
||||
Contrairement à `throws` :
|
||||
|
||||
```text
|
||||
aucun catch n'est obligatoire
|
||||
aucune propagation de la clause faults n'est obligatoire
|
||||
un appelant n'a pas à recopier les faults d'une callable appelée
|
||||
```
|
||||
|
||||
Exemple valide :
|
||||
|
||||
```text
|
||||
func outer() -> Void {
|
||||
inner(); // inner peut déclarer faults SomeFault
|
||||
return Void;
|
||||
}
|
||||
```
|
||||
|
||||
`outer` peut, mais n'est pas obligé de déclarer à son tour :
|
||||
|
||||
```text
|
||||
faults SomeFault
|
||||
```
|
||||
|
||||
`faults` ne fait pas partie de la signature d'overload et n'impose pas les restrictions de covariance contractuelle de `throws`. Un override peut documenter un ensemble différent de faults, puisque l'absence d'un fault dans la clause n'est jamais une garantie statique d'impossibilité.
|
||||
|
||||
Une API publique qui produit explicitement un fault important devrait normalement le documenter avec `faults`; un outil/linter peut signaler les omissions sans en faire une erreur de compilation du langage.
|
||||
|
||||
## 18.11 `try` / `catch` / `finally` — V1 REQUIS — FIGÉ
|
||||
|
||||
Un `try` doit être suivi d'au moins un `catch`.
|
||||
|
||||
@@ -272,7 +347,7 @@ try {
|
||||
...
|
||||
} catch (SpecificException error) {
|
||||
...
|
||||
} catch (ParentException error) {
|
||||
} catch (SomeFault faultValue) {
|
||||
...
|
||||
} finally {
|
||||
...
|
||||
@@ -281,75 +356,95 @@ try {
|
||||
|
||||
`finally` est facultatif et ne peut apparaître qu'après au moins un `catch`.
|
||||
|
||||
Chaque `catch` contient exactement un type explicite d'`Exception` ou descendant. Il n'existe pas de multi-catch `A | B` en V1 : des blocs `catch` distincts sont utilisés.
|
||||
|
||||
Les `catch` sont évalués dans l'ordre source. Le chevauchement par héritage est normal et utile : les cas spécifiques peuvent précéder un fallback de famille générale.
|
||||
|
||||
Un `catch` entièrement couvert par un `catch` précédent est une erreur de compilation, pas un simple warning.
|
||||
|
||||
Exemple valide :
|
||||
Le type explicite d'un `catch` doit être :
|
||||
|
||||
```text
|
||||
catch (FileNotFoundException error) {
|
||||
...
|
||||
} catch (IOException error) {
|
||||
...
|
||||
}
|
||||
Exception ou un descendant de Exception
|
||||
Fault ou un descendant de Fault
|
||||
```
|
||||
|
||||
Exemple invalide si `FileNotFoundException extends IOException` :
|
||||
Sont donc interdits :
|
||||
|
||||
```text
|
||||
catch (IOException error) {
|
||||
...
|
||||
} catch (FileNotFoundException error) {
|
||||
...
|
||||
}
|
||||
catch (Error error)
|
||||
catch (ResultError error)
|
||||
```
|
||||
|
||||
Un ensemble de `catch` n'a pas à être exhaustif. Toute `Exception` non capturée continue à se propager et doit être couverte par le contrat `throws` de la callable englobante.
|
||||
Il n'existe pas de multi-catch `A | B` en V1.
|
||||
|
||||
Les variables de `catch` suivent les règles normales de scope et de non-shadowing. Des `catch` distincts peuvent réutiliser le même nom parce que leurs scopes sont disjoints.
|
||||
Les `catch` sont évalués dans l'ordre source. Un `catch` entièrement couvert par un précédent dans la même branche d'héritage est une erreur de compilation.
|
||||
|
||||
## 18.11 `finally` non-escaping — V1 REQUIS — FIGÉ
|
||||
Une `Exception` non capturée continue à se propager et doit être couverte par `throws`.
|
||||
|
||||
`finally` exécute un bloc commun avant de quitter la construction `try/catch`, qu'il y ait :
|
||||
Un `Fault` non capturé continue à se propager de façon unchecked ; aucune clause `faults` n'est exigée sur les callables traversées.
|
||||
|
||||
Les variables de `catch` suivent les règles normales de scope et de non-shadowing.
|
||||
|
||||
## 18.12 `finally` non-escaping — V1 REQUIS — FIGÉ EN PRINCIPE
|
||||
|
||||
`finally` exécute un bloc commun avant de quitter la construction `try/catch`, notamment sur :
|
||||
|
||||
```text
|
||||
fin normale du try
|
||||
fin normale d'un catch
|
||||
return traversant la construction
|
||||
throw propagé
|
||||
Fault propagé
|
||||
break / continue traversant la construction
|
||||
Exception non capturée par les catch
|
||||
```
|
||||
|
||||
`finally` ne doit jamais remplacer une sortie déjà en cours. Les sorties structurées suivantes y sont interdites :
|
||||
`finally` ne doit pas remplacer volontairement une sortie déjà en cours. Les sorties structurées explicites suivantes y sont interdites :
|
||||
|
||||
```text
|
||||
return
|
||||
throw
|
||||
fault
|
||||
break
|
||||
continue
|
||||
emit
|
||||
```
|
||||
|
||||
Aucune `Exception` non capturée ne peut sortir indirectement d'un `finally`. Toute callable appelée depuis `finally` dont le contrat comporte `throws` doit avoir ses exceptions entièrement gérées à l'intérieur du `finally`.
|
||||
Toute `Exception` produite indirectement depuis `finally` doit être gérée localement selon les règles checked de `throws`.
|
||||
|
||||
Une faute runtime non récupérable reste distincte de ce contrat d'exception.
|
||||
Un `Fault` dynamique peut néanmoins survenir dans le code exécuté par `finally`, puisqu'il est unchecked. L'interaction exacte entre un tel fault, l'unwind, les destructeurs et une sortie déjà en cours reste à fermer avec le modèle mémoire/runtime.
|
||||
|
||||
## 18.12 Faute runtime / panic — V1 REQUIS — À FINALISER
|
||||
## 18.13 Sémantique runtime des `Fault` — V1 REQUIS — FIGÉ EN PRINCIPE
|
||||
|
||||
Les violations de contrat du langage telles que :
|
||||
Les `Fault` couvrent notamment les échecs unchecked et violations runtime tels que :
|
||||
|
||||
```text
|
||||
index hors limites
|
||||
division entière par zéro
|
||||
index dynamique hors limites
|
||||
division entière dynamique par zéro
|
||||
overflow checked
|
||||
représentation mémoire invalide
|
||||
borne dynamique invalide lors d'une construction directe lorsque la règle du type le définit
|
||||
iterator invalidé
|
||||
clé absente lors d'un accès strict map[key]
|
||||
doublon lors d'un insert strict
|
||||
conversion explicite directe dont les préconditions runtime ne sont pas satisfaites
|
||||
représentation/encodage invalide lors d'une construction directe validée
|
||||
```
|
||||
|
||||
ne sont pas nécessairement des `ResultError` ou des `Exception` récupérables.
|
||||
Lorsqu'une violation d'une précondition intrinsèque est démontrable statiquement, le compilateur doit la diagnostiquer plutôt que générer un programme condamné à fauter.
|
||||
|
||||
Le modèle exact de faute runtime/fatal error/panic et son interaction avec cleanup/destruction doit être défini avant la finalisation V1.
|
||||
Exemple :
|
||||
|
||||
```text
|
||||
StaticArray<int32,3> values = [1, 2, 3];
|
||||
int32 value = values[5]; // ERROR compilation
|
||||
```
|
||||
|
||||
Cette règle ne rend évidemment pas illégal un statement `fault` explicite : `fault SomeFault(...)` est un mécanisme volontaire du programme et peut être utilisé pour implémenter une API.
|
||||
|
||||
Lorsqu'un `Fault` ne peut être déterminé qu'au runtime :
|
||||
|
||||
```text
|
||||
capturé par catch
|
||||
-> le catch correspondant s'exécute
|
||||
|
||||
non capturé
|
||||
-> le fault remonte sans contrat checked
|
||||
-> à la frontière de l'unité d'exécution, il provoque un échec runtime diagnostiqué
|
||||
```
|
||||
|
||||
La définition exacte de « l'unité d'exécution » (processus, thread, task, isolate éventuel) et l'ordre final cleanup/destruction lors d'un fault seront fermés avec les chapitres mémoire et concurrence.
|
||||
|
||||
---
|
||||
|
||||
@@ -27,7 +27,7 @@ Un `if` qui contient `emit` devient un `if` producteur de valeur. Dans ce cas :
|
||||
- le résultat du `if` doit obligatoirement être affecté à une destination ;
|
||||
- un bloc `else` final est obligatoire ;
|
||||
- chaque voie de terminaison normale de chaque branche doit produire explicitement une valeur via `emit` ;
|
||||
- une voie que le compilateur prouve comme terminant définitivement le contrôle (`return`, `throw`, runtime fault certain ou non-terminaison prouvée) n'a pas à exécuter `emit` ;
|
||||
- une voie que le compilateur prouve comme terminant définitivement le contrôle (`return`, `throw`, `fault` explicite ou non-terminaison prouvée) n'a pas à exécuter `emit` ;
|
||||
- les valeurs émises doivent être compatibles avec le type de la destination ;
|
||||
- aucune valeur de secours n'est implicite, y compris pour `Option<T>`.
|
||||
|
||||
|
||||
@@ -6,13 +6,15 @@ Les opérateurs utilisateur ne peuvent être fournis que via un ensemble fermé
|
||||
|
||||
L'utilisateur ne peut pas inventer de nouveaux symboles opérateurs.
|
||||
|
||||
Les `operator` contracts :
|
||||
Les contrats `operator` :
|
||||
|
||||
- retournent directement leur valeur ;
|
||||
- ne retournent jamais `Result` ;
|
||||
- ne déclarent jamais `throws`.
|
||||
- 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 faute de contrat du langage peut néanmoins déclencher une faute runtime déterministe.
|
||||
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É
|
||||
|
||||
@@ -124,29 +126,38 @@ Les classes ne reçoivent aucune comparaison champ-à-champ automatique : elles
|
||||
|
||||
## 20.6 Comparaison — V1 REQUIS — FIGÉ EN PRINCIPE
|
||||
|
||||
Core :
|
||||
Core distingue l'ordre partiel de l'ordre total :
|
||||
|
||||
```text
|
||||
public enum Ordering {
|
||||
public enum PartialOrdering {
|
||||
Less,
|
||||
Equal,
|
||||
Greater,
|
||||
Unordered
|
||||
}
|
||||
|
||||
public enum Ordering {
|
||||
Less,
|
||||
Equal,
|
||||
Greater
|
||||
}
|
||||
```
|
||||
|
||||
Interfaces :
|
||||
Interfaces opérateur :
|
||||
|
||||
```text
|
||||
OpPartialCompare<Lhs,Rhs>
|
||||
-> PartialOrdering
|
||||
|
||||
OpCompare<T>
|
||||
-> Ordering
|
||||
```
|
||||
|
||||
`OpCompare<T>` renforce `OpPartialCompare<T,T>` et garantit un ordre total, donc pas de `Ordering::Unordered`.
|
||||
`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.
|
||||
|
||||
Les floats utilisent l'ordre partiel ; 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 `==`.
|
||||
|
||||
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`.
|
||||
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
|
||||
|
||||
@@ -187,21 +198,25 @@ D'autres index numériques pourront être supportés ultérieurement sans modifi
|
||||
|
||||
Un type utilisateur peut utiliser n'importe quel type d'index pertinent.
|
||||
|
||||
## 20.10 Map — V1 REQUIS — DIRECTION FIGÉE
|
||||
## 20.10 Map — V1 REQUIS — FIGÉ EN PRINCIPE
|
||||
|
||||
Direction recommandée :
|
||||
Le contrat des maps est défini au chapitre 22.
|
||||
|
||||
L'indexation est stricte :
|
||||
|
||||
```text
|
||||
Map<K,V>
|
||||
OpIndex<K,Option<V>>
|
||||
OpIndexMut<K,V>
|
||||
map[key] -> V
|
||||
```
|
||||
|
||||
Lecture : absent -> `None` ; présent -> `Some(value)`.
|
||||
La clé doit exister ; une absence dynamique produit `KeyNotFoundFault`.
|
||||
|
||||
Écriture : insertion si absent, remplacement si présent.
|
||||
L'accès conditionnel est explicite et distinct :
|
||||
|
||||
Une méthode `containsKey` peut compléter l'API sans être obligatoire avant toute lecture.
|
||||
```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É
|
||||
|
||||
|
||||
@@ -95,26 +95,37 @@ Aucun `Utf8CodeUnit` / `Utf16CodeUnit` / `Utf32CodeUnit` distinct n'est introdui
|
||||
|
||||
Aucun transcodage implicite n'existe.
|
||||
|
||||
Les conversions totales utilisent `to...`.
|
||||
|
||||
Les constructions ou réductions pouvant échouer utilisent `tryFrom...` / `tryTo...`.
|
||||
Les conversions directes retournent la destination attendue. Lorsqu'une validation runtime peut échouer, la callable peut déclarer `faults UnicodeEncodingFault` au lieu de forcer un `ResultError` ou une variante `try...` parallèle.
|
||||
|
||||
Exemples :
|
||||
|
||||
```text
|
||||
char::toUtf8Char()
|
||||
Utf8Char::toChar()
|
||||
Utf8Char::toUtf16Char()
|
||||
char::toUtf8Char() -> Utf8Char
|
||||
Utf8Char::toChar() -> char
|
||||
Utf8Char::toUtf16Char() -> Utf16Char
|
||||
|
||||
Utf8Char::tryFrom(uint8)
|
||||
Utf16Char::tryFrom(uint16)
|
||||
Utf32Char::tryFrom(uint32)
|
||||
Utf8Char::from(uint8) -> Utf8Char
|
||||
faults UnicodeEncodingFault
|
||||
|
||||
Utf8Char::tryToUint8()
|
||||
Utf16Char::tryToUint16()
|
||||
Utf32Char::toUint32()
|
||||
Utf16Char::from(uint16) -> Utf16Char
|
||||
faults UnicodeEncodingFault
|
||||
|
||||
Utf32Char::from(uint32) -> Utf32Char
|
||||
faults UnicodeEncodingFault
|
||||
|
||||
Utf8Char::toUint8() -> uint8
|
||||
faults UnicodeEncodingFault
|
||||
|
||||
Utf16Char::toUint16() -> uint16
|
||||
faults UnicodeEncodingFault
|
||||
|
||||
Utf32Char::toUint32() -> uint32
|
||||
```
|
||||
|
||||
`UnicodeEncodingFault extends Fault` est le nom de travail du fault Core associé aux données encodées invalides ou aux réductions impossibles.
|
||||
|
||||
Le Core n'expose pas simultanément `from(...)` et `tryFrom(...)` lorsque les deux opérations auraient exactement la même sémantique et ne différeraient que par le canal d'échec.
|
||||
|
||||
La matrice normative détaillée est définie dans `annexes/B-unicode-encoding-conversions.md`.
|
||||
|
||||
## 21.5 Aucun mélange implicite de types — V1 REQUIS — FIGÉ
|
||||
|
||||
@@ -135,9 +135,9 @@ Les indices d'une sous-slice sont relatifs à la slice source.
|
||||
|
||||
Les interfaces décrivent des capacités réellement garanties. Les classes/structs génériques fournissent le stockage et l'implémentation.
|
||||
|
||||
Saselang ne retient pas le modèle d'opérations optionnelles qui existent dans une interface mais échouent ensuite au runtime comme « unsupported ».
|
||||
Saselang ne retient pas le modèle d'opérations optionnelles présentes dans une interface mais susceptibles d'échouer ensuite comme « unsupported ».
|
||||
|
||||
Hiérarchie principale retenue :
|
||||
Hiérarchie principale :
|
||||
|
||||
```text
|
||||
Iterable<T>
|
||||
@@ -151,21 +151,84 @@ SettableList<T>
|
||||
ResizableList<T>
|
||||
```
|
||||
|
||||
`Set<T>` et `Map<K,V>` sont des branches distinctes à préciser.
|
||||
`Set<T>` et `Map<K,V>` forment des branches sémantiques distinctes.
|
||||
|
||||
### 22.4.1 `Iterable<T>` / `Iterator<T>`
|
||||
### 22.4.1 `Iterable<T>` et `Iterator<T>`
|
||||
|
||||
Interfaces Core reconnues par `foreach`.
|
||||
`foreach` dépend uniquement de `Iterable<T>`.
|
||||
|
||||
Elles ne portent pas le préfixe `Op`, car `foreach` est une construction du langage et non un opérateur symbolique.
|
||||
```text
|
||||
interface Iterable<T> {
|
||||
const method iterator() -> Iterator<T>;
|
||||
}
|
||||
```
|
||||
|
||||
Indexabilité et itérabilité sont indépendantes.
|
||||
Créer un iterator ne constitue pas une mutation sémantique de la source.
|
||||
|
||||
### 22.4.2 `Collection<T>`
|
||||
`Iterator<T>` représente une itération particulière et possède un état de progression mutable :
|
||||
|
||||
```text
|
||||
interface Iterator<T> {
|
||||
method next() -> Option<T>;
|
||||
}
|
||||
```
|
||||
|
||||
`Some(value)` fournit l'élément suivant ; `None` marque la fin normale de l'itération.
|
||||
|
||||
Saselang n'impose pas le couple `hasNext()` / `next()`. `Option<T>` rend l'état de fin explicite dans une seule opération.
|
||||
|
||||
`Iterator<T>` n'étend pas `Iterable<T>` par défaut. Une source capable de créer des itérations et une itération déjà en cours sont deux capacités différentes, même si certains types concrets peuvent éventuellement fournir les deux.
|
||||
|
||||
Pour les collections ordinaires non concurrentes, une mutation structurelle invalide par défaut les iterators actifs lorsque le type concret ne garantit pas explicitement une autre politique.
|
||||
|
||||
```text
|
||||
insert / remove / clear / append / changement structurel
|
||||
-> peut invalider l'iterator
|
||||
|
||||
utilisation ultérieure d'un iterator invalidé
|
||||
-> IteratorInvalidatedFault
|
||||
```
|
||||
|
||||
Le simple remplacement d'une valeur existante n'est pas automatiquement une mutation structurelle. Le type concret documente sa politique exacte.
|
||||
|
||||
Les collections concurrentes ou spécialisées peuvent fournir une autre politique (`snapshot`, stabilité, weak consistency, etc.) ; elle doit être explicite.
|
||||
|
||||
### 22.4.2 `View<T>`
|
||||
|
||||
`View<T>` représente une vue légère sur une source existante :
|
||||
|
||||
```text
|
||||
interface View<T> extends Iterable<T> {
|
||||
const method count() -> uint64;
|
||||
const method isEmpty() -> bool;
|
||||
}
|
||||
```
|
||||
|
||||
`View<T>` n'étend pas `Collection<T>`.
|
||||
|
||||
Le contrat général ne contient pas `contains()`. Une classe ou une interface plus spécialisée peut l'ajouter si elle en a réellement besoin.
|
||||
|
||||
Une `View<T>` :
|
||||
|
||||
```text
|
||||
n'impose aucune copie des éléments
|
||||
n'impose aucun stockage indépendant
|
||||
n'impose aucune contiguïté
|
||||
ne possède pas nécessairement les données qu'elle expose
|
||||
ne peut jamais augmenter les permissions const de sa source
|
||||
```
|
||||
|
||||
Par défaut, une vue est **vivante**, pas un snapshot : une nouvelle itération peut observer les modifications ultérieures de la source selon le contrat du type concret.
|
||||
|
||||
Le runtime/compilateur garantit que le stockage ou l'état source nécessaire reste valide aussi longtemps que la vue l'exige, sans syntaxe de lifetime utilisateur.
|
||||
|
||||
Le comportement d'un iterator déjà créé avant une modification reste régi par la politique d'invalidation/stabilité du type concret.
|
||||
|
||||
### 22.4.3 `Collection<T>`
|
||||
|
||||
`Collection<T>` étend `Iterable<T>` et représente une collection finie d'éléments.
|
||||
|
||||
Contrat minimal retenu :
|
||||
Contrat minimal :
|
||||
|
||||
```text
|
||||
count() -> uint64
|
||||
@@ -175,7 +238,7 @@ contains(const T value) -> bool
|
||||
|
||||
`count()` exprime le nombre d'éléments au sens général de collection.
|
||||
|
||||
### 22.4.3 `List<T>`
|
||||
### 22.4.4 `List<T>`
|
||||
|
||||
`List<T>` étend `Collection<T>` et `OpIndex<uint64,T>`.
|
||||
|
||||
@@ -193,33 +256,39 @@ Pour une `List<T>` :
|
||||
count() == length()
|
||||
```
|
||||
|
||||
Les deux noms sont néanmoins conservés parce qu'ils expriment des concepts différents : cardinalité générale de collection et longueur d'une séquence indexable.
|
||||
Les deux noms restent distincts parce qu'ils expriment la cardinalité générale d'une collection et la longueur d'une séquence indexable.
|
||||
|
||||
`List<T>` ne garantit ni remplacement d'un élément, ni redimensionnement, ni complexité algorithmique particulière de l'accès indexé.
|
||||
`List<T>` ne garantit ni remplacement, ni redimensionnement, ni complexité algorithmique particulière de l'accès indexé.
|
||||
|
||||
### 22.4.4 `SettableList<T>`
|
||||
### 22.4.5 `SettableList<T>`
|
||||
|
||||
`SettableList<T>` étend `List<T>` et `OpIndexMut<uint64,T>`.
|
||||
|
||||
Elle garantit le remplacement d'un élément existant sans modification de la longueur.
|
||||
Elle garantit le remplacement d'un élément existant sans modification de longueur :
|
||||
|
||||
```text
|
||||
list[index] = value;
|
||||
```
|
||||
|
||||
ne signifie jamais `append` lorsque `index == length()`.
|
||||
`index` doit désigner une case existante ; l'affectation ne signifie jamais `append`.
|
||||
|
||||
### 22.4.5 `ResizableList<T>`
|
||||
### 22.4.6 `ResizableList<T>`
|
||||
|
||||
`ResizableList<T>` étend `SettableList<T>`.
|
||||
`ResizableList<T>` étend `SettableList<T>` et garantit des opérations structurelles capables de modifier la longueur.
|
||||
|
||||
Elle garantit des opérations structurelles capables de modifier la longueur, par exemple ajout, insertion et suppression.
|
||||
Les signatures exactes seront figées avec `Vector<T>`.
|
||||
|
||||
Les signatures exactes seront figées lors de la définition du type concret redimensionnable.
|
||||
Un `resize(newLength)` sans information d'initialisation n'est pas retenu implicitement : agrandir une collection doit définir comment les nouveaux éléments sont construits.
|
||||
|
||||
Un `resize(newLength)` sans information d'initialisation n'est pas retenu implicitement : agrandir une collection doit toujours définir comment les nouveaux éléments sont construits.
|
||||
Lorsqu'il existe, `clear()` suit la convention :
|
||||
|
||||
### 22.4.6 Capacité du type et permission `const`
|
||||
```text
|
||||
clear() -> uint64
|
||||
```
|
||||
|
||||
et retourne le nombre d'éléments effectivement supprimés.
|
||||
|
||||
### 22.4.7 Capacité du type et permission `const`
|
||||
|
||||
La capacité intrinsèque du type et la permission d'un accès sont deux dimensions distinctes.
|
||||
|
||||
@@ -230,9 +299,9 @@ const SettableList<User> readonly = users;
|
||||
|
||||
Le type sait remplacer des éléments, mais l'accès `readonly` ne peut pas utiliser cette capacité.
|
||||
|
||||
La propagation générale de `const` reste applicable aux éléments obtenus via cet accès.
|
||||
La même règle s'applique à `Map`, `Set`, `View` et aux éléments obtenus à travers ces accès : une projection ne peut jamais augmenter les droits reçus de sa source.
|
||||
|
||||
### 22.4.7 Classification initiale
|
||||
### 22.4.8 Classification initiale des séquences
|
||||
|
||||
```text
|
||||
StaticArray<T,N>
|
||||
@@ -258,9 +327,271 @@ Vector<T>
|
||||
|
||||
`Vector<T>` reste à définir précisément.
|
||||
|
||||
Un type persistant/immutable par nature n'a aucune obligation d'implémenter `List<T>`. Par exemple, un futur `PersistentList<T>` peut implémenter uniquement `Collection<T>` et fournir ses propres opérations si cela correspond mieux à sa sémantique.
|
||||
Un type persistant/immutable par nature n'a aucune obligation d'implémenter `List<T>` s'il ne garantit pas sa sémantique.
|
||||
|
||||
Une interface Saselang n'est jamais implémentée uniquement parce qu'un type ressemble conceptuellement à une autre famille de types.
|
||||
### 22.4.9 `Set<T>` et `ResizableSet<T>`
|
||||
|
||||
`Set<T>` étend `Collection<T>`.
|
||||
|
||||
Il garantit :
|
||||
|
||||
```text
|
||||
unicité des éléments
|
||||
aucun index ordinal
|
||||
aucun ordre d'itération général garanti
|
||||
```
|
||||
|
||||
La capacité structurelle est séparée :
|
||||
|
||||
```text
|
||||
interface ResizableSet<T> extends Set<T> {
|
||||
method add(T value) -> bool;
|
||||
method remove(const T value) -> bool;
|
||||
method clear() -> uint64;
|
||||
}
|
||||
```
|
||||
|
||||
Sémantique :
|
||||
|
||||
```text
|
||||
add(value)
|
||||
true -> élément ajouté
|
||||
false -> élément déjà présent, set inchangé
|
||||
|
||||
remove(value)
|
||||
true -> élément supprimé
|
||||
false -> élément absent
|
||||
|
||||
clear()
|
||||
-> nombre d'éléments effectivement supprimés
|
||||
```
|
||||
|
||||
Il n'existe pas de niveau `SettableSet<T>` : remplacer un élément d'un set équivaut conceptuellement à une modification structurelle de son ensemble de valeurs.
|
||||
|
||||
### 22.4.10 `Map<K,V>`, `SettableMap<K,V>` et `ResizableMap<K,V>`
|
||||
|
||||
`Map<K,V>` n'étend pas `Collection<T>` et n'implémente pas directement `Iterable<...>`. Une map possède trois projections naturelles différentes : clés, valeurs et entrées ; aucune ne doit être choisie implicitement comme itération « par défaut ».
|
||||
|
||||
Contrat de lecture :
|
||||
|
||||
```text
|
||||
interface Map<K,V> extends OpIndex<K,V> {
|
||||
const method count() -> uint64;
|
||||
const method isEmpty() -> bool;
|
||||
const method containsKey(const K key) -> bool;
|
||||
const method get(const K key) -> Option<V>;
|
||||
|
||||
const method keys() -> View<K>;
|
||||
const method values() -> View<V>;
|
||||
const method entries() -> View<MapEntry<K,V>>;
|
||||
}
|
||||
```
|
||||
|
||||
Deux intentions sont séparées :
|
||||
|
||||
```text
|
||||
map[key] -> V
|
||||
accès strict
|
||||
la clé doit exister
|
||||
absence dynamique -> KeyNotFoundFault
|
||||
|
||||
map::get(key) -> Option<V>
|
||||
accès conditionnel
|
||||
absence normale -> None
|
||||
```
|
||||
|
||||
`SettableMap<K,V>` étend `Map<K,V>` et `OpIndexMut<K,V>`.
|
||||
|
||||
```text
|
||||
map[key] = value;
|
||||
```
|
||||
|
||||
remplace uniquement la valeur d'une clé existante. Cette syntaxe n'insère jamais implicitement une nouvelle clé. Une clé absente produit `KeyNotFoundFault`.
|
||||
|
||||
`ResizableMap<K,V>` étend `SettableMap<K,V>` et ajoute les changements structurels :
|
||||
|
||||
```text
|
||||
insert(K key, V value) -> Void
|
||||
faults DuplicateKeyFault
|
||||
|
||||
remove(const K key) -> Void
|
||||
faults KeyNotFoundFault
|
||||
|
||||
clear() -> uint64
|
||||
```
|
||||
|
||||
`insert` affirme que la clé est nouvelle ; `remove` affirme qu'elle existe. Leurs violations dynamiques sont des `Fault` unchecked et capturables.
|
||||
|
||||
Le Core ne fournit pas mécaniquement `tryInsert` / `tryRemove` ayant pour seule fonction de dupliquer ces opérations dans `Result` ou `bool`. Une variante conditionnelle ne sera ajoutée que si elle porte une sémantique réellement utile distincte.
|
||||
|
||||
Il n'existe pas de `put()` implicite « insert ou replace » tant qu'un besoin concret ne justifie pas cette troisième intention.
|
||||
|
||||
### 22.4.11 `MapEntry<K,V>`
|
||||
|
||||
`MapEntry<K,V>` représente une paire clé/valeur observée lors d'une projection `entries()`.
|
||||
|
||||
Conceptuellement :
|
||||
|
||||
```text
|
||||
struct MapEntry<K,V> {
|
||||
const method key() -> K;
|
||||
const method value() -> V;
|
||||
}
|
||||
```
|
||||
|
||||
`MapEntry` n'est pas un proxy mutable vers un bucket interne de la map et n'expose pas de `setValue()` implicite.
|
||||
|
||||
La mutation d'une map reste explicite via :
|
||||
|
||||
```text
|
||||
map[key] = value;
|
||||
```
|
||||
|
||||
La sémantique de copie/référence de `K` et `V` suit les règles normales de leurs types.
|
||||
|
||||
### 22.4.12 Ordre : `Ordering`, `Comparable<T>` et `Comparator<T>`
|
||||
|
||||
L'ordre total applicatif utilise :
|
||||
|
||||
```text
|
||||
enum Ordering {
|
||||
Less,
|
||||
Equal,
|
||||
Greater
|
||||
}
|
||||
```
|
||||
|
||||
`Comparable<T>` exprime l'ordre naturel ou principal du type dans son domaine :
|
||||
|
||||
```text
|
||||
interface Comparable<T> {
|
||||
const method compareTo(const T other) -> Ordering;
|
||||
}
|
||||
```
|
||||
|
||||
Un type peut tout à fait implémenter `Comparable<T>` tout en supportant plusieurs ordres alternatifs via des comparators. Par exemple, un `User` d'un jeu peut avoir un classement principal naturel et rester comparable autrement par nom, niveau ou date.
|
||||
|
||||
`Comparator<T>` exprime un ordre externe/alternatif :
|
||||
|
||||
```text
|
||||
interface Comparator<T> {
|
||||
const method compare(const T left, const T right) -> Ordering;
|
||||
}
|
||||
```
|
||||
|
||||
Règle de sélection :
|
||||
|
||||
```text
|
||||
Comparator explicitement fourni
|
||||
-> utilisé exclusivement
|
||||
|
||||
aucun Comparator fourni
|
||||
-> Comparable<T> requis
|
||||
```
|
||||
|
||||
Aucun mélange/fallback entre les deux n'est effectué pendant une même opération ou dans une même collection ordonnée.
|
||||
|
||||
`Ordering::Equal` signifie équivalence selon cette relation d'ordre. Il n'implique pas nécessairement `left == right`.
|
||||
|
||||
Les implémentations de `Comparable` et `Comparator` doivent respecter cohérence, symétrie d'ordre et transitivité. Le compilateur n'est pas tenu de prouver ces propriétés générales.
|
||||
|
||||
### 22.4.13 `SortedSet<T>` et `SortedMap<K,V>`
|
||||
|
||||
`SortedSet<T>` étend `Set<T>` et garantit un ordre total stable selon le comparator actif :
|
||||
|
||||
```text
|
||||
interface SortedSet<T> extends Set<T> {
|
||||
const method comparator() -> Option<Comparator<T>>;
|
||||
const method first() -> Option<T>;
|
||||
const method last() -> Option<T>;
|
||||
}
|
||||
```
|
||||
|
||||
`None` pour `comparator()` signifie que l'ordre naturel `Comparable<T>` est utilisé. `Some(comparator)` expose l'ordre externe choisi pour cette instance.
|
||||
|
||||
`SortedMap<K,V>` étend `Map<K,V>` et ordonne les entrées par clé :
|
||||
|
||||
```text
|
||||
interface SortedMap<K,V> extends Map<K,V> {
|
||||
const method comparator() -> Option<Comparator<K>>;
|
||||
const method firstKey() -> Option<K>;
|
||||
const method lastKey() -> Option<K>;
|
||||
}
|
||||
```
|
||||
|
||||
Pour une `SortedMap`, les vues `keys()`, `values()` et `entries()` parcourent les données dans l'ordre des clés.
|
||||
|
||||
Les opérations de bornes/ranges (`floor`, `ceiling`, `lower`, `higher` ou noms définitifs) seront fermées séparément afin de ne pas introduire de noms ambigus par simple imitation d'une autre plateforme.
|
||||
|
||||
### 22.4.14 `TreeSet<T>` et `TreeMap<K,V>`
|
||||
|
||||
Les types standard ordonnés généraux sont nommés :
|
||||
|
||||
```text
|
||||
TreeSet<T>
|
||||
TreeMap<K,V>
|
||||
```
|
||||
|
||||
Le nom n'impose pas une structure arborescente précise au niveau ABI/implémentation tant que le contrat observable reste respecté.
|
||||
|
||||
Un futur `BTreeMap<K,V>` peut exister comme implémentation explicitement fondée sur un B-tree ; il ne remplace pas le nom général `TreeMap`.
|
||||
|
||||
Comme Saselang n'autorise qu'un `construct` par classe, les deux modes de création passent par des factories de classe distinctes :
|
||||
|
||||
```text
|
||||
TreeSet<T>::natural()
|
||||
requiert T implements Comparable<T>
|
||||
|
||||
TreeSet<T>::withComparator(Comparator<T> comparator)
|
||||
n'exige pas Comparable<T>
|
||||
|
||||
TreeMap<K,V>::natural()
|
||||
requiert K implements Comparable<K>
|
||||
|
||||
TreeMap<K,V>::withComparator(Comparator<K> comparator)
|
||||
n'exige pas Comparable<K>
|
||||
```
|
||||
|
||||
Les contraintes appartiennent aux factories concernées et non nécessairement au type générique entier.
|
||||
|
||||
### 22.4.15 Contraintes des implémentations concrètes
|
||||
|
||||
Les interfaces abstraites `Set<T>` et `Map<K,V>` n'imposent pas une stratégie de stockage particulière.
|
||||
|
||||
Ainsi :
|
||||
|
||||
```text
|
||||
HashSet<T> / HashMap<K,V>
|
||||
peuvent exiger des capacités de hash/égalité
|
||||
|
||||
TreeSet<T> / TreeMap<K,V>
|
||||
utilisent Comparable ou Comparator
|
||||
```
|
||||
|
||||
`Hashable`, l'égalité et leurs contrats exacts seront fermés dans le bloc dédié. Ils ne sont pas imposés à `Set<T>` ou `Map<K,V>` eux-mêmes.
|
||||
|
||||
### 22.4.16 Collections concurrentes
|
||||
|
||||
Les garanties concurrentes sont orthogonales aux capacités structurelles et relèvent du SDK.
|
||||
|
||||
Une future :
|
||||
|
||||
```text
|
||||
ConcurrentMap<K,V>
|
||||
```
|
||||
|
||||
exprime des garanties de concurrence/atomicité et ne remplace pas `ResizableMap<K,V>`.
|
||||
|
||||
Un type concret peut par exemple implémenter les deux :
|
||||
|
||||
```text
|
||||
ConcurrentHashMap<K,V>
|
||||
implements ResizableMap<K,V>, ConcurrentMap<K,V>
|
||||
```
|
||||
|
||||
Le SDK n'introduit pas une variante `ConcurrentX` pour chaque type uniquement par symétrie. Les interfaces concurrentes ne sont ajoutées que lorsqu'un contrat atomique/concurrent concret existe.
|
||||
|
||||
Une opération composée n'est pas atomique simplement parce que chaque appel individuel est thread-safe. Les futures opérations atomiques (`putIfAbsent`, comparaison/remplacement, etc.) seront spécifiées avec le modèle de concurrence.
|
||||
|
||||
## 22.5 `Range<T>` — V1 REQUIS — FIGÉ EN PRINCIPE
|
||||
|
||||
@@ -308,7 +639,7 @@ valeur finie autorisée
|
||||
|
||||
Les bornes sont évaluées de gauche à droite, exactement une fois chacune, avant la construction du range.
|
||||
|
||||
Une borne statiquement prouvée invalide provoque une erreur de compilation. Une borne calculée dynamiquement mais invalide selon le contrat de `Range<T>` provoque un runtime fault lors de la construction directe. Une API Core explicite retournant `Result` pourra être fournie lorsqu'une validation récupérable est souhaitée.
|
||||
Une borne statiquement prouvée invalide provoque une erreur de compilation. Une borne calculée dynamiquement mais invalide selon le contrat de `Range<T>` provoque un `Fault` runtime lors de la construction directe. Le nom concret du fault sera fixé avec l'API Core ; aucune variante `try... -> Result` parallèle n'est créée automatiquement pour la même validation.
|
||||
|
||||
`lower > upper` ne constitue pas une erreur : le résultat est un range vide.
|
||||
|
||||
@@ -392,7 +723,7 @@ RangeStep<Date,Duration>
|
||||
|
||||
et de refuser des couples qui introduiraient une perte ou n'auraient pas de sens. Par exemple, un range `float16` peut recevoir seulement les types de pas explicitement supportés sans imposer qu'un `float32` plus large soit accepté.
|
||||
|
||||
Le pas exprime une magnitude de progression, pas une direction. Pour les types numériques Core, il doit être strictement supérieur à zéro. Un pas statiquement nul ou négatif est une erreur de compilation ; une valeur dynamique invalide provoque un runtime fault lors de la construction directe de la progression. Une API explicite en `Result` pourra exister pour une validation récupérable.
|
||||
Le pas exprime une magnitude de progression, pas une direction. Pour les types numériques Core, il doit être strictement supérieur à zéro. Un pas statiquement nul ou négatif est une erreur de compilation ; une valeur dynamique invalide provoque un `Fault` runtime lors de la construction directe de la progression. Aucune variante `try... -> Result` n'est ajoutée uniquement pour dupliquer ce contrôle.
|
||||
|
||||
Pour les types utilisateur, la validité du pas est définie par le contrat Range correspondant et n'est pas réduite artificiellement à une comparaison numérique avec zéro.
|
||||
|
||||
|
||||
@@ -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`.
|
||||
|
||||
---
|
||||
|
||||
@@ -13,11 +13,13 @@ threads natifs
|
||||
structured concurrency éventuelle
|
||||
cancellation
|
||||
synchronisation
|
||||
interaction avec Result/throws
|
||||
interaction avec Result/throws/faults
|
||||
interaction avec destruction déterministe
|
||||
runtime minimal
|
||||
```
|
||||
|
||||
Aucune dépendance obligatoire à un executor monolithique ne doit être supposée sans justification.
|
||||
|
||||
Les collections concurrentes spécialisées relèvent du SDK et non d'une symétrie artificielle du Core. Une future `ConcurrentMap<K,V>` doit exprimer des garanties de concurrence/atomicité orthogonales aux capacités structurelles `Map` / `SettableMap` / `ResizableMap`. Des types tels que `ConcurrentHashMap<K,V>` ne seront introduits que lorsqu'un contrat concurrent concret le justifie.
|
||||
|
||||
---
|
||||
|
||||
@@ -66,11 +66,51 @@ unsafe field
|
||||
|
||||
Le caractère dangereux est porté par le type/opération.
|
||||
|
||||
## 27.4 Raw pointers — V1 REQUIS — À FINALISER
|
||||
## 27.4 Pointeurs et accès mémoire bas niveau — V1 REQUIS — À FINALISER CRITIQUE
|
||||
|
||||
Les pointeurs bruts existent explicitement et leurs opérations de dereference/arithmétique autorisées doivent être précisément définies.
|
||||
Le modèle mémoire contient un sous-ensemble dédié aux pointeurs ; il ne doit pas être confondu avec les références de classe ou `Slice<T>`.
|
||||
|
||||
Les noms des types (`Ptr<T>`, `PtrMut<T>` ou autre) restent à figer.
|
||||
La spécification devra distinguer au minimum :
|
||||
|
||||
```text
|
||||
référence de classe
|
||||
accès sûr ordinaire vers un objet
|
||||
|
||||
Slice<T>
|
||||
vue sûre, bornée et contiguë sur un stockage existant
|
||||
|
||||
pointeur Saselang
|
||||
adresse explicite avec contrat de type/mutabilité à définir
|
||||
|
||||
pointeur brut / FFI
|
||||
accès mémoire bas niveau potentiellement unsafe
|
||||
|
||||
function pointer
|
||||
représentation ABI d'une cible callable, distincte des callables/closures ordinaires
|
||||
```
|
||||
|
||||
Les noms exacts des types (`Ptr<T>`, `PtrMut<T>` ou autre) restent à figer.
|
||||
|
||||
Doivent être définis explicitement :
|
||||
|
||||
```text
|
||||
nullabilité et non-null par défaut éventuel
|
||||
const T pointé et constness du pointeur lui-même
|
||||
dereference
|
||||
address-of
|
||||
arithmétique de pointeurs
|
||||
alignement
|
||||
allocation/libération manuelles
|
||||
casts entre pointeurs
|
||||
conversion pointeur <-> entier si elle existe
|
||||
pointeur opaque / équivalent éventuel de void*
|
||||
function pointers
|
||||
FFI C
|
||||
ownership ou absence d'ownership attaché au pointeur
|
||||
interaction avec allocator, lifetime interne et thread safety
|
||||
```
|
||||
|
||||
Le code ordinaire ne doit pas avoir besoin de pointeurs explicites lorsque les références de classe, arrays, slices ou autres abstractions sûres suffisent. Les opérations dangereuses doivent rester dans l'inventaire fermé `unsafe`.
|
||||
|
||||
## 27.5 Allocator — V1 REQUIS — À FINALISER CRITIQUE
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ Les sorties qui déclenchent les `defer` du scope traversé comprennent notammen
|
||||
fin normale
|
||||
return
|
||||
throw
|
||||
Fault propagé
|
||||
break
|
||||
continue
|
||||
emit quittant le scope concerné
|
||||
@@ -46,12 +47,12 @@ La valeur d'un `return` ou d'un `emit` est déterminée avant l'exécution des c
|
||||
|
||||
## 28.2 Unwind et ordre avec `catch` / `finally` — V1 REQUIS — FIGÉ
|
||||
|
||||
Lorsqu'une `Exception` quitte un scope, les `defer` des scopes abandonnés sont exécutés avant l'entrée dans le `catch` correspondant.
|
||||
Lorsqu'une `Exception` ou un `Fault` capturable quitte un scope, les `defer` des scopes abandonnés sont exécutés avant l'entrée dans le `catch` correspondant, sous réserve des détails d'unwind de `Fault` encore à fermer avec le runtime.
|
||||
|
||||
Ordre conceptuel :
|
||||
|
||||
```text
|
||||
throw
|
||||
throw / Fault propagé
|
||||
-> unwind des scopes quittés
|
||||
-> defer de ces scopes, LIFO
|
||||
-> catch correspondant éventuel
|
||||
@@ -73,6 +74,7 @@ Sont interdits dans un `defer` lorsqu'ils quittent le bloc :
|
||||
```text
|
||||
return
|
||||
throw
|
||||
fault
|
||||
break
|
||||
continue
|
||||
emit
|
||||
@@ -80,6 +82,8 @@ emit
|
||||
|
||||
Aucune `Exception` non capturée ne peut sortir indirectement d'un `defer`. Une callable appelée depuis un `defer` et susceptible de lancer une `Exception` doit voir cette exception entièrement gérée à l'intérieur du bloc `defer`.
|
||||
|
||||
Un `fault` explicite est interdit dans un `defer` pour la même raison qu'un `throw` explicite : le cleanup ne doit pas volontairement remplacer une sortie déjà en cours. Un `Fault` dynamique produit indirectement reste possible car il est unchecked ; son interaction exacte avec l'unwind/destruction fait partie du modèle mémoire encore à fermer.
|
||||
|
||||
Un `ResultError` reste une simple valeur : un appel retournant `Result<T,E>` est autorisé dans un `defer`, sous réserve des règles normales de traitement de cette valeur.
|
||||
|
||||
## 28.4 `finally` versus `defer` — V1 REQUIS — FIGÉ
|
||||
@@ -94,4 +98,4 @@ Un `try/finally` sans `catch` est interdit précisément parce que `defer` couvr
|
||||
|
||||
Pas de `errdefer` séparé en V1.
|
||||
|
||||
`catch` gère les chemins d'`Exception`; `defer` gère le cleanup systématique du scope. Un troisième mécanisme serait redondant.
|
||||
`catch` gère les chemins d'`Exception` et de `Fault`; `defer` gère le cleanup systématique du scope. Un troisième mécanisme dédié uniquement à l'échec serait redondant.
|
||||
|
||||
@@ -214,7 +214,7 @@ désactiver les contrôles d'overflow définis par Saselang
|
||||
modifier la sémantique d'un index hors limites
|
||||
modifier l'ordre d'évaluation
|
||||
modifier la représentation sémantique des types
|
||||
changer les règles Result/throws
|
||||
changer les règles Result/throws/faults
|
||||
désactiver les vérifications de sûreté du langage
|
||||
faire varier la validité d'un programme Saselang autrement que par une limite propre au backend/target
|
||||
```
|
||||
|
||||
@@ -12,7 +12,9 @@ Pas de visibilité explicite.
|
||||
|
||||
`main` ne peut pas déclarer `throws`, même s'il retourne `Result`.
|
||||
|
||||
L'environnement top-level ne possède pas d'appelant Saselang capable de l'envelopper dans un `try/catch`.
|
||||
L'environnement top-level ne possède pas d'appelant Saselang capable d'assumer un contrat checked : toute `Exception` doit donc être gérée avant de quitter `main`.
|
||||
|
||||
`main` peut documenter des `Fault` par `faults`, comme toute callable. Un `Fault` non capturé atteint la frontière de l'unité d'exécution et provoque l'échec runtime correspondant.
|
||||
|
||||
## 42.2 `ExitCode` — V1 REQUIS — FIGÉ EN PRINCIPE
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ Les commentaires documentaires sont :
|
||||
/** documentation de bloc */
|
||||
```
|
||||
|
||||
Ils ont la même sémantique documentaire avec deux ergonomies d'écriture différentes. Saselang ne reprend pas la redondance Javadoc/PHPDoc consistant à dupliquer systématiquement la signature via `@param`, `@return` ou `@throws` ; `saseldoc` dérive ces informations du programme.
|
||||
Ils ont la même sémantique documentaire avec deux ergonomies d'écriture différentes. Saselang ne reprend pas la redondance Javadoc/PHPDoc consistant à dupliquer systématiquement la signature via `@param`, `@return`, `@throws` ou `@faults` ; `saseldoc` dérive ces informations du programme.
|
||||
|
||||
Une Saseldoc est autorisée uniquement lorsqu'elle est immédiatement attachée à une déclaration documentable. Elle n'est jamais un commentaire libre à l'intérieur d'un corps exécutable.
|
||||
|
||||
@@ -128,7 +128,7 @@ Un marqueur `@...` inconnu dans un commentaire documentaire ne doit pas faire é
|
||||
|
||||
La visibilité n'est pas réduite artificiellement à un ordre total lorsque les domaines `protected`, `module` et `package` ne sont pas sémantiquement comparables. L'interface de filtrage doit pouvoir exprimer les ensembles de visibilité nécessaires sans falsifier le modèle d'accès du langage.
|
||||
|
||||
Les signatures, types de paramètres, generics, visibilité, `Result`, `throws`, héritage et interfaces sont dérivés du modèle sémantique plutôt que redéclarés manuellement dans la Saseldoc.
|
||||
Les signatures, types de paramètres, generics, visibilité, `Result`, `throws`, `faults`, héritage et interfaces sont dérivés du modèle sémantique plutôt que redéclarés manuellement dans la Saseldoc.
|
||||
|
||||
Les formats exacts V1 restent à finaliser avec la CLI, mais un format de sortie n'implique jamais un outil séparé.
|
||||
|
||||
|
||||
@@ -41,16 +41,17 @@ Restent à fermer :
|
||||
|
||||
## 48.4 Erreurs
|
||||
|
||||
Points désormais largement figés : hiérarchie `Error` / `ResultError` / `Exception`, `Result::Ok` / `Result::Err`, contraintes de `Result<T,E>`, absence de `unwrap` et `?` V1, `throw` / `throws`, contrats d'override/interface, sélection ordonnée des `catch`, `finally` non-escaping, causes, i18n, code de `ResultError`, stack trace d'`Exception` liée au `throw`, et sémantique LIFO/non-escaping de `defer`.
|
||||
Points désormais largement figés : hiérarchie `Error` / `ResultError` / `Exception` / `Fault`, `Result::Ok` / `Result::Err`, contraintes de `Result<T,E>`, absence de `unwrap` et `?` V1, `throw` / `throws` pour les exceptions checked, `fault` / `faults` pour les faults unchecked, `catch` limité aux branches `Exception` et `Fault`, contrats d'override `throws`, causes, i18n, code de `ResultError`, stack trace diagnostique et sémantique LIFO/non-escaping de `defer`.
|
||||
|
||||
Restent à fermer :
|
||||
|
||||
- faute runtime/panic/fatal error ;
|
||||
- interaction exacte cleanup/destruction/unwind pendant un `Fault` ;
|
||||
- unité d'exécution exacte terminée par un `Fault` non capturé ;
|
||||
- constructors faillibles et construction partielle ;
|
||||
- interaction exacte cleanup/destruction pendant fault ;
|
||||
- ordre exact `defer` / destructeurs automatiques avec le modèle mémoire ;
|
||||
- représentation Core/runtime exacte de `I18nMessage`, `ResultErrorCode`, `StackTrace` et `StackFrame` ;
|
||||
- éventuels helpers Core futurs `expectOk` / `expectErr` seulement si un besoin réel est démontré.
|
||||
- politique de lint/documentation pour les `Fault` explicites non listés dans `faults` ;
|
||||
- éventuels helpers Core futurs de `Result` seulement si un besoin réel est démontré.
|
||||
|
||||
## 48.5 Contrôle de flux
|
||||
|
||||
@@ -97,7 +98,10 @@ Restent à fermer :
|
||||
## 48.9 Core/SDK
|
||||
|
||||
- frontière Core/SDK définitive ;
|
||||
- collections V1 ;
|
||||
- `Vector<T>` et interaction avec `Slice<T>` lors des reallocations ;
|
||||
- contrats `Hashable` / égalité et implémentations HashSet/HashMap ;
|
||||
- opérations avancées de bornes/ranges pour `SortedSet` / `SortedMap` ;
|
||||
- propagation formelle de `const` dans `View<T>`, `Option<T>`, `Iterator<T>` et autres wrappers ;
|
||||
- String encodings ;
|
||||
- regex ;
|
||||
- filesystem/network/process ;
|
||||
|
||||
@@ -13,8 +13,8 @@ Les futures décisions doivent respecter les invariants suivants :
|
||||
9. **Les types Core compiler-known restent peu nombreux.**
|
||||
10. **Le package, le namespace, le target, la feature, la capability et l'artifact restent des dimensions distinctes.**
|
||||
11. **Une collision de namespace entre packages ne doit jamais fusionner implicitement leurs types.**
|
||||
12. **Les erreurs récupérables utilisent `Result`; les opérations réellement infaillibles retournent directement leur valeur.**
|
||||
13. **`throws` n'existe que sur une callable retournant `Result`.**
|
||||
12. **`ResultError`, `Exception` et `Fault` sont trois mécanismes distincts : valeur d'échec explicite, propagation checked et échec unchecked capturable.**
|
||||
13. **`throws` ne contient que des `Exception` et reste indépendant du type de retour ; `faults` ne contient que des `Fault` et reste optionnel/non exhaustif.**
|
||||
14. **L'identité d'objet est distincte de l'égalité de valeur.**
|
||||
15. **Les opérateurs utilisateur passent uniquement par les contrats Core `Op...`.**
|
||||
16. **Les interfaces fournissent l'héritage multiple de contrats/comportements sans introduire un second système de traits.**
|
||||
@@ -34,5 +34,6 @@ Les futures décisions doivent respecter les invariants suivants :
|
||||
29. **Un array safe devient observable uniquement après initialisation complète.**
|
||||
30. **Une bibliothèque spécialisée peut être officielle sans appartenir au Core ou au SDK obligatoire ; son artifact normal reste une `.saselib`.**
|
||||
31. **Les dépendances natives de bootstrap peuvent être remplacées progressivement par des implémentations Saselang sans imposer leur architecture historique au langage.**
|
||||
32. **Lorsqu'une forme légèrement plus longue supprime un implicite ou une ambiguïté réelle, Saselang privilégie l'explicite.**
|
||||
|
||||
---
|
||||
|
||||
@@ -121,3 +121,8 @@ text::append("def"); // OK si append est une méthode mutante de String
|
||||
## DO / DON'T / WHY / compiler error / edge cases
|
||||
|
||||
À consolider progressivement avant la baseline publique V3 et à transformer, lorsque pertinent, en tests de conformité de la toolchain.
|
||||
|
||||
|
||||
## Explicite plutôt qu'ambigu
|
||||
|
||||
Lorsqu'une forme légèrement plus longue supprime un implicite ou une ambiguïté réelle, Saselang la préfère à une syntaxe plus courte.
|
||||
|
||||
@@ -19,7 +19,7 @@ unions
|
||||
tuples
|
||||
generics
|
||||
contrôle de flux
|
||||
erreurs/exceptions
|
||||
erreurs/exceptions/faults
|
||||
opérateurs
|
||||
unsafe
|
||||
scope
|
||||
@@ -38,6 +38,7 @@ Result<T,E>
|
||||
Error
|
||||
ResultError
|
||||
Exception
|
||||
Fault
|
||||
Option<T>
|
||||
Nullable<T>
|
||||
Range<T>
|
||||
@@ -46,10 +47,18 @@ RangeStep<T,Step>
|
||||
RangeReverse<T>
|
||||
RangeReverseStep<T,Step>
|
||||
RangeProgression<T,Step>
|
||||
PartialOrdering
|
||||
Ordering
|
||||
Comparable<T>
|
||||
Comparator<T>
|
||||
Op...
|
||||
Iterable<T>
|
||||
Iterator<T>
|
||||
View<T>
|
||||
Collection<T>
|
||||
List<T>
|
||||
Set<T>
|
||||
Map<K,V>
|
||||
Array<T>
|
||||
StaticArray<T,N>
|
||||
TypeInfo
|
||||
@@ -59,7 +68,7 @@ ExitCode
|
||||
### Exemple 3
|
||||
|
||||
```text
|
||||
collections
|
||||
collections concrètes/spécialisées au-delà des contrats fondamentaux Core
|
||||
encodages explicites
|
||||
regex
|
||||
filesystem
|
||||
|
||||
@@ -19,7 +19,10 @@ type de retour
|
||||
visibilité
|
||||
fallibilité / Result
|
||||
throws
|
||||
contraintes génériques pertinentes
|
||||
qualification const et contraintes génériques pertinentes
|
||||
|
||||
faults
|
||||
visible mais non checked / non exhaustif
|
||||
modificateurs contractuels pertinents
|
||||
```
|
||||
|
||||
|
||||
@@ -16,30 +16,35 @@ operator implémentation d'un contrat opérateur
|
||||
### Exemple 2
|
||||
|
||||
```text
|
||||
opération infaillible
|
||||
-> retourne directement T
|
||||
|
||||
opération pouvant produire une erreur récupérable
|
||||
-> retourne Result<T>
|
||||
ou Result<T,E>
|
||||
T
|
||||
T throws SomeException
|
||||
T faults SomeFault
|
||||
T throws SomeException faults SomeFault
|
||||
Result<T,E>
|
||||
Result<T,E> throws SomeException
|
||||
Result<T,E> faults SomeFault
|
||||
```
|
||||
|
||||
Le type de retour et le mécanisme d'échec sont indépendants.
|
||||
|
||||
### Exemple 3
|
||||
|
||||
```text
|
||||
method length() -> uint64
|
||||
method containsKey(K key) -> bool
|
||||
Object::sameInstance(Object other) -> bool
|
||||
func min(int32 a, int32 b) -> int32
|
||||
func readConfig(String path) -> Config
|
||||
throws IOException
|
||||
|
||||
method elementAt(uint64 index) -> T
|
||||
faults IndexOutOfBoundsFault
|
||||
```
|
||||
|
||||
### Exemple 4
|
||||
|
||||
```text
|
||||
func readFile(String path) -> Result<String, IoError>
|
||||
method parse(String input) -> Result<Value, ParseError>
|
||||
func parseExternalInput(String input) -> Result<Value, ParseError>
|
||||
```
|
||||
|
||||
`Result` reste utilisé lorsque l'échec doit être transporté comme une valeur.
|
||||
|
||||
### Exemple 5
|
||||
|
||||
```text
|
||||
|
||||
@@ -1,259 +1,159 @@
|
||||
# Exemples / DO-DON'T — Chapitre 18 — `Result`, erreurs et exceptions
|
||||
# Exemples / DO-DON'T — Chapitre 18 — `Result`, erreurs, exceptions et faults
|
||||
|
||||
> Document compagnon non normatif tant qu'une règle n'est pas explicitement référencée comme normative par le chapitre.
|
||||
> Document compagnon. Les exemples illustrent les règles du chapitre ; la formulation normative reste dans le chapitre lui-même.
|
||||
|
||||
## Exemples actuellement présents dans le chapitre
|
||||
|
||||
### Exemple 1
|
||||
## Hiérarchie
|
||||
|
||||
```text
|
||||
Object
|
||||
└── Error
|
||||
├── ResultError
|
||||
└── Exception
|
||||
├── Exception
|
||||
└── Fault
|
||||
```
|
||||
|
||||
### Exemple 2
|
||||
|
||||
```text
|
||||
public final class ParseError extends ResultError {
|
||||
}
|
||||
|
||||
public final class FileNotFoundException extends Exception {
|
||||
}
|
||||
```
|
||||
|
||||
### Exemple 3
|
||||
|
||||
```text
|
||||
message: String
|
||||
cause: Option<Error>
|
||||
i18nMessage: Option<I18nMessage>
|
||||
```
|
||||
|
||||
### Exemple 4
|
||||
|
||||
```text
|
||||
message
|
||||
message humain canonique / fallback
|
||||
|
||||
cause
|
||||
erreur causale purement informative
|
||||
peut contenir un ResultError ou une Exception
|
||||
n'est pas automatiquement propagée
|
||||
|
||||
i18nMessage
|
||||
clé et paramètres de localisation
|
||||
ne contient pas un tableau de traductions
|
||||
```
|
||||
|
||||
### Exemple 5
|
||||
|
||||
```text
|
||||
code: ResultErrorCode
|
||||
```
|
||||
|
||||
### Exemple 6
|
||||
|
||||
```text
|
||||
code -> stable, machine-readable, non localisé
|
||||
message -> humain, canonique / fallback
|
||||
i18nMessage -> localisation externe
|
||||
```
|
||||
|
||||
### Exemple 7
|
||||
|
||||
```text
|
||||
throw exception;
|
||||
```
|
||||
|
||||
### Exemple 8
|
||||
|
||||
```text
|
||||
Result::Ok(T)
|
||||
Result::Err(E)
|
||||
```
|
||||
|
||||
### Exemple 9
|
||||
|
||||
```text
|
||||
E doit être ResultError ou un descendant de ResultError
|
||||
```
|
||||
|
||||
### Exemple 10
|
||||
|
||||
```text
|
||||
Result<Data,ResultError>
|
||||
Result<Data,ParseError>
|
||||
Result<Void,ResultError>
|
||||
```
|
||||
|
||||
### Exemple 11
|
||||
|
||||
```text
|
||||
Result<Data,Error>
|
||||
Result<Data,Exception>
|
||||
Result<Data,FileNotFoundException>
|
||||
```
|
||||
|
||||
### Exemple 12
|
||||
|
||||
```text
|
||||
Result<T>
|
||||
```
|
||||
|
||||
### Exemple 13
|
||||
|
||||
```text
|
||||
Result<T,ResultError>
|
||||
```
|
||||
|
||||
### Exemple 14
|
||||
|
||||
```text
|
||||
return Result::Ok(value);
|
||||
return Result::Err(error);
|
||||
```
|
||||
|
||||
### Exemple 15
|
||||
|
||||
```text
|
||||
result::expectOk(...)
|
||||
result::expectErr(...)
|
||||
```
|
||||
|
||||
### Exemple 16
|
||||
|
||||
```text
|
||||
ResultError -> Exception
|
||||
Exception -> ResultError
|
||||
```
|
||||
|
||||
### Exemple 17
|
||||
|
||||
```text
|
||||
throw ParseException(..., Option::Some(parseError));
|
||||
```
|
||||
|
||||
### Exemple 18
|
||||
|
||||
```text
|
||||
catch (FileNotFoundException error) {
|
||||
return Result::Err(FileResultError(..., Option::Some(error)));
|
||||
public final class IndexOutOfBoundsFault extends Fault {
|
||||
}
|
||||
```
|
||||
|
||||
### Exemple 19
|
||||
## `ResultError`
|
||||
|
||||
DO : utiliser `Result` lorsque l'échec est une valeur normale à inspecter explicitement.
|
||||
|
||||
```text
|
||||
T + throws -> interdit
|
||||
Result<T,E> -> valide sans throws
|
||||
Result<T,E> + throws -> valide
|
||||
func parseExternalInput(String input) -> Result<Value, ParseError> {
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
### Exemple 20
|
||||
DON'T : placer une `Exception` ou un `Fault` dans le paramètre erreur de `Result`.
|
||||
|
||||
```text
|
||||
Result<Value,FileNotFoundException> // ERROR
|
||||
Result<Value,IndexOutOfBoundsFault> // ERROR
|
||||
```
|
||||
|
||||
## `Exception`, `throw` et `throws`
|
||||
|
||||
```text
|
||||
func readConfig(String path) -> Config
|
||||
throws IOException
|
||||
```
|
||||
|
||||
### Exemple 21
|
||||
|
||||
```text
|
||||
supprimer entièrement des exceptions déclarées
|
||||
restreindre une famille à une ou plusieurs sous-familles compatibles
|
||||
gérer localement tout ou partie des exceptions du contrat parent
|
||||
```
|
||||
|
||||
### Exemple 22
|
||||
|
||||
```text
|
||||
throw FileNotFoundException(...); // valide
|
||||
throw ParseError(...); // erreur
|
||||
throw Error(...); // erreur
|
||||
```
|
||||
|
||||
### Exemple 23
|
||||
|
||||
```text
|
||||
catch (IOException error) {
|
||||
throw error;
|
||||
{
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
### Exemple 24
|
||||
Un retour direct est compatible avec `throws`.
|
||||
|
||||
```text
|
||||
try { ... }
|
||||
try { ... } finally { ... }
|
||||
finally { ... }
|
||||
throw FileNotFoundException(...); // OK
|
||||
throw IndexOutOfBoundsFault(...); // ERROR
|
||||
throw ParseError(...); // ERROR
|
||||
```
|
||||
|
||||
### Exemple 25
|
||||
## `Fault`, `fault` et `faults`
|
||||
|
||||
```text
|
||||
method elementAt(uint64 index) -> T
|
||||
faults IndexOutOfBoundsFault
|
||||
{
|
||||
if (index >= this::length()) {
|
||||
fault IndexOutOfBoundsFault(index, this::length());
|
||||
}
|
||||
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
La clause `faults` est optionnelle et non exhaustive.
|
||||
|
||||
DO : appeler sans cérémonie lorsque le fault n'est pas un chemin normal à traiter.
|
||||
|
||||
```text
|
||||
T value = list::elementAt(index);
|
||||
```
|
||||
|
||||
DO : capturer explicitement lorsque le programme veut réellement récupérer ce cas.
|
||||
|
||||
```text
|
||||
try {
|
||||
...
|
||||
} catch (SpecificException error) {
|
||||
...
|
||||
} catch (ParentException error) {
|
||||
...
|
||||
} finally {
|
||||
T value = list::elementAt(index);
|
||||
} catch (IndexOutOfBoundsFault faultValue) {
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
### Exemple 26
|
||||
Aucune propagation de `faults` n'est obligatoire :
|
||||
|
||||
```text
|
||||
catch (FileNotFoundException error) {
|
||||
...
|
||||
} catch (IOException error) {
|
||||
...
|
||||
func outer() -> Void {
|
||||
inner(); // inner peut déclarer faults SomeFault
|
||||
return Void;
|
||||
}
|
||||
```
|
||||
|
||||
### Exemple 27
|
||||
## `catch`
|
||||
|
||||
Valide :
|
||||
|
||||
```text
|
||||
catch (IOException error) {
|
||||
...
|
||||
} catch (FileNotFoundException error) {
|
||||
}
|
||||
|
||||
catch (IteratorInvalidatedFault faultValue) {
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
### Exemple 28
|
||||
Invalide :
|
||||
|
||||
```text
|
||||
fin normale du try
|
||||
fin normale d'un catch
|
||||
return traversant la construction
|
||||
throw propagé
|
||||
break / continue traversant la construction
|
||||
Exception non capturée par les catch
|
||||
catch (Error error) // ERROR
|
||||
catch (ResultError error) // ERROR
|
||||
```
|
||||
|
||||
### Exemple 29
|
||||
`catch` ne peut cibler que `Exception`, `Fault` ou leurs descendants.
|
||||
|
||||
## Direct versus valeur conditionnelle
|
||||
|
||||
Accès affirmatif :
|
||||
|
||||
```text
|
||||
return
|
||||
throw
|
||||
break
|
||||
continue
|
||||
emit
|
||||
User user = users[id]; // absence -> KeyNotFoundFault
|
||||
```
|
||||
|
||||
### Exemple 30
|
||||
Absence normale :
|
||||
|
||||
```text
|
||||
index hors limites
|
||||
division entière par zéro
|
||||
overflow checked
|
||||
représentation mémoire invalide
|
||||
borne dynamique invalide lors d'une construction directe lorsque la règle du type le définit
|
||||
Option<User> user = users::get(id);
|
||||
```
|
||||
|
||||
## DO / DON'T / WHY / compiler error / edge cases
|
||||
Le Core ne doit pas créer automatiquement une variante `tryOp()` uniquement pour transporter le même échec dans `Result`.
|
||||
|
||||
La couverture structurée de cette section sera enrichie au fur et à mesure de la fermeture des règles du chapitre. La migration `0.2.12` conserve volontairement les exemples historiques dans le chapitre afin de ne perdre aucun contexte normatif.
|
||||
## Erreur statique versus fault runtime
|
||||
|
||||
```text
|
||||
StaticArray<int32,3> values = [1, 2, 3];
|
||||
int32 a = values[5]; // ERROR compilation
|
||||
```
|
||||
|
||||
```text
|
||||
uint64 index = readIndex();
|
||||
int32 b = values[index]; // peut produire IndexOutOfBoundsFault au runtime
|
||||
```
|
||||
|
||||
Un statement `fault` explicite reste évidemment valide :
|
||||
|
||||
```text
|
||||
if (!state::isValid()) {
|
||||
fault InvalidStateFault(...);
|
||||
}
|
||||
```
|
||||
|
||||
@@ -91,12 +91,18 @@ transitive
|
||||
### Exemple 11
|
||||
|
||||
```text
|
||||
public enum Ordering {
|
||||
public enum PartialOrdering {
|
||||
Less,
|
||||
Equal,
|
||||
Greater,
|
||||
Unordered
|
||||
}
|
||||
|
||||
public enum Ordering {
|
||||
Less,
|
||||
Equal,
|
||||
Greater
|
||||
}
|
||||
```
|
||||
|
||||
### Exemple 12
|
||||
@@ -124,8 +130,11 @@ container[index] = value
|
||||
|
||||
```text
|
||||
Map<K,V>
|
||||
OpIndex<K,Option<V>>
|
||||
OpIndex<K,V>
|
||||
OpIndexMut<K,V>
|
||||
|
||||
map[key] // strict, absent -> KeyNotFoundFault
|
||||
map::get(key) // Option<V>
|
||||
```
|
||||
|
||||
### Exemple 16
|
||||
|
||||
@@ -78,12 +78,12 @@ char::toUtf8Char()
|
||||
Utf8Char::toChar()
|
||||
Utf8Char::toUtf16Char()
|
||||
|
||||
Utf8Char::tryFrom(uint8)
|
||||
Utf16Char::tryFrom(uint16)
|
||||
Utf32Char::tryFrom(uint32)
|
||||
Utf8Char::from(uint8) faults UnicodeEncodingFault
|
||||
Utf16Char::from(uint16) faults UnicodeEncodingFault
|
||||
Utf32Char::from(uint32) faults UnicodeEncodingFault
|
||||
|
||||
Utf8Char::tryToUint8()
|
||||
Utf16Char::tryToUint16()
|
||||
Utf8Char::toUint8() faults UnicodeEncodingFault
|
||||
Utf16Char::toUint16() faults UnicodeEncodingFault
|
||||
Utf32Char::toUint32()
|
||||
```
|
||||
|
||||
|
||||
@@ -158,7 +158,82 @@ Vector<T>
|
||||
ResizableList<T>
|
||||
```
|
||||
|
||||
### Exemple 18
|
||||
### Exemple 18 — `Iterator<T>`
|
||||
|
||||
```text
|
||||
interface Iterable<T> {
|
||||
const method iterator() -> Iterator<T>;
|
||||
}
|
||||
|
||||
interface Iterator<T> {
|
||||
method next() -> Option<T>;
|
||||
}
|
||||
```
|
||||
|
||||
### Exemple 19 — `View<T>`
|
||||
|
||||
```text
|
||||
interface View<T> extends Iterable<T> {
|
||||
const method count() -> uint64;
|
||||
const method isEmpty() -> bool;
|
||||
}
|
||||
```
|
||||
|
||||
`View<T>` n'impose pas `contains()`.
|
||||
|
||||
### Exemple 20 — Set
|
||||
|
||||
```text
|
||||
ResizableSet<T>::add(T value) -> bool
|
||||
ResizableSet<T>::remove(const T value) -> bool
|
||||
ResizableSet<T>::clear() -> uint64
|
||||
```
|
||||
|
||||
### Exemple 21 — Map
|
||||
|
||||
```text
|
||||
map[key] -> V // strict
|
||||
map::get(key) -> Option<V> // conditionnel
|
||||
map[key] = value // remplacement seulement
|
||||
map::insert(key, value) // clé nouvelle, DuplicateKeyFault sinon
|
||||
map::remove(key) // clé existante, KeyNotFoundFault sinon
|
||||
map::clear() -> uint64
|
||||
```
|
||||
|
||||
### Exemple 22 — Vues de Map
|
||||
|
||||
```text
|
||||
map::keys() -> View<K>
|
||||
map::values() -> View<V>
|
||||
map::entries() -> View<MapEntry<K,V>>
|
||||
```
|
||||
|
||||
### Exemple 23 — Ordre
|
||||
|
||||
```text
|
||||
enum Ordering {
|
||||
Less,
|
||||
Equal,
|
||||
Greater
|
||||
}
|
||||
|
||||
Comparable<T>
|
||||
Comparator<T>
|
||||
SortedSet<T>
|
||||
SortedMap<K,V>
|
||||
```
|
||||
|
||||
### Exemple 24 — Factories ordonnées
|
||||
|
||||
```text
|
||||
TreeSet<T>::natural()
|
||||
TreeSet<T>::withComparator(comparator)
|
||||
|
||||
TreeMap<K,V>::natural()
|
||||
TreeMap<K,V>::withComparator(comparator)
|
||||
```
|
||||
|
||||
## Exemples Range
|
||||
|
||||
```text
|
||||
a..b [a, b] bornes basse et haute incluses
|
||||
@@ -167,13 +242,13 @@ a..<b [a, b) borne basse incluse, borne haute exclue
|
||||
a>..<b (a, b) bornes basse et haute exclues
|
||||
```
|
||||
|
||||
### Exemple 19
|
||||
### Range 1
|
||||
|
||||
```text
|
||||
Range<uint64> ids = 1..100;
|
||||
```
|
||||
|
||||
### Exemple 20
|
||||
### Range 2
|
||||
|
||||
```text
|
||||
NaN interdit comme borne
|
||||
@@ -182,7 +257,7 @@ NaN interdit comme borne
|
||||
valeur finie autorisée
|
||||
```
|
||||
|
||||
### Exemple 21
|
||||
### Range 3
|
||||
|
||||
```text
|
||||
a..a contient exactement a
|
||||
@@ -191,7 +266,7 @@ a..<a vide
|
||||
a>..<a vide
|
||||
```
|
||||
|
||||
### Exemple 22
|
||||
### Range 4
|
||||
|
||||
```text
|
||||
range::lower()
|
||||
@@ -202,7 +277,7 @@ range::isEmpty()
|
||||
range::contains(value)
|
||||
```
|
||||
|
||||
### Exemple 23
|
||||
### Range 5
|
||||
|
||||
```text
|
||||
Range<T> intervalle ordonné
|
||||
@@ -213,13 +288,13 @@ RangeReverseStep<T,Step> parcours arrière avec pas explicite
|
||||
RangeProgression<T,Step> valeur de progression produite
|
||||
```
|
||||
|
||||
### Exemple 24
|
||||
### Range 6
|
||||
|
||||
```text
|
||||
(range)::step(step)
|
||||
```
|
||||
|
||||
### Exemple 25
|
||||
### Range 7
|
||||
|
||||
```text
|
||||
RangeStep<int32,int32>
|
||||
@@ -228,14 +303,14 @@ RangeStep<char,uint32>
|
||||
RangeStep<Date,Duration>
|
||||
```
|
||||
|
||||
### Exemple 26
|
||||
### Range 8
|
||||
|
||||
```text
|
||||
(range)::reverse()
|
||||
(range)::reverse()::step(step)
|
||||
```
|
||||
|
||||
### Exemple 27
|
||||
### Range 9
|
||||
|
||||
```text
|
||||
range
|
||||
@@ -243,25 +318,25 @@ range
|
||||
[::step(step)]
|
||||
```
|
||||
|
||||
### Exemple 28
|
||||
### Range 10
|
||||
|
||||
```text
|
||||
(250u8..255u8)::step(2u8)
|
||||
```
|
||||
|
||||
### Exemple 29
|
||||
### Range 11
|
||||
|
||||
```text
|
||||
250 252 254
|
||||
```
|
||||
|
||||
### Exemple 30
|
||||
### Range 12
|
||||
|
||||
```text
|
||||
(1..10)::step(4)
|
||||
```
|
||||
|
||||
### Exemple 31
|
||||
### Range 13
|
||||
|
||||
```text
|
||||
1 5 9
|
||||
|
||||
@@ -2,17 +2,7 @@
|
||||
|
||||
> Document compagnon. Les exemples illustrent les règles du chapitre ; la formulation normative reste dans le chapitre lui-même.
|
||||
|
||||
## Exemples extraits du chapitre
|
||||
|
||||
### Exemple 1
|
||||
|
||||
```text
|
||||
conversion de valeur
|
||||
cast de hiérarchie nominale
|
||||
bitcast de représentation binaire
|
||||
```
|
||||
|
||||
### Exemple 2
|
||||
## Conversion explicite
|
||||
|
||||
```text
|
||||
int8 small = ...;
|
||||
@@ -20,82 +10,94 @@ int32 large = small; // ERROR
|
||||
int32 explicitLarge = small::toInt32(); // OK
|
||||
```
|
||||
|
||||
### Exemple 3
|
||||
## Widening total
|
||||
|
||||
```text
|
||||
Dog dog = ...;
|
||||
Animal animal = dog;
|
||||
Serializable serializable = dog;
|
||||
int8 value = ...;
|
||||
int32 larger = value::toInt32();
|
||||
```
|
||||
|
||||
### Exemple 4
|
||||
Aucun `tryToInt32()` parallèle n'est nécessaire si toutes les valeurs source sont exactement représentables.
|
||||
|
||||
## Narrowing exact avec `Fault`
|
||||
|
||||
```text
|
||||
Animal animal = ...;
|
||||
|
||||
if (animal is Dog) {
|
||||
// animal est raffiné en Dog ici.
|
||||
}
|
||||
int32 value = ...;
|
||||
int8 smaller = value::toInt8();
|
||||
```
|
||||
|
||||
### Exemple 5
|
||||
La signature Core peut déclarer :
|
||||
|
||||
```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
|
||||
toInt8() -> int8
|
||||
faults NumericConversionFault
|
||||
```
|
||||
|
||||
### Exemple 6
|
||||
`OutOfRange` est produit lorsque la valeur ne tient pas dans `int8`.
|
||||
|
||||
## Politiques distinctes
|
||||
|
||||
```text
|
||||
tryToIntXX()
|
||||
tryToUintXX()
|
||||
value::toInt8() // exact, peut fault
|
||||
value::saturateToInt8()
|
||||
value::wrapToInt8()
|
||||
```
|
||||
|
||||
### Exemple 7
|
||||
Ces opérations coexistent seulement lorsque leur résultat peut réellement différer.
|
||||
|
||||
## Flottant vers entier
|
||||
|
||||
```text
|
||||
floor()
|
||||
ceil()
|
||||
round()
|
||||
truncate()
|
||||
float64 value = ...;
|
||||
|
||||
int32 exact = value::toInt32();
|
||||
```
|
||||
|
||||
### Exemple 8
|
||||
La conversion exige une valeur finie, intégrale et dans la plage.
|
||||
|
||||
Pour choisir explicitement une politique mathématique :
|
||||
|
||||
```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()
|
||||
```
|
||||
|
||||
### Exemple 9
|
||||
Pour choisir la politique de plage :
|
||||
|
||||
```text
|
||||
value::floor()::trySaturateToInt32()
|
||||
value::round()::tryWrapToInt32()
|
||||
value::floor()::saturateToInt32()
|
||||
value::round()::wrapToInt32()
|
||||
```
|
||||
|
||||
### Exemple 10
|
||||
## Entier vers flottant
|
||||
|
||||
```text
|
||||
int64 value = ...;
|
||||
|
||||
float64 exact = value::toFloat64();
|
||||
float64 approximated = value::roundToFloat64();
|
||||
```
|
||||
|
||||
`toFloat64()` exige l'exactitude ; `roundToFloat64()` accepte explicitement la perte de précision.
|
||||
|
||||
## Flottant vers flottant
|
||||
|
||||
```text
|
||||
toFloatXX()
|
||||
exige l'exactitude
|
||||
|
||||
roundToFloatXX()
|
||||
accepte l'arrondi canonique
|
||||
peut fault OutOfRange sur une valeur finie
|
||||
|
||||
saturatingRoundToFloatXX()
|
||||
accepte l'arrondi canonique
|
||||
sature une valeur finie hors domaine
|
||||
```
|
||||
|
||||
Les catégories suivantes sont préservées :
|
||||
|
||||
```text
|
||||
NaN -> NaN
|
||||
@@ -105,31 +107,13 @@ NaN -> NaN
|
||||
-0 -> -0
|
||||
```
|
||||
|
||||
### Exemple 11
|
||||
## `NumericConversionFault`
|
||||
|
||||
```text
|
||||
payload NaN
|
||||
quiet/signaling bit
|
||||
signe du NaN
|
||||
représentation binaire exacte
|
||||
NumericConversionFault extends Fault
|
||||
```
|
||||
|
||||
### Exemple 12
|
||||
|
||||
```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
|
||||
```
|
||||
|
||||
### Exemple 13
|
||||
Codes :
|
||||
|
||||
```text
|
||||
NotFinite
|
||||
@@ -138,40 +122,10 @@ OutOfRange
|
||||
Inexact
|
||||
```
|
||||
|
||||
### Exemple 14
|
||||
DON'T : introduire mécaniquement :
|
||||
|
||||
```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
|
||||
tryToTarget() -> Result<Target,NumericConversionError>
|
||||
```
|
||||
|
||||
### Exemple 15
|
||||
|
||||
```text
|
||||
sourceType
|
||||
targetType
|
||||
sourceValue
|
||||
timestamp
|
||||
backend
|
||||
roundingMode
|
||||
```
|
||||
|
||||
### Exemple 16
|
||||
|
||||
```text
|
||||
annexes/A-numeric-conversions.md
|
||||
```
|
||||
|
||||
## DO / DON'T / WHY / compiler error / edge cases
|
||||
|
||||
À consolider progressivement avant la baseline publique V3 et à transformer, lorsque pertinent, en tests de conformité de la toolchain.
|
||||
si cette méthode ne ferait que dupliquer `toTarget() faults NumericConversionFault`.
|
||||
|
||||
@@ -13,7 +13,7 @@ threads natifs
|
||||
structured concurrency éventuelle
|
||||
cancellation
|
||||
synchronisation
|
||||
interaction avec Result/throws
|
||||
interaction avec Result/throws/faults
|
||||
interaction avec destruction déterministe
|
||||
runtime minimal
|
||||
```
|
||||
|
||||
@@ -51,3 +51,16 @@ ownership annotations pour les usages ordinaires
|
||||
## DO / DON'T / WHY / compiler error / edge cases
|
||||
|
||||
À consolider progressivement avant la baseline publique V3 et à transformer, lorsque pertinent, en tests de conformité de la toolchain.
|
||||
|
||||
|
||||
## Pointeurs — distinctions à préserver
|
||||
|
||||
```text
|
||||
référence de classe
|
||||
Slice<T>
|
||||
pointeur Saselang
|
||||
pointeur brut / FFI
|
||||
function pointer
|
||||
```
|
||||
|
||||
Les pointeurs explicites restent un sous-modèle mémoire dédié et ne remplacent pas les références/slices sûres dans le code ordinaire.
|
||||
|
||||
@@ -65,3 +65,14 @@ emit
|
||||
## DO / DON'T / WHY / compiler error / edge cases
|
||||
|
||||
La couverture structurée de cette section sera enrichie au fur et à mesure de la fermeture des règles du chapitre. La migration `0.2.12` conserve volontairement les exemples historiques dans le chapitre afin de ne perdre aucun contexte normatif.
|
||||
|
||||
|
||||
## Fault et cleanup
|
||||
|
||||
```text
|
||||
defer {
|
||||
fault CleanupFault(...); // ERROR : fault explicite escaping
|
||||
}
|
||||
```
|
||||
|
||||
Un `Fault` dynamique produit indirectement reste possible car il est unchecked ; l'ordre exact d'unwind/destruction est encore à fermer.
|
||||
|
||||
@@ -162,7 +162,7 @@ désactiver les contrôles d'overflow définis par Saselang
|
||||
modifier la sémantique d'un index hors limites
|
||||
modifier l'ordre d'évaluation
|
||||
modifier la représentation sémantique des types
|
||||
changer les règles Result/throws
|
||||
changer les règles Result/throws/faults
|
||||
désactiver les vérifications de sûreté du langage
|
||||
faire varier la validité d'un programme Saselang autrement que par une limite propre au backend/target
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user