image

Bolsas de estudo DIO PRO para acessar bootcamps ilimitados

Disponible sólo:

37 vacantes
Article image
Saulo Maciel
Saulo Maciel13/04/2026 00:03
Compartir
CI&T - Do Prompt ao AgenteRecomendado para tiCI&T - Do Prompt ao Agente

Criando uma linguagem de programação: trocando interpretador

  • #Python

Prefácio:

Olá rede! Há certo tempo, venho desenvolvendo uma linguagem de programação pois é um sonho ter uma infra próxima do Tony Stark e do Batman.

A pensar que, meu viés de moral, é mais alinhado ao do Super Man. Brincadeiras a parte, decidi cria a Kaa, uma linguagem que funciona como minhas máquinas de estado.

O nome "Kaa", vem da língua indígena brasileira Nheengatu. Seu significado seria algo como: Mata; Flora; Bosque; Floresta.

image

Funcionamento:

A Kaa funciona como uma árvore. Ela não tem sistema de classes, somente funções e um sistema de compartilhá-las por clouseres como sistemas vivos separados que trabalham em conjunto, não estaria errado pensar em sementes para exemplificar.

Escolhi essa mecânica inspirado na minha vivência no ensino fundamental que comecei a fazer micro-bots para me auxiliar em uma certa atividade. Assim, eu dividia a forma que fazia um trabalho em pequenos robozinhos, no final, eles finalizavam um trabalho da escola. Na época, cheguei a criar uma linha de produção de trabalhos escolares e vender para a escola.

Mas, a grande dificuldade era a interconexão entre esses micro-bots. Então, ao passar dos anos, fui fazendo eles em python, shell script, java script, java, então pensei em criar uma linguagem. E reciclei a ideia dos micro-bots, os batizei de S-bots.

Então o POO da Kaa fica entorno disso, dois arquivos separdos com extensão de ".kaa":

// Kaa v3.11 - Teste de OOP (S-bots Factory)
// Arquivo inimigo.kaa

fun inimigo(nome,vida,especie) {
  var -obj self = {
      "nome": nome,
      "vida": vida,
      "dano": 0,
      "vivo": -T,
      "especie": especie,
  };
  
  fun gritar() {
      print "O OGRO ", self.nome, " ESTA FURIOSO!!";
  }


  fun nome(nome){
      self.nome = nome;
  }

  fun perde_vida(dano){
      self.vida = self.vida - dano;
  }

  fun morto(morto){
      if(morto==-F){
          self.vivo = -T;
          print "";
          print "O OGRO ", self.nome, " ESTA VIVO!!";
      }
      else{
          self.vivo = -F;
          print "";
          print "O OGRO ", self.nome, " MORREU!!";
      }
  }
  
  self.gritar = gritar;
  self.perde_vida = perde_vida;
  self.morto = morto;
  
  return self;
}

expor all;
// Arquivo ogro.kaa

add "./inimigo.kaa" all;

var -T control;
var -obj ogro1 = inimigo("jose",110,"ogro");
var -obj ogro2 = inimigo("joao",100,"ogro");

while(control==-T){
 
 print "";
 print ogro1.nome;
 print ogro1.vida;
 print ogro1.especie;
 print "-----------------------------";
 
 print ogro2.nome;
 print ogro2.vida;
 print ogro2.especie;
 print "";

 ogro1.gritar();
 ogro2.gritar();
 print ""; 

 var -s atacar;
 input "Deseja atacar? [s/n] " >> atacar;
 if(atacar=="s"){
 var -i qual_inimigo;
 input "Qual inimigo quer atacar? 1 -",ogro1.nome," 2 -",ogro2.nome, " ">> qual_inimigo;
 if(qual_inimigo==1){
    print "";
   ogro1.perde_vida(10);
   print ogro1.vida,":",ogro1.nome;
 }
 if(qual_inimigo==2){
    print "";
   ogro2.perde_vida(10);
   print ogro2.vida, ":",ogro2.nome;
 }
 }
 if(ogro1.vida==0){
 ogro1.morto(-T);
 destroy_arena(ogro1);
 }
 if(ogro2.vida==0){
 ogro2.morto(-T);
 destroy_arena(ogro2);
 }
 var -s sair;
 input "Deseja sair? [s/n] " >> sair;
 if(sair=="s"){
 control = -F;
 }
 destroy_arena();
}

Interpretador:

Depois de estruturar o sistema de arquivos como S-Bots e conseguir que eles funcionassem como classes vivas e modulares, o próximo grande passo foi uma decisão radical: jogar fora o interpretador de árvore (tree-walk).

A versão inicial da Kaa funcionava como a maioria dos interpretadores didáticos, percorrendo diretamente a AST (Árvore de Sintaxe Abstrata) nó por nó a cada execução. É elegante de se entender, mas tem um custo alto: cada operação redescobre o caminho. É como ler um livro inteiro para achar uma página toda vez que você precisa dela.

A solução foi construir uma Máquina Virtual de Bytecode própria. Em vez de caminhar pela árvore, o compilador interno da Kaa agora traduz o código-fonte em instruções simples e sequenciais, semelhante ao que a JVM faz com Java ou o CPython faz com .pyc. A VM lê essas instruções em linha reta, muito mais rápido.

Mas o que realmente mudou o jogo foi o otimizador JIT por Peephole. Ele analisa sequências de bytecode geradas e funde padrões repetitivos, como laços de contagem pesados, em superinstruções nativas. Na prática: benchmarks que antes levavam ~3.5 segundos caíram para ~0.6 segundos em manipulações iterativas na casa das centenas de milhares de operações.

O resultado foi uma linguagem que roda dentro do Python, mas que parou de se comportar como uma linguagem rodando dentro do Python.

O Motor JIT — Quando a Kaa Parou de Pedir Licença

Toda linguagem interpretada carrega um peso original: ela precisa de um intermediário. Você escreve código, mas quem realmente fala com o processador é outro programa. Esse intermediário cobra seu pedágio em milissegundos.

Por muito tempo, aceitei esse custo como inevitável por ser novato na área. A Kaa rodava sobre o Python, que já é ele mesmo interpretado. Era como contratar um tradutor que precisa de outro tradutor. O resultado era uma lentidão que, em operações simples, mal se nota, mas em laços pesados, iterações na casa das centenas de milhares, se tornava um muro.

A resposta foi o JIT por Peephole Optimization.

A ideia não é reescrever tudo em C. É mais cirúrgica do que isso: o otimizador observa o bytecode gerado pelo compilador da Kaa e identifica padrões. Sequências de instruções que aparecem repetidas dentro de laços, incrementos de contadores, comparações binárias previsíveis. Quando reconhece um desses padrões, ele não executa instrução por instrução. Ele funde aquele bloco inteiro numa única Superinstrução — uma operação atômica executada em nível mais baixo, próxima do metal.

É o conceito de Macro-Op Fusion, o mesmo princípio que processadores modernos usam internamente para fundir pares de instruções de assembly em pipeline. A Kaa trouxe isso para o nível da VM.

O impacto foi concreto: o benchmark que definia o teto da linguagem, um laço de incremento sobre centenas de milhares de iterações, passou de aproximadamente 3.5 segundos para 0.6 segundos. Numa linguagem que roda dentro do Python, que já é considerado lento pela comunidade de sistemas, isso representou algo inesperado.

Mas o número que mais me orgulha não é esse. É outro.

Máquinas Virtuais interpretadas construídas sobre Python costumam carregar um overhead de até 120 vezes em relação ao Python nativo. A Kaa, com o JIT ativo, ficou em ~19.5 vezes. Ainda há distância, mas a distância virou algo que se pode encarar sem vergonha.

O JIT não transforma a Kaa numa linguagem de sistemas, ao menos, ainda não. Ela não vai competir com Rust ou C++ em processamento bruto. Mas ele muda o contrato com o programador: você escreve em Kaa e não precisa se preocupar se um laço vai travar sua aplicação. O motor faz esse trabalho nos bastidores.

Assim como os micro-bots da escola precisavam de uma linha de produção eficiente para entregar o resultado no prazo, a Kaa precisava de um motor que respeitasse o trabalho que os S-Bots fazem. O JIT é essa linha de produção.

Conclusão — Um Sonho que Compila

A Kaa não nasceu de uma necessidade de mercado. Não surgiu de uma demanda corporativa, nem de um gap identificado em pesquisa acadêmica. Ela nasceu da mesma coisa que me fez montar aquela linha de produção de trabalhos escolares no ensino fundamental: a vontade irresistível de construir uma máquina que pensa do jeito que eu penso.

Toda linguagem de programação é, no fundo, uma filosofia materializada em código. O C acredita que o programador deve controlar tudo. O Python acredita que a legibilidade é lei. O Rust acredita que segurança de memória não pode ser opcional. A Kaa acredita que um sistema deve funcionar como uma floresta: troncos rígidos, tipados, confiáveis, e galhos que se adaptam, se compõem, crescem e morrem sem derrubar a árvore inteira.

Esse projeto é uma mistura honesta de tudo que fui acumulando ao longo dos anos. A obsessão com tipagem que aprendi a respeitar no C. A leveza de scripts que o Python me ensinou. A modularidade que o JavaScript me forçou a entender. E a filosofia de que um objeto não precisa de uma classe para ter identidade, que veio da minha própria cabeça, validada pelos S-Bots que antes viviam em planilhas e arquivos .bat numa tarde de escola.

E agora, pela primeira vez, tenho o mapa formal de tudo isso.

Ler o Crafting Interpreters, do Robert Nystrom, foi como encontrar o manual técnico de uma máquina que eu já tinha construído no escuro. Ali estão os scanners, os parsers, as árvores de sintaxe, as máquinas virtuais de bytecode, escritos com uma clareza que faz você querer parar a leitura a cada página para ir codar. É um daqueles livros raros que não te ensina só o como, te ensina o porquê.

Compartir
Recomendado para ti
Accenture - Python para Análise e Automação de Dados
Luizalabs - Back-end com Python - 2º Edição
TOTVS - Fundamentos de Engenharia de Dados e Machine Learning
Comentarios (0)
Recomendado para tiCI&T - Do Prompt ao Agente