This commit is contained in:
2026-09-12 19:31:05 +02:00
parent 57ae671f88
commit fd4e879c0c
20 changed files with 1232 additions and 255 deletions

View File

@@ -2,39 +2,22 @@
## 21.1 `String` — V1 REQUIS — FIGÉ EN PRINCIPE
`String` est le type ordinaire de texte Unicode.
`String` est le type ordinaire de texte Unicode au niveau sémantique.
La représentation interne peut varier suivant le backend/target, mais la sémantique observable doit rester identique.
Sa valeur observable est une séquence de Unicode scalar values.
## 21.2 Encodages explicites — V1 REQUIS — DIRECTION FIGÉE
La représentation physique interne peut varier suivant le backend/target, sans devenir observable via l'API sémantique de `String`.
Les encodages explicites appartiennent au SDK, pas au langage :
`String` est mutable par défaut lorsque son API expose des opérations mutantes contrôlées.
```text
Utf8String
Utf16String
Utf32String
AsciiString éventuel
Bytes
String text = "abc";
text::append("def"); // OK
```
Les conversions avec `String` doivent être explicites et définies.
Un accès `const String` interdit les mutations via cet accès selon les règles générales de `const`.
## 21.3 Indexation String — V1 REQUIS — À FINALISER
Il faut décider avant V1 ce que signifie l'accès au texte :
```text
byte
code unit
Unicode scalar
code point
grapheme cluster
```
Ne pas déclarer implicitement `String : OpIndex<uint64,char>` avant cette décision.
## 21.4 `char` — V1 REQUIS — FIGÉ
## 21.2 `char` — V1 REQUIS — FIGÉ
`char` représente exactement un Unicode scalar value, et non un octet, une unité UTF-8/UTF-16 ou un grapheme utilisateur complet.
@@ -49,13 +32,251 @@ Exemples valides :
'\u{1F600}'
```
Après traitement des escapes, un littéral `char` doit contenir exactement un scalar. `''`, `'ab'` ou une séquence produisant plusieurs scalars sont invalides.
Après traitement des escapes, un littéral `char` doit contenir exactement un scalar.
Saselang n'effectue aucune normalisation Unicode implicite des littéraux ; NFC/NFD et autres transformations relèvent d'opérations explicites de bibliothèque.
Saselang n'effectue aucune normalisation Unicode implicite.
## 21.5 Familles de littéraux texte — V1 REQUIS / RÉSERVÉ
## 21.3 Types encodés Core — V1 REQUIS — DIRECTION FIGÉE
Les familles suivantes sont reconnues ou réservées parce qu'elles représentent des sémantiques distinctes et non des alias gratuits :
Le Core fournit les types encodés explicites :
```text
Utf8Char
Utf16Char
Utf32Char
Utf8String
Utf16String
Utf32String
```
Ils ne sont ni des alias ni des sous-classes de `String`/`char`.
Ils expriment explicitement l'encodage utilisé.
```text
Utf8Char
exactement un Unicode scalar encodé en UTF-8
1 à 4 uint8
Utf16Char
exactement un Unicode scalar encodé en UTF-16
1 à 2 uint16
Utf32Char
exactement un Unicode scalar encodé en UTF-32
1 uint32
```
```text
Utf8String
séquence UTF-8 valide
Utf16String
séquence UTF-16 valide
Utf32String
séquence UTF-32 valide
```
Toute valeur de ces types maintient son invariant d'encodage.
Les code units brutes restent :
```text
UTF-8 -> uint8
UTF-16 -> uint16
UTF-32 -> uint32
```
Aucun `Utf8CodeUnit` / `Utf16CodeUnit` / `Utf32CodeUnit` distinct n'est introduit tant qu'un besoin sémantique réel n'est pas démontré.
## 21.4 Conversions Unicode — V1 REQUIS — FIGÉ EN PRINCIPE
Aucun transcodage implicite n'existe.
Les conversions totales utilisent `to...`.
Les constructions ou réductions pouvant échouer utilisent `tryFrom...` / `tryTo...`.
Exemples :
```text
char::toUtf8Char()
Utf8Char::toChar()
Utf8Char::toUtf16Char()
Utf8Char::tryFrom(uint8)
Utf16Char::tryFrom(uint16)
Utf32Char::tryFrom(uint32)
Utf8Char::tryToUint8()
Utf16Char::tryToUint16()
Utf32Char::toUint32()
```
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É
Une API textuelle n'effectue jamais un transcodage implicite de son argument.
```text
Utf8String text = ...;
Utf16Char value = ...;
text::append(value); // ERROR
text::append(value::toUtf8Char()); // OK
```
Même règle pour concaténation, insertion, remplacement, recherche typée et construction.
Les conversions sont effectuées explicitement avant l'opération métier.
## 21.6 Indexation — V1 REQUIS — FIGÉ
`String` n'implémente pas `OpIndex`.
```text
String text = ...;
text[5]; // ERROR
```
Son unité logique est explicitement nommée :
```text
text::scalarAt(index) -> char
text::scalarCount() -> uint64
```
Les strings encodées peuvent exposer `[]` en lecture pour leurs code units physiques :
```text
Utf8String[index] -> uint8
Utf16String[index] -> uint16
Utf32String[index] -> uint32
```
Elles n'exposent pas `OpIndexMut`, afin qu'une écriture brute ne puisse pas casser l'invariant d'encodage.
## 21.7 Accès scalar et caractère encodé — V1 REQUIS — FIGÉ EN PRINCIPE
Pour un `UtfXString` :
```text
encodedCharAt(scalarIndex)
retourne le UtfXChar correspondant au scalar ordinal demandé
scalarAt(scalarIndex)
retourne le char correspondant
```
Exemples :
```text
Utf8String::encodedCharAt(uint64) -> Utf8Char
Utf16String::encodedCharAt(uint64) -> Utf16Char
Utf32String::encodedCharAt(uint64) -> Utf32Char
Utf8String::scalarAt(uint64) -> char
Utf16String::scalarAt(uint64) -> char
Utf32String::scalarAt(uint64) -> char
```
Un index de code unit et un ordinal de scalar sont des concepts distincts.
Une API de décodage depuis un offset de code unit peut exister explicitement. En UTF-8/UTF-16, elle est faillible lorsqu'un offset peut pointer au milieu d'une séquence encodée.
Le nom exact de cette API reste à stabiliser avec les vues/slices.
## 21.8 Comptage — V1 REQUIS — FIGÉ
`String` expose :
```text
scalarCount()
```
Les strings encodées distinguent :
```text
codeUnitCount()
scalarCount()
```
Ces deux propriétés restent distinctes même lorsqu'elles coïncident systématiquement dans UTF-32, car elles décrivent deux unités sémantiques différentes.
## 21.9 Itération — V1 REQUIS — FIGÉ EN PRINCIPE
`String` possède une unité sémantique non ambiguë :
```text
String implements Iterable<char>
```
Pour `Utf8String`, `Utf16String` et `Utf32String`, plusieurs parcours utiles existent :
```text
code units
encoded chars
Unicode scalars
```
Aucun `Iterable<T>` direct unique n'est imposé aux strings encodées en V1.
Les parcours sont explicites :
```text
codeUnits()
encodedChars()
scalars()
```
Le type concret de vue/itérateur retourné sera fixé avec les collections et slices.
## 21.10 Mutation contrôlée — V1 REQUIS — FIGÉ
`String` et `UtfXString` ne sont pas intrinsèquement immutables.
Ils peuvent exposer des méthodes mutantes contrôlées.
```text
String text = "abc";
text::append("def");
```
Après l'appel, `text` contient la valeur modifiée selon le contrat de `append`.
Pour les strings encodées, toute méthode mutante doit préserver l'invariant d'encodage.
```text
Utf8String text = ...;
Utf8Char value = ...;
text::append(value); // OK
```
Une mutation brute de code unit reste interdite :
```text
text[index] = 0xFF; // ERROR
```
Un accès `const` désactive les opérations mutantes via cet accès, sans rendre globalement immutable l'objet partagé.
## 21.11 Comparaison et normalisation — V1 REQUIS — FIGÉ EN PRINCIPE
Aucune normalisation Unicode, case folding ou collation linguistique n'est implicite.
Deux `String` sont égales selon leur séquence sémantique exacte de Unicode scalars.
Des textes visuellement équivalents mais composés de séquences différentes peuvent donc être différents.
Les normalisations NFC/NFD, case folding, grapheme segmentation et collations localisées relèvent d'API explicites Core/SDK à détailler.
## 21.12 Familles de littéraux texte — V1 REQUIS / RÉSERVÉ
Les familles suivantes sont reconnues ou réservées parce qu'elles représentent des sémantiques distinctes :
```text
"..." String normale, escapes actifs
@@ -75,96 +296,49 @@ cr"..." chaîne C brute, réservé
t"..." template structuré, réservé
```
V1 doit au minimum couvrir les formes normales, multilignes, raw et interpolées. Les formes bytes, encodages explicites, C string, template et certaines combinaisons peuvent être implémentées en V2 mais leur espace lexical est réservé dès V1.
V1 doit au minimum couvrir les formes normales, multilignes, raw et interpolées.
Les préfixes de littéraux ne sont pas nécessairement des mots-clés globaux : ils sont reconnus comme préfixes lorsqu'ils sont immédiatement contigus au délimiteur correspondant.
Le délimiteur interne de l'interpolation reste à finaliser entre les formes déjà inventoriées.
Les combinaisons de préfixes ne sont pas arbitraires. Une matrice normative ultérieure doit classer chaque combinaison comme `supported`, `reserved` ou `forbidden/meaningless`, et retenir une seule orthographe canonique par combinaison. Des doublons tels que `ir` et `ri` pour une même sémantique ne coexistent pas.
## 21.13 Chaînes multilignes — V1 REQUIS — FIGÉ
La forme interpolée `i"..."` est réservée, mais le délimiteur interne de l'expression reste **V1 REQUIS — À FINALISER** entre :
```text
i"Hello {name}"
i"Hello ${name}"
```
Une seule de ces deux formes sera retenue comme syntaxe canonique. Une `String` non préfixée n'interprète jamais ces séquences comme interpolation.
## 21.6 Chaînes multilignes — V1 REQUIS — FIGÉ
Les triples quotes fournissent la forme multiligne :
```text
"""
first
second
"""
```
Les triples quotes fournissent la forme multiligne.
Le délimiteur de fermeture détermine l'indentation structurelle à retirer de chaque ligne. Une indentation supplémentaire volontaire dans le contenu est conservée.
Lorsque `"""` d'ouverture est immédiatement suivi d'un retour à la ligne, ce premier retour structurel n'appartient pas à la valeur. Lorsque le délimiteur de fermeture se trouve seul après l'indentation structurelle d'une nouvelle ligne, le dernier retour structurel est également supprimé.
La même règle de lignes et d'indentation s'applique aux variantes normales, raw et interpolées. Le caractère raw ou interpolé modifie le traitement du contenu, pas la structure multiligne.
Lorsque le délimiteur d'ouverture multiligne est immédiatement suivi d'un retour à la ligne, ce premier retour structurel n'appartient pas à la valeur. Lorsque le délimiteur de fermeture se trouve seul après l'indentation structurelle d'une nouvelle ligne, le dernier retour structurel est également supprimé.
Le formatter peut réindenter la structure source uniquement en préservant exactement la valeur sémantique du littéral.
## 21.7 Raw strings et délimiteurs — V1 REQUIS — FIGÉ
## 21.14 Raw strings et escapes — V1 REQUIS — FIGÉ
La forme raw utilise un préfixe `r` contigu et peut employer zéro ou plusieurs `#` comme partie du délimiteur :
Les raw strings utilisent `r` contigu et peuvent employer zéro ou plusieurs `#` dans leur délimiteur.
Aucun escape n'est interprété dans le contenu raw.
Dans les `String` normales et les `char`, l'ensemble canonique reste :
```text
r"simple"
r#"He said "hello"."#
r##"contains "# inside"##
\\
\"
\'
\n
\r
\t
\0
\u{...}
```
La fermeture reprend exactement le même nombre de `#` que l'ouverture. Aucun escape n'est interprété dans le contenu raw.
`\u{...}` contient de 1 à 6 chiffres hexadécimaux, n'accepte pas `_`, doit être inférieur ou égal à `0x10FFFF` et ne peut pas désigner la plage surrogate UTF-16.
La même mécanique est disponible pour les triples quotes :
`\xNN` reste réservé aux littéraux orientés octets.
```text
r"""..."""
r#"""..."""#
```
## 21.15 Source Unicode et représentation — V1 REQUIS — FIGÉ EN PRINCIPE
Les `#` appartiennent au délimiteur lexical et ne sont pas des escapes. Les variantes combinées réservées telles que `ir`, `br` ou `cr` suivent le même principe lorsqu'elles seront activées.
Le fichier source UTF-8 peut contenir directement des scalars Unicode valides dans `String`, `char`, commentaires et Saseldoc.
Une borne d'implémentation raisonnable au nombre de `#` peut être imposée, à condition d'être documentée et diagnostiquée explicitement ; cette borne n'est pas encore normative.
Une séquence UTF-8 invalide est une erreur de source.
`raw` est une propriété lexicale et ne change pas à elle seule le type résultat.
## 21.8 Escapes normaux — V1 REQUIS — FIGÉ
Dans les `String` normales et les `char`, l'ensemble canonique est :
```text
\\ backslash
\" double quote
\' single quote
\n newline
\r carriage return
\t horizontal tab
\0 NUL
\u{...} Unicode scalar
```
`\u{...}` contient de 1 à 6 chiffres hexadécimaux, n'accepte pas `_`, doit être inférieur ou égal à `0x10FFFF` et ne peut pas désigner la plage surrogate UTF-16 `0xD800..0xDFFF`.
Saselang n'introduit pas les alias historiques redondants `\uXXXX`, `\UXXXXXXXX`, les escapes octaux ou les control aliases C rares lorsque `\u{...}` couvre déjà leur besoin.
`\xNN` est réservé aux littéraux orientés octets, notamment `b"..."`, où il représente exactement un octet avec exactement deux chiffres hexadécimaux :
```text
b"\x00\x7f\x80\xff"
```
`\xNN` est interdit dans une `String` Unicode normale et dans `char`.
## 21.9 Unicode et représentation — V1 REQUIS — FIGÉ EN PRINCIPE
Le fichier source UTF-8 peut contenir directement des scalars Unicode valides dans `String`, `char`, commentaires et Saseldoc. Une séquence UTF-8 invalide est une erreur de source ; le compilateur ne la répare pas silencieusement.
La représentation physique interne de `String` reste indépendante de cette syntaxe source et peut varier selon backend/target conformément à la section 21.1.
La représentation physique interne de `String` reste indépendante de cette syntaxe source et peut varier suivant backend/target.
---