Skip to content

feat(argtype): add argtype DSL frontend and backend - #52

Merged
nx10 merged 3 commits into
mainfrom
feat/argtype
Jul 7, 2026
Merged

nx10 merged 3 commits into
mainfrom
feat/argtype

Conversation

@nx10

@nx10 nx10 commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Adds argtype - the hand-authored, TypeScript-types-like language for describing CLI argument grammars (spec) - as both a frontend and a backend, wired into compile(), the CLI (-b argtype, .argtype inputs), and the playground.

What is in it

  • Frontend (frontend/argtype/): lexer, parser, AST, lowering to Styx IR, frontmatter, doc-comment title/description handling, output templates. Covers the core grammar plus the outputs, mediatypes, and paths (.mutable() / .resolveParent()) extensions. set lowers to a sequence, any to its first branch; the draft constraints extension is parsed-and-ignored.
  • Backend (backend/argtype/): a pure IR -> argtype pretty-printer (the inverse of lowering), used as a round-trip / dogfooding oracle.

Corpus validation

Round-tripped against the full 1908-tool NiWrap corpus (compile -> emit argtype -> re-parse -> compare generated TypeScript, modulo doc comments):

  • Re-parse valid: 100% (1888/1888 that codegen in isolation)
  • Codegen identical (modulo doc): 98.15%; the remaining mismatches are the intentional union @type discriminant renaming (argtype derives cleaner discriminants from arm labels; no variants are lost).

Notable language / robustness details

  • Canonical .title() / .description() doc methods (.doc() alias); the # Title heading is ///-block sugar only.
  • Quoted labels and quoted output-template refs ({"4d_output"}) carry non-identifier names verbatim, so names round-trip exactly (no lossy sanitization).
  • Emits .title() / .description() chaining when a /// block would be misread (a leading # description, or a multi-line title).
  • Frontmatter # follows YAML (comment only after whitespace, so URL fragments survive); numeric version accepted; scientific-notation numbers; malformed exponents flagged; non-finite numeric bounds dropped with a warning; inverted min/max and count bounds warned.
  • Format detection recognizes combinator-free specs (bet: path) and tolerates blank lines before the frontmatter fence.

Testing

Full suite green (1053 tests on this branch), plus new frontend/backend/round-trip tests. tsc (core + cli), eslint, and prettier all pass.

The corresponding spec updates live in the separate argtype repo. Independent of #50 and #51.

nx10 added 3 commits July 6, 2026 16:16
argtype is the hand-authored, TypeScript-types-like language for
describing CLI argument grammars (spec at nx10.dev/argtype). This adds it
as both a frontend and a backend, wired into compile(), the CLI
(`-b argtype`, `.argtype` inputs), and the playground.

Frontend (frontend/argtype/): lexer, parser, AST, lowering to Styx IR,
frontmatter, doc-comment title/description split, and output templates.
Covers the core grammar plus the outputs, mediatypes, and paths
(.mutable()/.resolveParent()) extensions; `set` lowers to a sequence,
`any` to its first branch, and the draft constraints extension is
parsed-and-ignored.

Backend (backend/argtype/): a pure IR -> argtype pretty-printer (the
inverse of lowering), used for round-trip dogfooding. Validated against
the full 1908-tool NiWrap corpus: 100% re-parse valid, 98.15%
codegen-identical modulo doc comments (the remainder is intentional
union @type discriminant renaming).

Language/robustness details:
- Canonical `.title()` / `.description()` doc methods (`.doc()` alias);
  the `# Title` heading convention is `///`-block sugar only.
- Quoted labels and quoted output-template refs (`{"4d_output"}`) carry
  non-identifier names verbatim, so names round-trip exactly.
- Emits `.title()`/`.description()` chaining when a `///` block would be
  misread (leading `# ` description, multi-line title).
- Frontmatter `#` follows YAML (only a comment after whitespace);
  numeric `version` accepted; scientific-notation numbers; malformed
  exponents flagged; non-finite numeric bounds dropped with a warning;
  inverted min/max and count bounds warned.
- Format detection recognizes combinator-free specs and tolerates blank
  lines before the frontmatter fence.
- Output entries accept `.title()` / `.description()` (alias `.doc()`), and
  the emitter uses that chaining when a `///` block would be misread (a
  leading `# ` description or a multi-line title), matching node docs.
- The template interpolation scanner is now quote-aware and brace-balanced,
  so a `}` inside a quoted ref name (`{"a}b"}`) or nested `{}` inside a
  quoted op argument (`{a.or("{b}")}`) no longer ends the interpolation early.
…oc key)

Tighten the surface to one canonical name each, since the language is
unreleased and has no back-compat constraint:

- Frontmatter: only `urls:` (list); drop the singular `url` alias.
- Chaining: only `.title()` / `.description()`; drop the `.doc()` alias
  (an unknown `.doc()` is now parsed-and-ignored with a warning, like any
  other unsupported method).
- Stream frontmatter: `stdout` / `stderr` use `description:`, not `doc:`.
@nx10
nx10 merged commit eedb0bc into main Jul 7, 2026
2 checks passed
@nx10
nx10 deleted the feat/argtype branch July 7, 2026 15:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant