Files
hakorune/docs/private/roadmap/selfhosting/front_mvp.md

97 lines
5.1 KiB
Markdown
Raw Normal View History

# Self-Hosting Front MVP — Ny → JSON v0
Status: drafting (Phase 15.9 entry)
## Purpose
- Deliver a Ny-written front-end that lowers Stage-3 Ny source into JSON v0 accepted by the existing MIR/VM/LLVM lines.
- Keep Core (`src/`) untouched; all implementation resides under `lang/src/compiler/`(旧 `apps/selfhost-compiler/` は互換ライン)。
- Fail fast: unsupported syntax must abort with a precise diagnostic, never fall back to Rust-side parser.
## Scope (Day 12)
- Expressions: integer literal, boolean literal, null, binary ops (`+ - * / %`, comparisons `== != < <= > >=`), logical `&& ||`, grouped `(...)`.
- Statements: `return`, `local`, `assignment`, `if/else`, `loop` (while-style), `break`, `continue`.
- Calls: direct function call (`foo()`), method call sugar (`obj.method()`), builtin boxes (Array/Map/String minimal) deferred to Day 34.
- Metadata: `meta.usings` populated from `ParserBox.extract_usings` (already implemented).
- JSON normalization: `JsonProgramBox` fixes key orderと既定値を整備Local/Const/If/Loop/Return/Call、空配列は常に`[]`、null配列は[]に正規化)。
## Interfaces
| box | responsibility |
| --- | --- |
| `ParserBox` | Tokenize/parse Ny source into Stage-1 AST JSON. Already handles Stage-2 constructs; ensure Stage-3 gating by `stage3_enable`. |
| `EmitterBox` | Convert Stage-1 AST JSON to JSON v0 Program. Delegates normalization/meta injection to `JsonProgramBox`. Must guarantee single-line output when `NYASH_JSON_ONLY=1`. |
| `MirEmitterBox` | Out of scope for Day 12 (stub remains). |
### Contracts
- `ParserBox.parse_program2(src)` returns a `Program` JSON string with `version/kind/body/meta` keys.
- `EmitterBox.emit_program(ast_json, usings_json)` injects metadata and *must* avoid altering the AST when `ast_json` already conforms to JSON v0.
- `Main.main(args)` (`lang/src/compiler/entry/compiler.hako`) orchestrates: read source → parse → emit → print.
## Deliverables
1. **Documentation**
- This file (living roadmap).
- Update `CURRENT_TASK_SELFHOST.md` with checklists and timeline (done).
- README snippet explaining how to run the front MVP via `hakorune` flags.
2. **Code**
- Extend `ParserBox` where gaps exist (Stage-3 gating, diagnostics).
- Add `lang/src/compiler/stage1/json_program_box.hako` — normalization box for Program/Stmt/Expr + `meta.usings` injection.
- Keep `EmitterBox` thin by delegating to `JsonProgramBox`.
3. **Tests**
- Quick smokes: `tools/smokes/v2/profiles/quick/selfhost/selfhost_min_const_ret_vm.sh` など。
- Normalization shape: `tools/smokes/v2/profiles/quick/selfhost/selfhost_json_normalize_shapes.sh`If/Loop/Call/Return, meta.usings 確認)。
- Edge normalization: `tools/smokes/v2/profiles/quick/selfhost/selfhost_json_normalize_edges.sh`Loop body null→[]、Call args null→[]、Null ノード維持)。
- Harness comparator: `tools/smokes/v2/run.sh --profile quick``selfhost_front_min_vm_llvm.sh`LLVM 環境があれば)
## Fail-Fast Checklist
- Parser errors include position info (gpos) and stop compilation.
- Unsupported statements/expressions raise `StageUnsupported` error (box-based), not silent drop.
- JSON builder ensures key order (`version`, `kind`, `body`, `meta`) for deterministic output.
## Box Layout Proposal (migrated)
```
lang/src/compiler/
├── parser/ # Stage-1/2/3 parser boxes
│ ├── parser_box.hako
│ ├── parser_expr_box.hako
│ └── parser_stmt_box.hako
├── emitter/ # emit helpers and normalization
│ ├── emitter_box.hako
│ └── json_program_box.hako
├── entry/
│ └── compiler.hako # entry (Ny→JSON v0)
└── docs/
└── front_mvp.md # this file
```
## Execution Examples
Emit-only (JSON header, pipeline v2):
```
NYASH_USE_NY_COMPILER=1 \
NYASH_NY_COMPILER_MIN_JSON=1 \
NYASH_NY_COMPILER_CHILD_ARGS="--pipeline-v2" \
NYASH_NY_COMPILER_EMIT_ONLY=1 \
NYASH_JSON_ONLY=1 \
./target/release/hakorune --backend vm apps/tests/selfhost_min/const_ret.hako
```
Expected output: `{"version":0,...}` single-line JSON.
Execute via VM (Result comparison):
```
NYASH_USE_NY_COMPILER=1 \
NYASH_NY_COMPILER_EMIT_ONLY=0 \
NYASH_SELFHOST_READ_TMP=1 \
./target/release/hakorune --backend vm apps/tests/selfhost_min/const_ret.hako
```
Expected output: `Result: 42`
## Timeline (rolling)
- **Day 1**: Docs + const/return + binop. Add selfhost_min_const_ret smoke.
- **Day 2**: if/else, loop sum smoke, branch diagnostics.
- **Day 3**: Calls/BoxCall minimal, DP integration reuse.
- **Day 4**: externcall string primitives, verify via `run_llvm_extended.sh`.
- **Day 5**: CLI polish + docs cleanup + bench harness alignment.
## Open Questions
- Should Stage-3 acceptance (`break`, `continue`, `throw`) be gated by CLI flag? (Currently via `--stage3`.)
- JSON v0 normalization: do we normalize binary op names (`+``Add`) or keep literal symbols? (Existing Stage-1 uses symbols; MIR builder already maps them.)
- How much of `ParserBox` should move into dedicated modules for maintainability? (Deferred; focus on MVP shipping.)