Implement vector/tuple pattern binding (issue #17)#80
Merged
Conversation
Vector/tuple patterns silently produced () on the default EIR VM backend: `[match v #[a b] ...]` never matched and `[let [x y] v]` bound nothing. The checker also rejected the pattern variables as unbound (E0201). Fixed across all three layers. - Checker: bind_pattern_vars now handles Vec/Tuple patterns and binds variables with inferred element types (Vec elem type, positional tuple types); infer_let destructures via new bind_destructure_vars, and map destructuring names are bound so they no longer E0201. - EIR: new internal builtins SeqLen (length-or-minus-one test) and DestructureCheck (loud guard, new VmErrorKind::DestructureMismatch); Op::Field with Selector::Index now works on vectors; match pattern test/bind and the lower_let TODO replaced with recursive destructuring. - Legacy interp: pattern_matches gets the Vec/Tuple arm (previously fell through to no-match); bind_param errors on short destructures instead of silently binding (); #[x y] accepted as a let binding. Semantics (DESIGN.md §6): match `#[a b]` requires exact length (Rust slice prior); destructuring `let` requires at-least length, extra elements allowed (Clojure prior). Too short or non-sequence is a loud runtime error on every backend — never a silent () bind, per the agent-first rule. Tests: 11 interp_tests (both backends), 9 backend-parity corpus entries plus destructure_mismatch_raises_on_both_backends, 2 prior-alignment corpus entries. cargo test --workspace passes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
What shippedVector and tuple patterns now work correctly in both match expressions and destructuring assignments. Previously, writing
Plain-English summary generated by Choji from this pull request. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Fixes issue #17 (P0): vector/tuple patterns silently didn't bind on the default EIR VM backend.
[match v #[a b] ...]never matched and[let [x y] v]bound nothing — both prints in the repro returned(). The checker also rejected the pattern variables as unbound (E0201), so it didn't understand vector patterns either.Now the repro prints
3and15on bothloon runand--legacy, andloon checkpasses it cleanly.Semantics (DESIGN.md §6, new ruling)
No prior ruling existed, so I added one:
#[a b]: matches a vector or tuple of exactly that length (Rust slice-pattern prior); element subpatterns match recursively; non-match falls through.[let [x y] v]: requires a vector/tuple with at least as many elements as binders (extra allowed, Clojure prior). Too short or a non-sequence value is a loud runtime error on both backends (destructuring expected at least N elements, got M/destructuring requires a vector or tuple) — never a silent()bind, per the agent-first rule that silent-wrong is the worst failure mode.Changes
check/mod.rs):bind_pattern_varshandlesVec/Tuplepatterns and binds variables with inferred element types (Vec elem type, positional tuple types);infer_letdestructures via newbind_destructure_vars; map-destructure names are bound so they no longer E0201.lower.rs,vm.rs,mod.rs): new internal builtinsSeqLenandDestructureCheck(newVmErrorKind::DestructureMismatch);Op::FieldwithSelector::Indexnow works on vectors; pattern test/bind and thelower_letTODO replaced with recursive destructuring.interp/mod.rs):pattern_matchesgets theVec/Tuplearm (previously fell through to no-match, as suspected);bind_paramerrors on short destructures;#[x y]accepted as a let binding. Theinterp/machineVM shares these helpers.Tests
interp_tests.rs(both backends via shared helpers)destructure_mismatch_raises_on_both_backendscargo test --workspacepasses;cargo fmtrunReviewer notes
matchwith heterogeneous arm bodies gets a legitimate E0200 fromloon check— this is correct, not a regression, and doesn't blockloon run.[let {a b} m]) still silently binds nothing on the EIR VM — same failure class, out of scope here, flagged as a follow-up.🤖 Generated with Claude Code