Vai al contenuto
Ridgun
Italiano

23 Il Libro di Ridgun

La lib fmt — Formattatore Tabulare Canonico 2D ed Evidenziatore di Sintassi in 9 Formati

23.1. Perché esiste la lib fmt? (Il problema reale e la filosofia Ridgun)

«Perché ho bisogno di una lib fmt scritta da zero in Ridgun puro invece di collegare una libreria C tradizionale?»

Questa è la prima domanda che si pone qualsiasi ingegnere di sistema arrivando a fmt. E la risposta riassume l'intera filosofia di ridgun-libs:

Siamo sinceri: la bellezza del codice Ridgun risiede nelle sue colonne tabulari perfettamente allineate (::, =, |, ->, --), ma allineare gli spazi a mano o esportare codice colorato per terminale, HTML e LaTeX senza uno strumento dedicato è tedioso.

La lib fmt è il motore ufficiale di formattazione tabulare 2D ed evidenziazione lessicale di Ridgun: allinea firme fn ::, equazioni, guardie | e commenti --, ed esporta in 9 formati di output (FmtPlain, FmtTty, FmtTrueColor, FmtHtmlInline, FmtHtmlCss, FmtMarkdown, FmtPango, FmtLatex, FmtRtf).

In un ecosistema tradizionale, risolvere i compiti del dominio FMT comporta trascinare dipendenze esterne in C, gestire puntatori grezzi, conversioni opache di tipo, eccezioni non verificate o pause imprevedibili del garbage collector. In Ridgun, la lib fmt (src/main/ridgun/lib/fmt.rg) affronta il problema con quattro principi non negoziabili:

  1. Dichiara import fmt (o import fmt as alias) all'inizio del file: ogni lib definisce il proprio spazio dei nomi module :: fmt e in modalità --strict le funzioni multi-parola si invocano sempre con spazi naturali.
  2. Concatena le tue pipeline da sinistra a destra con ->: scrivi input passo uno -> passo due -> risultato, usa le maschere (+ _ _ +) per destrutturare le sequenze e ometti _ = nelle istruzioni sequenziali (o scarta il valore con -> ()).
  3. Ricorsione di coda con TCO (Tail-Call Optimization): tutte le scansioni interne di fmt vengono compilate in cicli nativi in spazio di stack $O(1)$.
  4. Memoria deterministica (RMM1 / RMM2): ogni struttura intermedia viene liberata nell'istante esatto in cui termina la sua ultima lettura, senza Garbage Collector.

23.2. Artefatti nativi, importazione e catalogo completo dell'API di fmt

In ridgun-libs, fmt è una lib di prima classe situata in src/main/ridgun/lib/fmt.rg (dominio FMT). Compilando con stable bundle, viene impacchettata in tre artefatti nativi:

ArtefattoPercorsoScopo
Bundle Ridguntarget/bundles/fmt.rglibDistribuzione e importazione diretta con import fmt
File compilatotarget/fmt.rgcArtefatto intermedio verificato da ridgunc
Oggetto condiviso ELF64target/libfmt.soLibreria dinamica nativa senza dipendenze C né libc

Ogni lib dichiara il proprio spazio dei nomi con module :: fmt: basta scrivere import fmt (o import fmt as alias) nell'intestazione e invocare le sue funzioni con spazi naturali (mia funzione x) e pipeline -> (x mia funzione -> risultato).

23.2.1. Riepilogo delle famiglie funzionali di fmt

Firma / Funzione / TipoCosa fa e quando usarla
fmt source / fmt source withFormatta codice sorgente Ridgun usando l'allineamento tabulare 2D canonico
fmt checkRestituisce True se il codice rispetta già il formato tabulare canonico di fmt source
fmt render / fmt render withFormatta e colora il codice verso uno qualsiasi dei 9 formati FmtTarget
fmt tokenize lineTokenizza una riga in TokKeyword, TokType, TokOperator, TokString, TokNumber, TokComment

23.2.2. Catalogo esaustivo dei tipi e delle firme in src/main/ridgun/lib/fmt.rg

Di seguito trovi l'inventario completo dei tipi algebrici (type), degli operatori (op ::) e delle firme di funzione (fn ::) definiti in src/main/ridgun/lib/fmt.rg (7 tipi, 0 operatori e 166 funzioni):

Tipi algebrici e record (type) di fmt:

type FmtTarget = FmtPlain | FmtTty | FmtTrueColor | FmtHtmlInline | FmtHtmlCss | FmtMarkdown | FmtPango | FmtLatex | FmtRtf
type FmtTheme = FmtThemeNone | FmtThemeDark | FmtThemeLight
type FmtConfig = indent_width: Int, max_align_params: Int, max_line_width: Int, is_aligned: Bool, target_format: FmtTarget, color_theme: FmtTheme
type FmtToken = FmtTok String Int
type FmtSig = NoSig | SigInfo String [String] String String [Int] Int Int
type FmtClause = NoClause | ClauseInfo [String] Bool String
type FmtWhereBind = NoWhereBind | WhereBindInfo String String
#Funzione / Firma (fn ::)Tipo di Ritorno
1fn :: default fmt configFmtConfig
2fn :: fmt config Int Int Int Bool FmtTarget FmtThemeFmtConfig
3fn :: fmt max Int IntInt
4fn :: fmt str list len [String]Int
5fn :: fmt str head [String]String
6fn :: fmt int at [Int] IntInt
7fn :: fmt spaces IntString
8fn :: fmt is hspace IntBool
9fn :: fmt leading indent loop String Int IntInt
10fn :: fmt leading indent StringInt
11fn :: fmt trim left loop String Int IntString
12fn :: fmt trim left StringString
13fn :: fmt trim right loop String IntString
14fn :: fmt trim right StringString
15fn :: fmt trim StringString
16fn :: fmt split raw lines loop String Int Int Int Int [String][String]
17fn :: fmt split raw lines String[String]
18fn :: fmt join lines [String]String
19fn :: fmt skip quoted String Int Int IntInt
20fn :: fmt find comment col String Int IntInt
21fn :: fmt strip comment StringString
22fn :: fmt strip comment at String IntString
23fn :: fmt extract comment StringString
24fn :: fmt extract comment at String IntString
25fn :: fmt skip hspace String Int IntInt
26fn :: fmt scan group end String Int Int IntInt
27fn :: fmt scan word end String Int Int IntInt
28fn :: fmt scan token end String Int Int IntInt
29fn :: fmt scan tokens loop String Int Int [FmtToken][FmtToken]
30fn :: fmt scan tokens at String Int Int [FmtToken][FmtToken]
31fn :: fmt scan tokens at step String Int Int [FmtToken] Int[FmtToken]
32fn :: fmt scan tokens String[FmtToken]
33fn :: fmt split sig arrow [FmtToken] [String](Bool, [String], String, Int)
34fn :: fmt is sig type tok StringBool
35fn :: fmt all type toks [String]Bool
36fn :: fmt is bare fn lhs [String]Bool
37fn :: fmt infer bare kind [String]String
38fn :: fmt parse sig line StringFmtSig
39fn :: fmt parse sig tokens Int String String [FmtToken]FmtSig
40fn :: fmt finish bare sig parse String String (Bool, [String], String, Int)FmtSig
41fn :: fmt finish sig parse String String String (Bool, [String], String, Int)FmtSig
42fn :: fmt append comment String StringString
43fn :: fmt has fat arrow [FmtToken]Bool
44fn :: fmt is top decl line StringBool
45fn :: fmt is top decl toks Int String [FmtToken]Bool
46fn :: fmt op tokens match [String] [String]Bool
47fn :: fmt is bare kind StringBool
48fn :: fmt sig base col StringInt
49fn :: fmt sig base col from FmtSigInt
50fn :: fmt clause matches sig String [String] [String]Bool
51fn :: fmt split clause eq [FmtToken] [String]([String], Bool, Int)
52fn :: fmt next nonblank is guard [String]Bool
53fn :: fmt check guard line String [String]Bool
54fn :: fmt parse clause line FmtSig String BoolFmtClause
55fn :: fmt parse clause clean String [String] String String String BoolFmtClause
56fn :: fmt check clause split String [String] String Bool ([String], Bool, Int)FmtClause
57fn :: fmt build clause info String [String] Bool IntFmtClause
58fn :: fmt find where arrow [FmtToken]Int
59fn :: fmt parse where line String BoolFmtWhereBind
60fn :: fmt parse where clean String String StringFmtWhereBind
61fn :: fmt build where bind String String IntFmtWhereBind
62fn :: fmt check where nonempty String StringFmtWhereBind
63fn :: fmt map str lens [String][Int]
64fn :: fmt slot width Int IntInt
65fn :: fmt max widths [Int] [String][Int]
66fn :: fmt build col starts [Int] Int[Int]
67fn :: fmt end col [Int] IntInt
68fn :: fmt scan group widths FmtSig [String] [Int] Int Bool Int([Int], Int)
69fn :: fmt scan group step FmtSig String [String] [Int] Int Bool Int FmtClause FmtWhereBind([Int], Int)
70fn :: fmt compute group geometry FmtSig [String] FmtConfigFmtSig
71fn :: fmt count op params [String]Int
72fn :: fmt count sig params String [String]Int
73fn :: fmt finish group geometry String [String] String String ([Int], Int) FmtConfigFmtSig
74fn :: fmt select group geometry String [String] String String [Int] Int Int Int Int FmtConfigFmtSig
75fn :: fmt pad lhs tokens [String] [Int] Int StringString
76fn :: fmt sig prefix String StringString
77fn :: fmt format sig line FmtSigString
78fn :: fmt format clause line FmtSig [String] Bool StringString
79fn :: fmt finish clause rhs String Bool String Int IntString
80fn :: fmt format where line FmtSig String String IntString
81fn :: fmt line opens block StringBool
82fn :: fmt check block opener String IntBool
83fn :: fmt line closes block StringBool
84fn :: fmt guard indent Int Int Int String IntInt
85fn :: fmt guard indent clean Int Int Int String String IntInt
86fn :: fmt format group body FmtSig [String] Int String Bool FmtConfig[String]
87fn :: fmt format group line FmtSig String String String Int [String] Int String Bool FmtConfig FmtClause FmtWhereBind[String]
88fn :: fmt format guard line FmtSig String Int [String] Int String FmtConfig Int[String]
89fn :: fmt next body indent Int String IntInt
90fn :: fmt next body indent clean Int String String IntInt
91fn :: fmt indent body line Int String String IntString
92fn :: fmt take group lines [String] [String]([String], [String])
93fn :: fmt format top lines [String] Int String FmtConfig[String]
94fn :: fmt dispatch top line String [String] Int String FmtConfig FmtSig[String]
95fn :: fmt run sig group FmtSig ([String], [String]) FmtConfig[String]
96fn :: fmt format non sig top String [String] Int String FmtConfig[String]
97fn :: fmt is digit IntBool
98fn :: fmt is upper IntBool
99fn :: fmt is lower IntBool
100fn :: fmt is ident char IntBool
101fn :: fmt is keyword StringBool
102fn :: fmt is logic op StringBool
103fn :: fmt is bool lit StringBool
104fn :: fmt classify word String BoolString
105fn :: fmt escape html loop String Int Int StringString
106fn :: fmt escape html StringString
107fn :: fmt escape latex loop String Int Int StringString
108fn :: fmt escape latex StringString
109fn :: fmt escape rtf loop String Int Int StringString
110fn :: fmt escape rtf StringString
111fn :: fmt escape for target String FmtTargetString
112fn :: fmt cat css class StringString
113fn :: fmt cat ansi16 StringString
114fn :: fmt cat rgb String FmtThemeString
115fn :: fmt cat hex String FmtThemeString
116fn :: fmt cat is bold StringBool
117fn :: fmt cat rtf idx StringString
118fn :: fmt span css String StringString
119fn :: fmt span tty String StringString
120fn :: fmt span truecolor String String BoolString
121fn :: fmt span html inline String String BoolString
122fn :: fmt span pango String String BoolString
123fn :: fmt span latex String String BoolString
124fn :: fmt span rtf String String BoolString
125fn :: fmt render span String String FmtTarget FmtThemeString
126fn :: fmt scan ident end String Int IntInt
127fn :: fmt scan space end String Int IntInt
128fn :: fmt find close brace String Int IntInt
129fn :: fmt render nonempty String String FmtTarget FmtThemeString
130fn :: fmt highlight dquote brace String Int Int Int Int FmtTarget FmtTheme StringString
131fn :: fmt highlight dquote loop String Int Int Int FmtTarget FmtTheme StringString
132fn :: fmt multi op at String Int IntString
133fn :: fmt is single op IntBool
134fn :: fmt comment cat StringString
135fn :: fmt hl space step String Int Int Bool FmtTarget FmtTheme String IntString
136fn :: fmt hl dquote step String Int Int FmtTarget FmtTheme String IntString
137fn :: fmt hl squote step String Int Int FmtTarget FmtTheme String IntString
138fn :: fmt hl pragma step String Int Int FmtTarget FmtTheme String IntString
139fn :: fmt hl mop step String Int Int FmtTarget FmtTheme String StringString
140fn :: fmt hl ident step String Int Int Bool FmtTarget FmtTheme String IntString
141fn :: fmt highlight line loop String Int Int Bool FmtTarget FmtTheme StringString
142fn :: fmt line starts clause StringBool
143fn :: fmt map tok strs [FmtToken][String]
144fn :: fmt highlight line String FmtTarget FmtThemeString
145fn :: fmt highlight lines [String] FmtTarget FmtTheme[String]
146fn :: fmt join rtf lines [String]String
147fn :: fmt html pre open FmtThemeString
148fn :: fmt rtf colortbl FmtThemeString
149fn :: fmt wrap target doc [String] FmtTarget FmtThemeString
150fn :: fmt html stylesheet FmtThemeString
151fn :: fmt source with config String FmtConfigString
152fn :: format ridgun source StringString
153fn :: fmt to tty with theme String FmtThemeString
154fn :: fmt to tty StringString
155fn :: fmt to truecolor with theme String FmtThemeString
156fn :: fmt to truecolor StringString
157fn :: fmt to html with theme String FmtThemeString
158fn :: fmt to html StringString
159fn :: fmt to html css StringString
160fn :: fmt to markdown StringString
161fn :: fmt to pango with theme String FmtThemeString
162fn :: fmt to pango StringString
163fn :: fmt to latex with theme String FmtThemeString
164fn :: fmt to latex StringString
165fn :: fmt to rtf with theme String FmtThemeString
166fn :: fmt to rtf StringString

23.3. Esplorare fmt a fondo: Esempi passo dopo passo di ogni funzionalità

Non basta consultare la tabella delle firme: esploreremo ciascuna delle funzionalità della lib fmt tramite esempi progressivi ed eseguibili in Ridgun. Inizieremo con due ricette tabulari di uso quotidiano e poi percorreremo nel dettaglio tutti gli scenari funzionali, le trasformazioni e i casi limite verificati in src/test/ridgun/test fmt.rg.

23.3.1. Esempio 1: Flusso principale in stile tabulare con fmt

Osserva come in Ridgun i segni = e i passaggi di trasformazione con fmt risultino allineati come una tabella pulita, senza variabili mutabili superflue né effetti collaterali nascosti:

import fmt

fn :: formatear y verificar String => String Bool
      formatear y verificar codigo =
        codigo fmt ridgun -> limpio
        limpio fmt check ridgun -> es_ok
        (limpio, es_ok)

23.3.2. Esempio 2: Composizione sicura e gestione dei casi limite

Ogni funzione della lib fmt è progettata per comporsi con le guardie booleane | e con il resto delle 34 lib di ridgun-libs:

import fmt

fn :: exportar bloque html String => String
      exportar bloque html codigo =
        fmt highlight ridgun codigo FmtHtmlCss

23.3.3. Esempio 3: Allineamento tabulare canonico (fmt ridgun, fmt ridgun with) di firme =>, clausole =, catene -> e commenti --

In questo esempio pratico esploriamo in modo esaustivo come si comporta fmt in questo blocco funzionale, inclusi input standard, combinazioni di parametri e valori di frontiera:

fn :: test fmt canonical alignment and config => ()
      test fmt canonical alignment and config =
        nl = char from code 10
        raw_src = "fn :: add Int Int => Int" + nl + "add x y = x + y" + nl + "add 0 y_long = y_long" + nl
        expected_2d = "fn :: add Int Int    => Int" + nl + "      add x   y      =  x + y" + nl + "      add 0   y_long =  y_long" + nl
        out_2d = format ridgun source raw_src
        assert str eq out_2d expected_2d "AC1: canonical 2D tabular alignment"

        -- Unaligned config (`is_aligned = False`) uses single-space separation
        cfg_unaligned = fmt config 2 4 80 False FmtPlain FmtThemeNone
        out_unaligned = fmt source with config raw_src cfg_unaligned
        expected_unaligned = "fn :: add Int Int => Int" + nl + "      add x y = x + y" + nl + "      add 0 y_long = y_long" + nl
        assert str eq out_unaligned expected_unaligned "AC1: unaligned FmtConfig"

        -- Guard and `where` alignment with custom indent_width = 4
        guard_src = "fn :: clamp Int => Int" + nl + "clamp x" + nl + "| x < 0 = 0" + nl + "| otherwise = x" + nl + "where" + nl + "lo -> 0" + nl
        cfg_ind4 = fmt config 4 4 80 True FmtPlain FmtThemeNone
        out_ind4 = fmt source with config guard_src cfg_ind4
        assert true (str contains out_ind4 "          | x < 0 = 0") "AC1: custom indent_width = 4 guard indentation"
        assert true (str contains out_ind4 "              lo -> 0") "AC1: custom indent_width = 4 where binding alignment"
        ()

23.3.4. Esempio 4: Evidenziazione lessicale ANSI a 16 colori e TrueColor a 24 bit con rilevamento automatico di TTY e NO_COLOR

In questo esempio pratico esploriamo in modo esaustivo come si comporta fmt in questo blocco funzionale, inclusi input standard, combinazioni di parametri e valori di frontiera:

fn :: test fmt terminal highlighting tty and truecolor => ()
      test fmt terminal highlighting tty and truecolor =
        nl = char from code 10
        esc = char from code 27
        interp_tok = (char from code 123) + "name" + (char from code 125)
        sample = "-- @implements FR-FMT-001" + nl + "-- comment line" + nl + "fn :: greet String => String" + nl + "greet name = \"Hello " + interp_tok + "\" + (int_to_str 0x2A)" + nl

        tty_dark = fmt to tty sample
        assert true (str contains tty_dark (esc + "[1;32m-- @implements FR-FMT-001" + esc + "[0m")) "AC2: TTY pragma highlight"
        assert true (str contains tty_dark (esc + "[90m-- comment line" + esc + "[0m")) "AC2: TTY comment highlight"
        assert true (str contains tty_dark (esc + "[1;35mfn" + esc + "[0m")) "AC2: TTY keyword highlight"
        assert true (str contains tty_dark (esc + "[1;34mgreet" + esc + "[0m")) "AC2: TTY function name highlight"
        assert true (str contains tty_dark (esc + "[33mString" + esc + "[0m")) "AC2: TTY type highlight"
        assert true (str contains tty_dark (esc + "[36m" + interp_tok + esc + "[0m")) "AC2: TTY string interpolation highlight"
        assert true (str contains tty_dark (esc + "[36m0x2A" + esc + "[0m")) "AC2: TTY hex number highlight"

        tty_none = fmt to tty with theme sample FmtThemeNone
        assert false (str contains tty_none esc) "AC2: FmtThemeNone emits no ANSI escape codes"

        tc_dark = fmt to truecolor sample
        assert true (str contains tc_dark (esc + "[1;38;2;198;120;221mfn" + esc + "[0m")) "AC2: TrueColor dark keyword RGB"
        assert true (str contains tc_dark (esc + "[1;38;2;97;175;239mgreet" + esc + "[0m")) "AC2: TrueColor dark function RGB"

        tc_light = fmt to truecolor with theme sample FmtThemeLight
        assert true (str contains tc_light (esc + "[1;38;2;166;38;164mfn" + esc + "[0m")) "AC2: TrueColor light keyword RGB"
        ()

23.3.5. Esempio 5: Esportazione di documenti evidenziati in HTML5 (<pre><code>), Pango Markup, LaTeX, RTF e SVG vettoriale

In questo esempio pratico esploriamo in modo esaustivo come si comporta fmt in questo blocco funzionale, inclusi input standard, combinazioni di parametri e valori di frontiera:

fn :: test fmt enriched document targets => ()
      test fmt enriched document targets =
        nl = char from code 10
        src = "fn :: cmp Int Int => Bool" + nl + "cmp a b = a < b AND b > 0" + nl

        -- 1. Inline HTML
        html_out = fmt to html src
        assert true (str starts with html_out "<pre class=\"ridgun-code\"") "AC3: HTML inline wrapper"
        assert true (str contains html_out "<span style=\"color:#c678dd;font-weight:bold\">fn</span>") "AC3: HTML inline keyword span"
        assert true (str contains html_out "&lt;") "AC3: HTML escapes < operator"
        assert true (str contains html_out "&gt;") "AC3: HTML escapes > operator"

        -- 2. CSS-class HTML + Stylesheet
        css_html = fmt to html css src
        assert true (str contains css_html "<span class=\"rg-kw\">fn</span>") "AC3: HTML CSS keyword class"
        assert true (str contains css_html "<span class=\"rg-fn\">cmp</span>") "AC3: HTML CSS function class"
        assert true (str contains css_html "<span class=\"rg-type\">Int</span>") "AC3: HTML CSS type class"
        assert true (str contains css_html "<span class=\"rg-logic\">AND</span>") "AC3: HTML CSS logic operator class"
        sheet_dark = fmt html stylesheet FmtThemeDark
        sheet_light = fmt html stylesheet FmtThemeLight
        assert true (str contains sheet_dark ".rg-kw") "AC3: Dark CSS stylesheet"
        assert true (str contains sheet_light "#fafafa") "AC3: Light CSS stylesheet"

        -- 3. Markdown
        md_out = fmt to markdown src
        assert true (str starts with md_out ("

-- 4. Pango Markup pango_out = fmt to pango src _ = assert true (str starts with pango_out ("<tt>" + nl)) "AC3: Pango <tt> wrapper" _ = assert true (str contains pango_out "<span foreground="#c678dd" weight="bold">fn</span>") "AC3: Pango span markup"

-- 5. LaTeX Verbatim latex_out = fmt to latex src _ = assert true (str contains latex_out "Verbatim") "AC3: LaTeX Verbatim environment" _ = assert true (str contains latex_out "textcolor[HTML]") "AC3: LaTeX textcolor macro"

-- 6. RTF rtf_out = fmt to rtf src _ = assert true (str contains rtf_out "rtf1") "AC3: RTF header" _ = assert true (str contains rtf_out "colortbl") "AC3: RTF color table" _ = assert true (str contains rtf_out "\cf1\b fn") "AC3: RTF bold color span" ()


---

## 23.4. Sotto il cofano: come è costruita `fmt` in Ridgun puro (`src/main/ridgun/lib/fmt.rg`)

Uno dei maggiori vantaggi di `ridgun-libs` è che **non ci sono scatole nere in C**. Puoi aprire `src/main/ridgun/lib/fmt.rg` e leggere esattamente come è implementata ogni operazione usando *pattern matching*, alberi di guardie `|` / `|.` e ricorsione di coda (TCO). Vediamo i pezzi chiave della sua implementazione reale:

### 23.4.1. Implementazione interna: Configuration Constructors

Nota come `fmt.rg` strutturi prima le firme `fn :: ... => ...` e risolva ogni caso tramite equazioni allineate e chiamate di coda:

module :: fmt

fn :: default fmt config => FmtConfig default fmt config = FmtConfig 2 4 80 True FmtPlain FmtThemeNone

fn :: fmt config Int Int Int Bool FmtTarget FmtTheme => FmtConfig fmt config indent_w max_params max_w aligned target theme = FmtConfig (fmt max 1 indent_w) (fmt max 0 max_params) (fmt max 20 max_w) aligned target theme


### 23.4.2. Implementazione interna: Signature Parsing (`fn ::` / `op ::`)

Nota come `fmt.rg` strutturi prima le firme `fn :: ... => ...` e risolva ogni caso tramite equazioni allineate e chiamate di coda:

fn :: fmt split sig arrow [FmtToken] [String] => (Bool, [String], String, Int) fmt split sig arrow [] _ = (False, [], "", 0) fmt split sig arrow ((FmtTok tok col):rest) lhs_acc | tok == "=>" OR tok == "->" = (True, lhs_acc, tok, col) | otherwise = fmt split sig arrow rest (lhs_acc :: [tok])

fn :: fmt is sig type tok String => Bool fmt is sig type tok "" = False fmt is sig type tok tok = ch = str char at tok 0 (ch >= 65 AND ch <= 90) OR ch == 91 OR ch == 40

fn :: fmt all type toks [String] => Bool fmt all type toks [] = True fmt all type toks (t:rest) | fmt is sig type tok t = fmt all type toks rest | otherwise = False

fn :: fmt is bare fn lhs [String] => Bool fmt is bare fn lhs (first_w:rest) | NOT (fmt is sig type tok first_w) = fmt all type toks rest fmt is bare fn lhs _ = False

fn :: fmt infer bare kind [String] => String fmt infer bare kind lhs_strs | fmt is bare fn lhs lhs_strs = "bare_fn" | otherwise = "bare_op"

fn :: fmt parse sig line String => FmtSig fmt parse sig line line = clean = fmt strip comment line cmt = fmt extract comment line toks = fmt scan tokens clean fmt parse sig tokens (fmt leading indent line) clean cmt toks

fn :: fmt parse sig tokens Int String String [FmtToken] => FmtSig fmt parse sig tokens _ clean cmt ((FmtTok kind ):(FmtTok "::" ):rest) | kind == "fn" OR kind == "op" = fmt finish sig parse clean cmt kind (fmt split sig arrow rest []) fmt parse sig tokens 0 clean cmt ((FmtTok w col):rest) | w == "type" OR w == "expand" OR w == "import" OR w == "global" OR w == "context" OR w == "shared" OR w == "hardware" OR (str starts with w "@") OR (str starts with w "--") OR (str starts with w "|") = NoSig | otherwise = fmt finish bare sig parse clean cmt (fmt split sig arrow ([FmtTok w col] :: rest) []) fmt parse sig tokens _ _ _ _ = NoSig

fn :: fmt finish bare sig parse String String (Bool, [String], String, Int) => FmtSig fmt finish bare sig parse _ _ (False, , , ) = NoSig fmt finish bare sig parse _ (True, [], , ) = NoSig fmt finish bare sig parse clean cmt (True, lhs_strs, arrow_s, arrow_col) | arrow_s == "=>" = fmt finish sig parse clean cmt (fmt infer bare kind lhs_strs) (True, lhs_strs, arrow_s, arrow_col) | otherwise = NoSig


### 23.4.3. Implementazione interna: Lexical Token Classification & Syntax Highlighting

Nota come `fmt.rg` strutturi prima le firme `fn :: ... => ...` e risolva ogni caso tramite equazioni allineate e chiamate di coda:

fn :: fmt is digit Int => Bool fmt is digit c = c >= 48 and c <= 57

fn :: fmt is upper Int => Bool fmt is upper c = c >= 65 and c <= 90

fn :: fmt is lower Int => Bool fmt is lower c = c >= 97 and c <= 122

fn :: fmt is ident char Int => Bool fmt is ident char c = (fmt is upper c) or (fmt is lower c) or (fmt is digit c) or c == 95

fn :: fmt is keyword String => Bool fmt is keyword w = w == "fn" or w == "op" or w == "type" or w == "expand" or w == "import" or w == "module" or w == "where" or w == "otherwise" or w == "with" or w == "do" or w == "mut" or w == "in" or w == "agent" or w == "send" or w == "to" or w == "receive" or w == "from" or w == "try" or w == "stop" or w == "timeout" or w == "global" or w == "context" or w == "shared" or w == "hardware" or w == "atomic" or w == "region" or w == "limit" or w == "map" or w == "filter" or w == "fold"

fn :: fmt is logic op String => Bool fmt is logic op w = w == "AND" or w == "OR" or w == "XOR" or w == "NOT" or w == "and" or w == "or" or w == "xor" or w == "not" or w == "shl" or w == "shr" or w == "rotr" or w == "rotl"

fn :: fmt is bool lit String => Bool fmt is bool lit w = w == "True" or w == "False"

fn :: fmt classify word String Bool => String fmt classify word "" _ = "plain" fmt classify word w in_fn = | fmt is keyword w = "keyword" | fmt is logic op w = "logic" | fmt is bool lit w = "bool" | fmt is upper (str char at w 0) = "type" | fmt is digit (str char at w 0) = "number" | in_fn = "function" | otherwise = "plain"


### 23.4.4. Implementazione interna: Public Entry Points

Nota come `fmt.rg` strutturi prima le firme `fn :: ... => ...` e risolva ogni caso tramite equazioni allineate e chiamate di coda:

fn :: fmt source with config String FmtConfig => String fmt source with config src cfg = src fmt split raw lines -> raw_lines fmt format top lines raw_lines 0 "" cfg -> formatted_lines cfg target_format -> target cfg color_theme -> theme fmt highlight lines formatted_lines target theme -> highlighted fmt wrap target doc highlighted target theme

fn :: format ridgun source String => String format ridgun source src = fmt source with config src (default fmt config)

fn :: fmt to tty with theme String FmtTheme => String fmt to tty with theme src theme = fmt source with config src (FmtConfig 2 4 80 True FmtTty theme)

fn :: fmt to tty String => String fmt to tty src = fmt to tty with theme src FmtThemeDark

fn :: fmt to truecolor with theme String FmtTheme => String fmt to truecolor with theme src theme = fmt source with config src (FmtConfig 2 4 80 True FmtTrueColor theme)

fn :: fmt to truecolor String => String fmt to truecolor src = fmt to truecolor with theme src FmtThemeDark

fn :: fmt to html with theme String FmtTheme => String fmt to html with theme src theme = fmt source with config src (FmtConfig 2 4 80 True FmtHtmlInline theme)

fn :: fmt to html String => String fmt to html src = fmt to html with theme src FmtThemeDark

fn :: fmt to html css String => String fmt to html css src = fmt source with config src (FmtConfig 2 4 80 True FmtHtmlCss FmtThemeDark)

fn :: fmt to markdown String => String fmt to markdown src = fmt source with config src (FmtConfig 2 4 80 True FmtMarkdown FmtThemeNone)

fn :: fmt to pango with theme String FmtTheme => String fmt to pango with theme src theme = fmt source with config src (FmtConfig 2 4 80 True FmtPango theme)

fn :: fmt to pango String => String fmt to pango src = fmt to pango with theme src FmtThemeDark

fn :: fmt to latex with theme String FmtTheme => String fmt to latex with theme src theme = fmt source with config src (FmtConfig 2 4 80 True FmtLatex theme)

fn :: fmt to latex String => String fmt to latex src = fmt to latex with theme src FmtThemeDark

fn :: fmt to rtf with theme String FmtTheme => String fmt to rtf with theme src theme = fmt source with config src (FmtConfig 2 4 80 True FmtRtf theme)

fn :: fmt to rtf String => String fmt to rtf src = fmt to rtf with theme src FmtThemeDark


---

## 23.5. Garanzie algoritmiche, memoria `RMM1`/`RMM2` e le 5 Regole d'Oro di `fmt`

- **Garanzia algoritmica e di sicurezza**: Idempotenza rigorosa (`fmt source (fmt source s) == fmt source s`) e conservazione del 100% dei token semantici.
- **Complessità dello stack $O(1)$ con TCO**: Tutti i cicli ricorsivi in `src/main/ridgun/lib/fmt.rg` sono in posizione di coda, perciò `ridgunc` li compila in salti nativi senza crescita dello stack.
- **Memoria deterministica (`RMM1`/`RMM2`)**: Zero pause del garbage collector; tutte le strutture intermedie vengono liberate in modo deterministico all'uscita dallo scope.
- **Verifica continua**: Testata in modo esaustivo con `stable check` e la suite automatizzata `src/test/ridgun/test fmt.rg`.

### Le 5 Regole d'Oro quando programmi con `fmt`

1. **Dichiara `import fmt` all'inizio del file** e usa le funzioni multi-parola con spazi naturali affinché il tuo codice si legga come prosa.
2. **Allinea le tue pipeline di dati con `=` e `->`**: concatena le chiamate a `fmt` in passaggi con nomi chiari e lascia che `stable format` allinei le colonne.
3. **Sfrutta le funzioni totali di `fmt` nelle tue guardie `|`**: controlla i valori di ritorno o destruttura gli ADT con *pattern matching* invece di dare per scontato che l'input esterno sia sempre valido.
4. **Evita di copiare grandi strutture se devi solo consultare un campo**: ricorda che in `RMM2` gli argomenti di input sono prestati e non incrementano né decrementano i contatori (`+0` / `-0`).
5. **Combina `fmt` con `test` (`import test`)**: scrivi sempre asserzioni con `assert equals` o `assert true` per fissare gli invarianti del tuo dominio.

---

Nel **Capitolo 24** passeremo a esplorare in profondità la lib **`cli`** (La lib `cli` — Flag, Opzioni, Barriera `--`, Sottocomandi e Variabili d'Ambiente).