Skip to content

Commit cdcf7e3

Browse files
committed
Expand example and parity coverage
1 parent f7d7082 commit cdcf7e3

23 files changed

Lines changed: 233 additions & 69 deletions

AGENT.md

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,15 @@ Compatibility pointer for tools that look for a singular `AGENT.md`.
1717

1818
- Run the compiler: `uv run a7 <args>` (or `uv run python main.py <args>`).
1919
The Python package lives at `a7/`; the entrypoint is `a7.cli:main`.
20-
- Full release gate: `./run_all_tests.sh`
20+
- Full release gate: `./run_all_tests.sh` (covers example E2E for **both**
21+
Zig and C backends and the 24-case backend parity sweep).
2122
- Debug artifacts:
2223
`uv run python scripts/build_examples.py --profile debug --backend both --clean`
2324
- Release artifacts:
2425
`uv run python scripts/build_examples.py --profile release --backend both --clean`
25-
- Backend parity: `uv run python scripts/verify_backend_parity.py`
26+
- Backend parity (24 cases — generic constraints, generic structs/functions,
27+
explicit enum discriminants, stdlib math, operator edge cases):
28+
`uv run python scripts/verify_backend_parity.py`
2629
- Package build: `uv build`
2730
- Wheel install smoke test (clean venv):
2831
`uv run python scripts/verify_wheel_install.py` (CI/release uses
@@ -48,6 +51,13 @@ Compatibility pointer for tools that look for a singular `AGENT.md`.
4851
- Keep `site/public/llms.txt`, `site/public/llms-full.txt`, and
4952
`site/public/docs/` aligned when site navigation, release commands, CLI
5053
behavior, or public docs structure changes.
54+
- Docs must distinguish currently supported features from parsed-only or
55+
reserved syntax — notably variadics, intrinsics other than `@type_set`,
56+
and multiple-declaration/destructuring binding syntax. Do not present
57+
parsed-only forms as working.
58+
- Package-registry publishing (a7 package index, registry client, lockfile
59+
resolution) is **out of scope**; reject related additions to code, docs,
60+
TODO, or MISSING.
5161

5262
See `AGENTS.md` for the full workflow, post-change checklist, and security
5363
caveats.

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88
## [Unreleased]
99

1010
### Changed
11+
- `examples/014_generics.a7` now runs real generic functions and generic struct
12+
instances in both backends; backend parity coverage now also includes type-set
13+
generic constraints, explicit enum discriminants, stdlib math mappings, and
14+
edge operator assignments/comparisons.
15+
- README, SPEC, site, and public Markdown docs now distinguish current features
16+
from parsed-only or reserved syntax such as variadics, non-`@type_set`
17+
intrinsics, and multiple declaration/destructuring syntax.
1118
- Generic struct literals now retain concrete instance types during semantic
1219
analysis, Zig emits generic struct instances with explicit type arguments,
1320
and the C backend monomorphizes used generic struct instances before codegen.

CLAUDE.md

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ from a fresh checkout.
2222
`uv run python scripts/build_examples.py --profile debug --backend both --clean`
2323
- Release artifact verification:
2424
`uv run python scripts/build_examples.py --profile release --backend both --clean`
25+
- Backend parity (24 cases — generic constraints, generic structs/functions,
26+
explicit enum discriminants, stdlib math, operator edge cases):
27+
`uv run python scripts/verify_backend_parity.py`
2528
- Full local release gate: `./run_all_tests.sh`
2629
- Package build: `uv build`
2730
- Wheel install smoke test (clean venv):
@@ -32,10 +35,14 @@ from a fresh checkout.
3235
then check `/a7-py/llms.txt`, `/a7-py/llms-full.txt`, and
3336
`/a7-py/docs/index.md`.
3437

38+
Examples are verified end-to-end against **both** the Zig and C backends —
39+
the Zig and C example E2E scripts must both pass for any change to
40+
`examples/`, codegen, or runtime behavior.
41+
3542
`run_all_tests.sh` is the single source of truth for the full gate (pytest,
36-
parser/semantic/codegen tests, example e2e for Zig and C, backend parity,
37-
debug + release artifacts, error-stage matrix, docs style, secrets check).
38-
Run it before reporting a non-trivial task as done.
43+
parser/semantic/codegen tests, example E2E for Zig and C, 24-case backend
44+
parity, debug + release artifacts, error-stage matrix, docs style, secrets
45+
check). Run it before reporting a non-trivial task as done.
3946

4047
The public docs site also ships Markdown entry points for agent tooling under
4148
`site/public/llms.txt`, `site/public/llms-full.txt`, and `site/public/docs/`.
@@ -65,6 +72,28 @@ navigation when docs structure changes.
6572
- This rule applies to A7 source only. Compiler internals already use
6673
iterative AST traversals; keep them that way.
6774

75+
## Docs Accuracy
76+
77+
User-facing docs (`README.md`, `docs/SPEC.md`, `MISSING_FEATURES.md`,
78+
`site/public/llms*.txt`, `site/public/docs/`) must clearly distinguish
79+
**currently supported** features from syntax that is only **parsed or
80+
reserved** but not yet implemented. In particular, mark these as
81+
parsed-only/reserved rather than working features:
82+
83+
- variadic parameters
84+
- intrinsics other than `@type_set`
85+
- multiple-declaration and destructuring binding syntax
86+
87+
Adding examples, snippets, or claims that imply the parsed-only forms work
88+
end-to-end is treated the same as a doc/code drift bug.
89+
90+
## Out of Scope
91+
92+
- Package-registry publishing (a7 package index, registry client, lockfile
93+
resolution, etc.) is **out of scope** for this repository. Do not add
94+
features, examples, docs, or TODO/MISSING entries that assume a registry;
95+
treat related requests as out-of-scope and flag them.
96+
6897
## Post-Change Checklist
6998

7099
When language features, backends, or user-facing behavior change, update:

MISSING_FEATURES.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,18 @@
5555

5656
## Remaining Language-First Gaps
5757

58+
0. **Spec-only syntax and parsed-only features**
59+
- Variadic parameters are parsed and partially type-checked, but runtime
60+
iteration and backend ABI lowering are not implemented.
61+
- Multiple return values / destructuring (`a, b, c := 1, 2, 3`) are planned
62+
syntax, not current parser support.
63+
- `@type_set(...)` is implemented for generic constraints. Other `@...`
64+
intrinsic names such as `@size_of`, `@align_of`, `@type_id`,
65+
`@type_name`, `@unreachable`, `@likely`, and `@unlikely` are reserved or
66+
tokenized but not semantically resolved/lowered yet.
67+
- Array/tensor programming syntax, performance annotations, and control-flow
68+
narrowing remain tracked backlog items in `TODO.md`.
69+
5870
1. **Advanced match diagnostics**
5971
- Exact duplicate bool, enum, and scalar literal case patterns are diagnosed.
6072
- Wildcard-first and fully covered bool/enum cases make later case patterns and else branches unreachable.

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ Use fixed-width integers such as `i32`, `i64`, `u32`, or `u64` when the data its
159159

160160
## What Works
161161

162-
- **Types**: Primitives, arrays, slices, pointers, generics, raw and aliased function types, inline structs
162+
- **Types**: Primitives, arrays, slices, pointers, generics, raw and aliased function types, inline struct return values
163163
- **Declarations**: Functions, structs, enums, unions, variables, constants, type aliases
164164
- **Control Flow**: if/else, while, for loops, for-in, labeled loops with break/continue, match statements, defer
165165
- **Function Rules**: Direct and mutual recursion are semantic errors
@@ -206,7 +206,7 @@ Use fixed-width integers such as `i32`, `i64`, `u32`, or `u64` when the data its
206206

207207
```bash
208208
cd site
209-
npm install
209+
npm ci
210210
npm run dev
211211
```
212212

TODO.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,8 +183,8 @@ Features that are spec'd and partially implemented, or missing from one backend.
183183

184184
### Unimplemented Spec Features
185185

186-
- [ ] Variadic functions (spec §6.5).
187-
Notes: spec'd but not parsed or implemented.
186+
- [ ] Variadic functions (spec §6.6).
187+
Notes: parsed and partially type-checked, but runtime iteration and backend ABI lowering are not implemented.
188188

189189
- [ ] Multiple return values / destructuring (`a, b, c := 1, 2, 3`).
190190
Notes: spec'd in §4.1, not parsed.

docs/SPEC.md

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -416,9 +416,9 @@ buffer: [1024]u8
416416
age: i32 = 25 // Explicit type
417417
name := "John" // Inferred as string
418418
419-
// Multiple declarations
420-
a, b, c: i32 = 1, 2, 3
421-
x, y := 10, 20
419+
// Multiple declaration/destructuring syntax is planned, not current:
420+
// a, b, c: i32 = 1, 2, 3
421+
// x, y := 10, 20
422422
```
423423

424424
### 4.2 Declaration Rules
@@ -814,8 +814,12 @@ v.normalize() // Modifies v through pointer
814814

815815
### 6.6 Variadic Functions
816816

817+
> **Implementation Status**: Variadic parameter syntax is parsed and partially
818+
> type-checked for declarations, but runtime iteration and ABI lowering are not
819+
> implemented. Do not treat variadic functions as runnable current syntax.
820+
817821
```a7
818-
// Variadic parameters must be last
822+
// Planned shape: variadic parameters must be last
819823
sum :: fn(values: ..i32) i32 {
820824
total := 0
821825
for val in values {
@@ -840,7 +844,7 @@ A7 uses a simple generic system where type parameters are compile-time constants
840844
- `$T` is used **inline** within type expressions to declare and reference generic types
841845
- The same `$T` syntax is used everywhere - no separate declaration vs reference syntax
842846
- Generic types are inferred from usage context at compile time
843-
- Constraints are a semantic analysis feature (future)
847+
- Constraints are a semantic analysis feature for declared generic functions
844848

845849
**Generic Type Parameter Syntax Rules:**
846850
- Must start with `$` followed immediately by a letter (a-z, A-Z)
@@ -874,7 +878,7 @@ pair :: fn(first: $T, second: $U) {
874878
y := second
875879
}
876880
877-
// Generic with array parameter
881+
// Planned broader composite propagation; not backend-complete yet.
878882
first :: fn(arr: []$T) $T {
879883
ret arr[0]
880884
}
@@ -1489,15 +1493,15 @@ Planned, not implemented as public stdlib modules yet:
14891493

14901494
### 10.4 Visibility Rules
14911495

1492-
- `public` modifier only applies to **global/top-level declarations**:
1496+
- `pub` modifier only applies to **global/top-level declarations**:
14931497
- Global functions
14941498
- Global variables and constants
14951499
- Type declarations (struct, enum, union)
1496-
- `public` items are exported from the file/module
1497-
- Non-public items are file-private
1500+
- `pub` items are exported from the file/module
1501+
- Non-`pub` items are file-private
14981502
- No protected/internal visibility
1499-
- **Struct fields are always file-private** (cannot be marked `public`)
1500-
- Function parameters and local variables cannot be marked `public`
1503+
- **Struct fields are always file-private** (cannot be marked `pub`)
1504+
- Function parameters and local variables cannot be marked `pub`
15011505

15021506
---
15031507

@@ -1510,7 +1514,12 @@ These functions are handled specially by the compiler and use the `@` prefix:
15101514
```a7
15111515
// Type sets
15121516
@type_set :: fn(types: ..type) TypeSet // Create type set
1517+
```
15131518

1519+
The tokenizer/parser reserve additional intrinsic spellings, but they are not
1520+
semantically resolved or backend-lowered yet:
1521+
1522+
```a7
15141523
// Memory intrinsics
15151524
@size_of :: fn($T: type) usize // Size in bytes
15161525
@align_of :: fn($T: type) usize // Alignment requirement

examples/011_memory.a7

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ main :: fn() {
1010
io.println("allocation failed")
1111
ret
1212
}
13+
defer del value_ptr
1314

1415
value_ptr.val = 42
1516
io.println("heap value = {}", value_ptr.val)

examples/014_generics.a7

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,32 @@
1-
// Generics status note
2-
//
3-
// Parser and semantic tests cover generic functions, type parameters, and
4-
// constraints. The runnable example stays explicit because release artifacts
5-
// must pass both Zig and C backends, and C generic lowering is still tracked.
1+
// Generic functions and structs
62

73
io :: import "std/io"
84

5+
identity($T) :: fn(value: $T) $T {
6+
ret value
7+
}
8+
9+
Box :: struct {
10+
value: $T
11+
}
12+
13+
Pair($A, $B) :: struct {
14+
first: $A
15+
second: $B
16+
}
17+
918
main :: fn() {
10-
io.println("=== Generics Status ===")
11-
io.println("Generic functions are validated in semantic tests.")
12-
io.println("C backend generic lowering is tracked before runtime examples.")
19+
io.println("=== Generics ===")
20+
21+
number := identity(7)
22+
word := identity("ok")
23+
boxed: Box(i32) = Box(i32){value: number}
24+
nested: Box(Box(i32)) = Box(Box(i32)){value: Box(i32){value: 5}}
25+
pair: Pair(i32, string) = Pair(i32, string){first: boxed.value, second: word}
26+
27+
io.println("identity number = {}", number)
28+
io.println("identity string = {}", word)
29+
io.println("boxed = {}", boxed.value)
30+
io.println("nested boxed = {}", nested.value.value)
31+
io.println("pair = {} {}", pair.first, pair.second)
1332
}

scripts/verify_backend_parity.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,17 @@
327327
main :: fn() {
328328
io.println("generic = {} {}", identity(7), identity("ok"))
329329
}
330+
''',
331+
"generic_constraint_calls": r'''
332+
io :: import "std/io"
333+
334+
smaller($T: Numeric) :: fn(a: $T, b: $T) $T {
335+
ret if a < b { a } else { b }
336+
}
337+
338+
main :: fn() {
339+
io.println("generic constraint = {} {}", smaller(7, 3), smaller(2.5, 4.5))
340+
}
330341
''',
331342
"enum_match_expression": r'''
332343
io :: import "std/io"
@@ -350,6 +361,25 @@
350361
io.println("enum busy = {}", score(State.Busy))
351362
io.println("enum done = {}", score(State.Done))
352363
}
364+
''',
365+
"enum_explicit_discriminants": r'''
366+
io :: import "std/io"
367+
368+
Status :: enum {
369+
Ok = 200
370+
NotFound = 404
371+
Error = 500
372+
}
373+
374+
main :: fn() {
375+
code: Status = Status.NotFound
376+
label := match code {
377+
case Status.Ok: "ok"
378+
case Status.NotFound: "missing"
379+
case Status.Error: "error"
380+
}
381+
io.println("enum explicit = {}", label)
382+
}
353383
''',
354384
"heap_struct_roundtrip": r'''
355385
io :: import "std/io"
@@ -395,6 +425,29 @@
395425
}
396426
io.println("cube = {}", total)
397427
}
428+
''',
429+
"operator_edge_surface": r'''
430+
io :: import "std/io"
431+
432+
main :: fn() {
433+
x := 12
434+
x &= 10
435+
x |= 1
436+
x ^= 3
437+
x <<= 2
438+
x >>= 1
439+
y := ~x
440+
ok := (x != 0) and (x <= 20) and (x >= 1)
441+
io.println("ops edge = {} {} {}", x, y, ok)
442+
}
443+
''',
444+
"stdlib_math_runtime": r'''
445+
io :: import "std/io"
446+
math :: import "std/math"
447+
448+
main :: fn() {
449+
io.println("math = {} {} {} {}", math.floor(3.8), math.ceil(3.2), math.min(7.0, 3.0), math.max(7.0, 3.0))
450+
}
398451
''',
399452
}
400453

0 commit comments

Comments
 (0)