College Online
0%

O que e um Compilador

Modulo 1 · Aula 1 ~20 min de leitura Nivel: Introdutorio

Video da aula estara disponivel em breve

Definicao

Um compilador e um programa que traduz codigo-fonte escrito em uma linguagem de programacao (a linguagem-fonte) para outra linguagem (a linguagem-alvo), tipicamente codigo de maquina ou uma representacao intermediaria. O compilador lê o programa inteiro, analisa sua estrutura e significado, e produz uma saida equivalente em outra forma.

Essa traducao nao e trivial. O compilador precisa entender a sintaxe (forma) e a semantica (significado) do programa-fonte, detectar erros, e gerar codigo correto e eficiente.

i
Compilador vs. Interpretador vs. Transpilador Um compilador traduz o programa inteiro antes de executar (C, Go, Rust). Um interpretador executa instrucao por instrucao, sem gerar codigo-alvo separado (Python classico, Ruby). Um transpilador traduz de uma linguagem-fonte para outra linguagem de alto nivel (TypeScript para JavaScript, Kotlin para JVM bytecode). Na pratica, muitos sistemas modernos misturam as abordagens: Python compila para bytecode (.pyc) que depois e interpretado pela VM.

As Fases da Compilacao

Um compilador e tipicamente dividido em fases, cada uma transformando uma representacao do programa em outra. O modelo classico tem seis fases principais, organizadas em front-end (dependente da linguagem-fonte) e back-end (dependente da linguagem-alvo):

Diagrama
                     FRONT-END                          BACK-END
            +--------------------------+     +---------------------------+
            |                          |     |                           |
Codigo  --> | Analise  --> Analise --> Analise | --> Rep.Inter. --> Otimi- --> Geracao |
Fonte       | Lexica      Sintatica   Seman. |     (IR)          zacao     de Codigo|
            |                          |     |                           |
            +--------------------------+     +---------------------------+
                                                                      |
                                                                      v
                                                                Codigo-Alvo

Fase 1: Analise Lexica    - Quebra o texto em tokens (palavras)
Fase 2: Analise Sintatica - Organiza tokens em arvore (estrutura)
Fase 3: Analise Semantica - Verifica tipos, escopos, significado
Fase 4: Representacao IR  - Traduz para formato intermediario
Fase 5: Otimizacao        - Melhora o codigo intermediario
Fase 6: Geracao de Codigo - Emite codigo na linguagem-alvo

Exemplo Concreto: Compilando uma Expressao

Vamos acompanhar a expressao resultado = taxa * 100 + bonus passando por cada fase:

Python
# Fase 1 - Analise Lexica: quebrar em tokens
# "resultado = taxa * 100 + bonus"
# Tokens gerados:
tokens = [
    ("ID", "resultado"),
    ("ASSIGN", "="),
    ("ID", "taxa"),
    ("MULTIPLY", "*"),
    ("NUMBER", 100),
    ("PLUS", "+"),
    ("ID", "bonus"),
]

# Fase 2 - Analise Sintatica: construir a arvore
#
#        =
#       / \
#  resultado  +
#            / \
#           *   bonus
#          / \
#       taxa  100
#
# A arvore respeita a precedencia: * antes de +

# Fase 3 - Analise Semantica: verificar tipos
# - "taxa" esta declarada? Sim, tipo float
# - 100 e int, taxa e float -> converter 100 para float
# - "bonus" esta declarada? Sim, tipo float
# - resultado recebe float: tipos compativeis

# Fase 4 - Representacao Intermediaria (three-address code)
# t1 = int_to_float(100)
# t2 = taxa * t1
# t3 = t2 + bonus
# resultado = t3

# Fase 5 - Otimizacao
# t1 = 100.0        (constant folding: conversao feita em compile-time)
# t2 = taxa * t1
# resultado = t2 + bonus   (eliminamos t3)

# Fase 6 - Geracao de Codigo (pseudo-assembly)
# LOAD  R1, taxa
# LOADF R2, 100.0
# MULF  R3, R1, R2
# LOAD  R4, bonus
# ADDF  R5, R3, R4
# STORE resultado, R5

Front-End e Back-End

A separacao entre front-end e back-end e uma decisao arquitetural fundamental. O front-end entende a linguagem-fonte; o back-end entende a maquina-alvo. Entre eles, a representacao intermediaria (IR) serve como contrato.

Diagrama
  Linguagens-Fonte          IR           Maquinas-Alvo
  +----------+          +------+         +----------+
  |    C     |--\       |      |    /--->|  x86_64  |
  +----------+   \      |      |   /     +----------+
  +----------+    }---->| LLVM |--{      +----------+
  | Rust     |   /      |  IR  |   \     |   ARM    |
  +----------+--/       |      |    \--->+----------+
  +----------+  /       |      |         +----------+
  | Swift    |-/        +------+    /--->| RISC-V   |
  +----------+                     /     +----------+

  M linguagens x N alvos = M+N front/back-ends (em vez de M*N)

Essa arquitetura e usada por compiladores reais. O LLVM, por exemplo, define uma IR comum e permite que qualquer linguagem que gere LLVM IR possa compilar para qualquer arquitetura que tenha um back-end LLVM.

*
Na pratica O GCC tambem usa essa separacao, com sua propria IR chamada GIMPLE/RTL. Clang e o front-end C/C++ do LLVM. O compilador Rust (rustc) tambem emite LLVM IR. Essa arquitetura modular e uma das razoes pelas quais e relativamente facil criar novas linguagens hoje — basta escrever o front-end e reusar um back-end existente.

Compiladores vs. Interpretadores: Um Espectro

Na realidade, a distincao entre compilacao e interpretacao nao e binaria — e um espectro:

Diagrama
Compilacao Pura                                   Interpretacao Pura
     |                                                    |
     v                                                    v
+--------+  +----------+  +---------+  +--------+  +-----------+
| C/C++  |  |   Java   |  | Python  |  |  Bash  |  | Calculad. |
| Go     |  |   C#     |  |  Ruby   |  |  sed   |  | de bolso  |
| Rust   |  |  Kotlin  |  |  PHP    |  |  awk   |  |           |
+--------+  +----------+  +---------+  +--------+  +-----------+
  Compila    Compila p/     Compila      Interpreta  Interpreta
  p/ nativo  bytecode +     p/ bytecode  linha a     direto
             JIT            (CPython)    linha

Hibrido: JavaScript V8 compila JIT p/ nativo em runtime

No harness.os

O harness.os implementa um pipeline que e estruturalmente analogo a um compilador. A entrada sao knowledge chunks, rules, e project state armazenados no banco de dados e em arquivos. A saida e um prompt otimizado que o agente AI vai executar.

Diagrama
Pipeline harness.os mapeado para fases de compilacao:

ENTRADA (Codigo-Fonte)          PROCESSAMENTO                    SAIDA (Codigo-Alvo)
+-------------------+    +---------------------------+    +-------------------+
| Knowledge chunks  |    | 1. Lexica: parse YAML/MD  |    |                   |
| Rules (YAML)      |--->| 2. Sintatica: validar     |--->| Prompt otimizado  |
| Project state     |    |    estrutura               |    | para o agente     |
| Session handoff   |    | 3. Semantica: resolver     |    |                   |
| CLAUDE.md files   |    |    refs, checar tipos      |    +-------------------+
+-------------------+    | 4. IR: context struct      |
                         | 5. Otimizar: token economy |
                         | 6. Gerar: montar prompt    |
                         +---------------------------+

Cada chamada a start_session() no MCP server e, essencialmente, uma "compilacao" — o harness lê as fontes (knowledge, rules, handoffs), processa, e gera o contexto que o agente recebe. A token economy do harness.os e uma forma de otimizacao de compilador: eliminar informacao redundante, comprimir contexto, priorizar o que e relevante.

!
Conexao importante Ao longo deste curso, vamos mapear cada fase do compilador para uma operacao equivalente no harness.os. Isso nao e apenas uma analogia — entender compiladores vai te dar ferramentas concretas para melhorar o pipeline de processamento de conhecimento do harness.

Resumo

Exercicio

Mapeie o pipeline de processamento de conhecimento do harness.os para as fases de compilacao. Para cada fase, identifique:

  1. Qual e a entrada?
  2. Qual e a saida?
  3. Que tipo de erro pode ser detectado nessa fase?
  4. Existe uma ferramenta MCP correspondente?

Verifique seu entendimento

Qual e a principal vantagem de separar o compilador em front-end e back-end com uma representacao intermediaria (IR)?

  • Torna o compilador mais rapido em tempo de execucao
  • Elimina a necessidade de otimizacao
  • Permite combinar M linguagens com N alvos usando M+N componentes em vez de M*N
  • Garante que o codigo gerado sera sempre otimo