Back to flin
flin

Le bug de gestion du None

Comment le modèle temporel de FLIN était bloqué par une correction de 10 lignes -- l'accès aux propriétés sur les valeurs None lançait des erreurs au lieu de se propager gracieusement.

Juste A. Gnimavo (Thales) & Claude | March 26, 2026 3 min flin
EN/ FR/ ES
flinbugnonenull-safetytype-systemdebugging

Certains bugs bloquent des fonctionnalités entières. Ils siègent à un point d'étranglement dans l'architecture du système, et tant qu'ils ne sont pas résolus, tout en aval reste inutilisable. Le bug de gestion du None était l'un de ceux-là. Il était petit -- dix lignes de code pour le corriger -- mais il se tenait entre nous et le modèle temporel tout entier.

Le 7 janvier 2026, nous avions 27 tests d'intégration temporels. Tous les 27 échouaient. L'opérateur d'accès temporel (@) avait été implémenté. Le stockage de l'historique des versions fonctionnait. La base de données maintenait correctement les versions des entités. Mais au moment où vous tentiez d'utiliser quoi que ce soit en vrai code, la VM lançait un TypeError et s'arrêtait.

Le problème

L'opérateur @ de FLIN avec un offset négatif récupère les versions antérieures. Quand une seule version existe, user @ -1 retourne correctement None. Le bug se manifestait quand on tentait d'accéder à une propriété sur cette valeur None :

flinprevious = user @ -1           // Returns None (only 1 version exists)
<div>{previous.name}</div>     // TypeError: expected object, found none

La correction

La correction était remarquablement simple. Nous avons modifié deux opcodes dans la VM : GetField et GetFieldDyn.

rust// OpCode::GetField (src/vm/vm.rs:1484-1494)
if let Value::Object(id) = obj {
    // Normal path: access field on object
    self.push(value)?;
} else if obj == Value::None {
    // NEW: Propagate None instead of throwing error
    self.push(Value::None)?;
} else {
    return Err(RuntimeError::TypeError {
        expected: "object or none",
        found: obj.type_name().to_string(),
    });
}

Après la correction, None.property retourne None, permettant des chaînes d'accès temporel propres sans vérifications null verbeuses.

La décision de conception

Nous avons choisi la propagation implicite du None -- None.property retourne None. Cela reflète le chaînage optionnel de JavaScript (null?.property), la navigation sûre de TypeScript, et le Option::and_then() de Rust.

Le compromis est que la propagation du None peut masquer des bugs. Mais nous avons accepté ce compromis car le vérificateur de types de FLIN attrape les erreurs de noms de champs à la compilation. La propagation du None n'affecte que les valeurs à l'exécution qui sont légitimement None.

Impact sur le modèle temporel

La correction de 10 lignes a débloqué 27 tests d'intégration, dont 4 ont immédiatement commencé à passer. Les 23 restants étaient bloqués par un problème séparé de rendu des espaces blancs HTML, pas par des erreurs de logique temporelle.

Dix lignes de code. Une heure de travail. Tout un sous-système de fonctionnalités débloqué. Parfois la chose la plus précieuse qu'un développeur puisse faire n'est pas de construire quelque chose de nouveau, mais de supprimer un seul obstacle qui empêchait tout le reste de fonctionner.


Ceci est la partie 158 de la série « Comment nous avons construit FLIN », documentant comment un CEO à Abidjan et un CTO IA ont conçu et construit un langage de programmation à partir de zéro.

Navigation de la série : - [157] Le bug d'itération de la boucle for - [158] Le bug de gestion du None (vous êtes ici) - [159] Le bug de rendu des espaces blancs HTML

Share this article:

Responses

Write a response
0/2000
Loading responses...

Related Articles

Thales & Claude thales

Treize agents, quarante-trois minutes : la première session Workflow de Claude Fable 5, et ce qu'un script d'orchestration déterministe change aux builds multi-agents

Un prompt, treize agents, quarante-trois minutes : la première session de production avec Claude Fable 5 et l'outil Workflow de Claude Code a livré un site web de production complet de sept pages plus un endpoint backend de capture de leads, en un seul commit. Le carnet de bord : le script d'orchestration déterministe, le patron d'injection de contrat entre les phases, l'économie par agent du fan-out parallèle, et le suspense de la limite de session que le journal de reprise a transformé en non-événement.

23 min Jun 12, 2026
claude-fable-5claude-codeworkflow-toolmulti-agent +10
Thales & Claude casp

La porte a détecté sa propre dérive : une journée dans CASP avec Claude Fable 5

Nous avons confié au modèle Claude le plus autonome à ce jour les clés de CASP — le CLI open source qui garde les agents de code IA honnêtes face à git — avec l'autorité de rejeter notre propre roadmap. Il a rejeté cinq choses, trouvé deux vrais bugs dans le validateur en le dogfoodant, les a corrigés sous une porte à deux auditeurs, et a laissé casp check entièrement vert sur son propre dépôt pour la première fois. CASP 0.3.0 en est le résultat.

16 min Jun 10, 2026
caspzerosuiteworkflowai-cto +9
Thales & Claude zerosuite

La transplantation du CASP : comment la discipline des six fichiers est passée de Conductor à un ERP transport anti-fraude, ce que la compétence /next ajoute quand l'opérateur tape juste « next », et pourquoi le coût d'une dérive du CASP grimpe quand le projet, c'est l'argent des autres

La discipline du CASP qui a piloté trente-cinq sessions de Conductor est agnostique au produit. Le carnet de bord de sa transplantation sur KASSIA, un ERP transport anti-fraude pour un exploitant de flotte en Côte d'Ivoire : ce qui a migré, ce qui n'a pas migré (le validateur sur mesure — et ce que son absence coûte), ce que la compétence /next ajoute quand l'opérateur tape un seul mot, et là où le CASP s'arrête — le bug de déploiement qu'il ne pouvait pas voir parce qu'il enregistre l'intention, pas la réalité de l'infrastructure.

23 min Jun 8, 2026
kassiaerp-kassia-transport-logistiquezerosuiteCASP +15