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.**
|
> **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+.
|
> 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
|
## Organisation de cette distribution
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
# Sommaire — Bible Saselang 0.2.16
|
# Sommaire — Bible Saselang 0.2.17
|
||||||
|
|
||||||
## Chapitres
|
## 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
|
## 0.2.16
|
||||||
|
|
||||||
|
|||||||
130
MANIFEST.toml
130
MANIFEST.toml
@@ -1,65 +1,153 @@
|
|||||||
format = 1
|
format = 1
|
||||||
version = "0.2.16"
|
version = "0.2.17"
|
||||||
distribution = "delta"
|
distribution = "delta"
|
||||||
base_version = "0.2.15"
|
base_version = "0.2.16"
|
||||||
documentation_layout = "multifile"
|
documentation_layout = "multifile"
|
||||||
|
|
||||||
[[modified]]
|
[[modified]]
|
||||||
path = "000-README.md"
|
path = "000-README.md"
|
||||||
sha256 = "4b4d422dcc52991e38c6cb1b7b92aeb391ca0b7d6bc1c8da0de4de6169c93b7a"
|
sha256 = "ca87a3caaadb1a618f0a35620a2e62e406bd8e186de0a7282e606a38f9f541ca"
|
||||||
|
|
||||||
[[modified]]
|
[[modified]]
|
||||||
path = "001-SUMMARY.md"
|
path = "001-SUMMARY.md"
|
||||||
sha256 = "2cf8811903512dc58739c4d16e2696d10bcb36f2b767d3e5eccf038013ef1a66"
|
sha256 = "88f6f80b7233900491f15d818cebbfdb3fc83f02667cfa137cb3ed6a17f86edf"
|
||||||
|
|
||||||
[[modified]]
|
[[modified]]
|
||||||
path = "003-CHANGELOG.md"
|
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]]
|
[[modified]]
|
||||||
path = "chapters/004-couches-de-lecosysteme-v1.md"
|
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]]
|
[[modified]]
|
||||||
path = "chapters/021-strings-unicode-et-encodages.md"
|
path = "chapters/021-strings-unicode-et-encodages.md"
|
||||||
sha256 = "3350f8581eb43343136caf7cf808b25da4543edac6b176ad61d3e40292b19d76"
|
sha256 = "c8e5ea1e1fce5fe3128d7dd1eb73ddd784b71d3fa24298de9bfabc1d44e05327"
|
||||||
|
|
||||||
[[modified]]
|
[[modified]]
|
||||||
path = "chapters/022-collections-et-iteration.md"
|
path = "chapters/022-collections-et-iteration.md"
|
||||||
sha256 = "a60534eef7f12201b238c7a4899b46c8be4df3535f293978e05471cc210c3d7a"
|
sha256 = "e7459c2db8d0fe0cdf573d25f888c1791b6d03a9de6f51ae849991039abc4328"
|
||||||
|
|
||||||
[[modified]]
|
[[modified]]
|
||||||
path = "chapters/037-dependances-et-scopes.md"
|
path = "chapters/024-casts-et-conversions.md"
|
||||||
sha256 = "64335ed6b00a8133718384e49b34be0f362569b9b177a35da963543abe603a9a"
|
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]]
|
[[modified]]
|
||||||
path = "chapters/048-inventaire-des-points-v1-encore-ouverts.md"
|
path = "chapters/048-inventaire-des-points-v1-encore-ouverts.md"
|
||||||
sha256 = "3c99a2d2901e5843b4ea40b26c541203c907a809ad2004fd93c0ad4a94a68413"
|
sha256 = "908856acb0472c2c4eee3d03b8260f21b5b6495d342053f371b00e54158ed2d1"
|
||||||
|
|
||||||
[[modified]]
|
[[modified]]
|
||||||
path = "chapters/051-invariants-de-conception.md"
|
path = "chapters/051-invariants-de-conception.md"
|
||||||
sha256 = "05c23658ea2b127c023b5d75630bd79096934d21f04f67f01375486fd35386e4"
|
sha256 = "c41f6c977c613631147b7d61c837afccc9b1c6807d62ade8175865f5108bf915"
|
||||||
|
|
||||||
|
[[modified]]
|
||||||
|
path = "examples/002-principes-generaux-du-langage-examples.md"
|
||||||
|
sha256 = "42b5758d733563c0bdabad9f6005f5818ccb42513e599bc878142db6b4298e10"
|
||||||
|
|
||||||
[[modified]]
|
[[modified]]
|
||||||
path = "examples/004-couches-de-lecosysteme-v1-examples.md"
|
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]]
|
[[modified]]
|
||||||
path = "examples/021-strings-unicode-et-encodages-examples.md"
|
path = "examples/021-strings-unicode-et-encodages-examples.md"
|
||||||
sha256 = "e065baa54cd9203f9b37883f5c418baea27ffc0fe4d28e97ff349a1b66f8adc7"
|
sha256 = "6ed3cd078599b329b5f8f42ceda323eadc954f3d7d566e177adca56451a2345b"
|
||||||
|
|
||||||
[[modified]]
|
[[modified]]
|
||||||
path = "examples/022-collections-et-iteration-examples.md"
|
path = "examples/022-collections-et-iteration-examples.md"
|
||||||
sha256 = "86749fa6c85fbfbc2cd18643ad1da639af76222845ebf4418e62f7744cb76003"
|
sha256 = "f3546d35335937506044a697ff1610da20823bf29334c307d6cf7a53122d8ce3"
|
||||||
|
|
||||||
[[modified]]
|
[[modified]]
|
||||||
path = "examples/037-dependances-et-scopes-examples.md"
|
path = "examples/024-casts-et-conversions-examples.md"
|
||||||
sha256 = "a384f5a4c624f75f7a52186c731fc95890fb0ee5067788b4f93b90b0989774e1"
|
sha256 = "47a4d0e0e7fd822995be140d62432f48642da237d026551fc922f011776d1b8b"
|
||||||
|
|
||||||
[[modified]]
|
[[modified]]
|
||||||
path = "examples/048-inventaire-des-points-v1-encore-ouverts-examples.md"
|
path = "examples/026-async-et-concurrence-examples.md"
|
||||||
sha256 = "069383c40e74b495cdd3ccbebd87850654fa1ef4b6095e93a4eab14acb5d1f3d"
|
sha256 = "0a206a6b7ee2818a1e743b0dc1a033b27ebd75f543b9979d9c7fa37150c30255"
|
||||||
|
|
||||||
[[modified]]
|
[[modified]]
|
||||||
path = "examples/051-invariants-de-conception-examples.md"
|
path = "examples/027-memoire-references-et-unsafe-examples.md"
|
||||||
sha256 = "307da7506d8411f033cfcfbf5fc555651175e28e64119e248a1c4d341afa487f"
|
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
|
# 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.
|
Cette annexe inventorie les conversions numériques Core sémantiquement distinctes sans créer d'alias ou de doublons inutiles.
|
||||||
Son objectif est d'énumérer le maximum de conversions numériques sémantiquement distinctes sans introduire d'alias ou de doublons inutiles.
|
|
||||||
|
|
||||||
## A.1. Répartition des responsabilités
|
## 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
|
```text
|
||||||
Bible langage / compilateur
|
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
|
Core
|
||||||
expose les membres numériques concrets
|
expose les membres numériques concrets
|
||||||
ex. int32::tryToInt8(), float64::tryRoundToFloat32()
|
ex. int32::toInt8(), float64::roundToFloat32()
|
||||||
|
|
||||||
Annexe Core
|
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
|
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.
|
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.
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
## A.2. Règle de non-redondance
|
## 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 :
|
Exemple :
|
||||||
|
|
||||||
```saselang
|
```text
|
||||||
int8 value = ...;
|
int8 value = ...;
|
||||||
int32 larger = value::toInt32();
|
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
|
```text
|
||||||
tryToInt32()
|
toInt8() // exact, peut fault OutOfRange
|
||||||
saturateToInt32()
|
saturateToInt8()
|
||||||
wrapToInt32()
|
wrapToInt8()
|
||||||
```
|
```
|
||||||
|
|
||||||
En revanche, pour `int32 -> int8`, `tryToInt8()`, `saturateToInt8()` et `wrapToInt8()` ont trois contrats différents et peuvent coexister.
|
Règle de composition :
|
||||||
|
|
||||||
|
|
||||||
Une règle de composition complète cette non-redondance :
|
|
||||||
|
|
||||||
> 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.
|
> 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 |
|
| Code | Famille | Contrat |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `T` | `toTarget()` | Exacte et totale pour toutes les valeurs valides du type source. |
|
| `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. |
|
| `E` | `toTarget()` | Exacte pour la valeur courante ; `faults NumericConversionFault` si impossible. |
|
||||||
| `R` | `roundToTarget()` | Perte de précision explicitement acceptée ; conversion totale pour cette paire de types. |
|
| `R` | `roundToTarget()` | Perte de précision explicitement acceptée ; totale pour cette paire. |
|
||||||
| `TR` | `tryRoundToTarget()` | Arrondi explicitement accepté, mais la valeur peut être hors du domaine destination. |
|
| `FR` | `roundToTarget()` | Arrondi accepté ; peut fault si la valeur est hors du domaine destination. |
|
||||||
| `S` | `saturateToTarget()` | Conversion totale par saturation lorsqu'aucun arrondi supplémentaire n'est nécessaire. |
|
| `S` | `saturateToTarget()` | Saturation explicite 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. |
|
| `SR` | `saturatingRoundToTarget()` | Arrondi canonique + saturation explicites. |
|
||||||
| `W` | `wrapToTarget()` | Conversion entière modulo `2^N`, avec interprétation selon le type entier destination. |
|
| `W` | `wrapToTarget()` | Conversion entière modulo `2^N`. |
|
||||||
| `—` | aucune | Même type ou opération sans sémantique distincte utile. |
|
| `—` | 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 :
|
## A.5. Flottants : hypothèses de représentation
|
||||||
|
|
||||||
```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
|
|
||||||
|
|
||||||
| Type | Précision significative `p` | Exposant maximal fini |
|
| Type | Précision significative `p` | Exposant maximal fini |
|
||||||
|---|---|---|
|
|---|---:|---:|
|
||||||
| `float16` | 11 bits | 15 |
|
| `float16` | 11 bits | 15 |
|
||||||
| `float32` | 24 bits | 127 |
|
| `float32` | 24 bits | 127 |
|
||||||
| `float64` | 53 bits | 1023 |
|
| `float64` | 53 bits | 1023 |
|
||||||
| `float128` | 113 bits | 16383 |
|
| `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 :
|
Légende :
|
||||||
|
|
||||||
- `T` = `toTarget()` uniquement ;
|
```text
|
||||||
- `E+S+W` = `tryToTarget()` + `saturateToTarget()` + `wrapToTarget()`.
|
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 |
|
| Source \ Destination | int8 | int16 | int32 | int64 | int128 | int256 | uint8 | uint16 | uint32 | uint64 | uint128 | uint256 |
|
||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
||||||
@@ -114,95 +129,104 @@ Légende :
|
|||||||
|
|
||||||
Règles :
|
Règles :
|
||||||
|
|
||||||
- si le domaine source est entièrement inclus dans le domaine destination, seule la forme `to...` existe ;
|
- domaine source entièrement inclus -> `to...` total ;
|
||||||
- sinon `tryTo...` effectue une conversion exacte conditionnelle ;
|
- sinon `to...` reste exact mais peut produire `OutOfRange` ;
|
||||||
- `saturateTo...` borne à `Target::Min` / `Target::Max` ; pour un signé vers non signé, toute valeur négative sature à `0` ;
|
- `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`, indépendante de la représentation machine du backend ;
|
- `wrapTo...` utilise une définition mathématique modulo `2^N` ;
|
||||||
- aucun wrapping ni saturation n'est implicite.
|
- aucun wrapping ni saturation n'est implicite.
|
||||||
|
|
||||||
## A.6. Entier -> flottant
|
## A.7. Entier -> flottant
|
||||||
|
|
||||||
Légende :
|
Légende :
|
||||||
|
|
||||||
- `T` = `toFloatXX()` uniquement ;
|
```text
|
||||||
- `E+R` = `tryToFloatXX()` + `roundToFloatXX()` ;
|
T
|
||||||
- `E+TR+SR` = `tryToFloatXX()` + `tryRoundToFloatXX()` + `saturatingRoundToFloatXX()`.
|
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 |
|
| Source \ Destination | float16 | float32 | float64 | float128 |
|
||||||
|---|---|---|---|---|
|
|---|---|---|---|---|
|
||||||
| int8 | T | T | T | T |
|
| int8 | T | T | T | T |
|
||||||
| int16 | E+R | T | T | T |
|
| int16 | E+R | T | T | T |
|
||||||
| int32 | E+TR+SR | E+R | T | T |
|
| int32 | E+FR+SR | E+R | T | T |
|
||||||
| int64 | E+TR+SR | E+R | E+R | T |
|
| int64 | E+FR+SR | E+R | E+R | T |
|
||||||
| int128 | E+TR+SR | E+R | E+R | E+R |
|
| int128 | E+FR+SR | E+R | E+R | E+R |
|
||||||
| int256 | E+TR+SR | E+TR+SR | E+R | E+R |
|
| int256 | E+FR+SR | E+FR+SR | E+R | E+R |
|
||||||
| uint8 | T | T | T | T |
|
| uint8 | T | T | T | T |
|
||||||
| uint16 | E+TR+SR | T | T | T |
|
| uint16 | E+FR+SR | T | T | T |
|
||||||
| uint32 | E+TR+SR | E+R | T | T |
|
| uint32 | E+FR+SR | E+R | T | T |
|
||||||
| uint64 | E+TR+SR | E+R | E+R | T |
|
| uint64 | E+FR+SR | E+R | E+R | T |
|
||||||
| uint128 | E+TR+SR | E+TR+SR | E+R | E+R |
|
| uint128 | E+FR+SR | E+FR+SR | E+R | E+R |
|
||||||
| uint256 | E+TR+SR | E+TR+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 ;
|
```text
|
||||||
- `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
|
|
||||||
int64 value = ...;
|
int64 value = ...;
|
||||||
|
|
||||||
Result<float64, NumericConversionError> exact = value::tryToFloat64();
|
float64 exact = value::toFloat64();
|
||||||
float64 approximated = value::roundToFloat64();
|
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 :
|
Légende :
|
||||||
|
|
||||||
- `T` = `toFloatXX()` uniquement ;
|
```text
|
||||||
- `E+TR+SR` = `tryToFloatXX()` + `tryRoundToFloatXX()` + `saturatingRoundToFloatXX()`.
|
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 |
|
| Source \ Destination | float16 | float32 | float64 | float128 |
|
||||||
|---|---|---|---|---|
|
|---|---|---|---|---|
|
||||||
| float16 | — | T | T | T |
|
| float16 | — | T | T | T |
|
||||||
| float32 | E+TR+SR | — | T | T |
|
| float32 | E+FR+SR | — | T | T |
|
||||||
| float64 | E+TR+SR | E+TR+SR | — | T |
|
| float64 | E+FR+SR | E+FR+SR | — | T |
|
||||||
| float128 | E+TR+SR | E+TR+SR | E+TR+SR | — |
|
| float128 | E+FR+SR | E+FR+SR | E+FR+SR | — |
|
||||||
|
|
||||||
Règles :
|
Règles :
|
||||||
|
|
||||||
- l'élargissement de format est exact au niveau de la valeur IEEE et utilise uniquement `toFloatXX()` ;
|
- l'élargissement de format utilise `toFloatXX()` total ;
|
||||||
- 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 ;
|
- la réduction exacte utilise `toFloatXX()` avec fault si nécessaire ;
|
||||||
- `NaN`, `+Infinity`, `-Infinity`, `+0` et `-0` restent des catégories IEEE valides dans la destination ;
|
- `roundToFloatXX()` accepte la perte de précision mais pas un débordement fini ;
|
||||||
- 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 ;
|
- `saturatingRoundToFloatXX()` sature seulement les valeurs finies hors domaine fini ;
|
||||||
- `tryToFloatXX()` accepte `NaN` et les infinities lorsque la destination est un type flottant Saselang, car ces catégories y sont représentables ;
|
- `NaN`, `+Infinity`, `-Infinity`, `+0` et `-0` restent des catégories valides ;
|
||||||
- `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 ;
|
- pour `NaN`, seule la propriété sémantique `isNaN(destination) == true` est garantie.
|
||||||
- la conservation exacte d'une représentation binaire relève d'un contrat binaire distinct et de `bitcast` lorsque ses propres contraintes sont compatibles.
|
|
||||||
|
|
||||||
## A.8. Flottant -> entier : composition des politiques
|
## A.9. Flottant -> entier : composition des politiques
|
||||||
|
|
||||||
Il n'existe jamais de simple `toIntXX()` ou `toUintXX()` depuis un flottant.
|
|
||||||
|
|
||||||
La conversion stricte canonique est :
|
La conversion stricte canonique est :
|
||||||
|
|
||||||
```text
|
```text
|
||||||
tryToIntXX()
|
toIntXX()
|
||||||
tryToUintXX()
|
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
|
```text
|
||||||
floor()
|
floor()
|
||||||
@@ -211,67 +235,56 @@ round()
|
|||||||
truncate()
|
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 :
|
```text
|
||||||
|
value::floor()::toInt32()
|
||||||
```saselang
|
value::ceil()::toInt32()
|
||||||
value::floor()::tryToInt32()
|
value::round()::toInt32()
|
||||||
value::ceil()::tryToInt32()
|
value::truncate()::toInt32()
|
||||||
value::round()::tryToInt32()
|
|
||||||
value::truncate()::tryToInt32()
|
|
||||||
```
|
```
|
||||||
|
|
||||||
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.9.2. Dépassement de domaine
|
||||||
|
|
||||||
### A.8.2. Dépassement de domaine
|
|
||||||
|
|
||||||
Les politiques de dépassement restent séparées de la politique mathématique.
|
|
||||||
|
|
||||||
Pour chaque destination entière, le Core peut exposer :
|
Pour chaque destination entière, le Core peut exposer :
|
||||||
|
|
||||||
```text
|
```text
|
||||||
tryToTarget()
|
toTarget()
|
||||||
trySaturateToTarget()
|
saturateToTarget()
|
||||||
tryWrapToTarget()
|
wrapToTarget()
|
||||||
```
|
```
|
||||||
|
|
||||||
avec les contrats suivants :
|
| Opération | Préconditions hors plage | Politique de plage |
|
||||||
|
|
||||||
| Opération | Préconditions non liées à la plage | Politique de plage |
|
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `tryToTarget()` | valeur finie et mathématiquement entière | `Err` si hors plage |
|
| `toTarget()` | valeur finie et mathématiquement entière | `OutOfRange` si hors plage |
|
||||||
| `trySaturateToTarget()` | valeur finie et mathématiquement entière | borne à `Target::Min` / `Target::Max` |
|
| `saturateToTarget()` | 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 |
|
| `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
|
Exemples :
|
||||||
value::floor()::trySaturateToInt32()
|
|
||||||
value::round()::trySaturateToUint16()
|
|
||||||
|
|
||||||
value::truncate()::tryWrapToInt8()
|
```text
|
||||||
value::ceil()::tryWrapToUint64()
|
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.9.3. Matrice flottant -> entier après élimination des doublons
|
||||||
|
|
||||||
### 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.
|
|
||||||
|
|
||||||
Légende :
|
Légende :
|
||||||
|
|
||||||
```text
|
```text
|
||||||
C
|
C
|
||||||
tryToTarget() uniquement
|
toTarget() uniquement
|
||||||
|
|
||||||
CSW
|
CSW
|
||||||
tryToTarget()
|
toTarget()
|
||||||
trySaturateToTarget()
|
saturateToTarget()
|
||||||
tryWrapToTarget()
|
wrapToTarget()
|
||||||
```
|
```
|
||||||
|
|
||||||
| Source \ Destination | int8 | int16 | int32 | int64 | int128 | int256 | uint8 | uint16 | uint32 | uint64 | uint128 | uint256 |
|
| 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 |
|
| 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 |
|
| 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 :
|
Cas particuliers :
|
||||||
|
|
||||||
- `+0` et `-0` donnent l'entier zéro ;
|
- `+0` et `-0` donnent 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 ;
|
- `NaN` et les infinities produisent `NotFinite` ;
|
||||||
- pour une destination non signée, la saturation d'une valeur négative entière donne `0` ;
|
- une valeur fractionnaire produit `NotIntegral` avant la politique de plage ;
|
||||||
- pour une destination signée, la saturation utilise `Target::Min` / `Target::Max` ;
|
- vers un non signé, la saturation d'une valeur négative entière donne `0` ;
|
||||||
- le wrapping est appliqué au résultat entier mathématique fini selon modulo `2^N`.
|
- 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.11. Typage contextuel des littéraux
|
||||||
|
|
||||||
## A.10. Typage contextuel des littéraux
|
|
||||||
|
|
||||||
Le typage contextuel d'un littéral reste distinct de toute conversion de valeur déjà typée.
|
Le typage contextuel d'un littéral reste distinct de toute conversion de valeur déjà typée.
|
||||||
|
|
||||||
```saselang
|
```text
|
||||||
int32 a = 42; // contextualisation du littéral
|
int32 a = 42;
|
||||||
|
|
||||||
int8 small = ...;
|
int8 small = ...;
|
||||||
int32 b = small; // ERROR : pas de conversion implicite
|
int32 b = small; // ERROR
|
||||||
int32 c = small::toInt32(); // OK
|
int32 c = small::toInt32(); // OK
|
||||||
```
|
```
|
||||||
|
|
||||||
## A.11. Core, targets et capacités
|
## A.12. `NumericConversionFault`
|
||||||
|
|
||||||
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 :
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
Language / Compiler Specification
|
NumericConversionFault extends Fault
|
||||||
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
|
|
||||||
```
|
```
|
||||||
|
|
||||||
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.
|
Codes sémantiques V1 :
|
||||||
|
|
||||||
## A.13. `NumericConversionError`
|
|
||||||
|
|
||||||
`NumericConversionError` est le nom de travail du `ResultError` Core des conversions récupérables.
|
|
||||||
|
|
||||||
Les codes sémantiques V1 sont :
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
NotFinite
|
NotFinite
|
||||||
@@ -358,19 +333,20 @@ OutOfRange
|
|||||||
Inexact
|
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
|
```text
|
||||||
non-redondance par paire
|
non-redondance par paire
|
||||||
composition plutôt qu'alias combinés
|
composition plutôt qu'alias combinés
|
||||||
|
Fault direct à la place des anciens try... purement mécaniques
|
||||||
règles float -> integer
|
règles float -> integer
|
||||||
règles NaN / infinities / signed zero
|
règles NaN / infinities / signed zero
|
||||||
NumericConversionError
|
NumericConversionFault
|
||||||
disponibilité Core pour les types supportés
|
Core-required pour les types supportés
|
||||||
émulation logicielle lorsque raisonnable
|
é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 ;
|
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 ;
|
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.
|
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
|
```text
|
||||||
aucune conversion implicite
|
aucune conversion implicite
|
||||||
aucun mélange de types dans les opérations textuelles
|
aucun mélange de types dans les opérations textuelles
|
||||||
to... uniquement pour une conversion totale et sûre
|
conversion directe vers la valeur attendue
|
||||||
tryFrom... / tryTo... lorsqu'une validation ou une condition peut échouer
|
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
|
aucun alias redondant
|
||||||
conversion explicite d'abord, opération ensuite
|
conversion explicite d'abord, opération ensuite
|
||||||
```
|
```
|
||||||
@@ -106,8 +107,8 @@ Ces transcodages sont totaux.
|
|||||||
UTF-8 :
|
UTF-8 :
|
||||||
|
|
||||||
```text
|
```text
|
||||||
Utf8Char::tryFrom(uint8)
|
Utf8Char::from(uint8) faults UnicodeEncodingFault
|
||||||
Utf8Char::tryFrom(StaticArray<uint8, N>)
|
Utf8Char::from(StaticArray<uint8, N>) faults UnicodeEncodingFault
|
||||||
```
|
```
|
||||||
|
|
||||||
`N` utile : 1 à 4. Le contenu doit représenter exactement un scalar UTF-8 valide.
|
`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 :
|
UTF-16 :
|
||||||
|
|
||||||
```text
|
```text
|
||||||
Utf16Char::tryFrom(uint16)
|
Utf16Char::from(uint16) faults UnicodeEncodingFault
|
||||||
Utf16Char::tryFrom(StaticArray<uint16, 2>)
|
Utf16Char::from(StaticArray<uint16, 2>) faults UnicodeEncodingFault
|
||||||
```
|
```
|
||||||
|
|
||||||
Un surrogate isolé est invalide.
|
Un surrogate isolé est invalide.
|
||||||
@@ -124,7 +125,7 @@ Un surrogate isolé est invalide.
|
|||||||
UTF-32 :
|
UTF-32 :
|
||||||
|
|
||||||
```text
|
```text
|
||||||
Utf32Char::tryFrom(uint32)
|
Utf32Char::from(uint32) faults UnicodeEncodingFault
|
||||||
```
|
```
|
||||||
|
|
||||||
La valeur doit être <= `0x10FFFF` et hors de la plage surrogate.
|
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 :
|
Le nom de travail de l'erreur est :
|
||||||
|
|
||||||
```text
|
```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
|
## B.7. `UtfXChar` -> code unit brute
|
||||||
|
|
||||||
| Source | Destination | Opération | Raison |
|
| Source | Destination | Opération | Raison |
|
||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| `Utf8Char` | `uint8` | `tryToUint8()` | 1 à 4 unités possibles |
|
| `Utf8Char` | `uint8` | `toUint8() faults UnicodeEncodingFault` | 1 à 4 unités possibles |
|
||||||
| `Utf16Char` | `uint16` | `tryToUint16()` | 1 ou 2 unités possibles |
|
| `Utf16Char` | `uint16` | `toUint16() faults UnicodeEncodingFault` | 1 ou 2 unités possibles |
|
||||||
| `Utf32Char` | `uint32` | `toUint32()` | exactement 1 unité |
|
| `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.
|
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 :
|
Conceptuellement :
|
||||||
|
|
||||||
```text
|
```text
|
||||||
Utf8String::tryFrom(Array<uint8>)
|
Utf8String::from(Array<uint8>) faults UnicodeEncodingFault
|
||||||
Utf16String::tryFrom(Array<uint16>)
|
Utf16String::from(Array<uint16>) faults UnicodeEncodingFault
|
||||||
Utf32String::tryFrom(Array<uint32>)
|
Utf32String::from(Array<uint32>) faults UnicodeEncodingFault
|
||||||
```
|
```
|
||||||
|
|
||||||
Le type exact accepté pourra inclure des slices/vues lors de leur définition.
|
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 ;
|
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 ;
|
4. API précise de concaténation et ses opérateurs ;
|
||||||
5. builders/buffers et leurs relations avec les strings valides ;
|
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.
|
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ë.
|
> **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É
|
## 2.2 Mots-clés — V1 REQUIS — FIGÉ
|
||||||
|
|
||||||
Les mots-clés du langage sont en anglais.
|
Les mots-clés du langage sont en anglais.
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ unions
|
|||||||
tuples
|
tuples
|
||||||
generics
|
generics
|
||||||
contrôle de flux
|
contrôle de flux
|
||||||
erreurs/exceptions
|
erreurs/exceptions/faults
|
||||||
opérateurs
|
opérateurs
|
||||||
unsafe
|
unsafe
|
||||||
scope
|
scope
|
||||||
@@ -42,6 +42,7 @@ Result<T,E>
|
|||||||
Error
|
Error
|
||||||
ResultError
|
ResultError
|
||||||
Exception
|
Exception
|
||||||
|
Fault
|
||||||
Option<T>
|
Option<T>
|
||||||
Nullable<T>
|
Nullable<T>
|
||||||
Range<T>
|
Range<T>
|
||||||
@@ -50,10 +51,18 @@ RangeStep<T,Step>
|
|||||||
RangeReverse<T>
|
RangeReverse<T>
|
||||||
RangeReverseStep<T,Step>
|
RangeReverseStep<T,Step>
|
||||||
RangeProgression<T,Step>
|
RangeProgression<T,Step>
|
||||||
|
PartialOrdering
|
||||||
Ordering
|
Ordering
|
||||||
|
Comparable<T>
|
||||||
|
Comparator<T>
|
||||||
Op...
|
Op...
|
||||||
Iterable<T>
|
Iterable<T>
|
||||||
Iterator<T>
|
Iterator<T>
|
||||||
|
View<T>
|
||||||
|
Collection<T>
|
||||||
|
List<T>
|
||||||
|
Set<T>
|
||||||
|
Map<K,V>
|
||||||
Array<T>
|
Array<T>
|
||||||
StaticArray<T,N>
|
StaticArray<T,N>
|
||||||
TypeInfo
|
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 :
|
Le SDK fournit les fonctionnalités de bibliothèque qui ne justifient pas une sémantique spéciale du compilateur :
|
||||||
|
|
||||||
```text
|
```text
|
||||||
collections
|
collections concrètes/spécialisées au-delà des contrats fondamentaux Core
|
||||||
encodages explicites
|
encodages explicites
|
||||||
regex
|
regex
|
||||||
filesystem
|
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 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é
|
visibilité
|
||||||
fallibilité / Result
|
fallibilité / Result
|
||||||
throws
|
throws
|
||||||
contraintes génériques pertinentes
|
qualification const et contraintes génériques pertinentes
|
||||||
modificateurs contractuels pertinents
|
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.
|
Les futurs pré/post-contrats formels, s'ils existent, devront également participer à cette notion.
|
||||||
|
|
||||||
## 13.5 Conflits d'héritage multiple — V1 REQUIS — FIGÉ
|
## 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
|
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
|
```text
|
||||||
opération infaillible
|
func readConfig(String path) -> Config
|
||||||
-> retourne directement T
|
throws IOException
|
||||||
|
|
||||||
opération pouvant produire une erreur récupérable
|
method elementAt(uint64 index) -> T
|
||||||
-> retourne Result<T>
|
faults IndexOutOfBoundsFault
|
||||||
ou Result<T,E>
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Exemples infaillibles :
|
`Result<T,E>` est utilisé lorsque l'échec doit être transporté explicitement comme une valeur et inspecté par l'appelant :
|
||||||
|
|
||||||
```text
|
```text
|
||||||
method length() -> uint64
|
func parseExternalInput(String input) -> Result<Value, ParseError>
|
||||||
method containsKey(K key) -> bool
|
|
||||||
Object::sameInstance(Object other) -> bool
|
|
||||||
func min(int32 a, int32 b) -> int32
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Exemples faillibles :
|
Les combinaisons sont indépendantes :
|
||||||
|
|
||||||
```text
|
```text
|
||||||
func readFile(String path) -> Result<String, IoError>
|
T
|
||||||
method parse(String input) -> Result<Value, ParseError>
|
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É
|
## 15.3 Retour explicite — V1 REQUIS — FIGÉ
|
||||||
|
|
||||||
Pas de retour implicite de dernière expression.
|
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É
|
## 18.1 Hiérarchie Core — V1 REQUIS — FIGÉ
|
||||||
|
|
||||||
La hiérarchie d'erreurs V1 est :
|
La hiérarchie V1 est :
|
||||||
|
|
||||||
```text
|
```text
|
||||||
Object
|
Object
|
||||||
└── Error
|
└── Error
|
||||||
├── ResultError
|
├── 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 :
|
Exemple :
|
||||||
|
|
||||||
@@ -29,9 +37,12 @@ public final class ParseError extends ResultError {
|
|||||||
|
|
||||||
public final class FileNotFoundException extends Exception {
|
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
|
## 18.2 Informations communes de `Error` — V1 REQUIS — FIGÉ EN PRINCIPE
|
||||||
|
|
||||||
@@ -51,7 +62,7 @@ message
|
|||||||
|
|
||||||
cause
|
cause
|
||||||
erreur causale purement informative
|
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
|
n'est pas automatiquement propagée
|
||||||
|
|
||||||
i18nMessage
|
i18nMessage
|
||||||
@@ -59,13 +70,11 @@ i18nMessage
|
|||||||
ne contient pas un tableau de traductions
|
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.
|
`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.
|
`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.
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
## 18.3 `ResultError` et code machine-readable — V1 REQUIS — FIGÉ EN PRINCIPE
|
## 18.3 `ResultError` et code machine-readable — V1 REQUIS — FIGÉ EN PRINCIPE
|
||||||
|
|
||||||
@@ -78,26 +87,31 @@ code: ResultErrorCode
|
|||||||
Le rôle de `ResultErrorCode` est distinct de `message` :
|
Le rôle de `ResultErrorCode` est distinct de `message` :
|
||||||
|
|
||||||
```text
|
```text
|
||||||
code -> stable, machine-readable, non localisé
|
code -> stable, machine-readable, non localisé
|
||||||
message -> humain, canonique / fallback
|
message -> humain, canonique / fallback
|
||||||
i18nMessage -> localisation externe
|
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
|
```text
|
||||||
throw exception;
|
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É
|
## 18.5 `Result<T,E>` — V1 REQUIS — FIGÉ
|
||||||
|
|
||||||
@@ -127,6 +141,7 @@ Sont invalides :
|
|||||||
```text
|
```text
|
||||||
Result<Data,Error>
|
Result<Data,Error>
|
||||||
Result<Data,Exception>
|
Result<Data,Exception>
|
||||||
|
Result<Data,Fault>
|
||||||
Result<Data,FileNotFoundException>
|
Result<Data,FileNotFoundException>
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -142,7 +157,7 @@ est équivalente à :
|
|||||||
Result<T,ResultError>
|
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>` :
|
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);
|
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
|
```text
|
||||||
result::expectOk(...)
|
ResultError / Result
|
||||||
result::expectErr(...)
|
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É
|
Exemple :
|
||||||
|
|
||||||
Aucune conversion automatique n'existe entre les deux branches :
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
ResultError -> Exception
|
method elementAt(uint64 index) -> T
|
||||||
Exception -> ResultError
|
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
|
```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
|
Aucune conversion automatique n'existe entre `ResultError`, `Exception` et `Fault`. Une traduction entre branches se fait par encapsulation explicite, éventuellement via `cause`.
|
||||||
catch (FileNotFoundException error) {
|
|
||||||
return Result::Err(FileResultError(..., Option::Some(error)));
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Un simple cast ne transforme pas un `ResultError` en `Exception` ni l'inverse.
|
|
||||||
|
|
||||||
## 18.7 `throws` — V1 REQUIS — FIGÉ
|
## 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
|
```text
|
||||||
T + throws -> interdit
|
T
|
||||||
Result<T,E> -> valide sans throws
|
T throws SomeException
|
||||||
Result<T,E> + throws -> valide
|
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`.
|
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.
|
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
|
`Fault`, `Error` et `ResultError` sont interdits dans `throws`.
|
||||||
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.
|
|
||||||
|
|
||||||
## 18.8 `throws` dans les contrats, interfaces et overrides — V1 REQUIS — FIGÉ
|
## 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 :
|
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.
|
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É
|
## 18.9 `throw` — V1 REQUIS — FIGÉ
|
||||||
|
|
||||||
`throw` ne peut lancer qu'une valeur dont le type statique est `Exception` ou un descendant de `Exception`.
|
`throw` ne peut lancer qu'une valeur dont le type statique est `Exception` ou un descendant de `Exception`.
|
||||||
|
|
||||||
```text
|
```text
|
||||||
throw FileNotFoundException(...); // valide
|
throw FileNotFoundException(...); // OK
|
||||||
throw ParseError(...); // erreur
|
throw ParseError(...); // ERROR
|
||||||
throw Error(...); // erreur
|
throw IndexOutOfBoundsFault(...); // ERROR
|
||||||
|
throw Error(...); // ERROR
|
||||||
```
|
```
|
||||||
|
|
||||||
Les racines abstraites `Error`, `ResultError` et `Exception` ne sont jamais instanciables directement.
|
La repropagation reste explicite :
|
||||||
|
|
||||||
La forme de repropagation reste explicite :
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
catch (IOException error) {
|
catch (IOException error) {
|
||||||
@@ -253,7 +266,69 @@ catch (IOException error) {
|
|||||||
|
|
||||||
Il n'existe pas de forme spéciale `throw;` en V1.
|
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`.
|
Un `try` doit être suivi d'au moins un `catch`.
|
||||||
|
|
||||||
@@ -272,7 +347,7 @@ try {
|
|||||||
...
|
...
|
||||||
} catch (SpecificException error) {
|
} catch (SpecificException error) {
|
||||||
...
|
...
|
||||||
} catch (ParentException error) {
|
} catch (SomeFault faultValue) {
|
||||||
...
|
...
|
||||||
} finally {
|
} finally {
|
||||||
...
|
...
|
||||||
@@ -281,75 +356,95 @@ try {
|
|||||||
|
|
||||||
`finally` est facultatif et ne peut apparaître qu'après au moins un `catch`.
|
`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.
|
Le type explicite d'un `catch` doit être :
|
||||||
|
|
||||||
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 :
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
catch (FileNotFoundException error) {
|
Exception ou un descendant de Exception
|
||||||
...
|
Fault ou un descendant de Fault
|
||||||
} catch (IOException error) {
|
|
||||||
...
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Exemple invalide si `FileNotFoundException extends IOException` :
|
Sont donc interdits :
|
||||||
|
|
||||||
```text
|
```text
|
||||||
catch (IOException error) {
|
catch (Error error)
|
||||||
...
|
catch (ResultError error)
|
||||||
} catch (FileNotFoundException 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
|
```text
|
||||||
fin normale du try
|
fin normale du try
|
||||||
fin normale d'un catch
|
fin normale d'un catch
|
||||||
return traversant la construction
|
return traversant la construction
|
||||||
throw propagé
|
throw propagé
|
||||||
|
Fault propagé
|
||||||
break / continue traversant la construction
|
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
|
```text
|
||||||
return
|
return
|
||||||
throw
|
throw
|
||||||
|
fault
|
||||||
break
|
break
|
||||||
continue
|
continue
|
||||||
emit
|
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
|
```text
|
||||||
index hors limites
|
index dynamique hors limites
|
||||||
division entière par zéro
|
division entière dynamique par zéro
|
||||||
overflow checked
|
overflow checked
|
||||||
représentation mémoire invalide
|
iterator invalidé
|
||||||
borne dynamique invalide lors d'une construction directe lorsque la règle du type le définit
|
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 ;
|
- le résultat du `if` doit obligatoirement être affecté à une destination ;
|
||||||
- un bloc `else` final est obligatoire ;
|
- un bloc `else` final est obligatoire ;
|
||||||
- chaque voie de terminaison normale de chaque branche doit produire explicitement une valeur via `emit` ;
|
- 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 ;
|
- les valeurs émises doivent être compatibles avec le type de la destination ;
|
||||||
- aucune valeur de secours n'est implicite, y compris pour `Option<T>`.
|
- 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.
|
L'utilisateur ne peut pas inventer de nouveaux symboles opérateurs.
|
||||||
|
|
||||||
Les `operator` contracts :
|
Les contrats `operator` :
|
||||||
|
|
||||||
- retournent directement leur valeur ;
|
- retournent directement leur valeur ;
|
||||||
- ne retournent jamais `Result` ;
|
- 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É
|
## 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
|
## 20.6 Comparaison — V1 REQUIS — FIGÉ EN PRINCIPE
|
||||||
|
|
||||||
Core :
|
Core distingue l'ordre partiel de l'ordre total :
|
||||||
|
|
||||||
```text
|
```text
|
||||||
public enum Ordering {
|
public enum PartialOrdering {
|
||||||
Less,
|
Less,
|
||||||
Equal,
|
Equal,
|
||||||
Greater,
|
Greater,
|
||||||
Unordered
|
Unordered
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum Ordering {
|
||||||
|
Less,
|
||||||
|
Equal,
|
||||||
|
Greater
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Interfaces :
|
Interfaces opérateur :
|
||||||
|
|
||||||
```text
|
```text
|
||||||
OpPartialCompare<Lhs,Rhs>
|
OpPartialCompare<Lhs,Rhs>
|
||||||
|
-> PartialOrdering
|
||||||
|
|
||||||
OpCompare<T>
|
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
|
## 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.
|
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
|
```text
|
||||||
Map<K,V>
|
map[key] -> V
|
||||||
OpIndex<K,Option<V>>
|
|
||||||
OpIndexMut<K,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É
|
## 20.11 Affectation — V1 REQUIS — FIGÉ
|
||||||
|
|
||||||
|
|||||||
@@ -95,26 +95,37 @@ Aucun `Utf8CodeUnit` / `Utf16CodeUnit` / `Utf32CodeUnit` distinct n'est introdui
|
|||||||
|
|
||||||
Aucun transcodage implicite n'existe.
|
Aucun transcodage implicite n'existe.
|
||||||
|
|
||||||
Les conversions totales utilisent `to...`.
|
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.
|
||||||
|
|
||||||
Les constructions ou réductions pouvant échouer utilisent `tryFrom...` / `tryTo...`.
|
|
||||||
|
|
||||||
Exemples :
|
Exemples :
|
||||||
|
|
||||||
```text
|
```text
|
||||||
char::toUtf8Char()
|
char::toUtf8Char() -> Utf8Char
|
||||||
Utf8Char::toChar()
|
Utf8Char::toChar() -> char
|
||||||
Utf8Char::toUtf16Char()
|
Utf8Char::toUtf16Char() -> Utf16Char
|
||||||
|
|
||||||
Utf8Char::tryFrom(uint8)
|
Utf8Char::from(uint8) -> Utf8Char
|
||||||
Utf16Char::tryFrom(uint16)
|
faults UnicodeEncodingFault
|
||||||
Utf32Char::tryFrom(uint32)
|
|
||||||
|
|
||||||
Utf8Char::tryToUint8()
|
Utf16Char::from(uint16) -> Utf16Char
|
||||||
Utf16Char::tryToUint16()
|
faults UnicodeEncodingFault
|
||||||
Utf32Char::toUint32()
|
|
||||||
|
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`.
|
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É
|
## 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.
|
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
|
```text
|
||||||
Iterable<T>
|
Iterable<T>
|
||||||
@@ -151,21 +151,84 @@ SettableList<T>
|
|||||||
ResizableList<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.
|
`Collection<T>` étend `Iterable<T>` et représente une collection finie d'éléments.
|
||||||
|
|
||||||
Contrat minimal retenu :
|
Contrat minimal :
|
||||||
|
|
||||||
```text
|
```text
|
||||||
count() -> uint64
|
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.
|
`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>`.
|
`List<T>` étend `Collection<T>` et `OpIndex<uint64,T>`.
|
||||||
|
|
||||||
@@ -193,33 +256,39 @@ Pour une `List<T>` :
|
|||||||
count() == length()
|
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>`.
|
`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
|
```text
|
||||||
list[index] = value;
|
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.
|
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é.
|
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
|
```text
|
||||||
StaticArray<T,N>
|
StaticArray<T,N>
|
||||||
@@ -258,9 +327,271 @@ Vector<T>
|
|||||||
|
|
||||||
`Vector<T>` reste à définir précisément.
|
`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
|
## 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.
|
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.
|
`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é.
|
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.
|
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.
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ Il n'existe aucune promotion numérique implicite générale entre deux valeurs
|
|||||||
|
|
||||||
```text
|
```text
|
||||||
int8 small = ...;
|
int8 small = ...;
|
||||||
int32 large = small; // ERROR
|
int32 large = small; // ERROR
|
||||||
int32 explicitLarge = small::toInt32(); // OK
|
int32 explicitLarge = small::toInt32(); // OK
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -48,63 +48,140 @@ if (animal is Dog) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Lorsqu'un test du type runtime **exact** est nécessaire, `instanceof` est utilisé.
|
Lorsqu'un test du type runtime exact est nécessaire, `instanceof` est utilisé.
|
||||||
|
|
||||||
Saselang n'introduit pas pour le moment de syntaxe générale concurrente telle que `(Dog)value`, `value as Dog` ou `cast<Dog>(value)`. Une telle opération ne pourra être ajoutée que si un besoin distinct de `is`/`instanceof` + refinement est démontré et si son contrat d'échec est explicite.
|
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.
|
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.
|
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
|
```text
|
||||||
toTarget()
|
toTarget()
|
||||||
conversion exacte et totale
|
conversion exacte
|
||||||
|
totale si tout le domaine source est représentable
|
||||||
tryToTarget()
|
sinon valeur directe + faults NumericConversionFault
|
||||||
conversion exacte pour la valeur courante, récupérable si impossible
|
|
||||||
|
|
||||||
roundToTarget()
|
roundToTarget()
|
||||||
perte de précision explicitement acceptée, conversion totale
|
perte de précision / arrondi explicitement accepté
|
||||||
|
peut fault si une autre précondition reste violée, par exemple le domaine fini destination
|
||||||
tryRoundToTarget()
|
|
||||||
perte de précision explicitement acceptée, mais conversion pouvant échouer
|
|
||||||
|
|
||||||
saturateToTarget()
|
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()
|
saturatingRoundToTarget()
|
||||||
arrondi + saturation explicitement annoncés
|
arrondi + saturation explicitement annoncés lorsque les deux sont nécessaires
|
||||||
|
|
||||||
wrapToTarget()
|
wrapToTarget()
|
||||||
wrapping entier explicite
|
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.
|
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.
|
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()`.
|
Si toutes les valeurs source sont représentables exactement dans la destination :
|
||||||
|
|
||||||
La conversion exacte stricte utilise :
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
tryToIntXX()
|
toTarget() -> Target
|
||||||
tryToUintXX()
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Elle réussit uniquement si la valeur source est finie, mathématiquement entière et représentable exactement dans le type destination. Sinon elle retourne `Result::Err(NumericConversionError(...))`.
|
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
|
```text
|
||||||
floor()
|
floor()
|
||||||
@@ -116,30 +193,38 @@ truncate()
|
|||||||
Elles se composent avec la conversion :
|
Elles se composent avec la conversion :
|
||||||
|
|
||||||
```text
|
```text
|
||||||
value::floor()::tryToInt32()
|
value::floor()::toInt32()
|
||||||
value::ceil()::tryToInt32()
|
value::ceil()::toInt32()
|
||||||
value::round()::tryToInt32()
|
value::round()::toInt32()
|
||||||
value::truncate()::tryToInt32()
|
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
|
```text
|
||||||
value::floor()::trySaturateToInt32()
|
value::floor()::saturateToInt32()
|
||||||
value::round()::tryWrapToInt32()
|
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 :
|
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
|
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 réduction de format :
|
||||||
|
|
||||||
Pour une valeur finie :
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
tryToFloatXX()
|
toFloatXX()
|
||||||
exige une représentation exacte
|
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
|
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()
|
saturatingRoundToFloatXX()
|
||||||
accepte l'arrondi canonique
|
accepte l'arrondi canonique
|
||||||
sature une valeur finie hors domaine vers +/-Target::Max
|
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 :
|
Les catégories sémantiques V1 sont :
|
||||||
|
|
||||||
@@ -213,7 +301,7 @@ Inexact
|
|||||||
alors que l'opération exige l'exactitude
|
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
|
```text
|
||||||
sourceType
|
sourceType
|
||||||
@@ -224,21 +312,19 @@ backend
|
|||||||
roundingMode
|
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.11 Réduction anti-doublon par paire — V1 REQUIS — FIGÉ
|
||||||
|
|
||||||
## 24.9 Réduction anti-doublon par paire — V1 REQUIS — FIGÉ
|
|
||||||
|
|
||||||
La matrice examine chaque paire `Source -> Target` et n'expose que les opérations dont le comportement peut réellement être distingué sur le domaine source.
|
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.
|
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.
|
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 :
|
Voir :
|
||||||
|
|
||||||
@@ -258,6 +344,6 @@ Voir :
|
|||||||
annexes/A-numeric-conversions.md
|
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
|
structured concurrency éventuelle
|
||||||
cancellation
|
cancellation
|
||||||
synchronisation
|
synchronisation
|
||||||
interaction avec Result/throws
|
interaction avec Result/throws/faults
|
||||||
interaction avec destruction déterministe
|
interaction avec destruction déterministe
|
||||||
runtime minimal
|
runtime minimal
|
||||||
```
|
```
|
||||||
|
|
||||||
Aucune dépendance obligatoire à un executor monolithique ne doit être supposée sans justification.
|
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.
|
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
|
## 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
|
fin normale
|
||||||
return
|
return
|
||||||
throw
|
throw
|
||||||
|
Fault propagé
|
||||||
break
|
break
|
||||||
continue
|
continue
|
||||||
emit quittant le scope concerné
|
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É
|
## 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 :
|
Ordre conceptuel :
|
||||||
|
|
||||||
```text
|
```text
|
||||||
throw
|
throw / Fault propagé
|
||||||
-> unwind des scopes quittés
|
-> unwind des scopes quittés
|
||||||
-> defer de ces scopes, LIFO
|
-> defer de ces scopes, LIFO
|
||||||
-> catch correspondant éventuel
|
-> catch correspondant éventuel
|
||||||
@@ -73,6 +74,7 @@ Sont interdits dans un `defer` lorsqu'ils quittent le bloc :
|
|||||||
```text
|
```text
|
||||||
return
|
return
|
||||||
throw
|
throw
|
||||||
|
fault
|
||||||
break
|
break
|
||||||
continue
|
continue
|
||||||
emit
|
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`.
|
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.
|
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É
|
## 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.
|
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 la sémantique d'un index hors limites
|
||||||
modifier l'ordre d'évaluation
|
modifier l'ordre d'évaluation
|
||||||
modifier la représentation sémantique des types
|
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
|
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
|
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`.
|
`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
|
## 42.2 `ExitCode` — V1 REQUIS — FIGÉ EN PRINCIPE
|
||||||
|
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ Les commentaires documentaires sont :
|
|||||||
/** documentation de bloc */
|
/** 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.
|
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.
|
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é.
|
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
|
## 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 :
|
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 ;
|
- constructors faillibles et construction partielle ;
|
||||||
- interaction exacte cleanup/destruction pendant fault ;
|
|
||||||
- ordre exact `defer` / destructeurs automatiques avec le modèle mémoire ;
|
- ordre exact `defer` / destructeurs automatiques avec le modèle mémoire ;
|
||||||
- représentation Core/runtime exacte de `I18nMessage`, `ResultErrorCode`, `StackTrace` et `StackFrame` ;
|
- 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
|
## 48.5 Contrôle de flux
|
||||||
|
|
||||||
@@ -97,7 +98,10 @@ Restent à fermer :
|
|||||||
## 48.9 Core/SDK
|
## 48.9 Core/SDK
|
||||||
|
|
||||||
- frontière Core/SDK définitive ;
|
- 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 ;
|
- String encodings ;
|
||||||
- regex ;
|
- regex ;
|
||||||
- filesystem/network/process ;
|
- 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.**
|
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.**
|
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.**
|
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.**
|
12. **`ResultError`, `Exception` et `Fault` sont trois mécanismes distincts : valeur d'échec explicite, propagation checked et échec unchecked capturable.**
|
||||||
13. **`throws` n'existe que sur une callable retournant `Result`.**
|
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.**
|
14. **L'identité d'objet est distincte de l'égalité de valeur.**
|
||||||
15. **Les opérateurs utilisateur passent uniquement par les contrats Core `Op...`.**
|
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.**
|
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.**
|
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`.**
|
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.**
|
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
|
## 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.
|
À 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
|
tuples
|
||||||
generics
|
generics
|
||||||
contrôle de flux
|
contrôle de flux
|
||||||
erreurs/exceptions
|
erreurs/exceptions/faults
|
||||||
opérateurs
|
opérateurs
|
||||||
unsafe
|
unsafe
|
||||||
scope
|
scope
|
||||||
@@ -38,6 +38,7 @@ Result<T,E>
|
|||||||
Error
|
Error
|
||||||
ResultError
|
ResultError
|
||||||
Exception
|
Exception
|
||||||
|
Fault
|
||||||
Option<T>
|
Option<T>
|
||||||
Nullable<T>
|
Nullable<T>
|
||||||
Range<T>
|
Range<T>
|
||||||
@@ -46,10 +47,18 @@ RangeStep<T,Step>
|
|||||||
RangeReverse<T>
|
RangeReverse<T>
|
||||||
RangeReverseStep<T,Step>
|
RangeReverseStep<T,Step>
|
||||||
RangeProgression<T,Step>
|
RangeProgression<T,Step>
|
||||||
|
PartialOrdering
|
||||||
Ordering
|
Ordering
|
||||||
|
Comparable<T>
|
||||||
|
Comparator<T>
|
||||||
Op...
|
Op...
|
||||||
Iterable<T>
|
Iterable<T>
|
||||||
Iterator<T>
|
Iterator<T>
|
||||||
|
View<T>
|
||||||
|
Collection<T>
|
||||||
|
List<T>
|
||||||
|
Set<T>
|
||||||
|
Map<K,V>
|
||||||
Array<T>
|
Array<T>
|
||||||
StaticArray<T,N>
|
StaticArray<T,N>
|
||||||
TypeInfo
|
TypeInfo
|
||||||
@@ -59,7 +68,7 @@ ExitCode
|
|||||||
### Exemple 3
|
### Exemple 3
|
||||||
|
|
||||||
```text
|
```text
|
||||||
collections
|
collections concrètes/spécialisées au-delà des contrats fondamentaux Core
|
||||||
encodages explicites
|
encodages explicites
|
||||||
regex
|
regex
|
||||||
filesystem
|
filesystem
|
||||||
|
|||||||
@@ -19,7 +19,10 @@ type de retour
|
|||||||
visibilité
|
visibilité
|
||||||
fallibilité / Result
|
fallibilité / Result
|
||||||
throws
|
throws
|
||||||
contraintes génériques pertinentes
|
qualification const et contraintes génériques pertinentes
|
||||||
|
|
||||||
|
faults
|
||||||
|
visible mais non checked / non exhaustif
|
||||||
modificateurs contractuels pertinents
|
modificateurs contractuels pertinents
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -16,30 +16,35 @@ operator implémentation d'un contrat opérateur
|
|||||||
### Exemple 2
|
### Exemple 2
|
||||||
|
|
||||||
```text
|
```text
|
||||||
opération infaillible
|
T
|
||||||
-> retourne directement T
|
T throws SomeException
|
||||||
|
T faults SomeFault
|
||||||
opération pouvant produire une erreur récupérable
|
T throws SomeException faults SomeFault
|
||||||
-> retourne Result<T>
|
Result<T,E>
|
||||||
ou 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
|
### Exemple 3
|
||||||
|
|
||||||
```text
|
```text
|
||||||
method length() -> uint64
|
func readConfig(String path) -> Config
|
||||||
method containsKey(K key) -> bool
|
throws IOException
|
||||||
Object::sameInstance(Object other) -> bool
|
|
||||||
func min(int32 a, int32 b) -> int32
|
method elementAt(uint64 index) -> T
|
||||||
|
faults IndexOutOfBoundsFault
|
||||||
```
|
```
|
||||||
|
|
||||||
### Exemple 4
|
### Exemple 4
|
||||||
|
|
||||||
```text
|
```text
|
||||||
func readFile(String path) -> Result<String, IoError>
|
func parseExternalInput(String input) -> Result<Value, ParseError>
|
||||||
method parse(String input) -> Result<Value, ParseError>
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
`Result` reste utilisé lorsque l'échec doit être transporté comme une valeur.
|
||||||
|
|
||||||
### Exemple 5
|
### Exemple 5
|
||||||
|
|
||||||
```text
|
```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
|
## Hiérarchie
|
||||||
|
|
||||||
### Exemple 1
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
Object
|
Object
|
||||||
└── Error
|
└── Error
|
||||||
├── ResultError
|
├── ResultError
|
||||||
└── Exception
|
├── Exception
|
||||||
|
└── Fault
|
||||||
```
|
```
|
||||||
|
|
||||||
### Exemple 2
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
public final class ParseError extends ResultError {
|
public final class ParseError extends ResultError {
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class FileNotFoundException extends Exception {
|
public final class FileNotFoundException extends Exception {
|
||||||
}
|
}
|
||||||
```
|
|
||||||
|
|
||||||
### Exemple 3
|
public final class IndexOutOfBoundsFault extends Fault {
|
||||||
|
|
||||||
```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)));
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Exemple 19
|
## `ResultError`
|
||||||
|
|
||||||
|
DO : utiliser `Result` lorsque l'échec est une valeur normale à inspecter explicitement.
|
||||||
|
|
||||||
```text
|
```text
|
||||||
T + throws -> interdit
|
func parseExternalInput(String input) -> Result<Value, ParseError> {
|
||||||
Result<T,E> -> valide sans throws
|
...
|
||||||
Result<T,E> + throws -> valide
|
|
||||||
```
|
|
||||||
|
|
||||||
### Exemple 20
|
|
||||||
|
|
||||||
```text
|
|
||||||
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
|
DON'T : placer une `Exception` ou un `Fault` dans le paramètre erreur de `Result`.
|
||||||
|
|
||||||
```text
|
```text
|
||||||
try { ... }
|
Result<Value,FileNotFoundException> // ERROR
|
||||||
try { ... } finally { ... }
|
Result<Value,IndexOutOfBoundsFault> // ERROR
|
||||||
finally { ... }
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Exemple 25
|
## `Exception`, `throw` et `throws`
|
||||||
|
|
||||||
|
```text
|
||||||
|
func readConfig(String path) -> Config
|
||||||
|
throws IOException
|
||||||
|
{
|
||||||
|
...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Un retour direct est compatible avec `throws`.
|
||||||
|
|
||||||
|
```text
|
||||||
|
throw FileNotFoundException(...); // OK
|
||||||
|
throw IndexOutOfBoundsFault(...); // ERROR
|
||||||
|
throw ParseError(...); // ERROR
|
||||||
|
```
|
||||||
|
|
||||||
|
## `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
|
```text
|
||||||
try {
|
try {
|
||||||
...
|
T value = list::elementAt(index);
|
||||||
} catch (SpecificException error) {
|
} catch (IndexOutOfBoundsFault faultValue) {
|
||||||
...
|
|
||||||
} catch (ParentException error) {
|
|
||||||
...
|
|
||||||
} finally {
|
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Exemple 26
|
Aucune propagation de `faults` n'est obligatoire :
|
||||||
|
|
||||||
```text
|
```text
|
||||||
catch (FileNotFoundException error) {
|
func outer() -> Void {
|
||||||
...
|
inner(); // inner peut déclarer faults SomeFault
|
||||||
} catch (IOException error) {
|
return Void;
|
||||||
...
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Exemple 27
|
## `catch`
|
||||||
|
|
||||||
|
Valide :
|
||||||
|
|
||||||
```text
|
```text
|
||||||
catch (IOException error) {
|
catch (IOException error) {
|
||||||
...
|
...
|
||||||
} catch (FileNotFoundException error) {
|
}
|
||||||
|
|
||||||
|
catch (IteratorInvalidatedFault faultValue) {
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Exemple 28
|
Invalide :
|
||||||
|
|
||||||
```text
|
```text
|
||||||
fin normale du try
|
catch (Error error) // ERROR
|
||||||
fin normale d'un catch
|
catch (ResultError error) // ERROR
|
||||||
return traversant la construction
|
|
||||||
throw propagé
|
|
||||||
break / continue traversant la construction
|
|
||||||
Exception non capturée par les catch
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Exemple 29
|
`catch` ne peut cibler que `Exception`, `Fault` ou leurs descendants.
|
||||||
|
|
||||||
|
## Direct versus valeur conditionnelle
|
||||||
|
|
||||||
|
Accès affirmatif :
|
||||||
|
|
||||||
```text
|
```text
|
||||||
return
|
User user = users[id]; // absence -> KeyNotFoundFault
|
||||||
throw
|
|
||||||
break
|
|
||||||
continue
|
|
||||||
emit
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Exemple 30
|
Absence normale :
|
||||||
|
|
||||||
```text
|
```text
|
||||||
index hors limites
|
Option<User> user = users::get(id);
|
||||||
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
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## 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
|
### Exemple 11
|
||||||
|
|
||||||
```text
|
```text
|
||||||
public enum Ordering {
|
public enum PartialOrdering {
|
||||||
Less,
|
Less,
|
||||||
Equal,
|
Equal,
|
||||||
Greater,
|
Greater,
|
||||||
Unordered
|
Unordered
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum Ordering {
|
||||||
|
Less,
|
||||||
|
Equal,
|
||||||
|
Greater
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Exemple 12
|
### Exemple 12
|
||||||
@@ -124,8 +130,11 @@ container[index] = value
|
|||||||
|
|
||||||
```text
|
```text
|
||||||
Map<K,V>
|
Map<K,V>
|
||||||
OpIndex<K,Option<V>>
|
OpIndex<K,V>
|
||||||
OpIndexMut<K,V>
|
OpIndexMut<K,V>
|
||||||
|
|
||||||
|
map[key] // strict, absent -> KeyNotFoundFault
|
||||||
|
map::get(key) // Option<V>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Exemple 16
|
### Exemple 16
|
||||||
|
|||||||
@@ -78,12 +78,12 @@ char::toUtf8Char()
|
|||||||
Utf8Char::toChar()
|
Utf8Char::toChar()
|
||||||
Utf8Char::toUtf16Char()
|
Utf8Char::toUtf16Char()
|
||||||
|
|
||||||
Utf8Char::tryFrom(uint8)
|
Utf8Char::from(uint8) faults UnicodeEncodingFault
|
||||||
Utf16Char::tryFrom(uint16)
|
Utf16Char::from(uint16) faults UnicodeEncodingFault
|
||||||
Utf32Char::tryFrom(uint32)
|
Utf32Char::from(uint32) faults UnicodeEncodingFault
|
||||||
|
|
||||||
Utf8Char::tryToUint8()
|
Utf8Char::toUint8() faults UnicodeEncodingFault
|
||||||
Utf16Char::tryToUint16()
|
Utf16Char::toUint16() faults UnicodeEncodingFault
|
||||||
Utf32Char::toUint32()
|
Utf32Char::toUint32()
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -158,7 +158,82 @@ Vector<T>
|
|||||||
ResizableList<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
|
```text
|
||||||
a..b [a, b] bornes basse et haute incluses
|
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
|
a>..<b (a, b) bornes basse et haute exclues
|
||||||
```
|
```
|
||||||
|
|
||||||
### Exemple 19
|
### Range 1
|
||||||
|
|
||||||
```text
|
```text
|
||||||
Range<uint64> ids = 1..100;
|
Range<uint64> ids = 1..100;
|
||||||
```
|
```
|
||||||
|
|
||||||
### Exemple 20
|
### Range 2
|
||||||
|
|
||||||
```text
|
```text
|
||||||
NaN interdit comme borne
|
NaN interdit comme borne
|
||||||
@@ -182,7 +257,7 @@ NaN interdit comme borne
|
|||||||
valeur finie autorisée
|
valeur finie autorisée
|
||||||
```
|
```
|
||||||
|
|
||||||
### Exemple 21
|
### Range 3
|
||||||
|
|
||||||
```text
|
```text
|
||||||
a..a contient exactement a
|
a..a contient exactement a
|
||||||
@@ -191,7 +266,7 @@ a..<a vide
|
|||||||
a>..<a vide
|
a>..<a vide
|
||||||
```
|
```
|
||||||
|
|
||||||
### Exemple 22
|
### Range 4
|
||||||
|
|
||||||
```text
|
```text
|
||||||
range::lower()
|
range::lower()
|
||||||
@@ -202,7 +277,7 @@ range::isEmpty()
|
|||||||
range::contains(value)
|
range::contains(value)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Exemple 23
|
### Range 5
|
||||||
|
|
||||||
```text
|
```text
|
||||||
Range<T> intervalle ordonné
|
Range<T> intervalle ordonné
|
||||||
@@ -213,13 +288,13 @@ RangeReverseStep<T,Step> parcours arrière avec pas explicite
|
|||||||
RangeProgression<T,Step> valeur de progression produite
|
RangeProgression<T,Step> valeur de progression produite
|
||||||
```
|
```
|
||||||
|
|
||||||
### Exemple 24
|
### Range 6
|
||||||
|
|
||||||
```text
|
```text
|
||||||
(range)::step(step)
|
(range)::step(step)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Exemple 25
|
### Range 7
|
||||||
|
|
||||||
```text
|
```text
|
||||||
RangeStep<int32,int32>
|
RangeStep<int32,int32>
|
||||||
@@ -228,14 +303,14 @@ RangeStep<char,uint32>
|
|||||||
RangeStep<Date,Duration>
|
RangeStep<Date,Duration>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Exemple 26
|
### Range 8
|
||||||
|
|
||||||
```text
|
```text
|
||||||
(range)::reverse()
|
(range)::reverse()
|
||||||
(range)::reverse()::step(step)
|
(range)::reverse()::step(step)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Exemple 27
|
### Range 9
|
||||||
|
|
||||||
```text
|
```text
|
||||||
range
|
range
|
||||||
@@ -243,25 +318,25 @@ range
|
|||||||
[::step(step)]
|
[::step(step)]
|
||||||
```
|
```
|
||||||
|
|
||||||
### Exemple 28
|
### Range 10
|
||||||
|
|
||||||
```text
|
```text
|
||||||
(250u8..255u8)::step(2u8)
|
(250u8..255u8)::step(2u8)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Exemple 29
|
### Range 11
|
||||||
|
|
||||||
```text
|
```text
|
||||||
250 252 254
|
250 252 254
|
||||||
```
|
```
|
||||||
|
|
||||||
### Exemple 30
|
### Range 12
|
||||||
|
|
||||||
```text
|
```text
|
||||||
(1..10)::step(4)
|
(1..10)::step(4)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Exemple 31
|
### Range 13
|
||||||
|
|
||||||
```text
|
```text
|
||||||
1 5 9
|
1 5 9
|
||||||
@@ -269,4 +344,4 @@ range
|
|||||||
|
|
||||||
## DO / DON'T / WHY / compiler error / edge cases
|
## 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.
|
À consolider progressivement avant la baseline publique V3 et à transformer, lorsque pertinent, en tests de conformité de la toolchain.
|
||||||
@@ -2,100 +2,102 @@
|
|||||||
|
|
||||||
> Document compagnon. Les exemples illustrent les règles du chapitre ; la formulation normative reste dans le chapitre lui-même.
|
> Document compagnon. Les exemples illustrent les règles du chapitre ; la formulation normative reste dans le chapitre lui-même.
|
||||||
|
|
||||||
## Exemples extraits du chapitre
|
## Conversion explicite
|
||||||
|
|
||||||
### Exemple 1
|
|
||||||
|
|
||||||
```text
|
|
||||||
conversion de valeur
|
|
||||||
cast de hiérarchie nominale
|
|
||||||
bitcast de représentation binaire
|
|
||||||
```
|
|
||||||
|
|
||||||
### Exemple 2
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
int8 small = ...;
|
int8 small = ...;
|
||||||
int32 large = small; // ERROR
|
int32 large = small; // ERROR
|
||||||
int32 explicitLarge = small::toInt32(); // OK
|
int32 explicitLarge = small::toInt32(); // OK
|
||||||
```
|
```
|
||||||
|
|
||||||
### Exemple 3
|
## Widening total
|
||||||
|
|
||||||
```text
|
```text
|
||||||
Dog dog = ...;
|
int8 value = ...;
|
||||||
Animal animal = dog;
|
int32 larger = value::toInt32();
|
||||||
Serializable serializable = dog;
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Exemple 4
|
Aucun `tryToInt32()` parallèle n'est nécessaire si toutes les valeurs source sont exactement représentables.
|
||||||
|
|
||||||
|
## Narrowing exact avec `Fault`
|
||||||
|
|
||||||
```text
|
```text
|
||||||
Animal animal = ...;
|
int32 value = ...;
|
||||||
|
int8 smaller = value::toInt8();
|
||||||
if (animal is Dog) {
|
|
||||||
// animal est raffiné en Dog ici.
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Exemple 5
|
La signature Core peut déclarer :
|
||||||
|
|
||||||
```text
|
```text
|
||||||
toTarget()
|
toInt8() -> int8
|
||||||
conversion exacte et totale
|
faults NumericConversionFault
|
||||||
|
|
||||||
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
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Exemple 6
|
`OutOfRange` est produit lorsque la valeur ne tient pas dans `int8`.
|
||||||
|
|
||||||
|
## Politiques distinctes
|
||||||
|
|
||||||
```text
|
```text
|
||||||
tryToIntXX()
|
value::toInt8() // exact, peut fault
|
||||||
tryToUintXX()
|
value::saturateToInt8()
|
||||||
|
value::wrapToInt8()
|
||||||
```
|
```
|
||||||
|
|
||||||
### Exemple 7
|
Ces opérations coexistent seulement lorsque leur résultat peut réellement différer.
|
||||||
|
|
||||||
|
## Flottant vers entier
|
||||||
|
|
||||||
```text
|
```text
|
||||||
floor()
|
float64 value = ...;
|
||||||
ceil()
|
|
||||||
round()
|
int32 exact = value::toInt32();
|
||||||
truncate()
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Exemple 8
|
La conversion exige une valeur finie, intégrale et dans la plage.
|
||||||
|
|
||||||
|
Pour choisir explicitement une politique mathématique :
|
||||||
|
|
||||||
```text
|
```text
|
||||||
value::floor()::tryToInt32()
|
value::floor()::toInt32()
|
||||||
value::ceil()::tryToInt32()
|
value::ceil()::toInt32()
|
||||||
value::round()::tryToInt32()
|
value::round()::toInt32()
|
||||||
value::truncate()::tryToInt32()
|
value::truncate()::toInt32()
|
||||||
```
|
```
|
||||||
|
|
||||||
### Exemple 9
|
Pour choisir la politique de plage :
|
||||||
|
|
||||||
```text
|
```text
|
||||||
value::floor()::trySaturateToInt32()
|
value::floor()::saturateToInt32()
|
||||||
value::round()::tryWrapToInt32()
|
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
|
```text
|
||||||
NaN -> NaN
|
NaN -> NaN
|
||||||
@@ -105,31 +107,13 @@ NaN -> NaN
|
|||||||
-0 -> -0
|
-0 -> -0
|
||||||
```
|
```
|
||||||
|
|
||||||
### Exemple 11
|
## `NumericConversionFault`
|
||||||
|
|
||||||
```text
|
```text
|
||||||
payload NaN
|
NumericConversionFault extends Fault
|
||||||
quiet/signaling bit
|
|
||||||
signe du NaN
|
|
||||||
représentation binaire exacte
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Exemple 12
|
Codes :
|
||||||
|
|
||||||
```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
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
NotFinite
|
NotFinite
|
||||||
@@ -138,40 +122,10 @@ OutOfRange
|
|||||||
Inexact
|
Inexact
|
||||||
```
|
```
|
||||||
|
|
||||||
### Exemple 14
|
DON'T : introduire mécaniquement :
|
||||||
|
|
||||||
```text
|
```text
|
||||||
NotFinite
|
tryToTarget() -> Result<Target,NumericConversionError>
|
||||||
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
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Exemple 15
|
si cette méthode ne ferait que dupliquer `toTarget() faults NumericConversionFault`.
|
||||||
|
|
||||||
```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.
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ threads natifs
|
|||||||
structured concurrency éventuelle
|
structured concurrency éventuelle
|
||||||
cancellation
|
cancellation
|
||||||
synchronisation
|
synchronisation
|
||||||
interaction avec Result/throws
|
interaction avec Result/throws/faults
|
||||||
interaction avec destruction déterministe
|
interaction avec destruction déterministe
|
||||||
runtime minimal
|
runtime minimal
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -51,3 +51,16 @@ ownership annotations pour les usages ordinaires
|
|||||||
## DO / DON'T / WHY / compiler error / edge cases
|
## 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.
|
À 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
|
## 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.
|
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 la sémantique d'un index hors limites
|
||||||
modifier l'ordre d'évaluation
|
modifier l'ordre d'évaluation
|
||||||
modifier la représentation sémantique des types
|
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
|
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
|
faire varier la validité d'un programme Saselang autrement que par une limite propre au backend/target
|
||||||
```
|
```
|
||||||
|
|||||||
Reference in New Issue
Block a user