Skip to content
Ridgun
English

Ridgun

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

01-benvenuto-in-ridgun.md195 lines · 11.5 KBRaw
1# Capitolo 01: Il tuo primo contatto con Ridgun (Senza caschi, senza parentesi graffe e senza punti e virgola)
2
3Bene, nel Capitolo 00 ti ho già convinto che non siamo pazzi per aver creato Ridgun. Ora probabilmente starai pensando:
4
5> *"Molto bello il discorso sulle tabelle e sui 16 core, ma mostrami del codice vero. Quanto ci mette uno a scrivere qualcosa che funzioni senza litigare con il compilatore?"*
6
7Dai, andiamo al sodo!
8
9---
10
11## 1.1. "Ciao, mondo!", ma con sostanza
12
13Nella maggior parte dei libri di programmazione ti mostrano uno sciapo `print("Ciao mondo")` e voltano pagina. Noi scriveremo direttamente una funzione con logica reale per farti vedere come respira Ridgun fin dal primo minuto.
14
15Crea un file chiamato `ciao.rg` e scrivi questo:
16
17```ridgun
18saluto String => String
19saluto "" = "Ciao, viaggiatore misterioso! (Non mi hai detto il tuo nome)"
20saluto "Root" = "Ehilà, Root! Attento a quello che cancelli oggi."
21saluto nome = "Ciao, {nome}! Benvenuto in Ridgun."
22
23main => ()
24main =
25 echo (saluto "Ada")
26 echo (saluto "Root")
27 echo (saluto "")
28```
29
30Per eseguirlo subito:
31
32```bash
33ridgunc run ciao.rg
34```
35
36E vedrai nel tuo terminale:
37
38```text
39Ciao, Ada! Benvenuto in Ridgun.
40Ehilà, Root! Attento a quello che cancelli oggi.
41Ciao, viaggiatore misterioso! (Non mi hai detto il tuo nome)
42```
43
44Fermati un attimo e guarda il blocco di `saluto` qui sopra. Noti cosa **NON** c'è?
45- **Non c'è `function`, né `def`, né `pub fn`** (se vuoi mettere `fn ::` davanti alla firma puoi farlo, ma è facoltativo).
46- **Non ci sono parentesi `(String nome)` né parentesi graffe `{ ... }`** a sporcare lo schermo.
47- **Non c'è `if (nome == "") ... else if (nome == "Root") ... else ...`**.
48- **Non c'è `return`**.
49
50---
51
52## 1.2. Come il tuo cervello legge un file `.rg`
53
54Analizziamo quelle quattro righe di `saluto`, perché qui c'è già il 50% della filosofia di Ridgun:
55
56```ridgun
57saluto String => String
58saluto "" = "Ciao, viaggiatore misterioso! (Non mi hai detto il tuo nome)"
59saluto "Root" = "Ehilà, Root! Attento a quello che cancelli oggi."
60saluto nome = "Ciao, {nome}! Benvenuto in Ridgun."
61```
62
631. **La prima riga è il contratto (`saluto String => String`)**:
64 Dice: *"Mi chiamo `saluto`, ricevo uno `String` e ti restituisco (`=>`) un altro `String`"*. Punto. Se qualcuno prova a chiamarmi passandomi il numero `42`, il compilatore gli batterà sulla spalla prima ancora di eseguire il programma.
652. **Le righe sotto sono i casi (dall'alto verso il basso)**:
66 - Mi hai passato la stringa vuota `""`? Restituisco la prima frase.
67 - Mi hai passato esattamente `"Root"`? Restituisco la seconda frase.
68 - Mi hai passato qualsiasi altra cosa? La salvo nella variabile `nome` e la inserisco nel testo usando `{nome}`.
693. **E cos'è `main => ()`?**:
70 Poiché `main` non riceve argomenti, mettiamo `=>` direttamente dopo il nome. E restituisce `()` (il tipo vuoto o *Unit*, per gli amici), perché il suo unico lavoro è stampare cose a schermo con `echo`.
71
72---
73
74## 1.3. "Aspetta... devo allineare quegli spazi a mano come un monaco amanuense?"
75
76Neanche per sogno! Se dovessi premere la barra spaziatrice contando le colonne a occhio, abbandoneresti Ridgun dopo dieci minuti (e a ragione).
77
78Tu scrivi il codice in fretta, con un solo spazio tra ogni parola:
79
80```ridgun
81saluto String => String
82saluto "" = "Ciao, viaggiatore misterioso!"
83saluto nome = "Ciao, {nome}!"
84```
85
86E quando esegui **`stable format`** (o premi `TAB` / salvi il file in Emacs con `ridgun-mode`), il formattatore canonico posiziona ogni parametro sotto il suo tipo e allinea tutti gli `=` con precisione millimetrica. Tu scrivi veloce; la macchina impagina la tabella.
87
88---
89
90## 1.4. Da script veloce a binario da combattimento in un comando
91
92Quando fai `ridgunc run ciao.rg`, stai compilando e lanciando il programma al volo. Ma immagina di aver finito il tuo strumento e di volerlo portare su un server di produzione o condividerlo con un collega che non ha installato Ridgun.
93
94Esegui:
95
96```bash
97ridgunc build ciao.rg -o ciao
98```
99
100E hai già `./ciao`: un **eseguibile nativo ELF per Linux x86_64**, pulito, senza codice morto (*Tree-Shaking*), con ottimizzazione dell'intero collegamento (*LTO*) e senza dipendere da alcun interprete esterno.
101
102---
103
104## 1.5. Il promemoria onesto: Da dove viene ogni idea di Ridgun?
105
106Ridgun non pretende di reinventare la ruota quadrata; prende in prestito senza complessi il meglio di quattro tradizioni:
107
108| Da chi | Cosa prende Ridgun | Cosa lascia fuori (per la tua salute mentale) |
109|---|---|---|
110| **Haskell / ML** | Funzioni pure, *pattern matching* per casi, tipi algebrici (`Option`, `Result`) e polimorfismo (`A`..`Z`). | Le monadi astratte, i 40 `LANGUAGE pragma` e il garbage collector. |
111| **J / APL** | L'ossessione per la forma tabellare del codice, tensori nativi e maschere di sequenze (`s(_ + _)`). | I simboli geroglifici impossibili da digitare su una tastiera normale. |
112| **Rust / C** | Binari ELF nativi piccoli, zero GC, controllo della memoria (`with region`) e chiamate di sistema POSIX. | La lotta costante con il *borrow checker*, i *lifetime* `'a` e la verbosità sintattica. |
113| **Erlang / Go** | Agenti isolati (`agent`, `send ... to`, `receive from`) e concorrenza tramite canali (`new bounded channel`). | I puntatori `nil` e le mutazioni condivise per distrazione. |
114
115---
116
117## 1.6. E la cosa più importante: Cosa fa Ridgun che NON ha nessun altro?
118
119Riconoscere i classici è buona educazione, ma se Ridgun fosse solo una "raccolta dei più grandi successi" di altri linguaggi, non staresti leggendo questo libro.
120
121Ci sono **otto cose** che abbiamo progettato e integrato in Ridgun che non troverai insieme — e molte di esse, nemmeno separatamente — in nessun altro linguaggio attuale:
122
123### 1. Blocchi paralleli `||` con `->` che sono veri grafi paralleli, non semplice zucchero sintattico
124In altri linguaggi funzionali un blocco di variabili locali ordina solo espressioni che poi vengono valutate su un singolo thread.
125In Ridgun, **un blocco `||` con frecce `->` è un Grafo Aciclico Diretto (DAG) di esecuzione parallela** senza nemmeno dover scrivere parole chiave extra come `where`:
126```ridgun
127rapporto annuale Int => Int
128rapporto annuale id = entrate - spese
129 || calcola vendite id -> entrate
130 || calcola costi id -> spese
131```
132Tu disegni le frecce di flusso (`->`). Il compilatore analizza chi dipende da chi, **verifica staticamente che tu non abbia creato alcun ciclo infinito**, e lancia i rami indipendenti in parallelo senza che tu scriva nemmeno un singolo `async`, `await`, `Future` o `Mutex`.
133
134### 2. Modello Nativo di Agenti (`agent`) a zero attrito con scelta intelligente in compilazione
135In altri linguaggi, programmare con attori o agenti ti obbliga a creare classi speciali, implementare *trait*, gestire *lock* o infettare le tue funzioni con `async`.
136In Ridgun, **qualsiasi funzione pura normale (`fn ::` o `op ::`) si trasforma direttamente in un agente autonomo — con o senza stato isolato — usando `agent`**:
137```ridgun
138servi http (Sessione, String) => (Sessione, String)
139...
140server = agent servi http sessione_iniziale
141send "GET /profilo" to server
142risposta = receive from server
143stop server
144```
145Ancora meglio: il compilatore **analizza a tempo di compilazione la profondità e il costo computazionale della funzione** sia in `agent` che in `||` e `||map`. Se la funzione è leggera, la esegue come un *green thread* istantaneo senza pagare il costo di riscaldare thread del sistema operativo; se è un calcolo pesante o ricorsivo profondo, la smista automaticamente in parallelo su thread reali del kernel (`SYS_clone`) distribuiti sui core della tua CPU.
146
147### 3. Il codice come tabella bidimensionale in cui la firma è l'intestazione delle colonne
148In qualsiasi altro linguaggio, la firma dei tipi va per conto suo su una riga e il corpo della funzione va sotto come un normale paragrafo di testo.
149In Ridgun, **la firma dei tipi è letteralmente l'intestazione di una tabella**, e ogni caso sottostante allinea ogni pattern esattamente sulla verticale del suo tipo e ogni `=` sotto il `=>`:
150```ridgun
151dividi Int Int => Option
152dividi _ 0 = None
153dividi a b = Some (a / b)
154```
155Nessun altro tratta la firma e le equazioni come un'unica matrice visiva verificata dal compilatore e impaginata automaticamente da `stable format`.
156
157### 4. Operatori frase (*Mixfix* N-ari) tipizzati e allineati (`op ::`)
158Nella maggior parte dei linguaggi, o ti accontenti di `+`, `-`, `*` o al massimo definisci un operatore binario criptico come `<|>` che nessuno sa cosa significhi.
159In Ridgun puoi creare **operatori che sono frasi leggibili con tutti gli slot tipizzati che vuoi** (incluse parole contestuali come `type` o `with`):
160```ridgun
161op :: Int limitato tra Int e Int => Int
162 x limitato tra min e max =
163 | x < min = min
164 | x > max = max
165 | otherwise = x
166```
167E poi nel tuo codice scrivi `velocita limitato tra 0 e 120`. Si legge come italiano (o inglese), ma è tipizzato al 100% e compilato in codice nativo.
168
169### 5. Maschere visive sulle sequenze (`s(_ + _)` e `-> (+ _ _ +) ->`)
170Hai mai dovuto scrivere un'insalata di indici `filter(\(i, x) -> i % 2 == 0)` o aprire una tupla con variabili mute solo per tenerti due posizioni precise?
171In Ridgun gli passi direttamente una **maschera visiva**:
172- `dati(_ + _)`: scarta il primo (`_`), tiene il secondo (`+`), scarta il terzo (`_`).
173- `analizza pacchetto "v0.9.9" -> (+ _ _ +) -> combina codice -> riepilogo`: filtra una tupla di 4 elementi nel bel mezzo della pipeline e passa il 1.º e il 4.º direttamente come i 2 argomenti della funzione successiva.
174Zero aritmetica degli indici, zero errori *off-by-one*.
175
176### 6. Polimorfismo a "zero rumore" (`A`..`Z`) governato dal tuo dominio
177In Rust, TypeScript o Java, quando una funzione è generica devi riempire la riga di parentesi angolari: `fn scambia<A, B>(coppia: (A, B)) -> (B, A)`.
178In Ridgun usi semplicemente una lettera maiuscola singola:
179```ridgun
180scambia (A, B) => (B, A)
181scambia (x, y) = (y, x)
182```
183*"E se nel mio programma voglio avere un tipo reale che si chiami `type A`?"* — Nessun problema: in Ridgun **le tue dichiarazioni `type` comandano**. Se non esiste `type A`, `A` è generico; nell'istante in cui definisci `type A = ...`, diventa il tuo tipo concreto in tutto il modulo.
184
185### 7. Zero file di configurazione strani: `build.rg` è puro Ridgun
186Dimenticati di imparare TOML per Cargo, JSON per npm, XML per Maven o la sintassi arcana di `Makefile` con tabulazioni invisibili. In Ridgun, la ricetta che costruisce il tuo progetto (`build.rg`) **è un file `.rg` come gli altri**, con le stesse funzioni pure e lo stesso *pattern matching* del resto del tuo codice.
187
188### 8. La "Santissima Trinità" che sembrava impossibile: Livello Haskell + Memoria RMM senza GC né Lifetime + Binari da ~350 KB
189Fino a oggi dovevi scegliere:
190- Se volevi espressività funzionale pura (Haskell, OCaml, Elixir), pagavi con un garbage collector e un runtime pesante.
191- Se volevi binari minuscoli di sistema senza garbage collector (C, Rust, Zig), pagavi gestendo puntatori o litigando con il *borrow checker* e scrivendo codice imperativo pieno di `let mut`.
192
193Ridgun rompe questo dilemma combinando **Ridgun Memory Management (`RMM`: `RMM1` statica e `RMM2` per conteggio di assegnazioni a cascata)**, **regioni lessicali (`with region`)** che liberano intere arene in $O(1)$, **ricorsione di coda trasformata in cicli nativi (`loop`)**, e **potatura del grafo delle chiamate (*Tree-Shaking*)** a partire da `main`. Il risultato: scrivi codice dichiarativo di altissimo livello e ottieni un eseguibile ELF autonomo da **~350 KB** capace di competere alla pari con strumenti scritti in C.
194
195Ora sì: con le carte in tavola, andiamo al **Capitolo 02** per mettere al lavoro **`ridgunc`** e **`stable`**.