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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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