Backends
Metalang possède désormais 5 nouveaux backends : lua, groovy, scala, forth et smalltalk.
LUA
Le backend LUA a été relativement simple à écrire, il y a juste eu une blague : en LUA, une fonction ne peut pas recevoir plus de 256 arguments, et quand je génère des prints, parfois (sur certains tests), ça dépassait.
Scala
Scala est un langage intéressant : c'est probablement un des rare langage objet typés plus ou moins à jours sur sur les concepts modernes (exemple : les tuples).
La seule subtilité de ce langage a été l'affectation sur les paramètres de fonctions : c'est interdit en scala.
Smalltalk
Je cherchais un langage vraiment différent de ceux déjà gérés, et smalltalk semblait pouvoir prétendre à ce titre.
Smalltalk n'a pas de priorités sur les opérations, les méthodes doivent etre appellées en nommant les arguments (comme en objective-C), tout est objet. Une curiosité en smalltalk : les blocs de code sont des valeurs comme les autres, ce qui veut dire qu'il est possible de les donner en argument à des méthodes, c'est d'ailleur comme ça que if est codé : true est une classe qui hérite de bool, true définit une méthode "ifTrue:code1 ifFalse:code2" et qui exécute le bloc : code1. C'est vraiment intéressant comme langage.
Voici le code généré pour l'exponentielle dichotomique :
exp0: a b: b [|o| (b = 0) ifTrue:[^ 1]. ((b rem: 2) = 0) ifTrue:[ o := (self exp0: a b: (b quo: 2)). ^ (o * o) ] ifFalse:[^ (a * (self exp0: a b: (b - 1)))]. ]
Pour metalang, nous avons choisi l'implémentation gnusmalltalk, ça fonctionne plutot bien et c'est relativement rapide.
Forth
Dans la série des langages étranges qui ne ressemblent pas à ce que Metalang gérait, j'ai pensé à Forth.
Forth est différent de tout les langages de part son fonctionnement : en forth, on a pas de parser, on a une boucle d'évaluation. Cette boucle peut évaluer un parser qui ira appeller une fonction qui ira ensuite soit compiler soit executer du code. Ce fonctionnement suffit pour en faire un langage extensible, haut niveau, puissant et compilé. Un petit milier de lignes d'assembleur suffisent pour écrire un loader forth. Je pense que le mot loader est le meilleur puisque ce langage est à la fois compilé et à la fois interprété mais c'est la librairie standard qui compile ou qui interprete... Pour l'execution, forth utilise une stack de valeurs, une stack pour les retours de fonctions et une mémoire. La mémoire contient à la fois du code executable et les données du programme. C'est vraiment un langage surprennant.
Voici le code généré pour l'exponentielle dichotomique
: exp0 recursive { a b } b 0 = IF 1 exit THEN b 2 % 0 = IF a b 2 // exp0 { o } o o * exit ELSE a a b 1 - exp0 * exit THEN ;
Je n'ai pas voulu chercher à compiler vers du forth vraiment propre : ça aurait été compliqué de gérer la stack d'une façon clean, j'ai donc utilisé les variables locales, et forth possède quelques curiosités : l'utilisation de variables locales est limitée (selon l'implémentation, c'est 24 je crois pour gnuforth.)
Backend Groovy
Après la série des vieux langages oubliés, j'ai repris le chemin des langages modernes. J'ai cherché à ajouter groovy, tout d'abbord en prennant java comme base, puis en remplaçant les endroits ou on peut faire mieux que java.
En groovy, on peut faire des scripts qui n'ont pas besoin de classe, on a pas besoin de mettre des ";" et public est inutile. ça rend le code généré légèrement plus court. Par contre, ce qui m'a posé problème c'est les char : groovy n'a pas de syntaxe pour créer des char litéraux...
Groovy est un langage assez experimental mais qui semble fontionner plutot bien.