Skip to content
Ridgun
English

Ridgun

The language itself: a compiler that compiles itself, the stable project tool, the specification and the book

01-bem-vindo-ao-ridgun.md195 lines · 11.5 KBRaw
1# Capítulo 01: O seu primeiro contacto com o Ridgun (Sem capacetes, sem chavetas e sem pontos e vírgulas)
2
3Muito bem, já o convenci no Capítulo 00 de que não estamos loucos por criar o Ridgun. Agora provavelmente está a pensar:
4
5> *"Muito bonito o discurso das tabelas e dos 16 núcleos, mas mostre-me código de verdade. Quanto tempo demora alguém a escrever algo que funcione sem andar à pancada com o compilador?"*
6
7Vamos lá, mãos à obra!
8
9---
10
11## 1.1. "Olá, mundo!", mas com substância
12
13Na maioria dos livros de programação ensinam-lhe um `print("Olá mundo")` insosso e viram a página. Nós vamos escrever diretamente uma função com lógica real para que veja como o Ridgun respira desde o primeiro minuto.
14
15Crie um ficheiro chamado `ola.rg` e escreva isto:
16
17```ridgun
18saudacao String => String
19saudacao "" = "Olá, viajante misterioso! (Não me disseste o teu nome)"
20saudacao "Root" = "Ora viva, Root! Cuidado com o que apagas hoje."
21saudacao nome = "Olá, {nome}! Bem-vindo ao Ridgun."
22
23main => ()
24main =
25 echo (saudacao "Ada")
26 echo (saudacao "Root")
27 echo (saudacao "")
28```
29
30Para o executar agora mesmo:
31
32```bash
33ridgunc run ola.rg
34```
35
36E verá no seu terminal:
37
38```text
39Olá, Ada! Bem-vindo ao Ridgun.
40Ora viva, Root! Cuidado com o que apagas hoje.
41Olá, viajante misterioso! (Não me disseste o teu nome)
42```
43
44Pare um momento e olhe para o bloco de `saudacao` acima. Nota o que **NÃO** há?
45- **Não há `function`, nem `def`, nem `pub fn`** (se quiser pôr `fn ::` antes da assinatura pode fazê-lo, mas é opcional).
46- **Não há parênteses `(String nome)` nem chavetas `{ ... }`** a sujar o ecrã.
47- **Não há `if (nome == "") ... else if (nome == "Root") ... else ...`**.
48- **Não há `return`**.
49
50---
51
52## 1.2. Como o seu cérebro lê um ficheiro `.rg`
53
54Vamos dissecar essas quatro linhas de `saudacao`, porque aqui já está 50% da filosofia do Ridgun:
55
56```ridgun
57saudacao String => String
58saudacao "" = "Olá, viajante misterioso! (Não me disseste o teu nome)"
59saudacao "Root" = "Ora viva, Root! Cuidado com o que apagas hoje."
60saudacao nome = "Olá, {nome}! Bem-vindo ao Ridgun."
61```
62
631. **A primeira linha é o contrato (`saudacao String => String`)**:
64 Diz: *"Chamo-me `saudacao`, recebo uma `String` e devolvo-lhe (`=>`) outra `String`"*. Ponto final. Se alguém tentar chamar-me passando o número `42`, o compilador dar-lhe-á um toque no ombro antes sequer de executar o programa.
652. **As linhas abaixo são os casos (de cima para baixo)**:
66 - Passou-me a cadeia vazia `""`? Devolvo a primeira frase.
67 - Passou-me exatamente `"Root"`? Devolvo a segunda frase.
68 - Passou-me qualquer outra coisa? Guardo-a na variável `nome` e coloco-a dentro do texto usando `{nome}`.
693. **E o que é `main => ()`?**:
70 Como `main` não recebe argumentos, pomos `=>` diretamente depois do nome. E devolve `()` (o tipo vazio ou *Unit*, para os amigos), porque o seu único trabalho é mostrar coisas no ecrã com `echo`.
71
72---
73
74## 1.3. "Espere... tenho de alinhar esses espaços à mão como um monge copista?"
75
76Nem pensar! Se tivesse de carregar na barra de espaços a contar colunas a olho, abandonaria o Ridgun ao fim de dez minutos (e com razão).
77
78Escreve o código depressa, com um único espaço entre cada palavra:
79
80```ridgun
81saudacao String => String
82saudacao "" = "Olá, viajante misterioso!"
83saudacao nome = "Olá, {nome}!"
84```
85
86E quando executa **`stable format`** (ou prime `TAB` / guarda o ficheiro no Emacs com `ridgun-mode`), o formatador canónico coloca cada parâmetro debaixo do seu tipo e alinha todos os `=` com precisão milimétrica. Você escreve rápido; a máquina pagina a tabela.
87
88---
89
90## 1.4. De script rápido a binário de combate num só comando
91
92Quando faz `ridgunc run ola.rg`, está a compilar e a lançar o programa na hora. Mas imagine que já terminou a sua ferramenta e quer levá-la para um servidor de produção ou partilhá-la com um colega que não tem o Ridgun instalado.
93
94Executa:
95
96```bash
97ridgunc build ola.rg -o ola
98```
99
100E já tem `./ola`: um **executável nativo ELF de Linux x86_64**, limpo, sem código morto (*Tree-Shaking*), com otimização de ligação completa (*LTO*) e sem depender de nenhum interpretador externo.
101
102---
103
104## 1.5. A cábula honesta: De onde vem cada ideia do Ridgun?
105
106O Ridgun não pretende reinventar a roda quadrada; pede emprestado sem complexos o melhor de quatro tradições:
107
108| De quem | O que o Ridgun aproveita | O que deixa de fora (pela sua saúde mental) |
109|---|---|---|
110| **Haskell / ML** | Funções puras, *pattern matching* por casos, tipos algébricos (`Option`, `Result`) e polimorfismo (`A`..`Z`). | As mónadas abstratas, os 40 `LANGUAGE pragmas` e o coletor de lixo. |
111| **J / APL** | A obsessão pela forma tabular do código, tensores nativos e máscaras de sequências (`s(_ + _)`). | Os símbolos hieroglíficos impossíveis de escrever num teclado normal. |
112| **Rust / C** | Binários ELF nativos pequenos, zero GC, controlo de memória (`with region`) e chamadas ao sistema POSIX. | A luta constante com o *borrow checker*, os *lifetimes* `'a` e a verbosidade sintática. |
113| **Erlang / Go** | Agentes isolados (`agent`, `send ... to`, `receive from`) e concorrência por canais (`new bounded channel`). | Os ponteiros `nil` e as mutações partilhadas por descuido. |
114
115---
116
117## 1.6. E o mais importante: O que faz o Ridgun que NINGUÉM mais tem?
118
119Reconhecer os clássicos é sinal de boa educação, mas se o Ridgun fosse apenas uma "coletânea de grandes êxitos" de outras linguagens, não estaria a ler este livro.
120
121Há **oito coisas** que desenhámos e integrámos no Ridgun que não vai encontrar juntas — e muitas delas, nem sequer em separado — em nenhuma outra linguagem atual:
122
123### 1. Blocos paralelos `||` com `->` que são grafos paralelos reais, não simples açúcar sintático
124Noutras linguagens funcionais, um bloco de variáveis locais apenas ordena expressões que depois são avaliadas numa única thread.
125Em Ridgun, **um bloco `||` com setas `->` é um Grafo Acíclico Dirigido (DAG) de execução paralela** sem sequer precisar de escrever palavras-chave extra como `where`:
126```ridgun
127relatorio anual Int => Int
128relatorio anual id = receitas - despesas
129 || calcular vendas id -> receitas
130 || calcular custos id -> despesas
131```
132Você desenha as setas de fluxo (`->`). O compilador analisa quem depende de quem, **verifica estaticamente que não criou nenhum ciclo infinito**, e lança os ramos independentes em paralelo sem que escreva um único `async`, `await`, `Future` nem `Mutex`.
133
134### 2. Modelo Nativo de Agentes (`agent`) de zero fricção com escolha inteligente em compilação
135Noutras linguagens, programar com atores ou agentes obriga-o a criar classes especiais, implementar *traits*, gerir *locks* ou infetar as suas funções com `async`.
136Em Ridgun, **qualquer função pura normal (`fn ::` ou `op ::`) converte-se diretamente num agente autónomo — com ou sem estado isolado — usando `agent`**:
137```ridgun
138atender http (Sessao, String) => (Sessao, String)
139...
140servidor = agent atender http sessao_inicial
141send "GET /perfil" to servidor
142resposta = receive from servidor
143stop servidor
144```
145Melhor ainda: o compilador **analisa em tempo de compilação a profundidade e o custo computacional da função** tanto em `agent` como em `||` e `||map`. Se a função for leve, executa-a como uma *green thread* instantânea sem pagar o custo de aquecer threads do sistema operativo; se for um cálculo pesado ou recursivo profundo, despacha-a automaticamente em paralelo sobre threads reais do kernel (`SYS_clone`) distribuídas pelos núcleos do seu CPU.
146
147### 3. O código como tabela bidimensional onde a assinatura é o cabeçalho das colunas
148Em qualquer outra linguagem, a assinatura de tipos anda solta numa linha e o corpo da função vai por baixo como um parágrafo de texto normal.
149Em Ridgun, **a assinatura de tipos é literalmente o cabeçalho de uma tabela**, e cada caso abaixo alinha cada padrão exatamente na vertical do seu tipo e cada `=` debaixo do `=>`:
150```ridgun
151dividir Int Int => Option
152dividir _ 0 = None
153dividir a b = Some (a / b)
154```
155Mais ninguém trata a assinatura e as equações como uma única matriz visual verificada pelo compilador e paginada automaticamente pelo `stable format`.
156
157### 4. Operadores frase (*Mixfix* N-ários) tipados e alinhados (`op ::`)
158Na maioria das linguagens, ou se aguenta com `+`, `-`, `*` ou no máximo define um operador binário críptico como `<|>` que ninguém sabe o que significa.
159Em Ridgun pode criar **operadores que são frases legíveis com tantos espaços tipados quantos quiser** (incluindo palavras contextuais como `type` ou `with`):
160```ridgun
161op :: Int limitado entre Int e Int => Int
162 x limitado entre min e max =
163 | x < min = min
164 | x > max = max
165 | otherwise = x
166```
167E depois no seu código escreve `velocidade limitado entre 0 e 120`. Lê-se como português (ou inglês), mas está 100% tipado e compilado para código nativo.
168
169### 5. Máscaras visuais sobre sequências (`s(_ + _)` e `-> (+ _ _ +) ->`)
170Alguma vez teve de escrever uma salada de índices ou abrir uma tupla com variáveis mudas só para ficar com duas posições concretas?
171Em Ridgun passa-lhe diretamente uma **máscara visual**:
172- `dados(_ + _)`: descarta o primeiro (`_`), fica com o segundo (`+`), descarta o terceiro (`_`).
173- `analisar pacote "v0.9.9" -> (+ _ _ +) -> combinar codigo -> resumo`: filtra uma tupla de 4 elementos em plena tubagem e passa o 1.º e o 4.º diretamente como argumentos da função seguinte.
174Zero aritmética de índices, zero erros *off-by-one*.
175
176### 6. Polimorfismo de "zero ruído" (`A`..`Z`) governado pelo seu domínio
177Em Rust, TypeScript ou Java, quando uma função é genérica tem de encher a linha de parênteses angulares: `fn trocar<A, B>(par: (A, B)) -> (B, A)`.
178Em Ridgun usa simplesmente uma letra maiúscula solta:
179```ridgun
180trocar (A, B) => (B, A)
181trocar (x, y) = (y, x)
182```
183*"E se no meu programa eu quiser ter um tipo real que se chame `type A`?"* — Sem problema: em Ridgun **as suas declarações `type` mandam**. Se não existir `type A`, `A` é genérico; no instante em que define `type A = ...`, passa a ser o seu tipo concreto em todo o módulo.
184
185### 7. Zero ficheiros de configuração estranhos: `build.rg` é Ridgun puro
186Esqueça aprender TOML para o Cargo, JSON para o npm, XML para o Maven ou a sintaxe arcana de `Makefile` com tabulações invisíveis. Em Ridgun, a receita que constrói o seu projeto (`build.rg`) **é mais um ficheiro `.rg`**, com as mesmas funções puras e o mesmo *pattern matching* que o resto do seu código.
187
188### 8. A "Santíssima Trindade" que parecia impossível: Nível Haskell + Memória RMM sem GC nem Lifetimes + Binários de ~350 KB
189Até hoje tinha de escolher:
190- Se queria expressividade funcional pura (Haskell, OCaml, Elixir), pagava com um coletor de lixo e um runtime pesado.
191- Se queria binários diminutos de sistema sem coletor de lixo (C, Rust, Zig), pagava gerindo ponteiros ou lutando com o *borrow checker* e escrevendo código imperativo cheio de `let mut`.
192
193O Ridgun rompe esse dilema combinando **Ridgun Memory Management (`RMM`: `RMM1` estática e `RMM2` por contagem de atribuições em cascata)**, **regiões léxicas (`with region`)** que libertam arenas inteiras em $O(1)$, **recursão de cauda transformada em ciclos nativos (`loop`)**, e **poda de grafo de chamadas (*Tree-Shaking*)** a partir de `main`. O resultado: escreve código declarativo de altíssimo nível e obtém um executável ELF autónomo de **~350 KB** capaz de competir de igual para igual com ferramentas escritas em C.
194
195Agora sim: com as cartas na mesa, vamos ao **Capítulo 02** para pôr a trabalhar o **`ridgunc`** e o **`stable`**.