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

View File

@@ -1,4 +1,4 @@
# Bible Saselang 0.2.16
# Bible Saselang 0.2.17
> **Statut : pré-spécification normative de Saselang V1.**
>
@@ -7,7 +7,7 @@
>
> La V2 visera principalement la réécriture/self-hosting de la toolchain V1 en Saselang lui-même. Les extensions majeures de cibles et d'écosystème sont prévues à partir de V3+.
>
> **Révision 0.2.16 :** formalisation des arrays/slices et de leur initialisation, hiérarchie de capacités de collections (`Collection`, `List`, `SettableList`, `ResizableList`), sous-chaînes à stockage partageable et politique des bibliothèques officielles `.saselib`.
> **Révision 0.2.17 :** introduction normative de `Fault` comme troisième branche d`Error`, ajout de `fault` / `faults`, indépendance de `throws` vis-à-vis du type de retour, simplification des conversions numériques/Unicode, fermeture des contrats `Map`/`Set`/`View`/`Iterator` et des collections ordonnées.
## Organisation de cette distribution

View File

@@ -1,4 +1,4 @@
# Sommaire — Bible Saselang 0.2.16
# Sommaire — Bible Saselang 0.2.17
## Chapitres

View File

@@ -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

View File

@@ -1,65 +1,153 @@
format = 1
version = "0.2.16"
version = "0.2.17"
distribution = "delta"
base_version = "0.2.15"
base_version = "0.2.16"
documentation_layout = "multifile"
[[modified]]
path = "000-README.md"
sha256 = "4b4d422dcc52991e38c6cb1b7b92aeb391ca0b7d6bc1c8da0de4de6169c93b7a"
sha256 = "ca87a3caaadb1a618f0a35620a2e62e406bd8e186de0a7282e606a38f9f541ca"
[[modified]]
path = "001-SUMMARY.md"
sha256 = "2cf8811903512dc58739c4d16e2696d10bcb36f2b767d3e5eccf038013ef1a66"
sha256 = "88f6f80b7233900491f15d818cebbfdb3fc83f02667cfa137cb3ed6a17f86edf"
[[modified]]
path = "003-CHANGELOG.md"
sha256 = "0f78fefe1d630ebc0587b7bb0865f77c34b9782562bf47af6d86e82cac8bf738"
sha256 = "ccc7116c032fc68b6a91fba447674673d0a6141229498e1db3d00a246d11df0f"
[[modified]]
path = "annexes/A-numeric-conversions.md"
sha256 = "cc13423ccf18bbfac922f6e9a9afe422d438bd1f4aeea10919941a55c3d9dc98"
[[modified]]
path = "annexes/B-unicode-encoding-conversions.md"
sha256 = "c26a957419e4b60706b61c9f482380a5cd496de2fe685beb33bc86927a287ee4"
[[modified]]
path = "chapters/002-principes-generaux-du-langage.md"
sha256 = "63b26e729bac07ee2395634698c54f33c0f16d6f121571e9bc6096bd05cfa40f"
[[modified]]
path = "chapters/004-couches-de-lecosysteme-v1.md"
sha256 = "5d6bfbc9e9d7c5253fbe470c114a2b2394c16cf62a5cd7efd3d9f40252ae0106"
sha256 = "18c0b82d5b2b55dab17a2197dc2635d1d050ac4b06b6c3fc1dc34e12e5978bb6"
[[modified]]
path = "chapters/011-tuples.md"
sha256 = "8008f930e37a69980ccf39af0261d5af63efb136268c4793e1899da1fc58a523"
[[modified]]
path = "chapters/013-interfaces.md"
sha256 = "330f2d231ed7d6ffbbbd8a1703c8f27f17b2c9c2b372d5c5c663fa4b6ae3a43d"
[[modified]]
path = "chapters/015-fonctions-methodes-et-clsmethod.md"
sha256 = "e15da7b6f0b86fcadfa7d0ec4c5b4877ed97580d7292aa13dfab3a271b3b2468"
[[modified]]
path = "chapters/018-result-erreurs-et-exceptions.md"
sha256 = "d2e08f85e0f077ece4e5f15d3dc47ce552608376001b128f222230070ed23726"
[[modified]]
path = "chapters/019-controle-de-flux.md"
sha256 = "34ec610fd03ac339504d48a265793fdb2c146404d38285b9bada72683f88361d"
[[modified]]
path = "chapters/020-operateurs.md"
sha256 = "59119759c87babc9dc0d852fcdfcda6d527fcb475c6c22d26cd0fe546d50f0df"
[[modified]]
path = "chapters/021-strings-unicode-et-encodages.md"
sha256 = "3350f8581eb43343136caf7cf808b25da4543edac6b176ad61d3e40292b19d76"
sha256 = "c8e5ea1e1fce5fe3128d7dd1eb73ddd784b71d3fa24298de9bfabc1d44e05327"
[[modified]]
path = "chapters/022-collections-et-iteration.md"
sha256 = "a60534eef7f12201b238c7a4899b46c8be4df3535f293978e05471cc210c3d7a"
sha256 = "e7459c2db8d0fe0cdf573d25f888c1791b6d03a9de6f51ae849991039abc4328"
[[modified]]
path = "chapters/037-dependances-et-scopes.md"
sha256 = "64335ed6b00a8133718384e49b34be0f362569b9b177a35da963543abe603a9a"
path = "chapters/024-casts-et-conversions.md"
sha256 = "e6cd16e5e4b65c2f05bac57a5410cb7aaa74253d2572f969b4fcf1dbf3618e93"
[[modified]]
path = "chapters/026-async-et-concurrence.md"
sha256 = "65ab9ddcfa155130daf913d9f24ebf8583fca92e3fbd4325d3b5ef86729b998a"
[[modified]]
path = "chapters/027-memoire-references-et-unsafe.md"
sha256 = "c82271a7b7b179b49a963c1f00b1e5179c71c4d9839a50d4ca541b9b6c604215"
[[modified]]
path = "chapters/028-defer-et-nettoyage.md"
sha256 = "d2d9d9e5b2faa7a238931f80a3247b735e9a1a1c5967a3920b3649da6a6bfd32"
[[modified]]
path = "chapters/041-artifacts-exports-profils-et-reservation-des-formats-futurs.md"
sha256 = "bbec66e98338765dfb85b22e941811eedc2f1c7bd11ab9ccc86483f3ea4c3ec2"
[[modified]]
path = "chapters/042-main-et-exitcode.md"
sha256 = "c8466a02c19df25d3a792fc289e774f1f4f790137389b6c9e0a9905f0cf28bcc"
[[modified]]
path = "chapters/043-documentation-et-tests-de-conformite.md"
sha256 = "3769820873793f73f75030c0d54c8194cbdc2a9a0428ccfd6707e3284f194003"
[[modified]]
path = "chapters/048-inventaire-des-points-v1-encore-ouverts.md"
sha256 = "3c99a2d2901e5843b4ea40b26c541203c907a809ad2004fd93c0ad4a94a68413"
sha256 = "908856acb0472c2c4eee3d03b8260f21b5b6495d342053f371b00e54158ed2d1"
[[modified]]
path = "chapters/051-invariants-de-conception.md"
sha256 = "05c23658ea2b127c023b5d75630bd79096934d21f04f67f01375486fd35386e4"
sha256 = "c41f6c977c613631147b7d61c837afccc9b1c6807d62ade8175865f5108bf915"
[[modified]]
path = "examples/002-principes-generaux-du-langage-examples.md"
sha256 = "42b5758d733563c0bdabad9f6005f5818ccb42513e599bc878142db6b4298e10"
[[modified]]
path = "examples/004-couches-de-lecosysteme-v1-examples.md"
sha256 = "3b37dee80e15c28fde237d208da3b16885c3190603f074b3bf4fabc21cda13e8"
sha256 = "2731f6e5861d041801bf831a936c59c6df854ac55b858500e32542e64105bb8a"
[[modified]]
path = "examples/013-interfaces-examples.md"
sha256 = "2338543b0551c291dea59ebbd394a35d9e560d817b9e2d92eaa62c02d6ee3bd0"
[[modified]]
path = "examples/015-fonctions-methodes-et-clsmethod-examples.md"
sha256 = "0760c83e732d77942b48339135a146d98a60f6dd2c60fc06bc8b093fdf026058"
[[modified]]
path = "examples/018-result-erreurs-et-exceptions-examples.md"
sha256 = "47f50de6f6bf327e9f00de9a5a4e9470839d6e5e4d0ee570e432441d2924c6bb"
[[modified]]
path = "examples/020-operateurs-examples.md"
sha256 = "717035959ea34130d7eeed2af8d3945afb10772b3015f6031c4462494076fec3"
[[modified]]
path = "examples/021-strings-unicode-et-encodages-examples.md"
sha256 = "e065baa54cd9203f9b37883f5c418baea27ffc0fe4d28e97ff349a1b66f8adc7"
sha256 = "6ed3cd078599b329b5f8f42ceda323eadc954f3d7d566e177adca56451a2345b"
[[modified]]
path = "examples/022-collections-et-iteration-examples.md"
sha256 = "86749fa6c85fbfbc2cd18643ad1da639af76222845ebf4418e62f7744cb76003"
sha256 = "f3546d35335937506044a697ff1610da20823bf29334c307d6cf7a53122d8ce3"
[[modified]]
path = "examples/037-dependances-et-scopes-examples.md"
sha256 = "a384f5a4c624f75f7a52186c731fc95890fb0ee5067788b4f93b90b0989774e1"
path = "examples/024-casts-et-conversions-examples.md"
sha256 = "47a4d0e0e7fd822995be140d62432f48642da237d026551fc922f011776d1b8b"
[[modified]]
path = "examples/048-inventaire-des-points-v1-encore-ouverts-examples.md"
sha256 = "069383c40e74b495cdd3ccbebd87850654fa1ef4b6095e93a4eab14acb5d1f3d"
path = "examples/026-async-et-concurrence-examples.md"
sha256 = "0a206a6b7ee2818a1e743b0dc1a033b27ebd75f543b9979d9c7fa37150c30255"
[[modified]]
path = "examples/051-invariants-de-conception-examples.md"
sha256 = "307da7506d8411f033cfcfbf5fc555651175e28e64119e248a1c4d341afa487f"
path = "examples/027-memoire-references-et-unsafe-examples.md"
sha256 = "acadba49f317caa4805e8770c5732a029071559921a6c0a05281cfb026ef98e6"
[[modified]]
path = "examples/028-defer-et-nettoyage-examples.md"
sha256 = "121e51d8cef0c2de89005d895aa05dfb8c52e9c69991dac411d1ceb7dbb00b05"
[[modified]]
path = "examples/041-artifacts-exports-profils-et-reservation-des-formats-futurs-examples.md"
sha256 = "673a51f5c919b22ab1ec72b95f79ce17afd64ab0ec70bfaba260fc245a1f51d2"

View File

@@ -1,32 +1,29 @@
# Saselang — Annexe A — Matrice des conversions numériques
**Version documentaire : 0.2.12. Statut : inventaire de conception Core, destiné à devenir normatif après validation.**
**Version documentaire : 0.2.17. Statut : inventaire de conception Core destiné à devenir normatif après validation.**
Cette annexe est le listing exhaustif de travail des conversions numériques Core.
Son objectif est d'énumérer le maximum de conversions numériques sémantiquement distinctes sans introduire d'alias ou de doublons inutiles.
Cette annexe inventorie les conversions numériques Core sémantiquement distinctes sans créer d'alias ou de doublons inutiles.
## A.1. Répartition des responsabilités
Les conversions numériques sont exposées comme capacités de l'API Core des primitives. Elles ne deviennent pas chacune une construction grammaticale du compilateur.
Les conversions numériques sont des capacités de l'API Core des primitives, pas des constructions grammaticales distinctes.
```text
Bible langage / compilateur
définit les règles de typage, d'appel, d'intrinsic, de target et de lowering
définit typage, contrats, faults, targets et lowering
Core
expose les membres numériques concrets
ex. int32::tryToInt8(), float64::tryRoundToFloat32()
ex. int32::toInt8(), float64::roundToFloat32()
Annexe Core
liste exhaustivement les opérations disponibles par paire de types
liste les opérations disponibles par paire de types
Compilateur / Sase IR / backend
valide et abaisse l'opération Core sans que chaque nom devienne de la grammaire
valide et abaisse les opérations Core
```
Une capacité Core peut être conditionnée par un target ou une plateforme lorsque cela est réellement nécessaire. L'absence d'une capacité demandée doit être diagnostiquée à la compilation pour le target choisi, et non découverte tardivement dans le backend.
Les conversions numériques fondamentales entre primitives standard sont destinées à constituer le socle Core commun ; le mécanisme de capacités existe surtout pour les opérations qui ne peuvent raisonnablement pas être garanties partout.
Si les types source et destination sont supportés par un target, les conversions fondamentales non redondantes sont Core-required. Une implémentation logicielle conforme est admise lorsqu'une instruction matérielle n'existe pas.
## A.2. Règle de non-redondance
@@ -34,68 +31,86 @@ Une variante n'existe que si elle apporte une sémantique observable différente
Exemple :
```saselang
```text
int8 value = ...;
int32 larger = value::toInt32();
```
Puisque toutes les valeurs `int8` sont représentables exactement dans `int32`, les formes suivantes n'ont aucune raison d'exister :
Toutes les valeurs `int8` sont exactement représentables dans `int32`; il n'existe donc pas de variantes inutiles `saturateToInt32()` ou `wrapToInt32()`.
Pour `int32 -> int8`, les trois contrats suivants sont distincts :
```text
tryToInt32()
saturateToInt32()
wrapToInt32()
toInt8() // exact, peut fault OutOfRange
saturateToInt8()
wrapToInt8()
```
En revanche, pour `int32 -> int8`, `tryToInt8()`, `saturateToInt8()` et `wrapToInt8()` ont trois contrats différents et peuvent coexister.
Une règle de composition complète cette non-redondance :
Règle de composition :
> Deux opérations ne sont fusionnées dans un même nom que si leur séparation en opérations Core successives modifierait la sémantique, perdrait de l'information ou empêcherait d'exprimer le même contrat.
Ainsi `value::floor()::tryToInt32()` rend inutile un alias `tryFloorToInt32()` si les deux formes sont strictement équivalentes.
Ainsi :
## A.3. Nomenclature générale
```text
value::floor()::toInt32()
```
rend inutile un alias `floorToInt32()` si les deux formes sont strictement équivalentes.
## A.3. Canal d'échec V1
Les anciennes variantes `try... -> Result<T,NumericConversionError>` ne font plus partie de la matrice canonique uniquement pour transporter un échec de conversion.
La conversion directe retourne la destination attendue et peut déclarer :
```text
faults NumericConversionFault
```
lorsque sa précondition runtime n'est pas totale.
`NumericConversionFault` est unchecked et capturable. Une API spécialisée peut toujours choisir explicitement `Result` si son domaine veut représenter l'échec comme une valeur normale, mais cela ne crée pas une seconde famille automatique `try...` dans le Core numérique.
## A.4. Nomenclature générale
| Code | Famille | Contrat |
|---|---|---|
| `T` | `toTarget()` | Exacte et totale pour toutes les valeurs valides du type source. |
| `E` | `tryToTarget()` | Exacte pour la valeur courante ; retourne `Err` si l'exactitude ou la représentabilité échoue. |
| `R` | `roundToTarget()` | Perte de précision explicitement acceptée ; conversion totale pour cette paire de types. |
| `TR` | `tryRoundToTarget()` | Arrondi explicitement accepté, mais la valeur peut être hors du domaine destination. |
| `S` | `saturateToTarget()` | Conversion totale par saturation lorsqu'aucun arrondi supplémentaire n'est nécessaire. |
| `SR` | `saturatingRoundToTarget()` | Arrondi canonique + saturation explicites pour une destination flottante lorsque les deux peuvent être nécessaires. |
| `W` | `wrapToTarget()` | Conversion entière modulo `2^N`, avec interprétation selon le type entier destination. |
| `E` | `toTarget()` | Exacte pour la valeur courante ; `faults NumericConversionFault` si impossible. |
| `R` | `roundToTarget()` | Perte de précision explicitement acceptée ; totale pour cette paire. |
| `FR` | `roundToTarget()` | Arrondi accepté ; peut fault si la valeur est hors du domaine destination. |
| `S` | `saturateToTarget()` | Saturation explicite lorsqu'aucun arrondi supplémentaire n'est nécessaire. |
| `SR` | `saturatingRoundToTarget()` | Arrondi canonique + saturation explicites. |
| `W` | `wrapToTarget()` | Conversion entière modulo `2^N`. |
| `—` | aucune | Même type ou opération sans sémantique distincte utile. |
`NumericConversionError` est retenu comme nom de travail Core. Il pourra être renommé avant stabilisation de la spécification si nécessaire.
Aucune de ces opérations n'autorise une conversion implicite entre deux valeurs déjà typées.
Les formes `try...` retournent conceptuellement :
```saselang
Result<Target, NumericConversionError>
```
Aucune de ces opérations n'autorise une conversion implicite entre deux variables déjà typées.
## A.4. Flottants : hypothèses de représentation
## A.5. Flottants : hypothèses de représentation
| Type | Précision significative `p` | Exposant maximal fini |
|---|---|---|
|---|---:|---:|
| `float16` | 11 bits | 15 |
| `float32` | 24 bits | 127 |
| `float64` | 53 bits | 1023 |
| `float128` | 113 bits | 16383 |
Les conversions avec arrondi utilisent par défaut la règle canonique **round to nearest, ties to even**. Cette règle ne dépend ni du linter, ni du profil, ni du backend.
Les conversions avec arrondi utilisent la règle canonique **round to nearest, ties to even**. Cette règle ne dépend ni du linter, ni du profil, ni du backend.
## A.5. Entier -> entier
## A.6. Entier -> entier
Légende :
- `T` = `toTarget()` uniquement ;
- `E+S+W` = `tryToTarget()` + `saturateToTarget()` + `wrapToTarget()`.
```text
T
toTarget() total
E+S+W
toTarget() faults OutOfRange
saturateToTarget()
wrapToTarget()
```
| Source \ Destination | int8 | int16 | int32 | int64 | int128 | int256 | uint8 | uint16 | uint32 | uint64 | uint128 | uint256 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -114,95 +129,104 @@ Légende :
Règles :
- si le domaine source est entièrement inclus dans le domaine destination, seule la forme `to...` existe ;
- sinon `tryTo...` effectue une conversion exacte conditionnelle ;
- `saturateTo...` borne à `Target::Min` / `Target::Max` ; pour un signé vers non signé, toute valeur négative sature à `0` ;
- `wrapTo...` utilise une définition mathématique modulo `2^N`, indépendante de la représentation machine du backend ;
- domaine source entièrement inclus -> `to...` total ;
- sinon `to...` reste exact mais peut produire `OutOfRange` ;
- `saturateTo...` borne à `Target::Min` / `Target::Max`, avec `0` pour un négatif vers non signé ;
- `wrapTo...` utilise une définition mathématique modulo `2^N` ;
- aucun wrapping ni saturation n'est implicite.
## A.6. Entier -> flottant
## A.7. Entier -> flottant
Légende :
- `T` = `toFloatXX()` uniquement ;
- `E+R` = `tryToFloatXX()` + `roundToFloatXX()` ;
- `E+TR+SR` = `tryToFloatXX()` + `tryRoundToFloatXX()` + `saturatingRoundToFloatXX()`.
```text
T
toFloatXX() total et exact
E+R
toFloatXX() exact, peut fault Inexact
roundToFloatXX() total
E+FR+SR
toFloatXX() exact, peut fault Inexact/OutOfRange
roundToFloatXX() peut fault OutOfRange
saturatingRoundToFloatXX() total
```
| Source \ Destination | float16 | float32 | float64 | float128 |
|---|---|---|---|---|
| int8 | T | T | T | T |
| int16 | E+R | T | T | T |
| int32 | E+TR+SR | E+R | T | T |
| int64 | E+TR+SR | E+R | E+R | T |
| int128 | E+TR+SR | E+R | E+R | E+R |
| int256 | E+TR+SR | E+TR+SR | E+R | E+R |
| int32 | E+FR+SR | E+R | T | T |
| int64 | E+FR+SR | E+R | E+R | T |
| int128 | E+FR+SR | E+R | E+R | E+R |
| int256 | E+FR+SR | E+FR+SR | E+R | E+R |
| uint8 | T | T | T | T |
| uint16 | E+TR+SR | T | T | T |
| uint32 | E+TR+SR | E+R | T | T |
| uint64 | E+TR+SR | E+R | E+R | T |
| uint128 | E+TR+SR | E+TR+SR | E+R | E+R |
| uint256 | E+TR+SR | E+TR+SR | E+R | E+R |
| uint16 | E+FR+SR | T | T | T |
| uint32 | E+FR+SR | E+R | T | T |
| uint64 | E+FR+SR | E+R | E+R | T |
| uint128 | E+FR+SR | E+FR+SR | E+R | E+R |
| uint256 | E+FR+SR | E+FR+SR | E+R | E+R |
Contrats :
Exemple :
- `toFloatXX()` existe seulement si **toute** valeur source est exactement représentable ;
- `tryToFloatXX()` exige une représentation exacte de la valeur courante ;
- `roundToFloatXX()` existe seulement lorsque toute valeur source reste dans le domaine fini destination, mais qu'une perte de précision peut être nécessaire ;
- `tryRoundToFloatXX()` accepte l'arrondi canonique mais retourne `Err` si la magnitude finie dépasse le domaine destination ;
- `saturatingRoundToFloatXX()` est réservé aux paires pour lesquelles un débordement de domaine est possible : une valeur finie trop grande est bornée au plus grand fini de même signe, puis la précision destination s'applique selon l'arrondi canonique ;
- il n'existe pas de `wrapToFloatXX()`.
Exemple distinct :
```saselang
```text
int64 value = ...;
Result<float64, NumericConversionError> exact = value::tryToFloat64();
float64 exact = value::toFloat64();
float64 approximated = value::roundToFloat64();
```
`tryToFloat64()` et `roundToFloat64()` ne sont pas des alias : le premier refuse toute perte de précision, le second l'accepte explicitement.
La première opération exige l'exactitude et peut produire `NumericConversionFault::Inexact`; la seconde accepte explicitement la perte de précision.
## A.7. Flottant -> flottant
## A.8. Flottant -> flottant
Légende :
- `T` = `toFloatXX()` uniquement ;
- `E+TR+SR` = `tryToFloatXX()` + `tryRoundToFloatXX()` + `saturatingRoundToFloatXX()`.
```text
T
toFloatXX() total et exact
E+FR+SR
toFloatXX() exact, peut fault
roundToFloatXX() accepte l'arrondi, peut fault OutOfRange fini
saturatingRoundToFloatXX() total
```
| Source \ Destination | float16 | float32 | float64 | float128 |
|---|---|---|---|---|
| float16 | — | T | T | T |
| float32 | E+TR+SR | — | T | T |
| float64 | E+TR+SR | E+TR+SR | — | T |
| float128 | E+TR+SR | E+TR+SR | E+TR+SR | — |
| float32 | E+FR+SR | — | T | T |
| float64 | E+FR+SR | E+FR+SR | — | T |
| float128 | E+FR+SR | E+FR+SR | E+FR+SR | — |
Règles :
- l'élargissement de format est exact au niveau de la valeur IEEE et utilise uniquement `toFloatXX()` ;
- la réduction de format propose `tryToFloatXX()` pour exiger l'exactitude, `tryRoundToFloatXX()` pour accepter la perte de précision mais pas le débordement fini, et `saturatingRoundToFloatXX()` pour obtenir une opération totale sur le domaine flottant ;
- `NaN`, `+Infinity`, `-Infinity`, `+0` et `-0` restent des catégories IEEE valides dans la destination ;
- pour `NaN`, seule la propriété sémantique `isNaN(destination) == true` est garantie ; payload, signe et quiet/signaling bit ne sont pas garantis par une conversion de valeur ;
- `tryToFloatXX()` accepte `NaN` et les infinities lorsque la destination est un type flottant Saselang, car ces catégories y sont représentables ;
- `saturatingRoundToFloatXX()` ne transforme pas une infinité en valeur finie puisque l'infinité est elle-même représentable dans le format destination ; la saturation explicite concerne les valeurs **finies** hors du domaine fini destination ;
- la conservation exacte d'une représentation binaire relève d'un contrat binaire distinct et de `bitcast` lorsque ses propres contraintes sont compatibles.
- l'élargissement de format utilise `toFloatXX()` total ;
- la réduction exacte utilise `toFloatXX()` avec fault si nécessaire ;
- `roundToFloatXX()` accepte la perte de précision mais pas un débordement fini ;
- `saturatingRoundToFloatXX()` sature seulement les valeurs finies hors domaine fini ;
- `NaN`, `+Infinity`, `-Infinity`, `+0` et `-0` restent des catégories valides ;
- pour `NaN`, seule la propriété sémantique `isNaN(destination) == true` est garantie.
## A.8. Flottant -> entier : composition des politiques
Il n'existe jamais de simple `toIntXX()` ou `toUintXX()` depuis un flottant.
## A.9. Flottant -> entier : composition des politiques
La conversion stricte canonique est :
```text
tryToIntXX()
tryToUintXX()
toIntXX()
toUintXX()
```
Elle réussit uniquement si la valeur flottante est finie, mathématiquement entière, dans le domaine de la destination et exactement représentable comme entier destination. Sinon elle retourne `Err(NumericConversionError(...))`.
avec :
### A.8.1. Politiques mathématiques séparées
```text
faults NumericConversionFault
```
Les opérations Core :
lorsque la valeur peut être non finie, non entière ou hors plage.
### A.9.1. Politiques mathématiques séparées
```text
floor()
@@ -211,67 +235,56 @@ round()
truncate()
```
restent des opérations sur le flottant et définissent chacune une politique mathématique unique.
restent des opérations sur le flottant. Elles se composent ensuite avec la conversion :
Elles se composent ensuite avec les conversions :
```saselang
value::floor()::tryToInt32()
value::ceil()::tryToInt32()
value::round()::tryToInt32()
value::truncate()::tryToInt32()
```text
value::floor()::toInt32()
value::ceil()::toInt32()
value::round()::toInt32()
value::truncate()::toInt32()
```
Cette composition remplace les alias redondants `tryFloorTo...`, `tryCeilTo...`, `tryRoundTo...` et `tryTruncateTo...`.
Aucun alias combiné n'est ajouté lorsqu'il serait strictement équivalent.
`round()` utilise la règle canonique **nearest, ties to even**.
### A.8.2. Dépassement de domaine
Les politiques de dépassement restent séparées de la politique mathématique.
### A.9.2. Dépassement de domaine
Pour chaque destination entière, le Core peut exposer :
```text
tryToTarget()
trySaturateToTarget()
tryWrapToTarget()
toTarget()
saturateToTarget()
wrapToTarget()
```
avec les contrats suivants :
| Opération | Préconditions non liées à la plage | Politique de plage |
| Opération | Préconditions hors plage | Politique de plage |
|---|---|---|
| `tryToTarget()` | valeur finie et mathématiquement entière | `Err` si hors plage |
| `trySaturateToTarget()` | valeur finie et mathématiquement entière | borne à `Target::Min` / `Target::Max` |
| `tryWrapToTarget()` | valeur finie et mathématiquement entière | modulo `2^N` selon le type entier destination |
| `toTarget()` | valeur finie et mathématiquement entière | `OutOfRange` si hors plage |
| `saturateToTarget()` | valeur finie et mathématiquement entière | borne à `Target::Min` / `Target::Max` |
| `wrapToTarget()` | valeur finie et mathématiquement entière | modulo `2^N` |
Les politiques se composent :
`NotFinite` et `NotIntegral` restent possibles pour les trois familles lorsqu'elles s'appliquent.
```saselang
value::floor()::trySaturateToInt32()
value::round()::trySaturateToUint16()
Exemples :
value::truncate()::tryWrapToInt8()
value::ceil()::tryWrapToUint64()
```text
value::floor()::saturateToInt32()
value::round()::saturateToUint16()
value::truncate()::wrapToInt8()
value::ceil()::wrapToUint64()
```
Il n'existe pas de variantes combinées telles que `trySaturatingFloorToInt32()` ou `tryWrappingRoundToInt32()` lorsque la composition ci-dessus possède exactement la même sémantique.
### A.8.3. Matrice flottant -> entier après élimination des doublons
Pour chaque paire, la matrice conserve uniquement les politiques dont le résultat peut réellement différer sur une valeur source admissible.
### A.9.3. Matrice flottant -> entier après élimination des doublons
Légende :
```text
C
tryToTarget() uniquement
toTarget() uniquement
CSW
tryToTarget()
trySaturateToTarget()
tryWrapToTarget()
toTarget()
saturateToTarget()
wrapToTarget()
```
| Source \ Destination | int8 | int16 | int32 | int64 | int128 | int256 | uint8 | uint16 | uint32 | uint64 | uint128 | uint256 |
@@ -281,75 +294,37 @@ CSW
| float64 | CSW | CSW | CSW | CSW | CSW | CSW | CSW | CSW | CSW | CSW | CSW | CSW |
| float128 | CSW | CSW | CSW | CSW | CSW | CSW | CSW | CSW | CSW | CSW | CSW | CSW |
Justification :
- toutes les valeurs finies et mathématiquement entières de `float16` tiennent dans `int32` et les entiers signés plus larges ; saturation et wrapping n'apportent donc rien pour ces paires ;
- toutes les valeurs finies et mathématiquement entières de `float32` tiennent dans `int256`, mais pas dans `int128` ou plus petit ;
- pour toute destination non signée, les valeurs négatives rendent checked, saturation et wrapping distincts, même lorsque toute magnitude positive finie tient dans la destination ;
- `float64` et `float128` disposent de valeurs finies dépassant le domaine de tous les entiers Saselang V1.
Cas particuliers :
- `+0` et `-0` donnent l'entier zéro ;
- `NaN`, `+Infinity` et `-Infinity` échouent dans ces familles car ils ne satisfont pas la précondition de valeur finie et mathématiquement entière ;
- pour une destination non signée, la saturation d'une valeur négative entière donne `0` ;
- pour une destination signée, la saturation utilise `Target::Min` / `Target::Max` ;
- le wrapping est appliqué au résultat entier mathématique fini selon modulo `2^N`.
- `+0` et `-0` donnent zéro ;
- `NaN` et les infinities produisent `NotFinite` ;
- une valeur fractionnaire produit `NotIntegral` avant la politique de plage ;
- vers un non signé, la saturation d'une valeur négative entière donne `0` ;
- le wrapping s'applique à l'entier mathématique fini modulo `2^N`.
## A.9. `bitcast` reste hors de cette matrice
## A.10. `bitcast` reste hors de cette matrice
`bitcast<T>(value)` n'est pas une conversion numérique. Il conserve les bits et change leur interprétation sous les contraintes de taille et de validité déjà définies par le langage.
`bitcast<T>(value)` conserve les bits et change leur interprétation sous ses propres contraintes. Il ne constitue jamais une alternative implicite à `to...`, `round...`, `saturate...` ou `wrap...`.
Il ne constitue jamais une alternative implicite à `to...`, `try...`, `round...`, `saturate...` ou `wrap...`.
## A.10. Typage contextuel des littéraux
## A.11. Typage contextuel des littéraux
Le typage contextuel d'un littéral reste distinct de toute conversion de valeur déjà typée.
```saselang
int32 a = 42; // contextualisation du littéral
```text
int32 a = 42;
int8 small = ...;
int32 b = small; // ERROR : pas de conversion implicite
int32 c = small::toInt32(); // OK
int32 b = small; // ERROR
int32 c = small::toInt32(); // OK
```
## A.11. Core, targets et capacités
Les membres de conversion appartiennent au Core des primitives. Le compilateur doit pouvoir reconnaître leur contrat via les métadonnées/Core intrinsics nécessaires sans transformer chaque membre en syntaxe spéciale.
Pour les conversions fondamentales de cette matrice :
> si les types source et destination sont supportés par le target, les opérations non redondantes définies par la matrice sont Core-required.
L'absence d'une instruction matérielle native ne rend pas l'opération optionnelle lorsqu'une émulation logicielle conforme est raisonnablement possible.
Un target réduit peut ne pas exposer un type fondamental donné. Dans ce cas, l'indisponibilité doit porter sur le type/capacité fondamentale, pas sur une sélection arbitraire de ses conversions.
La nomenclature générale des capabilities et leurs niveaux sont définis au chapitre 40.
## A.12. Hiérarchie documentaire cible
La documentation Saselang est destinée à être organisée par niveaux :
## A.12. `NumericConversionFault`
```text
Language / Compiler Specification
ce que le compilateur doit accepter, refuser et produire
Saselang + Core Specification
langage + environnement Core normatif
Saselang Platform Documentation
langage + Core + SDKs + extensions de plateforme
NumericConversionFault extends Fault
```
Depuis `0.2.12`, la Bible est distribuée sous forme d'une archive multifichier structurée avec sommaire, chapitres séparés, exemples/DO-DON'T par chapitre et annexes référencées.
## A.13. `NumericConversionError`
`NumericConversionError` est le nom de travail du `ResultError` Core des conversions récupérables.
Les codes sémantiques V1 sont :
Codes sémantiques V1 :
```text
NotFinite
@@ -358,19 +333,20 @@ OutOfRange
Inexact
```
L'erreur reste minimale et ne transporte pas automatiquement la valeur source, les types source/destination, le backend, un timestamp ou un mode d'arrondi.
Le fault reste minimal et ne transporte pas automatiquement la valeur source, les types source/destination, le backend, un timestamp ou un mode d'arrondi.
## A.14. État de l'annexe
## A.13. État de l'annexe
Les principes sémantiques de la matrice sont désormais largement figés :
Principes largement figés :
```text
non-redondance par paire
composition plutôt qu'alias combinés
Fault direct à la place des anciens try... purement mécaniques
règles float -> integer
règles NaN / infinities / signed zero
NumericConversionError
disponibilité Core pour les types supportés
NumericConversionFault
Core-required pour les types supportés
émulation logicielle lorsque raisonnable
```
@@ -378,5 +354,5 @@ Restent principalement à auditer lors de l'implémentation Core :
1. le listing mécanique exhaustif des membres concrets exposés par chaque primitive ;
2. les noms définitifs des constantes/membres Core associés ;
3. la représentation interne exacte des codes `NumericConversionError` ;
3. la représentation interne exacte des codes `NumericConversionFault` ;
4. les tests de conformité couvrant toutes les cellules de la matrice.

View File

@@ -9,8 +9,9 @@ Elle applique les mêmes principes que la matrice numérique :
```text
aucune conversion implicite
aucun mélange de types dans les opérations textuelles
to... uniquement pour une conversion totale et sûre
tryFrom... / tryTo... lorsqu'une validation ou une condition peut échouer
conversion directe vers la valeur attendue
faults UnicodeEncodingFault lorsqu'une validation runtime peut échouer
aucune variante try... parallèle si elle ne change que le canal d'échec
aucun alias redondant
conversion explicite d'abord, opération ensuite
```
@@ -106,8 +107,8 @@ Ces transcodages sont totaux.
UTF-8 :
```text
Utf8Char::tryFrom(uint8)
Utf8Char::tryFrom(StaticArray<uint8, N>)
Utf8Char::from(uint8) faults UnicodeEncodingFault
Utf8Char::from(StaticArray<uint8, N>) faults UnicodeEncodingFault
```
`N` utile : 1 à 4. Le contenu doit représenter exactement un scalar UTF-8 valide.
@@ -115,8 +116,8 @@ Utf8Char::tryFrom(StaticArray<uint8, N>)
UTF-16 :
```text
Utf16Char::tryFrom(uint16)
Utf16Char::tryFrom(StaticArray<uint16, 2>)
Utf16Char::from(uint16) faults UnicodeEncodingFault
Utf16Char::from(StaticArray<uint16, 2>) faults UnicodeEncodingFault
```
Un surrogate isolé est invalide.
@@ -124,7 +125,7 @@ Un surrogate isolé est invalide.
UTF-32 :
```text
Utf32Char::tryFrom(uint32)
Utf32Char::from(uint32) faults UnicodeEncodingFault
```
La valeur doit être <= `0x10FFFF` et hors de la plage surrogate.
@@ -132,15 +133,17 @@ La valeur doit être <= `0x10FFFF` et hors de la plage surrogate.
Le nom de travail de l'erreur est :
```text
UnicodeEncodingError extends ResultError
UnicodeEncodingFault extends Fault
```
Le Core ne fournit pas simultanément une variante `tryFrom... -> Result` ayant exactement la même validation. Si un domaine applicatif souhaite transporter l'échec comme valeur, il peut encapsuler explicitement la construction dans son propre `Result`.
## B.7. `UtfXChar` -> code unit brute
| Source | Destination | Opération | Raison |
|---|---|---|---|
| `Utf8Char` | `uint8` | `tryToUint8()` | 1 à 4 unités possibles |
| `Utf16Char` | `uint16` | `tryToUint16()` | 1 ou 2 unités possibles |
| `Utf8Char` | `uint8` | `toUint8() faults UnicodeEncodingFault` | 1 à 4 unités possibles |
| `Utf16Char` | `uint16` | `toUint16() faults UnicodeEncodingFault` | 1 ou 2 unités possibles |
| `Utf32Char` | `uint32` | `toUint32()` | exactement 1 unité |
Les séquences complètes de code units sont accessibles via `codeUnits()`. Le type concret de vue retourné sera fixé avec les collections/slices.
@@ -176,9 +179,9 @@ Tous ces transcodages sont explicites et totaux.
Conceptuellement :
```text
Utf8String::tryFrom(Array<uint8>)
Utf16String::tryFrom(Array<uint16>)
Utf32String::tryFrom(Array<uint32>)
Utf8String::from(Array<uint8>) faults UnicodeEncodingFault
Utf16String::from(Array<uint16>) faults UnicodeEncodingFault
Utf32String::from(Array<uint32>) faults UnicodeEncodingFault
```
Le type exact accepté pourra inclure des slices/vues lors de leur définition.
@@ -283,5 +286,5 @@ les opérations mutantes sont interdites via `text`, mais un autre alias mutable
3. nom exact de l'API de décodage depuis un offset de code unit ;
4. API précise de concaténation et ses opérateurs ;
5. builders/buffers et leurs relations avec les strings valides ;
6. codes définitifs de `UnicodeEncodingError` ;
6. codes définitifs de `UnicodeEncodingFault` ;
7. localisation Core/SDK des opérations Unicode avancées : graphemes, normalisation, case folding, collation.

View File

@@ -22,6 +22,8 @@ Principe directeur :
> **boring but working** : une règle stable et prévisible vaut mieux qu'une syntaxe plus courte mais ambiguë.
Lorsqu'une forme légèrement plus longue supprime un implicite ou une ambiguïté réelle, Saselang privilégie l'explicite. La concision n'est pas un objectif supérieur à la lisibilité du contrat.
## 2.2 Mots-clés — V1 REQUIS — FIGÉ
Les mots-clés du langage sont en anglais.

View File

@@ -17,7 +17,7 @@ unions
tuples
generics
contrôle de flux
erreurs/exceptions
erreurs/exceptions/faults
opérateurs
unsafe
scope
@@ -42,6 +42,7 @@ Result<T,E>
Error
ResultError
Exception
Fault
Option<T>
Nullable<T>
Range<T>
@@ -50,10 +51,18 @@ RangeStep<T,Step>
RangeReverse<T>
RangeReverseStep<T,Step>
RangeProgression<T,Step>
PartialOrdering
Ordering
Comparable<T>
Comparator<T>
Op...
Iterable<T>
Iterator<T>
View<T>
Collection<T>
List<T>
Set<T>
Map<K,V>
Array<T>
StaticArray<T,N>
TypeInfo
@@ -71,7 +80,7 @@ Une capacité Core peut être conditionnée par un target lorsqu'elle ne peut ra
Le SDK fournit les fonctionnalités de bibliothèque qui ne justifient pas une sémantique spéciale du compilateur :
```text
collections
collections concrètes/spécialisées au-delà des contrats fondamentaux Core
encodages explicites
regex
filesystem

View File

@@ -49,6 +49,6 @@ Si tous les éléments permettent l'égalité pertinente, le tuple peut être co
Si tous les éléments sont comparables, l'ordre du tuple est lexicographique.
Si un composant comparé retourne `Ordering::Unordered`, le tuple est `Unordered`.
Si un composant comparé retourne `PartialOrdering::Unordered`, le résultat de comparaison du tuple est `PartialOrdering::Unordered`.
---

View File

@@ -41,10 +41,12 @@ type de retour
visibilité
fallibilité / Result
throws
contraintes génériques pertinentes
qualification const et contraintes génériques pertinentes
modificateurs contractuels pertinents
```
`faults` reste visible dans la déclaration et dans la documentation, mais sa nature optionnelle/non exhaustive signifie qu'il n'impose pas la même compatibilité d'override que `throws`.
Les futurs pré/post-contrats formels, s'ils existent, devront également participer à cette notion.
## 13.5 Conflits d'héritage multiple — V1 REQUIS — FIGÉ

View File

@@ -9,37 +9,42 @@ clsmethod méthode de classe
operator implémentation d'un contrat opérateur
```
## 15.2 Retours directs et `Result` — V1 REQUIS — FIGÉ
## 15.2 Retours directs, `Result`, `throws` et `faults` — V1 REQUIS — FIGÉ
L'ancienne règle « toute fonction/méthode retourne `Result` » est supprimée.
Le type de retour et le mécanisme d'échec sont des dimensions distinctes.
Règle V1 :
Une callable peut retourner directement `T` même si elle peut produire une `Exception` checked ou un `Fault` unchecked :
```text
opération infaillible
-> retourne directement T
func readConfig(String path) -> Config
throws IOException
opération pouvant produire une erreur récupérable
-> retourne Result<T>
ou Result<T,E>
method elementAt(uint64 index) -> T
faults IndexOutOfBoundsFault
```
Exemples infaillibles :
`Result<T,E>` est utilisé lorsque l'échec doit être transporté explicitement comme une valeur et inspecté par l'appelant :
```text
method length() -> uint64
method containsKey(K key) -> bool
Object::sameInstance(Object other) -> bool
func min(int32 a, int32 b) -> int32
func parseExternalInput(String input) -> Result<Value, ParseError>
```
Exemples faillibles :
Les combinaisons sont indépendantes :
```text
func readFile(String path) -> Result<String, IoError>
method parse(String input) -> Result<Value, ParseError>
T
T throws SomeException
T faults SomeFault
T throws SomeException faults SomeFault
Result<T,E>
Result<T,E> throws SomeException
Result<T,E> faults SomeFault
```
Saselang ne force donc plus une callable à retourner `Result` uniquement parce qu'elle peut échouer. À l'inverse, une API ne doit pas remplacer systématiquement un échec normal du domaine par un `Fault` si `Option` ou `Result` exprime mieux le contrat.
Le Core ne crée pas mécaniquement des paires `op()` / `tryOp()` ayant pour seule différence « valeur directe avec fault » versus « même opération dans Result ». Deux opérations distinctes doivent porter des sémantiques réellement distinctes.
## 15.3 Retour explicite — V1 REQUIS — FIGÉ
Pas de retour implicite de dernière expression.

View File

@@ -1,25 +1,33 @@
# 18. `Result`, erreurs et exceptions
# 18. `Result`, erreurs, exceptions et faults
## 18.1 Hiérarchie Core — V1 REQUIS — FIGÉ
La hiérarchie d'erreurs V1 est :
La hiérarchie V1 est :
```text
Object
└── Error
├── ResultError
── Exception
── Exception
└── Fault
```
Les trois classes racines sont abstraites et ne sont donc jamais instanciées directement.
Les quatre classes racines sont abstraites et ne sont jamais instanciées directement.
`Error` est la racine abstraite commune des erreurs Saselang. Elle ne détermine pas à elle seule le mécanisme de propagation.
`Error` est la racine commune. Elle ne choisit pas à elle seule le mécanisme de propagation.
`ResultError` représente exclusivement la famille des erreurs transportables par `Result<T,E>`.
```text
ResultError
échec transporté explicitement comme une valeur dans Result<T,E>
`Exception` représente exclusivement la famille des erreurs propagées par `throw` / `throws` / `try` / `catch` / `finally`.
Exception
échec checked propagé par throw / throws
`ResultError` et `Exception` sont des branches sœurs. Une classe utilisateur destinée à un `Result` hérite directement ou indirectement de `ResultError`. Une exception utilisateur hérite directement ou indirectement de `Exception`.
Fault
échec unchecked, capturable, pouvant être documenté par faults
```
Les trois branches sont sœurs. Aucune n'est implicitement convertible vers une autre.
Exemple :
@@ -29,9 +37,12 @@ public final class ParseError extends ResultError {
public final class FileNotFoundException extends Exception {
}
public final class IndexOutOfBoundsFault extends Fault {
}
```
L'interface `Throwable` ne fait pas partie de Saselang V1. Elle pourra être réintroduite ultérieurement si un besoin réel apparaît sans modifier la règle fondamentale : `Result` transporte des `ResultError`, tandis que `throw` transporte des `Exception`.
Il n'existe pas d'interface `Throwable` en V1.
## 18.2 Informations communes de `Error` — V1 REQUIS — FIGÉ EN PRINCIPE
@@ -51,7 +62,7 @@ message
cause
erreur causale purement informative
peut contenir un ResultError ou une Exception
peut contenir un ResultError, une Exception ou un Fault
n'est pas automatiquement propagée
i18nMessage
@@ -59,13 +70,11 @@ i18nMessage
ne contient pas un tableau de traductions
```
`cause` est de type `Option<Error>` et non `Nullable<Error>` : l'absence de cause est une absence sémantique. Une cause de type statique `Error` ne peut pas être passée directement à `throw`; il faut d'abord prouver par `is` qu'elle est une `Exception`, ou l'encapsuler explicitement dans une nouvelle exception.
`cause` n'accorde aucun droit de propagation. Une valeur statiquement typée `Error` ne peut être utilisée ni avec `throw` ni avec `fault` sans preuve préalable de sa branche exacte.
`message`, `cause` et `i18nMessage` sont initialisés lors de la construction et ne sont pas publiquement mutables.
`Error` ne porte pas de propriétés universelles supplémentaires telles que timestamp, thread id, process id, host, severity ou code plateforme. Ces informations appartiennent aux sous-classes, SDKs ou couches de logging/diagnostic lorsqu'elles sont pertinentes.
Le type exact `I18nMessage`, sa clé et la représentation de ses paramètres seront finalisés avec Core/SDK et le système de formatting/i18n.
`Error` ne porte pas de propriétés universelles supplémentaires telles que timestamp, thread id, process id, host, severity ou code plateforme. Ces informations appartiennent aux sous-classes, au SDK ou aux couches de logging/diagnostic lorsqu'elles sont pertinentes.
## 18.3 `ResultError` et code machine-readable — V1 REQUIS — FIGÉ EN PRINCIPE
@@ -78,26 +87,31 @@ code: ResultErrorCode
Le rôle de `ResultErrorCode` est distinct de `message` :
```text
code -> stable, machine-readable, non localisé
message -> humain, canonique / fallback
code -> stable, machine-readable, non localisé
message -> humain, canonique / fallback
i18nMessage -> localisation externe
```
La représentation exacte de `ResultErrorCode` sera finalisée avec Core/SDK. `Exception` n'a pas de code obligatoire.
La représentation exacte de `ResultErrorCode` sera finalisée avec Core/SDK.
## 18.4 `Exception` et stack trace — V1 REQUIS — FIGÉ EN PRINCIPE
Ni `Exception` ni `Fault` n'ont de code universel obligatoire ; leurs sous-types peuvent naturellement en définir lorsqu'il est utile.
`Exception` reste généraliste. Elle peut recevoir des informations de stack trace liées à sa propagation.
## 18.4 Diagnostic de `Exception` et `Fault` — V1 REQUIS — FIGÉ EN PRINCIPE
La création d'un objet `Exception` ne doit pas obligatoirement capturer immédiatement une stack trace. Le contexte de propagation peut être attaché ou capturé lors de :
`Exception` et `Fault` peuvent recevoir des informations de stack trace liées à leur propagation runtime.
La création de l'objet ne doit pas obligatoirement capturer immédiatement une stack trace. Le contexte peut être attaché ou capturé lors de :
```text
throw exception;
fault someFault;
```
La représentation exacte (`StackTrace`, `StackFrame`, capture lazy ou autre optimisation) relève de Core/runtime. Cette information reste diagnostique et n'intervient pas dans la sélection des `catch`.
ou lorsqu'un `Fault` est produit intrinsèquement par le runtime/Core.
`Error` et `ResultError` n'ont pas de stack trace automatique obligatoire.
La représentation exacte (`StackTrace`, `StackFrame`, capture lazy ou autre optimisation) relève du Core/runtime. Cette information reste diagnostique et n'intervient pas dans la sélection des `catch`.
`ResultError` n'a pas de stack trace automatique obligatoire.
## 18.5 `Result<T,E>` — V1 REQUIS — FIGÉ
@@ -127,6 +141,7 @@ Sont invalides :
```text
Result<Data,Error>
Result<Data,Exception>
Result<Data,Fault>
Result<Data,FileNotFoundException>
```
@@ -142,7 +157,7 @@ est équivalente à :
Result<T,ResultError>
```
`Result<Void,E>` et `Result<Void>` sont autorisés pour représenter un succès sans payload utile. `Option<Void>` reste interdit.
`Result<Void,E>` et `Result<Void>` sont autorisés. `Option<Void>` reste interdit.
Il n'existe aucune conversion implicite de `T` vers `Result<T,E>` ni de `E` vers `Result<T,E>` :
@@ -151,73 +166,72 @@ return Result::Ok(value);
return Result::Err(error);
```
sont explicites.
restent explicites.
`Result` suit les règles générales des enums algébriques. Son inspection et l'extraction sûre de ses payloads utilisent `match` avec bindings typés. V1 n'introduit ni `unwrap`, ni opérateur `?`, ni extraction implicite d'une variante.
`Result` suit les règles générales des enums algébriques. V1 n'introduit ni `unwrap`, ni opérateur `?`, ni extraction implicite d'une variante.
Des helpers Core futurs tels que :
## 18.6 Choix du mécanisme d'échec — V1 REQUIS — FIGÉ EN PRINCIPE
Les trois branches ne sont pas trois orthographes du même concept.
```text
result::expectOk(...)
result::expectErr(...)
ResultError / Result
l'échec est une donnée normale du résultat et l'appelant doit l'inspecter explicitement
Exception
l'échec appartient au contrat checked de la callable et doit être capturé ou propagé par throws
Fault
l'échec est unchecked ; l'appelant peut le capturer mais n'y est pas obligé
```
peuvent être étudiés si un besoin réel apparaît. Ils resteraient une API de `Result`, pas une syntaxe du langage, et leur comportement d'échec devrait être explicitement spécifié.
Une API directe n'est donc plus obligée de retourner `Result` uniquement parce qu'elle peut échouer.
## 18.6 Séparation `ResultError` / `Exception` — V1 REQUIS — FIGÉ
Aucune conversion automatique n'existe entre les deux branches :
Exemple :
```text
ResultError -> Exception
Exception -> ResultError
method elementAt(uint64 index) -> T
faults IndexOutOfBoundsFault
```
La traduction d'un mécanisme vers l'autre se fait par encapsulation explicite dans une nouvelle erreur de la branche cible, éventuellement en conservant l'erreur source dans `cause`.
peut retourner directement `T`.
Exemples conceptuels :
Inversement, lorsqu'une absence ou un échec constitue une donnée normale du domaine, `Option` ou `Result` reste préférable :
```text
throw ParseException(..., Option::Some(parseError));
map::get(key) -> Option<V>
parseExternalInput(...) -> Result<Value, ParseError>
```
ou :
Le Core ne doit pas créer mécaniquement un couple `op()` / `tryOp()` uniquement pour offrir d'un côté une valeur directe et de l'autre un `Result`. Deux opérations coexistantes doivent avoir des sémantiques réellement distinctes.
```text
catch (FileNotFoundException error) {
return Result::Err(FileResultError(..., Option::Some(error)));
}
```
Un simple cast ne transforme pas un `ResultError` en `Exception` ni l'inverse.
Aucune conversion automatique n'existe entre `ResultError`, `Exception` et `Fault`. Une traduction entre branches se fait par encapsulation explicite, éventuellement via `cause`.
## 18.7 `throws` — V1 REQUIS — FIGÉ
`throws` est interdit sur une `func` / `method` / `clsmethod` à retour direct. Il n'est permis que si le retour est `Result<T>` ou `Result<T,E>`.
`throws` est indépendant du type de retour.
Sont valides :
```text
T + throws -> interdit
Result<T,E> -> valide sans throws
Result<T,E> + throws -> valide
T
T throws SomeException
Result<T,E>
Result<T,E> throws SomeException
Void throws SomeException
```
Tout type déclaré dans `throws` doit être `Exception` ou un descendant de `Exception`.
Une callable doit déclarer toute famille d'exception susceptible d'atteindre sa frontière sans être gérée localement. Cette obligation est transitive : une exception déclarée par une callable appelée doit être soit capturée localement, soit couverte par le `throws` de l'appelant.
Un type déclaré dans `throws` couvre ses descendants. Une clause :
Un type déclaré dans `throws` couvre ses descendants. Une même clause ne doit pas contenir de types redondants lorsqu'un type déclaré couvre déjà entièrement un autre type de la liste.
```text
throws IOException
```
peut donc couvrir `FileNotFoundException` si cette dernière hérite de `IOException`.
Une même clause `throws` ne doit pas contenir de types redondants lorsqu'un type déclaré couvre déjà entièrement un autre type de la liste.
`Fault`, `Error` et `ResultError` sont interdits dans `throws`.
## 18.8 `throws` dans les contrats, interfaces et overrides — V1 REQUIS — FIGÉ
`throws` ne fait pas partie de la signature d'overload. Il fait partie du contrat de la callable.
`throws` ne fait pas partie de la signature d'overload. Il fait partie du contrat checked de la callable.
Un override ou une implémentation peut :
@@ -229,21 +243,20 @@ gérer localement tout ou partie des exceptions du contrat parent
Il ne peut jamais ajouter une exception non couverte par le contrat parent ni élargir une famille déclarée.
La même règle s'applique aux contrats d'interface. Lorsque plusieurs interfaces portent la même signature, l'implémentation doit satisfaire simultanément tous leurs contrats `throws`. Une implémentation sans exception sortante est toujours compatible avec un contrat qui en autorise.
La même règle s'applique aux contrats d'interface. Une implémentation sans exception sortante est toujours compatible avec un contrat qui en autorise.
## 18.9 `throw` — V1 REQUIS — FIGÉ
`throw` ne peut lancer qu'une valeur dont le type statique est `Exception` ou un descendant de `Exception`.
```text
throw FileNotFoundException(...); // valide
throw ParseError(...); // erreur
throw Error(...); // erreur
throw FileNotFoundException(...); // OK
throw ParseError(...); // ERROR
throw IndexOutOfBoundsFault(...); // ERROR
throw Error(...); // ERROR
```
Les racines abstraites `Error`, `ResultError` et `Exception` ne sont jamais instanciables directement.
La forme de repropagation reste explicite :
La repropagation reste explicite :
```text
catch (IOException error) {
@@ -253,7 +266,69 @@ catch (IOException error) {
Il n'existe pas de forme spéciale `throw;` en V1.
## 18.10 `try` / `catch` / `finally` — V1 REQUIS — FIGÉ
## 18.10 `fault` et `faults` — V1 REQUIS — FIGÉ EN PRINCIPE
`fault` produit explicitement un `Fault` :
```text
fault InvalidStateFault(...);
```
Le type statique de la valeur doit être `Fault` ou un descendant de `Fault`.
```text
fault InvalidStateFault(...); // OK
fault FileNotFoundException(...); // ERROR
fault ParseError(...); // ERROR
```
Une callable peut documenter des faults significatifs directement dans sa signature :
```text
method elementAt(uint64 index) -> T
faults IndexOutOfBoundsFault
```
Plusieurs familles peuvent être listées explicitement :
```text
faults FirstFault, SecondFault
```
Chaque type listé doit être `Fault` ou un descendant de `Fault`; une liste ne doit pas contenir de famille redondante déjà couverte par un parent déclaré.
La clause `faults` est **optionnelle et non exhaustive**.
Elle signifie que les faults listés font explicitement partie du contrat/documentation utile de l'API. Elle ne signifie pas qu'aucun autre fault runtime ne peut survenir.
Contrairement à `throws` :
```text
aucun catch n'est obligatoire
aucune propagation de la clause faults n'est obligatoire
un appelant n'a pas à recopier les faults d'une callable appelée
```
Exemple valide :
```text
func outer() -> Void {
inner(); // inner peut déclarer faults SomeFault
return Void;
}
```
`outer` peut, mais n'est pas obligé de déclarer à son tour :
```text
faults SomeFault
```
`faults` ne fait pas partie de la signature d'overload et n'impose pas les restrictions de covariance contractuelle de `throws`. Un override peut documenter un ensemble différent de faults, puisque l'absence d'un fault dans la clause n'est jamais une garantie statique d'impossibilité.
Une API publique qui produit explicitement un fault important devrait normalement le documenter avec `faults`; un outil/linter peut signaler les omissions sans en faire une erreur de compilation du langage.
## 18.11 `try` / `catch` / `finally` — V1 REQUIS — FIGÉ
Un `try` doit être suivi d'au moins un `catch`.
@@ -272,7 +347,7 @@ try {
...
} catch (SpecificException error) {
...
} catch (ParentException error) {
} catch (SomeFault faultValue) {
...
} finally {
...
@@ -281,75 +356,95 @@ try {
`finally` est facultatif et ne peut apparaître qu'après au moins un `catch`.
Chaque `catch` contient exactement un type explicite d'`Exception` ou descendant. Il n'existe pas de multi-catch `A | B` en V1 : des blocs `catch` distincts sont utilisés.
Les `catch` sont évalués dans l'ordre source. Le chevauchement par héritage est normal et utile : les cas spécifiques peuvent précéder un fallback de famille générale.
Un `catch` entièrement couvert par un `catch` précédent est une erreur de compilation, pas un simple warning.
Exemple valide :
Le type explicite d'un `catch` doit être :
```text
catch (FileNotFoundException error) {
...
} catch (IOException error) {
...
}
Exception ou un descendant de Exception
Fault ou un descendant de Fault
```
Exemple invalide si `FileNotFoundException extends IOException` :
Sont donc interdits :
```text
catch (IOException error) {
...
} catch (FileNotFoundException error) {
...
}
catch (Error error)
catch (ResultError error)
```
Un ensemble de `catch` n'a pas à être exhaustif. Toute `Exception` non capturée continue à se propager et doit être couverte par le contrat `throws` de la callable englobante.
Il n'existe pas de multi-catch `A | B` en V1.
Les variables de `catch` suivent les règles normales de scope et de non-shadowing. Des `catch` distincts peuvent réutiliser le même nom parce que leurs scopes sont disjoints.
Les `catch` sont évalués dans l'ordre source. Un `catch` entièrement couvert par un précédent dans la même branche d'héritage est une erreur de compilation.
## 18.11 `finally` non-escaping — V1 REQUIS — FIGÉ
Une `Exception` non capturée continue à se propager et doit être couverte par `throws`.
`finally` exécute un bloc commun avant de quitter la construction `try/catch`, qu'il y ait :
Un `Fault` non capturé continue à se propager de façon unchecked ; aucune clause `faults` n'est exigée sur les callables traversées.
Les variables de `catch` suivent les règles normales de scope et de non-shadowing.
## 18.12 `finally` non-escaping — V1 REQUIS — FIGÉ EN PRINCIPE
`finally` exécute un bloc commun avant de quitter la construction `try/catch`, notamment sur :
```text
fin normale du try
fin normale d'un catch
return traversant la construction
throw propagé
Fault propagé
break / continue traversant la construction
Exception non capturée par les catch
```
`finally` ne doit jamais remplacer une sortie déjà en cours. Les sorties structurées suivantes y sont interdites :
`finally` ne doit pas remplacer volontairement une sortie déjà en cours. Les sorties structurées explicites suivantes y sont interdites :
```text
return
throw
fault
break
continue
emit
```
Aucune `Exception` non capturée ne peut sortir indirectement d'un `finally`. Toute callable appelée depuis `finally` dont le contrat comporte `throws` doit avoir ses exceptions entièrement gérées à l'intérieur du `finally`.
Toute `Exception` produite indirectement depuis `finally` doit être gérée localement selon les règles checked de `throws`.
Une faute runtime non récupérable reste distincte de ce contrat d'exception.
Un `Fault` dynamique peut néanmoins survenir dans le code exécuté par `finally`, puisqu'il est unchecked. L'interaction exacte entre un tel fault, l'unwind, les destructeurs et une sortie déjà en cours reste à fermer avec le modèle mémoire/runtime.
## 18.12 Faute runtime / panic — V1 REQUIS — À FINALISER
## 18.13 Sémantique runtime des `Fault` — V1 REQUIS — FIGÉ EN PRINCIPE
Les violations de contrat du langage telles que :
Les `Fault` couvrent notamment les échecs unchecked et violations runtime tels que :
```text
index hors limites
division entière par zéro
index dynamique hors limites
division entière dynamique par zéro
overflow checked
représentation mémoire invalide
borne dynamique invalide lors d'une construction directe lorsque la règle du type le définit
iterator invalidé
clé absente lors d'un accès strict map[key]
doublon lors d'un insert strict
conversion explicite directe dont les préconditions runtime ne sont pas satisfaites
représentation/encodage invalide lors d'une construction directe validée
```
ne sont pas nécessairement des `ResultError` ou des `Exception` récupérables.
Lorsqu'une violation d'une précondition intrinsèque est démontrable statiquement, le compilateur doit la diagnostiquer plutôt que générer un programme condamné à fauter.
Le modèle exact de faute runtime/fatal error/panic et son interaction avec cleanup/destruction doit être défini avant la finalisation V1.
Exemple :
```text
StaticArray<int32,3> values = [1, 2, 3];
int32 value = values[5]; // ERROR compilation
```
Cette règle ne rend évidemment pas illégal un statement `fault` explicite : `fault SomeFault(...)` est un mécanisme volontaire du programme et peut être utilisé pour implémenter une API.
Lorsqu'un `Fault` ne peut être déterminé qu'au runtime :
```text
capturé par catch
-> le catch correspondant s'exécute
non capturé
-> le fault remonte sans contrat checked
-> à la frontière de l'unité d'exécution, il provoque un échec runtime diagnostiqué
```
La définition exacte de « l'unité d'exécution » (processus, thread, task, isolate éventuel) et l'ordre final cleanup/destruction lors d'un fault seront fermés avec les chapitres mémoire et concurrence.
---

View File

@@ -27,7 +27,7 @@ Un `if` qui contient `emit` devient un `if` producteur de valeur. Dans ce cas :
- le résultat du `if` doit obligatoirement être affecté à une destination ;
- un bloc `else` final est obligatoire ;
- chaque voie de terminaison normale de chaque branche doit produire explicitement une valeur via `emit` ;
- une voie que le compilateur prouve comme terminant définitivement le contrôle (`return`, `throw`, runtime fault certain ou non-terminaison prouvée) n'a pas à exécuter `emit` ;
- une voie que le compilateur prouve comme terminant définitivement le contrôle (`return`, `throw`, `fault` explicite ou non-terminaison prouvée) n'a pas à exécuter `emit` ;
- les valeurs émises doivent être compatibles avec le type de la destination ;
- aucune valeur de secours n'est implicite, y compris pour `Option<T>`.

View File

@@ -6,13 +6,15 @@ Les opérateurs utilisateur ne peuvent être fournis que via un ensemble fermé
L'utilisateur ne peut pas inventer de nouveaux symboles opérateurs.
Les `operator` contracts :
Les contrats `operator` :
- retournent directement leur valeur ;
- ne retournent jamais `Result` ;
- ne déclarent jamais `throws`.
- ne déclarent jamais `throws` ;
- peuvent produire des `Fault` unchecked lorsque le contrat de l'opération le prévoit ;
- peuvent documenter ces faults par une clause `faults`.
Une faute de contrat du langage peut néanmoins déclencher une faute runtime déterministe.
Une opération dont la précondition est statiquement prouvée fausse est rejetée à la compilation lorsque la règle du langage permet cette preuve. Une violation seulement dynamique produit le `Fault` correspondant.
## 20.2 Interfaces arithmétiques — V1 REQUIS — FIGÉ
@@ -124,29 +126,38 @@ Les classes ne reçoivent aucune comparaison champ-à-champ automatique : elles
## 20.6 Comparaison — V1 REQUIS — FIGÉ EN PRINCIPE
Core :
Core distingue l'ordre partiel de l'ordre total :
```text
public enum Ordering {
public enum PartialOrdering {
Less,
Equal,
Greater,
Unordered
}
public enum Ordering {
Less,
Equal,
Greater
}
```
Interfaces :
Interfaces opérateur :
```text
OpPartialCompare<Lhs,Rhs>
-> PartialOrdering
OpCompare<T>
-> Ordering
```
`OpCompare<T>` renforce `OpPartialCompare<T,T>` et garantit un ordre total, donc pas de `Ordering::Unordered`.
`OpCompare<T>` garantit un ordre total. Les floats utilisent l'ordre partiel pour leurs opérateurs généraux en raison de `NaN`; les entiers peuvent utiliser l'ordre total.
Les floats utilisent l'ordre partiel ; les entiers peuvent utiliser l'ordre total.
`Ordering::Equal` signifie équivalence dans la relation d'ordre considérée. Il ne doit pas être confondu automatiquement avec l'égalité générale `==`.
Le lien exact entre égalité et comparaison pour éviter deux contrats contradictoires sur une même paire doit être verrouillé dans la spécification finale des interfaces `Op`.
Les contrats applicatifs `Comparable<T>` et `Comparator<T>` des collections ordonnées utilisent `Ordering` et sont définis au chapitre 22.
## 20.7 Comparaisons hétérogènes — V1 REQUIS — FIGÉ EN PRINCIPE
@@ -187,21 +198,25 @@ D'autres index numériques pourront être supportés ultérieurement sans modifi
Un type utilisateur peut utiliser n'importe quel type d'index pertinent.
## 20.10 Map — V1 REQUIS — DIRECTION FIGÉE
## 20.10 Map — V1 REQUIS — FIGÉ EN PRINCIPE
Direction recommandée :
Le contrat des maps est défini au chapitre 22.
L'indexation est stricte :
```text
Map<K,V>
OpIndex<K,Option<V>>
OpIndexMut<K,V>
map[key] -> V
```
Lecture : absent -> `None` ; présent -> `Some(value)`.
La clé doit exister ; une absence dynamique produit `KeyNotFoundFault`.
Écriture : insertion si absent, remplacement si présent.
L'accès conditionnel est explicite et distinct :
Une méthode `containsKey` peut compléter l'API sans être obligatoire avant toute lecture.
```text
map::get(key) -> Option<V>
```
`OpIndexMut<K,V>` remplace uniquement la valeur d'une clé existante ; l'affectation indexée n'insère jamais implicitement une nouvelle clé.
## 20.11 Affectation — V1 REQUIS — FIGÉ

View File

@@ -95,26 +95,37 @@ Aucun `Utf8CodeUnit` / `Utf16CodeUnit` / `Utf32CodeUnit` distinct n'est introdui
Aucun transcodage implicite n'existe.
Les conversions totales utilisent `to...`.
Les constructions ou réductions pouvant échouer utilisent `tryFrom...` / `tryTo...`.
Les conversions directes retournent la destination attendue. Lorsqu'une validation runtime peut échouer, la callable peut déclarer `faults UnicodeEncodingFault` au lieu de forcer un `ResultError` ou une variante `try...` parallèle.
Exemples :
```text
char::toUtf8Char()
Utf8Char::toChar()
Utf8Char::toUtf16Char()
char::toUtf8Char() -> Utf8Char
Utf8Char::toChar() -> char
Utf8Char::toUtf16Char() -> Utf16Char
Utf8Char::tryFrom(uint8)
Utf16Char::tryFrom(uint16)
Utf32Char::tryFrom(uint32)
Utf8Char::from(uint8) -> Utf8Char
faults UnicodeEncodingFault
Utf8Char::tryToUint8()
Utf16Char::tryToUint16()
Utf32Char::toUint32()
Utf16Char::from(uint16) -> Utf16Char
faults UnicodeEncodingFault
Utf32Char::from(uint32) -> Utf32Char
faults UnicodeEncodingFault
Utf8Char::toUint8() -> uint8
faults UnicodeEncodingFault
Utf16Char::toUint16() -> uint16
faults UnicodeEncodingFault
Utf32Char::toUint32() -> uint32
```
`UnicodeEncodingFault extends Fault` est le nom de travail du fault Core associé aux données encodées invalides ou aux réductions impossibles.
Le Core n'expose pas simultanément `from(...)` et `tryFrom(...)` lorsque les deux opérations auraient exactement la même sémantique et ne différeraient que par le canal d'échec.
La matrice normative détaillée est définie dans `annexes/B-unicode-encoding-conversions.md`.
## 21.5 Aucun mélange implicite de types — V1 REQUIS — FIGÉ

View File

@@ -135,9 +135,9 @@ Les indices d'une sous-slice sont relatifs à la slice source.
Les interfaces décrivent des capacités réellement garanties. Les classes/structs génériques fournissent le stockage et l'implémentation.
Saselang ne retient pas le modèle d'opérations optionnelles qui existent dans une interface mais échouent ensuite au runtime comme « unsupported ».
Saselang ne retient pas le modèle d'opérations optionnelles présentes dans une interface mais susceptibles d'échouer ensuite comme « unsupported ».
Hiérarchie principale retenue :
Hiérarchie principale :
```text
Iterable<T>
@@ -151,21 +151,84 @@ SettableList<T>
ResizableList<T>
```
`Set<T>` et `Map<K,V>` sont des branches distinctes à préciser.
`Set<T>` et `Map<K,V>` forment des branches sémantiques distinctes.
### 22.4.1 `Iterable<T>` / `Iterator<T>`
### 22.4.1 `Iterable<T>` et `Iterator<T>`
Interfaces Core reconnues par `foreach`.
`foreach` dépend uniquement de `Iterable<T>`.
Elles ne portent pas le préfixe `Op`, car `foreach` est une construction du langage et non un opérateur symbolique.
```text
interface Iterable<T> {
const method iterator() -> Iterator<T>;
}
```
Indexabilité et itérabilité sont indépendantes.
Créer un iterator ne constitue pas une mutation sémantique de la source.
### 22.4.2 `Collection<T>`
`Iterator<T>` représente une itération particulière et possède un état de progression mutable :
```text
interface Iterator<T> {
method next() -> Option<T>;
}
```
`Some(value)` fournit l'élément suivant ; `None` marque la fin normale de l'itération.
Saselang n'impose pas le couple `hasNext()` / `next()`. `Option<T>` rend l'état de fin explicite dans une seule opération.
`Iterator<T>` n'étend pas `Iterable<T>` par défaut. Une source capable de créer des itérations et une itération déjà en cours sont deux capacités différentes, même si certains types concrets peuvent éventuellement fournir les deux.
Pour les collections ordinaires non concurrentes, une mutation structurelle invalide par défaut les iterators actifs lorsque le type concret ne garantit pas explicitement une autre politique.
```text
insert / remove / clear / append / changement structurel
-> peut invalider l'iterator
utilisation ultérieure d'un iterator invalidé
-> IteratorInvalidatedFault
```
Le simple remplacement d'une valeur existante n'est pas automatiquement une mutation structurelle. Le type concret documente sa politique exacte.
Les collections concurrentes ou spécialisées peuvent fournir une autre politique (`snapshot`, stabilité, weak consistency, etc.) ; elle doit être explicite.
### 22.4.2 `View<T>`
`View<T>` représente une vue légère sur une source existante :
```text
interface View<T> extends Iterable<T> {
const method count() -> uint64;
const method isEmpty() -> bool;
}
```
`View<T>` n'étend pas `Collection<T>`.
Le contrat général ne contient pas `contains()`. Une classe ou une interface plus spécialisée peut l'ajouter si elle en a réellement besoin.
Une `View<T>` :
```text
n'impose aucune copie des éléments
n'impose aucun stockage indépendant
n'impose aucune contiguïté
ne possède pas nécessairement les données qu'elle expose
ne peut jamais augmenter les permissions const de sa source
```
Par défaut, une vue est **vivante**, pas un snapshot : une nouvelle itération peut observer les modifications ultérieures de la source selon le contrat du type concret.
Le runtime/compilateur garantit que le stockage ou l'état source nécessaire reste valide aussi longtemps que la vue l'exige, sans syntaxe de lifetime utilisateur.
Le comportement d'un iterator déjà créé avant une modification reste régi par la politique d'invalidation/stabilité du type concret.
### 22.4.3 `Collection<T>`
`Collection<T>` étend `Iterable<T>` et représente une collection finie d'éléments.
Contrat minimal retenu :
Contrat minimal :
```text
count() -> uint64
@@ -175,7 +238,7 @@ contains(const T value) -> bool
`count()` exprime le nombre d'éléments au sens général de collection.
### 22.4.3 `List<T>`
### 22.4.4 `List<T>`
`List<T>` étend `Collection<T>` et `OpIndex<uint64,T>`.
@@ -193,33 +256,39 @@ Pour une `List<T>` :
count() == length()
```
Les deux noms sont néanmoins conservés parce qu'ils expriment des concepts différents : cardinalité générale de collection et longueur d'une séquence indexable.
Les deux noms restent distincts parce qu'ils expriment la cardinalité générale d'une collection et la longueur d'une séquence indexable.
`List<T>` ne garantit ni remplacement d'un élément, ni redimensionnement, ni complexité algorithmique particulière de l'accès indexé.
`List<T>` ne garantit ni remplacement, ni redimensionnement, ni complexité algorithmique particulière de l'accès indexé.
### 22.4.4 `SettableList<T>`
### 22.4.5 `SettableList<T>`
`SettableList<T>` étend `List<T>` et `OpIndexMut<uint64,T>`.
Elle garantit le remplacement d'un élément existant sans modification de la longueur.
Elle garantit le remplacement d'un élément existant sans modification de longueur :
```text
list[index] = value;
```
ne signifie jamais `append` lorsque `index == length()`.
`index` doit désigner une case existante ; l'affectation ne signifie jamais `append`.
### 22.4.5 `ResizableList<T>`
### 22.4.6 `ResizableList<T>`
`ResizableList<T>` étend `SettableList<T>`.
`ResizableList<T>` étend `SettableList<T>` et garantit des opérations structurelles capables de modifier la longueur.
Elle garantit des opérations structurelles capables de modifier la longueur, par exemple ajout, insertion et suppression.
Les signatures exactes seront figées avec `Vector<T>`.
Les signatures exactes seront figées lors de la définition du type concret redimensionnable.
Un `resize(newLength)` sans information d'initialisation n'est pas retenu implicitement : agrandir une collection doit définir comment les nouveaux éléments sont construits.
Un `resize(newLength)` sans information d'initialisation n'est pas retenu implicitement : agrandir une collection doit toujours définir comment les nouveaux éléments sont construits.
Lorsqu'il existe, `clear()` suit la convention :
### 22.4.6 Capacité du type et permission `const`
```text
clear() -> uint64
```
et retourne le nombre d'éléments effectivement supprimés.
### 22.4.7 Capacité du type et permission `const`
La capacité intrinsèque du type et la permission d'un accès sont deux dimensions distinctes.
@@ -230,9 +299,9 @@ const SettableList<User> readonly = users;
Le type sait remplacer des éléments, mais l'accès `readonly` ne peut pas utiliser cette capacité.
La propagation générale de `const` reste applicable aux éléments obtenus via cet accès.
La même règle s'applique à `Map`, `Set`, `View` et aux éléments obtenus à travers ces accès : une projection ne peut jamais augmenter les droits reçus de sa source.
### 22.4.7 Classification initiale
### 22.4.8 Classification initiale des séquences
```text
StaticArray<T,N>
@@ -258,9 +327,271 @@ Vector<T>
`Vector<T>` reste à définir précisément.
Un type persistant/immutable par nature n'a aucune obligation d'implémenter `List<T>`. Par exemple, un futur `PersistentList<T>` peut implémenter uniquement `Collection<T>` et fournir ses propres opérations si cela correspond mieux à sa sémantique.
Un type persistant/immutable par nature n'a aucune obligation d'implémenter `List<T>` s'il ne garantit pas sa sémantique.
Une interface Saselang n'est jamais implémentée uniquement parce qu'un type ressemble conceptuellement à une autre famille de types.
### 22.4.9 `Set<T>` et `ResizableSet<T>`
`Set<T>` étend `Collection<T>`.
Il garantit :
```text
unicité des éléments
aucun index ordinal
aucun ordre d'itération général garanti
```
La capacité structurelle est séparée :
```text
interface ResizableSet<T> extends Set<T> {
method add(T value) -> bool;
method remove(const T value) -> bool;
method clear() -> uint64;
}
```
Sémantique :
```text
add(value)
true -> élément ajouté
false -> élément déjà présent, set inchangé
remove(value)
true -> élément supprimé
false -> élément absent
clear()
-> nombre d'éléments effectivement supprimés
```
Il n'existe pas de niveau `SettableSet<T>` : remplacer un élément d'un set équivaut conceptuellement à une modification structurelle de son ensemble de valeurs.
### 22.4.10 `Map<K,V>`, `SettableMap<K,V>` et `ResizableMap<K,V>`
`Map<K,V>` n'étend pas `Collection<T>` et n'implémente pas directement `Iterable<...>`. Une map possède trois projections naturelles différentes : clés, valeurs et entrées ; aucune ne doit être choisie implicitement comme itération « par défaut ».
Contrat de lecture :
```text
interface Map<K,V> extends OpIndex<K,V> {
const method count() -> uint64;
const method isEmpty() -> bool;
const method containsKey(const K key) -> bool;
const method get(const K key) -> Option<V>;
const method keys() -> View<K>;
const method values() -> View<V>;
const method entries() -> View<MapEntry<K,V>>;
}
```
Deux intentions sont séparées :
```text
map[key] -> V
accès strict
la clé doit exister
absence dynamique -> KeyNotFoundFault
map::get(key) -> Option<V>
accès conditionnel
absence normale -> None
```
`SettableMap<K,V>` étend `Map<K,V>` et `OpIndexMut<K,V>`.
```text
map[key] = value;
```
remplace uniquement la valeur d'une clé existante. Cette syntaxe n'insère jamais implicitement une nouvelle clé. Une clé absente produit `KeyNotFoundFault`.
`ResizableMap<K,V>` étend `SettableMap<K,V>` et ajoute les changements structurels :
```text
insert(K key, V value) -> Void
faults DuplicateKeyFault
remove(const K key) -> Void
faults KeyNotFoundFault
clear() -> uint64
```
`insert` affirme que la clé est nouvelle ; `remove` affirme qu'elle existe. Leurs violations dynamiques sont des `Fault` unchecked et capturables.
Le Core ne fournit pas mécaniquement `tryInsert` / `tryRemove` ayant pour seule fonction de dupliquer ces opérations dans `Result` ou `bool`. Une variante conditionnelle ne sera ajoutée que si elle porte une sémantique réellement utile distincte.
Il n'existe pas de `put()` implicite « insert ou replace » tant qu'un besoin concret ne justifie pas cette troisième intention.
### 22.4.11 `MapEntry<K,V>`
`MapEntry<K,V>` représente une paire clé/valeur observée lors d'une projection `entries()`.
Conceptuellement :
```text
struct MapEntry<K,V> {
const method key() -> K;
const method value() -> V;
}
```
`MapEntry` n'est pas un proxy mutable vers un bucket interne de la map et n'expose pas de `setValue()` implicite.
La mutation d'une map reste explicite via :
```text
map[key] = value;
```
La sémantique de copie/référence de `K` et `V` suit les règles normales de leurs types.
### 22.4.12 Ordre : `Ordering`, `Comparable<T>` et `Comparator<T>`
L'ordre total applicatif utilise :
```text
enum Ordering {
Less,
Equal,
Greater
}
```
`Comparable<T>` exprime l'ordre naturel ou principal du type dans son domaine :
```text
interface Comparable<T> {
const method compareTo(const T other) -> Ordering;
}
```
Un type peut tout à fait implémenter `Comparable<T>` tout en supportant plusieurs ordres alternatifs via des comparators. Par exemple, un `User` d'un jeu peut avoir un classement principal naturel et rester comparable autrement par nom, niveau ou date.
`Comparator<T>` exprime un ordre externe/alternatif :
```text
interface Comparator<T> {
const method compare(const T left, const T right) -> Ordering;
}
```
Règle de sélection :
```text
Comparator explicitement fourni
-> utilisé exclusivement
aucun Comparator fourni
-> Comparable<T> requis
```
Aucun mélange/fallback entre les deux n'est effectué pendant une même opération ou dans une même collection ordonnée.
`Ordering::Equal` signifie équivalence selon cette relation d'ordre. Il n'implique pas nécessairement `left == right`.
Les implémentations de `Comparable` et `Comparator` doivent respecter cohérence, symétrie d'ordre et transitivité. Le compilateur n'est pas tenu de prouver ces propriétés générales.
### 22.4.13 `SortedSet<T>` et `SortedMap<K,V>`
`SortedSet<T>` étend `Set<T>` et garantit un ordre total stable selon le comparator actif :
```text
interface SortedSet<T> extends Set<T> {
const method comparator() -> Option<Comparator<T>>;
const method first() -> Option<T>;
const method last() -> Option<T>;
}
```
`None` pour `comparator()` signifie que l'ordre naturel `Comparable<T>` est utilisé. `Some(comparator)` expose l'ordre externe choisi pour cette instance.
`SortedMap<K,V>` étend `Map<K,V>` et ordonne les entrées par clé :
```text
interface SortedMap<K,V> extends Map<K,V> {
const method comparator() -> Option<Comparator<K>>;
const method firstKey() -> Option<K>;
const method lastKey() -> Option<K>;
}
```
Pour une `SortedMap`, les vues `keys()`, `values()` et `entries()` parcourent les données dans l'ordre des clés.
Les opérations de bornes/ranges (`floor`, `ceiling`, `lower`, `higher` ou noms définitifs) seront fermées séparément afin de ne pas introduire de noms ambigus par simple imitation d'une autre plateforme.
### 22.4.14 `TreeSet<T>` et `TreeMap<K,V>`
Les types standard ordonnés généraux sont nommés :
```text
TreeSet<T>
TreeMap<K,V>
```
Le nom n'impose pas une structure arborescente précise au niveau ABI/implémentation tant que le contrat observable reste respecté.
Un futur `BTreeMap<K,V>` peut exister comme implémentation explicitement fondée sur un B-tree ; il ne remplace pas le nom général `TreeMap`.
Comme Saselang n'autorise qu'un `construct` par classe, les deux modes de création passent par des factories de classe distinctes :
```text
TreeSet<T>::natural()
requiert T implements Comparable<T>
TreeSet<T>::withComparator(Comparator<T> comparator)
n'exige pas Comparable<T>
TreeMap<K,V>::natural()
requiert K implements Comparable<K>
TreeMap<K,V>::withComparator(Comparator<K> comparator)
n'exige pas Comparable<K>
```
Les contraintes appartiennent aux factories concernées et non nécessairement au type générique entier.
### 22.4.15 Contraintes des implémentations concrètes
Les interfaces abstraites `Set<T>` et `Map<K,V>` n'imposent pas une stratégie de stockage particulière.
Ainsi :
```text
HashSet<T> / HashMap<K,V>
peuvent exiger des capacités de hash/égalité
TreeSet<T> / TreeMap<K,V>
utilisent Comparable ou Comparator
```
`Hashable`, l'égalité et leurs contrats exacts seront fermés dans le bloc dédié. Ils ne sont pas imposés à `Set<T>` ou `Map<K,V>` eux-mêmes.
### 22.4.16 Collections concurrentes
Les garanties concurrentes sont orthogonales aux capacités structurelles et relèvent du SDK.
Une future :
```text
ConcurrentMap<K,V>
```
exprime des garanties de concurrence/atomicité et ne remplace pas `ResizableMap<K,V>`.
Un type concret peut par exemple implémenter les deux :
```text
ConcurrentHashMap<K,V>
implements ResizableMap<K,V>, ConcurrentMap<K,V>
```
Le SDK n'introduit pas une variante `ConcurrentX` pour chaque type uniquement par symétrie. Les interfaces concurrentes ne sont ajoutées que lorsqu'un contrat atomique/concurrent concret existe.
Une opération composée n'est pas atomique simplement parce que chaque appel individuel est thread-safe. Les futures opérations atomiques (`putIfAbsent`, comparaison/remplacement, etc.) seront spécifiées avec le modèle de concurrence.
## 22.5 `Range<T>` — V1 REQUIS — FIGÉ EN PRINCIPE
@@ -308,7 +639,7 @@ valeur finie autorisée
Les bornes sont évaluées de gauche à droite, exactement une fois chacune, avant la construction du range.
Une borne statiquement prouvée invalide provoque une erreur de compilation. Une borne calculée dynamiquement mais invalide selon le contrat de `Range<T>` provoque un runtime fault lors de la construction directe. Une API Core explicite retournant `Result` pourra être fournie lorsqu'une validation récupérable est souhaitée.
Une borne statiquement prouvée invalide provoque une erreur de compilation. Une borne calculée dynamiquement mais invalide selon le contrat de `Range<T>` provoque un `Fault` runtime lors de la construction directe. Le nom concret du fault sera fixé avec l'API Core ; aucune variante `try... -> Result` parallèle n'est créée automatiquement pour la même validation.
`lower > upper` ne constitue pas une erreur : le résultat est un range vide.
@@ -392,7 +723,7 @@ RangeStep<Date,Duration>
et de refuser des couples qui introduiraient une perte ou n'auraient pas de sens. Par exemple, un range `float16` peut recevoir seulement les types de pas explicitement supportés sans imposer qu'un `float32` plus large soit accepté.
Le pas exprime une magnitude de progression, pas une direction. Pour les types numériques Core, il doit être strictement supérieur à zéro. Un pas statiquement nul ou négatif est une erreur de compilation ; une valeur dynamique invalide provoque un runtime fault lors de la construction directe de la progression. Une API explicite en `Result` pourra exister pour une validation récupérable.
Le pas exprime une magnitude de progression, pas une direction. Pour les types numériques Core, il doit être strictement supérieur à zéro. Un pas statiquement nul ou négatif est une erreur de compilation ; une valeur dynamique invalide provoque un `Fault` runtime lors de la construction directe de la progression. Aucune variante `try... -> Result` n'est ajoutée uniquement pour dupliquer ce contrôle.
Pour les types utilisateur, la validité du pas est définie par le contrat Range correspondant et n'est pas réduite artificiellement à une comparaison numérique avec zéro.

View File

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

View File

@@ -13,11 +13,13 @@ threads natifs
structured concurrency éventuelle
cancellation
synchronisation
interaction avec Result/throws
interaction avec Result/throws/faults
interaction avec destruction déterministe
runtime minimal
```
Aucune dépendance obligatoire à un executor monolithique ne doit être supposée sans justification.
Les collections concurrentes spécialisées relèvent du SDK et non d'une symétrie artificielle du Core. Une future `ConcurrentMap<K,V>` doit exprimer des garanties de concurrence/atomicité orthogonales aux capacités structurelles `Map` / `SettableMap` / `ResizableMap`. Des types tels que `ConcurrentHashMap<K,V>` ne seront introduits que lorsqu'un contrat concurrent concret le justifie.
---

View File

@@ -66,11 +66,51 @@ unsafe field
Le caractère dangereux est porté par le type/opération.
## 27.4 Raw pointers — V1 REQUIS — À FINALISER
## 27.4 Pointeurs et accès mémoire bas niveau — V1 REQUIS — À FINALISER CRITIQUE
Les pointeurs bruts existent explicitement et leurs opérations de dereference/arithmétique autorisées doivent être précisément définies.
Le modèle mémoire contient un sous-ensemble dédié aux pointeurs ; il ne doit pas être confondu avec les références de classe ou `Slice<T>`.
Les noms des types (`Ptr<T>`, `PtrMut<T>` ou autre) restent à figer.
La spécification devra distinguer au minimum :
```text
référence de classe
accès sûr ordinaire vers un objet
Slice<T>
vue sûre, bornée et contiguë sur un stockage existant
pointeur Saselang
adresse explicite avec contrat de type/mutabilité à définir
pointeur brut / FFI
accès mémoire bas niveau potentiellement unsafe
function pointer
représentation ABI d'une cible callable, distincte des callables/closures ordinaires
```
Les noms exacts des types (`Ptr<T>`, `PtrMut<T>` ou autre) restent à figer.
Doivent être définis explicitement :
```text
nullabilité et non-null par défaut éventuel
const T pointé et constness du pointeur lui-même
dereference
address-of
arithmétique de pointeurs
alignement
allocation/libération manuelles
casts entre pointeurs
conversion pointeur <-> entier si elle existe
pointeur opaque / équivalent éventuel de void*
function pointers
FFI C
ownership ou absence d'ownership attaché au pointeur
interaction avec allocator, lifetime interne et thread safety
```
Le code ordinaire ne doit pas avoir besoin de pointeurs explicites lorsque les références de classe, arrays, slices ou autres abstractions sûres suffisent. Les opérations dangereuses doivent rester dans l'inventaire fermé `unsafe`.
## 27.5 Allocator — V1 REQUIS — À FINALISER CRITIQUE

View File

@@ -37,6 +37,7 @@ Les sorties qui déclenchent les `defer` du scope traversé comprennent notammen
fin normale
return
throw
Fault propagé
break
continue
emit quittant le scope concerné
@@ -46,12 +47,12 @@ La valeur d'un `return` ou d'un `emit` est déterminée avant l'exécution des c
## 28.2 Unwind et ordre avec `catch` / `finally` — V1 REQUIS — FIGÉ
Lorsqu'une `Exception` quitte un scope, les `defer` des scopes abandonnés sont exécutés avant l'entrée dans le `catch` correspondant.
Lorsqu'une `Exception` ou un `Fault` capturable quitte un scope, les `defer` des scopes abandonnés sont exécutés avant l'entrée dans le `catch` correspondant, sous réserve des détails d'unwind de `Fault` encore à fermer avec le runtime.
Ordre conceptuel :
```text
throw
throw / Fault propagé
-> unwind des scopes quittés
-> defer de ces scopes, LIFO
-> catch correspondant éventuel
@@ -73,6 +74,7 @@ Sont interdits dans un `defer` lorsqu'ils quittent le bloc :
```text
return
throw
fault
break
continue
emit
@@ -80,6 +82,8 @@ emit
Aucune `Exception` non capturée ne peut sortir indirectement d'un `defer`. Une callable appelée depuis un `defer` et susceptible de lancer une `Exception` doit voir cette exception entièrement gérée à l'intérieur du bloc `defer`.
Un `fault` explicite est interdit dans un `defer` pour la même raison qu'un `throw` explicite : le cleanup ne doit pas volontairement remplacer une sortie déjà en cours. Un `Fault` dynamique produit indirectement reste possible car il est unchecked ; son interaction exacte avec l'unwind/destruction fait partie du modèle mémoire encore à fermer.
Un `ResultError` reste une simple valeur : un appel retournant `Result<T,E>` est autorisé dans un `defer`, sous réserve des règles normales de traitement de cette valeur.
## 28.4 `finally` versus `defer` — V1 REQUIS — FIGÉ
@@ -94,4 +98,4 @@ Un `try/finally` sans `catch` est interdit précisément parce que `defer` couvr
Pas de `errdefer` séparé en V1.
`catch` gère les chemins d'`Exception`; `defer` gère le cleanup systématique du scope. Un troisième mécanisme serait redondant.
`catch` gère les chemins d'`Exception` et de `Fault`; `defer` gère le cleanup systématique du scope. Un troisième mécanisme dédié uniquement à l'échec serait redondant.

View File

@@ -214,7 +214,7 @@ désactiver les contrôles d'overflow définis par Saselang
modifier la sémantique d'un index hors limites
modifier l'ordre d'évaluation
modifier la représentation sémantique des types
changer les règles Result/throws
changer les règles Result/throws/faults
désactiver les vérifications de sûreté du langage
faire varier la validité d'un programme Saselang autrement que par une limite propre au backend/target
```

View File

@@ -12,7 +12,9 @@ Pas de visibilité explicite.
`main` ne peut pas déclarer `throws`, même s'il retourne `Result`.
L'environnement top-level ne possède pas d'appelant Saselang capable de l'envelopper dans un `try/catch`.
L'environnement top-level ne possède pas d'appelant Saselang capable d'assumer un contrat checked : toute `Exception` doit donc être gérée avant de quitter `main`.
`main` peut documenter des `Fault` par `faults`, comme toute callable. Un `Fault` non capturé atteint la frontière de l'unité d'exécution et provoque l'échec runtime correspondant.
## 42.2 `ExitCode` — V1 REQUIS — FIGÉ EN PRINCIPE

View File

@@ -74,7 +74,7 @@ Les commentaires documentaires sont :
/** documentation de bloc */
```
Ils ont la même sémantique documentaire avec deux ergonomies d'écriture différentes. Saselang ne reprend pas la redondance Javadoc/PHPDoc consistant à dupliquer systématiquement la signature via `@param`, `@return` ou `@throws` ; `saseldoc` dérive ces informations du programme.
Ils ont la même sémantique documentaire avec deux ergonomies d'écriture différentes. Saselang ne reprend pas la redondance Javadoc/PHPDoc consistant à dupliquer systématiquement la signature via `@param`, `@return`, `@throws` ou `@faults` ; `saseldoc` dérive ces informations du programme.
Une Saseldoc est autorisée uniquement lorsqu'elle est immédiatement attachée à une déclaration documentable. Elle n'est jamais un commentaire libre à l'intérieur d'un corps exécutable.
@@ -128,7 +128,7 @@ Un marqueur `@...` inconnu dans un commentaire documentaire ne doit pas faire é
La visibilité n'est pas réduite artificiellement à un ordre total lorsque les domaines `protected`, `module` et `package` ne sont pas sémantiquement comparables. L'interface de filtrage doit pouvoir exprimer les ensembles de visibilité nécessaires sans falsifier le modèle d'accès du langage.
Les signatures, types de paramètres, generics, visibilité, `Result`, `throws`, héritage et interfaces sont dérivés du modèle sémantique plutôt que redéclarés manuellement dans la Saseldoc.
Les signatures, types de paramètres, generics, visibilité, `Result`, `throws`, `faults`, héritage et interfaces sont dérivés du modèle sémantique plutôt que redéclarés manuellement dans la Saseldoc.
Les formats exacts V1 restent à finaliser avec la CLI, mais un format de sortie n'implique jamais un outil séparé.

View File

@@ -41,16 +41,17 @@ Restent à fermer :
## 48.4 Erreurs
Points désormais largement figés : hiérarchie `Error` / `ResultError` / `Exception`, `Result::Ok` / `Result::Err`, contraintes de `Result<T,E>`, absence de `unwrap` et `?` V1, `throw` / `throws`, contrats d'override/interface, sélection ordonnée des `catch`, `finally` non-escaping, causes, i18n, code de `ResultError`, stack trace d'`Exception` liée au `throw`, et sémantique LIFO/non-escaping de `defer`.
Points désormais largement figés : hiérarchie `Error` / `ResultError` / `Exception` / `Fault`, `Result::Ok` / `Result::Err`, contraintes de `Result<T,E>`, absence de `unwrap` et `?` V1, `throw` / `throws` pour les exceptions checked, `fault` / `faults` pour les faults unchecked, `catch` limité aux branches `Exception` et `Fault`, contrats d'override `throws`, causes, i18n, code de `ResultError`, stack trace diagnostique et sémantique LIFO/non-escaping de `defer`.
Restent à fermer :
- faute runtime/panic/fatal error ;
- interaction exacte cleanup/destruction/unwind pendant un `Fault` ;
- unité d'exécution exacte terminée par un `Fault` non capturé ;
- constructors faillibles et construction partielle ;
- interaction exacte cleanup/destruction pendant fault ;
- ordre exact `defer` / destructeurs automatiques avec le modèle mémoire ;
- représentation Core/runtime exacte de `I18nMessage`, `ResultErrorCode`, `StackTrace` et `StackFrame` ;
- éventuels helpers Core futurs `expectOk` / `expectErr` seulement si un besoin réel est démontré.
- politique de lint/documentation pour les `Fault` explicites non listés dans `faults` ;
- éventuels helpers Core futurs de `Result` seulement si un besoin réel est démontré.
## 48.5 Contrôle de flux
@@ -97,7 +98,10 @@ Restent à fermer :
## 48.9 Core/SDK
- frontière Core/SDK définitive ;
- collections V1 ;
- `Vector<T>` et interaction avec `Slice<T>` lors des reallocations ;
- contrats `Hashable` / égalité et implémentations HashSet/HashMap ;
- opérations avancées de bornes/ranges pour `SortedSet` / `SortedMap` ;
- propagation formelle de `const` dans `View<T>`, `Option<T>`, `Iterator<T>` et autres wrappers ;
- String encodings ;
- regex ;
- filesystem/network/process ;

View File

@@ -13,8 +13,8 @@ Les futures décisions doivent respecter les invariants suivants :
9. **Les types Core compiler-known restent peu nombreux.**
10. **Le package, le namespace, le target, la feature, la capability et l'artifact restent des dimensions distinctes.**
11. **Une collision de namespace entre packages ne doit jamais fusionner implicitement leurs types.**
12. **Les erreurs récupérables utilisent `Result`; les opérations réellement infaillibles retournent directement leur valeur.**
13. **`throws` n'existe que sur une callable retournant `Result`.**
12. **`ResultError`, `Exception` et `Fault` sont trois mécanismes distincts : valeur d'échec explicite, propagation checked et échec unchecked capturable.**
13. **`throws` ne contient que des `Exception` et reste indépendant du type de retour ; `faults` ne contient que des `Fault` et reste optionnel/non exhaustif.**
14. **L'identité d'objet est distincte de l'égalité de valeur.**
15. **Les opérateurs utilisateur passent uniquement par les contrats Core `Op...`.**
16. **Les interfaces fournissent l'héritage multiple de contrats/comportements sans introduire un second système de traits.**
@@ -34,5 +34,6 @@ Les futures décisions doivent respecter les invariants suivants :
29. **Un array safe devient observable uniquement après initialisation complète.**
30. **Une bibliothèque spécialisée peut être officielle sans appartenir au Core ou au SDK obligatoire ; son artifact normal reste une `.saselib`.**
31. **Les dépendances natives de bootstrap peuvent être remplacées progressivement par des implémentations Saselang sans imposer leur architecture historique au langage.**
32. **Lorsqu'une forme légèrement plus longue supprime un implicite ou une ambiguïté réelle, Saselang privilégie l'explicite.**
---

View File

@@ -121,3 +121,8 @@ text::append("def"); // OK si append est une méthode mutante de String
## DO / DON'T / WHY / compiler error / edge cases
À consolider progressivement avant la baseline publique V3 et à transformer, lorsque pertinent, en tests de conformité de la toolchain.
## Explicite plutôt qu'ambigu
Lorsqu'une forme légèrement plus longue supprime un implicite ou une ambiguïté réelle, Saselang la préfère à une syntaxe plus courte.

View File

@@ -19,7 +19,7 @@ unions
tuples
generics
contrôle de flux
erreurs/exceptions
erreurs/exceptions/faults
opérateurs
unsafe
scope
@@ -38,6 +38,7 @@ Result<T,E>
Error
ResultError
Exception
Fault
Option<T>
Nullable<T>
Range<T>
@@ -46,10 +47,18 @@ RangeStep<T,Step>
RangeReverse<T>
RangeReverseStep<T,Step>
RangeProgression<T,Step>
PartialOrdering
Ordering
Comparable<T>
Comparator<T>
Op...
Iterable<T>
Iterator<T>
View<T>
Collection<T>
List<T>
Set<T>
Map<K,V>
Array<T>
StaticArray<T,N>
TypeInfo
@@ -59,7 +68,7 @@ ExitCode
### Exemple 3
```text
collections
collections concrètes/spécialisées au-delà des contrats fondamentaux Core
encodages explicites
regex
filesystem

View File

@@ -19,7 +19,10 @@ type de retour
visibilité
fallibilité / Result
throws
contraintes génériques pertinentes
qualification const et contraintes génériques pertinentes
faults
visible mais non checked / non exhaustif
modificateurs contractuels pertinents
```

View File

@@ -16,30 +16,35 @@ operator implémentation d'un contrat opérateur
### Exemple 2
```text
opération infaillible
-> retourne directement T
opération pouvant produire une erreur récupérable
-> retourne Result<T>
ou Result<T,E>
T
T throws SomeException
T faults SomeFault
T throws SomeException faults SomeFault
Result<T,E>
Result<T,E> throws SomeException
Result<T,E> faults SomeFault
```
Le type de retour et le mécanisme d'échec sont indépendants.
### Exemple 3
```text
method length() -> uint64
method containsKey(K key) -> bool
Object::sameInstance(Object other) -> bool
func min(int32 a, int32 b) -> int32
func readConfig(String path) -> Config
throws IOException
method elementAt(uint64 index) -> T
faults IndexOutOfBoundsFault
```
### Exemple 4
```text
func readFile(String path) -> Result<String, IoError>
method parse(String input) -> Result<Value, ParseError>
func parseExternalInput(String input) -> Result<Value, ParseError>
```
`Result` reste utilisé lorsque l'échec doit être transporté comme une valeur.
### Exemple 5
```text

View File

@@ -1,259 +1,159 @@
# Exemples / DO-DON'T — Chapitre 18 — `Result`, erreurs et exceptions
# Exemples / DO-DON'T — Chapitre 18 — `Result`, erreurs, exceptions et faults
> Document compagnon non normatif tant qu'une règle n'est pas explicitement référencée comme normative par le chapitre.
> Document compagnon. Les exemples illustrent les règles du chapitre ; la formulation normative reste dans le chapitre lui-même.
## Exemples actuellement présents dans le chapitre
### Exemple 1
## Hiérarchie
```text
Object
└── Error
├── ResultError
── Exception
── Exception
└── Fault
```
### Exemple 2
```text
public final class ParseError extends ResultError {
}
public final class FileNotFoundException extends Exception {
}
```
### Exemple 3
```text
message: String
cause: Option<Error>
i18nMessage: Option<I18nMessage>
```
### Exemple 4
```text
message
message humain canonique / fallback
cause
erreur causale purement informative
peut contenir un ResultError ou une Exception
n'est pas automatiquement propagée
i18nMessage
clé et paramètres de localisation
ne contient pas un tableau de traductions
```
### Exemple 5
```text
code: ResultErrorCode
```
### Exemple 6
```text
code -> stable, machine-readable, non localisé
message -> humain, canonique / fallback
i18nMessage -> localisation externe
```
### Exemple 7
```text
throw exception;
```
### Exemple 8
```text
Result::Ok(T)
Result::Err(E)
```
### Exemple 9
```text
E doit être ResultError ou un descendant de ResultError
```
### Exemple 10
```text
Result<Data,ResultError>
Result<Data,ParseError>
Result<Void,ResultError>
```
### Exemple 11
```text
Result<Data,Error>
Result<Data,Exception>
Result<Data,FileNotFoundException>
```
### Exemple 12
```text
Result<T>
```
### Exemple 13
```text
Result<T,ResultError>
```
### Exemple 14
```text
return Result::Ok(value);
return Result::Err(error);
```
### Exemple 15
```text
result::expectOk(...)
result::expectErr(...)
```
### Exemple 16
```text
ResultError -> Exception
Exception -> ResultError
```
### Exemple 17
```text
throw ParseException(..., Option::Some(parseError));
```
### Exemple 18
```text
catch (FileNotFoundException error) {
return Result::Err(FileResultError(..., Option::Some(error)));
public final class IndexOutOfBoundsFault extends Fault {
}
```
### Exemple 19
## `ResultError`
DO : utiliser `Result` lorsque l'échec est une valeur normale à inspecter explicitement.
```text
T + throws -> interdit
Result<T,E> -> valide sans throws
Result<T,E> + throws -> valide
```
### 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;
func parseExternalInput(String input) -> Result<Value, ParseError> {
...
}
```
### Exemple 24
DON'T : placer une `Exception` ou un `Fault` dans le paramètre erreur de `Result`.
```text
try { ... }
try { ... } finally { ... }
finally { ... }
Result<Value,FileNotFoundException> // ERROR
Result<Value,IndexOutOfBoundsFault> // ERROR
```
### 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
try {
...
} catch (SpecificException error) {
...
} catch (ParentException error) {
...
} finally {
T value = list::elementAt(index);
} catch (IndexOutOfBoundsFault faultValue) {
...
}
```
### Exemple 26
Aucune propagation de `faults` n'est obligatoire :
```text
catch (FileNotFoundException error) {
...
} catch (IOException error) {
...
func outer() -> Void {
inner(); // inner peut déclarer faults SomeFault
return Void;
}
```
### Exemple 27
## `catch`
Valide :
```text
catch (IOException error) {
...
} catch (FileNotFoundException error) {
}
catch (IteratorInvalidatedFault faultValue) {
...
}
```
### Exemple 28
Invalide :
```text
fin normale du try
fin normale d'un catch
return traversant la construction
throw propagé
break / continue traversant la construction
Exception non capturée par les catch
catch (Error error) // ERROR
catch (ResultError error) // ERROR
```
### Exemple 29
`catch` ne peut cibler que `Exception`, `Fault` ou leurs descendants.
## Direct versus valeur conditionnelle
Accès affirmatif :
```text
return
throw
break
continue
emit
User user = users[id]; // absence -> KeyNotFoundFault
```
### Exemple 30
Absence normale :
```text
index hors limites
division entière par zéro
overflow checked
représentation mémoire invalide
borne dynamique invalide lors d'une construction directe lorsque la règle du type le définit
Option<User> user = users::get(id);
```
## DO / DON'T / WHY / compiler error / edge cases
Le Core ne doit pas créer automatiquement une variante `tryOp()` uniquement pour transporter le même échec dans `Result`.
La couverture structurée de cette section sera enrichie au fur et à mesure de la fermeture des règles du chapitre. La migration `0.2.12` conserve volontairement les exemples historiques dans le chapitre afin de ne perdre aucun contexte normatif.
## Erreur statique versus fault runtime
```text
StaticArray<int32,3> values = [1, 2, 3];
int32 a = values[5]; // ERROR compilation
```
```text
uint64 index = readIndex();
int32 b = values[index]; // peut produire IndexOutOfBoundsFault au runtime
```
Un statement `fault` explicite reste évidemment valide :
```text
if (!state::isValid()) {
fault InvalidStateFault(...);
}
```

View File

@@ -91,12 +91,18 @@ transitive
### Exemple 11
```text
public enum Ordering {
public enum PartialOrdering {
Less,
Equal,
Greater,
Unordered
}
public enum Ordering {
Less,
Equal,
Greater
}
```
### Exemple 12
@@ -124,8 +130,11 @@ container[index] = value
```text
Map<K,V>
OpIndex<K,Option<V>>
OpIndex<K,V>
OpIndexMut<K,V>
map[key] // strict, absent -> KeyNotFoundFault
map::get(key) // Option<V>
```
### Exemple 16

View File

@@ -78,12 +78,12 @@ char::toUtf8Char()
Utf8Char::toChar()
Utf8Char::toUtf16Char()
Utf8Char::tryFrom(uint8)
Utf16Char::tryFrom(uint16)
Utf32Char::tryFrom(uint32)
Utf8Char::from(uint8) faults UnicodeEncodingFault
Utf16Char::from(uint16) faults UnicodeEncodingFault
Utf32Char::from(uint32) faults UnicodeEncodingFault
Utf8Char::tryToUint8()
Utf16Char::tryToUint16()
Utf8Char::toUint8() faults UnicodeEncodingFault
Utf16Char::toUint16() faults UnicodeEncodingFault
Utf32Char::toUint32()
```

View File

@@ -158,7 +158,82 @@ Vector<T>
ResizableList<T>
```
### Exemple 18
### Exemple 18 — `Iterator<T>`
```text
interface Iterable<T> {
const method iterator() -> Iterator<T>;
}
interface Iterator<T> {
method next() -> Option<T>;
}
```
### Exemple 19 — `View<T>`
```text
interface View<T> extends Iterable<T> {
const method count() -> uint64;
const method isEmpty() -> bool;
}
```
`View<T>` n'impose pas `contains()`.
### Exemple 20 — Set
```text
ResizableSet<T>::add(T value) -> bool
ResizableSet<T>::remove(const T value) -> bool
ResizableSet<T>::clear() -> uint64
```
### Exemple 21 — Map
```text
map[key] -> V // strict
map::get(key) -> Option<V> // conditionnel
map[key] = value // remplacement seulement
map::insert(key, value) // clé nouvelle, DuplicateKeyFault sinon
map::remove(key) // clé existante, KeyNotFoundFault sinon
map::clear() -> uint64
```
### Exemple 22 — Vues de Map
```text
map::keys() -> View<K>
map::values() -> View<V>
map::entries() -> View<MapEntry<K,V>>
```
### Exemple 23 — Ordre
```text
enum Ordering {
Less,
Equal,
Greater
}
Comparable<T>
Comparator<T>
SortedSet<T>
SortedMap<K,V>
```
### Exemple 24 — Factories ordonnées
```text
TreeSet<T>::natural()
TreeSet<T>::withComparator(comparator)
TreeMap<K,V>::natural()
TreeMap<K,V>::withComparator(comparator)
```
## Exemples Range
```text
a..b [a, b] bornes basse et haute incluses
@@ -167,13 +242,13 @@ a..<b [a, b) borne basse incluse, borne haute exclue
a>..<b (a, b) bornes basse et haute exclues
```
### Exemple 19
### Range 1
```text
Range<uint64> ids = 1..100;
```
### Exemple 20
### Range 2
```text
NaN interdit comme borne
@@ -182,7 +257,7 @@ NaN interdit comme borne
valeur finie autorisée
```
### Exemple 21
### Range 3
```text
a..a contient exactement a
@@ -191,7 +266,7 @@ a..<a vide
a>..<a vide
```
### Exemple 22
### Range 4
```text
range::lower()
@@ -202,7 +277,7 @@ range::isEmpty()
range::contains(value)
```
### Exemple 23
### Range 5
```text
Range<T> intervalle ordonné
@@ -213,13 +288,13 @@ RangeReverseStep<T,Step> parcours arrière avec pas explicite
RangeProgression<T,Step> valeur de progression produite
```
### Exemple 24
### Range 6
```text
(range)::step(step)
```
### Exemple 25
### Range 7
```text
RangeStep<int32,int32>
@@ -228,14 +303,14 @@ RangeStep<char,uint32>
RangeStep<Date,Duration>
```
### Exemple 26
### Range 8
```text
(range)::reverse()
(range)::reverse()::step(step)
```
### Exemple 27
### Range 9
```text
range
@@ -243,25 +318,25 @@ range
[::step(step)]
```
### Exemple 28
### Range 10
```text
(250u8..255u8)::step(2u8)
```
### Exemple 29
### Range 11
```text
250 252 254
```
### Exemple 30
### Range 12
```text
(1..10)::step(4)
```
### Exemple 31
### Range 13
```text
1 5 9

View File

@@ -2,100 +2,102 @@
> Document compagnon. Les exemples illustrent les règles du chapitre ; la formulation normative reste dans le chapitre lui-même.
## Exemples extraits du chapitre
### Exemple 1
```text
conversion de valeur
cast de hiérarchie nominale
bitcast de représentation binaire
```
### Exemple 2
## Conversion explicite
```text
int8 small = ...;
int32 large = small; // ERROR
int32 large = small; // ERROR
int32 explicitLarge = small::toInt32(); // OK
```
### Exemple 3
## Widening total
```text
Dog dog = ...;
Animal animal = dog;
Serializable serializable = dog;
int8 value = ...;
int32 larger = value::toInt32();
```
### Exemple 4
Aucun `tryToInt32()` parallèle n'est nécessaire si toutes les valeurs source sont exactement représentables.
## Narrowing exact avec `Fault`
```text
Animal animal = ...;
if (animal is Dog) {
// animal est raffiné en Dog ici.
}
int32 value = ...;
int8 smaller = value::toInt8();
```
### Exemple 5
La signature Core peut déclarer :
```text
toTarget()
conversion exacte et totale
tryToTarget()
conversion exacte pour la valeur courante, récupérable si impossible
roundToTarget()
perte de précision explicitement acceptée, conversion totale
tryRoundToTarget()
perte de précision explicitement acceptée, mais conversion pouvant échouer
saturateToTarget()
saturation explicite lorsqu'aucun arrondi supplémentaire n'est nécessaire
saturatingRoundToTarget()
arrondi + saturation explicitement annoncés
wrapToTarget()
wrapping entier explicite
toInt8() -> int8
faults NumericConversionFault
```
### Exemple 6
`OutOfRange` est produit lorsque la valeur ne tient pas dans `int8`.
## Politiques distinctes
```text
tryToIntXX()
tryToUintXX()
value::toInt8() // exact, peut fault
value::saturateToInt8()
value::wrapToInt8()
```
### Exemple 7
Ces opérations coexistent seulement lorsque leur résultat peut réellement différer.
## Flottant vers entier
```text
floor()
ceil()
round()
truncate()
float64 value = ...;
int32 exact = value::toInt32();
```
### Exemple 8
La conversion exige une valeur finie, intégrale et dans la plage.
Pour choisir explicitement une politique mathématique :
```text
value::floor()::tryToInt32()
value::ceil()::tryToInt32()
value::round()::tryToInt32()
value::truncate()::tryToInt32()
value::floor()::toInt32()
value::ceil()::toInt32()
value::round()::toInt32()
value::truncate()::toInt32()
```
### Exemple 9
Pour choisir la politique de plage :
```text
value::floor()::trySaturateToInt32()
value::round()::tryWrapToInt32()
value::floor()::saturateToInt32()
value::round()::wrapToInt32()
```
### Exemple 10
## Entier vers flottant
```text
int64 value = ...;
float64 exact = value::toFloat64();
float64 approximated = value::roundToFloat64();
```
`toFloat64()` exige l'exactitude ; `roundToFloat64()` accepte explicitement la perte de précision.
## Flottant vers flottant
```text
toFloatXX()
exige l'exactitude
roundToFloatXX()
accepte l'arrondi canonique
peut fault OutOfRange sur une valeur finie
saturatingRoundToFloatXX()
accepte l'arrondi canonique
sature une valeur finie hors domaine
```
Les catégories suivantes sont préservées :
```text
NaN -> NaN
@@ -105,31 +107,13 @@ NaN -> NaN
-0 -> -0
```
### Exemple 11
## `NumericConversionFault`
```text
payload NaN
quiet/signaling bit
signe du NaN
représentation binaire exacte
NumericConversionFault extends Fault
```
### Exemple 12
```text
tryToFloatXX()
exige une représentation exacte
tryRoundToFloatXX()
accepte l'arrondi canonique
refuse une valeur finie hors domaine fini destination
saturatingRoundToFloatXX()
accepte l'arrondi canonique
sature une valeur finie hors domaine vers +/-Target::Max
```
### Exemple 13
Codes :
```text
NotFinite
@@ -138,40 +122,10 @@ OutOfRange
Inexact
```
### Exemple 14
DON'T : introduire mécaniquement :
```text
NotFinite
NaN ou +/-Infinity lorsqu'une valeur finie est requise
NotIntegral
float -> integer alors que la valeur n'est pas mathématiquement entière
OutOfRange
valeur mathématique hors du domaine de la destination
Inexact
valeur dans le domaine destination mais non représentable exactement
alors que l'opération exige l'exactitude
tryToTarget() -> Result<Target,NumericConversionError>
```
### Exemple 15
```text
sourceType
targetType
sourceValue
timestamp
backend
roundingMode
```
### Exemple 16
```text
annexes/A-numeric-conversions.md
```
## DO / DON'T / WHY / compiler error / edge cases
À consolider progressivement avant la baseline publique V3 et à transformer, lorsque pertinent, en tests de conformité de la toolchain.
si cette méthode ne ferait que dupliquer `toTarget() faults NumericConversionFault`.

View File

@@ -13,7 +13,7 @@ threads natifs
structured concurrency éventuelle
cancellation
synchronisation
interaction avec Result/throws
interaction avec Result/throws/faults
interaction avec destruction déterministe
runtime minimal
```

View File

@@ -51,3 +51,16 @@ ownership annotations pour les usages ordinaires
## DO / DON'T / WHY / compiler error / edge cases
À consolider progressivement avant la baseline publique V3 et à transformer, lorsque pertinent, en tests de conformité de la toolchain.
## Pointeurs — distinctions à préserver
```text
référence de classe
Slice<T>
pointeur Saselang
pointeur brut / FFI
function pointer
```
Les pointeurs explicites restent un sous-modèle mémoire dédié et ne remplacent pas les références/slices sûres dans le code ordinaire.

View File

@@ -65,3 +65,14 @@ emit
## DO / DON'T / WHY / compiler error / edge cases
La couverture structurée de cette section sera enrichie au fur et à mesure de la fermeture des règles du chapitre. La migration `0.2.12` conserve volontairement les exemples historiques dans le chapitre afin de ne perdre aucun contexte normatif.
## Fault et cleanup
```text
defer {
fault CleanupFault(...); // ERROR : fault explicite escaping
}
```
Un `Fault` dynamique produit indirectement reste possible car il est unchecked ; l'ordre exact d'unwind/destruction est encore à fermer.

View File

@@ -162,7 +162,7 @@ désactiver les contrôles d'overflow définis par Saselang
modifier la sémantique d'un index hors limites
modifier l'ordre d'évaluation
modifier la représentation sémantique des types
changer les règles Result/throws
changer les règles Result/throws/faults
désactiver les vérifications de sûreté du langage
faire varier la validité d'un programme Saselang autrement que par une limite propre au backend/target
```