v0.2.18
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
# Bible Saselang 0.2.17
|
||||
# Bible Saselang 0.2.18
|
||||
|
||||
> **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.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.
|
||||
> **Révision 0.2.18 :** fermeture de `Vector<T>` / `Slice<T>` autour d’un backing storage stable, fixation de l’API et des complexités de `Vector`, introduction des contrats Core `Equatable<T>`, `Hashable` et `Hasher`, fermeture de `HashSet<T>` / `HashMap<K,V>` et de leurs builders, et renommage de l’identité universelle d’objet en `Object::sameIdentity(...)`.
|
||||
|
||||
## Organisation de cette distribution
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Sommaire — Bible Saselang 0.2.17
|
||||
# Sommaire — Bible Saselang 0.2.18
|
||||
|
||||
## Chapitres
|
||||
|
||||
|
||||
@@ -1,4 +1,27 @@
|
||||
# Changelog documentaire — 0.2.17
|
||||
# Changelog documentaire — 0.2.18
|
||||
|
||||
## 0.2.18
|
||||
|
||||
- `Vector<T>` fermé comme `ResizableList<T>` contigu à longueur runtime dynamique, avec `append`, `insert`, `removeAt`, `clear`, `capacity`, `reserve` et `slice` ;
|
||||
- `Vector::append(T) -> Void` figé ; `insert(index,value)` accepte `0 <= index <= length()` et produit `IndexOutOfBoundsFault` au-delà ;
|
||||
- `Vector::removeAt(index) -> T` figé avec `IndexOutOfBoundsFault` pour un index invalide ;
|
||||
- garanties de complexité de `Vector` figées : indexation O(1), cardinalité O(1), append O(1) amorti, insert/removeAt O(n), slice O(1), capacity O(1), reserve O(n) au pire ;
|
||||
- aucun `reserveExact`, `resize` implicite ni opération générale de shrink dans le contrat standard de `Vector` ;
|
||||
- construction dynamique explicite par class methods/factories et `VectorBuilder<T>` ; le littéral `[...]` reste réservé aux arrays contextualisés ;
|
||||
- backing storage stable retenu dès V1 pour `Vector`/`Slice` : une relocalisation physique, `reserve`, un remplacement d’élément ou `append` ne rendent pas les slices existantes invalides ;
|
||||
- en V1, `insert`, `removeAt` et un `clear` effectif invalident toutes les slices dérivées du vector ; un accès ultérieur produit `SliceInvalidatedFault` ;
|
||||
- `Equatable<T>` introduit comme capacité Core réutilisant le contrat opérateur canonique `OpEqual<T>` sans seconde implémentation de l’égalité ;
|
||||
- `Object::sameInstance(...)` renommé en `Object::sameIdentity(...)` pour distinguer explicitement identité de référence et égalité logique ;
|
||||
- `Hashable` fixé dans le Core avec stabilité normative de l’identité hashable pendant toute la durée de vie de la valeur ;
|
||||
- `Hasher` fixé dans le Core ; ses implémentations concrètes restent des implémentations SDK/runtime ;
|
||||
- contrat minimal `Hasher::writeBytes(const Slice<uint8>)` + `finish() -> uint64`, avec framing canonique Core des valeurs fondamentales et `finish()` non mutateur ;
|
||||
- `HashSet<T>` et `HashMap<K,V>` fermés comme implémentations SDK non ordonnées exigeant respectivement `T` ou `K` `Equatable + Hashable` ;
|
||||
- collisions de hash définies comme normales et résolues par l’égalité ; aucune `HashCollisionFault` ;
|
||||
- hasher/seed internes des collections hashées non contractuels et potentiellement différents entre instances ; ordre d’itération non stable/non garanti ;
|
||||
- `ResizableMap::remove(key)` retourne désormais `V` et reste strict avec `KeyNotFoundFault` ;
|
||||
- builders `Vector`, `HashSet` et `HashMap` mutables, chaînables, non consommés par `build()` et produisant des résultats sémantiquement indépendants ;
|
||||
- un doublon dans `HashSetBuilder` suit la sémantique idempotente du set ; une clé dupliquée dans `HashMapBuilder` produit `DuplicateKeyFault` ;
|
||||
- la sémantique flottante de cette révision référence explicitement IEEE 754-2019, standard actif au moment de la révision ; une future norme finale devra être adoptée explicitement par une révision de Saselang.
|
||||
|
||||
## 0.2.17
|
||||
|
||||
|
||||
126
MANIFEST.toml
126
MANIFEST.toml
@@ -1,153 +1,77 @@
|
||||
format = 1
|
||||
version = "0.2.17"
|
||||
version = "0.2.18"
|
||||
distribution = "delta"
|
||||
base_version = "0.2.16"
|
||||
base_version = "0.2.17"
|
||||
documentation_layout = "multifile"
|
||||
|
||||
[[modified]]
|
||||
path = "000-README.md"
|
||||
sha256 = "ca87a3caaadb1a618f0a35620a2e62e406bd8e186de0a7282e606a38f9f541ca"
|
||||
sha256 = "176b7c95eafc357841a753cbac3a2d2933ec4cd40a4fcb060ec766981b81d178"
|
||||
|
||||
[[modified]]
|
||||
path = "001-SUMMARY.md"
|
||||
sha256 = "88f6f80b7233900491f15d818cebbfdb3fc83f02667cfa137cb3ed6a17f86edf"
|
||||
sha256 = "7265b8ca2ea8755b62047afcc26f4408e1bf4bdf3c0b834b045c95a1a001bbb0"
|
||||
|
||||
[[modified]]
|
||||
path = "003-CHANGELOG.md"
|
||||
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"
|
||||
sha256 = "38042709f038f5360c8c0c41d1e76b97c383e1523b9a78dadb7bf4662b340e74"
|
||||
|
||||
[[modified]]
|
||||
path = "chapters/004-couches-de-lecosysteme-v1.md"
|
||||
sha256 = "18c0b82d5b2b55dab17a2197dc2635d1d050ac4b06b6c3fc1dc34e12e5978bb6"
|
||||
sha256 = "973f4ff576db0ff79413f9b985bd6d65347a2e50c22d65cc7a4348de89f97120"
|
||||
|
||||
[[modified]]
|
||||
path = "chapters/011-tuples.md"
|
||||
sha256 = "8008f930e37a69980ccf39af0261d5af63efb136268c4793e1899da1fc58a523"
|
||||
path = "chapters/005-types-primitifs.md"
|
||||
sha256 = "d38450bec6c610be74df86745e6d8bd58e1b14162f51f27ccbab1ae633faa115"
|
||||
|
||||
[[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"
|
||||
path = "chapters/008-classes-et-object.md"
|
||||
sha256 = "aa69f6a580aea1669ea74e35f6d45385be1a653751312e774ecec61d9ffb35bb"
|
||||
|
||||
[[modified]]
|
||||
path = "chapters/020-operateurs.md"
|
||||
sha256 = "59119759c87babc9dc0d852fcdfcda6d527fcb475c6c22d26cd0fe546d50f0df"
|
||||
|
||||
[[modified]]
|
||||
path = "chapters/021-strings-unicode-et-encodages.md"
|
||||
sha256 = "c8e5ea1e1fce5fe3128d7dd1eb73ddd784b71d3fa24298de9bfabc1d44e05327"
|
||||
sha256 = "4275630a72c6059efdf030cd487f248d429a02464e908f396a7c69724072e23a"
|
||||
|
||||
[[modified]]
|
||||
path = "chapters/022-collections-et-iteration.md"
|
||||
sha256 = "e7459c2db8d0fe0cdf573d25f888c1791b6d03a9de6f51ae849991039abc4328"
|
||||
|
||||
[[modified]]
|
||||
path = "chapters/024-casts-et-conversions.md"
|
||||
sha256 = "e6cd16e5e4b65c2f05bac57a5410cb7aaa74253d2572f969b4fcf1dbf3618e93"
|
||||
|
||||
[[modified]]
|
||||
path = "chapters/026-async-et-concurrence.md"
|
||||
sha256 = "65ab9ddcfa155130daf913d9f24ebf8583fca92e3fbd4325d3b5ef86729b998a"
|
||||
sha256 = "bb233a14375151b08d1a6d3394d5797b5e64903cc18d9fa51a3a2a7592658c24"
|
||||
|
||||
[[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"
|
||||
sha256 = "c55125c1b827ee54190f01ca1fe9a348e32f82c817fe77a932f3a0cf300b92fc"
|
||||
|
||||
[[modified]]
|
||||
path = "chapters/048-inventaire-des-points-v1-encore-ouverts.md"
|
||||
sha256 = "908856acb0472c2c4eee3d03b8260f21b5b6495d342053f371b00e54158ed2d1"
|
||||
sha256 = "9a149609581e1b6e98a138cce73f600d95922e5751efd776298d47eb18ff3b6a"
|
||||
|
||||
[[modified]]
|
||||
path = "chapters/051-invariants-de-conception.md"
|
||||
sha256 = "c41f6c977c613631147b7d61c837afccc9b1c6807d62ade8175865f5108bf915"
|
||||
|
||||
[[modified]]
|
||||
path = "examples/002-principes-generaux-du-langage-examples.md"
|
||||
sha256 = "42b5758d733563c0bdabad9f6005f5818ccb42513e599bc878142db6b4298e10"
|
||||
sha256 = "fd127aee2790e6a82c8689df69c9cdf5f51875e393145998c55ab2d65177ebd3"
|
||||
|
||||
[[modified]]
|
||||
path = "examples/004-couches-de-lecosysteme-v1-examples.md"
|
||||
sha256 = "2731f6e5861d041801bf831a936c59c6df854ac55b858500e32542e64105bb8a"
|
||||
sha256 = "34272a034167db417de5c795deb8714b62cf4dfc392cac547d206e905ad59581"
|
||||
|
||||
[[modified]]
|
||||
path = "examples/013-interfaces-examples.md"
|
||||
sha256 = "2338543b0551c291dea59ebbd394a35d9e560d817b9e2d92eaa62c02d6ee3bd0"
|
||||
path = "examples/005-types-primitifs-examples.md"
|
||||
sha256 = "999b1536e6ccbb69d157d06b0422466cd245038303442c3a573f61ab38e675db"
|
||||
|
||||
[[modified]]
|
||||
path = "examples/015-fonctions-methodes-et-clsmethod-examples.md"
|
||||
sha256 = "0760c83e732d77942b48339135a146d98a60f6dd2c60fc06bc8b093fdf026058"
|
||||
|
||||
[[modified]]
|
||||
path = "examples/018-result-erreurs-et-exceptions-examples.md"
|
||||
sha256 = "47f50de6f6bf327e9f00de9a5a4e9470839d6e5e4d0ee570e432441d2924c6bb"
|
||||
path = "examples/008-classes-et-object-examples.md"
|
||||
sha256 = "af4c3b04ac3f3874e9e06835fc30577bb0d321d8d543d5910fb62821878e2a28"
|
||||
|
||||
[[modified]]
|
||||
path = "examples/020-operateurs-examples.md"
|
||||
sha256 = "717035959ea34130d7eeed2af8d3945afb10772b3015f6031c4462494076fec3"
|
||||
|
||||
[[modified]]
|
||||
path = "examples/021-strings-unicode-et-encodages-examples.md"
|
||||
sha256 = "6ed3cd078599b329b5f8f42ceda323eadc954f3d7d566e177adca56451a2345b"
|
||||
sha256 = "9341bb4943ce02f0dca5aa7bd7da9efc096bcc109c478f9305b0efccba905950"
|
||||
|
||||
[[modified]]
|
||||
path = "examples/022-collections-et-iteration-examples.md"
|
||||
sha256 = "f3546d35335937506044a697ff1610da20823bf29334c307d6cf7a53122d8ce3"
|
||||
|
||||
[[modified]]
|
||||
path = "examples/024-casts-et-conversions-examples.md"
|
||||
sha256 = "47a4d0e0e7fd822995be140d62432f48642da237d026551fc922f011776d1b8b"
|
||||
|
||||
[[modified]]
|
||||
path = "examples/026-async-et-concurrence-examples.md"
|
||||
sha256 = "0a206a6b7ee2818a1e743b0dc1a033b27ebd75f543b9979d9c7fa37150c30255"
|
||||
sha256 = "3a7adefa465732c9aac025522d6db8f120fd7614fb77d528b80267b52885b7d1"
|
||||
|
||||
[[modified]]
|
||||
path = "examples/027-memoire-references-et-unsafe-examples.md"
|
||||
sha256 = "acadba49f317caa4805e8770c5732a029071559921a6c0a05281cfb026ef98e6"
|
||||
sha256 = "edc7139b7b130ee4c6e50a8af5d81dbdad93eec03ba682ce4822b26168f5d235"
|
||||
|
||||
[[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"
|
||||
path = "profiles/language-core.md"
|
||||
sha256 = "698595f3b0b703cb981ea153e94e8e444c1f04efdd3a908a79901fd9dfa65401"
|
||||
|
||||
@@ -55,6 +55,9 @@ PartialOrdering
|
||||
Ordering
|
||||
Comparable<T>
|
||||
Comparator<T>
|
||||
Equatable<T>
|
||||
Hashable
|
||||
Hasher
|
||||
Op...
|
||||
Iterable<T>
|
||||
Iterator<T>
|
||||
@@ -65,6 +68,7 @@ Set<T>
|
||||
Map<K,V>
|
||||
Array<T>
|
||||
StaticArray<T,N>
|
||||
Slice<T>
|
||||
TypeInfo
|
||||
ExitCode
|
||||
```
|
||||
@@ -80,7 +84,8 @@ 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 concrètes/spécialisées au-delà des contrats fondamentaux Core
|
||||
collections concrètes/spécialisées au-delà des contrats fondamentaux Core (`Vector`, `HashSet`, `HashMap`, `TreeSet`, `TreeMap`, etc.)
|
||||
implémentations concrètes de `Hasher` et stratégies de hashing
|
||||
encodages explicites
|
||||
regex
|
||||
filesystem
|
||||
@@ -95,6 +100,8 @@ plateforme
|
||||
|
||||
Le découpage exact Core/SDK doit être finalisé avant gel de l'API V1.
|
||||
|
||||
Le principe retenu est que le Core porte les **contrats** devant être connus de manière générale (`Hashable`, `Hasher`, interfaces de collections, arrays/slices fondamentaux), tandis que le SDK porte les implémentations concrètes qui n'ont pas besoin d'une connaissance spéciale du compilateur, notamment `Vector<T>`, `HashSet<T>`, `HashMap<K,V>` et les hashers concrets.
|
||||
|
||||
## 4.4 Bibliothèques officielles `.saselib` — DIRECTION FIGÉE
|
||||
|
||||
Au-delà du Core et du SDK, l'écosystème Saselang peut fournir des familles de bibliothèques officielles distribuées au format `.saselib`.
|
||||
|
||||
@@ -114,7 +114,13 @@ Le modulo euclidien sera une opération explicite du Core/SDK.
|
||||
|
||||
## 5.6 Floats — V1 REQUIS — À FINALISER
|
||||
|
||||
La sémantique flottante suit IEEE pour les représentations et opérations applicables. Les littéraux sont arrondis vers le type flottant cible selon les règles IEEE normales ; Saselang n'exige pas qu'un littéral décimal soit représentable exactement.
|
||||
La sémantique flottante suit le standard IEEE 754 normatif explicitement adopté par la révision de Saselang concernée. Une nouvelle révision d'IEEE 754 ne modifie jamais silencieusement une version déjà publiée de Saselang : elle doit être adoptée explicitement par une révision ultérieure de la spécification.
|
||||
|
||||
Pour la révision `0.2.18`, la référence normative est **IEEE 754-2019**, standard actif le plus récent au moment de cette révision. Un projet de révision futur ne remplace pas cette référence tant qu'un nouveau standard final n'a pas été publié puis explicitement adopté.
|
||||
|
||||
Les littéraux sont arrondis vers le type flottant cible selon les règles IEEE applicables ; Saselang n'exige pas qu'un littéral décimal soit représentable exactement.
|
||||
|
||||
Les comparaisons flottantes conservent notamment les propriétés IEEE applicables : `NaN == NaN` est faux et `+0.0 == -0.0` est vrai. Les types `float*` relèvent donc de l'égalité partielle générale et ne satisfont pas directement la relation réflexive requise par `Equatable<float*>`.
|
||||
|
||||
Les règles de conversion, `NaN`, infinities et zéros signés déjà figées sont détaillées au chapitre 24 et dans l'annexe `A-numeric-conversions.md`. Les règles restantes des opérations flottantes, notamment division par zéro et comportement de `%`, doivent encore être fermées avant implémentation finale.
|
||||
|
||||
|
||||
@@ -62,12 +62,12 @@ Ils relèvent de la grammaire et ne sont pas surchargeables.
|
||||
`Object` fournit une opération intrinsèque non overridable :
|
||||
|
||||
```text
|
||||
Object::sameInstance(Object other) -> bool
|
||||
const method sameIdentity(const Object other) -> bool
|
||||
```
|
||||
|
||||
Elle teste l'identité d'instance, c'est-à-dire si deux références désignent exactement le même objet.
|
||||
Cette méthode intrinsèque non overridable, portée par `Object`, teste l’identité de référence : deux accès sont identiques s’ils désignent exactement le même objet.
|
||||
|
||||
Elle n'est pas équivalente à `==`.
|
||||
`sameIdentity()` n’est pas équivalent à `==`, qui exprime l’égalité logique lorsqu’elle est disponible.
|
||||
|
||||
Exemple : deux objets différents peuvent être logiquement égaux mais ne pas être la même instance.
|
||||
|
||||
|
||||
@@ -97,11 +97,12 @@ a ^ b
|
||||
|
||||
Pas de NAND/NOR natifs.
|
||||
|
||||
## 20.5 Égalité — V1 REQUIS — FIGÉ EN PRINCIPE
|
||||
## 20.5 Égalité — V1 REQUIS — FIGÉ
|
||||
|
||||
```text
|
||||
OpPartialEqual<Lhs,Rhs>
|
||||
OpEqual<T>
|
||||
Equatable<T>
|
||||
```
|
||||
|
||||
`OpEqual<T>` renforce :
|
||||
@@ -118,11 +119,20 @@ symétrique
|
||||
transitive
|
||||
```
|
||||
|
||||
`float*` n'est pas `OpEqual` au sens strict si NaN brise la réflexivité ; il relève de l'égalité partielle.
|
||||
`Equatable<T>` est la capacité Core destinée aux APIs génériques qui ont besoin de cette égalité totale. Elle réutilise l'implémentation opérateur canonique et n'introduit ni seconde méthode `equals()` ni deuxième définition de `==` :
|
||||
|
||||
`!=` est toujours dérivé de `==`, jamais implémenté indépendamment.
|
||||
```text
|
||||
interface Equatable<T> extends OpEqual<T> {
|
||||
}
|
||||
```
|
||||
|
||||
Les classes ne reçoivent aucune comparaison champ-à-champ automatique : elles doivent choisir explicitement leur sémantique d'égalité si elles veulent supporter `==`.
|
||||
Ainsi, la règle générale reste inchangée : les opérateurs utilisateur sont définis uniquement via les interfaces compiler-known `Op...`, tandis que `Equatable<T>` permet d'exprimer une contrainte sémantique de haut niveau sans dupliquer l'opération.
|
||||
|
||||
Les `float*` conservent les comparaisons IEEE de la version normative adoptée. Comme `NaN == NaN` est faux, ils ne satisfont pas directement `Equatable<float*>` et relèvent de l'égalité partielle générale.
|
||||
|
||||
`!=` est toujours la négation logique de `==`, jamais une implémentation indépendante.
|
||||
|
||||
Les classes ne reçoivent aucune comparaison champ-à-champ automatique : elles doivent choisir explicitement leur sémantique d'égalité si elles veulent supporter `==`. L'identité de référence universelle reste distincte et s'obtient par `Object::sameIdentity(...)`.
|
||||
|
||||
## 20.6 Comparaison — V1 REQUIS — FIGÉ EN PRINCIPE
|
||||
|
||||
|
||||
@@ -125,6 +125,29 @@ part[0]::getName(); // OK
|
||||
|
||||
Le backing storage nécessaire à une slice reste vivant aussi longtemps que nécessaire. Cette garantie ne requiert aucune syntaxe de lifetime utilisateur.
|
||||
|
||||
Lorsqu'une slice provient d'un `Vector<T>`, elle référence un backing storage stable/indirect et non une adresse physique brute dont la validité dépendrait d'une allocation précise. Une relocalisation physique du buffer est donc invisible sémantiquement.
|
||||
|
||||
En V1 :
|
||||
|
||||
```text
|
||||
remplacement d'un élément du Vector
|
||||
reserve(...) / relocalisation physique
|
||||
append(...)
|
||||
-> les Slice existantes restent valides
|
||||
|
||||
insert(...)
|
||||
removeAt(...)
|
||||
clear() ayant effectivement supprimé au moins un élément
|
||||
-> toutes les Slice dérivées de ce Vector sont invalidées
|
||||
|
||||
utilisation ultérieure d'une Slice invalidée
|
||||
-> SliceInvalidatedFault
|
||||
```
|
||||
|
||||
`append` préserve les slices existantes parce qu'il ne change ni la position ni l'identité logique des éléments déjà présents. `insert` et `removeAt` peuvent déplacer les positions existantes ; V1 choisit donc une invalidation globale simple plutôt qu'un suivi dynamique de toutes les plages actives.
|
||||
|
||||
Un `clear()` sur un vector déjà vide n'effectue aucune mutation structurelle et n'introduit pas une invalidation supplémentaire.
|
||||
|
||||
Une slice vide est une valeur valide.
|
||||
|
||||
Les indices d'une sous-slice sont relatifs à la slice source.
|
||||
@@ -274,19 +297,29 @@ list[index] = value;
|
||||
|
||||
### 22.4.6 `ResizableList<T>`
|
||||
|
||||
`ResizableList<T>` étend `SettableList<T>` et garantit des opérations structurelles capables de modifier la longueur.
|
||||
|
||||
Les signatures exactes seront figées avec `Vector<T>`.
|
||||
|
||||
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.
|
||||
|
||||
Lorsqu'il existe, `clear()` suit la convention :
|
||||
`ResizableList<T>` étend `SettableList<T>` et garantit les opérations structurelles fondamentales suivantes :
|
||||
|
||||
```text
|
||||
clear() -> uint64
|
||||
interface ResizableList<T> extends SettableList<T> {
|
||||
method append(T value) -> Void;
|
||||
|
||||
method insert(uint64 index, T value) -> Void
|
||||
faults IndexOutOfBoundsFault;
|
||||
|
||||
method removeAt(uint64 index) -> T
|
||||
faults IndexOutOfBoundsFault;
|
||||
|
||||
method clear() -> uint64;
|
||||
}
|
||||
```
|
||||
|
||||
et retourne le nombre d'éléments effectivement supprimés.
|
||||
`insert(index,value)` accepte `0 <= index <= length()`. `index == length()` est donc un append positionnel valide, même si `append(value)` reste la forme explicite recommandée pour cette intention.
|
||||
|
||||
`removeAt(index)` exige `0 <= index < length()` et retourne l'élément retiré. Le modèle futur copy/move fixe son transfert physique sans changer cette signature sémantique.
|
||||
|
||||
Un `resize(newLength)` sans information d'initialisation n'est pas retenu : agrandir une collection ne doit jamais inventer implicitement des valeurs zéro, nulles ou non initialisées.
|
||||
|
||||
`clear()` retourne le nombre d'éléments effectivement supprimés.
|
||||
|
||||
### 22.4.7 Capacité du type et permission `const`
|
||||
|
||||
@@ -325,11 +358,80 @@ Vector<T>
|
||||
ResizableList<T>
|
||||
```
|
||||
|
||||
`Vector<T>` reste à définir précisément.
|
||||
|
||||
Un type persistant/immutable par nature n'a aucune obligation d'implémenter `List<T>` s'il ne garantit pas sa sémantique.
|
||||
|
||||
### 22.4.9 `Set<T>` et `ResizableSet<T>`
|
||||
### 22.4.9 `Vector<T>` — V1 REQUIS — FIGÉ
|
||||
|
||||
`Vector<T>` est l'implémentation standard SDK d'une séquence contiguë redimensionnable. Il implémente `ResizableList<T>`.
|
||||
|
||||
Surface fondamentale :
|
||||
|
||||
```text
|
||||
Vector<T>::empty() -> Vector<T>
|
||||
Vector<T>::filled(uint64 length, T value) -> Vector<T>
|
||||
Vector<T>::generate(...) -> Vector<T> // signature finale avec les callables
|
||||
Vector<T>::builder() -> VectorBuilder<T>
|
||||
|
||||
length() -> uint64
|
||||
count() -> uint64
|
||||
isEmpty() -> bool
|
||||
|
||||
vector[index] -> T
|
||||
vector[index] = value
|
||||
|
||||
append(T value) -> Void
|
||||
|
||||
insert(uint64 index, T value) -> Void
|
||||
faults IndexOutOfBoundsFault
|
||||
|
||||
removeAt(uint64 index) -> T
|
||||
faults IndexOutOfBoundsFault
|
||||
|
||||
clear() -> uint64
|
||||
capacity() -> uint64
|
||||
reserve(uint64 additional) -> Void
|
||||
slice(Range<uint64> range) -> Slice<T>
|
||||
```
|
||||
|
||||
`capacity()` et `reserve()` sont propres à `Vector<T>` et ne font pas partie de `ResizableList<T>`.
|
||||
|
||||
`reserve(additional)` garantit, si l'opération réussit, une capacité suffisante pour ajouter au moins `additional` éléments supplémentaires sans nouvelle croissance de capacité. Il ne change jamais `length()`.
|
||||
|
||||
Le contrat standard ne fournit pas :
|
||||
|
||||
```text
|
||||
reserveExact()
|
||||
resize(newLength) sans valeur/factory
|
||||
shrink général
|
||||
remove(value) générique
|
||||
```
|
||||
|
||||
Une collection spécialisée peut exposer une opération de shrink lorsqu'un besoin réel le justifie ; cette capacité n'appartient ni à `Vector<T>` général ni à `ResizableList<T>`.
|
||||
|
||||
Les littéraux `[...]` restent les littéraux contextualisés d'`Array<T>` / `StaticArray<T,N>` et ne construisent pas implicitement un `Vector<T>` :
|
||||
|
||||
```text
|
||||
Vector<int32> values = [1, 2, 3]; // ERROR
|
||||
```
|
||||
|
||||
La construction multi-éléments dynamique passe par une class method/factory explicite, notamment le builder.
|
||||
|
||||
`Vector<T>` garantit :
|
||||
|
||||
```text
|
||||
indexation [] / []= O(1)
|
||||
length / count / isEmpty O(1)
|
||||
append O(1) amorti
|
||||
insert O(n) au pire
|
||||
removeAt O(n) au pire
|
||||
slice O(1)
|
||||
capacity O(1)
|
||||
reserve O(n) au pire si relocalisation nécessaire
|
||||
```
|
||||
|
||||
Ces garanties appartiennent au type concret `Vector<T>`, pas à `List<T>` ou `ResizableList<T>` en général.
|
||||
|
||||
### 22.4.10 `Set<T>` et `ResizableSet<T>`
|
||||
|
||||
`Set<T>` étend `Collection<T>`.
|
||||
|
||||
@@ -368,7 +470,7 @@ clear()
|
||||
|
||||
Il n'existe pas de niveau `SettableSet<T>` : remplacer un élément d'un set équivaut conceptuellement à une modification structurelle de son ensemble de valeurs.
|
||||
|
||||
### 22.4.10 `Map<K,V>`, `SettableMap<K,V>` et `ResizableMap<K,V>`
|
||||
### 22.4.11 `Map<K,V>`, `SettableMap<K,V>` et `ResizableMap<K,V>`
|
||||
|
||||
`Map<K,V>` n'étend pas `Collection<T>` et n'implémente pas directement `Iterable<...>`. Une map possède trois projections naturelles différentes : clés, valeurs et entrées ; aucune ne doit être choisie implicitement comme itération « par défaut ».
|
||||
|
||||
@@ -414,19 +516,19 @@ remplace uniquement la valeur d'une clé existante. Cette syntaxe n'insère jama
|
||||
insert(K key, V value) -> Void
|
||||
faults DuplicateKeyFault
|
||||
|
||||
remove(const K key) -> Void
|
||||
remove(const K key) -> V
|
||||
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.
|
||||
`insert` affirme que la clé est nouvelle ; `remove` affirme qu'elle existe et retourne la valeur retirée. Leurs violations dynamiques sont des `Fault` unchecked et capturables.
|
||||
|
||||
Le Core ne fournit pas mécaniquement `tryInsert` / `tryRemove` ayant pour seule fonction de dupliquer ces opérations dans `Result` ou `bool`. Une variante conditionnelle ne sera ajoutée que si elle porte une sémantique réellement utile distincte.
|
||||
|
||||
Il n'existe pas de `put()` implicite « insert ou replace » tant qu'un besoin concret ne justifie pas cette troisième intention.
|
||||
|
||||
### 22.4.11 `MapEntry<K,V>`
|
||||
### 22.4.12 `MapEntry<K,V>`
|
||||
|
||||
`MapEntry<K,V>` représente une paire clé/valeur observée lors d'une projection `entries()`.
|
||||
|
||||
@@ -449,7 +551,7 @@ map[key] = value;
|
||||
|
||||
La sémantique de copie/référence de `K` et `V` suit les règles normales de leurs types.
|
||||
|
||||
### 22.4.12 Ordre : `Ordering`, `Comparable<T>` et `Comparator<T>`
|
||||
### 22.4.13 Ordre : `Ordering`, `Comparable<T>` et `Comparator<T>`
|
||||
|
||||
L'ordre total applicatif utilise :
|
||||
|
||||
@@ -495,7 +597,7 @@ Aucun mélange/fallback entre les deux n'est effectué pendant une même opérat
|
||||
|
||||
Les implémentations de `Comparable` et `Comparator` doivent respecter cohérence, symétrie d'ordre et transitivité. Le compilateur n'est pas tenu de prouver ces propriétés générales.
|
||||
|
||||
### 22.4.13 `SortedSet<T>` et `SortedMap<K,V>`
|
||||
### 22.4.14 `SortedSet<T>` et `SortedMap<K,V>`
|
||||
|
||||
`SortedSet<T>` étend `Set<T>` et garantit un ordre total stable selon le comparator actif :
|
||||
|
||||
@@ -523,7 +625,7 @@ Pour une `SortedMap`, les vues `keys()`, `values()` et `entries()` parcourent le
|
||||
|
||||
Les opérations de bornes/ranges (`floor`, `ceiling`, `lower`, `higher` ou noms définitifs) seront fermées séparément afin de ne pas introduire de noms ambigus par simple imitation d'une autre plateforme.
|
||||
|
||||
### 22.4.14 `TreeSet<T>` et `TreeMap<K,V>`
|
||||
### 22.4.15 `TreeSet<T>` et `TreeMap<K,V>`
|
||||
|
||||
Les types standard ordonnés généraux sont nommés :
|
||||
|
||||
@@ -554,23 +656,162 @@ TreeMap<K,V>::withComparator(Comparator<K> comparator)
|
||||
|
||||
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
|
||||
### 22.4.16 `Equatable<T>`, `Hashable` et `Hasher`
|
||||
|
||||
Les interfaces abstraites `Set<T>` et `Map<K,V>` n'imposent pas une stratégie de stockage particulière.
|
||||
|
||||
Ainsi :
|
||||
`Equatable<T>` est un contrat Core de haut niveau fondé sur l'égalité totale `OpEqual<T>` ; il n'ajoute aucune seconde méthode d'égalité :
|
||||
|
||||
```text
|
||||
HashSet<T> / HashMap<K,V>
|
||||
peuvent exiger des capacités de hash/égalité
|
||||
|
||||
TreeSet<T> / TreeMap<K,V>
|
||||
utilisent Comparable ou Comparator
|
||||
interface Equatable<T> extends OpEqual<T> {
|
||||
}
|
||||
```
|
||||
|
||||
`Hashable`, l'égalité et leurs contrats exacts seront fermés dans le bloc dédié. Ils ne sont pas imposés à `Set<T>` ou `Map<K,V>` eux-mêmes.
|
||||
`Hashable` est un contrat Core indépendant de `Comparable<T>` et de `Equatable<T>` au niveau de l'héritage :
|
||||
|
||||
### 22.4.16 Collections concurrentes
|
||||
```text
|
||||
interface Hashable {
|
||||
const method hash(Hasher hasher) -> Void;
|
||||
}
|
||||
```
|
||||
|
||||
Obligation normative de `Hashable` : **toute donnée participant à l'identité hashable d'une valeur doit rester stable pendant toute la durée de vie de cette valeur**.
|
||||
|
||||
Un objet peut donc rester mutable dans ses autres propriétés. Si `id` seul définit son hash et son égalité, des champs tels que `name` ou `score` peuvent changer sans violer `Hashable`.
|
||||
|
||||
Lorsqu'un type est à la fois `Equatable<T>` et `Hashable`, le contrat exige :
|
||||
|
||||
```text
|
||||
a == b
|
||||
-> même résultat de hash avec le même Hasher et la même configuration
|
||||
```
|
||||
|
||||
L'inverse n'est pas requis : une collision de hash entre valeurs non égales est normale.
|
||||
|
||||
`Hasher` appartient au Core parce que son contrat doit être connu des valeurs `Hashable` :
|
||||
|
||||
```text
|
||||
interface Hasher {
|
||||
method writeBytes(const Slice<uint8> bytes) -> Void;
|
||||
const method finish() -> uint64;
|
||||
}
|
||||
```
|
||||
|
||||
Les implémentations concrètes de `Hasher` appartiennent au SDK/runtime et peuvent employer des algorithmes/seeds différents.
|
||||
|
||||
`finish()` observe l'état courant sans le modifier : deux appels successifs sans `writeBytes()` intermédiaire retournent le même résultat.
|
||||
|
||||
Le Core définit le framing canonique utilisé par ses types fondamentaux `Hashable`. Les composants logiques successifs ne doivent pas devenir indistinguables par simple concaténation ambiguë d'octets ; par exemple les couples `("ab","c")` et `("a","bc")` ne peuvent pas être traités comme une unique séquence logique identique.
|
||||
|
||||
La représentation injectée dans un `Hasher` est un protocole de hashing interne, pas un format de sérialisation, une ABI ou un format de stockage public.
|
||||
|
||||
Les `float*` bruts conservent leur égalité IEEE partielle et ne satisfont pas directement `Equatable<float*>`; ils ne sont donc pas directement admissibles comme clés des collections hashées standard qui exigent `Equatable`.
|
||||
|
||||
### 22.4.17 `HashSet<T>` et `HashMap<K,V>`
|
||||
|
||||
Les implémentations standard hashées appartiennent au SDK :
|
||||
|
||||
```text
|
||||
HashSet<T>::empty() -> HashSet<T>
|
||||
HashSet<T>::builder() -> HashSetBuilder<T>
|
||||
|
||||
HashMap<K,V>::empty() -> HashMap<K,V>
|
||||
HashMap<K,V>::builder() -> HashMapBuilder<K,V>
|
||||
|
||||
HashSet<T>
|
||||
implements ResizableSet<T>
|
||||
where T implements Equatable<T>
|
||||
where T implements Hashable
|
||||
|
||||
HashMap<K,V>
|
||||
implements ResizableMap<K,V>
|
||||
where K implements Equatable<K>
|
||||
where K implements Hashable
|
||||
```
|
||||
|
||||
Elles ne garantissent aucun ordre logique ou d'itération stable. Deux instances contenant les mêmes éléments, ou deux exécutions du même programme, peuvent parcourir les données dans des ordres différents.
|
||||
|
||||
Le hasher concret et sa seed ne font pas partie du contrat observable général. Deux instances peuvent employer des seeds distinctes.
|
||||
|
||||
Une collision est normale :
|
||||
|
||||
```text
|
||||
même hash + égalité vraie
|
||||
-> même clé / même élément logique
|
||||
|
||||
même hash + égalité fausse
|
||||
-> collision, les deux valeurs peuvent coexister
|
||||
```
|
||||
|
||||
Il n'existe pas de `HashCollisionFault`.
|
||||
|
||||
Garanties de complexité moyennes :
|
||||
|
||||
```text
|
||||
contains / containsKey / get O(1) moyen
|
||||
add / insert / remove O(1) moyen
|
||||
count / isEmpty O(1)
|
||||
```
|
||||
|
||||
Le pire cas peut être O(n). Le contrat ne fige ni chaining, ni open addressing, ni Robin Hood, ni autre stratégie physique.
|
||||
|
||||
Pour `HashMap`, toutes les règles strictes de `Map`/`ResizableMap` restent valables : `map[key]` exige la clé, `get()` représente l'absence normale, `insert()` exige une clé nouvelle, `remove()` exige une clé existante et retourne `V`.
|
||||
|
||||
Pour `HashSet`, `add()` et `remove()` conservent leurs retours booléens ordinaires.
|
||||
|
||||
Une réorganisation interne des buckets/rehash est physiquement invisible. Une `View<T>` existante sur `keys()`, `values()` ou `entries()` reste une vue valide de la collection ; un `Iterator<T>` déjà créé peut néanmoins être invalidé par la mutation structurelle selon la règle générale des iterators.
|
||||
|
||||
### 22.4.18 Builders des collections concrètes
|
||||
|
||||
Les collections dynamiques concrètes utilisent des class methods explicites plutôt que de détourner le littéral `[...]` :
|
||||
|
||||
```text
|
||||
Vector<T>::builder() -> VectorBuilder<T>
|
||||
HashSet<T>::builder() -> HashSetBuilder<T>
|
||||
HashMap<K,V>::builder() -> HashMapBuilder<K,V>
|
||||
```
|
||||
|
||||
Contrats minimaux :
|
||||
|
||||
```text
|
||||
class VectorBuilder<T> {
|
||||
method append(T value) -> VectorBuilder<T>;
|
||||
const method build() -> Vector<T>;
|
||||
}
|
||||
|
||||
class HashSetBuilder<T> {
|
||||
method add(T value) -> HashSetBuilder<T>;
|
||||
const method build() -> HashSet<T>;
|
||||
}
|
||||
|
||||
class HashMapBuilder<K,V> {
|
||||
method insert(K key, V value) -> HashMapBuilder<K,V>
|
||||
faults DuplicateKeyFault;
|
||||
|
||||
const method build() -> HashMap<K,V>;
|
||||
}
|
||||
```
|
||||
|
||||
Les builders sont des objets mutables ordinaires. Les méthodes de configuration peuvent retourner le même builder afin de permettre le chaînage :
|
||||
|
||||
```text
|
||||
Vector<int32> values =
|
||||
Vector<int32>::builder()
|
||||
::append(1)
|
||||
::append(2)
|
||||
::append(3)
|
||||
::build();
|
||||
```
|
||||
|
||||
`build()` ne consomme pas le builder. Un builder peut produire plusieurs collections successives ; chaque résultat est sémantiquement indépendant des modifications ultérieures du builder. Un partage physique interne/COW reste possible tant que cette indépendance observable est respectée.
|
||||
|
||||
Un builder vide produit la collection vide correspondante.
|
||||
|
||||
`HashSetBuilder<T>` suit la sémantique du set : ajouter deux valeurs égales ne produit pas un fault et la valeur n'apparaît qu'une fois.
|
||||
|
||||
`HashMapBuilder<K,V>` suit la sémantique stricte de `insert` : une seconde clé égale produit `DuplicateKeyFault`; aucune règle implicite « first wins » ou « last wins » n'existe.
|
||||
|
||||
Les builders standard ne permettent pas de choisir une seed ou une implémentation de hasher. Ils ne fournissent pas non plus un `reserveExact` caché.
|
||||
|
||||
### 22.4.19 Collections concurrentes
|
||||
|
||||
Les garanties concurrentes sont orthogonales aux capacités structurelles et relèvent du SDK.
|
||||
|
||||
|
||||
@@ -35,6 +35,18 @@ resource ownership
|
||||
thread-safety implications
|
||||
```
|
||||
|
||||
### 27.2.1 Backing storage stable des collections contiguës — V1 REQUIS — FIGÉ EN PRINCIPE
|
||||
|
||||
Les abstractions sûres telles que `Slice<T>` ne doivent pas dépendre directement de l'adresse physique actuelle d'un buffer redimensionnable.
|
||||
|
||||
Pour `Vector<T>`, V1 retient un backing storage stable/indirect : le vector et ses slices peuvent conceptuellement référencer un contrôle de stockage commun capable de relocaliser son buffer physique sans rendre les slices invalides uniquement pour cette raison.
|
||||
|
||||
Cette exigence est sémantique, pas une structure ABI imposée. Une implémentation peut employer handle stable, indirection, contrôle partagé ou autre mécanisme sûr équivalent.
|
||||
|
||||
Le programmeur n'observe ni l'adresse précédente ni la relocalisation, et n'utilise aucun lifetime explicite pour maintenir le stockage nécessaire vivant.
|
||||
|
||||
La politique d'invalidation logique des slices (`append` préservé ; `insert`/`removeAt`/`clear` effectif invalidants en V1) est définie au chapitre 22 et reste distincte de la simple relocalisation physique.
|
||||
|
||||
## 27.3 `unsafe` — V1 REQUIS — FIGÉ EN PRINCIPE
|
||||
|
||||
`unsafe` ne désactive pas le système de types.
|
||||
|
||||
@@ -98,8 +98,6 @@ Restent à fermer :
|
||||
## 48.9 Core/SDK
|
||||
|
||||
- frontière Core/SDK définitive ;
|
||||
- `Vector<T>` et interaction avec `Slice<T>` lors des reallocations ;
|
||||
- contrats `Hashable` / égalité et implémentations HashSet/HashMap ;
|
||||
- opérations avancées de bornes/ranges pour `SortedSet` / `SortedMap` ;
|
||||
- propagation formelle de `const` dans `View<T>`, `Option<T>`, `Iterator<T>` et autres wrappers ;
|
||||
- String encodings ;
|
||||
|
||||
@@ -36,4 +36,10 @@ Les futures décisions doivent respecter les invariants suivants :
|
||||
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.**
|
||||
|
||||
33. **Une relocalisation physique de backing storage n'est pas une mutation sémantique observable et ne doit pas, à elle seule, invalider une `Slice<T>`.**
|
||||
34. **Les littéraux `[...]` restent des littéraux d'array contextualisés ; les collections dynamiques utilisent des factories/class methods/builders explicites.**
|
||||
35. **Une valeur `Hashable` possède une identité hashable stable pendant toute sa durée de vie ; aucune collection hashée ne repose sur un hash qui change silencieusement.**
|
||||
36. **Les collisions de hash sont normales ; l'égalité logique tranche l'identité, et aucun ordre d'itération des collections hashées n'est garanti par accident.**
|
||||
37. **Les standards externes adoptés normativement sont référencés par version ; une révision externe future ne modifie jamais silencieusement une version publiée de Saselang.**
|
||||
|
||||
---
|
||||
|
||||
@@ -90,3 +90,10 @@ saselang/mapdb*
|
||||
## 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.
|
||||
|
||||
### Exemple — contrat Core, implémentation SDK
|
||||
|
||||
```text
|
||||
Core: Hashable, Hasher, interfaces de collections, Slice<T>
|
||||
SDK : Vector<T>, HashSet<T>, HashMap<K,V>, implémentations concrètes de Hasher
|
||||
```
|
||||
|
||||
@@ -153,3 +153,13 @@ where T implements Numeric
|
||||
## 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.
|
||||
|
||||
### Exemple — égalité flottante IEEE adoptée
|
||||
|
||||
```text
|
||||
NaN == NaN // false
|
||||
+0.0 == -0.0 // true
|
||||
```
|
||||
|
||||
La révision 0.2.18 référence IEEE 754-2019 ; une révision future du standard n'altère pas rétroactivement cette version de Saselang.
|
||||
|
||||
|
||||
@@ -46,9 +46,19 @@ super::method()
|
||||
### Exemple 6
|
||||
|
||||
```text
|
||||
Object::sameInstance(Object other) -> bool
|
||||
const method sameIdentity(const Object other) -> bool
|
||||
```
|
||||
|
||||
## 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.
|
||||
|
||||
### Exemple 7 — égalité logique vs identité
|
||||
|
||||
```text
|
||||
User a = ...;
|
||||
User b = ...;
|
||||
|
||||
a == b; // égalité logique si User la définit
|
||||
a::sameIdentity(b); // identité exacte de référence
|
||||
```
|
||||
|
||||
@@ -72,6 +72,7 @@ a ^ b
|
||||
```text
|
||||
OpPartialEqual<Lhs,Rhs>
|
||||
OpEqual<T>
|
||||
Equatable<T>
|
||||
```
|
||||
|
||||
### Exemple 9
|
||||
@@ -241,3 +242,21 @@ a < b && b < c
|
||||
## 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.
|
||||
|
||||
### Exemple 29 — `Equatable<T>` ne duplique pas `==`
|
||||
|
||||
```text
|
||||
interface Equatable<T> extends OpEqual<T> {
|
||||
}
|
||||
```
|
||||
|
||||
`Equatable<T>` sert de contrainte sémantique aux APIs génériques ; l'implémentation opérateur reste `OpEqual<T>`.
|
||||
|
||||
### Exemple 30 — floats
|
||||
|
||||
```text
|
||||
NaN == NaN // false selon IEEE
|
||||
+0.0 == -0.0 // true selon IEEE
|
||||
```
|
||||
|
||||
Les `float*` bruts ne satisfont donc pas directement `Equatable<float*>`.
|
||||
|
||||
@@ -196,7 +196,7 @@ 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::remove(key) -> V // clé existante, KeyNotFoundFault sinon
|
||||
map::clear() -> uint64
|
||||
```
|
||||
|
||||
@@ -344,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.\n\n## Exemples 0.2.18 — Vector / Slice / hashing\n\n### Vector 1 — backing stable et slices\n\n```text\nVector<int32> values = Vector<int32>::builder()\n ::append(10)\n ::append(20)\n ::append(30)\n ::build();\n\nSlice<int32> part = values::slice(0..<2);\n\nvalues::reserve(1000); // part reste valide\nvalues::append(40); // part reste valide\nvalues[0] = 11; // part reste valide et observe 11\n\nvalues::insert(0, 5); // part devient invalide en V1\npart[0]; // SliceInvalidatedFault\n```\n\n### Vector 2 — API structurelle\n\n```text\nvalues::append(value); // -> Void\nvalues::insert(index, value); // index <= length()\nT removed = values::removeAt(index);\nuint64 removedCount = values::clear();\n```\n\n### DON'T — literal de Vector\n\n```text\nVector<int32> values = [1, 2, 3]; // ERROR\n```\n\n### DO — builder explicite\n\n```text\nVector<int32> values = Vector<int32>::builder()\n ::append(1)\n ::append(2)\n ::append(3)\n ::build();\n```\n\n### Hash 1 — contrats Core\n\n```text\ninterface Equatable<T> extends OpEqual<T> {\n}\n\ninterface Hashable {\n const method hash(Hasher hasher) -> Void;\n}\n\ninterface Hasher {\n method writeBytes(const Slice<uint8> bytes) -> Void;\n const method finish() -> uint64;\n}\n```\n\n### Hash 2 — clé stable\n\n```text\nclass UserKey implements Equatable<UserKey>, Hashable {\n const uint64 id;\n String label;\n\n // == et hash reposent uniquement sur id.\n // label peut changer sans modifier l'identité hashable.\n}\n```\n\n### DON'T — identité hashable mutable\n\n```text\nclass BadKey implements Equatable<BadKey>, Hashable {\n String name;\n\n // DON'T si == et hash dépendent de name et que name peut changer.\n}\n```\n\n### HashSet / HashMap\n\n```text\nHashSet<T>\n where T implements Equatable<T>\n where T implements Hashable\n\nHashMap<K,V>\n where K implements Equatable<K>\n where K implements Hashable\n```\n\nL'ordre d'itération n'est pas garanti. Une collision de hash n'est pas une erreur ; l'égalité distingue les valeurs.\n\n### HashMapBuilder — doublons stricts\n\n```text\nHashMap<String,int32> values = HashMap<String,int32>::builder()\n ::insert("one", 1)\n ::insert("two", 2)\n ::build();\n\nHashMap<String,int32>::builder()\n ::insert("one", 1)\n ::insert("one", 2); // DuplicateKeyFault\n```\n
|
||||
@@ -64,3 +64,13 @@ 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.
|
||||
|
||||
### Exemple — backing storage stable
|
||||
|
||||
```text
|
||||
Vector<int32> values = ...;
|
||||
Slice<int32> part = values::slice(0..<2);
|
||||
|
||||
values::reserve(1024); // une éventuelle relocalisation physique reste invisible
|
||||
part[0]; // toujours valide
|
||||
```
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Saselang + Core Specification — vue 0.2.12
|
||||
# Saselang + Core Specification — vue 0.2.18
|
||||
|
||||
Cette vue englobe la Language / Compiler Specification et ajoute le Core normatif.
|
||||
|
||||
Elle inclut notamment `Object`, `String`, `Result`, `Error`, `ResultError`, `Exception`, `Option`, `Nullable`, ranges, opérateurs Core, API des primitives et conversions numériques.
|
||||
Elle inclut notamment `Object`, `String`, `Result`, `Error`, `ResultError`, `Exception`, `Fault`, `Option`, `Nullable`, ranges, opérateurs Core, `Equatable<T>`, `Hashable`, `Hasher`, interfaces de collections, arrays/slices fondamentaux, API des primitives et conversions numériques.
|
||||
|
||||
L'annexe `../annexes/A-numeric-conversions.md` appartient à cette vue.
|
||||
|
||||
Reference in New Issue
Block a user