Um compilador/interpretador experimental escrito em Rust para uma linguagem com sintaxe inspirada no Python, mas com regras explícitas de tipagem estática e blocos delimitados por end. O projeto nasceu como ferramenta acadêmica para explorar conceitos de construção de compiladores e interpretação de linguagens.
🔎 Precisa copiar o README inteiro? A versão crua está disponível em
README.md, bastando abrir o arquivo em modo Raw no GitHub ou executarcat README.mdapós clonar o repositório.
- Visão Geral
- Arquitetura em Alto Nível
- Catálogo de Features da Linguagem
- Literais e Operações Numéricas
- Lógica Booleana e Comparações
- Listas e Tuplas
- Declarações
val/vare Atribuições - Controle de Fluxo (
if/elif/else,while,for) - Funções Tipadas, Retorno e Recursão
- Assertions em Tempo de Execução
- Blocos de Teste Automatizado
- Valores
Resulte Propagação de Erros - Valores
Maybe(Opcionais) - Construtores de Tipos Algébricos (ADT)
- Guia Rápido
- Documentação Complementar
- Contribuindo
RPython tem como foco:
- Aprendizado de compiladores: o código-fonte serve como laboratório para parsing, análise semântica, verificação de tipos e interpretação.
- Linguagem familiar: a sintaxe lembra Python, mas inclui recursos clássicos de linguagens fortemente tipadas (anotações obrigatórias em funções, declarações
var/val, ADTs em desenvolvimento). - Ferramentas modernas: todo o pipeline é escrito em Rust, aproveitando segurança de memória e uma rica base de testes automatizados.
- Parser (
src/parser) – Constrói a Árvore de Sintaxe Abstrata (AST) a partir do código-fonte utilizandonom. - IR/AST (
src/ir) – Define as estruturas centrais da linguagem (expressões, declarações, tipos e construtores). - Environment (
src/environment) – Implementa pilha de escopos para variáveis, funções e tipos. - Type Checker (
src/type_checker) – Analisa programas para garantir consistência de tipos antes da execução. (Algumas funcionalidades avançadas ainda estão em desenvolvimento.) - Interpreter (
src/interpreter) – Avalia a AST produzindo resultados de execução. - Pretty Printer (
src/pretty_print) – Gera representações legíveis da AST, útil para debugging e tooling.
Os módulos de AST, parser, verificação de tipos e interpretador já oferecem um conjunto sólido de recursos — de operações aritméticas a estruturas de controle, passando por coleções, funções tipadas e tratamento de erros. Consulte src/ir/ast.rs e src/parser/parser_stmt.rs para ver a implementação completa de cada construção apresentada abaixo. A seguir reunimos exemplos autoexplicativos para cada feature disponível hoje.
val inteiro = 42;
val real = 3.14;
val soma = inteiro + 8;
val mix = real * 2.0 - inteiro;
val divisao = inteiro / 2;
val idade = 20;
val possui_autorizacao = False;
val maior_de_idade = idade >= 18;
val pode_participar = maior_de_idade or possui_autorizacao;
val precisa_aviso = not maior_de_idade and possui_autorizacao == False;
val lista_vazia = [];
val linguagens = ["RPython", "Rust", "Python"];
val pares = [(1, "um"), (2, "dois")];
val coordenada = (latitude, longitude, "Norte");
ℹ️ Listas e tuplas aparecem como
ListValueeTuplena AST, garantindo suporte a coleções homogêneas e heterogêneas (vejasrc/ir/ast.rs).
val nome = "RPython"; # imutável
var contador = 0; # mutável
contador = contador + 1;
val saudacao = "Olá, " + nome;
ℹ️ Declarações
val/vare reatribuições são modeladas porStatement::ValDeclaration,Statement::VarDeclarationeStatement::Assignmentemsrc/ir/ast.rs.
if nota >= 9:
conceito = "Excelente";
elif nota >= 7:
conceito = "Bom";
else:
conceito = "Recuperação";
end
var total = 0;
while total < 3:
total = total + 1;
end
val numeros = [1, 2, 3];
var soma = 0;
for n in numeros:
soma = soma + n;
end
ℹ️ O núcleo reconhece
if/elif/else, laçoswhileeforcomo variantes específicas da AST, preservando o bloco associado a cada controle de fluxo (implementações emsrc/ir/ast.rsesrc/parser/parser_stmt.rs).
def fibonacci(n: Int) -> Int:
if n <= 1:
return n;
end
return fibonacci(n - 1) + fibonacci(n - 2);
end;
val resultado = fibonacci(10);
asserttrue(resultado == 55, "Fib(10) deve ser 55");
ℹ️ Funções são representadas por
Function+Statement::FuncDef, com anotações obrigatórias de tipos de parâmetros e retorno (src/ir/ast.rsesrc/parser/parser_stmt.rs).
asserttrue(condicao, "Mensagem de sucesso");
assertfalse(condicao, "Mensagem de erro");
asserteq(resultado, esperado, "Valores devem ser iguais");
assertneq(id_atual, ultimo_id, "IDs não podem coincidir");
ℹ️ Há variantes dedicadas para cada assertiva (
Assert,AssertTrue,AssertFalse,AssertEQ,AssertNEQ) que permitem mensagens customizadas e integração com o runner de testes (detalhes emsrc/ir/ast.rs).
test soma_basica():
val resultado = 2 + 3;
asserttrue(resultado == 5, "2 + 3 deve ser 5");
end
ℹ️ O interpretador expõe
Statement::TestDefpara registrar casos de teste e executá-los isoladamente com coleta de resultados (vejasrc/ir/ast.rsesrc/interpreter/statement_execute.rs).
def dividir(a: Int, b: Int) -> Result[Int, String]:
if b == 0:
return Err("Divisão por zero");
end
return Ok(a / b);
end;
def dividir_e_incrementar(a: Int, b: Int, inc: Int) -> Result[Int, String]:
val quociente = dividir(a, b)?; # Propaga Err automaticamente
return Ok(quociente + inc);
end;
val resultado = dividir_e_incrementar(10, 2, 1);
assertfalse(is_error(resultado), "Esperávamos um Ok");
ℹ️ Resultado de erros utiliza as variantes
COk,CErr,Propagate,IsErroreUnwrapdentro da AST e do interpretador, cobrindo desde a construção até a propagação de falhas (src/ir/ast.rsesrc/interpreter/expression_eval.rs).
val nome = Just("RPython");
if is_nothing(nome):
assertfalse(True, "Nome não deveria ser Nothing");
end
val texto = nome!; # unwrap: lança erro se for Nothing
ℹ️ Valores opcionais contam com
CJust,CNothing,IsNothingeUnwrap, permitindo presença ou ausência de dados com verificação estática (consultesrc/ir/ast.rsesrc/type_checker/expression_type_checker.rs).
data Forma:
| Circulo Int
| Retangulo Int Int
end
val figura = Circulo(5);
ℹ️ Tipos algébricos são descritos por
Type::TAlgebraicDataeValueConstructor, habilitando construtores nomeados com múltiplos campos (src/ir/ast.rs).
💡 A sintaxe usa
;para separar instruções dentro de blocos e a palavra-chaveendpara finalizar estruturas de controle e definições.
- Rust (última versão estável)
- Cargo (já incluído na instalação padrão do Rust)
- Git
git clone https://github.com/UnBCIC-TP2/r-python.git
cd r-python# Compilar o projeto
cargo build
# Executar a suíte de testes
cargo testVocê pode experimentar trechos da linguagem utilizando cargo test -- --nocapture para observar os programas de exemplo instrumentados no main. Em breve disponibilizaremos uma CLI dedicada para avaliar arquivos .rpy diretamente.
- Environment Module – Escopos, tabelas de símbolos e política de resolução de nomes.
- Parser Component – Estratégias de parsing com
nom, gramática suportada e exemplos de AST. - Type Checker Module – Regras de tipagem, tipos suportados e roadmap do verificador. (Em evolução)
Contribuições são muito bem-vindas! Antes de abrir issues ou enviar pull requests, consulte nossos guias:
Fique à vontade para sugerir melhorias na linguagem, adicionar novos exemplos ou expandir a documentação.