diff --git a/CLAUDE.md b/CLAUDE.md index 2cd0dfbc..d0ee8a18 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -276,16 +276,18 @@ NYASH_DISABLE_PLUGINS=1 ./target/release/nyash program.nyash NYASH_LLVM_USE_HARNESS=1 ./target/release/nyash program.nyash ``` -## 📝 Update (2025-09-23) 🚀 フェーズM+M.2完全達成!PHI統一革命完了 -- ✅ **フェーズM.2完全達成!** JSON v0 Bridge層クリーンアップ完了でPHI完全統一実現 -- ✅ **8箇所のno_phi分岐完全削除!** try_catch(3)、ternary(1)、peek(1)、loop_(2)、expr(1) -- ✅ **strip_phi_functions()削除!** 40行の複雑なPHI→edge-copy後処理撤廃 -- ✅ **config::env::mir_no_phi()大幅簡略化!** 40行→8行、phi-legacy依存完全除去 -- ✅ **未使用コード完全削除!** PHI_ON_GATED_WARNED static、mir_no_phiフィールド等 -- 🔧 **安定性完全確認!** cargo check成功、基本・複雑PHIテスト両方正常動作 -- 📊 **圧縮効果絶大!** フェーズM+M.2で推定500行超削減達成 -- 🎯 **Phase 15準備完了**: MIR層PHI統一により80k→20k行圧縮の主要基盤完成 -- 🚀 **次段階**: collect_prints動作確認→JSON v0 Bridge最終統合→Phase 15完遂 +## 📝 Update (2025-09-23) ✅ Step 1完了!peek→match統一 Step 2開始 +- ✅ **フェーズM+M.2完全達成!** PHI統一革命でcollect_prints問題根本解決 +- ✅ **Step 1完全達成!** match式オブジェクトリテラル判定修正完了 + - **修正完了**: `src/parser/expr/match_expr.rs` の `is_object_literal()` メソッド追加 + - **副作用修正**: `match_token()` → `current_token()` で副作用除去 + - **動作確認**: 単行match式 + オブジェクトリテラル ✅ 完全動作 + - **発見**: 複数行パース未対応(後回し決定) +- 🚀 **Step 2開始準備!** peek→match完全統一でアーキテクチャクリーンアップ + - **対象ファイル**: `json_v0_bridge/ast.rs`, `lowering/peek.rs` → `match_expr.rs` + - **統一効果**: AI理解向上・ドキュメント整合性・保守性向上・ソースコード美化 + - **作業順序**: claude.md更新→todo調整→commit→peek構造体→match構造体完全移行 +- 🎯 **アーキテクチャ美化**: ややこしいpeek/match混在状況の完全解消へ ## 📝 Update (2025-09-22) 🎯 Phase 15 JITアーカイブ完了&デバッグ大進展! - ✅ **JIT/Craneliftアーカイブ完了!** Phase 15集中開発のため全JIT機能を安全にアーカイブ diff --git a/src/parser/expr/match_expr.rs b/src/parser/expr/match_expr.rs index 5d0eecd4..def8e4d0 100644 --- a/src/parser/expr/match_expr.rs +++ b/src/parser/expr/match_expr.rs @@ -48,19 +48,24 @@ impl NyashParser { } self.consume(TokenType::FatArrow)?; let expr = if self.match_token(&TokenType::LBRACE) { - // ブロックを式として扱う(最後の文の値が返る) - self.advance(); // consume '{' - let mut stmts: Vec = Vec::new(); - while !self.match_token(&TokenType::RBRACE) && !self.is_at_end() { - self.skip_newlines(); - if !self.match_token(&TokenType::RBRACE) { - stmts.push(self.parse_statement()?); + if self.is_object_literal() { + // オブジェクトリテラルとして処理 + self.parse_expression()? + } else { + // ブロックを式として扱う(最後の文の値が返る) + self.advance(); // consume '{' + let mut stmts: Vec = Vec::new(); + while !self.match_token(&TokenType::RBRACE) && !self.is_at_end() { + self.skip_newlines(); + if !self.match_token(&TokenType::RBRACE) { + stmts.push(self.parse_statement()?); + } + } + self.consume(TokenType::RBRACE)?; + ASTNode::Program { + statements: stmts, + span: Span::unknown(), } - } - self.consume(TokenType::RBRACE)?; - ASTNode::Program { - statements: stmts, - span: Span::unknown(), } } else { // 値アームは通常の式全体を受理 @@ -104,17 +109,22 @@ impl NyashParser { } else { None }; self.consume(TokenType::FatArrow)?; let body = if self.match_token(&TokenType::LBRACE) { - self.advance(); // consume '{' - let mut stmts: Vec = Vec::new(); - while !self.match_token(&TokenType::RBRACE) && !self.is_at_end() { - self.skip_newlines(); - if !self.match_token(&TokenType::RBRACE) { - let st = self.parse_statement()?; - stmts.push(st); + if self.is_object_literal() { + // オブジェクトリテラルとして処理 + self.parse_expression()? + } else { + self.advance(); // consume '{' + let mut stmts: Vec = Vec::new(); + while !self.match_token(&TokenType::RBRACE) && !self.is_at_end() { + self.skip_newlines(); + if !self.match_token(&TokenType::RBRACE) { + let st = self.parse_statement()?; + stmts.push(st); + } } + self.consume(TokenType::RBRACE)?; + ASTNode::Program { statements: stmts, span: Span::unknown() } } - self.consume(TokenType::RBRACE)?; - ASTNode::Program { statements: stmts, span: Span::unknown() } } else { // 値アームは通常の式全体を受理 self.parse_expression()? @@ -144,17 +154,22 @@ impl NyashParser { } else { None }; self.consume(TokenType::FatArrow)?; let expr = if self.match_token(&TokenType::LBRACE) { - self.advance(); // consume '{' - let mut stmts: Vec = Vec::new(); - while !self.match_token(&TokenType::RBRACE) && !self.is_at_end() { - self.skip_newlines(); - if !self.match_token(&TokenType::RBRACE) { - let st = self.parse_statement()?; - stmts.push(st); + if self.is_object_literal() { + // オブジェクトリテラルとして処理 + self.parse_expression()? + } else { + self.advance(); // consume '{' + let mut stmts: Vec = Vec::new(); + while !self.match_token(&TokenType::RBRACE) && !self.is_at_end() { + self.skip_newlines(); + if !self.match_token(&TokenType::RBRACE) { + let st = self.parse_statement()?; + stmts.push(st); + } } + self.consume(TokenType::RBRACE)?; + ASTNode::Program { statements: stmts, span: Span::unknown() } } - self.consume(TokenType::RBRACE)?; - ASTNode::Program { statements: stmts, span: Span::unknown() } } else { // 値アームは通常の式全体を受理 self.parse_expression()? @@ -309,6 +324,20 @@ impl NyashParser { }) } + /// オブジェクトリテラル判定: { IDENTIFIER : または { STRING : の場合はtrue + fn is_object_literal(&self) -> bool { + // 副作用を避けるためcurrent_token()を使用 + if !matches!(self.current_token().token_type, TokenType::LBRACE) { + return false; + } + match self.peek_token() { + TokenType::IDENTIFIER(_) | TokenType::STRING(_) => { + matches!(self.peek_nth_token(2), TokenType::COLON) + } + _ => false + } + } + // match 用の最小リテラルパーサ(式は受け付けない) fn lit_only_for_match(&mut self) -> Result { match &self.current_token().token_type {