Saltar ao contido
Ridgun
Galego

23 O Libro de Ridgun

A lib fmt — Formatador Tabular Canónico 2D e Resaltador de Sintaxe en 9 Formatos

23.1. Por que existe a lib fmt? (O problema real e a filosofía Ridgun)

«Por que necesito unha lib fmt escrita dende cero en Ridgun puro en vez de enlazar unha librería de C de toda a vida?»

Esa é a primeira pregunta que se fai calquera enxeñeiro de sistemas ao chegar a fmt. E a resposta resume toda a filosofía de ridgun-libs:

Sexamos sinceros: a beleza do código Ridgun reside nas súas columnas tabulares perfectamente aliñadas (::, =, |, ->, --), pero aliñar espazos á man ou exportar código coloreado para terminal, HTML e LaTeX sen unha ferramenta dedicada é tedioso.

A lib fmt é o motor oficial de formatado tabular 2D e resaltado léxico de Ridgun: aliña sinaturas fn ::, ecuacións, gardas | e comentarios --, e exporta a 9 formatos de saída (FmtPlain, FmtTty, FmtTrueColor, FmtHtmlInline, FmtHtmlCss, FmtMarkdown, FmtPango, FmtLatex, FmtRtf).

Nun ecosistema tradicional, resolver as tarefas do dominio FMT implica arrastrar dependencias externas en C, loitar con punteiros crus, conversións opacas de tipos, excepcións non verificadas ou pausas impredicibles do colector de lixo. En Ridgun, a lib fmt (src/main/ridgun/lib/fmt.rg) aborda o problema con catro principios innegociables:

  1. Declara import fmt (ou import fmt as alias) ao inicio do ficheiro: cada lib define o seu espazo de nomes module :: fmt e en modo --strict as funcións multi-palabra invócanse sempre con espazos naturais.
  2. Encadea as túas tubaxes de esquerda a dereita con ->: escribe entrada paso un -> paso dous -> resultado, usa máscaras (+ _ _ +) para desestruturar secuencias e omite _ = en sentenzas secuenciais (ou descarta con -> ()).
  3. Recursión de cola con TCO (Tail-Call Optimization): todos os percorridos internos de fmt compílanse a bucles nativos en espazo de pila $O(1)$.
  4. Memoria determinista (RMM1 / RMM2): cada estrutura intermedia libérase no instante exacto en que remata a súa última lectura, sen Garbage Collector.

23.2. Artefactos nativos, importación e catálogo completo da API de fmt

En ridgun-libs, fmt é unha lib de primeira clase situada en src/main/ridgun/lib/fmt.rg (dominio FMT). Ao compilar con stable bundle, empaquétase en tres formatos nativos:

ArtefactoRutaPropósito
Bundle Ridguntarget/bundles/fmt.rglibDistribución e importación directa con import fmt
Ficheiro compiladotarget/fmt.rgcArtefacto intermedio verificado por ridgunc
Obxecto compartido ELF64target/libfmt.soBiblioteca dinámica nativa sen dependencias de C nin libc

Cada lib declara o seu propio espazo de nomes con module :: fmt: abonda con escribir import fmt (ou import fmt as alias) na cabeceira e chamar ás súas funcións con espazos naturais (mina funcion x) e tubaxes -> (x mina funcion -> resultado).

23.2.1. Resumo de familias funcionais de fmt

Sinatura / Función / TipoQue fai e cando usala
fmt source / fmt source withFormatea código fonte Ridgun usando o aliñamento tabular 2D canónico
fmt checkDevolve True se o código xa cumpre o formato tabular canónico de fmt source
fmt render / fmt render withFormatea e colorea o código cara a calquera dos 9 formatos FmtTarget
fmt tokenize lineTokeniza unha liña en TokKeyword, TokType, TokOperator, TokString, TokNumber, TokComment

23.2.2. Catálogo exhaustivo de tipos e sinaturas en src/main/ridgun/lib/fmt.rg

A continuación tes o inventario completo de tipos alxébricos (type), operadores (op ::) e sinaturas de funcións (fn ::) definidos en src/main/ridgun/lib/fmt.rg (7 tipos, 0 operadores e 166 funcións):

Tipos alxébricos e rexistros (type) de 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
#Función / Sinatura (fn ::)Tipo de Retorno
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. Explorando fmt a fondo: Exemplos paso a paso de cada funcionalidade

Non abonda con ver a táboa de sinaturas: imos explorar cada unha das funcionalidades da lib fmt mediante exemplos progresivos e executables en Ridgun. Comezaremos polas dúas receitas tabulares de uso cotián e despois percorreremos en detalle todos os escenarios funcionais, transformacións e casos límite verificados en src/test/ridgun/test fmt.rg.

23.3.1. Exemplo 1: Fluxo principal en estilo tabular con fmt

Observa como en Ridgun os signos = e os pasos de transformación con fmt quedan aliñados coma unha táboa limpa, sen variables mutables innecesarias nin efectos laterais ocultos:

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. Exemplo 2: Composición segura e manexo de casos de bordo

Toda función da lib fmt está deseñada para compoñerse con gardas booleanas | e co resto das 32 libs de ridgun-libs:

import fmt

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

23.3.3. Exemplo 3: Aliñación tabular canónica (fmt ridgun, fmt ridgun with) de sinaturas =>, cláusulas =, enlaces -> e comentarios --

Neste exemplo práctico exploramos de forma exhaustiva como se comporta fmt neste bloque funcional, incluíndo entradas estándar, combinacións de parámetros e valores fronteira:

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. Exemplo 4: Resaltado léxico ANSI de 16 cores e TrueColor de 24 bits con detección automática de TTY e NO_COLOR

Neste exemplo práctico exploramos de forma exhaustiva como se comporta fmt neste bloque funcional, incluíndo entradas estándar, combinacións de parámetros e valores fronteira:

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. Exemplo 5: Exportación de documentos resaltados a HTML5 (<pre><code>), Pango Markup, LaTeX, RTF e SVG vectorial

Neste exemplo práctico exploramos de forma exhaustiva como se comporta fmt neste bloque funcional, incluíndo entradas estándar, combinacións de parámetros e valores fronteira:

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. Baixo o capó: como está construída `fmt` en Ridgun puro (`src/main/ridgun/lib/fmt.rg`)

Unha das maiores vantaxes de `ridgun-libs` é que **non hai caixas negras en C**. Podes abrir `src/main/ridgun/lib/fmt.rg` e ler exactamente como está implementada cada operación usando *pattern matching*, árbores de gardas `|` / `|.` e recursión de cola (TCO). Vexamos as pezas clave da súa implementación real:

### 23.4.1. Implementación interna: Configuration Constructors

Fíxate en como `fmt.rg` estrutura as sinaturas `fn :: ... => ...` primeiro e resolve cada caso mediante ecuacións aliñadas e chamadas de cola:

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. Implementación interna: Signature Parsing (`fn ::` / `op ::`)

Fíxate en como `fmt.rg` estrutura as sinaturas `fn :: ... => ...` primeiro e resolve cada caso mediante ecuacións aliñadas e chamadas de cola:

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. Implementación interna: Lexical Token Classification & Syntax Highlighting

Fíxate en como `fmt.rg` estrutura as sinaturas `fn :: ... => ...` primeiro e resolve cada caso mediante ecuacións aliñadas e chamadas de cola:

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. Implementación interna: Public Entry Points

Fíxate en como `fmt.rg` estrutura as sinaturas `fn :: ... => ...` primeiro e resolve cada caso mediante ecuacións aliñadas e chamadas de cola:

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. Garantías algorítmicas, memoria `RMM1`/`RMM2` e as 5 Regras de Ouro de `fmt`

- **Garantía algorítmica e de seguridade**: Idempotencia estrita (`fmt source (fmt source s) == fmt source s`) e preservación do 100 % dos tokens semánticos.
- **Complexidade de pila $O(1)$ con TCO**: Todos os bucles recursivos en `src/main/ridgun/lib/fmt.rg` están en posición de cola, polo que `ridgunc` os compila a saltos nativos sen crecemento de pila.
- **Memoria determinista (`RMM1`/`RMM2`)**: Cero pausas de colector de lixo; todas as estruturas intermedias libéranse de forma determinista ao saír do ámbito.
- **Verificación continua**: Probada exhaustivamente con `stable check` e a suite automatizada `src/test/ridgun/test fmt.rg`.

### As 5 Regras de Ouro ao programar con `fmt`

1. **Declara `import fmt` ao inicio do ficheiro** e aproveita a equivalencia entre espazos e guións baixos para que o teu código se lea coma prosa.
2. **Aliña as túas tubaxes de datos con `=`**: encadea as chamadas a `fmt` en pasos con nome propio e deixa que `stable format` aliñe as columnas.
3. **Aproveita as funcións totais de `fmt` nas túas gardas `|`**: comproba os valores de retorno ou desenvolve os ADTs con *pattern matching* en vez de asumir que a entrada externa sempre é válida.
4. **Evita copiar grandes estruturas se só necesitas consultar un campo**: lembra que en `RMM2` os argumentos de entrada non incrementan nin decrementan contadores (`+0` / `-0`).
5. **Combina `fmt` con `test` (`import test`)**: escribe sempre asercións con `assert equals` ou `assert true` para fixar os invariantes do teu dominio.

---

No **Capítulo 24** pasaremos a explorar en profundidade a lib **`cli`** (A lib `cli` — Bandeiras, Opcións, Barreira `--`, Subcomandos e Variables de Contorno).