🔍 Por Trás dos Panos
Entenda como seu código Jech é processado e executado
🎯 O que você vai aprender
Nesta página, você vai descobrir como o comando say("hello world");
passa por cada etapa do nosso compilador/interpretador até ser executado.
Vamos explorar todas as fases: desde a análise léxica até a execução final.
🚀 Demonstração Interativa
Digite um código Jech e veja como ele é processado em cada etapa:
📝 Análise Léxica (Lexer)
⏳O código fonte é dividido em tokens (unidades mínimas de significado).
Cada caractere é lido e agrupado em categorias: palavras-chave, identificadores, operadores, literais, etc.
🌳 Análise Sintática (Parser)
⏳Os tokens são organizados em uma Árvore Sintática Abstrata (AST).
O parser verifica se a sequência de tokens segue as regras gramaticais da linguagem.
🔍 Análise Semântica
⏳Verifica se o código faz sentido lógico.
Checa tipos de dados, escopo de variáveis, e se funções/variáveis foram declaradas antes de serem usadas.
⚙️ Geração de Código Intermediário
⏳A AST é convertida em bytecode ou código intermediário.
Este formato é mais fácil de executar e otimizar que a AST original.
🎯 Execução (Runtime)
⏳O código intermediário é executado pela máquina virtual.
A VM interpreta cada instrução e executa as operações correspondentes.
📚 Explicação Detalhada de Cada Etapa
1. Análise Léxica (Lexer/Tokenizer)
O que faz: Transforma o código fonte (string) em uma sequência de tokens.
Exemplo:
say("hello world");
[
{ type: 'IDENTIFIER', value: 'say' },
{ type: 'LPAREN', value: '(' },
{ type: 'STRING', value: 'hello world' },
{ type: 'RPAREN', value: ')' },
{ type: 'SEMICOLON', value: ';' }
]
Como funciona:
- Lê o código caractere por caractere
- Ignora espaços em branco e comentários
- Agrupa caracteres em tokens significativos
- Identifica o tipo de cada token (palavra-chave, operador, literal, etc.)
2. Análise Sintática (Parser)
O que faz: Organiza os tokens em uma estrutura hierárquica (AST) que representa a estrutura do programa.
Exemplo:
CallExpression
├── callee: Identifier("say")
└── arguments:
└── StringLiteral("hello world")
Como funciona:
- Consome tokens da esquerda para a direita
- Aplica regras gramaticais da linguagem
- Constrói uma árvore que representa a estrutura do código
- Detecta erros de sintaxe (parênteses não fechados, etc.)
3. Análise Semântica
O que faz: Verifica se o código faz sentido do ponto de vista lógico.
Verificações realizadas:
- ✅ A
função
sayexiste? - ✅ O número de argumentos está correto?
- ✅ Os tipos de dados são compatíveis?
- ✅ As variáveis foram declaradas antes do uso?
Como funciona:
- Percorre a AST verificando regras semânticas
- Mantém uma tabela de símbolos (variáveis e funções declaradas)
- Verifica compatibilidade de tipos
- Detecta erros como variáveis não declaradas ou tipos incompatíveis
4. Geração de Código Intermediário
O que faz: Converte a AST em instruções mais simples e otimizadas.
Exemplo de Bytecode:
LOAD_CONST "hello world" ; Carrega a string
LOAD_GLOBAL say ; Carrega a função say
CALL_FUNCTION 1 ; Chama com 1 argumento
POP_TOP ; Remove resultado da pilha
Como funciona:
- Traduz cada nó da AST em instruções simples
- Usa uma representação baseada em pilha
- Aplica otimizações básicas
- Gera código independente de plataforma
5. Execução (Runtime)
O que faz: Executa as instruções do bytecode usando uma máquina virtual.
Processo de Execução:
- VM lê
a instrução
LOAD_CONST "hello world" - Empilha a string na pilha de operandos
- Lê
LOAD_GLOBAL saye empilha a função -
Executa
CALL_FUNCTION 1: desempilha função e argumento, executa - A
função
sayimprime "hello world" no console -
POP_TOPremove o resultado da pilha
Como funciona:
- Mantém uma pilha de operandos e frames de chamada
- Executa instruções em um loop (fetch-decode-execute)
- Gerencia memória para variáveis e objetos
- Interage com funções nativas (como
say)