Joan edukira
Ridgun
Euskara

Erreferentzia

Ridgun lengoaiaren espezifikazioa

Ikuspegi orokorra

Ridgun lengoaia funtzionala da, paralelismoa oinarrian duena, hizkuntza naturaleko eragileak eta tipatze estatiko sendoa dituena. Haren sintaxiak Haskell eta ML familiako lengoaietan du inspirazioa, eta paralelismorako eta gizakiek irakurtzeko moduko eragileak definitzeko eraikuntza berriak gehitzen ditu.

Ezaugarri nagusiak:

  • Hizkuntza naturaleko eragileak — Eragileak ingelesezko esaldiak bezala irakurtzen dira
  • Paralelismo inplizitua — Exekuzio paraleloa primitiba sintaktikoa da, ez liburutegi-dei bat
  • Tipatze estatiko sendoa — Mota guztiak sinaduretan deklaratzen dira
  • Ereduen bidezko definizioak — Funtzioak eta eragileak ekuazioen bidez definitzen dira

Iruzkinak

Lerro bakarreko iruzkinek -- erabiltzen dute:

-- This is a comment

Testu-kateak

Ridgunek bi kate-literal mota ditu, interpolazioaren aldetik portaera desberdinarekin.

Kate interpolatuak (komatxo bikoitzak)

Komatxo bikoitzeko kateek lerro barruko kode-interpolazioa onartzen dute {expr} erabiliz. Giltzen arteko adierazpena ebaluatu egiten da eta emaitza katean txertatzen da.

name = "Ridgun"
"Hello, {name}!"                         -- "Hello, Ridgun!"
"Sum is {sum 3 4}"                       -- "Sum is 7"
"Nested: {factorial 5} done"             -- "Nested: 120 done"

"..." barruan giltza literal bat sartzeko, ihes egin alderantzizko barrarekin (\{ eta \}) edo bikoiztu ({{ eta }}):

"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"

Kate gordinak (komatxo bakunak)

Komatxo bakuneko kateak gordinak dira: ez da interpolaziorik egiten. Karaktere guztiak testu literal gisa hartzen dira, giltzak barne.

'Hello, {name}!'                         -- "Hello, {name}!"
'{this is just pure chars}'              -- "{this is just pure chars}"
'No {interpolation} here'               -- "No {interpolation} here"

Laburpena

SintaxiaInterpolazioaErabilera
"..."Bai — {expr} (ihes egin giltzei \{/\} edo {{/}} erabiliz)Adierazpenak txertatuta dituzten kate dinamikoak
'...'Ez — dena literalaTestu estatikoa, txantiloiak, regex ereduak

Programaren egitura

Ridgunen kode exekutagarri guztiak funtzio edo eragile baten barruan egon behar du. main funtzioa da programa exekutatzeko derrigorrezko sarrera-puntua.

fn :: main => ()
      main = echo "Hello, Ridgun!"

Ridgun iturburu-fitxategi batek hauek bakarrik izan ditzake:

  • import sententziak
  • type definizioak
  • fn eta op deklarazioak eta definizioak
  • main funtzio bat sarrera-puntu gisa

Ez da onartzen goi-mailako adierazpen soltarik. Exekutatzen den guztiari main-etik deitu behar zaio.

CLI erabilera

ridgunc <command> [options] <file.rg>
KomandoaZertarako
runIturburu-fitxategi bat konpilatu eta exekutatzen du
checkMotak egiaztatu eta aztertzen ditu, exekutatu gabe
compile.rgc bytecode-fitxategi bat sortzen du
buildExekutagarri natibo bat sortzen du; liburutegi bat --lib edo --so aukerarekin
versionKonpiladorearen bertsioa erakusten du
helpLaguntza erakusten du

Formatua, probak eta proiektuak stable tresnaren ardura dira.


Funtzioak eta eragileak

Funtzioak eta hizkuntza naturaleko edo infix eragileak => <return_type>-rekin amaitzen den mota-sinadura batekin deklaratzen dira, eta atzetik ekuazio bat edo gehiago (cases) dituzte. Hasierako fn :: eta op :: aurrizkiak aukerakoak dira:

  • Aurrizkirik gabeko forma kanonikoa (0 zutabean hasten da):
  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)
  • Aurrizki esplizitudun forma (fn :: / op ::, 0 zutabean hasten da, klausulak 6 zutabean lerrokatuta):
  fn :: sum Int Int => Int
        sum a   b   =  a + b

  fn :: format app err AppErr        => String
        format app err (IoError msg) =  "IO:{msg}"
  • Hizkuntza naturaleko zuriuneak fn ::-n, funtzio integratuetan eta fitxategi-izenetan (FR-COMP-005):
  • fn :: deklarazioek eta deiek zuriunez bereizitako hitz anitzeko izenak onartzen dituzte (fn :: format app err AppErr => String, fn :: project name => String), op :: eta aurrizkirik gabeko deklarazioek bezala.
  • Runtime-ko eta testetako funtzio integratuei zuriuneekin dei dakieke (assert equals a b, str len s, read file p, cmm live blocks), eta _ formek ere bateragarriak izaten jarraitzen dute.
  • ridgunc-ek eta stable-k modu natiboan onartzen dituzte hitz anitzeko funtzio-erreferentzia lehen mailakoak (map double val xs, ||map double val xs, filter is even xs, fold add pair 0 xs) eta zuriuneak dituzten .rg fitxategi-izenak (src/test/ridgun/test core language.rg).

Mota-aldagai polimorfikoak (A..Z) eta testuinguruko gako-hitzak (type, with)

Eragile-hitzen eta mota-parametroen artean anbiguotasun lexikorik ez dagoela bermatzeko, bai aurrizkidun sinaduretan (op ::) bai aurrizkirik gabekoetan:

  • Sinadura bateko mota-token guztiak letra larriz hasten dira (edo [...] / (...)-rekin):
  • Letra larri bakarrek (A..Z) mota-aldagai polimorfikoak adierazten dituzte (adibidez, [A], (A, B), (A => B), swap A with B => (B, A)). Parametroetan errepikatzen den mota-aldagaia bateratu egiten da dei-gune bakoitzean, eta itzulera-motan ordezkatzen da.
  • Letra larriz hasitako karaktere anitzeko identifikatzaileek (Int, String, Bool, RExpr, Tensor) mota zehatzak edo erabiltzaileak definitutakoak adierazten dituzte.
  • Goi-mailako sinadura bateko letra xehez idatzitako token guztiak (edo +, -, *, /, % eragile-ikurrak) funtzioaren edo eragile mixfix-aren izenaren parte dira.
  • type eta with testuinguruko gako-hitzak: type-k goi-mailan bakarrik sartzen du mota-deklarazio bat, eta atzetik UpperName = duenean soilik. Beste leku guztietan (fn :: eta op :: sinaduretan, eragile-hitzetan, parametro-ereduetan, aldagai lokaletan eta erregistro-eremuen izenetan), type eta with baliozko identifikatzaile edo hitzak dira, anbiguotasunik gabe.
  • => aurretik letra xehezko identifikatzaile bat hasieran eta motak bakarrik dituen goi-mailako sinadura aurrizki-funtzio bat da (fn); => aurretik motekin tartekatuta bi letra xehezko hitz edo gehiago edo eragile-ikurrak dituen edozein sinadura eragile mixfix, infix edo postfix bat da (op).

Deklarazioa eta definizioa bereizita daude:

  • Deklarazioa (fn ::) — izena, parametro-motak eta itzulera-mota zehazten ditu
  • Definizioa — parametro-izenak lotzen ditu eta inplementazioa ematen du

Eragileak

Eragileak dira Ridgunen ezaugarri bereizgarria. Hizkuntza naturalaz izendatzen dira eta op ::-rekin definitzen dira. Ohiko eragileek (+, -) ez bezala, Ridgunen eragileak esaldiak bezala irakurtzen diren hitz anitzeko adierazpenak dira.

Sintaxia

op :: <natural language signature with types> -> <return_type>
      <natural language pattern with params> = <body>

Oinarrizko adibidea

-- Declaration: "add [Int] to [Int]" returns an Int
op :: add Int to Int => Int
      add a to b = a + b

Erabilera honela irakurriko litzateke: add 3 to 5 → 8

Parametro tipatuen arteko hitzak (to, and, in eta abar) eragilearen gako-hitzak dira: eragilearen identitatearen parte dira eta dei-guneetan agertu behar dute.

Eragile paraleloak (||)

Eragileek exekuzio paraleloa lehen mailako kontzeptu gisa adieraz dezakete || erabiliz:

-- 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

Elementu nagusiak:

  • Itzulera-balio anitz — => Res, Res-k bi itzulera-balio deklaratzen ditu
  • || expr -> var blokea — Azpikalkuluak emaitza-izenei lotzen dizkie (where kendu egin da; ||-k adar paralelo guztiak bateratzen ditu)
  • -> — Azpikalkulu paralelo baten emaitza aldagai bati (edo tentsore-xerra bati, -> out[i, j]) esleitzen dio
  • || adar independenteak aldi berean exekutatzen dira DAG paralelo gisa, datuen mendekotasunen arabera

Bloke paralelo zuzena (|| expr)

Adierazpen edo funtzio batek tarteko aldagai-izenik gabe kalkulu paraleloen tupla bat zuzenean itzultzen duenean, || lerroak = ondoren agertzen dira zuzenean:

-- 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

|| lerro bakoitza ataza paralelo independente gisa exekutatzen da. Emaitzak deklarazio-ordenan biltzen dira.

Eragileak gainkargatzea

Lehendik dauden eragileak (+ bezalako integratuak barne) mota berrietarako gainkarga daitezke:

-- Overload + for Complex numbers
op :: Complex + Complex => Complex
      a + b = (real a) + (real b) + complex_i * ((imaginary a) + (imaginary b))

Lehentasuna

Eragile sinbolikoek dute lehentasunik handiena: matematika lehenik.

Eragile sinbolikoak (+, * bezalakoak) hizkuntza naturaleko eragileen gorputzetan agertzen direnean, inguruko eragile-gako-hitzek baino estuago lotzen dira. Horri esker, adierazpen aritmetikoak espero bezala ebaluatzen dira, parentesi gehigarririk gabe.

LehentasunaKategoriaAdibideak
HandienaEragile sinbolikoak*, /, +, -, %
Funtzio-aplikazioaf x
Alderaketa==, !=, <, >
Logikoakand, or, xor, not
TxikienaHizkuntza naturaleko eragileakadd a to b, run a and b in parallel

Eragileak kateatzea eta ezkerretik eskuinerako hodi idiomatikoak (->) (FR-COMP-014)

Balioak edo sekuentziak eraldatzen dituzten eragileak eta funtzioak ezkerretik eskuinera katea daitezke, datuak iturritik helmugara modu naturalean joan daitezen, eskuinetik ezkerrerako parentesi habiaratuen (h (g (f x))) edo behin erabiltzeko tarteko aldagaien (st1, st2, st3) beharrik gabe.

1. Gomendatutako Ridgun hodi-estilo idiomatikoa (2b)

Ridgunek ezkerreko eragigaiaren infix deia eta -> hodi-urrats esplizituak AST berean bateratzen ditu. Beheko lau formak baliozkoak eta baliokideak diren arren, 2b forma da gomendatutako Ridgun estilo idiomatikoa: subjektu eta eragiketa batekin hasten da ezkerrean, ondorengo eraldaketak ->-rekin kateatzen ditu eta azken emaitza -> target-ekin lotzen du:

-- 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

Urrats anitzeko hodiak ->-rekin hasten diren koskadun jarraipen-lerroetan ere idatz daitezke:

raw_nums map (x => x * 3)
  -> filter (x => x >= 12)
  -> fold 0 (acc x => acc + x)
  -> total_sum

2. ->-ren lehen argumentuaren arau unibertsala eta bilduma-konbinatzaileak

  • Funtzioen eta eragileen arau unibertsala: ->-ren ezkerretik datorren edozein balio (edo x op a b infix dei baten ezkerretik datorrena) eskuineko funtzioaren edo eragilearen lehen argumentu gisa sartzen da:
  • x -> f a b $\equiv$ x f a b $\equiv$ f x a b
  • Arazorik gabe funtzionatzen du bai fn :: deklarazioekin bai op :: deklarazio mixfix-ekin, sinadurak bikoiztu gabe.
  • Ondorengo funtzio batek hodiko balioa lehena ez den parametro-posizio batean behar badu, _ leku-marka esplizitu batek _ horretan jartzen du balioa (payload -> write_file output_path _).
  • Bilduma-konbinatzaileak (map, ||map, filter, ||filter, fold): Bilduma onartzen dute bai ohiko aurrizki-posizioan (map f xs, filter g xs, fold f init xs) bai infix edo hodi-urrats baten ezkerretik (xs map f, xs -> map f, xs filter g, xs -> filter g, xs fold init f, xs -> fold init f).
  • Agente-urratsak (-> send to, -> ask to): -> send to ag edo -> ask to ag urratsek ezkerreko balioa pasatzen dute mezu gisa ([5, 10, 15] -> sum int list -> send to worker_ag).
  • Amaierako aldagai-lotura (-> var): Bloke sekuentzial bateko hodi-sententzia bat -> var-rekin amaitzen denean (var aldagai lokal baten izena denean eta ez deklaratutako funtzio batena), var lotzen du (var = <pipeline_result>) blokearen gainerakorako.

3. Sekuentzia-maskarak hodietan (-> (+ _ _ +) ->)

Urrats batek balio anitzeko sekuentzia edo tupla bat itzultzen duenean, sekuentzia-maskara urrats batek (-> (+ _ _ +) ->) haren elementuak iragazten ditu (+-k posizio bat mantentzen du, _-k baztertu egiten du) eta hautatutako tupla zuzenean despaketatzen du hurrengo argumentu anitzeko funtziorako:

parse header packet "v0.9.9" -> (+ _ _ +) -> combine code msg -> status_line

4. _ = gabeko albo-ondorioko sententziak eta Unit balioaren baztertze esplizitua (-> ())

Bloke sekuentzialetan, albo-ondorioko sententziak (echo, write_file, write_bytes, shell_exec, log info, print_error_lines, sys_mkdir eta abar) zuzenean idazten dira, _ = errepikapenik gabe:

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

=> () funtzio baten azken adierazpenak () ez den balio bat itzultzen duen laguntzaile bati deitzen dionean (adibidez, shell_exec : String => Int), gehitu -> () adierazpena ebaluatzeko, haren itzulera-balioa baztertzeko eta () emateko:

fn :: exec built run Int => ()
      exec built run 0   =  shell_exec "./target/app" -> ()
      exec built run _   =  sys_exit 1

5. Sekuentzia-eragileak point-free erara kateatzea

Sekuentziak itzultzen dituzten eragileak ere point-free erara katea daitezke:

op :: Int Int switch -> Int Int
      a   b   switch =  b   a

op :: Int Int invariant -> Int Int
      a   b   invariant =  a b switch switch

Oharra: -> eta => biak onartzen dira itzulera-motaren bereizle gisa fn :: / op :: goiburuetan. Adierazpenetan, -> ezkerretik eskuinerako hodi- eta lotura-eragilea da, eta =>-k itxitura lexikoak sartzen ditu: (x => expr).


Mota-sistema

Mota-sinadurak

Mota-sinadurak deklarazioetan agertzen dira, fn :: edo op :: ondoren (edo aurrizkirik gabe):

fn :: <name> <type1> <type2> ... => <return_type1> <return_type2> ...
op :: <words and types mixed> => <return_type1> <return_type2> ...
  • Parametroak posizionalak dira; motak parametroak espero diren lekuan agertzen dira.
  • Tuplen eta sekuentzien mota-sintaxi bateratua (FR-COMP-008):
  • Ridgunen, T1 T2 ... Tn argumentu-zerrenda batek eta (T1, T2, ..., Tn) tupla batek azpiko mota konposatu bera adierazten dute: tipatutako balioen sekuentzia ordenatu eta tamaina finkoko bat (seq).
  • Horregatik, zuriunez bereizitako motak eta komaz bereizitako tupla-motak % 100 trukagarriak dira itzulera-motetan, zerrenda-kortxeteetan eta parentesi arteko tupletan:
  • Itzulera-motak => / -> ondoren:
      fn :: parse header String => Int Int [String String] String
      -- 100% equivalent to:
      fn :: parse header String => (Int, Int, [(String, String)], String)
  • Tuplen zerrendak ([T1 T2 ... Tn]):
      [String String]        -- equivalent to [(String, String)]
      [Int String Bool]      -- equivalent to [(Int, String, Bool)]
  • Parentesi arteko tuplak ((T1 T2 ... Tn)):
      fn :: fst (A B) => A
            fst (a, _) =  a
  • Zergatik ez duen honek anbiguotasun sintaktikorik: Haskell/ML-n ez bezala (non Maybe Int elkarren ondoan jartzeak mota-aplikazioa adierazten duen), Ridgunen mota parametrizatuek parentesi esplizituak erabiltzen dituzte (Tensor(Float, 3, 3)) eta zerrendek kortxeteak ([T]). Gainera, mota-token guztiak letra larriz (A..Z, Int, String), [-rekin edo (-rekin hasten dira, eta funtzio- eta eragile-hitzak letra xehez idazten dira. Beraz, T1 T2 ez dator inoiz talkan mota-eraikitzaileekin edo eragile-gako-hitzekin.
  • => (edo ->) geziak sarrera-motak eta itzulera-mota bereizten ditu.

Mota integratuak

MotaDeskribapena
IntOsokoa
RealZenbaki erreala
BoolBoolearra
CharUnicode karaktere bakarra (UTF-8)
StringTestu-katea (UTF-8)
ComplexZenbaki konplexua
TensorN dimentsioko tentsore aldakorra (Real elementuak, PUZ)
Tensor_GPUN dimentsioko tentsore aldakorra (Real elementuak, GPU)

[!NOTE] Ridgunen testu guztia UTF-8 kodeketan dago lehenespenez. Char-ek Unicode kode-puntu bakarra adierazten du, eta String Char-en sekuentzia bat da.

Bool literalak

Bool-ek bi balio primitibo ditu:

True                                     -- boolean true
False                                    -- boolean false

True eta False eraikitzaileak dira: adierazpenetan erabil daitezke, argumentu gisa pasa daitezke eta ereduekin parekatu daitezke:

fn :: is_valid Int => Bool
      is_valid n =
        | n > 0     = True
        | otherwise = False

Eragile logikoak

Ridgunek letra xehezko hitzez osatutako eragile logikoak erabiltzen ditu, ikurren ordez:

EragileaEsanahiaAdibidea
andKonjuntzio logikoaa and b
orDisjuntzio logikoaa or b
xorDisjuntzio esklusiboaa xor b
notUkapen logikoanot a
result = True and False                  -- False
result = True or False                   -- True
result = True xor True                   -- False
result = not False                       -- True

Hauek gako-hitzezko infix eragileak dira, semantika boolear estandarrarekin.

Bilduma-mota natiboak

Zerrendak

Zerrendak mota errekurtsibo integratu eta aldaezinak dira, sintaxi propioarekin. Ez dago eskuzko ADT definiziorik egin beharrik. Zerrendak egokiak dira datuen prozesamendu funtzionalerako, kalkulu sinbolikorako eta algoritmo errekurtsiboetarako. Zenbakizko kalkulu aldakorrerako, ikus Tentsoreak behean.

Mota-sintaxia: [type] — emandako motako elementuen zerrenda bat.

fn :: sum_list [Int] => Int
fn :: reverse [Int] => [Int]

Literal-sintaxia: [elem1, elem2, ...] — zerrenda-literal bat. [] zerrenda hutsa da.

fn :: my_list => [Int]
my_list = [1, 2, 3, 4, 5]

Cons ereduen bat-etortzea: (x:xs) — zerrenda bat x burutan eta xs isatsean deskonposatzen du. [] zerrenda hutsarekin bat dator. Erabili _ komodin gisa: bat dator baina ez du ezer lotzen.

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

Kateaketa: ::-k bi zerrenda (edo sekuentzia) elkartzen ditu.

fn :: append [Int] [Int] => [Int]
      append a b = a :: b

Tentsoreak

Tentsoreak Ridgunen N dimentsioko zenbakizko mota natibo eta aldakorra dira. Bektoreak, matrizeak eta dimentsio handiagoko matrizeak mota bakarrean orokortzen dituzte. Elementuak Real dira lehenespenez.

Literal-sintaxia: Tensor eta atzetik kortxete habiaratuak. Habiaratze-sakonerak dimentsio-kopurua zehazten du.

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]]]

Indexatzea: Bai indexatze kateatua bai komaz bereizitakoa onartzen dira.

val = m[0][1]        -- chained indexing: row 0, col 1
val = m[0, 1]        -- comma indexing: equivalent
row = m[0]           -- slice: entire first row

Aldaketa (lekuan bertan): Tentsoreak aldakorrak dira: elementuak eta xerrak lekuan bertan alda daitezke (PyTorch/NumPy eran).

m[0, 1] = 5.0                            -- set element
m[0] = Tensor [10, 20]                   -- set entire row

Tentsore-uzkurdura (@): @ eragileak Einsteinen batuketa egiten du. Eragigai bakoitzeko azpiindizeek uzkurdura definitzen dute: eragigai guztiek partekatzen dituzten indizeak batu egiten dira, eta indize bakarrek emaitzan irauten dute.

-- 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)

Uzkurdurak adierazpen bakarrean hainbat tentsorerekin funtzionatzen du:

-- 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 eragiketak (+, -, *, /): Azpiindizeak dituzten eragile aritmetikoek elementuz elementuko eragiketak egiten dituzte. Bat datozen indizeek dimentsioak lerrokatzen dituzte, eta bat ez datozenei broadcasting aplikatzen zaie.

-- 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

Horrek unsqueeze, expand_dims edo eskuzko birmoldaketen beharra kentzen du: indizeak dira broadcasting arauak.

GPU aldaera: Tensor_GPU-k tentsorea GPUaren memorian jartzen du kalkulua azkartzeko.

g = Tensor_GPU [[1, 2], [3, 4]]
result = g_ij @ g_jk                     -- GPU-accelerated matrix multiply

Sekuentziak (seq)

Sekuentziak Ridgunen oinarrizko mota konposatua dira. seq bat balioen bilduma ordenatu eta tamaina finkokoa da: funtsean, tupla tipatu bat. Funtzioen eta eragileen parametro-zerrendak inplizituki sekuentziak dira.

-- 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 lotura ((name)) — parametro-izen bat parentesi artean jartzeak parametro guztiak seq aldagai bakarrean lotzen ditu:

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

Maskara-hautatzailea (s(+ _)) — elementuak maskara baten bidez ateratzen ditu: +-k posizio bat hautatzen du eta _-k saltatu egiten du:

s(+ _)                -- select 1st, skip 2nd
s(_ +)                -- skip 1st, select 2nd
s(+ _ _ _)            -- select 1st, skip 2nd-4th
s(_ _ _ +)            -- skip 1st-3rd, select 4th

Indize-hautatzailea (s(0 3)) — elementuak zerotik hasitako posizioen bidez ateratzen ditu:

fn :: extreme_points Int Int Int Int => Int Int
      extreme_points (s)             =  s(0 3)

Elkartze laua (:) — bi sekuentzia sekuentzia lau bakarrean kateatzen ditu:

seq1 = a, b         -- seq(a, b)
seq2 = c, d         -- seq(c, d)
seq1:seq2            -- seq(a, b, c, d)

Habiaratzea (,) — sekuentziak elementu bereizi gisa konposatzen ditu (sekuentzien sekuentzia):

seq1, seq2           -- seq(seq(a, b), seq(c, d))

Datu-mota aljebraikoak (ADTak)

Ridgunek datu-mota aljebraikoak erabiltzen ditu erabiltzaileak definitutako motetarako. Ez dago klaserik, metodorik edo impl blokerik: funtzioek eta eragileek motak hartzen dituzte parametro gisa.

Biderkadura-motak (erregistroak) eta erregistroak eguneratzeko sintaxia (with)

Eremu izendunak dituen mota:

type Conf  = host: String, port: Int, tls: Bool
type Point = x: Real, y: Real

Eremuak izenez atzitzen dira, funtzioak balira bezala (host c, port c), eta modu funtzionalean eguneratzen dira with eta bi puntuak : erabiliz:

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

Batura-motak (aldaerak)

| bidez bereizitako eraikitzaile anitz dituen mota:

type Result = Ok Int | Err String
type Option = Some Int | None
type Color = Red | Green | Blue

Batura-ADT generikoak eta biderkadura-erregistro generikoak (FR-COMP-013)

Erabiltzaileak definitutako batura-ADTek eta biderkadura-erregistroek letra larrizko mota-parametro bat edo gehiago deklara ditzakete (A..Z edo letra larriz hasitako mota-aldagaien izenak) motaren izenaren eta =-ren artean:

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
  • Mota parametrikoen aplikazioak (Result Int String, Page User, [Box Int]) fn :: / op :: sinaduretan, erregistro-eremu habiaratuetan eta ADT eraikitzaileen edukietan erabil daitezke.
  • Eraikitzaileek (Ok 42, Ok "hello", Page [1, 2] 2), eredu bat-etortzeak, eremu-atzitzaileek (items p, total p) eta erregistroen eguneratze funtzionalek (p with total = 10) mota-aldagai berriak instantziatzen dituzte dei-gune bakoitzean.
  • type Option A = Some A | None ADT polimorfiko integratu gisa erregistratzen da aurrez, erabiltzaileak dagoeneko deklaratu ez badu; beraz, try receive from ag-k Some v edo None itzultzen du, deklarazio gehigarririk behar izan gabe (FR-COMP-013).

Funtzio anonimoak eta itxitura lexikoak ((x => expr), (a b => expr) — FR-COMP-013)

Funtzio anonimoak (lambdak) parentesi artean idazten dira, zuriunez bereizitako parametroekin eta atzetik => eta gorputzaren adierazpena jarrita ((x => expr) edo (a b => expr), adibidez map (x => x + offset) xs, fold (acc x => acc + x) 0 xs), eta aldagai lokalak edo parametroak harrapa ditzakete inguruko esparru lexikotik:

fn :: add offset Int [Int] => [Int]
      add offset k   xs    =  map (x => x + k) xs

Bost arau kanonikok gobernatzen dituzte funtzio anonimoak:

  1. Derrigorrezko parentesiak: Lambda orok parentesi artean egon behar du: (... => ...). Parentesirik gabeko x => expr (adibidez f = x => x + 1) konpilazio-errorea da (lambda expression must be enclosed in parentheses: '(x => expr)').
  2. Parametrorik gabeko lambdak ((=> expr)): Ridgunek debekatu egiten du () jartzea => aurretik funtzio-sinaduretan (fn :: main => ()). Horrekin bat etorriz, parametrorik gabeko lambda (=> expr) idazten da (thunk () gisa deitzen zaio), eta sinaduretan bere mota (=> Type) da. (() => expr) edo (() => Type) idaztea konpilazio-errorea da.
  3. Parametro anitz tuplen deskonposizioaren aldean ((a b => expr) eta ((a b) => expr)): (a b => expr) 2 parametroko lambda bat da (adibidez fold (acc x => acc + x) 0 xs), eta ((a b) => expr), berriz, tupla bat deskonposatzen duen parametro bakarreko lambda bat (map ((a b) => a + b) [(1, 2), (3, 4)]). Biak nahasteak aldea azaltzen duen mota-errore berezi bat sortzen du.
  4. Lerro anitzeko lambda-gorputzak: => lerroaren amaieran dagoenean, azpiko koskadun blokeak sententzia anitzeko gorputza (edo | zain-gorputza) osatzen du, eta )-k ixten du:
   map (x =>
     doubled = x * 2
     doubled + offset
   ) [1, 2, 3]
  1. Letra larrizko motak eta letra xehezko balioak: (Conn => Conn) funtzio-mota bat da eta (conn => conn) lambda-balio bat. Letra larrizko motak ((Conn => Conn)) adierazpen batean edo letra xehezko parametroak ((conn => conn)) fn :: sinadura batean idaztea konpilazio-errore argi batekin baztertzen da.

Harrapatutako loturak automatikoki aplikazio partzialeko itxitura bihurtzen dira, eta RMM1/RMM2-k kudeatzen ditu.

Mota errekurtsiboak

Motek beren buruari erreferentzia egin diezaiokete:

type List = Empty | Cons Int List
type Tree = Leaf Int | Node Tree Tree

Motek partekatutako eraikitzaile-izenak (FR-COMP-005)

type deklarazio anitzek aldaera-eraikitzaileen izen berak (Error, Var, Lit, None eta abar) berrerabil ditzakete, aritate berdin edo desberdinekin. Mota-egiaztatzaileak eraikitzaile-ereduak zutabeak espero duen parametro-motaren bidez bereizten ditu, eta eraikitzaile-deiak argumentuen aritate eta moten eta ADT bildura itzulera-moten bidez ebazten ditu:

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

Mota irekien hedapenak (expand type) eta fn :: klausulen bateratze automatikoa (FR-COMP-005)

Lehendik dauden batura-ADTak eta biderkadura-erregistroak expand type UpperName = ...-rekin heda daitezke:

  • Batura-ADT bat hedatzea: aldaera-eraikitzaile berriak gehitzen dizkio lehendik dagoen motari.
  • Biderkadura-erregistro bat hedatzea: eremu izendun berriak (field: Type) gehitzen ditu eta haien eremu-atzitzaile funtzioak automatikoki sortzen ditu.
  • Mota-izeneko aldaerak, eraikitzaile-izen erredundanterik gabe: type eta expand type batura-deklarazioetan, izena mota integratu soil bat (String, Int, Real/Float, Bool, Char) duen eta atzetik mota-argumentu gehigarririk ez duen aldaera batek mota horretako balioak zuzenean adierazten ditu (Int Int edo String String idatzi gabe). Deitzaileek balio soilak (describe "hej", describe 42) edo eraikitzaile-dei esplizituak (describe (String "hej"), describe (Int 42)) pasa ditzakete, eta ekuazioak bai literalekin ("admin", 0) bai eredu tipatuekin ((String s), (Int n)) parekatu daitezke.
  • fn :: / op :: klausulen bateratze automatikoa (expand fn gabe): lehendik dagoen fn :: edo op :: bat eredu-klausula berriekin berriro deklaratzean, klausula horiek automatikoki bateratzen dira lehendik dagoen funtzio-definizioan, eta eraikitzaile edo literal zehatzen eredu-klausulak dena harrapatzen duen edozein ordezko klausularen (_ / aldagaia) aurretik jartzen dira:
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

Moduluen izen-espazioak, sarbide kualifikatua eta modulukako inportazio-ikusgarritasun zorrotza (FR-COMP-012)

.rg fitxategi edo .rglib sorta bakoitzak moduluaren izen-espazio bat definitzen du (fitxategi-izenaren oinarritik edo module :: <name> goiburu esplizitu batetik ateratzen da), eta beste modulu batzuk inporta ditzake import <mod> edo import <mod> as <alias> erabiliz.

  1. Fitxategi anitzeko moduluak (module :: <name>):
  • module :: <name> goiburu bera deklaratzen duten fitxategi anitzek (adibidez, orm.rg eta orm_changeset.rg, biak module :: orm-ekin hasita) orm izen-espazio logiko bakarra partekatzen dute, eta elkarren motak, eraikitzaileak, erregistro-eremuak eta funtzioak zuzenean ikusten dituzte.
  1. Sarbide kualifikatua (mod.Type, mod.Constructor, mod.field, mod.fn):
  • Esportatutako motei, batura-ADTen eraikitzaileei, biderkadura-erregistroen eremu-atzitzaileei, erregistro-eguneratzeei (with) eta funtzioei <mod_or_alias>. aurrizkiarekin egin dakieke erreferentzia (http.Config, db.Status, http.Ok 200, http.port cfg, http.check status cfg).
  1. Modulukako izen kualifikatugabeen 3 mailako ebazpen zorrotza:
  • M modulu bakoitzak (erroko aplikazio-modulua barne) kualifikatu gabeko motak, eraikitzaileak, erregistro-eremuak, funtzioak eta hitz anitzeko deiak M-ren inportazio-grafoaren arabera bakarrik ebazten ditu, hiru lehentasun-mailatan:
  • 1. maila — Modulua bera (M): M-ren beraren deklarazioek (module :: M partekatzen duten fitxategi guztietan) dute beti lehentasunik handiena.
  • 2. maila — M-ren inportazio zuzenak: M-k izena definitzen ez badu, ridgunc-ek M-k zuzenean inportatutako moduluetan bilatzen du (import D). Inportazio zuzen bakar batek (D) definitzen badu izena, D-ren deklaraziora ebazten da, anbiguotasunik gabe, konpilazio-unitateko beste modulu batzuek (mendekotasun iragankorrek, ondoko moduluek edo erroko aplikazioak) izen bera definitzen badute ere. M-ren bi inportazio zuzenek edo gehiagok izen bera definitzen badute eta M-k definitzen ez badu, kualifikatu gabeko erreferentziak anbiguo gisa baztertzen dira (__ambiguous__.<name>) eta kualifikatu egin behar dira (d1.<name> edo d2.<name>).
  • 3. maila — M-ren inportazio iragankorrak: 1. eta 2. mailek izena definitzen ez dutenean bakarrik kontsultatzen dira. Ondorioz, M-ko inportazio zuzen batek (import json) garbi estaltzen du laguntzaile iragankor bat (solstice-k barnean inportatutako codec.json_get_str), solstice edo M deiak berrizendatzera edo kualifikatzera behartu gabe.
  • Inportatu gabeko ondoko moduluekiko eta erroko aplikazioarekiko isolamendua: M-k inportatu ez dituen moduluetan (ez zuzenean, ez iragankorki) bakarrik definitutako deklarazioak ikusezinak dira M barruko kualifikatu gabeko bilaketarentzat (__unimported__.<name>). Horien artean daude erroko aplikazioak inportatutako ondoko liburutegiak eta, M liburutegi inportatua konpilatzean, erroko aplikazioaren beraren deklarazioak.

= gramatika bateratua ((none), |, ||) eta aldagai lokalak (FR-COMP-003)

Ridgunen definizio edo lotura orok —dela funtzio-klausula bat (fn ::), eragile-klausula bat (op ::), aldagai lokal aldaezin bat (x =), aldagai lokal aldakor bat (mut x =) edo zain-adar bat (| cond = / | otherwise =)— =-rekin amaitzen da eta eskuinaldean lau bloke- edo adierazpen-forma berberak onartzen ditu:

= ondorengo aurrizkiaExekuzio-semantikaEsanahia
Lerroko <expr>Adierazpen bakarra (azpian || expr -> var lerro aukerakoekin)<expr> zuzenean ebaluatzen du (azpiko || DAG lotura paraleloak ebatzita).
(none) (lerro koskadunak)Sekuentziala (goitik behera)Sententziak ordenan ebaluatzen ditu (mut, esleipenak, albo-ondorioak); azken adierazpena da emaitza.
| <cond> = ...Baldintzazkoa (zainak eta erabaki-zuhaitz habiaratuak)Baldintza boolearrak goitik behera ebaluatzen ditu, lehen True adarrera (edo | otherwise =-ra) iritsi arte.
|| <expr>Paraleloa (green-thread DAG / tupla)|| adarrak aldi berean ebaluatzen ditu (|| expr -> var DAG nodo izendunetarako, || expr tupla-emaitza paraleloetarako).

1. Zainak (|) beti =-ren atzetik doaz (funtzioak, eragileak, aldagai lokalak eta erabaki-zuhaitz habiaratuak)

Zain-blokeak (| cond = ... eta | otherwise = ...) beti = baten atzetik agertzen dira, eta horrela funtzio-klausulak, eragile-klausulak, aldagai lokalen definizioak eta baldintzazko zuhaitz habiaratuak bateratzen dituzte:

Zainak dituzten funtzio- eta eragile-klausulak

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

Aldagai lokalen esleipena zainekin

| edozein =-ren ondoren baliozkoa denez, aldagai lokalak baldintzapean lot daitezke, if/else gako-hitzik edo funtzio laguntzailerik behar izan gabe:

discount =
  | is_vip      = 20
  | total > 100 = 10
  | otherwise   = 0

Lerro anitzeko bloke sekuentzialak, erabaki-zuhaitz sakonak eta ixtaile habiaratuak (|. / ||.)

Zain-adar bakoitza =-rekin amaitzen da; beraz, haren gorputza bloke sekuentzial bat ((none)), bloke paralelo bat (||) edo beste | zain-bloke habiaratu bat izan daiteke. Horri esker, nahi adina erabaki-zuhaitz (3-4 maila edo gehiago) idatz daitezke | cond = eta | otherwise = barruan.

  • Maila habiaratuak ixtea (|. eta ||.):
  • Maila bakarreko bloke sinpleetan edo funtzio edo zuhaitz baten amaieran, ez da ixteko tokenik behar.
  • | (edo ||) azpibloke habiaratu bat amaitzen denean eta exekuzioa kanpoko maila batera itzultzen denean, non azpian adar edo sententzia gehiago dauden, |.-k (|-rako) edo ||.-k (||-rako) maila habiaratu hori esplizituki ixten dute.
  • Baliozkoak dira bai azken lerroaren amaieran jartzea (| otherwise = val |., estilo trinko kanonikoa) bai hurrengo lerroan jartzea (|.):
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. Aldaezinak lehenespenez (x = ...) eta aldagai aldakor esplizituak (mut x = ...)

Bloke sekuentzialen barruan, aldagai lokalek 1. aukera jarraitzen dute:

  • Lotura aldaezina (x = <rhs>):
  • x aldagai lokal aldaezin berri bat deklaratzen du.
  • Esparru berean geroago x = ... berriro esleitzen saiatzea, aurretik mut x = ... deklaratu gabe, konpilazio-errorea da.
  • Deklarazio aldakorra (mut x = <rhs>) eta berresleipena (x = <new_rhs>):
  • mut x = <rhs>-k x aldakor gisa deklaratzen du uneko esparruan eta hasieratu egiten du.
  • Esparru bereko ondorengo x berresleipenak x = <new_rhs> idazten dira, besterik gabe (mut errepikatu gabe).
  • RMM2-n, x = <new_rhs> berresleitzean egitura berria handitzen da (+1) egitura zaharra txikitu aurretik (-1, kaskadan bere seme-alabetara hedatuz kontagailua 0-ra iristen bada).
fn :: accumulate Int => Int
      accumulate n =
        factor = 2
        mut acc = n * factor
        acc = acc + 10
        acc =
          | acc > 100 = 100
          | otherwise = acc
        acc

3. Literalen eta ADT eraikitzaileen eredu bat-etortzea

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

Paralelismo-primitibak (||)

Ridgunek exekuzio paralelo guztia ||-ren pean bateratzen du (where kendu egin da):

DAG lotura paralelo izendunak (|| 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
  • Adierazpen baten azpiko || expr -> var lerro guztiek Grafo Zuzendu Azikliko (DAG) paralelo bat osatzen dute.
  • Konpiladoreak || lerroen arteko aldagai-mendekotasunak aztertzen ditu (x-k eta y-k ez dute mendekotasunik eta paraleloan exekutatzen dira 1. olatuan; z x-ren eta y-ren menpe dago eta 2. olatuan exekutatzen da, x + y + z ebaluatu aurretik).
  • Tentsore-xerren idazketa paraleloak ere onartzen dira (|| expr -> out[i, j]).

Bloke paralelo zuzenak (|| expr)

op :: run Conf and Conf in parallel => Res, Res
      run a    and b    in parallel =
        || run_process a
        || run_process b

|| lerro bakoitza green thread paralelo bereizi gisa exekutatzen da, eta emaitzak tupla gisa itzultzen dira deklarazio-ordenan (edo elkartu egiten dira bloke sekuentzial baten barruan jartzen direnean).

Kanal tipatuak

Green thread-en arteko datu-korronteetarako eta ekoizle-kontsumitzaile topologietarako, Ridgunek MPMC kanal tipatuak (Channel) eskaintzen ditu:

Funtzio edo eragile integratuaSinaduraHelburua
new_channel() => ChannelKanal tipatu mugagabe bat sortzen du
new_bounded_channelInt => ChannelKanal mugatu bat sortzen du, backpressure edukierarekin
send_throughT Channel => ()Balio bat kanalera bidaltzen du (blokeatu egiten da mugatua eta beteta badago)
receive_fromChannel => TKanaleko hurrengo balioa jasotzen du
try_receive_fromChannel => OptionKontsulta blokeatu gabea, Some v edo None itzultzen duena

S/I primitibak

Ridgunek funtzio integratuak eskaintzen ditu terminaleko irteerarako.

echo

Nahi adina kate inprimatzen ditu terminalean, zuriunez bereizita, eta atzetik lerro-jauzia.

fn :: echo String... => ()

Azken parametro-motaren ... atzizkiak bariadiko gisa markatzen du: mota horretako argumentu bat edo gehiago onartzen ditu.

echo "hello"                            -- prints: hello
echo "hello" "world" "!"               -- prints: hello world !
echo "result: {result}"                 -- prints: result: 42

out

Kate bat terminalean zuzenean idazten duen eta itzultzen duen eragilea (kateatzea ahalbidetzen du).

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

Laburpena

FuntzioaMotaHelburua
echoString... => ()Kateak inprimatzen ditu zuriuneekin eta lerro-jauziarekin
outString => StringKatea inprimatzen du eta itzuli egiten du kateatzeko

Liburutegi estandarra

Liburutegiak import-ekin inportatzen dira:

import test

Unitate-testak (lib/test.rg)

Terminaleko irteerarako echo erabiltzen duen test-liburutegi sinple bat.

Baieztapenak:

EragileaHelburua
assert Int equals IntOsokoen berdintasuna
assert Real equals RealErrealen berdintasuna
assert String equals StringKateen berdintasuna
assert Bool is trueBoolearra egiazkoa da
assert Bool is falseBoolearra faltsua da

Testen egitura:

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

Terminaleko irteera:

═══ Arithmetic ═══
● sum adds correctly
  ✓ PASS
● factorial base case
  ✓ PASS

Elementu sintaktikoen laburpena

ElementuaSintaxiaHelburua
Iruzkina-- textLerro bakarreko iruzkina
Funtzio-deklarazioafn :: name types => returnFuntzio baten mota-sinadura deklaratzen du
Funtzio-definizioaname params = bodyFuntzio baten inplementazioa definitzen du
Eragile-deklarazioaop :: words types words => returnHizkuntza naturaleko eragile bat deklaratzen du
Eragile-definizioawords params words = bodyEragile baten inplementazioa definitzen du
Itzulera anitz=> type, typeItzulera-balio anitz deklaratzen ditu
Parametro bariadikoakType...Mota bateko argumentu bat edo gehiago onartzen ditu
Tentsore-literalaTensor [[1, 2], [3, 4]]N dimentsioko tentsore bat sortzen du
Tentsoreen indexatzeat[0, 1] edo t[0][1]Tentsorearen elementuak atzitzen ditu
Tentsoreen aldaketat[0, 1] = 5.0Tentsorearen elementuak lekuan bertan aldatzen ditu
Einstein uzkurduraA_ij @ B_jkPartekatutako indizeen gaineko tentsore-uzkurdura
Hadamard eragiketaA_ij * B_ijElementuz elementuko aritmetika, indizeak lerrokatuta
echoecho "a" "b" "c"Kateak terminalean inprimatzen ditu
out"text" outKatea terminalera ateratzen du
Lotura lokal aldaezinax = exprAldagai lokal aldaezin bat lotzen du (=-k (none), |, || onartzen ditu)
Lotura lokal aldakorramut x = exprAldagai lokal aldakor bat deklaratzen du (x = new_expr bidez berresleitzen da)
Zain-blokea| cond = expr= ondorengo baldintzazko zain-adarra (| habiaratua onartzen du)
DAG bloke paraleloa|| expr -> varAzpikalkulu paraleloak, DAG emaitza izendunekin
Bloke paralelo zuzena|| exprTupla bat itzultzen duen exekuzio paraleloa
Eragileak gainkargatzeaop :: type + type => typeLehendik dauden eragileak gainkargatzen ditu mota berrietarako
Bool literalakTrue, FalseBalio primitibo boolearrak
Eragile logikoakand, or, xor, notLetra xehezko hitzez osatutako eragile logikoak
Sarrera-puntuafn :: main => ()Programaren derrigorrezko sarrera-puntua

Iturburu-kodearen formatu kanonikoa (stable format eta editore-tresnak)

Estetikoa soilik, ez da konpiladorearen baldintza (FR-TOOL-001): Ridgunen analizatzaile lexikoari eta sintaktikoari ez die eragiten zutabeen lerrokatze horizontalak. Lerrokatu gabeko eta zutabetan lerrokatutako .rg iturburu-fitxategiak % 100 baliokideak dira ridgunc-entzat. Beheko arauek stable format-ek eta GNU Emacs ridgun-mode-k (C-c C-f) aplikatzen duten antolaera estetiko kanonikoa definitzen dute.

  1. Lerrokatze-taldea sinadura bakoitzeko (fn :: / op ::):
  • fn :: edo op :: deklarazio bakoitzak lerrokatze-talde bat hasten du, bere sinadura, eredu-klausulak eta || expr -> var loturak hartzen dituena, eta hurrengo goi-mailako deklarazioan amaitzen da (fn, op, type, import, global, context, shared, hardware, @).
  1. Ezkerreko aldeko tokenen zutabe-lerrokatzea ($C_0 = 6$):
  • fn :: eta op :: 6 karaktereko zabalera dute, beraz, sinaduraren ezkerreko aldeko $0$ tokena $C_0 = 6$ zutabean hasten da.
  • =>/-> aurreko $i \in [0, N-1]$ token-zirrikitu bakoitzak ("...", '...', [...] eta (...) token bakar gisa hartuta) $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))$ zabalera du eta $C_i = C_{i-1} + W_{i-1} + 1$ zutabean hasten da. 18 karaktere baino zabalagoak diren klausula-ereduak muturreko balio gisa hartzen dira: ez dute $W_i$ handitzen taldearen gainerakorako, eta beren lerroan gainezka egiten dute zuriune batekin.
  • Dagozkien definizio-klausulak $6$ zutabera ($C_0$) koskatzen dira, funtzioaren izena edo eragile-hitzak eta argumentu-eredu guztiak sinadurako zirrikituen azpian bertikalki lerrokatzeko.
  1. =>, = eta -> ikurren lerrokatze bertikala ($C_{\text{arrow}}$):
  • Izan bedi $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)$ eta $C_{\text{ret}} = C_{\text{arrow}} + \text{len}(\text{arrow}) + 1$.
  • Sinaduran, => $C_{\text{arrow}}$ zutabean jartzen da eta itzulera-mota $C_{\text{ret}}$ zutabean.
  • Lerro bakarreko klausuletan (<lhs> = <rhs>), lerro anitzeko bloke-klausuletan (<lhs> =) eta zain-goiburuko klausuletan (<lhs> = eta atzetik | cond = ...), = $C_{\text{arrow}}$ zutabean jartzen da (=>-ren azpian zuzenean lerrokatuta); lerro bakarreko klausuletan, <rhs> $C_{\text{ret}}$ zutabean hasten da.
  • DAG lotura paraleloetan (|| <lhs> -> <rhs>), || $8$ zutabean hasten da (6 + 2), -> $C_{\text{arrow}}$ zutabean jartzen da eta <rhs> $C_{\text{ret}}$ zutabean hasten da.
  • Ordezko forma trinkoa (> 4 parametro edo > 80 zutabe): Deklarazio batek 4 parametro-zirrikitu baino gehiago baditu edo haren sinadura lerrokatuak 80 karaktere gainditu baditzake, zutabeen betegarri horizontala desgaitu egiten da talde horretan eta tokenak zuriune bakarrez (" ") bereizten dira, klausulen 6 zutabeko koska mantenduta.
  1. Egitura-koska (2 zuriuneko desplazamendua):
  • Goi-mailako deklarazioak (fn, op, type, import, global, context, shared, hardware, @): 0 zutabea.
  • Funtzio- edo eragile-klausulak sinadura baten azpian: 6 zutabea.
  • Zainak (| cond = expr) eta hodi paraleloak (|| expr / || expr -> var): prev_indent + 2 (8 zutabea klausula baten barruan, edo indent + 2 lotura lokal baten edo zain habiaratu baten barruan).
  • =-rekin amaitzen den lerro baten atzeko bloke sekuentzialaren gorputz-lerroak: prev_indent + 2.

Goi-mailako bilduma-eragiketa sekuentzialak eta paraleloak (FR-COMP-001, FR-COMP-014)

Ridgunek bilduma-konbinatzaile sekuentzial estandarrak (map, filter, fold) eskaintzen ditu, || aurrizkidun nukleo anitzeko konbinatzaile paralelo esplizituekin batera (||map, ||filter). Bost konbinatzaileek onartzen dituzte bai ezkerretik eskuinerako hodi edo infix sintaxi idiomatikoa (xs map f -> filter g -> fold 0 h -> res) bai ohiko aurrizki-sintaxia (map f xs):

IntegratuaAurrizki- eta hodi-formakExekuzio-eredua
mapxs map f / xs -> map f / map f xsSekuentziala: f x ezkerretik eskuinera ebaluatzen du, zorrotz, deitzen duen harian.
`map`
filterxs filter p / xs -> filter p / filter p xsSekuentziala: p x predikatua ezkerretik eskuinera ebaluatzen du, zorrotz, deitzen duen harian.
`filter`
foldxs fold init f / xs -> fold init f / fold f init xsEzkerreko tolestura sekuentziala: acc = f acc x metatzen du ezkerretik eskuinera, init-etik hasita.

Hitzez hitzeko fitxategi-S/Ia, byte-korronteak eta POSIX integratuak (FR-VM-001, FR-VM-002)

  1. Hitzez hitzeko fitxategi- eta byte-korronte-S/Ia (FR-VM-001):
  • read_file : String => String-k fitxategien edukia hitzez hitz irakurtzen du (\r\n eta EOFeko lerro-jauzia dagoen ala ez zehazki mantenduta, eta konpiladorearen .rg import aurreprozesadorea datu-fitxategietan inoiz exekutatu gabe).
  • load_rg_source : String => String konpiladorearen tresna-kateak bakarrik erabiltzen du, .rg iturburu-fitxategiak import txertaketarekin kargatzean.
  • read_bytes : String => [Int] eta write_bytes : String [Int] => () byte-korronte bitar gordinak irakurri eta idazten dituzte (0..255, 0x00 NUL eta 0x80..0xFF barne).
  1. Fitxategi-sistemaren, prozesuen eta segurtasunaren POSIX integratuak (FR-VM-002):
  • Fitxategi-sistema: list_dir, file_lstat, sha256_file, sys_mkdir, sys_chmod.
  • Prozesuak eta ingurunea: sys_exec, sys_chdir, sys_getcwd, sys_getenv, sys_setenv, sys_exit.
  • Segurtasuna eta pribilegioen bereizketa: sys_getuid, sys_getgid, sys_username, sys_user_groups, sys_lookup_uid_gid, sys_setresgid, sys_setgroups, sys_setresuid, sys_execve, sys_read_pass.
  1. Plataforma anitzeko PAL S/Ia, polling-a, prozesu-primitibak, helburu-ADTak eta with timeout kuota deklaratiboak (FR-COMP-007):
  • Aurrez deklaratutako helburu-plataformaren ADTak:
  • type SysOs = Linux | MacOS | Windows (sys os => SysOs, hedagarria expand type SysOs = ... bidez)
  • type SysArch = X86_64 | Arm64 (sys arch => SysArch, hedagarria expand type SysArch = ... bidez)
  • Iraupen-unitateko literalak: Osoko literalek _ms (* 1), _s (* 1000) eta _min (* 60000) atzizkiak onartzen dituzte (adibidez, 500_ms, 5_s, 2_min), byte-unitateen atzizkiez gain (_KB, _MB, _GB).
  • 1. geruza — Plataforma anitzeko PAL primitibak .rglib sistema-liburutegietarako (posix.rglib / io.rglib):
  • sys os => SysOs eta sys arch => SysArch (konpilazio-garaiko helburuko sistema eragilearen eta arkitekturaren batura-ADTak)
  • sys open mode String String => Int (path, "r", "w", "a", "rw", "w+", "a+" modu eramangarria -> deskribatzailea/handle-a >= 0 edo -errno, sistema eragile helburu bakoitzerako itzulita)
  • sys open String Int Int => Int (path, Ridgun PAL flags normalizatuak (0 = irakurri, 1 = idatzi, 2 = rdwr, 64 = sortu, 512 = moztu, 1024 = gehitu amaieran, 2048 = nonblock), mode -> fd >= 0 edo -errno)
  • sys close Int => Int (fd -> 0 edo -errno)
  • sys read fd Int Int => String (fd, max_bytes -> fd-tik irakurritako katea)
  • sys write fd Int String => Int (fd, data -> idatzitako byteak edo -errno)
  • sys poll Int Int Int => Int (fd, Ridgun PAL events normalizatuak (1 = POLLIN/irakurri, 4 = POLLOUT/idatzi), timeout_ms -> > 0 revents prest dagoenean, 0 denbora-muga gainditzean, < 0 -errno denean; sys remaining ms erabiltzen du timeout_ms < 0 denean with timeout barruan)
  • sys terminate Int Bool => Int (pid, force -> prozesu-amaiera eramangarria, ordenatua edo behartua) eta sys kill Int Int => Int (pid, seinale normalizatua -> 0 edo -errno)
  • sys call Int Int Int Int Int Int Int => Int (nr, a1..a6 -> helburuko sistema eragilearen ABIko maila baxuko sistema-dei ihesbidea)
  • sys time ms => Int eta sys sleep ms Int => () (milisegundoko erloju monotonoa eta loa)
  • sys deadline ms => Int eta sys remaining ms => Int (denbora-muga lexiko aktiboaren epe-muga eta geratzen diren milisegundoak, edo -1 mugarik ez dagoenean)
  • 2. geruza — with timeout <duration> do exekuzio-kuota deklaratiboa:
  • with region 64_KB do-k byte-kuota lexiko bat ezartzen duen bezala, with timeout 500_ms do-k (edo with region 64_KB, timeout 500_ms do konbinazioak) exekuzio-epe-muga lexiko bat (sys_time_ms + duration_ms) ezartzen du uneko hariaren testuinguruan, eta aurreko epe-muga berrezartzen du blokeatik irtetean:
       with timeout 500_ms do
         rem = sys remaining ms
         rc  = sys poll fd 1 rem
         rc
  1. Liburutegi berrerabilgarrien konpilazioa (.rglib eta ELF64 .so) eta stable hedagarria (FR-COMP-006, FR-TOOL-003):
  • ridgunc build --lib <file.rg> -o <out.rglib>-ek eta ridgunc build --so <file.rg> -o <lib.so>-k (edo stable built lib / stable new --lib <name> komandoek) moduluak konpilatzen dituzte fn :: main => () behar izan gabe, eta esportatutako funtzio, eragile eta mota guztiak gordetzen dituzte.
  • stable-k fn :: task <words...> => String komando pertsonalizatuak eta fn :: plugins => [String] hedapenak (plugins/*.rg, .stable/plugins/*.rg) aurkitzen ditu, eta stable tasks eta stable plugins bidez zerrendatzen dira.

Ridgunen memoria-kudeaketa (RMM): RMM1 (CMM) eta RMM2 (FR-COMP-002)

Ridgunek heap memoria (String, [a], (a, b), ADTak, Tensor) modu deterministan kudeatzen du, arakatze bidezko zabor-biltzailerik (GC) gabe, Ridgun Memory Management (RMM) bidez:

  1. RMM1 politika — Memoria Kudeaketa Konpilatua (CMM Lineala eta Baldintzazkoa):
  • Kontrol-fluxua eta deitutako funtzioak konpilazio-garaian estatikoki ezagunak direnean aplikatzen da, habiaratu gabeko loturen gainean:
  • CMM Lineala (rg_cmm_move / rg_cmm_drop): Konpiladoreak aldagai lokal bakoitzaren azken erabileraren sententzia zehatza zehazten du konpilazio-garaian, itzulitako aldagaiak mugitzen ditu (rg_cmm_move(&mut lv_x)) eta baldintzarik gabeko askapena igortzen du (rg_cmm_drop(&mut lv_x)) aldagaiaren azken erabileraren ondoren berehala, may-alias biziriak geratzen ez direnean.
  • CMM Baldintzazkoa (rg_cmm_drop_unless / ptr(a) != ptr(c)): Adarkatze estatikoko dei batek (c = choose_list cond a b) hautagai diren sarreretako bat itzultzen duenean eta hautagai bat edo gehiago c-rekin batera bizirik geratzen direnean, konpiladoreak arbasoen may-alias taula (RCmmAlias) eraikitzen du eta PUZ ziklo 1eko erakusle-identitatearen zain bat igortzen du aldagai bakoitzaren azken erabilera estatikoko sententzian:
       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)
  1. RMM2 politika — Esleipen bidezko kontaketa eta egituren kaskada (politika aktiboa):
  • Memoria-kudeaketa bateratzen du funtzioetan, adarkatutako itzuleretan (choose_list), edukiontzi habiaratuetan (xs = [a, b, ..., z], xs[3] = a), aldagai lokal aldakorretan (mut x = ...) eta hari anitzeko exekuzioan:
  • Eskalar primitiboak (Int, Real, Bool, ()): Ez dira inoiz zenbatzen; balioz kopiatzen dira pilan edo erregistroetan.
  • Funtzioaren sarrerako argumentuak (pats): Ez dira inoiz ukitzen (+0 sartzean, -0 irtetean).
  • Barneko aldagai lokalak (x = ... / mut x = ...): +1 jasotzen dute esleipenean (x = expr, xs[3] = a). Berresleipen aldakorrean (x = new_expr), new_expr-ek +1 jasotzen du x zaharrak -1 jaso aurretik.
  • Funtzioaren amaiera / esparrutik irtetea:
  • Itzultzen ez diren barneko aldagai lokalek -1 jasotzen dute lehenik: rc == 0 bada, bloke gurasoa askatzen da eta -1 kaskadan hedatzen dio, banan-banan, bere seme-alaba zuzen bakoitzari (rc-a 0-ra iristen zaion edozein seme-alaba errekurtsiboki askatuz).
  • Itzultzen den barneko aldagai lokal batek (return a) -1 jasotzen du (edo rg_cmm_move bidez mugitzen da), eta bidean rc-a 0 izan arren, salbuetsi egiten da, deitzailearen esleipenak (c = make_pair ()) +1 gehi dezan (0 + 1 = 1). Sarrerako argumentu bat itzultzen denean (choose_list cond a b), funtzioaren barruan ukitu gabe egon da (rc = 1), beraz deitzailearen c = choose_list cond a b-k +1 gehitzen du (1 + 1 = 2, a-ren eta c-ren artean partekatuta).
  1. RMM3 politika (Erreserbatua):
  • Etorkizuneko optimizazio estatiko oldarkor baterako erreserbatua.
  • Ikus docs/etc/cmm_architecture.md (Ridgun biltegian) RMM1 eta RMM2-ren espezifikazio osorako.