Skip to content

Commit eae2124

Browse files
committed
Diagnose symbolic range overlap
1 parent 6264baf commit eae2124

11 files changed

Lines changed: 107 additions & 12 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
4343
- `fall` now lowers in both Zig and C backends for its documented narrow form:
4444
the final direct statement of a non-final match case. Invalid placements are
4545
semantic errors.
46+
- Match range diagnostics now catch conservative runtime-symbolic interval
47+
overlaps when two inclusive ranges share an endpoint symbol, such as
48+
`low..high` followed by `high..top`.
4649
- Release-manifest verification rejects parent-directory traversal and unsafe
4750
absolute paths, while preserving the documented flat downloaded-assets flow.
4851
- File-backed module imports are now contained to configured search paths and

MISSING_FEATURES.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@
5656
- Exact duplicate bool, enum, and scalar literal case patterns are diagnosed.
5757
- Wildcard-first and fully covered bool/enum cases make later case patterns and else branches unreachable.
5858
- Literal and compile-time constant numeric/char range overlaps are diagnosed.
59-
- Non-constant symbolic interval range overlap remains incomplete.
59+
- Conservative non-constant symbolic interval overlaps are diagnosed when
60+
inclusive ranges share an endpoint symbol.
6061
- True variable-binding/capture patterns are not defined; plain identifier patterns currently refer to existing symbols.
6162

6263
2. **Memory/lifetime model**

TODO.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,8 +119,11 @@ Features that are spec'd and partially implemented, or missing from one backend.
119119
- [x] Add constant/computed-constant range match overlap diagnostics.
120120
Notes: literal, constant identifier, and simple constant-expression numeric/char endpoints now participate in range overlap and covered-literal diagnostics.
121121

122-
- [ ] Add non-constant symbolic interval match overlap diagnostics.
123-
Notes: range overlap checks do not reason about runtime symbolic intervals.
122+
- [x] Add conservative non-constant symbolic interval match overlap diagnostics.
123+
Files: `a7/passes/type_checker.py`, `test/test_semantic_control_flow.py`
124+
Notes: range overlap checks now diagnose inclusive runtime-symbolic ranges
125+
that share an endpoint symbol, such as `low..high` followed by `high..top`;
126+
arbitrary runtime inequalities are still not guessed.
124127

125128
- [ ] Define and implement true variable-binding match patterns.
126129
Files: `a7/passes/type_checker.py`, `a7/backends/zig.py`, `a7/backends/c.py`

a7/passes/type_checker.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1771,10 +1771,16 @@ def _match_pattern_range(self, pattern: ASTNode) -> Optional[Tuple[str, float, f
17711771
start = self._range_pattern_value(pattern.start, set()) if pattern.start else None
17721772
end = self._range_pattern_value(pattern.end, set()) if pattern.end else None
17731773
if start is None or end is None:
1774-
return None
1774+
start = self._range_symbolic_value(pattern.start) if pattern.start else None
1775+
end = self._range_symbolic_value(pattern.end) if pattern.end else None
1776+
if start is None or end is None:
1777+
return None
17751778

17761779
start_kind, start_value = start
17771780
end_kind, end_value = end
1781+
if start_kind.startswith("symbol:") and end_kind.startswith("symbol:"):
1782+
symbols = sorted({start_kind.removeprefix("symbol:"), end_kind.removeprefix("symbol:")})
1783+
return (f"symbolic:{'|'.join(symbols)}", 0, 0)
17781784
if start_kind != end_kind:
17791785
return None
17801786

@@ -1855,6 +1861,25 @@ def _range_const_expr_value(self, node: Optional[ASTNode], resolving: Set[str])
18551861

18561862
return None
18571863

1864+
def _range_symbolic_value(self, node: Optional[ASTNode]) -> Optional[Tuple[str, int | float]]:
1865+
"""Resolve runtime-symbolic range endpoints backed by local variables."""
1866+
if node is None:
1867+
return None
1868+
1869+
if node.kind in {NodeKind.IDENTIFIER, NodeKind.PATTERN_IDENTIFIER}:
1870+
name = node.name or ""
1871+
if not name:
1872+
return None
1873+
symbol = self.symbols.lookup(name)
1874+
if symbol is None or symbol.kind != SymbolKind.VARIABLE:
1875+
return None
1876+
symbol_type = symbol.type
1877+
if symbol_type.kind != TypeKind.UNKNOWN and not self._is_numeric_compatible(symbol_type):
1878+
return None
1879+
return (f"symbol:{name}", 0)
1880+
1881+
return None
1882+
18581883
def _range_literal_value(self, literal: ASTNode) -> Optional[Tuple[str, int | float]]:
18591884
"""Normalize literal values that can participate in range overlap checks."""
18601885
if literal.literal_kind == LiteralKind.INTEGER:
@@ -1914,6 +1939,12 @@ def _find_overlapping_match_range(
19141939
"""Return a previous range pattern that overlaps this range, if any."""
19151940
current_kind, current_low, current_high = range_key
19161941
for seen_kind, seen_low, seen_high, seen_pattern in seen_ranges:
1942+
if current_kind.startswith("symbolic:") and seen_kind.startswith("symbolic:"):
1943+
current_symbols = set(current_kind.removeprefix("symbolic:").split("|"))
1944+
seen_symbols = set(seen_kind.removeprefix("symbolic:").split("|"))
1945+
if current_symbols & seen_symbols:
1946+
return seen_pattern
1947+
continue
19171948
if current_kind != seen_kind:
19181949
continue
19191950
if current_low <= seen_high and seen_low <= current_high:

docs/SPEC.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2133,7 +2133,8 @@ Status snapshot (2026-05-08):
21332133
- Exact duplicate bool, enum, and scalar literal patterns are diagnosed.
21342134
- Wildcard-first and fully covered bool/enum cases make later cases and else branches unreachable.
21352135
- Literal and compile-time constant numeric/char range overlaps are diagnosed.
2136-
- Non-constant symbolic interval range overlap diagnostics are still incomplete.
2136+
- Conservative non-constant symbolic interval overlaps are diagnosed when
2137+
inclusive ranges share an endpoint symbol.
21372138
- True variable-binding/capture patterns are not implemented; plain identifier patterns refer to existing symbols.
21382139

21392140
3. **Memory/lifetime model depth**

site/public/docs/features.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,4 @@
2828

2929
## Current Limits
3030

31-
The status page is canonical for remaining gaps. Key limits include complete memory/lifetime guarantees, full generic specialization beyond simple top-level functions, tagged union workflows, and symbolic match-range diagnostics.
31+
The status page is canonical for remaining gaps. Key limits include complete memory/lifetime guarantees, full generic specialization beyond simple top-level functions, tagged union workflows, true match capture patterns, and arbitrary symbolic inequality reasoning.

site/public/docs/guide/features.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,4 +28,4 @@
2828

2929
## Current Limits
3030

31-
The status page is canonical for remaining gaps. Key limits include complete memory/lifetime guarantees, full generic specialization beyond simple top-level functions, tagged union workflows, and symbolic match-range diagnostics.
31+
The status page is canonical for remaining gaps. Key limits include complete memory/lifetime guarantees, full generic specialization beyond simple top-level functions, tagged union workflows, true match capture patterns, and arbitrary symbolic inequality reasoning.

site/public/docs/status.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515

1616
## Known Gaps
1717

18-
- Advanced match diagnostics still have incomplete symbolic interval overlap handling.
18+
- Advanced match diagnostics still lack true capture patterns and arbitrary
19+
symbolic inequality reasoning; shared-endpoint symbolic range overlaps are
20+
diagnosed.
1921
- Ownership/borrow-style lifetime guarantees are not implemented.
2022
- Heap fixed arrays (`new [N]T`) are rejected until their language and backend representation is defined.
2123
- Full generic specialization is incomplete beyond simple top-level generic functions.

site/public/llms-full.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ Implemented:
3939

4040
Known gaps:
4141

42-
- Advanced match diagnostics do not reason about non-constant symbolic intervals.
42+
- Advanced match diagnostics catch shared-endpoint symbolic range overlaps, but
43+
do not infer arbitrary symbolic inequalities.
4344
- True identifier-binding/capture match patterns are not defined.
4445
- Ownership, borrowing, lifetime, use-after-free, and double-free guarantees are not implemented.
4546
- Heap fixed arrays (`new [N]T`) are rejected until representation is defined.

site/src/pages/Status.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const done = [
1313
]
1414

1515
const missing = [
16-
{ name: 'Advanced match diagnostics', desc: 'Exact duplicate, wildcard-first, full bool/enum coverage, and literal plus compile-time constant range overlaps are diagnosed. Non-constant symbolic intervals and true capture patterns remain open.' },
16+
{ name: 'Advanced match diagnostics', desc: 'Exact duplicate, wildcard-first, full bool/enum coverage, literal plus compile-time constant ranges, and shared-endpoint symbolic ranges are diagnosed. True capture patterns and arbitrary symbolic inequalities remain open.' },
1717
{ name: 'Memory/lifetime model', desc: 'Only basic del reference checks. No ownership/borrow-style lifetime analysis.' },
1818
{ name: 'Backend semantic parity hardening', desc: 'Core conformance is green, but differential backend checks should expand for every new language feature.' },
1919
{ name: 'Package-registry publishing', desc: 'The current release workflow deliberately stops at package artifacts attached to draft GitHub releases. Registry publishing should be a separate reviewed change if it is added later.' },
@@ -57,8 +57,8 @@ export default function Status() {
5757

5858
<SectionPanel title="Next priorities">
5959
<ol className="doc-list">
60-
<li>Add non-constant symbolic interval range-overlap match diagnostics.</li>
61-
<li>Improve type checker: control-flow narrowing and deeper assignment compatibility.</li>
60+
<li>Define and implement true variable-binding match patterns.</li>
61+
<li>Improve type checker: control-flow narrowing, arbitrary symbolic range reasoning, and deeper assignment compatibility.</li>
6262
<li>Expand differential/backend-equivalence checks for new language features.</li>
6363
<li>Decide whether package-registry publishing belongs in the release workflow; keep it out until that design is explicit.</li>
6464
</ol>

0 commit comments

Comments
 (0)