diff --git a/000-README.md b/000-README.md index 5090664..c4962f1 100644 --- a/000-README.md +++ b/000-README.md @@ -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 diff --git a/001-SUMMARY.md b/001-SUMMARY.md index 5b37c5c..d788e08 100644 --- a/001-SUMMARY.md +++ b/001-SUMMARY.md @@ -1,4 +1,4 @@ -# Sommaire — Bible Saselang 0.2.16 +# Sommaire — Bible Saselang 0.2.17 ## Chapitres diff --git a/003-CHANGELOG.md b/003-CHANGELOG.md index 758bd76..316bfbb 100644 --- a/003-CHANGELOG.md +++ b/003-CHANGELOG.md @@ -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` et `Comparator` retenus pour l'ordre naturel/principal et l'ordre externe ; un comparator explicite gagne toujours ; +- `Iterable::iterator()` et `Iterator::next() -> Option` figés ; `Iterator` reste distinct d'`Iterable` ; +- ajout de `View extends Iterable` avec `count()` / `isEmpty()` et sans `contains()` obligatoire ; +- `Set` / `ResizableSet` fermés, avec `clear() -> uint64` ; +- `Map` n'est pas directement `Iterable`; `keys()` / `values()` / `entries()` retournent des vues ; +- indexation map stricte `map[key] -> V`, `get(key) -> Option`, 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` reste une valeur de lecture et non un proxy mutable vers la map ; +- `SortedSet`, `SortedMap`, `TreeSet` et `TreeMap` 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 diff --git a/MANIFEST.toml b/MANIFEST.toml index b144baa..6f344e3 100644 --- a/MANIFEST.toml +++ b/MANIFEST.toml @@ -1,65 +1,153 @@ format = 1 -version = "0.2.16" +version = "0.2.17" distribution = "delta" -base_version = "0.2.15" +base_version = "0.2.16" documentation_layout = "multifile" [[modified]] path = "000-README.md" -sha256 = "4b4d422dcc52991e38c6cb1b7b92aeb391ca0b7d6bc1c8da0de4de6169c93b7a" +sha256 = "ca87a3caaadb1a618f0a35620a2e62e406bd8e186de0a7282e606a38f9f541ca" [[modified]] path = "001-SUMMARY.md" -sha256 = "2cf8811903512dc58739c4d16e2696d10bcb36f2b767d3e5eccf038013ef1a66" +sha256 = "88f6f80b7233900491f15d818cebbfdb3fc83f02667cfa137cb3ed6a17f86edf" [[modified]] path = "003-CHANGELOG.md" -sha256 = "0f78fefe1d630ebc0587b7bb0865f77c34b9782562bf47af6d86e82cac8bf738" +sha256 = "ccc7116c032fc68b6a91fba447674673d0a6141229498e1db3d00a246d11df0f" + +[[modified]] +path = "annexes/A-numeric-conversions.md" +sha256 = "cc13423ccf18bbfac922f6e9a9afe422d438bd1f4aeea10919941a55c3d9dc98" + +[[modified]] +path = "annexes/B-unicode-encoding-conversions.md" +sha256 = "c26a957419e4b60706b61c9f482380a5cd496de2fe685beb33bc86927a287ee4" + +[[modified]] +path = "chapters/002-principes-generaux-du-langage.md" +sha256 = "63b26e729bac07ee2395634698c54f33c0f16d6f121571e9bc6096bd05cfa40f" [[modified]] path = "chapters/004-couches-de-lecosysteme-v1.md" -sha256 = "5d6bfbc9e9d7c5253fbe470c114a2b2394c16cf62a5cd7efd3d9f40252ae0106" +sha256 = "18c0b82d5b2b55dab17a2197dc2635d1d050ac4b06b6c3fc1dc34e12e5978bb6" + +[[modified]] +path = "chapters/011-tuples.md" +sha256 = "8008f930e37a69980ccf39af0261d5af63efb136268c4793e1899da1fc58a523" + +[[modified]] +path = "chapters/013-interfaces.md" +sha256 = "330f2d231ed7d6ffbbbd8a1703c8f27f17b2c9c2b372d5c5c663fa4b6ae3a43d" + +[[modified]] +path = "chapters/015-fonctions-methodes-et-clsmethod.md" +sha256 = "e15da7b6f0b86fcadfa7d0ec4c5b4877ed97580d7292aa13dfab3a271b3b2468" + +[[modified]] +path = "chapters/018-result-erreurs-et-exceptions.md" +sha256 = "d2e08f85e0f077ece4e5f15d3dc47ce552608376001b128f222230070ed23726" + +[[modified]] +path = "chapters/019-controle-de-flux.md" +sha256 = "34ec610fd03ac339504d48a265793fdb2c146404d38285b9bada72683f88361d" + +[[modified]] +path = "chapters/020-operateurs.md" +sha256 = "59119759c87babc9dc0d852fcdfcda6d527fcb475c6c22d26cd0fe546d50f0df" [[modified]] path = "chapters/021-strings-unicode-et-encodages.md" -sha256 = "3350f8581eb43343136caf7cf808b25da4543edac6b176ad61d3e40292b19d76" +sha256 = "c8e5ea1e1fce5fe3128d7dd1eb73ddd784b71d3fa24298de9bfabc1d44e05327" [[modified]] path = "chapters/022-collections-et-iteration.md" -sha256 = "a60534eef7f12201b238c7a4899b46c8be4df3535f293978e05471cc210c3d7a" +sha256 = "e7459c2db8d0fe0cdf573d25f888c1791b6d03a9de6f51ae849991039abc4328" [[modified]] -path = "chapters/037-dependances-et-scopes.md" -sha256 = "64335ed6b00a8133718384e49b34be0f362569b9b177a35da963543abe603a9a" +path = "chapters/024-casts-et-conversions.md" +sha256 = "e6cd16e5e4b65c2f05bac57a5410cb7aaa74253d2572f969b4fcf1dbf3618e93" + +[[modified]] +path = "chapters/026-async-et-concurrence.md" +sha256 = "65ab9ddcfa155130daf913d9f24ebf8583fca92e3fbd4325d3b5ef86729b998a" + +[[modified]] +path = "chapters/027-memoire-references-et-unsafe.md" +sha256 = "c82271a7b7b179b49a963c1f00b1e5179c71c4d9839a50d4ca541b9b6c604215" + +[[modified]] +path = "chapters/028-defer-et-nettoyage.md" +sha256 = "d2d9d9e5b2faa7a238931f80a3247b735e9a1a1c5967a3920b3649da6a6bfd32" + +[[modified]] +path = "chapters/041-artifacts-exports-profils-et-reservation-des-formats-futurs.md" +sha256 = "bbec66e98338765dfb85b22e941811eedc2f1c7bd11ab9ccc86483f3ea4c3ec2" + +[[modified]] +path = "chapters/042-main-et-exitcode.md" +sha256 = "c8466a02c19df25d3a792fc289e774f1f4f790137389b6c9e0a9905f0cf28bcc" + +[[modified]] +path = "chapters/043-documentation-et-tests-de-conformite.md" +sha256 = "3769820873793f73f75030c0d54c8194cbdc2a9a0428ccfd6707e3284f194003" [[modified]] path = "chapters/048-inventaire-des-points-v1-encore-ouverts.md" -sha256 = "3c99a2d2901e5843b4ea40b26c541203c907a809ad2004fd93c0ad4a94a68413" +sha256 = "908856acb0472c2c4eee3d03b8260f21b5b6495d342053f371b00e54158ed2d1" [[modified]] path = "chapters/051-invariants-de-conception.md" -sha256 = "05c23658ea2b127c023b5d75630bd79096934d21f04f67f01375486fd35386e4" +sha256 = "c41f6c977c613631147b7d61c837afccc9b1c6807d62ade8175865f5108bf915" + +[[modified]] +path = "examples/002-principes-generaux-du-langage-examples.md" +sha256 = "42b5758d733563c0bdabad9f6005f5818ccb42513e599bc878142db6b4298e10" [[modified]] path = "examples/004-couches-de-lecosysteme-v1-examples.md" -sha256 = "3b37dee80e15c28fde237d208da3b16885c3190603f074b3bf4fabc21cda13e8" +sha256 = "2731f6e5861d041801bf831a936c59c6df854ac55b858500e32542e64105bb8a" + +[[modified]] +path = "examples/013-interfaces-examples.md" +sha256 = "2338543b0551c291dea59ebbd394a35d9e560d817b9e2d92eaa62c02d6ee3bd0" + +[[modified]] +path = "examples/015-fonctions-methodes-et-clsmethod-examples.md" +sha256 = "0760c83e732d77942b48339135a146d98a60f6dd2c60fc06bc8b093fdf026058" + +[[modified]] +path = "examples/018-result-erreurs-et-exceptions-examples.md" +sha256 = "47f50de6f6bf327e9f00de9a5a4e9470839d6e5e4d0ee570e432441d2924c6bb" + +[[modified]] +path = "examples/020-operateurs-examples.md" +sha256 = "717035959ea34130d7eeed2af8d3945afb10772b3015f6031c4462494076fec3" [[modified]] path = "examples/021-strings-unicode-et-encodages-examples.md" -sha256 = "e065baa54cd9203f9b37883f5c418baea27ffc0fe4d28e97ff349a1b66f8adc7" +sha256 = "6ed3cd078599b329b5f8f42ceda323eadc954f3d7d566e177adca56451a2345b" [[modified]] path = "examples/022-collections-et-iteration-examples.md" -sha256 = "86749fa6c85fbfbc2cd18643ad1da639af76222845ebf4418e62f7744cb76003" +sha256 = "f3546d35335937506044a697ff1610da20823bf29334c307d6cf7a53122d8ce3" [[modified]] -path = "examples/037-dependances-et-scopes-examples.md" -sha256 = "a384f5a4c624f75f7a52186c731fc95890fb0ee5067788b4f93b90b0989774e1" +path = "examples/024-casts-et-conversions-examples.md" +sha256 = "47a4d0e0e7fd822995be140d62432f48642da237d026551fc922f011776d1b8b" [[modified]] -path = "examples/048-inventaire-des-points-v1-encore-ouverts-examples.md" -sha256 = "069383c40e74b495cdd3ccbebd87850654fa1ef4b6095e93a4eab14acb5d1f3d" +path = "examples/026-async-et-concurrence-examples.md" +sha256 = "0a206a6b7ee2818a1e743b0dc1a033b27ebd75f543b9979d9c7fa37150c30255" [[modified]] -path = "examples/051-invariants-de-conception-examples.md" -sha256 = "307da7506d8411f033cfcfbf5fc555651175e28e64119e248a1c4d341afa487f" +path = "examples/027-memoire-references-et-unsafe-examples.md" +sha256 = "acadba49f317caa4805e8770c5732a029071559921a6c0a05281cfb026ef98e6" + +[[modified]] +path = "examples/028-defer-et-nettoyage-examples.md" +sha256 = "121e51d8cef0c2de89005d895aa05dfb8c52e9c69991dac411d1ceb7dbb00b05" + +[[modified]] +path = "examples/041-artifacts-exports-profils-et-reservation-des-formats-futurs-examples.md" +sha256 = "673a51f5c919b22ab1ec72b95f79ce17afd64ab0ec70bfaba260fc245a1f51d2" diff --git a/annexes/A-numeric-conversions.md b/annexes/A-numeric-conversions.md index 9b7b07b..f866b8c 100644 --- a/annexes/A-numeric-conversions.md +++ b/annexes/A-numeric-conversions.md @@ -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` 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 -``` - -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 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(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(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. diff --git a/annexes/B-unicode-encoding-conversions.md b/annexes/B-unicode-encoding-conversions.md index 63e9020..031f926 100644 --- a/annexes/B-unicode-encoding-conversions.md +++ b/annexes/B-unicode-encoding-conversions.md @@ -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) +Utf8Char::from(uint8) faults UnicodeEncodingFault +Utf8Char::from(StaticArray) faults UnicodeEncodingFault ``` `N` utile : 1 à 4. Le contenu doit représenter exactement un scalar UTF-8 valide. @@ -115,8 +116,8 @@ Utf8Char::tryFrom(StaticArray) UTF-16 : ```text -Utf16Char::tryFrom(uint16) -Utf16Char::tryFrom(StaticArray) +Utf16Char::from(uint16) faults UnicodeEncodingFault +Utf16Char::from(StaticArray) 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) -Utf16String::tryFrom(Array) -Utf32String::tryFrom(Array) +Utf8String::from(Array) faults UnicodeEncodingFault +Utf16String::from(Array) faults UnicodeEncodingFault +Utf32String::from(Array) 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. diff --git a/chapters/002-principes-generaux-du-langage.md b/chapters/002-principes-generaux-du-langage.md index 6d9a418..5adfe31 100644 --- a/chapters/002-principes-generaux-du-langage.md +++ b/chapters/002-principes-generaux-du-langage.md @@ -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. diff --git a/chapters/004-couches-de-lecosysteme-v1.md b/chapters/004-couches-de-lecosysteme-v1.md index 57b35c7..9decb3d 100644 --- a/chapters/004-couches-de-lecosysteme-v1.md +++ b/chapters/004-couches-de-lecosysteme-v1.md @@ -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 Error ResultError Exception +Fault Option Nullable Range @@ -50,10 +51,18 @@ RangeStep RangeReverse RangeReverseStep RangeProgression +PartialOrdering Ordering +Comparable +Comparator Op... Iterable Iterator +View +Collection +List +Set +Map Array StaticArray 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 diff --git a/chapters/011-tuples.md b/chapters/011-tuples.md index 30968e1..f175c44 100644 --- a/chapters/011-tuples.md +++ b/chapters/011-tuples.md @@ -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`. --- diff --git a/chapters/013-interfaces.md b/chapters/013-interfaces.md index fb892e9..f741f91 100644 --- a/chapters/013-interfaces.md +++ b/chapters/013-interfaces.md @@ -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É diff --git a/chapters/015-fonctions-methodes-et-clsmethod.md b/chapters/015-fonctions-methodes-et-clsmethod.md index dd6f68d..ee4a7c1 100644 --- a/chapters/015-fonctions-methodes-et-clsmethod.md +++ b/chapters/015-fonctions-methodes-et-clsmethod.md @@ -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 - ou Result +method elementAt(uint64 index) -> T + faults IndexOutOfBoundsFault ``` -Exemples infaillibles : +`Result` 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 ``` -Exemples faillibles : +Les combinaisons sont indépendantes : ```text -func readFile(String path) -> Result -method parse(String input) -> Result +T +T throws SomeException +T faults SomeFault +T throws SomeException faults SomeFault +Result +Result throws SomeException +Result 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. diff --git a/chapters/018-result-erreurs-et-exceptions.md b/chapters/018-result-erreurs-et-exceptions.md index 916a1d1..14d7ae2 100644 --- a/chapters/018-result-erreurs-et-exceptions.md +++ b/chapters/018-result-erreurs-et-exceptions.md @@ -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`. +```text +ResultError + échec transporté explicitement comme une valeur dans Result -`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` et non `Nullable` : 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` — V1 REQUIS — FIGÉ @@ -127,6 +141,7 @@ Sont invalides : ```text Result Result +Result Result ``` @@ -142,7 +157,7 @@ est équivalente à : Result ``` -`Result` et `Result` sont autorisés pour représenter un succès sans payload utile. `Option` reste interdit. +`Result` et `Result` sont autorisés. `Option` reste interdit. Il n'existe aucune conversion implicite de `T` vers `Result` ni de `E` vers `Result` : @@ -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 +parseExternalInput(...) -> Result ``` -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` ou `Result`. +`throws` est indépendant du type de retour. + +Sont valides : ```text -T + throws -> interdit -Result -> valide sans throws -Result + throws -> valide +T +T throws SomeException +Result +Result 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 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. + +--- diff --git a/chapters/019-controle-de-flux.md b/chapters/019-controle-de-flux.md index 59f7a84..9b759db 100644 --- a/chapters/019-controle-de-flux.md +++ b/chapters/019-controle-de-flux.md @@ -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`. diff --git a/chapters/020-operateurs.md b/chapters/020-operateurs.md index b914b82..79df1a0 100644 --- a/chapters/020-operateurs.md +++ b/chapters/020-operateurs.md @@ -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 + -> PartialOrdering + OpCompare + -> Ordering ``` -`OpCompare` renforce `OpPartialCompare` et garantit un ordre total, donc pas de `Ordering::Unordered`. +`OpCompare` 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` et `Comparator` 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 -OpIndex> -OpIndexMut +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 +``` + +`OpIndexMut` 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É diff --git a/chapters/021-strings-unicode-et-encodages.md b/chapters/021-strings-unicode-et-encodages.md index 0a9d02a..b18ef82 100644 --- a/chapters/021-strings-unicode-et-encodages.md +++ b/chapters/021-strings-unicode-et-encodages.md @@ -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É diff --git a/chapters/022-collections-et-iteration.md b/chapters/022-collections-et-iteration.md index 9cfa338..444719c 100644 --- a/chapters/022-collections-et-iteration.md +++ b/chapters/022-collections-et-iteration.md @@ -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 @@ -151,21 +151,84 @@ SettableList ResizableList ``` -`Set` et `Map` sont des branches distinctes à préciser. +`Set` et `Map` forment des branches sémantiques distinctes. -### 22.4.1 `Iterable` / `Iterator` +### 22.4.1 `Iterable` et `Iterator` -Interfaces Core reconnues par `foreach`. +`foreach` dépend uniquement de `Iterable`. -Elles ne portent pas le préfixe `Op`, car `foreach` est une construction du langage et non un opérateur symbolique. +```text +interface Iterable { + const method iterator() -> Iterator; +} +``` -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` +`Iterator` représente une itération particulière et possède un état de progression mutable : + +```text +interface Iterator { + method next() -> Option; +} +``` + +`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` rend l'état de fin explicite dans une seule opération. + +`Iterator` n'étend pas `Iterable` 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` + +`View` représente une vue légère sur une source existante : + +```text +interface View extends Iterable { + const method count() -> uint64; + const method isEmpty() -> bool; +} +``` + +`View` n'étend pas `Collection`. + +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` : + +```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` `Collection` étend `Iterable` 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` +### 22.4.4 `List` `List` étend `Collection` et `OpIndex`. @@ -193,33 +256,39 @@ Pour une `List` : 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` ne garantit ni remplacement d'un élément, ni redimensionnement, ni complexité algorithmique particulière de l'accès indexé. +`List` ne garantit ni remplacement, ni redimensionnement, ni complexité algorithmique particulière de l'accès indexé. -### 22.4.4 `SettableList` +### 22.4.5 `SettableList` `SettableList` étend `List` et `OpIndexMut`. -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` +### 22.4.6 `ResizableList` -`ResizableList` étend `SettableList`. +`ResizableList` étend `SettableList` 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`. -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 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 @@ -258,9 +327,271 @@ Vector `Vector` reste à définir précisément. -Un type persistant/immutable par nature n'a aucune obligation d'implémenter `List`. Par exemple, un futur `PersistentList` peut implémenter uniquement `Collection` 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` 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` et `ResizableSet` + +`Set` étend `Collection`. + +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 extends Set { + 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` : remplacer un élément d'un set équivaut conceptuellement à une modification structurelle de son ensemble de valeurs. + +### 22.4.10 `Map`, `SettableMap` et `ResizableMap` + +`Map` n'étend pas `Collection` 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 extends OpIndex { + const method count() -> uint64; + const method isEmpty() -> bool; + const method containsKey(const K key) -> bool; + const method get(const K key) -> Option; + + const method keys() -> View; + const method values() -> View; + const method entries() -> View>; +} +``` + +Deux intentions sont séparées : + +```text +map[key] -> V + accès strict + la clé doit exister + absence dynamique -> KeyNotFoundFault + +map::get(key) -> Option + accès conditionnel + absence normale -> None +``` + +`SettableMap` étend `Map` et `OpIndexMut`. + +```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` étend `SettableMap` 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` + +`MapEntry` représente une paire clé/valeur observée lors d'une projection `entries()`. + +Conceptuellement : + +```text +struct MapEntry { + 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` et `Comparator` + +L'ordre total applicatif utilise : + +```text +enum Ordering { + Less, + Equal, + Greater +} +``` + +`Comparable` exprime l'ordre naturel ou principal du type dans son domaine : + +```text +interface Comparable { + const method compareTo(const T other) -> Ordering; +} +``` + +Un type peut tout à fait implémenter `Comparable` 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` exprime un ordre externe/alternatif : + +```text +interface Comparator { + 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 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` et `SortedMap` + +`SortedSet` étend `Set` et garantit un ordre total stable selon le comparator actif : + +```text +interface SortedSet extends Set { + const method comparator() -> Option>; + const method first() -> Option; + const method last() -> Option; +} +``` + +`None` pour `comparator()` signifie que l'ordre naturel `Comparable` est utilisé. `Some(comparator)` expose l'ordre externe choisi pour cette instance. + +`SortedMap` étend `Map` et ordonne les entrées par clé : + +```text +interface SortedMap extends Map { + const method comparator() -> Option>; + const method firstKey() -> Option; + const method lastKey() -> Option; +} +``` + +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` et `TreeMap` + +Les types standard ordonnés généraux sont nommés : + +```text +TreeSet +TreeMap +``` + +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` 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::natural() + requiert T implements Comparable + +TreeSet::withComparator(Comparator comparator) + n'exige pas Comparable + +TreeMap::natural() + requiert K implements Comparable + +TreeMap::withComparator(Comparator comparator) + n'exige pas Comparable +``` + +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` et `Map` n'imposent pas une stratégie de stockage particulière. + +Ainsi : + +```text +HashSet / HashMap + peuvent exiger des capacités de hash/égalité + +TreeSet / TreeMap + 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` ou `Map` 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 +``` + +exprime des garanties de concurrence/atomicité et ne remplace pas `ResizableMap`. + +Un type concret peut par exemple implémenter les deux : + +```text +ConcurrentHashMap + implements ResizableMap, ConcurrentMap +``` + +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` — 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` 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` 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 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. diff --git a/chapters/024-casts-et-conversions.md b/chapters/024-casts-et-conversions.md index ee12464..9d93be3 100644 --- a/chapters/024-casts-et-conversions.md +++ b/chapters/024-casts-et-conversions.md @@ -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(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` 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` 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`. --- diff --git a/chapters/026-async-et-concurrence.md b/chapters/026-async-et-concurrence.md index d562765..6574631 100644 --- a/chapters/026-async-et-concurrence.md +++ b/chapters/026-async-et-concurrence.md @@ -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` doit exprimer des garanties de concurrence/atomicité orthogonales aux capacités structurelles `Map` / `SettableMap` / `ResizableMap`. Des types tels que `ConcurrentHashMap` ne seront introduits que lorsqu'un contrat concurrent concret le justifie. + --- diff --git a/chapters/027-memoire-references-et-unsafe.md b/chapters/027-memoire-references-et-unsafe.md index 56035dc..239f841 100644 --- a/chapters/027-memoire-references-et-unsafe.md +++ b/chapters/027-memoire-references-et-unsafe.md @@ -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`. -Les noms des types (`Ptr`, `PtrMut` 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 + 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`, `PtrMut` 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 diff --git a/chapters/028-defer-et-nettoyage.md b/chapters/028-defer-et-nettoyage.md index 0713509..89430f9 100644 --- a/chapters/028-defer-et-nettoyage.md +++ b/chapters/028-defer-et-nettoyage.md @@ -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` 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. diff --git a/chapters/041-artifacts-exports-profils-et-reservation-des-formats-futurs.md b/chapters/041-artifacts-exports-profils-et-reservation-des-formats-futurs.md index 3289d4a..988b531 100644 --- a/chapters/041-artifacts-exports-profils-et-reservation-des-formats-futurs.md +++ b/chapters/041-artifacts-exports-profils-et-reservation-des-formats-futurs.md @@ -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 ``` diff --git a/chapters/042-main-et-exitcode.md b/chapters/042-main-et-exitcode.md index f5e33c3..5ef1b86 100644 --- a/chapters/042-main-et-exitcode.md +++ b/chapters/042-main-et-exitcode.md @@ -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 diff --git a/chapters/043-documentation-et-tests-de-conformite.md b/chapters/043-documentation-et-tests-de-conformite.md index 25eb9ee..29f9e87 100644 --- a/chapters/043-documentation-et-tests-de-conformite.md +++ b/chapters/043-documentation-et-tests-de-conformite.md @@ -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é. diff --git a/chapters/048-inventaire-des-points-v1-encore-ouverts.md b/chapters/048-inventaire-des-points-v1-encore-ouverts.md index 4bfbed6..eeb7d72 100644 --- a/chapters/048-inventaire-des-points-v1-encore-ouverts.md +++ b/chapters/048-inventaire-des-points-v1-encore-ouverts.md @@ -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`, 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`, 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` et interaction avec `Slice` 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`, `Option`, `Iterator` et autres wrappers ; - String encodings ; - regex ; - filesystem/network/process ; diff --git a/chapters/051-invariants-de-conception.md b/chapters/051-invariants-de-conception.md index 4ee11fa..388a3cb 100644 --- a/chapters/051-invariants-de-conception.md +++ b/chapters/051-invariants-de-conception.md @@ -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.** --- diff --git a/examples/002-principes-generaux-du-langage-examples.md b/examples/002-principes-generaux-du-langage-examples.md index baf059f..01eedbc 100644 --- a/examples/002-principes-generaux-du-langage-examples.md +++ b/examples/002-principes-generaux-du-langage-examples.md @@ -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. diff --git a/examples/004-couches-de-lecosysteme-v1-examples.md b/examples/004-couches-de-lecosysteme-v1-examples.md index 0613e1c..9a9d8d9 100644 --- a/examples/004-couches-de-lecosysteme-v1-examples.md +++ b/examples/004-couches-de-lecosysteme-v1-examples.md @@ -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 Error ResultError Exception +Fault Option Nullable Range @@ -46,10 +47,18 @@ RangeStep RangeReverse RangeReverseStep RangeProgression +PartialOrdering Ordering +Comparable +Comparator Op... Iterable Iterator +View +Collection +List +Set +Map Array StaticArray 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 diff --git a/examples/013-interfaces-examples.md b/examples/013-interfaces-examples.md index 463d634..4425cfe 100644 --- a/examples/013-interfaces-examples.md +++ b/examples/013-interfaces-examples.md @@ -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 ``` diff --git a/examples/015-fonctions-methodes-et-clsmethod-examples.md b/examples/015-fonctions-methodes-et-clsmethod-examples.md index 05f6ac7..8218a34 100644 --- a/examples/015-fonctions-methodes-et-clsmethod-examples.md +++ b/examples/015-fonctions-methodes-et-clsmethod-examples.md @@ -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 - ou Result +T +T throws SomeException +T faults SomeFault +T throws SomeException faults SomeFault +Result +Result throws SomeException +Result 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 -method parse(String input) -> Result +func parseExternalInput(String input) -> Result ``` +`Result` reste utilisé lorsque l'échec doit être transporté comme une valeur. + ### Exemple 5 ```text diff --git a/examples/018-result-erreurs-et-exceptions-examples.md b/examples/018-result-erreurs-et-exceptions-examples.md index d690ea4..31e9129 100644 --- a/examples/018-result-erreurs-et-exceptions-examples.md +++ b/examples/018-result-erreurs-et-exceptions-examples.md @@ -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 -i18nMessage: Option -``` - -### 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 -Result -Result -``` - -### Exemple 11 - -```text -Result -Result -Result -``` - -### Exemple 12 - -```text -Result -``` - -### Exemple 13 - -```text -Result -``` - -### 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 -> valide sans throws -Result + 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 { + ... } ``` -### Exemple 24 +DON'T : placer une `Exception` ou un `Fault` dans le paramètre erreur de `Result`. ```text -try { ... } -try { ... } finally { ... } -finally { ... } +Result // ERROR +Result // 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 = 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 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(...); +} +``` diff --git a/examples/020-operateurs-examples.md b/examples/020-operateurs-examples.md index 7785f57..6527413 100644 --- a/examples/020-operateurs-examples.md +++ b/examples/020-operateurs-examples.md @@ -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 -OpIndex> +OpIndex OpIndexMut + +map[key] // strict, absent -> KeyNotFoundFault +map::get(key) // Option ``` ### Exemple 16 diff --git a/examples/021-strings-unicode-et-encodages-examples.md b/examples/021-strings-unicode-et-encodages-examples.md index cf306cf..a57b257 100644 --- a/examples/021-strings-unicode-et-encodages-examples.md +++ b/examples/021-strings-unicode-et-encodages-examples.md @@ -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() ``` diff --git a/examples/022-collections-et-iteration-examples.md b/examples/022-collections-et-iteration-examples.md index dd6e70e..0503a79 100644 --- a/examples/022-collections-et-iteration-examples.md +++ b/examples/022-collections-et-iteration-examples.md @@ -158,7 +158,82 @@ Vector ResizableList ``` -### Exemple 18 +### Exemple 18 — `Iterator` + +```text +interface Iterable { + const method iterator() -> Iterator; +} + +interface Iterator { + method next() -> Option; +} +``` + +### Exemple 19 — `View` + +```text +interface View extends Iterable { + const method count() -> uint64; + const method isEmpty() -> bool; +} +``` + +`View` n'impose pas `contains()`. + +### Exemple 20 — Set + +```text +ResizableSet::add(T value) -> bool +ResizableSet::remove(const T value) -> bool +ResizableSet::clear() -> uint64 +``` + +### Exemple 21 — Map + +```text +map[key] -> V // strict +map::get(key) -> Option // 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 +map::values() -> View +map::entries() -> View> +``` + +### Exemple 23 — Ordre + +```text +enum Ordering { + Less, + Equal, + Greater +} + +Comparable +Comparator +SortedSet +SortedMap +``` + +### Exemple 24 — Factories ordonnées + +```text +TreeSet::natural() +TreeSet::withComparator(comparator) + +TreeMap::natural() +TreeMap::withComparator(comparator) +``` + +## Exemples Range ```text a..b [a, b] bornes basse et haute incluses @@ -167,13 +242,13 @@ a.... 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.... intervalle ordonné @@ -213,13 +288,13 @@ RangeReverseStep parcours arrière avec pas explicite RangeProgression valeur de progression produite ``` -### Exemple 24 +### Range 6 ```text (range)::step(step) ``` -### Exemple 25 +### Range 7 ```text RangeStep @@ -228,14 +303,14 @@ RangeStep RangeStep ``` -### 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 @@ -269,4 +344,4 @@ range ## DO / DON'T / WHY / compiler error / edge cases -À consolider progressivement avant la baseline publique V3 et à transformer, lorsque pertinent, en tests de conformité de la toolchain. +À consolider progressivement avant la baseline publique V3 et à transformer, lorsque pertinent, en tests de conformité de la toolchain. \ No newline at end of file diff --git a/examples/024-casts-et-conversions-examples.md b/examples/024-casts-et-conversions-examples.md index 275f035..79b0caf 100644 --- a/examples/024-casts-et-conversions-examples.md +++ b/examples/024-casts-et-conversions-examples.md @@ -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 ``` -### 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`. diff --git a/examples/026-async-et-concurrence-examples.md b/examples/026-async-et-concurrence-examples.md index 75bd846..da66194 100644 --- a/examples/026-async-et-concurrence-examples.md +++ b/examples/026-async-et-concurrence-examples.md @@ -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 ``` diff --git a/examples/027-memoire-references-et-unsafe-examples.md b/examples/027-memoire-references-et-unsafe-examples.md index 4951cac..1979659 100644 --- a/examples/027-memoire-references-et-unsafe-examples.md +++ b/examples/027-memoire-references-et-unsafe-examples.md @@ -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 +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. diff --git a/examples/028-defer-et-nettoyage-examples.md b/examples/028-defer-et-nettoyage-examples.md index 6942a50..56e15cc 100644 --- a/examples/028-defer-et-nettoyage-examples.md +++ b/examples/028-defer-et-nettoyage-examples.md @@ -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. diff --git a/examples/041-artifacts-exports-profils-et-reservation-des-formats-futurs-examples.md b/examples/041-artifacts-exports-profils-et-reservation-des-formats-futurs-examples.md index 4c63d07..aa49295 100644 --- a/examples/041-artifacts-exports-profils-et-reservation-des-formats-futurs-examples.md +++ b/examples/041-artifacts-exports-profils-et-reservation-des-formats-futurs-examples.md @@ -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 ```