docs(repl): record Phase 288.1 contract and results
更新内容: - docs/reference/language/repl.md - Phase 288.1 完了ステータスに更新 - Implementation Architecture セクション追加(AST rewrite 方式説明) - AST Rewriter の動作フロー追加(Variable/Assignment 変換ロジック) - ExternCall Bridge の仕組み追加(__repl.get/set → VMValue) - Expression Detection ロジック追加(wrapper AST 判定) - 動作例を完全に更新(全機能が動作済み) - docs/development/current/main/phases/phase-288/README.md - Phase 288.1 完了セクション追加 - 変更ファイル一覧(8ファイル, +592行)記録 - 確認コマンド 4種 記録(変数永続化/式表示/_変数/リセット) - 回帰テスト結果記録(154/154 PASS) - docs/development/current/main/10-Now.md - "Phase 288.1 完了" に更新 - 次の候補(REPL UX 改善 / JoinIR 設計作業)を追記 - CURRENT_TASK.md - 1段落サマリー更新(288.1 完了、次の方向性) Phase 288.1 成果(SSOT記録): ✅ 変数永続化(session → eval bridge) ✅ 式自動表示(pure expression auto-output) ✅ _ 変数(last displayed value) ✅ Fail-Fast 未定義エラー + ヒント ✅ セッションリセット(.reset) ✅ 154/154 smoke tests PASS(file mode 不変) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@ -12,7 +12,11 @@ Scope: Repo root の旧リンク互換。現行の入口は `docs/development/cu
|
||||
|
||||
### 状況(SSOT)
|
||||
|
||||
**2025-12-25: Phase 288.1 完了**
|
||||
REPL session persistence + auto-display 実装完了。AST rewrite 方式(__repl.get/set ExternCall)により、変数永続化・式自動表示・`_` 変数をすべて実現。154/154 smoke tests PASS(file mode 不変)。次の候補は REPL UX 改善(multi-line input等)または JoinIR/return 系の設計作業。
|
||||
|
||||
- 現行の入口: `docs/development/current/main/10-Now.md`
|
||||
- Phase 288.1 詳細: `docs/development/current/main/phases/phase-288/README.md`
|
||||
- 次の候補: `docs/development/current/main/30-Backlog.md`
|
||||
- Design goal: `docs/development/current/main/design/join-explicit-cfg-construction.md`
|
||||
|
||||
|
||||
@ -2,20 +2,42 @@
|
||||
|
||||
## Current Focus (next)
|
||||
|
||||
- Phase 288.1(dev-tools): REPL session persistence + auto-display
|
||||
- 目的: `hakorune --repl` で変数が行を跨いで生きる(暗黙local)+式の自動表示(`_` を含む)
|
||||
- 入口: `docs/development/current/main/phases/phase-288/README.md`
|
||||
- 手順: `docs/development/current/main/phases/phase-288/P1-INSTRUCTIONS.md`
|
||||
**2025-12-25: Phase 288.1 完了** ✅
|
||||
- REPL session persistence + auto-display 実装完了
|
||||
- AST rewrite 方式(__repl.get/set ExternCall)
|
||||
- 154/154 smoke tests PASS(file mode 不変)
|
||||
- 詳細: `docs/development/current/main/phases/phase-288/README.md`
|
||||
|
||||
- Phase 284(design-first): Return as ExitKind SSOT(patternに散らさない)
|
||||
- 目的: `return` を `ExitKind` + `compose::*` / `emit_frag()` に収束させ、pattern側の個別実装を増やさない
|
||||
- 入口: `docs/development/current/main/phases/phase-284/README.md`
|
||||
- 手順: `docs/development/current/main/phases/phase-284/P0-INSTRUCTIONS.md`
|
||||
- 次: Phase 285(design-first)Box lifecycle SSOT(`docs/development/current/main/phases/phase-285/README.md`)
|
||||
- 次の次: Phase 286(design-first)JoinIR line absorption(`docs/development/current/main/phases/phase-286/README.md`)
|
||||
**次の候補**:
|
||||
1. **Phase 288.2+** (REPL UX improvements): Multi-line input, syntax highlighting, history
|
||||
2. **Phase 284** (design-first): Return as ExitKind SSOT
|
||||
- 入口: `docs/development/current/main/phases/phase-284/README.md`
|
||||
- 手順: `docs/development/current/main/phases/phase-284/P0-INSTRUCTIONS.md`
|
||||
3. **JoinIR/slot improvements**: Phase 285/286 継続
|
||||
- Phase 285: Box lifecycle SSOT
|
||||
- Phase 286: JoinIR line absorption
|
||||
|
||||
## Recently Completed
|
||||
|
||||
### 2025-12-25: Phase 288.1(REPL Session Persistence + Auto-Display)
|
||||
|
||||
- ✅ **Phase 288.1完了**: REPL variable persistence + expression auto-display
|
||||
- 詳細: `docs/development/current/main/phases/phase-288/README.md`
|
||||
- 実装方式: AST Rewrite + ExternCall Bridge
|
||||
- 達成内容:
|
||||
- ✅ AST Rewriter 実装(~430行、`src/runner/repl/ast_rewriter.rs`)
|
||||
- ✅ __repl.get/set ExternCall handlers 実装
|
||||
- ✅ Rc<RefCell<ReplSessionBox>> session sharing
|
||||
- ✅ Expression auto-display + `_` variable
|
||||
- ✅ Fail-fast undefined variable errors
|
||||
- 検証結果:
|
||||
- ✅ Variable persistence: `x = 42` then `print(x)` → `42`
|
||||
- ✅ Expression display: `1 + 1` → `2`
|
||||
- ✅ `_` variable: `10 * 2` → `20`, then `_` → `20`
|
||||
- ✅ Session reset: `.reset` clears all variables
|
||||
- ✅ 154/154 smoke tests PASS (no regressions)
|
||||
- Files: 8 files, +592 lines (REPL-isolated)
|
||||
|
||||
### 2025-12-24: Phase 285LLVM-1.3(LLVM InstanceBox Field Access)
|
||||
|
||||
- ✅ **Phase 285LLVM-1.3完了**: InstanceBox field access (getField/setField) implementation
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# Phase 288: REPL mode (design-first, file-mode unaffected)
|
||||
|
||||
Status: ✅ P0–P3 complete (2025-12-25) / ⏳ 288.1 next
|
||||
Status: ✅ Phase 288.1 complete (2025-12-25)
|
||||
|
||||
Goal: Add an interactive REPL for Nyash while keeping file mode semantics unchanged and keeping the language SSOT stable.
|
||||
|
||||
@ -22,12 +22,68 @@ SSOT:
|
||||
- ✅ **P3 (UX)**: print() 出力表示、Main box wrapper(VM entry point 修正)、.reset 実装
|
||||
- ✅ **Box化**: `src/runner/repl/` モジュール分離(ReplRunnerBox)、runner/mod.rs -118行 (commit: 3445ef7a7)
|
||||
|
||||
## Next (Phase 288.1)
|
||||
## Completed (Phase 288.1) - Session Persistence + Auto-Display
|
||||
|
||||
The MVP intentionally deferred these:
|
||||
✅ **AST Rewriter** (~430 lines, `src/runner/repl/ast_rewriter.rs`):
|
||||
- Transforms undeclared variables: `x` → `__repl.get("x")`
|
||||
- Transforms assignments: `x = 42` → `__repl.set("x", 42)`
|
||||
- Respects `local` declarations, reserved names (`me`, `true`, `false`, `null`)
|
||||
- Special handling: skips nested scopes, Main wrapper
|
||||
|
||||
- Session variable **persistence across lines** (bridge session → compilation/runtime)
|
||||
- Expression auto-display + `_` last-value binding
|
||||
✅ **ExternCall Bridge**:
|
||||
- MIR builder: `__repl.get/set` → `ExternCall` lowering (`src/mir/builder/calls/build.rs` +41 lines)
|
||||
- VM handler: `ExternCall("__repl", "get"/"set")` implementation (`src/backend/mir_interpreter/handlers/externals.rs` +54 lines)
|
||||
- Fail-fast undefined variable errors with hints
|
||||
|
||||
✅ **Session Management**:
|
||||
- `Rc<RefCell<ReplSessionBox>>` pattern for proper persistence
|
||||
- VM receives session via `set_repl_session()` (`src/backend/mir_interpreter/mod.rs` +12 lines)
|
||||
- Session survives across REPL lines
|
||||
|
||||
✅ **Expression Auto-Display**:
|
||||
- Detects pure expressions vs statements (wrapper AST check)
|
||||
- Auto-displays non-Void expression results
|
||||
- Stores displayed values in `_` variable
|
||||
|
||||
✅ **Testing**:
|
||||
- All 154 smoke tests pass (no regressions)
|
||||
- Variable persistence: `x = 42` then `print(x)` → `42`
|
||||
- Expression display: `1 + 1` → `2`
|
||||
- `_` variable: `10 * 2` → `20`, then `_` → `20`
|
||||
- Fail-fast: undefined variables error with hints
|
||||
- Session reset: `.reset` clears all variables
|
||||
|
||||
**Files Modified** (8 files, +592 lines):
|
||||
- `src/runner/repl/ast_rewriter.rs` (NEW, +430 lines)
|
||||
- `src/runner/repl/repl_runner.rs` (+84/-35 lines)
|
||||
- `src/backend/mir_interpreter/handlers/externals.rs` (+54 lines)
|
||||
- `src/mir/builder/calls/build.rs` (+41 lines)
|
||||
- `src/backend/mir_interpreter/mod.rs` (+12 lines)
|
||||
- `src/runner/repl/repl_session.rs` (+11/-9 lines)
|
||||
- `src/runner/repl/mod.rs` (+2 lines)
|
||||
- `src/runner/mod.rs` (+2/-1 lines)
|
||||
|
||||
**Confirmation Commands**:
|
||||
```bash
|
||||
# Variable persistence
|
||||
echo -e 'x = 42\nprint(x)\n.exit' | ./target/release/hakorune --repl
|
||||
|
||||
# Expression auto-display + _
|
||||
echo -e '1 + 1\n_\n.exit' | ./target/release/hakorune --repl
|
||||
|
||||
# Fail-fast undefined
|
||||
echo -e 'print(y)\n.exit' | ./target/release/hakorune --repl
|
||||
|
||||
# Session reset
|
||||
echo -e 'x = 1\n.reset\nprint(x)\n.exit' | ./target/release/hakorune --repl
|
||||
|
||||
# Regression test
|
||||
./tools/smokes/v2/run.sh --profile quick # 154/154 PASS
|
||||
```
|
||||
|
||||
## Next
|
||||
|
||||
Further UX improvements (deferred):
|
||||
- Multi-line input handling (continuations)
|
||||
|
||||
Entry: `docs/development/current/main/phases/phase-288/P1-INSTRUCTIONS.md`
|
||||
- Syntax highlighting
|
||||
- Command history persistence
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
# REPL Mode (Read–Eval–Print Loop) — Specification (SSOT)
|
||||
|
||||
**Status**: Phase 288 P0–P3 complete (2025-12-25, MVP) / Phase 288.1 next (session persistence + auto-display)
|
||||
**Status**: Phase 288.1 complete (2025-12-25, Session Persistence + Auto-Display)
|
||||
|
||||
## Philosophy: Two Execution Contexts, One Language
|
||||
|
||||
@ -297,25 +297,53 @@ Recommended file-mode errors:
|
||||
|
||||
## 9) Phase 288 MVP Implementation Status
|
||||
|
||||
### Completed (Phase 288 P0-P3) - 2025-12-25
|
||||
### Completed (Phase 288.1) - 2025-12-25
|
||||
|
||||
✅ **CLI Entry** (`--repl` / `-i` flags)
|
||||
✅ **REPL Loop** (`.help`, `.exit`, `.reset` commands)
|
||||
✅ **ReplSessionBox** (VMValue-based session state)
|
||||
✅ **ReplSessionBox** (VMValue-based session state with `Rc<RefCell<>>`)
|
||||
✅ **Implicit Local Binding** (`x = 1` compiles without error)
|
||||
✅ **print() Output** (ExternCall output displays correctly)
|
||||
✅ **`_` Variable** (last value stored in session)
|
||||
✅ **Variable Persistence** (session variables accessible across lines via AST rewrite)
|
||||
✅ **Expression Auto-Display** (`1+1` → `2` automatic output)
|
||||
✅ **`_` Variable** (last displayed value accessible, Void not stored)
|
||||
✅ **Session Reset** (`.reset` command clears state)
|
||||
✅ **Main Box Entry Point** (VM execution fixed)
|
||||
✅ **Fail-Fast Undefined Variables** (clear error messages with hints)
|
||||
|
||||
### Deferred to Phase 288.1+
|
||||
### Implementation Architecture (Phase 288.1)
|
||||
|
||||
⏳ **Variable Persistence** (session variables accessible across lines)
|
||||
⏳ **Expression Auto-Display** (`1+1` → `2` automatic output)
|
||||
⏳ **Complex Expression Detection** (distinguish expression vs statement)
|
||||
⏳ **REPL Variable Injection** (session → compilation context bridge)
|
||||
**AST Rewrite Approach**:
|
||||
```
|
||||
User Input: x = 42
|
||||
↓
|
||||
Parse → AST (static box Main { main() { x = 42 } })
|
||||
↓
|
||||
AST Rewriter (REPL-specific):
|
||||
- Undeclared Variable: x → __repl.get("x")
|
||||
- Undeclared Assignment: x = 42 → __repl.set("x", 42)
|
||||
- Respects: local declarations, reserved names (me/true/false/null)
|
||||
- Skips: nested scopes (function/method bodies), Main wrapper
|
||||
↓
|
||||
Rewritten AST → MIR Compiler
|
||||
↓
|
||||
ExternCall("__repl", "get"/"set", args)
|
||||
↓
|
||||
VM Execution → ReplSessionBox.get/set
|
||||
```
|
||||
|
||||
### Current Behavior (Phase 288 P3 MVP)
|
||||
**Key Components**:
|
||||
- **`src/runner/repl/ast_rewriter.rs`** (~430 lines): AST transformation
|
||||
- **`src/mir/builder/calls/build.rs`**: `__repl.get/set` → ExternCall MIR lowering
|
||||
- **`src/backend/mir_interpreter/handlers/externals.rs`**: ExternCall handlers
|
||||
- **`Rc<RefCell<ReplSessionBox>>`**: Session sharing between REPL runner and VM
|
||||
|
||||
**Expression Detection**:
|
||||
- Checks wrapper AST (`Main.main` body) for single expression node
|
||||
- Pure expressions: Literal, BinaryOp, MethodCall, New, etc.
|
||||
- Statements: Assignment, Local, Print, If, Loop, etc.
|
||||
- Void values not displayed or stored in `_`
|
||||
|
||||
### Current Behavior (Phase 288.1)
|
||||
|
||||
```nyash
|
||||
>>> .help
|
||||
@ -325,33 +353,37 @@ Commands:
|
||||
.help - Show this help
|
||||
|
||||
>>> x = 42
|
||||
>>> # Silent (implicit local creation)
|
||||
>>> # Silent (implicit local creation via __repl.set)
|
||||
|
||||
>>> print("Hello REPL!")
|
||||
Hello REPL! # print() output displays
|
||||
|
||||
>>> print(42 + 1)
|
||||
43 # Arithmetic works
|
||||
>>> print(x)
|
||||
42 # ✅ Variable persistence works!
|
||||
|
||||
>>> 1 + 1
|
||||
>>> # Silent (expression auto-display in Phase 288.1)
|
||||
2 # ✅ Expression auto-display works!
|
||||
|
||||
>>> _
|
||||
2 # ✅ Last displayed value accessible
|
||||
|
||||
>>> print("Hello")
|
||||
Hello # Statements don't auto-display
|
||||
|
||||
>>> .reset
|
||||
Session reset
|
||||
|
||||
>>> print("After reset")
|
||||
After reset # REPL continues after reset
|
||||
>>> print(x)
|
||||
Error: Runtime error: Invalid instruction: Undefined variable: 'x'
|
||||
Hint: Variable not defined. Assign a value first.
|
||||
>>> # ✅ Fail-Fast with clear error
|
||||
```
|
||||
|
||||
**Known Limitations** (Phase 288 MVP):
|
||||
- Variable persistence not yet implemented (`x = 1` then `print(x)` errors)
|
||||
- `_` variable stored but not accessible in user code yet
|
||||
- No expression auto-display (deferred to Phase 288.1)
|
||||
|
||||
**Design Philosophy**: Follow 80/20 rule - deliver working REPL first, polish UX later.
|
||||
**Design Principles**:
|
||||
- **AST Rewrite**: REPL-specific transformation, parser unchanged
|
||||
- **ExternCall Bridge**: Clean VM/REPL separation
|
||||
- **Fail-Fast**: No silent void, clear error messages
|
||||
- **Box-First**: Complete isolation in `src/runner/repl/`
|
||||
|
||||
---
|
||||
|
||||
**Document Version**: Phase 288 P0 (2025-12-25)
|
||||
**Implementation**: Phase 288 P1-P3 (CLI + Session + Basic UX)
|
||||
**Next Phase**: Phase 288.1 (Expression Auto-Display)
|
||||
**Document Version**: Phase 288.1 (2025-12-25)
|
||||
**Implementation**: Complete (CLI + Session + Persistence + Auto-Display)
|
||||
**Next**: Further UX improvements (multiline input, syntax highlighting, etc.)
|
||||
|
||||
Reference in New Issue
Block a user