Brainfuck metacompiler
Dans la série des compilateurs jouets, j'ai voulu écrire un compilateur brainfuck en métalang. L'idée était plutot curieuse : générer par méta-programmation du code métalang en lisant une source écrite en brainfuck.
On suppose la mémoire contenue dans la variable "mem", la position courrante : current_pos, et la variable temporaire qui sert aux entrées : input. On peut alors écrire les différentes instructions brainfucks sous formes de fonctions métalang
def lexems read_current() return { read char input mem[current_pos] = int_of_char(input) } end def lexems print_current() return { print char char_of_int(mem[current_pos]) } end def lexems incr() return { mem[current_pos] = mem[current_pos] + 1 } end def lexems decr() return { mem[current_pos] = mem[current_pos] - 1 } end def lexems prev() return { current_pos = current_pos - 1} end def lexems next() return { current_pos = current_pos + 1} end
Ensuite, on définit une macro qui lit l'entrée standard et la convertie en AST métalang.
def lexems eval() def read char c if c == '.' then return { ${print_current()} ${eval()} } elsif c == ',' then return { ${read_current()} ${eval()} } elsif c == '>' then return { ${next()} ${eval()} } elsif c == '<' then return { ${prev()} ${eval()} } elsif c == '+' then return { ${incr()} ${eval()} } elsif c == '-' then return { ${decr()} ${eval()} } elsif c == '[' then return { while (mem[current_pos] != 0) do ${eval()} } elsif c == ']' then return { end ${eval()} } elsif c == ' ' || c == '\n' || c == '\r' then return eval() else return {} end end
Il nous reste juste le code du main à écrire.
main def char input = ' ' def current_pos = 500 def array<int> mem[1000] with i do return 0 end ${ eval() } end
On obtient ainsi un compilateur brainfuck écrit en métalang. Pour obtenir le code C correspondant au code brainfuck, il suffit d'écrire : ./metalang brainfuck.metalang < brainfuck.source. Ce compilateur agit en fait comme une sorte de front-end à métalang.
Il s'agit d'avantage de l'écriture d'un frontend pour métalang sous forme de plugin que de l'écriture d'un compilateur.
Le code source du compilateur brainfuck