zo iNiTiATiON SPEECHES
S01E35 2024-09-01

S01E35 — 01-09-2024.

Ô non ! J’ai ouvert la boite… de Pandore.

jour 35.

Sur toutes les choses que j’avais à faire, il fallait que je choisisse celui qui allait causer le plus de problèmes et de situations improbables. C’est donc ça la programmation bas niveau ? Être en perpétuelle joute avec la machine. Je comprends pourquoi certains abandonnent, se prendre des patates de forain sur le menton par la machine finie toujours par un KO. Mais être KO ne veut pas dire qu’on ne peut plus remonter sur le ring pour cette fois esquiver chaque offensive de la machine.

Idéalement, c’est ce que je me dis. À vrai dire, je suis dans la mouise. J’avançais un peu plus lentement que dans mes débuts (mais tant que j’avance, je suis relativement satisfait) lorsque je décide de me lancer dans l’écriture d’une petite preuve de concept d’un système de module. Dans les langages de programmation, le système de module va permettre d’ajouter des modules dans un programme — vulgairement synthétisé.

Facile, je dois simplement récupérer l’ensemble des fichiers requis et les parser.

Quel idiot ! Tête de oim, je me rends fou moi-même. Déjà, il n’y a pas que ça mais c’est un peu plus complexe que ça. Je t’explique après. Revenons sur l’écriture de la preuve de concept. Je gratte un petit programme capable de récupérer parallèlement et récursivement un ensemble de fichiers depuis un point d’entrée donné. Plutôt fier de moi, ça fonctionne bien. Je réfléchis à la hâte sur comment ce programme doit s’intégrer avec mon écosystème.

Je fais ça, puis ça, ensuite ça, enfin ça et on est bon !

Tu parles… Je décide de suivre ma folie. Après quelques petites galères, je réussis mon intégration sauf que lorsque j’exécute mon programme… mon compilateur déraille.

Qu’est-ce quiya fiston, pourquoi tu bégaies comme ça ?

Pour te donner du contexte, mon système de module charge en amont un début de ma librairie standard — deux fichiers exactement :

-u8


fun add(x: u8, y: u8): u8 { x + y }
fun sub(x: u8, y: u8): u8 { x - y }
fun mul(x: u8, y: u8): u8 { x * y }
fun div(x: u8, y: u8): u8 { x / y }
fun rem(x: u8, y: u8): u8 { x % y }

fun min(a : u8, b : u8): u8 { a < b ? b : a }
fun max(a : u8, b : u8): u8 { a > b ? a : b }

fun lt(x: u8, y: u8): bool { x < y }
fun le(x: u8, y: u8): bool { x <= y }
fun eq(x: u8, y: u8): bool { x == y }
fun ne(x: u8, y: u8): bool { x != y }
fun ge(x: u8, y: u8): bool { x >= y }
fun gt(x: u8, y: u8): bool { x > y }

-int


fun add(x: int, y: int): int { x + y }
fun sub(x: int, y: int): int { x - y }
fun mul(x: int, y: int): int { x * y }
fun div(x: int, y: int): int { x / y }
fun rem(x: int, y: int): int { x % y }

fun min(a : int, b : int): int { a < b ? b : a }
fun max(a : int, b : int): int { a > b ? a : b }

fun lt(x: int, y: int): bool { x < y }
fun le(x: int, y: int): bool { x <= y }
fun eq(x: int, y: int): bool { x == y }
fun ne(x: int, y: int): bool { x != y }
fun ge(x: int, y: int): bool { x >= y }
fun gt(x: int, y: int): bool { x > y }

Rien de sophistiqué, c’est juste des déclarations. Mais si tu es un expert en compilo, tu dois surement rigoler et comprendre pourquoi mon compilo bégaie. Si tu Rien de sophistiqué, c’est juste des déclarations. Mais si tu es un expert en compilo, tu dois surement rigoler et comprendre pourquoi mon compilo bégaie. Si comme moi tu ne comprends pas. C’est nor-mal et surtout après avoir subi quelques patates de forain qui ont remis mon cerveau en place, je peux te donner des explications :

J’ai deux fichiers, j’ouvre ces fichiers pour lire leurs contenus ensuite j’envoie ces fichiers dans la moulinette du compilateur et là j’ai une erreur. Pourquoi ? L’erreur se trouve dans les noms des fonctions. Entre les deux fichiers, les noms sont identiques ce qui crée des conflits. Je ne suis pas encore cent pour cent sûr mais la probabilité est forte et c’est le raisonnement le plus logique.

Puisque mon système module n’a aucune intelligence. Il ne comprend pas la portée des fichiers, ni même les liens entre eux (parent, enfant). Cette erreur m’a fait comprendre la mécanique d’un système de module. Enfin, je crois.

Imagine-toi un projet avec la structure suivante :


mon-projet
|-- lib/
|   |-- int.zo  
|   |-- u8.zo
|-- src/
    |-- main-zo

Le dossier lib/ contient ma librairie standard et le dossier src/ contient le point d’entrée de mon projet. Alala en écrivant, je me rends compte de ma bavure. Un bon module système doit avoir l’intelligence de comprendre l’arborescence d’un projet. C-à-d qu’en entrant qu’il a une sorte de ScopeMap dédié pour les modules. En s’imaginant le parcours du système de module :

  • Le système entre dans le dossier lib/il doit ajouter un nouveau scope.
  • Le système lit ouvre le fichier int.zoil doit ajouter un scope enfant du scope du dossier lib/ et ajouter son contenu.
  • Le système lit ouvre le fichier u8.zoil doit ajouter un scope enfant du scope du dossier lib/ et ajouter son contenu.
  • Le sytème sort du dossier lib/il revient à la racine des scopes.
  • Le système entre dans le dossier src/il doit ajouter un nouveau scope.
  • Le système lit ouvre le fichier main.zoil doit ajouter un scope enfant du scope du dossier src/ et ajouter son contenu.

C’est comme ça que je le vois. La mécanique est invisible, mais les marqueurs sont bel et bien présents. De cette manière, on découpe binairement le comportement du module système. Une entrée égale 0, une sortie égale 1 :

  • 0entrer dans un scope.
  • 1sortir du scope courant.

Pffffff ! Rien que d’y penser, je suis déjà dans l’mal. L’Arc du Tokenizer n’est même pas fini qu’une boite de Pandore vient de s’ouvrir. L’Arc du système de module va être épique. Ça n’en finira ja-mais, il y a toujours un truc qui sort du chapeau alors que je n’ai rien demandé.

@invisageable