Files
inline-schema/docs/syntax-rework-plan.md
T

109 lines
6.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Implementation Plan: Syntax Clarity & Parser Robustness
Status: **Draft — not yet applied**
## Goals
1. Eliminate the backtracking heuristics in the value parser by making the value grammar context-free.
2. Remove redundant/ambiguous syntax forms.
3. Make union resolution deterministic and structural (not error-message-driven).
4. Address the `csv-parse` quote conflict.
5. Keep the `;` separator (forced by CSV constraints — not the source of ambiguity).
All changes are **breaking** to the DSL → bump to `2.0.0`, update README + `csv-loader.md`, add a migration note.
---
## Phase 1 — Mandatory brackets for composite values
**Files:** `src/value-parser.ts`, `src/index.test.ts`, `src/csv-loader/reference-resolver.ts`
- Remove the `allowOmitBrackets` parameter from `parseValue`, `parseTupleValue`, `parseArrayValue`.
- Delete the `elementIsTupleOrArray` disambiguation block and all `savedPos` restore logic in `parseArrayValue`.
- In `parseValue` (top-level), drop the `allowOmitBrackets = schema.type === "tuple" || "array"` special case — brackets are always required.
- Values now must be fully bracketed: `[a; 1]; [b; 2]` (no more `[a; 1]; [b; 2]` without outer brackets).
**Tests to update** (currently assert bracket-optional behavior):
- `index.test.ts`: "should parse tuple without brackets" [L177], "should parse array without brackets" [L215], "should parse array of tuples without outer brackets" [L249].
- `reference-resolver.ts` / `index.test.ts` reference tests: "should parse array reference IDs without brackets" [L685].
**Decision point:** Full mandatory brackets, or a *top-level-only* carve-out (brackets optional only when the value is the whole cell and the element is non-composite)? Recommend **full mandatory** for a clean grammar; note the carve-out as a fallback if ergonomics matter more.
---
## Phase 2 — Single array form `Type[]`
**Files:** `src/parser.ts`, `src/index.test.ts`
- Remove the `[Type][]` array syntax from `parseSchemaInternal`. Keep only `Type[]`.
- This makes `[string]` a **1-tuple** (currently it collapses to an array). Update the tuple branch: `[t]``{ type: "tuple", elements: [t] }`; the special case `elements.length === 1 && !elements[0].name` becomes a real tuple.
- Update `schemaToTypeString` in `src/type-utils.ts` — the `array` case currently special-cases tuple elements; with `[Type][]` gone, arrays are always `elementType[]` (keep the `(union)[]` paren wrapping).
**Tests to update:**
- `index.test.ts`: "should parse array of tuples" [L239] uses `[string; number][]` → becomes `[string; number][]` (unchanged) but "array of tuples without outer brackets" [L249] changes per Phase 1.
- Any test using `[number][]`, `[string][]` schema strings (e.g. README examples, `csv-loader.md`).
---
## Phase 3 — Deterministic union resolution
**Files:** `src/csv-loader/reference-resolver.ts`, `src/validator.ts` (via `type-utils.ts`), `src/csv-loader/module-gen.ts`
- **Rule:** In a union, always try **non-reference members before reference members**, regardless of author order. This makes fallback structural instead of error-message-driven.
- In `parseValueWithReferences` and `resolveNestedReferences`, replace the `/not found|Circular reference|Failed to load/` error-message inspection with a fixed ordering: partition members into `nonRef` / `ref`, try `nonRef` first, then `ref`.
- In `module-gen.ts` `generateSchemaResolutionCode` union case, apply the same ordering so generated code matches runtime behavior.
- **Document the rule** in README (union member ordering is currently "first match wins" per AGENTS.md).
**Note:** This changes behavior for `@users[] | string``string` would now win for plain strings. Flag as a deliberate semantic change.
---
## Phase 4 — Quote conflict resolution
**Files:** `src/parser.ts`, `src/csv-loader/loader.ts`, README, `csv-loader.md`
**Options (pick one):**
- **(a) Standardize on single-quoted literals only** — minimal change, but leaves a footgun.
- **(b) Quote the entire schema cell** so `csv-parse` treats it as one field — requires loader-side handling to strip the outer quotes before parsing.
- **(c) Drop quotes entirely** — use bare-token literals (e.g. `on` / `off` as identifiers). Most robust, largest change.
**Recommendation:** (b) — it's the only option that fixes the root cause (schema cells containing `"` break `csv-parse`) without redesigning the literal syntax. Requires: in `loader.ts`, detect schema-row cells that are fully quoted and unwrap before `parseSchema`.
---
## Phase 5 — Cleanup & consistency
**Files:** `src/csv-loader/reference-resolver.ts`, `src/csv-loader/loader.ts`, `src/csv-loader/module-gen.ts`
- **Reverse-reference performance:** `resolveReverseReference` does `refTable.filter(...)` per row. Build a `Map<fk, rows[]>` lookup once per referenced table (mirroring what `module-gen.ts` already generates) and reuse it. Cache the lookup alongside the parsed table in `referenceTableCache`.
- **Remove the `,` stop-character in `parseReferenceValue`** (value parser has a `,` stop char the schema parser doesn't — drift). Make reference ID parsing consistent with the rest of the value grammar.
- **`int`/`float`/`number``number`:** document the collapse in README (type-level collapse is intentional; parse-time distinction remains).
---
## Phase 6 — Docs & migration
**Files:** `README.md`, `csv-loader.md`, `AGENTS.md`
- Update all syntax tables and examples for mandatory brackets + single array form.
- Add a **Migration section** listing the breaking changes:
1. Composite values must be fully bracketed.
2. `[Type][]` array form removed — use `Type[]`.
3. `[single]` is now a 1-tuple, not an array.
4. Union resolution now prefers non-reference members.
5. (If Phase 4b) schema cells may be fully quoted.
- Update `AGENTS.md` gotchas: union ordering rule, quote handling.
---
## Validation
- `npm run typecheck`
- `npm run test` (update `src/index.test.ts`, `src/csv-loader/*.test.ts` first)
- Manually verify the integration fixture (`user_rev.csv` / `order_rev.csv`) still resolves.
---
## Suggested execution order
Phases 1 → 2 are tightly coupled (both touch bracket parsing) — do them together. Phase 3 is independent. Phase 4 is independent. Phases 56 are cleanup/docs and can go last.