mardi 30 juin 2009

Hello, world.

Cela fait quelques temps déjà que Lama a exécuté sa première addition et son premier programme "hello, world". A l'heure actuelle, il exécute en réalité un fichier contenant une centaine de lignes de test.


J'ai successivement franchi le cap de la compilation et de l'exécution d'instructions simples, puis de la création de procédures, puis de la lecture de fichiers sources, puis de la création de types et de structures, puis de la création de blocs conditionnels et de boucles, puis de la création de clôtures, puis de la création d'espaces de noms, puis du chargement d'extensions sous forme de librairies partagées.

Dernièrement, j'ai ajouté la définition de types-union (au sens des langages fonctionnels), qui permettent notamment d'intégrer la mécanique de gestion d'erreur que je souhaitais et dont j'ai parlé il y a quelques mois.

Pour résumer, les types-union permettent d'exprimer le fait qu'une valeur (une variable, un champ de structure, un paramètre ou un résultat) appartient à un type parmi un ensemble de types. Cet ensemble est connu à la compilation, le type effectif de la variable dépend de ce qui se passe à l'exécution. Le compilateur peut vérifier à la compilation que le programme traitera à peu près correctement tous les cas de figure qui se présenteront à l'exécution.

On utilise les types-union pour la gestion d'erreur en créant un type particulier pour le cas d'erreur, par exemple DivisionParZero, et en l'associant dans une union avec le type "normal". Par exemple:

proc inverse Real x -> DivisionParZero/Real y

  if x=0

    set y DivisionParZero

  else

    set y 1/x

    end

  end

Le type DivisionParZero est un cas particulier de type qu'on appelle "type unité" parce qu'il ne représente qu'une seule valeur. Avec Lama, on le définit comme un t-uple vide:

type DivisionParZero []

Dans ce cas particulier, on se moque de la valeur effective associée au type. Elle est simplement représentée par le nom du type lui-même.

Quand on utilise la procédure "inverse" définie ci-dessus, on obtient une valeur qui peut appartenir à l'un ou l'autre des deux types. Pour pouvoir l'utiliser, il faut d'abord vérifier à quel type elle appartient; on utilise la struture "on" pour ce faire:

var r: inverse z {avec z: un nombre quelconque}

on DivisionParZero r

  print "Erreur: division par zero"

  end

on Real r

  print "le résultat est:" ~ (toString r)

  end

Le compilateur vérifiera que tous les types de l'union sont passés en revue par le programme, comme pour un switch...case du C.

Les types-union résolvent une seconde difficulté: dans un langage à typage statique fort comme Lama, les structures de données classiques comme les listes ou les tableaux ne peuvent contenir qu'un seul type de données. Les unions permettent en quelque sorte de cacher plusieurs types dernière un seul type. C'est certes moins flexible qu'avec un langage dynamique, mais c'est aussi plus sûr et plus rigoureux.


Sur le plan de la syntaxe, il ne me reste plus qu'à implémenter les macros. Je prévois un système inspiré de Forth, où les macros sont des procédures particulières exécutées lors de la compilation. Celles-ci peuvent faire appel à certaines parties du compilateur pour remplir leur fonction. Un exemple d'utilisation très élémentaire serait que la macro "bricole" une chaine contenant l'expression voulue et appelle une procédure du genre "eval", ce qui équivaut déjà aux macros du langage C.

Cependant, sur le plan du fonctionnement, les choses sont moins avancées: il manque un gros morceau, la gestion automatique de mémoire (dont on pourra se passer pour une première version de "démo"); l'interpréteur a tendance à se planter facilement sur les erreurs de syntaxe. Enfin, il manque quelques vérifications stratégiques comme sur la structure "on" ci-dessus, ou sur le fait que la variable de retour reçoit bien une valeur dans tous les cas de figure.

PS: les liens pointent parfois vers des pages Wikipédia anglaises parce que la version française n'était pas suffisamment complète dans le cadre de mon propos.


Aucun commentaire:

Enregistrer un commentaire