Skip to content
Ridgun
English

Ridgun

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

01-valkommen-till-ridgun.md195 lines · 11.6 KBRaw
1# Kapitel 01: Din första kontakt med Ridgun (Utan hjälm, utan måsvingar och utan semikolon)
2
3Okej, i Kapitel 00 övertygade jag dig om att vi inte är galna som har skapat Ridgun. Nu tänker du säkert:
4
5> *"Mycket fint snack om tabeller och 16 kärnor, men visa mig riktig kod. Hur lång tid tar det att skriva något som fungerar utan att behöva slåss med kompilatorn?"*
6
7Då kör vi — rakt på sak!
8
9---
10
11## 1.1. "Hej, världen!", men med substans
12
13I de flesta programmeringsböcker visar man ett trist `print("Hej världen")` och vänder blad. Vi ska gå direkt på att skriva en funktion med riktig logik så att du ser hur Ridgun andas från första minuten.
14
15Skapa en fil som heter `hej.rg` och skriv det här:
16
17```ridgun
18halsning String => String
19halsning "" = "Hej, mystiska resenär! (Du har inte sagt vad du heter)"
20halsning "Root" = "Men se där, Root! Var försiktig med vad du raderar i dag."
21halsning namn = "Hej, {namn}! Välkommen till Ridgun."
22
23main => ()
24main =
25 echo (halsning "Ada")
26 echo (halsning "Root")
27 echo (halsning "")
28```
29
30För att köra det direkt:
31
32```bash
33ridgunc run hej.rg
34```
35
36Och du kommer att se i din terminal:
37
38```text
39Hej, Ada! Välkommen till Ridgun.
40Men se där, Root! Var försiktig med vad du raderar i dag.
41Hej, mystiska resenär! (Du har inte sagt vad du heter)
42```
43
44Stanna upp ett ögonblick och titta på `halsning`-blocket ovan. Märker du vad som **INTE** finns där?
45- **Det finns inget `function`, inget `def` och inget `pub fn`** (om du vill sätta `fn ::` framför signaturen går det bra, men det är valfritt).
46- **Det finns inga parenteser `(String namn)` eller måsvingar `{ ... }`** som skräpar ner skärmen.
47- **Det finns inget `if (namn == "") ... else if (namn == "Root") ... else ...`**.
48- **Det finns inget `return`**.
49
50---
51
52## 1.2. Hur din hjärna läser en `.rg`-fil
53
54Låt oss plocka isär de fyra raderna i `halsning`, för här finns redan 50 % av Ridguns filosofi:
55
56```ridgun
57halsning String => String
58halsning "" = "Hej, mystiska resenär! (Du har inte sagt vad du heter)"
59halsning "Root" = "Men se där, Root! Var försiktig med vad du raderar i dag."
60halsning namn = "Hej, {namn}! Välkommen till Ridgun."
61```
62
631. **Den första raden är kontraktet (`halsning String => String`)**:
64 Den säger: *"Jag heter `halsning`, jag tar emot en `String` och jag ger dig tillbaka (`=>`) en annan `String`"*. Punkt. Om någon försöker anropa mig och skicka in talet `42` kommer kompilatorn att knacka dem på axeln innan programmet ens körs.
652. **Raderna nedanför är fallen (uppifrån och ner)**:
66 - Har du skickat in den tomma strängen `""`? Då returnerar jag den första meningen.
67 - Har du skickat in exakt `"Root"`? Då returnerar jag den andra meningen.
68 - Har du skickat in vad som helst annat? Då sparar jag det i variabeln `namn` och stoppar in det i texten med hjälp av `{namn}`.
693. **Och vad är `main => ()`?**:
70 Eftersom `main` inte tar några argument sätter vi `=>` direkt efter namnet. Och den returnerar `()` (den tomma typen eller *Unit*, vänner emellan), eftersom dess enda uppgift är att skriva ut saker på skärmen med `echo`.
71
72---
73
74## 1.3. "Vänta... måste jag rada upp de där mellanslagen för hand som en medeltida skrivarmunk?"
75
76Absolut inte! Om du var tvungen att trycka på mellanslagstangenten och räkna kolumner med ögonmått skulle du överge Ridgun efter tio minuter (och det med rätta).
77
78Du skriver koden snabbt, med ett enda mellanslag mellan varje ord:
79
80```ridgun
81halsning String => String
82halsning "" = "Hej, mystiska resenär!"
83halsning namn = "Hej, {namn}!"
84```
85
86Och när du kör **`stable format`** (eller trycker `TAB` / sparar filen i Emacs med `ridgun-mode`) placerar den kanoniska formateraren varje parameter under sin typ och justerar alla `=` med millimeterprecision. Du skriver snabbt; maskinen formger tabellen.
87
88---
89
90## 1.4. Från snabbt skript till stridsduglig binär med ett enda kommando
91
92När du kör `ridgunc run hej.rg` kompilerar och startar du programmet i farten. Men föreställ dig att du har blivit klar med ditt verktyg och vill ta med det till en produktionsserver eller dela det med en kollega som inte har Ridgun installerat.
93
94Du kör:
95
96```bash
97ridgunc build hej.rg -o hej
98```
99
100Och så har du `./hej`: en **inbyggd ELF-körbar fil för Linux x86_64**, ren, utan död kod (*Tree-Shaking*), med länkoptimering över hela programmet (*LTO*) och helt oberoende av någon extern tolk.
101
102---
103
104## 1.5. Den ärliga fusklappen: Varifrån kommer varje idé i Ridgun?
105
106Ridgun försöker inte uppfinna ett fyrkantigt hjul på nytt; det lånar skamlöst det bästa från fyra traditioner:
107
108| Från vem | Vad Ridgun lånar | Vad det lämnar utanför (för din mentala hälsas skull) |
109|---|---|---|
110| **Haskell / ML** | Rena funktioner, mönstermatchning (*pattern matching*) per fall, algebraiska datatyper (`Option`, `Result`) och polymorfism (`A`..`Z`). | De abstrakta monaderna, de 40 `LANGUAGE`-pragmana och skräpsamlaren. |
111| **J / APL** | Besattheten av kodens tabellform, inbyggda tensorer och sekvensmasker (`s(_ + _)`). | De hieroglyfiska symbolerna som är omöjliga att skriva på ett vanligt tangentbord. |
112| **Rust / C** | Små inbyggda ELF-binärer, noll GC, minneskontroll (`with region`) och POSIX-systemanrop. | Den ständiga kampen med *borrow checker*, livstider `'a` och syntaktisk mångordighet. |
113| **Erlang / Go** | Isolerade agenter (`agent`, `send ... to`, `receive from`) och samtidighet via kanaler (`new bounded channel`). | `nil`-pekare och delade muteringar av misstag. |
114
115---
116
117## 1.6. Och det viktigaste: Vad gör Ridgun som INGEN annan har?
118
119Att erkänna klassikerna hör till god ton, men om Ridgun bara vore en "Greatest Hits-samling" från andra språk skulle du inte läsa den här boken.
120
121Det finns **åtta saker** som vi har konstruerat och integrerat i Ridgun som du inte kommer att hitta tillsammans — och många av dem inte ens var för sig — i något annat nutida språk:
122
123### 1. Parallella `||`-block med `->` som är äkta parallella grafer, inte bara syntaktiskt socker
124I andra funktionella språk ordnar ett block med lokala variabler bara uttryck som sedan evalueras i en enda tråd.
125I Ridgun är **ett `||`-block med pilar `->` en riktad acyklisk graf (DAG) för parallell körning** utan att du ens behöver skriva extra nyckelord som `where`:
126```ridgun
127arsrapport Int => Int
128arsrapport id = intakter - utgifter
129 || berakna forsaljning id -> intakter
130 || berakna kostnader id -> utgifter
131```
132Du ritar flödespilarna (`->`). Kompilatorn analyserar vem som beror på vem, **verifierar statiskt att du inte har skapat någon oändlig cykel** och startar de oberoende grenarna parallellt utan att du skriver ett enda `async`, `await`, `Future` eller `Mutex`.
133
134### 2. Friktionsfri inbyggd agentmodell (`agent`) med smart trådval vid kompilering
135I andra språk tvingar aktörs- eller agentprogrammering dig att skapa specialklasser, implementera *traits*, hantera lås eller smitta ner dina funktioner med `async`.
136I Ridgun **förvandlas vilken vanlig ren funktion som helst (`fn ::` eller `op ::`) direkt till en autonom agent — med eller utan isolerat tillstånd — med hjälp av `agent`**:
137```ridgun
138hantera http (Session, String) => (Session, String)
139...
140server = agent hantera http startsession
141send "GET /profil" to server
142svar = receive from server
143stop server
144```
145Ännu bättre: kompilatorn **analyserar funktionens djup och beräkningskostnad vid kompilering** i både `agent`, `||` och `||map`. Om funktionen är lättviktig körs den som en omedelbar *green thread* utan kostnaden för att värma upp operativsystemtrådar; om den är en tung eller djupt rekursiv beräkning skickas den automatiskt ut parallellt över riktiga kärntrådar (`SYS_clone`) på dina CPU-kärnor.
146
147### 3. Koden som en tvådimensionell tabell där signaturen är kolumnrubriken
148I alla andra språk lever typsignaturen sitt eget liv på en rad och funktionskroppen ligger nedanför som ett vanligt textstycke.
149I Ridgun **är typsignaturen bokstavligen tabellens rubrikrad**, och varje fall nedanför justerar varje mönster rakt under sin typ och varje `=` under `=>`:
150```ridgun
151dividera Int Int => Option
152dividera _ 0 = None
153dividera a b = Some (a / b)
154```
155Ingen annan behandlar signaturen och ekvationerna som en enda visuell matris som verifieras av kompilatorn och formges automatiskt av `stable format`.
156
157### 4. Typade och justerade frasoperatorer (*N-ära Mixfix*) (`op ::`)
158I de flesta språk får du antingen nöja dig med `+`, `-`, `*` eller på sin höjd definiera en kryptisk binär operator som `<|>` som ingen vet vad den betyder.
159I Ridgun kan du skapa **operatorer som är läsbara fraser med så många typade platser du vill** (inklusive kontextuella ord som `type` eller `with`):
160```ridgun
161op :: Int begransad mellan Int och Int => Int
162 x begransad mellan min och max =
163 | x < min = min
164 | x > max = max
165 | otherwise = x
166```
167Och sedan skriver du i din kod `hastighet begransad mellan 0 och 120`. Det läses som vanlig svenska (eller engelska), men är till 100 % typat och kompilerat till maskinkod.
168
169### 5. Visuella masker över sekvenser (`s(_ + _)` och `-> (+ _ _ +) ->`)
170Har du någonsin behövt skriva en hel sallad av index eller packa upp en tupel med dummyvariabler bara för att behålla två specifika positioner?
171I Ridgun skickar du direkt in en **visuell mask**:
172- `data(_ + _)`: kastar det första (`_`), behåller det andra (`+`), kastar det tredje (`_`).
173- `tolka paket "v0.9.9" -> (+ _ _ +) -> kombinera kod -> sammanfattning`: filtrerar en tupel med 4 element mitt i en pipeline och skickar det 1:a och 4:e direkt som argument till nästa funktion.
174Noll indexaritmetik, noll *off-by-one*-fel.
175
176### 6. Polymorfism med "noll brus" (`A`..`Z`) styrd av din domän
177I Rust, TypeScript eller Java måste du fylla raden med vinkelparenteser när en funktion är generisk: `fn byt_plats<A, B>(par: (A, B)) -> (B, A)`.
178I Ridgun använder du helt enkelt en fristående versal:
179```ridgun
180byt plats (A, B) => (B, A)
181byt plats (x, y) = (y, x)
182```
183*"Men tänk om jag i mitt program vill ha en riktig typ som heter `type A`?"* — Inga problem: i Ridgun **är det dina `type`-deklarationer som bestämmer**. Om `type A` inte finns är `A` generisk; i samma ögonblick som du definierar `type A = ...` blir den din konkreta typ i hela modulen.
184
185### 7. Noll konstiga konfigurationsfiler: `build.rg` är ren Ridgun
186Glöm att behöva lära dig TOML för Cargo, JSON för npm, XML för Maven eller den arkaiska syntaxen i `Makefile` med osynliga tabulatorer. I Ridgun är receptet som bygger ditt projekt (`build.rg`) **bara ännu en `.rg`-fil**, med samma rena funktioner och samma mönstermatchning som resten av din kod.
187
188### 8. Den "heliga treenigheten" som verkade omöjlig: Haskell-nivå + RMM-minne utan GC eller Lifetimes + Binärer på ~350 KB
189Fram till i dag var du tvungen att välja:
190- Om du ville ha ren funktionell uttrycksfullhet (Haskell, OCaml, Elixir) betalade du med en skräpsamlare och en tung körtidsmiljö.
191- Om du ville ha pyttesmå systembinärer utan skräpsamlare (C, Rust, Zig) betalade du genom att hantera pekare eller brottas med *borrow checker* och skriva imperativ kod full av `let mut`.
192
193Ridgun bryter det dilemmat genom att kombinera **Ridgun Memory Management (`RMM`: statisk `RMM1` och kaskadräknad `RMM2`)**, **lexikala regioner (`with region`)** som frigör hela arenor i $O(1)$, **svansrekursion som omvandlas till inbyggda loopar (`loop`)** samt **beskärning av anropsgrafen (*Tree-Shaking*)** från `main`. Resultatet: du skriver deklarativ kod på allra högsta nivå och får en fristående ELF-körbar fil på **~350 KB** som kan mäta sig öga mot öga med verktyg skrivna i C.
194
195Nu ligger korten på bordet: låt oss gå vidare till **Kapitel 02** för att sätta **`ridgunc`** och **`stable`** i arbete.