Primeiro ponto para deixar claro, não sou um cientista da computação.
Em 2017 eu me aventurei com criptomoedas e me apaixonei pelo Burstcoin. Ele tem a possibilidade de programação contratos inteligentes na blockchain. Na época não consegui criar um contrato, pois só havia uma ferramenta para programação e o código deveria ser programado em um tipo específico de assembly.
O tempo passou e agora em 2021 resolvi me aventurar novamente. Já há uma ferramenta para programação em alto nível (Blocktalk) mas entrei pelo desafio. Consegui fazer meu primeiro contrato inteligente (em assembly) e senti a dificuldade de converter um simples código em C para as instruções de máquina.
Num rompante de coragem e desconhecimento do assunto resolvi que iria criar um compilador. Peguei um projeto interessante (CaptCC) de um protótipo de compilador de C escrito em Javascript e fiquei uma semana batendo cabeça no código, entre entender e estudar o assunto. Cheguei a desistir, mas dois dias depois percebi que minha abordagem estava errada. Eu não conseguiria fazer algo bom que não fosse com funções recursivas.
Vários aqui já sabem o que é uma função recursiva e o princípio de funcionamento com o tradicional exemplo de calcular o fatorial. Mas se vc tem uma série de objetos de tipos diferentes, o buraco é muito mais embaixo. Quebrei a cabeça vários dias também pra descobrir que se começa pelo final em uma função recursiva.
É muito interessante esse salto, de onde uma linguagem de programação se assemelha a uma linguagem humana para passar para uma corrente de instruções de computadores. Entendi um pouco mais sobre a beleza do pensamento humano, comunicação e linguagem. Cada pessoa é como uma função recursiva, onde cada frase é uma sentença e cada palavra tem um significado semelhante mas distinto entre as pessoas. A vivência de cada um, a cada momento, altera um pouco mais do que será a pessoa no futuro. Talvez seja por isso que o ser humano gasta seus 10-12 primeiros anos de vida pra conseguir pensar “por si mesmo”, e talvez por isso a mudança a si próprio precisa ser construída dia após dia.
Quando parecia que eu estava próximo do final, comecei alguns testes e descobri comportamentos estranhos do compilador. Entendi então a necessidade de criar uma série de testes que fossem realizados a cada alteração, de modo a garantir que consertar um ponto não quebre algo inesperado. Os test cases me tomaram um grande tempo para fazer centenas de combinações possível, mas sem eles certamente o resultado não seria satisfatório. Parece que quando se trata de função recursiva, não há dois “jeitos certos” de fazer!
Por fim, o projeto (opensource, claro) está disponível no GitHub - deleterium/BurstAT-Compiler: Parser and compiler for arithmetic operations: C-like to BursAT assembly , onde já recebi uma contribuição estilosa do @yet1dev . Também é mais fácil ir direto na github-pages pra quem quiser rodar já no seu navegador:
Obrigado pela atenção, pela paciência e se alguém da área se interessar, poderia me explicar se é (muito) necessário mudar a ordem das operações de mesma precedência para “esquerda para direita”? Ex: a=b/c/d
atualmente está compilando para a=b/(c/d)
, ou seja da direita para a esquerda.