Blog
Lexer → Parser → AST → Bytecode → JIT. Como Python, JavaScript, Go e Rust transformam texto em instruções. Crafting Interpreters (Robert Nystrom), Engineering a Compiler (Cooper/Torczon).
Compilador transforma código fonte em código alvo SEM executar (gcc, rustc). Interpretador EXECUTA direto (Python tradicional, Ruby). Híbridos: V8 (interpreta + JIT), JVM (compila pra bytecode + JIT em runtime), Crafting Interpreters de Robert Nystrom.
O LEXER varre caracteres e produz TOKENS: "if (x > 0)" vira [IF, LPAREN, IDENT(x), GT, NUMBER(0), RPAREN]. Regex vs autômato finito determinístico (DFA). Por que JavaScript precisa de lookahead. Ferramentas: flex, ANTLR.
O PARSER constrói AST (Abstract Syntax Tree) a partir dos tokens. Recursive descent vs Pratt parser vs LALR(1). Por que JavaScript é hard to parse (ASI). Caso real: Babel AST, Roslyn AST, libcst (Python).
Depois do parse, o compilador VERIFICA: variáveis declaradas? tipos compatíveis? escopo correto? Symbol table, type checking (HM algorithm em Haskell, structural em TS, nominal em Java). Erros: "undefined variable", "type mismatch".
Native: C, Go, Rust compilam pra assembly direto. Bytecode: Java (.class na JVM), C# (CIL no CLR), Python (.pyc). Interpretado puro: Ruby tradicional, Bash. Trade-offs: startup time, runtime speed, portabilidade, debugging.
JIT (Just-In-Time) observa o código em runtime e compila o "hot path" pra assembly nativo. V8 (Chrome/Node) tem 4 tiers: Ignition → SparkPlug → Maglev → TurboFan. PyPy faz Python 4-10x mais rápido que CPython. GraalVM compila Java em nativo (AOT).
LLVM é o "linker universal de compiladores". Você escreve frontend que gera LLVM IR, e LLVM dá pra você otimização + geração de código pra x86/ARM/RISC-V/WASM. Usado por Rust, Swift, Julia, Crystal, Zig. Chris Lattner (Apple → Tesla → Modular).
GC libera memória que ninguém mais aponta. Mark&Sweep (clássico, pausa total), Generational (objetos novos morrem cedo — JVM G1), Concurrent (ZGC sub-millisecond), Reference counting (Python, Swift). Por que Go usa GC e Rust escolheu não usar.
Compilador gera .o (object files com símbolos não-resolvidos). LINKER (ld, lld, mold) junta tudo num executável ELF/Mach-O/PE resolvendo símbolos. LOADER do OS carrega em memória, faz dynamic linking de .so/.dylib/.dll, ASLR. Por que linking é o gargalo de C++ builds.
Implementação prática inspirada em Crafting Interpreters de Robert Nystrom. Lox é uma linguagem completa de brinquedo: variáveis, funções, classes, closures. Você escreve lexer (50 linhas), parser recursive descent (100), tree-walking interpreter (150). Em 300 linhas você TEM uma linguagem rodando.
Carregando…