Skip to content

Parse zero-argument contract signatures () -> T#55

Merged
yavorpanayotov merged 1 commit into
mainfrom
fix/zero-arg-contract-signatures
Jun 19, 2026
Merged

Parse zero-argument contract signatures () -> T#55
yavorpanayotov merged 1 commit into
mainfrom
fix/zero-arg-contract-signatures

Conversation

@yavorpanayotov

Copy link
Copy Markdown
Collaborator

What

Lets contract operation signatures declare zero arguments with an empty parameter list:

contract Registry {
    list_things: () -> Set<Foo>
    health: () -> Status
}

Closes juxt/allium#37.

Why

Signatures previously required ≥1 parameter — both op: () -> T and op: -> T failed to parse:

expected expression (identifier, number, string, ...), found ')'

That forced a nominal dummy parameter (op: (_unit: Any) -> T) for common parameterless operations (list-all, fetch global state, health checks), leaking an implementation artefact into the spec and making signature-level comparison against a real API noisier.

Fix

parse_paren_expr only recognised (name: ...) typed parameter lists; empty () fell through to the expression parser, which errored on ). It now handles () as an empty parameter list — represented as an empty block — so the trailing -> Type projection attaches the return type with no parameters, exactly mirroring how multi-parameter lists already become a block.

The empty-params form needs no downstream changes: I traced the consumers and both the analyzer (analysis.rs) and the test-plan builder (test_plan.rs) treat contract signatures as generic expression trees and never extract/validate parameters, so an empty parameter list flows through cleanly.

Scope

  • () -> ReturnType is supported (the conventional spelling).
  • The bare-arrow form -> ReturnType remains a parse error — keeping one canonical spelling, as the issue allowed ("at least one of the two forms").

Verification

  • New regression test zero_arg_contract_signature_parens asserts the form parses cleanly and produces an empty-block parameter list.
  • cargo test --workspace green (579 tests; parser 392, CLI 187).
  • End-to-end: allium check on the issue's exact reproduction now exits 0 with no diagnostics (previously a parse error).
  • The LSP/editor path parses via the same Rust parser compiled to WASM, so it picks this up once the WASM parser is rebuilt — no separate TypeScript change needed.

Docs: added a zero-argument signature example to the v3 language reference (contracts section).

🤖 Generated with Claude Code

Contract operation signatures previously required at least one parameter:
both `op: () -> T` and `op: -> T` failed to parse, forcing a nominal
`_unit: Any` dummy argument. Zero-arg operations (list-all, fetch global
state, health checks) are common at integration boundaries, so the dummy
leaked an implementation artefact into the spec.

`parse_paren_expr` only recognised `(name: ...)` typed parameter lists;
empty `()` fell through to the expression parser, which errored on `)`.
Handle `()` as an empty parameter list — an empty block — so the trailing
`-> Type` projection attaches the return type with no parameters,
mirroring how multi-parameter lists already become a block. The analyzer
and test-plan builder read contract signatures as generic expression
trees and never extract parameters, so the empty-params form flows
through with no downstream changes.

`() -> ReturnType` is supported; the bare-arrow form `-> ReturnType`
remains a parse error (one canonical spelling).

Closes juxt/allium#37

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@yavorpanayotov yavorpanayotov merged commit 4c7b4ad into main Jun 19, 2026
2 checks passed
@yavorpanayotov yavorpanayotov deleted the fix/zero-arg-contract-signatures branch June 19, 2026 13:13
yavorpanayotov added a commit to juxt/allium that referenced this pull request Jun 19, 2026
* Wire allium-lsp in plugin.json for live .allium diagnostics (#39)

Add an lspServers entry so the Claude Code plugin connects the
allium-lsp language server to .allium files, giving Claude checker
diagnostics, go-to-definition and hover immediately after each edit
without a separate `allium check` invocation.

Note in the README that allium-lsp is not bundled and must be
installed separately (and be on PATH), consistent with official
marketplace LSP plugins.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Fix allium-lsp invocation and install note

The language server calls createConnection(ProposedFeatures.all), which
requires a transport flag on argv, so it must be launched as
`allium-lsp --stdio` (per allium-tools CONTRIBUTING). Add args: ["--stdio"]
to the lspServers entry; without it the server errors on startup.

allium-lsp is not published to npm (the bare and @juxt-scoped names both
404), so drop the `npm install -g allium-lsp` instruction and point to the
allium-tools repo for installing the server onto PATH instead.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Document zero-argument contract signatures

Note that contract operations can take an empty parameter list,
`name: () -> ReturnType`, for parameterless operations (list-all, fetch
global state, health checks). Mirrors the v3 language reference in
allium-tools and matches the parser fix in juxt/allium-tools#55.

Refs #37

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
yavorpanayotov added a commit that referenced this pull request Jun 19, 2026
Minor bump for the new zero-argument contract signature syntax
(`op: () -> T`, #55) — backwards-compatible new language functionality.
Updates all workspace packages via scripts/version-bump.sh.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

Contract signatures cannot express zero-argument operations

1 participant