Suivant |
On part d'une conception classique de l'ordinateur, avec une mémoire linéique composée d'octets numérotés. On ne cherche pas à modifier l'architecture existante, celle-ci établit l'octet comme mémoire de base, et cela a pour conséquence de privilégier des blocs mémoires contigües composés d'un nombre entier d'octets. On remarque que :
1 octet adresse 256 o (octets)
2 octets adresse environ 65 ko (kilooctet)
3 octets adresse environ 1.7 Mo (mégaoctet)
4 octets adresse environ 4.3 Go (gigaoctet)
5 octets adresse environ 1.5 To (téraoctet)
Et 1 Téraoctet de mémoires est une quantité sufffisante pour un ordinateur à notre époque. C'est pourquoi il y aura 5 tailles d'adressage d'octets. On souhaite élabore un langage de programmation lié au hardware décrivant un traitement de cette mémoire.
La mémoire vive de l'ordinateur se présente comme une succession d'octets tel un message. Pour donner une signification au message, on procède comme un archéologue ou un linguiste qui découvre des hiéroglyphes, une succession de signes parmi un ensemble de 256 signes, et on cherche à découvrir la grammaire qui est utilisée pour donner un sense à ces suites de signes.
On pourrait y rechercher une grammaire générale, mais on préfère commencer progressivement en y recherchant des grammaires simples compatible avec le hardware ce qui nous permettra de définir une typologie simple en symbiose avec le hardware.
On définit la notion d'objet comme étant mémorisé dans un bloc contigüe d'octets et possédant un type et un nom mémorisés ailleurs.
Il convient de définir cette première typologie, une typologie en toile de fond qui définit un langage background, ce qui reste lorsque l'on a tout enlevé.
Il convient de subdiviser la mémoire en une succession contigüe d'objets. Mais des objets d'un même type peuvent avoir des tailles différentes. Cela a pour conséquence de classifier les types selon le mécanisme mis en oeuvre pour déterminer la taille de leurs objets. Il y a trois catégories d'objet :
Chaque type se range dans une des 3 catégories : type de modon, type de varon ou type de nonon.
Le langage que nous voulons définir est polymorphe c'est-à-dire qu'il change de forme en cours de route pouvant ainsi toujours s'adapter au problème. Puisque nous créons un langage qui s'adapte sur mesure pour chaque problème, il n'est plus à craindre de s'égarer dans l'élaboration d'un langage de fond spécifique épousant le hardware. Mais ce langage devra constituer l'embryon de tous les autres langages.
Le hardware prédéfinit un type d'objet qu'est celui des instructions machines, de type varon, pouvant avoir une taille de 1 à 8 octects (correspondant à l'architecture 64 bits des ordinateurs actuels).
Le fonctionnement classique de l'ordinateur se résume en l'exécution d'une instruction machine : Il existe un compteur d'instructions qui pointe sur une instruction machine. L'ordinateur procède à l'exécution de l'instruction machine. Puis il incrémente le compteur d'instruction du nombre d'octets de la taille de l'instruction pour pouvoir pointer l'instruction suivante, ou bien l'instruction machine exécutée était celle d'un saut et son exécution a directement modifié le compteur d'instruction. Puis l'ordinateur répète l'opération. On ajoute à cela une interruption en cas d'erreur qui se produit lorsque l'instruction machine n'est pas reconnue ou qu'elle génère une erreur, et qui correspond à une instruction de saut vers un programme sensé gèrer les erreurs.
A partir de cette définition on est amené à définir ce qu'est un programme vu par le bas, sans qu'il y ait de système d'exploitation, une étude que nous reprendrons plus-tard. On courcircuite cette étape en faisant le choix d'un noyau Linux.
Le noyau linux installé sur l'ordinateur va répartir le temps d'exécution de l'ordinateur entre plusieurs instance de programme s'executant, appelées processus.
Le processus possède un environnement qui est un ensemble de variables avec leur contenant. C'est la mémoire vive du processus. Puis il peut créer des processus fils reprenant une partie de cet environnement. Enfin il agit sur des données partageés sous forme de fichier qui constitue la mémoire de l'ordinateur.
Le noyau linux propose une arborescence de fichiers avec droits d'accès, qui contient la mémoire commune de l'ordinateur, aussi bien périphérique que interne. Le contenue du fichier désigne un bloc successif d'octets pouvant prendre toutes valeurs.
On fait la distinction entre deux types de données, les données binaires qui peuvent prendre toute forme, tandis que les données textes doivent être des suites de caractères unicode au format utf-8. C'est à dire qu'un caractère est un varon qui peut occupé 1, 2, 3 ou 4 octets, contenant l'unicode.
L'unicode codifie les caractères de toutes les langues du monde. Il apporte une impressionante richesse au pauvre alphabet aglo-saxon et atteint une universalité trés remarquable.
Alors se pose la question, y-a-t'il un intérêt à mélanger ces deux types de données dans un même fichier ? Il semble que linux est choisie de ne pas le faire, sachant que dans le pire des cas, on considère que tout est binaire. Mais dans notre discution, nous allons le faire. La typologie dense des objets va perrmettre d'interpréter un fichier contenant des données textes et binaires mélangés.
Est-il possible de construire le langage de programmation par étape en commençant par le bas, c'est à dire par le harware. Comment concevoir les constantes, les variables, les fonctions, les types.... C'est le mariage entre le software (le langage) et le hardware (la structure matérielle) qui va accoucher d'un langage de fond spécifique quasi canonique.
L'objet est mémorisé dans un bloc contigüe d'octets, mais son nom et son type sont mémorisés ailleurs.
Le type est un concept, celui d'ensemble d'objets ainsi que celui de structure mathématique, et l'objet est un autre concept plus général, que nous définirons en même temps que notre langage de programmation. Nous procèdons à la construction, telle une genèse engendrant le langage.
On élabore un langage de programmation dit hardware décrivant un traitement de la mémoire linéïque, qui, allégé des arbitraires matériels, devient une question purement mathématique et linguistique. L'entropie des données joue alors un rôle central. On cherche à définir des types denses, voir complètement denses, c'est à dire où chaque configuration de bits est autorisée et correspond à un objet distinct de ce type. La plus petite taille mémoire transportant une information est le bit. L'octet devient alors vite une contrainte matériel arbitraire génante. Pour rendre la discution purement mathématique et linguistique, il faut supprimer l'octet et le remplacer par le bit qui constitue la plus petite taille de mémoire.
On repart donc sur une conception abstraite de l'ordinateur, avec une mémoire linéique composée de bits numérotés. Un bloc de `n` bits permets d'adresser `2^n` bits. Et on laissera à la charge de l'ordinateur une étape de calcul pour recaler les données sur un découpage de la mémoire par octets.
Reprenons les trois types modon, varon et nonon, et regardons les assemblages possibles. L'idée est de construire une grammaire intégrant la contrainte hardware d'une mémoire linéïque composée de bits. Et on part du type le plus simple, qu'est le type singleton de taille mémoire nulle.
Un type singleton ne contient qu'un objet. Et donc ses objets n'occupent pas de mémoire. Une variable de type singleton ne contient pas de contenue. Sa taille mémoire est nulle. Parcontre elle possède un type qui est un singleton.
Dans notre langage, il est représenté par un mot qui n'a pas déjà été prédéfini. Le langage étant fortement dynamique, les opérateurs sont variables, et l'évaluation du mot doit redonner le mot. En d'autre terme, le type singleton ne comprend qu'un objet qui est lui-même.
La variable de type singleton se contient elle-même et désigne à la foi l'objet et son type. On parlera d'objet singleton, ou simplement de singleton.
Le type énuméré se présente comme une liste de singletons distincts. Il se déclare par une liste de terme entourées d'accolades et séparées par des virgules. Par exemple :
jour = {lundi, mardi, mercredi, jeudi, vendredi}
Chaque terme est évalué et doit produire un type singleton. Le type énuméré ainsi construit possède comme objet l'ensemble des évaluation des termes apparaissant dans l'énumération au moment où la déclaration du type est exécutée.
La variable de type jour correspond à un bloc de bits suffisant pour compter les objects du type jour. On appelle un objet de type jour, une telle variable instantiée, c'est à dire avec une valeur déterminée.
Chaque objet de type jour possède un numéro identifiant qui correspond à sa position dans l'énumération en commençant par zéro. L'objet lundi est de type lundi (et constitue lui-même le type lundi). Et il a comme identifiant 0 pour le type jour. La variable de type lundi contient l'objet lundi, et la variable de type jour contient un identifiant sur 3 bits désignant un des 5 objects du type jour. Il reste 3 configurations inutilisées qui se symbolise par des extensions futures possibles représentées par le symbole _ , que apriori l'interpréteur ajoutera de lui-même.
jour = {lundi, mardi, mercredi, jeudi, vendredi, _, _, _}
L'objet de type jour est de taille 3 bits. Une fois évaluée, il se transforme en l'objet qu'il contient et qui est l'objet de type singleton correpondant à sa position dans l'énumération définissant le type jour.
Le type booléen est le types énuméré suivant :
booléen = {0,1}
L'objet 0 est de type 0. L'objet 1 est de type 1. L'objet de type booléen comprend un bit qui s'il est à 0 contient l'objet 0 et s'il est à 1 contient l'objet 1.
En procédant ainsi on construit petit-à-petit un langage de fond. Ainsi, l'instruction x=0 sans autre précision et où x n'a pas de type prédéfini, va regarder parmi tous les types déjà définis dans le présent document jusqu'à maintenant, quel type peut posséder l'objet 0, et va en attribuer un à x. À ce stade, x ne peut prendre comme type précédement définie dans le présent document que celui de booléen. L'instruction va lui attribuer le type booléen, puis va lui alouer un bit et lui attribuer la valeur 0.
Il convient de définir les trois sortes de type hardware les plus généraux :
Le modon est un bloc de n bits où n est un entier naturel spécifié dans le type. On note ce type bitn. Et on identifie les objets de ce type aux entier modulo `2^(n)`.
On a donc défini un opérateur bit s'appliquant à un entier collé à droite. Le terme bitn désigne le type de modon à n bits.
On définit un opérateur # s'appliquant à un entier x collé à gauche et à un entier n coller à droite. Le terme x#n désigne l'objet de type bitn qui contient l'entier x modulo `2^n`.
Le varon est un blocs de bits qu'il est nécessaire et suffisant de lire pour déterminer sa fin. Une des conséquences de cela est qu'un varon ne pas pas être de taille nulle.
Le varon possède une taille minimal précisée dans le type et une fonction qui appliqué à cette première lecture de taille minimal retourne soit la taille du varon où soit seulement une taille supplémentaire nécessitant de réitérer l'opération sur la nouvelle partie lue.
Mais il est inutile de couvrire tous les algorithmes possibles. On ne va garder que les quelques algorithmes pertinant qui on fait leurs preuves, pour définir les varons.
Il y a deux sortes de varon, ceux qui, avec éventuellement une entête, se subdivisent en sous-objet de même taille et sur lesquels des algotrithmes d'adressage indirecte peuvent s'opérer. Cette sorte de varon fait partie des tables. Et il y a ceux qui, avec éventuellement une entête, se subdivisent en sous-objets de taille variable. Cette sorte de varon fait partie des chaines. Mais nous n'allons pas définir les tables et les chaines directement. Nous allons les construire par le bas.
Nous décrivons une sorte de type nonon appelé dictionnaire. On peut en imaginer d'autres. Le dictionnaire est l'ensemble des objets du type en question. Pour déterminer la fin du nonon, on lit une brique suivante (la brique est un modon ou un varon définie dans le type) et on regarde si on obtient un début de séquence de briques appartenant au dictionnaire. Si c'est le cas on continue avec la brique suivante, sinon c'est que l'on est arrivé à la fin et qu'il faut rejeté cette brique. On voit qu'il est nécessaire de lire une brique au delà de l'objet pour déterminer sa fin.
Le type dictionnaire se présente comme une liste de mot. Il se déclare par une liste de terme entourées de parenthèse et séparées par des virgules. Par exemple :
dico = ("bonjour", "chat", "maison", "ciel")
Chaque terme est évalué et doit produire un objet. Le type énuméré ainsi construit possède comme objet l'ensemble des évaluation des termes apparaissant dans l'énumération au moment où la déclaration du type est exécutée.
La variable de type dico correspond à une chaine de caractères sans caractère de fin. Les objets de type dico on une taille variable de 4 ou 6 ou 7 octets. On peut convertir le type dico en un type énuméré. On numérote chaque objet à partir de zéo.
A= Renum(dico)
A = {bonjour, chat, maison, ciel}
L'espace de nom est propre au type A de tel sorte que pour désigner l'objet chat en dehors des accolades, il faut le préfixer par le type. Ainsi A::chat désigne l'objet chat du type A.
Le type haché est une autre forme compressée du type dico, mais compressé partiellement à l'aide d'une table de hachage de `2^n` cases. La chaine de caractère est transformée en un code de hachage singularisé, à l'initalisation du type. Ce type possède des éléments tous de même tailles `n` bits.
A=Hache(dico,n)
Le type A est un modon de taille n bits. Une variable de type A contient comme valeur le code de hachage qui par le biais de la table de hachage permet de retrouver la chaine de caractère correspondante. et réciproquement la fonction de hachage permet de calculer le code à partir d'une chaine de caractères.
Étant donné deux types A, B, le type somme A+B représente l'union disjointe des types, c'est à dire le type des éléments pouvant être un élément de A ou bien un élément de B et en les distiguant selon le chemin emprunté pour les désigner.
card(A+B) = card(A) + card(B)
La somme de deux types énumératifs est un type énumératif couvrant les mêmes objets mais préfixé par une position. Par exemple considérons le type A = {3,5,7} et le type B={2,3}. Le type A+B est égal à :
{0:3, 0:5, 0:7, 1:2, 1:3}
On a donc défini un opérateur : s'appliquant à un objet x collé à gauche et à un objet y collé à droite, pour former l'objet concaténé x:y. Et le type des objects concaténés est égal au produit des types des objects.
type(x:y) = type(x)×type(y)
On remarquera qu'une somme de deux types d'objet totalement denses constitue un type d'objet totalement denses. Puis on peut sommer le même type plusieur fois. Considérons par exemple le type A = {1..4} qui signifie {1,2,3,4}. C'est un type totalement dense dont les objets sont des modons de tailles 2 bits. Autrement dit :
A ⊂ bit2
Puis considérons le type A+A. Ses objets ont une taille de 3 bits, le premier bit déterminant s'il sagit d'un élément du premier A ou un élément du second A. Maintenant faisons une troisième sommation (A+A)+A. Ce type admet des objets de 3 ou 4 bits. C'est donc un type de varon où le premier bit détermine sa taille.
On défini le type produit par un entier strictement positif. Le type nA correspond à la somme de A avec lui-même n fois, mais sous la forme d'un modon de taille minimale. L'objet comprend un premier modon de type {1..n} suivi d'un objet de type A. Autrement dit :
nA = {1..n}×A
Le type A est totalement dense, et donc le type nA est totalement dense si n est une puissance de 2.
Étant donné deux types A, B, le type produit A×B, représente le type des couples composés d'un premier élément de type A et d'un second élément de type B mais présenté de façon dense c'est à dire sous la forme d'une concaténation d'objets.
Pour pouvoir faire le produit de deux dictionnaires A×B, il faut que ceux-ci vérifient une propriété d'intégrité, à savoir qu'aucun mot de A ne commence par un mot de A et se termine par un début de mot de B.
Si A n'est pas un nonon on peut faire le produit A×B. Par contre si A est un nonon, on ne peut procéder au produit que si on apporte un moyen de déterminer la fin du nonon. Et cela se fait si A est un dictionnaire et si (A,B) vérifient la propriété d'intégrité, à savoir qu'aucune objet de A ne commence par un objet de A et se termine par un début de séquence de briques d'un objet de B.
Dans la pratique on utilise un séquenceur, un objet de taille d'une brique dont le but est de séquencer une suite de nonons, et qui possède la propriété suivante : Les dictionnaires utilisés n'ont aucun mot contenant cette brique. Le produit d'un nonon avec cette brique séquenceur (que joue par exemple le caractère blanc pour séparer les mots dans un texte) transforme le nonon en un varon.
On défini le type exposant par un entier strictement positif. Le type A^n correspond au produit de A avec lui-même n fois.
A^n = A×A×...×A (n fois)
Si A est un modon, l'objet devient une table de n objets de type A sur laquel on peut procédé à des adressages indirectes.
Si A est un varon, l'objet devient une chaine de n objets de type A.
Si A est un nonon, il est nécessaire que le type A vérifie un propriété d'intégrité lui permettant de séparer deux de ses objects concaténés.
Chaque objet de type loi de composition forment une structure de données néguentropique. Ces structures de données contenant des liens internes que sont ces pointeurs, transportent une quantité d'informations dites introspectives, qui peut se refléter comme deux miroir en vis-à-vis jusqu'à l'infini. L'objet acquère de par ces liens sur lui-même et cette reflexivité, une capacité d'organisation qui lui est propre, et qui, utilisé d'une certaine façon, permet de réduire l'entropie. Cela s'appelle de la néguentropie.
On ne considère que des types de loi de composition d'arité fixe p et totalement dense. Autrement dit, s'ils ne le sont pas, on les complètes pour qu'ils le soient. Le type loi de composition possède deux paramètres entiers, l"arité des sommets p, et n où 2^n est le nombre d'éléments de E. Nous avons un type E énuméré de 2^n élément. Le type loi de composition sur E se note :
E^p→E
Un objet de ce type correspond à une application de E^p vers E, définie de manière totalement dense. L'objet est composé d'une table de 2^(n*p) briques de n bits chacune. La taille des objets est n*2^(n*p) bits.
|E| |
`E"→"E` |
`E^2→"E` |
`E^3"→"E` |
`E^4"→"E` |
`E^5"→"E` | `E^6"→"E` | `E^7"→"E` | `E^8"→"E` | `E^9"→"E` | `E^10"→"E` | `E^11"→"E` | `E^12"→"E` | |
n
|
`2^n` |
`n2^n "b"` |
`n2^(2n) "b"` |
`n2^(3n) "b"` |
`n2^(4n) "b"` |
`n2^(5n) "b"` |
`n2^(6n) "b"` |
`n2^(7n) "b"` |
`n2^(8n) "b"` |
`n2^(9n) "b"` |
`n2^(10n) "b"` |
`n2^(11n) "b"` | `n2^(12n) "b"` |
`1`
|
`2`
|
`2 "b"` |
`4 "b"` |
`1 "o"` |
`2 "o"` |
`4 "o"` |
`8 "o"` |
`16 "o"` |
`32 "o"` |
`64 "o"` |
`128 "o"` |
`256 "o"` |
`510 "o"` |
`2`
|
`4`
|
`1 "o"` |
`4 "o"` |
`16 "o"` |
`64 "o"` |
`260 "o"` |
`1 "ko"` |
`4.1 "ko"` |
`16 "ko"` |
`66 "ko"` |
`260 "ko"` |
`1 "Mo"` |
`4.2 "Mo"` |
`3` |
`8` |
`3 "o"` |
`24 "o"` |
`190 "o"` |
`1.5 "ko"` |
`120 "ko"` |
`98 "ko"` |
`79 "ko"` |
`6.3 "Mo"` |
`50 "Mo"` |
`400 "Mo"` |
`3.2 "Go"` |
`26 "Go"` |
`4`
|
`16`
|
`8 "o"` |
`130 "o"`
|
`2 "ko"` |
`33 "ko"` |
`520 "ko"` |
`8.4 "Mo"` |
`134 "Mo"` |
`2.1 "Go"` |
`34 "Go"` |
`550 "Go"` |
||
`5` |
`32` |
`20 "o"` |
`640 "o"` |
`20 "ko"` |
`660 "ko"` |
`21 "Mo"` |
`670 "Mo"` |
`21 "Go"` |
`688 "Go"` |
||||
`6`
|
`64`
|
`48 "o"`
|
`3.1 "ko"`
|
`200 "ko"` |
`13 "Mo"` |
`805 "Mo"` |
`52 "Go"` |
||||||
`7` |
`130` |
`110 "o"` |
`14 "ko"`
|
`1.8 "Mo"` |
`230 "Mo"` |
`30 "Go"` |
|||||||
`8`
|
`260`
|
`260 "o"`
|
`66 "ko"`
|
`17 "Mo"` |
`4.3 "Go"` |
||||||||
`9` |
`510` |
`580 "o"` |
`290 "ko"`
|
`150 "Mo"` |
`77 "Go"` |
||||||||
`10`
|
`1 "k"`
|
`1.3 "ko"` |
`1.3 "Mo"`
|
`1.3 "Go"` |
|||||||||
`11` |
`2 "k"` |
`2.8 "ko"` |
`5.8 "Mo"` |
`12 "Go"` |
|||||||||
`12`
|
`4.1 "k"`
|
`6.1 "ko"`
|
`25 "Mo"`
|
`103 "Go"` |
|||||||||
`13` |
`8.1 "k"` |
`13 "ko"` |
`109 "Mo"` |
||||||||||
`14`
|
`16 "k"`
|
`29 "ko"`
|
`470 "Mo"`
|
||||||||||
`15` |
`33 "k"` |
`61 "ko"` |
`2 "Go"` |
||||||||||
`16`
|
`66 "k"`
|
`130 "ko"`
|
`8.6 "Go"`
|
||||||||||
`17` |
`130 "k"` |
`279 "ko"` |
`37 "Go"` |
||||||||||
`18`
|
`260 "k"`
|
`590 "ko"`
|
`150 "Go"`
|
||||||||||
`19` |
`520 "k"` |
`1.2 "Mo"` |
|||||||||||
`20`
|
`1 "M"`
|
`2.6 "Mo"`
|
|||||||||||
`21` |
`2.1 "M"` |
`5.5 "Mo"` |
|||||||||||
`22`
|
`4.2 "M"`
|
`12 "Mo"`
|
|||||||||||
`23` |
`8.4 "M"` |
`24 "Mo"` |
|||||||||||
`24`
|
`17 "M"`
|
`50 "Mo"`
|
|||||||||||
`25` |
`34 "M"` |
`100 "Mo"` |
|||||||||||
`26`
|
`67 "M"`
|
`218 "Mo"`
|
|||||||||||
`27` |
`130 "M"` |
`450 "Mo"` |
|||||||||||
`28`
|
`270 "M"`
|
`940 "Mo"`
|
|||||||||||
`29` |
`540 "M"` |
`1.9 "Go"` |
|||||||||||
`30`
|
`1.1 "G"`
|
`4 "Go"`
|
|||||||||||
`31` |
`2.1 "G"` |
`8.3 "Go"` |
|||||||||||
`32`
|
`4.3 "G"`
|
`17 "Go"` |
|||||||||||
`33` |
`8.6 "G"` |
`35 "Go"` |
|||||||||||
`34`
|
`17 "G"`
|
`73 "Go"` |
---- 1 avril 2023 ----
On définit des objets composés, appelé tables, en ne retenant que quelques algorithmes d'entrée-sortie jugée efficace et suffisant. Les tables comprennent éventuellement un sous-objet de tête déterminant la taille, suivi par une succession de modons de même type.
Etant donné un type A. on note A^5
Une table est la concaténation d'un modon ou d'un varon déterminant un nombre entier `n`, le tout concaténé avec `n` briques, la taille de la brique étant spécifié dans le type de la table.
Une chaine est la concaténation d'un modon ou d'un varon déterminant un nombre entier `n`, le tout concaténé avec `n` briques, la taille de la brique étant spécifié dans le type.
Le nonon est un blocs de bit dont on ne connait pas la fin. Les objets de ce type se note simplement en juxtaposant des `0` et de `1`
Le type bâton représente une suite de bits à 1 suivi d'un bit à 0 qui signal la fin du bloc.
Par symétrie le type ¬bâton représente une suite de bits à 0 suivi d'un bit à 1 qui signal la fin du bloc.
Le type bâton s'inscrit dans un genre de type plus générale appelé chaîne vue plus bas.
Puisque le mot `0` désigne un bit contenant `0`, et le mot `1` désigne un bit contenant `1`, qu'est-ce que pourrait désigner le mot `2` ? Il désigne deux bits contenant `10` l'expression binaire de `2`. Et il en est de même pour tous les entiers naturels. Ainsi nous complétons le langage de fond, en introduisant les séquences de chiffres ne commençant pas par zéro, qui sont traduites en leur expression binaire, des données brutes qui sont des séquences de bits ne commençant pas par zéro.
Un mot constitué d'une succession de chiffres s'appelle une suite de chiffres, et si elle ne commence pas par zéro, elle s'évalue en un entier naturel qui se mémorise en une suite de bits ne commençant pas par zéro.
Le type des entiers naturels est un type dont la taille des objets est inconnue.
Et il y a trois sortes de type énumératifs :
Les type de modon on une taille prés-établie. Les types de varon, fixe la taille de leurs objets en consultant leurs premiers bits. Par contre, les types dictionnaires ne permettent pas de définir la taille de leurs éléments simplement en les lisant.
Par exemple si le terme `u` représente la suite de bit `1010`, et si le terme `v` représente la suite de bits `001`, le type `{u,v}` possède deux éléments de tailles différentes que sont la suite de bits `1010` et la suite de bits `001`.
Et si on a besoin d'un type énumératif sans évaluation, on utilise les guillemets ou des quotes pour entourer les termes de l'énumération tel que par exemple le type `{“u“,“v“}`
Lorsque se pose la question de savoir si une donnée brute de taille fixée `X` appartient à un type `T`, on transmet la donnée et sa taille qui est précisée par son conteneur, à un opérateur, `X in T`, qui retourne le bits `1` si c'est vrai et retourne le bits `0` si c'est faux. Cela constitue un teste d'intégrité de `X` en tant qu'objet de type `T`. La même opération se prolonge si `X` possède un type plus précis que Element. On teste alors en plus si le type de `X` peut bien être considéré comme une spécialisation du type `T`.
Les types dictionnaires sont utilisés pour traiter des chaînes d'éléments du type en question. Mais à ce niveau intemédiaire de langage, on ne veut pas perdre d'efficacité et l'interprétation d'une telle suites d'éléments doit se faire en une seule lecture. Et cela est possible si on s'en tient à choisire systématiquement les mots les plus grands du dictionnaire. Par exemple considérons le type `{“abc“,“a“,“bcd“,“d“,“"_"“}`, alors la séquence `"abcd"` correspondra à la séquence de mots `"abc", "d"` et non à la séquence de mots `"a", "bcd"`. Et pour désigner la deuxième interprétation, il nous faut recourir à un mot pouvant jouer le rôle de séparateur tel que `"a_bcd"`. Ainsi, il est fait un choix dans l'interprétation des suites de mot d'un même dictionnaire, sans que cela ne réduise la capacité d'expression du langage.