Referens
Språkspecifikation för Ridgun
Översikt
Ridgun är ett funktionellt språk med parallellism i första rummet, operatorer i naturligt språk och stark statisk typning. Syntaxen är inspirerad av Haskell och språken i ML-familjen, samtidigt som den inför nya konstruktioner för parallellism och människoläsbara operatordefinitioner.
Viktiga egenskaper:
- Operatorer i naturligt språk — Operatorer läses som engelska meningar
- Implicit parallellism — Parallell körning är en primitiv i syntaxen, inte ett biblioteksanrop
- Stark statisk typning — Alla typer deklareras i signaturer
- Definitioner i mönsterstil — Funktioner och operatorer definieras med ekvationer
Kommentarer
Enradskommentarer använder --:
-- This is a comment
Strängar
Ridgun har två typer av strängliteraler med olika beteende för interpolering.
Interpolerade strängar (dubbla citattecken)
Strängar med dubbla citattecken stöder kodinterpolering på plats med {expr}. Uttrycket inom måsvingarna beräknas och resultatet sätts in i strängen.
name = "Ridgun"
"Hello, {name}!" -- "Hello, Ridgun!"
"Sum is {sum 3 4}" -- "Sum is 7"
"Nested: {factorial 5} done" -- "Nested: 120 done"
För att få med en bokstavlig måsvinge i "..." föregår du den antingen med ett omvänt snedstreck (\{ och \}) eller dubblar den ({{ och }}):
"Shell expansion: \$\{VAR:-default\}" -- "Shell expansion: ${VAR:-default}"
"This is {{not interpolated}}" -- "This is {not interpolated}"
"Use \{ \} or {{}} for literal braces" -- "Use { } or {} for literal braces"
Råa strängar (enkla citattecken)
Strängar med enkla citattecken är råa — ingen interpolering görs. Alla tecken behandlas som bokstavlig text, även måsvingar.
'Hello, {name}!' -- "Hello, {name}!"
'{this is just pure chars}' -- "{this is just pure chars}"
'No {interpolation} here' -- "No {interpolation} here"
Sammanfattning
| Syntax | Interpolering | Användning |
|---|---|---|
"..." | Ja — {expr} (skydda måsvingar med \{/\} eller {{/}}) | Dynamiska strängar med inbäddade uttryck |
'...' | Nej — allt är bokstavligt | Statisk text, mallar, regexmönster |
Programstruktur
All körbar kod i Ridgun måste finnas inuti en funktion eller operator. Funktionen main är den obligatoriska startpunkten för programkörningen.
fn :: main => ()
main = echo "Hello, Ridgun!"
En källfil i Ridgun får bara innehålla:
import-satsertype-definitionerfn- ochop-deklarationer och -definitioner- En
main-funktion som startpunkt
Lösa uttryck på toppnivå är inte tillåtna. Allt som körs måste anropas från main.
Användning på kommandoraden
ridgunc <command> [options] <file.rg>
| Kommando | Syfte |
|---|---|
run | Kompilerar och kör en källfil |
check | Typkontrollerar och analyserar utan att köra |
compile | Skapar en bytekodfil .rgc |
build | Bygger ett inbyggt program; ett bibliotek med --lib eller --so |
version | Visar kompilatorns version |
help | Visar hjälpen |
Formatering, tester och projekt sköts av stable.
Funktioner och operatorer
Funktioner och operatorer i naturligt språk eller infix-form deklareras med en typsignatur som slutar med => <return_type>, följd av en eller flera ekvationer (cases). Prefixen fn :: och op :: i början är valfria:
- Kanonisk form utan prefix (börjar i kolumn 0):
list len [A] => Int
list len [] = 0
list len (_:xs) = 1 + (list len xs)
swap A with B => (B, A)
swap x with y = (y, x)
- Explicit form med prefix (
fn ::/op ::, börjar i kolumn 0 med klausulerna justerade i kolumn 6):
fn :: sum Int Int => Int
sum a b = a + b
fn :: format app err AppErr => String
format app err (IoError msg) = "IO:{msg}"
- Mellanslag som i naturligt språk i
fn ::, inbyggda funktioner och filnamn (FR-COMP-005): fn ::-deklarationer och -anrop stöder namn i flera ord åtskilda med mellanslag (fn :: format app err AppErr => String,fn :: project name => String), precis somop ::och deklarationer utan prefix.- Inbyggda körtids- och testfunktioner kan anropas med mellanslag (
assert equals a b,str len s,read file p,cmm live blocks), medan_-formerna förblir bakåtkompatibla. - Förstaklassreferenser till funktioner med namn i flera ord (
map double val xs,||map double val xs,filter is even xs,fold add pair 0 xs) och.rg-filnamn med mellanslag (src/test/ridgun/test core language.rg) stöds direkt avridguncochstable.
Polymorfa typvariabler (A..Z) och kontextuella nyckelord (type, with)
För att garantera att det inte finns någon lexikal tvetydighet mellan operatorord och typparametrar, i signaturer både med prefix (op ::) och utan prefix, gäller följande:
- Varje typtoken i en signatur börjar med stor bokstav (eller
[...]/(...)): - Enstaka stora bokstäver (
A..Z) betecknar polymorfa typvariabler (t.ex.[A],(A, B),(A => B),swap A with B => (B, A)). Upprepade förekomster av en typvariabel i flera parametrar enhetligas vid varje anrop och sätts in i returtypen. - Identifierare med flera tecken och stor begynnelsebokstav (
Int,String,Bool,RExpr,Tensor) betecknar konkreta eller användardefinierade typer. - Varje token med små bokstäver (eller operatorsymbol
+,-,*,/,%) i en signatur på toppnivå är en del av namnet på funktionen eller mixfix-operatorn. - Kontextuella nyckelord
typeochwith:typeinleder bara en typdeklaration på toppnivå när det följs avUpperName =. Överallt annars (signaturer medfn ::ochop ::, operatorord, parametermönster, lokala variabler och fältnamn i poster) ärtypeochwithgiltiga identifierare eller ord utan tvetydighet. - En signatur på toppnivå med en inledande identifierare med små bokstäver följd av bara typer före
=>är en prefixfunktion (fn); varje signatur med två eller fler ord med små bokstäver eller operatorsymboler insprängda bland typer före=>är en mixfix-, infix- eller postfix-operator (op).
Deklarationen och definitionen är åtskilda:
- Deklaration (
fn ::) — anger namn, parametertyper och returtyp - Definition — binder parameternamn och ger implementationen
Operatorer
Operatorer är det som utmärker Ridgun. De namnges med naturligt språk och definieras med op ::. Till skillnad från traditionella operatorer (+, -) är Ridguns operatorer uttryck i flera ord som läses som meningar.
Syntax
op :: <natural language signature with types> -> <return_type>
<natural language pattern with params> = <body>
Grundläggande exempel
-- Declaration: "add [Int] to [Int]" returns an Int
op :: add Int to Int => Int
add a to b = a + b
Ett anrop läses så här: add 3 to 5 → 8
Orden mellan typade parametrar (to, and, in osv.) är operatorns nyckelord — de är en del av operatorns identitet och måste finnas med vid anropet.
Parallella operatorer (||)
Operatorer kan uttrycka parallell körning som ett förstaklassbegrepp med ||:
-- Run two configs in parallel with named DAG bindings (|| expr -> var)
op :: run Conf and Conf in parallel => Res, Res
run a and b in parallel = res_a, res_b
|| run my own process a -> res_a
|| run my own process b -> res_b
Viktiga delar:
- Flera returvärden —
=> Res, Resdeklarerar två returvärden - Blocket
|| expr -> var— Binder delberäkningar till resultatnamn (whereär borttaget;||förenar alla parallella grenar) ->— Tilldelar resultatet av en parallell delberäkning till en variabel (eller ett tensorsnitt-> out[i, j])- Oberoende
||-grenar körs samtidigt som en parallell DAG utifrån databeroenden
Direkt parallellt pipe-block (|| expr)
När ett uttryck eller en funktion direkt returnerar en tupel av parallella beräkningar utan mellanliggande variabelnamn står ||-raderna direkt efter =:
-- Run two processes in parallel and return their results as a tuple
op :: another way to run two processes Conf Conf in parallel => Res, Res
another way to run two processes a b in parallel =
|| run my own process a
|| run my own process b
Varje ||-rad körs som en oberoende parallell uppgift. Resultaten samlas i deklarationsordning.
Överlagring av operatorer
Befintliga operatorer (även inbyggda som +) kan överlagras för nya typer:
-- Overload + for Complex numbers
op :: Complex + Complex => Complex
a + b = (real a) + (real b) + complex_i * ((imaginary a) + (imaginary b))
Prioritet
Symboliska operatorer har högst prioritet — matematiken först.
När symboliska operatorer (som +, *) förekommer inuti kroppar till operatorer i naturligt språk binder de starkare än den omgivande operatorns nyckelord. Det gör att aritmetiska uttryck beräknas som väntat utan extra parenteser.
| Prioritet | Kategori | Exempel |
|---|---|---|
| Högst | Symboliska operatorer | *, /, +, -, % |
| Funktionsanrop | f x | |
| Jämförelse | ==, !=, <, > | |
| Logiska | and, or, xor, not | |
| Lägst | Operatorer i naturligt språk | add a to b, run a and b in parallel |
Operatorkedjor och idiomatiska pipelines från vänster till höger (->) (FR-COMP-014)
Operatorer och funktioner som omvandlar värden eller sekvenser kan kedjas från vänster till höger så att data flödar naturligt från källa till mål utan nästlade parenteser som läses från höger till vänster (h (g (f x))) eller engångsvariabler däremellan (st1, st2, st3).
1. Den rekommenderade idiomatiska pipeline-stilen i Ridgun (2b)
Ridgun förenar infix-anrop med vänsteroperand och explicita ->-pipelinesteg i samma AST. Alla fyra formerna nedan är giltiga och likvärdiga, men formen 2b (som börjar naturligt med ett subjekt + en operation till vänster, kedjar efterföljande omvandlingar med -> och binder slutresultatet med -> target) är den rekommenderade idiomatiska stilen i Ridgun:
-- Recommended idiomatic style (2b):
xs map (x => x * 2) -> filter (x => x > 6) -> compact limit 14 -> results
-- Equivalent unified forms (all normalize to the exact same AST):
xs -> map (x => x * 2) -> filter (x => x > 6) -> compact limit 14 -> results -- (2) explicit -> from subject
xs map (x => x * 2) filter (x => x > 6) compact limit 14 -> results -- (1) contiguous infix chain
map (x => x * 2) xs -> filter (x => x > 6) -> compact limit 14 -> results -- (3) prefix start + -> chain
Pipelines med flera steg kan också skrivas på indragna fortsättningsrader som börjar med ->:
raw_nums map (x => x * 3)
-> filter (x => x >= 12)
-> fold 0 (acc x => acc + x)
-> total_sum
2. Den universella regeln om första argumentet för -> och samlingskombinatorer
- Universell regel för funktioner och operatorer: Ett värde som kommer från vänster om
->(eller vänster om ett infix-anropx op a b) blir första argumentet till funktionen eller operatorn till höger: x -> f a b$\equiv$x f a b$\equiv$f x a b- Fungerar smidigt för både
fn ::-deklarationer och mixfix-deklarationer medop ::utan dubblerade signaturer. - Om en funktion längre ned behöver det inkommande värdet i en annan parameterposition än den första placerar en explicit platshållare
_värdet där_står (payload -> write_file output_path _). - Samlingskombinatorer (
map,||map,filter,||filter,fold): Tar emot samlingen antingen i traditionell prefixposition (map f xs,filter g xs,fold f init xs) eller från vänster om ett infix- eller pipelinesteg (xs map f,xs -> map f,xs filter g,xs -> filter g,xs fold init f,xs -> fold init f). - Agentsteg (
-> send to,-> ask to): När ett värde skickas in i-> send to ageller-> ask to agblir värdet till vänster meddelandet ([5, 10, 15] -> sum int list -> send to worker_ag). - Bindning av slutvariabel (
-> var): När en pipelinesats i ett sekventiellt block slutar med-> var(därvarär namnet på en lokal variabel och inte en deklarerad funktion) binder denvar(var = <pipeline_result>) för resten av blocket.
3. Sekvensmasker i pipelines (-> (+ _ _ +) ->)
När ett steg returnerar en sekvens med flera värden eller en tupel filtrerar ett sekvensmasksteg (-> (+ _ _ +) ->) elementen (+ behåller en position, _ kastar den) och packar upp den valda tupeln direkt in i en funktion med flera argument längre ned:
parse header packet "v0.9.9" -> (+ _ _ +) -> combine code msg -> status_line
4. Sidoeffektsatser utan _ = och explicit kassering av enhetsvärden (-> ())
I sekventiella block skrivs sidoeffektsatser (echo, write_file, write_bytes, shell_exec, log info, print_error_lines, sys_mkdir osv.) direkt, utan onödigt _ =:
verify strict if enabled strict_mode input_path
s_errs -> format_type_errors -> print_error_lines
echo "[ridgunc --strict] {input_path}: {err_c} error(s) found."
sys_exit 1
När det sista uttrycket i en => ()-funktion anropar en hjälpfunktion som returnerar något annat än () (som shell_exec : String => Int) lägger du till -> () för att beräkna uttrycket, kasta returvärdet och ge ():
fn :: exec built run Int => ()
exec built run 0 = shell_exec "./target/app" -> ()
exec built run _ = sys_exit 1
5. Punktfri kedjning av sekvensoperatorer
Operatorer som returnerar sekvenser kan också kedjas punktfritt:
op :: Int Int switch -> Int Int
a b switch = b a
op :: Int Int invariant -> Int Int
a b invariant = a b switch switch
Obs: Både
->och=>accepteras som avskiljare för returtypen ifn ::- ochop ::-huvuden. I uttryck är->operatorn för pipelines och bindning från vänster till höger, medan=>inleder lexikala closures(x => expr).
Typsystem
Typsignaturer
Typsignaturer står i deklarationer efter fn :: eller op :: (eller utan prefix):
fn :: <name> <type1> <type2> ... => <return_type1> <return_type2> ...
op :: <words and types mixed> => <return_type1> <return_type2> ...
- Parametrar är positionella; typer står där parametrar förväntas.
- Enhetlig syntax för tupel- och sekvenstyper (
FR-COMP-008): - I Ridgun representerar en argumentlista
T1 T2 ... Tnoch en tupel(T1, T2, ..., Tn)samma underliggande sammansatta typ: en ordnad sekvens med fast storlek av typade värden (seq). - Därför är typer åtskilda med mellanslag och tupeltyper åtskilda med kommatecken 100 % utbytbara i returtyper, listklamrar och tupler inom parentes:
- Returtyper efter
=>/->:
fn :: parse header String => Int Int [String String] String
-- 100% equivalent to:
fn :: parse header String => (Int, Int, [(String, String)], String)
- Listor av tupler (
[T1 T2 ... Tn]):
[String String] -- equivalent to [(String, String)]
[Int String Bool] -- equivalent to [(Int, String, Bool)]
- Tupler inom parentes (
(T1 T2 ... Tn)):
fn :: fst (A B) => A
fst (a, _) = a
- Varför det här inte ger någon syntaktisk tvetydighet: Till skillnad från Haskell/ML (där sammanställning som
Maybe Intbetecknar typapplikation) använder parametriserade typer i Ridgun explicita parenteser (Tensor(Float, 3, 3)) och listor använder hakparenteser ([T]). Dessutom börjar varje typtoken med en stor bokstav (A..Z,Int,String),[eller(, medan ord i funktioner och operatorer skrivs med små bokstäver. Därför krockarT1 T2aldrig med typkonstruktorer eller operatornyckelord. - Pilen
=>(eller->) skiljer indatatyper från returtypen.
Inbyggda typer
| Typ | Beskrivning |
|---|---|
Int | Heltal |
Real | Reellt tal |
Bool | Booleskt värde |
Char | Ett enskilt Unicode-tecken (UTF-8) |
String | Textsträng (UTF-8) |
Complex | Komplext tal |
Tensor | Muterbar N-dimensionell tensor (Real-element, CPU) |
Tensor_GPU | Muterbar N-dimensionell tensor (Real-element, GPU) |
[!NOTE] All text i Ridgun är UTF-8-kodad som standard.
Charrepresenterar en enskild Unicode-kodpunkt,Stringär en sekvens avChar.
Booleska literaler
Bool har två primitiva värden:
True -- boolean true
False -- boolean false
True och False är konstruktorer — de kan användas i uttryck, skickas som argument och mönstermatchas:
fn :: is_valid Int => Bool
is_valid n =
| n > 0 = True
| otherwise = False
Logiska operatorer
Ridgun använder ordbaserade logiska operatorer med små bokstäver i stället för symboliska:
| Operator | Betydelse | Exempel |
|---|---|---|
and | Logisk konjunktion | a and b |
or | Logisk disjunktion | a or b |
xor | Exklusivt eller | a xor b |
not | Logisk negation | not a |
result = True and False -- False
result = True or False -- True
result = True xor True -- False
result = not False -- True
Det här är infix-operatorer i form av nyckelord med vanlig boolesk semantik.
Nativa samlingstyper
Listor
Listor är en inbyggd oföränderlig rekursiv typ med egen syntax. Ingen manuell definition av en algebraisk datatyp behövs. Listor passar för funktionell databehandling, symbolisk beräkning och rekursiva algoritmer. För muterbara numeriska beräkningar, se Tensorer nedan.
Typsyntax: [type] — en lista med element av den angivna typen.
fn :: sum_list [Int] => Int
fn :: reverse [Int] => [Int]
Literalsyntax: [elem1, elem2, ...] — en listliteral. [] är den tomma listan.
fn :: my_list => [Int]
my_list = [1, 2, 3, 4, 5]
Mönstermatchning med cons: (x:xs) — plockar isär en lista i huvudet x och svansen xs. [] matchar den tomma listan. Använd _ som ett jokertecken som matchar utan att binda.
fn :: sum_list [Int] => Int
sum_list [] = 0
sum_list (x:xs) = x + sum_list xs
fn :: list_length [Int] => Int
list_length [] = 0
list_length (_:xs) = 1 + list_length xs
Sammanfogning: :: sammanfogar två listor (eller sekvenser).
fn :: append [Int] [Int] => [Int]
append a b = a :: b
Tensorer
Tensorer är Ridguns nativa muterbara N-dimensionella numeriska typ. De generaliserar vektorer, matriser och högre dimensionella arrayer till en enda typ. Elementen är Real som standard.
Literalsyntax: Tensor följt av nästlade hakparenteser. Nästlingsdjupet bestämmer antalet dimensioner.
v = Tensor [1, 2, 3] -- 1D (vector), shape: (3)
m = Tensor [[1, 2], [5, 3]] -- 2D (matrix), shape: (2, 2)
t = Tensor [[[1, 2], [3, 4]], -- 3D tensor, shape: (2, 2, 2)
[[5, 6], [7, 8]]]
Indexering: Både kedjad och kommaseparerad indexering stöds.
val = m[0][1] -- chained indexing: row 0, col 1
val = m[0, 1] -- comma indexing: equivalent
row = m[0] -- slice: entire first row
Mutation (på plats): Tensorer är muterbara — element och snitt kan ändras på plats (som i PyTorch och NumPy).
m[0, 1] = 5.0 -- set element
m[0] = Tensor [10, 20] -- set entire row
Tensorkontraktion (@): Operatorn @ utför Einsteinsummering. Indexen på varje operand definierar kontraktionen: index som delas av alla operander summeras; unika index finns kvar i resultatet.
-- A has shape (s, d, f), B has shape (n, d, f)
-- Shared indices: d, f → contracted (summed)
-- Result T has shape (s, n)
T = A_sdf @ B_ndf
-- Equivalent to: np.einsum('sdf,ndf->sn', A, B)
Kontraktion fungerar över flera tensorer i ett enda uttryck:
-- A(a,b,c), B(a,b,c), C(a,b,c,d)
-- Shared: a, b, c → contracted. Result R has shape (d)
R = A_abc @ B_abc @ C_abcd
-- Equivalent to: np.einsum('abc,abc,abcd->d', A, B, C)
Hadamard-operationer (+, -, *, /): Aritmetiska operatorer med index utför elementvisa operationer. Index som matchar justerar dimensionerna; index som inte matchar utvidgas med broadcasting.
-- Element-wise multiply: same shape, same indices
H = A_ij * B_ij -- shape (i, j)
-- Broadcasting: B has fewer dimensions
S = A_ij * B_j -- B broadcasts along i
-- Element-wise add
C = A_ij + B_ij
-- Element-wise divide
D = A_ij / B_j -- B broadcasts along i
Det gör att du inte behöver unsqueeze, expand_dims eller manuell omformning — indexen är reglerna för broadcasting.
GPU-variant: Tensor_GPU placerar tensorn i GPU-minnet för accelererad beräkning.
g = Tensor_GPU [[1, 2], [3, 4]]
result = g_ij @ g_jk -- GPU-accelerated matrix multiply
Sekvenser (seq)
Sekvenser är Ridguns grundläggande sammansatta typ. En seq är en ordnad samling värden med fast storlek — i praktiken en typad tupel. Parameterlistor till funktioner och operatorer är implicit sekvenser.
-- These parameter types form implicit sequences:
fn :: sum Int Int => Int -- params: seq(Int, Int)
fn :: process Int Real => Bool -- params: seq(Int, Real)
Seq-bindning ((name)) — om du sätter ett parameternamn inom parentes binds alla parametrar som en enda seq-variabel:
fn :: first_of_seq Int Int => Int
first_of_seq (s) = s(+ _)
-- Equivalent without seq binding:
fn :: first_of Int Int => Int
first_of s _ => s
Maskväljare (s(+ _)) — plockar ut element med en mask, där + väljer en position och _ hoppar över den:
s(+ _) -- select 1st, skip 2nd
s(_ +) -- skip 1st, select 2nd
s(+ _ _ _) -- select 1st, skip 2nd-4th
s(_ _ _ +) -- skip 1st-3rd, select 4th
Indexväljare (s(0 3)) — plockar ut element utifrån deras nollbaserade positioner:
fn :: extreme_points Int Int Int Int => Int Int
extreme_points (s) = s(0 3)
Platt sammanfogning (:) — sammanfogar två sekvenser till en enda platt sekvens:
seq1 = a, b -- seq(a, b)
seq2 = c, d -- seq(c, d)
seq1:seq2 -- seq(a, b, c, d)
Nästling (,) — sätter ihop sekvenser som separata element (en sekvens av sekvenser):
seq1, seq2 -- seq(seq(a, b), seq(c, d))
Algebraiska datatyper (ADT)
Ridgun använder algebraiska datatyper för användardefinierade typer. Det finns inga klasser, metoder eller impl-block — funktioner och operatorer tar typer som parametrar.
Produkttyper (poster) och syntax för postuppdatering (with)
En typ med namngivna fält:
type Conf = host: String, port: Int, tls: Bool
type Point = x: Real, y: Real
Fält nås med namn som funktioner (host c, port c) och uppdateras funktionellt med with och kolon ::
fn :: get_host Conf => String
get_host c = host c
-- Functional record update (creates a new Conf with updated fields;
-- mutates in place via Arc::try_unwrap when the record is uniquely owned):
fn :: enable_tls Conf => Conf
enable_tls c = c with tls = True, port = 443
Summatyper (varianter)
En typ med flera konstruktorer, åtskilda med |:
type Result = Ok Int | Err String
type Option = Some Int | None
type Color = Red | Green | Blue
Generiska summatyper och generiska poster (FR-COMP-013)
Användardefinierade summatyper och poster kan deklarera en eller flera typparametrar med stor bokstav (A..Z eller namn på typvariabler med stor begynnelsebokstav) mellan typnamnet och =:
type Result T E = Ok T | Err E
type Option A = Some A | None
type Box A = Box A
type Page T = items: [T], total: Int
type Pair A B = fst: A, snd: B
- Parametriska typapplikationer (
Result Int String,Page User,[Box Int]) kan användas ifn ::- ochop ::-signaturer, nästlade postfält och data i konstruktorer för algebraiska datatyper. - Konstruktorer (
Ok 42,Ok "hello",Page [1, 2] 2), mönstermatchning, fältfunktioner (items p,total p) och funktionella postuppdateringar (p with total = 10) skapar nya typvariabler vid varje anrop. type Option A = Some A | Noneär förregistrerad som en inbyggd polymorf algebraisk datatyp när användaren inte redan har deklarerat den, såtry receive from agreturnerarSome vellerNoneutan att några extra deklarationer behövs (FR-COMP-013).
Anonyma funktioner och lexikala closures ((x => expr), (a b => expr) — FR-COMP-013)
Anonyma funktioner (lambdas) skrivs inom parentes med parametrar åtskilda med mellanslag följda av => och uttrycket som är kroppen ((x => expr) eller (a b => expr), t.ex. map (x => x + offset) xs, fold (acc x => acc + x) 0 xs) och kan fånga lokala variabler eller parametrar från det omgivande lexikala scopet:
fn :: add offset Int [Int] => [Int]
add offset k xs = map (x => x + k) xs
Fem kanoniska regler styr anonyma funktioner:
- Obligatoriska parenteser: Varje lambda måste stå inom parentes
(... => ...).x => exprutan parenteser (somf = x => x + 1) ger ett fel vid kompilering (lambda expression must be enclosed in parentheses: '(x => expr)'). - Lambdas utan parametrar (
(=> expr)): Ridgun förbjuder()före=>i funktionssignaturer (fn :: main => ()). På samma sätt skrivs en lambda utan parametrar(=> expr)(anropas somthunk ()), och dess typ i signaturer är(=> Type). Att skriva(() => expr)eller(() => Type)ger ett fel vid kompilering. - Flera parametrar kontra uppdelning av tupler (
(a b => expr)kontra((a b) => expr)):(a b => expr)är en lambda med 2 parametrar (somfold (acc x => acc + x) 0 xs), medan((a b) => expr)är en lambda med 1 parameter som plockar isär en tupel (map ((a b) => a + b) [(1, 2), (3, 4)]). Om du blandar ihop dem får du ett särskilt typfel som förklarar skillnaden. - Lambdakroppar på flera rader: När
=>står i slutet av raden bildar det indragna blocket under den en kropp med flera satser (eller|-vakter) som avslutas med):
map (x =>
doubled = x * 2
doubled + offset
) [1, 2, 3]
- Typer med stor bokstav kontra värden med liten bokstav:
(Conn => Conn)är en funktionstyp och(conn => conn)är ett lambdavärde. Att skriva typer med stor bokstav(Conn => Conn)i ett uttryck eller parametrar med liten bokstav(conn => conn)i enfn ::-signatur avvisas med ett tydligt fel vid kompilering.
Fångade bindningar lyfts automatiskt till closures med partiell applicering som hanteras av RMM1/RMM2.
Rekursiva typer
Typer kan referera till sig själva:
type List = Empty | Cons Int List
type Tree = Leaf Int | Node Tree Tree
Delade konstruktornamn mellan typer (FR-COMP-005)
Flera type-deklarationer kan återanvända samma namn på variantkonstruktorer (som Error, Var, Lit, None) med samma eller olika aritet. Typkontrollanten skiljer konstruktormönster åt med hjälp av kolumnens förväntade parametertyp, och den löser konstruktoranrop utifrån argumentens aritet och typer och returtyper som är unioner av algebraiska datatyper:
type ParseOut = Parsed Int | Error String
type DbOut = Rows Int | Error Int String
type MiniExpr = Var String | Lit Int
type MiniPat = Var String | Lit Int | Wild
Öppna typutvidgningar (expand type) och automatisk sammanslagning av fn ::-klausuler (FR-COMP-005)
Befintliga summatyper och poster kan utökas med expand type UpperName = ...:
- Utöka en summatyp: lägger till nya variantkonstruktorer i den befintliga typen.
- Utöka en post: lägger till nya namngivna fält (
field: Type) och genererar automatiskt deras fältfunktioner. - Typnamnsvarianter utan överflödiga konstruktornamn: i summadeklarationer med
typeochexpand typerepresenterar en variant vars namn är en inbyggd typ utan vidare (String,Int,Real/Float,Bool,Char), utan extra typargument efter sig, värden av den typen direkt (utan att du skriverInt IntellerString String). Anropare kan skicka rena värden (describe "hej",describe 42) eller explicita konstruktoranrop (describe (String "hej"),describe (Int 42)), och ekvationer kan matcha både literaler ("admin",0) och typade mönster ((String s),(Int n)). - Automatisk sammanslagning av
fn ::- ochop ::-klausuler (utanexpand fn): om du deklarerar om en befintligfn ::ellerop ::med nya mönsterklausuler slås klausulerna automatiskt ihop med den befintliga funktionsdefinitionen, och klausuler med specifika konstruktor- eller literalmönster placeras före alla generella reservklausuler (_/ variabel):
type Something = String | Int | MyStruct Float Int
expand type Something = Bool
fn :: describe something Something => String
describe something "admin" = "special_admin"
describe something 0 = "zero_int"
describe something (String s) = "str:{s}"
describe something (Int n) = "int:{n}"
describe something (Bool b) = "bool:{b}"
describe something (MyStruct ratio cnt) = "struct:{ratio}:{cnt}"
type AppErr = IoError String | Timeout Int
fn :: format app err AppErr => String
format app err (IoError msg) = "IO:{msg}"
format app err (Timeout ms) = "TO:{ms}"
format app err _ = "UNKNOWN"
expand type AppErr = AuthError String | DbError Int String
fn :: format app err AppErr => String
format app err (AuthError user) = "AUTH:{user}"
format app err (DbError code db) = "DB:{code}:{db}"
type AppConfig = host: String, port: Int
expand type AppConfig = tls: Bool
Modulnamnrymder, kvalificerad åtkomst och strikt importsynlighet per modul (FR-COMP-012)
Varje .rg-fil eller .rglib-paket definierar en modulnamnrymd (som härleds från filens stam eller från ett explicit module :: <name>-huvud) och kan importera andra moduler med import <mod> eller import <mod> as <alias>.
- Moduler i flera filer (
module :: <name>):
- Flera filer som deklarerar samma
module :: <name>-huvud (till exempelorm.rgochorm_changeset.rg, som båda börjar medmodule :: orm) delar en enda logisk modulnamnrymdormoch ser varandras typer, konstruktorer, postfält och funktioner direkt.
- Kvalificerad åtkomst (
mod.Type,mod.Constructor,mod.field,mod.fn):
- Exporterade typer, konstruktorer i summatyper, fältfunktioner i poster, postuppdateringar (
with) och funktioner kan refereras till med prefixet<mod_or_alias>.(http.Config,db.Status,http.Ok 200,http.port cfg,http.check status cfg).
- Strikt namnupplösning i 3 nivåer per modul för okvalificerade namn:
- Varje modul
M(även applikationens rotmodul) löser okvalificerade typer, konstruktorer, postfält, funktioner och anrop med flera ord strikt motM:s egen importgraf, i tre prioritetsnivåer: - Nivå 1 — Den egna modulen (
M): Deklarationer iMsjälv (i alla filer som delarmodule :: M) har alltid högst prioritet. - Nivå 2 — Direkta importer i
M: OmMinte definierar namnet sökerridgunci moduler somMimporterar direkt (import D). Om en enda direkt importDdefinierar namnet löses det entydigt tillD:s deklaration, även om andra moduler i kompileringsenheten (transitiva beroenden, syskonmoduler eller rotapplikationen) också definierar samma namn. Om två eller fler direkta importer iMdefinierar samma namn ochMinte definierar det avvisas okvalificerade referenser som tvetydiga (__ambiguous__.<name>) och måste kvalificeras (d1.<name>kontrad2.<name>). - Nivå 3 — Transitiva importer i
M: Används bara när varken nivå 1 eller nivå 2 definierar namnet. Därför skuggar en direkt import iM(import json) på ett rent sätt en transitiv hjälpfunktion (codec.json_get_strsomsolsticeimporterar internt) utan att tvingasolsticeellerMatt byta namn på eller kvalificera sina anrop. - Isolering från syskonmoduler som inte importerats och från rotapplikationen: Deklarationer som bara definieras i moduler som
Minte har importerat (varken direkt eller transitivt) — även syskonbibliotek som rotapplikationen importerar, eller deklarationer i själva rotapplikationen när ett importerat bibliotekMkompileras — är osynliga för okvalificerad sökning inutiM(__unimported__.<name>).
Enhetlig =-grammatik ((none), |, ||) och lokala variabler (FR-COMP-003)
Varje definition eller bindning i Ridgun — oavsett om det är en funktionsklausul (fn ::), en operatorklausul (op ::), en oföränderlig lokal variabel (x =), en muterbar lokal variabel (mut x =) eller en vaktgren (| cond = / | otherwise =) — slutar med = och accepterar exakt samma fyra block- och uttrycksformer i högerledet:
Prefix efter = | Körningssemantik | Betydelse |
|---|---|---|
Inline <expr> | Ett enda uttryck (med valfria || expr -> var-rader under) | Beräknar <expr> direkt (och löser eventuella parallella ||-DAG-bindningar under det). |
(none) (indragna rader) | Sekventiell (uppifrån och ned) | Beräknar satser i ordning (mut, tilldelningar, sidoeffekter); det sista uttrycket är resultatet. |
| <cond> = ... | Villkorlig (vakter och nästlade beslutsträd) | Beräknar booleska villkor uppifrån och ned fram till den första grenen som är True (eller | otherwise =). |
|| <expr> | Parallell (DAG eller tupel med green threads) | Beräknar ||-grenar samtidigt (|| expr -> var för namngivna DAG-noder, || expr för parallella tupelresultat). |
1. Vakter (|) står alltid efter = (funktioner, operatorer, lokala variabler och nästlade beslutsträd)
Vaktblock (| cond = ... och | otherwise = ...) står alltid efter ett =, vilket förenar funktionsklausuler, operatorklausuler, definitioner av lokala variabler och nästlade villkorsträd:
Funktions- och operatorklausuler med vakter
fn :: abs Int => Int
abs n =
| n < 0 = 0 - n
| otherwise = n
op :: clamp Int between Int and Int => Int
clamp x between lo and hi =
| x < lo = lo
| x > hi = hi
| otherwise = x
Tilldelning av lokala variabler med vakter
Eftersom | är giltigt efter varje = kan lokala variabler bindas villkorligt utan ett if/else-nyckelord eller en hjälpfunktion:
discount =
| is_vip = 20
| total > 100 = 10
| otherwise = 0
Sekventiella block på flera rader, djupa beslutsträd och nästlade avslutare (|. / ||.)
Varje vaktgren slutar med =, så dess kropp kan i sin tur vara ett sekventiellt block ((none)), ett parallellt block (||) eller ett annat nästlat |-vaktblock — vilket möjliggör godtyckliga beslutsträd (3–4 nivåer djupa eller mer) inuti | cond = och | otherwise =.
- Avsluta nästlade nivåer (
|.och||.): - I enkla block med en nivå eller i slutet av en funktion eller ett träd behövs ingen avslutande token.
- När ett nästlat
|-delblock (eller||-delblock) är klart och körningen återvänder till en yttre nivå där fler grenar eller satser följer längre ned avslutar|.(för|) eller||.(för||) uttryckligen den nästlade nivån. - Både placering på samma rad i slutet av den sista raden (
| otherwise = val |., den kanoniska kompakta stilen) och placering på nästa rad (|.) är giltiga:
fn :: evaluate_payment Account Customer Payment => String
evaluate_payment account customer payment =
| is_locked account = "REJECTED_ACCOUNT_LOCKED"
| amount payment <= 0 = "ERROR_INVALID_AMOUNT"
| otherwise =
| tier customer == "ENTERPRISE" =
| amount payment > 50000 =
| has_dual_signature payment = "APPROVED_ENTERPRISE_DUAL_SIG"
| tenure customer > 10 = "RISK_COMMITTEE_REVIEW"
| otherwise = "REJECTED_ENTERPRISE_LIMIT" |.
| country payment != "US" =
| is_whitelisted (country payment) = "APPROVED_ENTERPRISE_INTL"
| otherwise = "HELD_COMPLIANCE_INTL" |.
| otherwise = "APPROVED_ENTERPRISE_STANDARD" |.
| tier customer == "VIP" =
| amount payment > 10000 =
| has_2fa payment = "APPROVED_VIP_2FA"
| otherwise = "REQUEST_VIP_SMS" |.
| otherwise = "APPROVED_VIP_DIRECT" |.
| otherwise =
| amount payment > 1000 =
| has_2fa payment and risk payment < 30 = "APPROVED_RETAIL_2FA"
| otherwise = "REJECTED_RETAIL_RISK" |.
| otherwise = "APPROVED_RETAIL_LOW_AMOUNT"
fn :: charge_order Payment => Int
charge_order payment =
|| fetch_base_fee payment -> base_fee
|| compute_risk_score payment -> risk_score ||.
surcharge =
| risk_score > 80 = 50
| otherwise = 0 |.
base_fee + surcharge
2. Oföränderliga som standard (x = ...) kontra explicit muterbara variabler (mut x = ...)
Inuti sekventiella block följer lokala variabler alternativ 1:
- Oföränderlig bindning (
x = <rhs>): - Deklarerar en ny oföränderlig lokal variabel
x. - Att försöka tilldela
x = ...på nytt senare i samma scope utan en tidigaremut x = ...-deklaration är ett fel vid kompilering. - Muterbar deklaration (
mut x = <rhs>) och omtilldelning (x = <new_rhs>): mut x = <rhs>deklarerarxsom muterbar i det aktuella scopet och initierar den.- Senare omtilldelningar till
xi samma scope skrivs helt enkelt somx = <new_rhs>(utan att upprepamut). - Under
RMM2ökar omtilldelningenx = <new_rhs>räknaren för den nya strukturen (+1) innan den minskar räknaren för den gamla (-1, i kaskad till dess barn om räknaren når0).
fn :: accumulate Int => Int
accumulate n =
factor = 2
mut acc = n * factor
acc = acc + 10
acc =
| acc > 100 = 100
| otherwise = acc
acc
3. Mönstermatchning på literaler och konstruktorer
fn :: factorial Int => Int
factorial 0 = 1
factorial n = n * factorial (n - 1)
fn :: unwrap Result => Int
unwrap (Ok n) = n
unwrap (Err msg) = 0
fn :: length List => Int
length Empty = 0
length (Cons _ rest) = 1 + length rest
fn :: sum_tree Tree => Int
sum_tree (Leaf n) = n
sum_tree (Node left right) = sum_tree left + sum_tree right
Primitiver för parallellism (||)
Ridgun förenar all parallell körning under || (where är borttaget):
Namngivna parallella DAG-bindningar (|| expr -> var)
fn :: compute_total Int Int => Int
compute_total a b = x + y + z
|| heavy_calc a -> x
|| heavy_calc b -> y
|| combine x y -> z
- Alla
|| expr -> var-rader under ett uttryck bildar en parallell riktad acyklisk graf (DAG). - Kompilatorn analyserar variabelberoenden mellan
||-rader (xochyhar inga beroenden och körs parallellt i våg 1;zberor påxochyoch körs i våg 2 innanx + y + zberäknas). - Parallella skrivningar till tensorsnitt (
|| expr -> out[i, j]) stöds också.
Direkta parallella pipe-block (|| expr)
op :: run Conf and Conf in parallel => Res, Res
run a and b in parallel =
|| run_process a
|| run_process b
Varje ||-rad körs som en separat parallell green thread, och resultaten returneras som en tupel i deklarationsordning (eller slås ihop när de placeras inuti ett sekventiellt block).
Typade kanaler
För dataströmmar och producent–konsument-topologier över green threads har Ridgun typade MPMC-kanaler (Channel):
| Inbyggd funktion eller operator | Signatur | Syfte |
|---|---|---|
new_channel | () => Channel | Skapar en obegränsad typad kanal |
new_bounded_channel | Int => Channel | Skapar en begränsad kanal med kapacitet för mottryck |
send_through | T Channel => () | Skickar ett värde till en kanal (blockerar om den är begränsad och full) |
receive_from | Channel => T | Tar emot nästa värde från en kanal |
try_receive_from | Channel => Option | Icke-blockerande poll som returnerar Some v eller None |
I/O-primitiver
Ridgun har inbyggda funktioner för utskrift till terminalen.
echo
Skriver ut ett godtyckligt antal strängar i terminalen, åtskilda med mellanslag och följda av en radbrytning.
fn :: echo String... => ()
Suffixet ... på den sista parametertypen markerar den som variadisk — den tar emot ett eller flera argument av den typen.
echo "hello" -- prints: hello
echo "hello" "world" "!" -- prints: hello world !
echo "result: {result}" -- prints: result: 42
out
En operator som skriver en sträng direkt till terminalen och returnerar den (vilket gör att den går att kedja).
op :: String out => String
"hello" out -- prints: hello
"step 1 done" out -- prints: step 1 done
-- Chaining: out returns the string, so it can be passed onward
fn :: log_and_process String => String
log_and_process s = process (s out) and report
Sammanfattning
| Funktion | Typ | Syfte |
|---|---|---|
echo | String... => () | Skriver ut strängar med mellanslag och radbrytning |
out | String => String | Skriver ut en sträng och returnerar den för kedjning |
Standardbibliotek
Bibliotek importeras med import:
import test
Enhetstester (lib/test.rg)
Ett enkelt testbibliotek som använder echo för utskrift till terminalen.
Påståenden:
| Operator | Syfte |
|---|---|
assert Int equals Int | Likhet mellan heltal |
assert Real equals Real | Likhet mellan reella tal |
assert String equals String | Likhet mellan strängar |
assert Bool is true | Booleskt värde är sant |
assert Bool is false | Booleskt värde är falskt |
Teststruktur:
import test
fn :: main => ()
main =
describe "Arithmetic" does
test "sum adds correctly" does
assert (sum 3 4) equals 7
test "factorial base case" does
assert (factorial 0) equals 1
Utskrift i terminalen:
═══ Arithmetic ═══
● sum adds correctly
✓ PASS
● factorial base case
✓ PASS
Sammanfattning av syntaktiska element
| Element | Syntax | Syfte |
|---|---|---|
| Kommentar | -- text | Enradskommentar |
| Funktionsdeklaration | fn :: name types => return | Deklarerar en funktions typsignatur |
| Funktionsdefinition | name params = body | Definierar en funktions implementation |
| Operatordeklaration | op :: words types words => return | Deklarerar en operator i naturligt språk |
| Operatordefinition | words params words = body | Definierar en operators implementation |
| Flera returvärden | => type, type | Deklarerar flera returvärden |
| Variadiska parametrar | Type... | Tar emot ett eller flera argument av en typ |
| Tensorliteral | Tensor [[1, 2], [3, 4]] | Skapar en N-dimensionell tensor |
| Tensorindexering | t[0, 1] eller t[0][1] | Når tensorelement |
| Tensormutation | t[0, 1] = 5.0 | Ändrar tensorelement på plats |
| Einsteinkontraktion | A_ij @ B_jk | Tensorkontraktion över delade index |
| Hadamard-operation | A_ij * B_ij | Elementvis aritmetik med justering av index |
echo | echo "a" "b" "c" | Skriver ut strängar i terminalen |
out | "text" out | Skriver en sträng till terminalen |
| Oföränderlig lokal bindning | x = expr | Binder en oföränderlig lokal variabel (= stöder (none), |, ||) |
| Muterbar lokal bindning | mut x = expr | Deklarerar en muterbar lokal variabel (tilldelas på nytt med x = new_expr) |
| Vaktblock | | cond = expr | Villkorlig vaktgren efter = (stöder nästlade |) |
| Parallellt DAG-block | || expr -> var | Parallella delberäkningar med namngivna DAG-resultat |
| Parallellt pipe-block | || expr | Parallell körning som returnerar en tupel |
| Överlagring av operatorer | op :: type + type => type | Överlagrar befintliga operatorer för nya typer |
| Booleska literaler | True, False | Primitiva booleska värden |
| Logiska operatorer | and, or, xor, not | Ordbaserade logiska operatorer med små bokstäver |
| Startpunkt | fn :: main => () | Programmets obligatoriska startpunkt |
Kanonisk formatering av källkod (stable format och editorverktyg)
Bara estetik — inget krav från kompilatorn (
FR-TOOL-001): Ridguns lexer och parser bryr sig inte om horisontell kolumnjustering..rg-källfiler med och utan kolumnjustering är 100 % likvärdiga förridgunc. Reglerna nedan definierar den kanoniska estetiska layouten som tillämpas avstable formatoch GNU Emacsridgun-mode(C-c C-f).
- Justeringsgrupp per signatur (
fn ::/op ::):
- Varje
fn ::- ellerop ::-deklaration inleder en justeringsgrupp som omfattar signaturen, dess mönsterklausuler och dess|| expr -> var-bindningar och slutar vid nästa deklaration på toppnivå (fn,op,type,import,global,context,shared,hardware,@).
- Kolumnjustering av token i vänsterledet ($C_0 = 6$):
fn ::ochop ::är 6 tecken breda, så token $0$ i signaturens vänsterled börjar i kolumn $C_0 = 6$.- Varje tokenplats $i \in [0, N-1]$ före
=>/->(där"...",'...',[...]och(...)räknas som enskilda token) har bredden $W_i = \max(\text{len}(\text{sig_tok}i), \max{\text{clause} : \text{len}(\text{clause_tok}_i) \le 18} \text{len}(\text{clause_tok}_i))$ och börjar i kolumn $C_i = C_{i-1} + W_{i-1} + 1$. Klausulmönster som är bredare än18tecken behandlas som avvikare: de sträcker inte ut $W_i$ för resten av gruppen utan går helt enkelt över kanten på sin egen rad med 1 mellanslag. - Matchande definitionsklausuler dras in till kolumn $6$ ($C_0$) så att funktionsnamnet eller operatororden och varje argumentmönster radas upp lodrätt under sina motsvarande platser i signaturen.
- Lodrät justering av
=>,=och->($C_{\text{arrow}}$):
- Låt $C_{\text{arrow}} = \max\big(C_{N-1} + W_{N-1} + 1,; \max_{\text{pipe_bind}}(8 + 3 + \text{len}(\text{pipe_lhs}) + 1)\big)$ och $C_{\text{ret}} = C_{\text{arrow}} + \text{len}(\text{arrow}) + 1$.
- I signaturen placeras
=>vid $C_{\text{arrow}}$ och returtypen vid $C_{\text{ret}}$. - I klausuler på en rad (
<lhs> = <rhs>), blockklausuler på flera rader (<lhs> =) och klausuler som inleds med vakter (<lhs> =följt av| cond = ...) placeras=vid $C_{\text{arrow}}$ (justerat direkt under=>); i klausuler på en rad börjar<rhs>vid $C_{\text{ret}}$. - I parallella DAG-bindningar (
|| <lhs> -> <rhs>) börjar||i kolumn $8$ (6 + 2),->placeras vid $C_{\text{arrow}}$ och<rhs>börjar vid $C_{\text{ret}}$. - Kompakt reservläge (
> 4parametrar eller> 80kolumner): Om en deklaration har fler än4parameterplatser eller om dess justerade signaturrad skulle bli längre än80tecken stängs den horisontella kolumnutfyllnaden av för den gruppen, och token skiljs åt med ett enda mellanslag (" ") samtidigt som indraget av klausuler till kolumn 6 behålls.
- Strukturellt indrag (förskjutning med 2 mellanslag):
- Deklarationer på toppnivå (
fn,op,type,import,global,context,shared,hardware,@): kolumn0. - Funktions- och operatorklausuler under en signatur: kolumn
6. - Vakter (
| cond = expr) och parallella pipes (|| expr/|| expr -> var):prev_indent + 2(kolumn8inuti en klausul, ellerindent + 2inuti en lokal bindning eller nästlad vakt). - Rader i en sekventiell blockkropp efter en rad som slutar med
=:prev_indent + 2.
Sekventiella och parallella samlingsoperationer av högre ordning (FR-COMP-001, FR-COMP-014)
Ridgun har vanliga sekventiella samlingskombinatorer (map, filter, fold) tillsammans med explicita parallella kombinatorer för flera kärnor med prefixet || (||map, ||filter). Alla fem kombinatorerna stöder både idiomatisk pipeline- och infix-syntax från vänster till höger (xs map f -> filter g -> fold 0 h -> res) och traditionell prefixsyntax (map f xs):
| Inbyggd | Prefix- och pipelineformer | Körningsmodell |
|---|---|---|
map | xs map f / xs -> map f / map f xs | Sekventiell: beräknar f x strikt från vänster till höger på den anropande tråden. |
| ` | map` | |
filter | xs filter p / xs -> filter p / filter p xs | Sekventiell: beräknar predikatet p x strikt från vänster till höger på den anropande tråden. |
| ` | filter` | |
fold | xs fold init f / xs -> fold init f / fold f init xs | Sekventiell vänstervikning: ackumulerar acc = f acc x från vänster till höger med start i init. |
Ordagrann fil-I/O, byteströmmar och inbyggda POSIX-funktioner (FR-VM-001, FR-VM-002)
- Ordagrann I/O för filer och byteströmmar (
FR-VM-001):
read_file : String => Stringläser filinnehåll ordagrant (bevarar\r\noch om det finns en radbrytning i slutet av filen eller inte, och kör aldrig kompilatorns.rg-import-förprocessor på datafiler).load_rg_source : String => Stringanvänds enbart av kompilatorns verktygskedja när.rg-källfiler läses in medimport-sammanfogning.read_bytes : String => [Int]ochwrite_bytes : String [Int] => ()läser och skriver råa binära byteströmmar (0..255, inklusive0x00NUL och0x80..0xFF).
- Inbyggda POSIX-funktioner för filsystem, processer och säkerhet (
FR-VM-002):
- Filsystem:
list_dir,file_lstat,sha256_file,sys_mkdir,sys_chmod. - Processer och miljö:
sys_exec,sys_chdir,sys_getcwd,sys_getenv,sys_setenv,sys_exit. - Säkerhet och behörighetsseparation:
sys_getuid,sys_getgid,sys_username,sys_user_groups,sys_lookup_uid_gid,sys_setresgid,sys_setgroups,sys_setresuid,sys_execve,sys_read_pass.
- Plattformsoberoende PAL-I/O, polling, processprimitiver, algebraiska datatyper för målplattformen och deklarativa
with timeout-kvoter (FR-COMP-007):
- Fördeklarerade algebraiska datatyper för målplattformen:
type SysOs = Linux | MacOS | Windows(sys os => SysOs, kan utökas viaexpand type SysOs = ...)type SysArch = X86_64 | Arm64(sys arch => SysArch, kan utökas viaexpand type SysArch = ...)- Literaler med tidsenheter: Heltalsliteraler accepterar suffixen
_ms(* 1),_s(* 1000) och_min(* 60000) (t.ex.500_ms,5_s,2_min), som komplement till suffixen för byteenheter (_KB,_MB,_GB). - Lager 1 — Plattformsoberoende PAL-primitiver för
.rglib-systembibliotek (posix.rglib/io.rglib): sys os => SysOsochsys arch => SysArch(summatyper för målplattformens operativsystem och arkitektur vid kompileringstid)sys open mode String String => Int(path, portabelt läge"r","w","a","rw","w+","a+"-> deskriptor eller handtag>= 0eller-errno, översatt för varje operativsystem)sys open String Int Int => Int(path, Ridguns normaliserade PAL-flags(0= läsning,1= skrivning,2= läsning och skrivning,64= skapa,512= trunkera,1024= lägg till i slutet,2048= icke-blockerande),mode->fd >= 0eller-errno)sys close Int => Int(fd->0eller-errno)sys read fd Int Int => String(fd,max_bytes-> sträng som lästs frånfd)sys write fd Int String => Int(fd,data-> skrivna byte eller-errno)sys poll Int Int Int => Int(fd, Ridguns normaliserade PAL-events(1=POLLIN/läsning,4=POLLOUT/skrivning),timeout_ms->> 0revents när den är redo,0vid timeout,< 0vid-errno; användersys remaining msnärtimeout_ms < 0inutiwith timeout)sys terminate Int Bool => Int(pid,force-> portabel kontrollerad eller tvingad processavslutning) ochsys kill Int Int => Int(pid, normaliserad signal ->0eller-errno)sys call Int Int Int Int Int Int Int => Int(nr,a1..a6-> nödutgång på låg nivå för systemanrop enligt målplattformens ABI)sys time ms => Intochsys sleep ms Int => ()(monoton millisekundklocka och väntan)sys deadline ms => Intochsys remaining ms => Int(aktiv lexikal deadline för timeout och återstående millisekunder, eller-1om obegränsad)- Lager 2 — Deklarativ körningskvot med
with timeout <duration> do: - Precis som
with region 64_KB dosätter en lexikal bytekvot sätterwith timeout 500_ms do(eller kombineratwith region 64_KB, timeout 500_ms do) en lexikal körningsdeadline (sys_time_ms + duration_ms) i den aktuella trådens kontext och återställer den föregående deadlinen när blocket avslutas:
with timeout 500_ms do
rem = sys remaining ms
rc = sys poll fd 1 rem
rc
- Se
docs/lang/pal-and-system-libraries.mdför den fullständiga arkitekturspecifikationen av PAL och systembibliotek (.rglib).
- Kompilering av återanvändbara bibliotek (
.rgliboch ELF64.so) och utökningsbartstable(FR-COMP-006,FR-TOOL-003):
ridgunc build --lib <file.rg> -o <out.rglib>ochridgunc build --so <file.rg> -o <lib.so>(ellerstable built lib/stable new --lib <name>) kompilerar moduler utan att krävafn :: main => ()och behåller alla exporterade funktioner, operatorer och typer.stablehittar egnafn :: task <words...> => String-kommandon ochfn :: plugins => [String]-tillägg (plugins/*.rg,.stable/plugins/*.rg), som listas medstable tasksochstable plugins.
Ridgun Memory Management (RMM): RMM1 (CMM) och RMM2 (FR-COMP-002)
Ridgun hanterar heapminne (String, [a], (a, b), algebraiska datatyper, Tensor) deterministiskt utan en spårande skräpsamlare (GC) genom Ridgun Memory Management (RMM):
- Policy
RMM1— Kompilerad minneshantering (linjär + villkorlig CMM):
- Tillämpas när kontrollflöde och anropade funktioner är statiskt kända vid kompileringstid för icke-nästlade bindningar:
- Linjär CMM (
rg_cmm_move/rg_cmm_drop): Kompilatorn bestämmer vid kompileringstid exakt vilken sats som är den sista som använder varje lokal variabel, flyttar returnerade variabler (rg_cmm_move(&mut lv_x)) och lägger in ovillkorlig frigörning (rg_cmm_drop(&mut lv_x)) direkt efter variabelns sista användning när inga möjliga alias lever kvar. - Villkorlig CMM (
rg_cmm_drop_unless/ptr(a) != ptr(c)): När ett statiskt förgrenande anrop (c = choose_list cond a b) returnerar en av flera möjliga indata och en eller flera av kandidaterna lever kvar tillsammans medcbygger kompilatorn härkomsttabellen för möjliga alias (RCmmAlias) och lägger in en pekaridentitetsvakt på 1 cykel vid varje variabels statiska sista användning:
a = make_a () -- Allocates M1
b = make_b () -- Allocates M2
c = choose_list cond a b -- b dies here while c is live -> if ptr(b) != ptr(c) { free(b) }
print_list a -- a dies here while c is live -> if ptr(a) != ptr(c) { free(a) }
consume_list c -- c dies here (no live peers) -> free(c) (unconditional)
- Policy
RMM2— Tilldelningsräkning och strukturräkning i kaskad (aktiv policy):
- Förenar minneshanteringen över funktioner, förgrenande returer (
choose_list), nästlade behållare (xs = [a, b, ..., z],xs[3] = a), muterbara lokala variabler (mut x = ...) och körning i flera trådar: - Primitiva skalärer (
Int,Real,Bool,()): Räknas aldrig; kopieras som värden på stacken eller i register. - Inkommande funktionsargument (
pats): Rörs aldrig (+0vid inträde,-0vid utträde). - Interna lokala variabler (
x = .../mut x = ...): Får+1vid tilldelning (x = expr,xs[3] = a). Vid omtilldelning av en muterbar variabel (x = new_expr) fårnew_expr+1innan gamlaxfår-1. - Slutet av funktionen eller utträde ur ett scope:
- Interna lokala variabler som inte returneras får först
-1: omrc == 0frigörs föräldrablocket och sprider-1i kaskad, en i taget, till varje direkt barnstruktur (och frigör rekursivt varje barn varsrcnår0). - En intern lokal variabel som returneras (
return a) får-1(eller flyttas viarg_cmm_move), och även om dessrcär0under transporten skonas den, så att anroparens tilldelning (c = make_pair ()) lägger till+1(0 + 1 = 1). När ett inkommande argument returneras (choose_list cond a b) har det inte rörts inuti funktionen (rc = 1), så anroparensc = choose_list cond a blägger till+1(1 + 1 = 2, delat mellanaochc).
- Policy
RMM3(reserverad):
- Reserverad för en kommande aggressiv statisk optimeringspolicy.
- Se
docs/etc/cmm_architecture.md(i Ridguns repository) för den fullständiga specifikationen avRMM1ochRMM2.