Saltar para o conteúdo
Ridgun
Português

23 O Livro do Ridgun

A lib fmt — Formatador Tabular Canónico 2D e Realçador de Sintaxe em 9 Formatos

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

«Por que preciso de uma lib fmt escrita de raiz em Ridgun puro em vez de ligar uma biblioteca C tradicional?»

Essa é a primeira pergunta que qualquer engenheiro de sistemas faz ao chegar à fmt. E a resposta resume toda a filosofia do ridgun-libs:

Sejamos sinceros: a beleza do código Ridgun reside nas suas colunas tabulares perfeitamente alinhadas (::, =, |, ->, --), mas alinhar espaços à mão ou exportar código colorido para terminal, HTML e LaTeX é trabalhoso.

A lib fmt é o motor oficial de formatação tabular 2D e realce léxico do Ridgun: alinha assinaturas fn ::, equações, guardas | e comentários --, e exporta para 9 formatos de saída (FmtPlain, FmtTty, FmtTrueColor, FmtHtmlInline, FmtHtmlCss, FmtMarkdown, FmtPango, FmtLatex, FmtRtf).

Num ecossistema tradicional, resolver as tarefas do domínio FMT implica arrastar dependências externas em C, lidar com ponteiros brutos, conversões opacas de tipos, exceções não verificadas ou pausas imprevisíveis do coletor de lixo. Em Ridgun, a lib fmt (src/main/ridgun/lib/fmt.rg) aborda o problema com quatro princípios inegociáveis:

  1. Declare import fmt (ou import fmt as alias) no início do ficheiro: cada lib define o seu espaço de nomes module :: fmt e em modo --strict as funções multi-palavra são sempre invocadas com espaços naturais.
  2. Encadeie os seus pipelines da esquerda para a direita com ->: escreva entrada passo um -> passo dois -> resultado, use máscaras (+ _ _ +) para desestruturar sequências e omita _ = em instruções sequenciais (ou descarte com -> ()).
  3. Recursão de cauda com TCO (Tail-Call Optimization): todas as travessias internas da fmt são compiladas para ciclos nativos em espaço de pilha $O(1)$.
  4. Memória determinística (RMM1 / RMM2): cada estrutura intermédia é libertada no instante exato em que termina a sua última leitura, sem Garbage Collector.

23.2. Artefactos nativos, importação e catálogo completo da API de fmt

No ridgun-libs, fmt é uma lib de primeira classe localizada em src/main/ridgun/lib/fmt.rg (domínio FMT). Ao compilar com stable bundle, é empacotada em três formatos nativos:

ArtefactoCaminhoFinalidade
Bundle Ridguntarget/bundles/fmt.rglibDistribuição e importação direta com import fmt
Ficheiro compiladotarget/fmt.rgcArtefacto intermédio verificado pelo ridgunc
Objeto partilhado ELF64target/libfmt.soBiblioteca dinâmica nativa sem dependências de C nem libc

Cada lib declara o seu próprio espaço de nomes com module :: fmt: basta escrever import fmt (ou import fmt as alias) no topo e invocar as suas funções com espaços naturais (minha funcao x) e pipelines -> (x minha funcao -> resultado).

23.2.1. Resumo das famílias funcionais da fmt

Assinatura / Função / TipoO que faz e quando usar
fmt source / fmt source withFormata código-fonte Ridgun usando o alinhamento tabular 2D canónico
fmt checkDevolve True se o código já cumprir o formato tabular canónico de fmt source
fmt render / fmt render withFormata e realça o código para qualquer um dos 9 formatos FmtTarget
fmt tokenize lineTokeniza uma linha em TokKeyword, TokType, TokOperator, TokString, TokNumber, TokComment

23.2.2. Catálogo exaustivo de tipos e assinaturas em src/main/ridgun/lib/fmt.rg

Abaixo encontra-se o inventário completo de tipos algébricos (type), operadores (op ::) e assinaturas de funções (fn ::) definidos em src/main/ridgun/lib/fmt.rg (7 tipos, 0 operadores e 166 funções):

Tipos algébricos e registos (type) da 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
#Função / Assinatura (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 a fmt a fundo: Exemplos passo a passo de cada funcionalidade

Não basta ver a tabela de assinaturas: vamos explorar cada uma das funcionalidades da lib fmt através de exemplos progressivos e executáveis em Ridgun. Começaremos pelas duas receitas tabulares de uso diário e depois percorreremos em detalhe todos os cenários funcionais, transformações e casos de fronteira verificados em src/test/ridgun/test fmt.rg.

23.3.1. Exemplo 1: Fluxo principal em estilo tabular com fmt

Repare como em Ridgun os sinais = e os passos de transformação com fmt ficam alinhados como uma tabela limpa, sem variáveis mutáveis desnecessárias nem efeitos colaterais 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: Composição segura e tratamento de casos de fronteira

Todas as funções da lib fmt foram desenhadas para se comporem com guardas booleanas | e com as restantes 32 libs do ridgun-libs:

import fmt

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

23.3.3. Exemplo 3: Alinhamento tabular canónico (fmt ridgun, fmt ridgun with) de assinaturas =>, cláusulas =, ligações -> e comentários --

Neste exemplo prático exploramos de forma exaustiva como a fmt se comporta neste bloco funcional, incluindo entradas padrão, combinações de parâmetros e valores limite:

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: Realce léxico ANSI de 16 cores e TrueColor de 24 bits com deteção automática de TTY e NO_COLOR

Neste exemplo prático exploramos de forma exaustiva como a fmt se comporta neste bloco funcional, incluindo entradas padrão, combinações de parâmetros e valores limite:

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: Exportação de documentos realçados para HTML5 (<pre><code>), Pango Markup, LaTeX, RTF e SVG vetorial

Neste exemplo prático exploramos de forma exaustiva como a fmt se comporta neste bloco funcional, incluindo entradas padrão, combinações de parâmetros e valores limite:

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. Debaixo do capô: como a `fmt` é construída em Ridgun puro (`src/main/ridgun/lib/fmt.rg`)

Uma das maiores vantagens do `ridgun-libs` é que **não existem caixas-pretas em C**. Pode abrir `src/main/ridgun/lib/fmt.rg` e ler exatamente como cada operação é implementada usando *pattern matching*, árvores de guardas `|` / `|.` e recursão de cauda (TCO). Vejamos as peças-chave da sua implementação real:

### 23.4.1. Implementação interna: Configuration Constructors

Observe como `fmt.rg` estrutura primeiro as assinaturas `fn :: ... => ...` e resolve cada caso através de equações alinhadas e chamadas de cauda:

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. Implementação interna: Signature Parsing (`fn ::` / `op ::`)

Observe como `fmt.rg` estrutura primeiro as assinaturas `fn :: ... => ...` e resolve cada caso através de equações alinhadas e chamadas de cauda:

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. Implementação interna: Lexical Token Classification & Syntax Highlighting

Observe como `fmt.rg` estrutura primeiro as assinaturas `fn :: ... => ...` e resolve cada caso através de equações alinhadas e chamadas de cauda:

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. Implementação interna: Public Entry Points

Observe como `fmt.rg` estrutura primeiro as assinaturas `fn :: ... => ...` e resolve cada caso através de equações alinhadas e chamadas de cauda:

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. Garantias algorítmicas, memória `RMM1`/`RMM2` e as 5 Regras de Ouro da `fmt`

- **Garantia algorítmica e de segurança**: Idempotência estrita (`fmt source (fmt source s) == fmt source s`) e preservação de 100 % dos tokens semânticos.
- **Complexidade de pilha $O(1)$ com TCO**: Todos os ciclos recursivos em `src/main/ridgun/lib/fmt.rg` estão em posição de cauda, pelo que o `ridgunc` os compila para saltos nativos sem crescimento de pilha.
- **Memória determinística (`RMM1`/`RMM2`)**: Zero pausas de coletor de lixo; todas as estruturas intermédias são libertadas de forma determinística à saída do escopo.
- **Verificação contínua**: Testada exaustivamente com `stable check` e pela suite automatizada `src/test/ridgun/test fmt.rg`.

### As 5 Regras de Ouro ao programar com a `fmt`

1. **Declare `import fmt` no início do ficheiro** e aproveite a equivalência entre espaços e underscores para que o seu código se leia como prosa.
2. **Alinhe os seus pipelines de dados com `=`**: encadeie as chamadas à `fmt` em passos nomeados e deixe o `stable format` alinhar as colunas.
3. **Aproveite as funções totais da `fmt` nas suas guardas `|`**: verifique os valores de retorno ou desempacote os ADTs com *pattern matching* em vez de assumir que a entrada externa é sempre válida.
4. **Evite copiar grandes estruturas se só precisa de consultar um campo**: lembre-se de que no `RMM2` os argumentos de entrada não incrementam nem decrementam contadores (`+0` / `-0`).
5. **Combine a `fmt` com `test` (`import test`)**: escreva sempre asserções com `assert equals` ou `assert true` para fixar os invariantes do seu domínio.

---

No **Capítulo 24** passaremos a explorar em profundidade a lib **`cli`** (A lib `cli` — Flags, Opções, Barreira `--`, Subcomandos e Variáveis de Ambiente).