Repository navigation
Parte V Riferimento
Da SPEC-CORE.md §4:
program = { sep } { stmt sep { sep } } ;
stmt = funcdef | "return" [ expr ] | "break" | "continue" | expr ;
funcdef = "function" NAME "(" [ NAME { "," NAME } ] ")" block "end"
| NAME "(" [ NAME { "," NAME } ] ")" "=" expr ;
expr = assegnamento ;
assegnamento = NAME ( "=" | "+=" | "-=" | "*=" ) expr | ternario ;
ternario = or_expr [ "?" expr ":" expr ] ;
or_expr = and_expr { "||" and_expr } ;
and_expr = cmp_expr { "&&" cmp_expr } ;
cmp_expr = sum_expr { ( "==" | "!=" | "<" | "<=" | ">" | ">=" ) sum_expr } ;
sum_expr = mul_expr { ( "+" | "-" ) mul_expr } ;
mul_expr = pow_expr { ( "*" | "%" ) pow_expr } ;
pow_expr = unary { "^" unary } ; (* destra *)
unary = ( "-" | "!" ) unary | postfix ;
postfix = primary { "(" args ")" | "[" expr "]" } ;
primary = INT | STRING | SYMBOL | "true" | "false" | "nothing" | NAME
| "(" expr ")"
| "[" [ expr { "," expr } ] "]"
| "(" NAME { "," NAME } ")" "->" expr
| "if" expr block { "elseif" expr block } [ "else" block ] "end"
| "while" expr block "end"
| "let" [ NAME "=" expr { "," NAME "=" expr } ] block "end"
| "begin" block "end"
| "function" "(" [ NAME { "," NAME } ] ")" block "end" ;
block = { stmt sep { sep } } ; (* fino a end/else/elseif *)La grammatica Full (Pratt, 12 livelli) è in SPEC.md §2.
Triad-Core (eseguibile oggi):
assegnamento: x = e x += e x -= e x *= e xs[i] = e
funzione: f(a, b) = e
function f(a, b) ... end (anche !io, ignorato)
anonima: x -> e (a, b) -> e function (a) ... end
condizione: if c ... elseif c ... else ... end c ? a : b
ciclo: while c ... end break continue
blocchi: let a = 1, b = 2 ... end begin ... end
uscita: return e
liste: [1, 2] xs[i] (da 1) length(xs) push!(xs, v)
stringhe: "a" * "b" length(s) string(x)
conversioni: Int("42") Symbol("s") typeof(x)
I/O: print(...) println(...) ARGS
bootstrap: readfile(p) strlen(s) strbyte(s, i) strsub(s, a, b) exit(n)
Triad-Full (specifica):
struttura: struct Nome; x::T; y::T; end
funzione: function f(a::T)::R !eff ... end
fatto: fact p(:a, :b)
regola: rule p(?x, ?y) :- q(?x), r(?y)
query: solve p(?x) limit N depth D steps S trace
destruttura: (a, b) = [1, 2] for (k, v) in [[1,2],[3,4]] ... end
ciclo for: for v in it ... end 1:n xs[2:end] [e for x in xs if c]
try/catch: try b catch e h end / try b end
contratto: requires c / ensures c
budget: with budget(steps = N) ... end
traccia: with trace ... end / solve p trace
effetto: function f() !io ... end
macro: macro m(a) ... end / @m(e)
quote: :(espr) / quote ... end / $espr
eval: eval(codice)
Core (oggi):
| sintomo | causa probabile | soluzione |
|---|---|---|
parse error: expected RPAREN |
1.5, /, () -> … o altra sintassi Full |
resta nel sottoinsieme Core (§4) |
"x = $x" stampato letteralmente |
l'interpolazione è solo Full | "x = " * string(x) |
error: if cond |
condizione non Bool
|
usa un confronto (x != 0) |
error: < type error su a < b < c
|
confronti concatenati | a < b && b < c |
| una funzione non aggiorna un globale | le funzioni nominate assegnano in locale | restituisci il valore o usa una lista (§16.4) |
error: undefined variable f |
funzione chiamata prima della definizione | definiscila più in alto |
FAIL … (golden mancante …) |
checkout senza expected.out
|
git pull; controlla .gitignore
|
| il seed esce con 1 senza messaggi | funzionalità non supportata dal seed | prova con l'interprete JS; vedi §15 |
| il seed Windows viene bloccato | falso positivo dell'antivirus | escludi seed\windows-x86_64
|
Full (specifica):
| sintomo | causa probabile | soluzione |
|---|---|---|
Err(:syntax) "atteso fine istruzione" |
manca end o un separatore |
aggiungi end o ;
|
Err(:undef) |
nome non definito | definiscilo, o usa :nome per un simbolo |
Err(:method) / Err(:ambiguous)
|
nessun metodo / più metodi ugualmente specifici | aggiungi o ridisegna le firme |
Err(:bounds) in destrutturazione |
arità diversa dal pattern | liste di lunghezza esatta |
Err(:effect) |
!io/!state chiamata da funzione pura |
dichiara l'effetto nel chiamante |
Err(:budget) in solve
|
troppi passi | aumenta steps o usa limit/depth
|
Strumenti Full previsti: triad --tree file, sexpr(codice), parse/unparse,
with trace … end, solve … trace, try … end con .kind/.msg/.data.
-
S0 / seed: interprete Triad-Core in codice macchina (
seed/). -
S1: interprete di tutto Triad scritto in Triad-Core (
selfhost/). -
S2 / S3 / S4: compilatore nativo, self-hosting, runtime completo (vedi
BOOTSTRAP.md). - E0 / E1 / …: stadi del port Linux del seed (milestone M7).
- Triad-Core / Triad-Full: i due profili di conformità.
-
Interprete JS:
seed/dev/triad_core.cjs, riferimento Core per sviluppo e CI. -
Golden: output atteso committato (
expected.out,expected.code). -
Primitivi di bootstrap:
readfile,strlen,strbyte,strsub,exit(solo Core). -
Lista taggata: record Core del tipo
[:Tag, campo1, …]. -
Node: l'unico tipo di albero di Triad Full (
head,args): codice e dati coincidono. -
Solution:
{nome = valore, …}restituita dasolve;s.nomeos[:nome]. -
Err: errore come dato (
kind,msg,data). -
Traced:
(result, trace)restituito dawith trace/solve … trace. -
Occurs-check: l'unificazione rifiuta
?x = f(?x). - Multiple dispatch: scelta del metodo più specifico tra gli applicabili.
-
Effetti dichiarati:
!io,!statenella firma; controllo dinamico. -
Contratti:
requires(pre) /ensures(post, conresult). -
Budget:
with budget(steps = N); l'esaurimento èErr(:budget). -
Destrutturazione:
(a, b) = lista,for (k, v) in lista_di_liste.
Stato (dettagli in STATUS.md):
- Core: 37/37 casi con l'interprete JS; 33 casi sul seed Windows in CI.
- Full: 12 casi golden congelati, passa solo
errore. - S1: prototipi in
selfhost/, smoke test in CI; non ancora conformance. - S2–S4: non iniziati. Seed Linux: E0.
- CLI
triad: solo esecuzione di file (REPL e opzioni di SPEC §14 da fare).
Limiti dello standard (SPEC §15): argomenti con nome (salvo budget(steps = …)), struct
mutabili, tipi astratti utente e parametrici, macro senza parentesi, quote annidate a più
livelli, cut di Prolog non sono previsti; il controllo degli effetti è dinamico.
Fix storici applicati alla vecchia implementazione Julia; il comportamento "dopo" è quello richiesto da SPEC.md per ogni implementazione:
| # | fix | dopo |
|---|---|---|
| 1 | round-trip del range |
unparse(1:n) produce "1:n" (senza spazi) |
| 2 |
unparse di :destructure/:dfor
|
hanno rami propri e fanno round-trip |
| 3 | xs[end] = v |
end è legato anche in scrittura: xs[end] = 7 funziona |
| 4 | escape sconosciuti | solo \n \t \" \\ \$; altri → Err(:syntax) con riga e colonna |
| 5 | commenti #= annidati |
la profondità è contata; #= non chiuso → errore incomplete
|
| 6 | lambda con parametri tipati |
function (x::Int) x end controlla i tipi: f(2.0) → Err(:type)
|
Serve Julia? No. L'implementazione Julia è stata rimossa; Triad gira sul seed in codice macchina (Windows) o sull'interprete JS di sviluppo.
Perché i miei esempi con struct o fact non girano? Sono Triad-Full: il runtime attuale
esegue solo Triad-Core. Vedi la tabella in testa alla wiki.
.td o .triad? .triad è canonica; .td è accettata come alias (ed è anche
l'estensione di LLVM TableGen, quindi per il riconoscimento esterno conviene .triad).
Come verifico che un programma sia Core "puro"? Eseguilo con l'interprete JS e controlla di non usare primitivi di bootstrap se deve valere anche per Full; per i casi normativi aggiungilo alla conformance Core.
Perché selfhost/*.td falliscono con l'interprete JS? Usano get(xs, i), helper non
standard del seed Windows; vanno eseguiti con seed.exe.
Dove propongo una modifica al linguaggio? Nello standard (SPEC.md/SPEC-CORE.md) con
voce in CHANGELOG.md e casi di conformance; poi nelle implementazioni.
Wiki mantenuta insieme allo standard: quando cambia SPEC.md, SPEC-CORE.md, il runtime o gli
strumenti, aggiorna il capitolo corrispondente. Gli esempi Core marcati Output: si
verificano eseguendoli con node seed/dev/triad_core.cjs.
Parte prima
Parte seconda 4. Le parole del linguaggio 5. Valori e tipi 6. Espressioni, operatori e variabili 7. Decidere e ripetere 8. Funzioni e ricorsione 9. Lambda, chiusure e visibilità dei nomi 10. Liste e dati strutturati 11. Stringhe, simboli e byte 12. Quando le cose vanno storte 13. Progetto: un piccolo interprete
Parte terza 14. Tipi, struct e multiple dispatch 15. Programmazione logica 16. Codice come dato e macro 17. Garanzie, costrutti Full e interfaccia
Parte quarta 18. Anatomia del progetto e contratto di conformità 19. L'interprete di riferimento 20. Il seed in codice macchina 21. Verso il self-hosting 22. Gli strumenti di sviluppo
Appendici
- Riferimento dei builtin Core
- Catalogo conformance Core
- Catalogo conformance Full
- Sorgenti degli esempi
- Sorgenti self-hosted
- Documenti di riferimento
- Indice analitico
Manuale di consultazione