Metalang V1.0.2 : Macrophage
Ma nouvelle série de commits sur metalang intègre des fixes variés et un tout nouveau système de macros.
Les macros sont vieilles dans les langages de programmations, on a le préprocesseur C et les macros lisp pour en témoigner. J'ai ajouté cette feature à Métalang récemment. Au début, le but était simplement d'avoir des templates comme en C++ mais la qualité du code produit par les macros m'apparait aujourd'hui trop faible pour cette utilisation.
J'ai opté pour une solution proche de celle du lisp : les macros sont écrites dans le même langage que le reste. Elles sont composées (en gros) de deux primitives : ${ ... } et { ... }, la première permet de faire une insertion et la seconde permet de capturer. L'idée est de manipuler des suites de lexems avec des insertions, ces lexems seront parsés ensuite lorsqu'ils seront inserrés dans du code (dans une instruction ou au toplvl).
Loop unroll s'écrit comme ceci :
def lexems loop_unroll(int i, int fin, lexems var, lexems content) if i == fin then return {} else return { ${var} = ${i} ${content} ${loop_unroll(i+1, fin, var, content)} } end end
et voici comment on l'appelle :
main def j = 0; ${loop_unroll(0, 5, {j}, { print int j ; print string "\n"})} end
Ce genre de choses ne produit pas un code très lisible, mais cependant j'ai écrit deux exemples intéressants pour cette feature : un solveur de sudoku qui génère une fonction de vérification qui ne contient aucune boucle, et un compilateur brainfuck qui lit et génère le code metalang pendant la compilation métalang, ce qui permet d'obtenir le code C, js, etc... qui correspond au brainfuck.
Bref, metalang comprend maintenant un système de macros correcte, certe moins puissant que ce qui existe en lisp, mais plus haut niveau, plus simple et plus puissant que ce qui existe en C.