Visão geral
Linguagem de programação de verdade, não um interpretador que anda pela árvore sintática. O
código Lyra passa por quatro estágios — lexer, parser, compilador, VM — e vira instruções
binárias antes de rodar. Suporta variável, escopo de bloco, if/while/for, função com
parâmetro e retorno, recursão, função como valor de primeira classe e curto-circuito real em
&&/||.
fun fib(n) {
if (n < 2) { return n; }
return fib(n - 1) + fib(n - 2);
}
print "fib(15) = " + str(fib(15));
Como funciona
Toda variável local (parâmetro, var dentro de função ou bloco) vira um índice de slot na
pilha da VM, calculado em tempo de compilação — ler uma local em tempo de execução é um acesso
de array, não uma busca por nome. Só variável global passa por um dicionário em tempo de
execução. Erro de runtime (variável não definida, divisão por zero, tipo errado, recursão
infinita) sempre vira uma exceção controlada com a call stack completa no momento da falha, como
um traceback de verdade — nunca um crash nativo do .NET.
Testes
37 testes automatizados cobrindo cada camada: lexer (operadores, literais, comentário, contagem de linha), motor completo ponta a ponta (aritmética com precedência, escopo com sombreamento, recursão via Fibonacci, função como valor, closures fechando sobre global) e uma bateria de erros provocados de propósito — incluindo recursão infinita, provando que vira um erro controlado ("Stack overflow") em vez de derrubar o processo.
Decisão de projeto assumida
Função aninhada não enxerga variável local de quem a envolve, só globais — implementar closures de verdade precisaria de upvalues (o mecanismo do Lua/clox, com células de variável compartilhadas), complexidade a mais que não valia pra esse escopo. Documentado no README como próximo passo natural, não como bug escondido.
Stack
C# 12, .NET 8, xUnit. Zero dependências de terceiros.