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.