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>
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
//! AILang authoring surface — form (A) S-expression projection.
|
||||
//!
|
||||
//! This crate is **one of potentially many** producers / consumers of
|
||||
//! [`ailang_core::ast::Module`] values. The JSON-AST in `ailang-core`
|
||||
//! remains the canonical, hashable, content-addressed source of truth;
|
||||
//! form (A) is the AI-authoring projection optimised for token-efficient
|
||||
//! production by LLMs (see `docs/DESIGN.md` Decision 6).
|
||||
//!
|
||||
//! ## Modules
|
||||
//!
|
||||
//! - [`mod@lex`] — hand-written lexer for the 3-rule lexical core
|
||||
//! (whitespace / parens / comments delimit tokens; first character
|
||||
//! classifies into integer / string / ident).
|
||||
//! - [`mod@parse`] — hand-written recursive-descent parser. One Rust
|
||||
//! function per EBNF production, line-by-line auditable. No
|
||||
//! parser-combinator dependency.
|
||||
//! - [`mod@print`] — deterministic pretty-printer that emits form (A).
|
||||
//! Round-trip with the parser is the contract that gates the
|
||||
//! surface (see the integration test `tests/round_trip.rs`).
|
||||
//!
|
||||
//! ## Round-trip contract
|
||||
//!
|
||||
//! For every well-formed [`ailang_core::ast::Module`] value `m`,
|
||||
//! [`parse()`] applied to [`print()`]`(m)` produces a module whose
|
||||
//! canonical JSON bytes equal those of `m`. This is enforced by the
|
||||
//! integration test against every `examples/*.ail.json` fixture.
|
||||
//!
|
||||
//! ## Architectural pin
|
||||
//!
|
||||
//! No new AST nodes, no schema changes, no new hashable form.
|
||||
//! `ailang-check` and `ailang-codegen` are projection-agnostic — they
|
||||
//! consume `Module` values regardless of which front-end produced them.
|
||||
|
||||
pub mod lex;
|
||||
pub mod parse;
|
||||
pub mod print;
|
||||
|
||||
pub use parse::{parse, ParseError};
|
||||
pub use print::print;
|
||||
Reference in New Issue
Block a user