Files
AILang/examples/list_map_poly.ailx
T
Brummel 706f90bacd Iter 14c: ailang-surface ships — form (A) parser + pretty-printer
Strictly additive new crate per Decision 6 architectural pin.
JSON-AST stays the source of truth; ailang-surface is one
producer/consumer of ailang_core::ast::Module values. ailang-check
and ailang-codegen unchanged.

Crate contents:
- src/lex.rs (~264 LOC): 3-rule lexical core. Whitespace and parens
  delimit tokens; semicolon to EOL is comment; first-character
  classifier (digit -> int, " -> string, else -> ident).
- src/parse.rs (~1041 LOC): hand-written recursive descent. One Rust
  fn per EBNF production. No parser-combinator dep.
- src/print.rs (~371 LOC): deterministic pretty-printer. Round-trip
  contract with parse() is the surface's correctness gate.
- tests/round_trip.rs (~128 LOC): integration test runs every
  examples/*.ail.json fixture through print -> parse -> canonical
  JSON, asserts canonical-byte equality with the original.

Two AST-driven form widenings beyond the 14b sketch (both folded
into DESIGN.md Decision 6):
- lam-term carries (typed name type) params, ret type, and
  optional effects (Term::Lam has parallel param_tys/ret_ty/
  effects fields).
- import-clause admits (import name (as alias)?) (Import.alias
  is Option<String>).

Production count ~28, under 30-rule budget. Constraint 1
(formalisable for foreign LLM) intact.

Verification:
- cargo build --workspace green.
- cargo test --workspace: 76 tests green (was 64; +9 surface unit,
  +2 round-trip integration). All 17 fixtures round-trip
  byte-identical at canonical level. 3 hand-written .ailx
  exhibits parse to canonical JSON identical to their .ail.json
  siblings.
- cargo doc --no-deps zero warnings (DESIGN.md item 6 invariant).

Manual smoke test (ail parse → ail run): hello, box,
list_map_poly all produce expected output through the form-(A)
authoring lane end-to-end.

CLI: ail parse <file.ailx> [-o <file.ail.json>]. .ail.json
remains a first-class input to every existing subcommand.

Plan 14d: stdlib (std_list.ailx with length/filter/fold/concat/
reverse/head/tail), authored in form (A) from day one.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 16:22:14 +02:00

63 lines
1.6 KiB
Plaintext

; Iter 14b design exhibit, finalised in Iter 14c.
; Hash-equivalent to list_map_poly.ail.json (round-trip-tested).
(module list_map_poly
(data List (vars a)
(doc "Polymorphic singly-linked list.")
(ctor Nil)
(ctor Cons a (con List a)))
(fn inc
(doc "Add 1 to an Int.")
(type (fn-type (params (con Int)) (ret (con Int))))
(params x)
(body (app + x 1)))
(fn map
(doc "Polymorphic map: apply f to every element, recursing on the tail.")
(type
(forall (vars a b)
(fn-type
(params (fn-type (params a) (ret b))
(con List a))
(ret (con List b)))))
(params f xs)
(body
(match xs
(case (pat-ctor Nil)
(term-ctor List Nil))
(case (pat-ctor Cons h t)
(term-ctor List Cons
(app f h)
(app map f t))))))
(fn print_list
(doc "Print each Int on its own line.")
(type
(fn-type
(params (con List (con Int)))
(ret (con Unit))
(effects IO)))
(params xs)
(body
(match xs
(case (pat-ctor Nil)
(lit-unit))
(case (pat-ctor Cons h t)
(seq
(do io/print_int h)
(app print_list t))))))
(fn main
(doc "Map inc over [1,2,3] via polymorphic List, then print: 2,3,4.")
(type (fn-type (params) (ret (con Unit)) (effects IO)))
(params)
(body
(app print_list
(app map inc
(term-ctor List Cons 1
(term-ctor List Cons 2
(term-ctor List Cons 3
(term-ctor List Nil)))))))))