4.2 KiB
7. Types nominaux et fichiers .saseltype
7.1 Nommage — V1 REQUIS — FIGÉ
Les types nominaux non primitifs commencent obligatoirement par une lettre ASCII majuscule. Aucune convention UpperCamelCase, PascalCase ou autre n'est imposée au-delà de cette première lettre.
7.2 Types nominaux V1 — V1 REQUIS — FIGÉ
Un fichier .saseltype peut définir exactement un des types suivants :
class
struct
interface
enum
union
Le nom du fichier doit correspondre exactement au nom du type.
Le fichier ne contient pas d'autres types top-level ni de fonctions auxiliaires top-level.
7.3 Ordre source et découverte nominale — V1 REQUIS — FIGÉ
L'ordre textuel des fichiers ou des déclarations n'a pas de signification sémantique pour la résolution des types.
Le frontend doit d'abord construire un index des déclarations nominales accessibles avant de finaliser leurs dépendances sémantiques.
Saselang n'expose pas de syntaxe utilisateur de forward declaration telle que :
class Foo;
struct Bar;
Une forward declaration manuelle serait redondante avec la collecte nominale du compilateur et réintroduirait des problèmes de cohérence inutiles.
7.4 États conceptuels de complétude — V1 REQUIS — FIGÉ EN PRINCIPE
La spécification distingue conceptuellement :
nominalement connu
identité du type, kind et paramètres génériques connus
sémantiquement complet
déclaration, héritage, interfaces et contrats résolus
layout-complet
représentation by-value, taille et alignement calculables lorsque nécessaires
Ces états décrivent le travail du compilateur ; le programmeur n'a pas à gérer explicitement des « types incomplets » comme en C/C++.
Une déclaration générique peut être sémantiquement complète sans posséder un layout concret unique avant instanciation.
7.5 Dépendances de layout by-value — V1 REQUIS — FIGÉ
Toute dépendance récursive par valeur est interdite, même lorsqu'une instanciation particulière pourrait théoriquement avoir une taille nulle.
Exemples interdits :
struct A {
A value;
}
struct A {
B b;
}
struct B {
A a;
}
struct A {
StaticArray<A, 0> values;
}
La longueur nulle ne crée aucune exception à la règle.
Les tuples, payloads d'enums algébriques, structs et autres composants réellement stockés inline participent au graphe de layout. StaticArray<T,N> participe également à ce graphe quel que soit N.
Le compilateur doit détecter les cycles directs et indirects du graphe by-value.
7.6 Classes et références — V1 REQUIS — FIGÉ EN PRINCIPE
Une valeur de type classe représente une référence d'objet et non une copie inline de l'objet complet.
Ainsi :
class A {
B b;
}
class B {
A a;
}
ne crée pas un cycle de layout by-value.
Une classe peut néanmoins contenir des champs réellement by-value, par exemple un struct ; le layout de ces champs reste soumis aux règles normales du graphe de layout.
Le modèle mémoire exact des références sera détaillé au chapitre mémoire sans modifier cette propriété sémantique.
7.7 Interfaces et stockage — V1 REQUIS — FIGÉ
Une interface est un contrat et ne possède pas d'état d'instance propre.
Le fait qu'une classe, un struct ou un autre type admissible implémente une interface ne change jamais implicitement son modèle de stockage, son identité ou son mode d'indirection.
Un struct qui implémente une interface reste donc soumis exactement aux mêmes interdictions de récursivité by-value qu'un autre struct.
7.8 Héritage cyclique — V1 REQUIS — FIGÉ
Le graphe extends doit être acyclique.
Sont interdits :
class A extends B
class B extends A
et :
interface A extends B
interface B extends A
ainsi que tout cycle indirect.
Les diamants non cycliques restent autorisés pour les interfaces. Le fait d'atteindre un ancêtre commun par plusieurs chemins ne constitue pas un cycle.
Les diagnostics doivent identifier le graphe réellement fautif, par exemple :
cyclic inheritance
recursive by-value layout
et non produire un message générique de « circular dependency ».