chore: Phase 25.1 完了 - LoopForm v2/Stage1 CLI/環境変数削減 + Phase 26-D からの変更

Phase 25.1 完了成果:
-  LoopForm v2 テスト・ドキュメント・コメント完備
  - 4ケース(A/B/C/D)完全テストカバレッジ
  - 最小再現ケース作成(SSAバグ調査用)
  - SSOT文書作成(loopform_ssot.md)
  - 全ソースに [LoopForm] コメントタグ追加

-  Stage-1 CLI デバッグ環境構築
  - stage1_cli.hako 実装
  - stage1_bridge.rs ブリッジ実装
  - デバッグツール作成(stage1_debug.sh/stage1_minimal.sh)
  - アーキテクチャ改善提案文書

-  環境変数削減計画策定
  - 25変数の完全調査・分類
  - 6段階削減ロードマップ(25→5、80%削減)
  - 即時削除可能変数特定(NYASH_CONFIG/NYASH_DEBUG)

Phase 26-D からの累積変更:
- PHI実装改善(ExitPhiBuilder/HeaderPhiBuilder等)
- MIRビルダーリファクタリング
- 型伝播・最適化パス改善
- その他約300ファイルの累積変更

🎯 技術的成果:
- SSAバグ根本原因特定(条件分岐内loop変数変更)
- Region+next_iパターン適用完了(UsingCollectorBox等)
- LoopFormパターン文書化・テスト化完了
- セルフホスティング基盤強化

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: ChatGPT <noreply@openai.com>
Co-Authored-By: Task Assistant <task@anthropic.com>
This commit is contained in:
nyash-codex
2025-11-21 06:25:17 +09:00
parent baf028a94f
commit f9d100ce01
366 changed files with 14322 additions and 5236 deletions

View File

@ -9,9 +9,9 @@
*/
use crate::ast::{ASTNode, Span};
use crate::parser::{NyashParser, ParseError};
use crate::parser::common::ParserUtils;
use crate::parser::cursor::TokenCursor;
use crate::parser::{NyashParser, ParseError};
use crate::tokenizer::TokenType;
impl NyashParser {

View File

@ -6,8 +6,8 @@
*/
use crate::ast::ASTNode;
use crate::parser::{NyashParser, ParseError};
use crate::parser::common::ParserUtils;
use crate::parser::{NyashParser, ParseError};
use crate::tokenizer::TokenType;
impl NyashParser {
@ -17,7 +17,9 @@ impl NyashParser {
TokenType::BOX => crate::parser::declarations::box_def::parse_box_declaration(self),
TokenType::FLOW => crate::parser::declarations::box_def::parse_box_declaration(self), // flow is syntactic sugar for static box
TokenType::IMPORT => self.parse_import(),
TokenType::INTERFACE => crate::parser::declarations::box_def::parse_interface_box_declaration(self),
TokenType::INTERFACE => {
crate::parser::declarations::box_def::parse_interface_box_declaration(self)
}
TokenType::GLOBAL => self.parse_global_var(),
TokenType::FUNCTION => self.parse_function_declaration(),
TokenType::STATIC => self.parse_static_declaration(),
@ -28,4 +30,4 @@ impl NyashParser {
}),
}
}
}
}

View File

@ -8,8 +8,8 @@
*/
use crate::ast::{ASTNode, CatchClause, Span};
use crate::parser::{NyashParser, ParseError};
use crate::parser::common::ParserUtils;
use crate::parser::{NyashParser, ParseError};
use crate::tokenizer::TokenType;
impl NyashParser {
@ -76,7 +76,9 @@ impl NyashParser {
}
/// Parse catch parameter: (ExceptionType varName) or (varName) or ()
pub(crate) fn parse_catch_param(&mut self) -> Result<(Option<String>, Option<String>), ParseError> {
pub(crate) fn parse_catch_param(
&mut self,
) -> Result<(Option<String>, Option<String>), ParseError> {
match &self.current_token().token_type {
TokenType::IDENTIFIER(first) => {
let first_str = first.clone();
@ -121,4 +123,4 @@ impl NyashParser {
line: self.current_token().line,
})
}
}
}

View File

@ -5,9 +5,9 @@
*/
use crate::ast::ASTNode;
use crate::parser::{NyashParser, ParseError};
use crate::parser::common::ParserUtils;
use crate::parser::cursor::TokenCursor;
use crate::parser::{NyashParser, ParseError};
use crate::tokenizer::TokenType;
/// Check if token cursor is enabled
@ -16,7 +16,6 @@ pub(super) fn cursor_enabled() -> bool {
}
impl NyashParser {
/// Thin adapter: when Cursor route is enabled, align statement start position
/// by letting TokenCursor apply its statement-mode newline policy
pub(super) fn with_stmt_cursor<F>(&mut self, f: F) -> Result<ASTNode, ParseError>

View File

@ -7,9 +7,9 @@
*/
use crate::ast::{ASTNode, Span};
use crate::parser::{NyashParser, ParseError};
use crate::parser::common::ParserUtils;
use crate::parser::cursor::TokenCursor;
use crate::parser::{NyashParser, ParseError};
use crate::tokenizer::TokenType;
impl NyashParser {
@ -71,4 +71,4 @@ impl NyashParser {
span: Span::unknown(),
})
}
}
}

View File

@ -27,8 +27,8 @@ pub mod exceptions;
pub mod modules;
use crate::ast::{ASTNode, CatchClause, Span};
use crate::parser::{NyashParser, ParseError};
use crate::parser::common::ParserUtils;
use crate::parser::{NyashParser, ParseError};
use crate::tokenizer::TokenType;
impl NyashParser {
@ -94,14 +94,20 @@ impl NyashParser {
// Critical: Skip any leading NEWLINE tokens immediately after '{'
// This ensures the first statement starts at the correct position
while self.match_token(&TokenType::NEWLINE) { self.advance(); }
while self.match_token(&TokenType::NEWLINE) {
self.advance();
}
let mut statements = Vec::new();
// Be tolerant to blank lines within blocks: skip NEWLINE tokens between statements
while !self.is_at_end() {
while self.match_token(&TokenType::NEWLINE) { self.advance(); }
if self.match_token(&TokenType::RBRACE) { break; }
while self.match_token(&TokenType::NEWLINE) {
self.advance();
}
if self.match_token(&TokenType::RBRACE) {
break;
}
statements.push(self.parse_statement()?);
}
if trace_blocks {
@ -137,21 +143,33 @@ impl NyashParser {
TokenType::IDENTIFIER(_) => {
// Expect '(' after optional NEWLINE
let mut k = 1usize;
while matches!(this.peek_nth_token(k), TokenType::NEWLINE) { k += 1; }
if !matches!(this.peek_nth_token(k), TokenType::LPAREN) { return false; }
while matches!(this.peek_nth_token(k), TokenType::NEWLINE) {
k += 1;
}
if !matches!(this.peek_nth_token(k), TokenType::LPAREN) {
return false;
}
// Walk to matching ')'
k += 1; // after '('
let mut depth: i32 = 1;
while !matches!(this.peek_nth_token(k), TokenType::EOF) {
match this.peek_nth_token(k) {
TokenType::LPAREN => depth += 1,
TokenType::RPAREN => { depth -= 1; if depth == 0 { k += 1; break; } },
TokenType::RPAREN => {
depth -= 1;
if depth == 0 {
k += 1;
break;
}
}
_ => {}
}
k += 1;
}
// Allow NEWLINE(s) between ')' and '{'
while matches!(this.peek_nth_token(k), TokenType::NEWLINE) { k += 1; }
while matches!(this.peek_nth_token(k), TokenType::NEWLINE) {
k += 1;
}
matches!(this.peek_nth_token(k), TokenType::LBRACE)
}
_ => false,
@ -160,14 +178,22 @@ impl NyashParser {
while !self.is_at_end() {
// Skip blank lines at method body top-level
while self.match_token(&TokenType::NEWLINE) { self.advance(); }
while self.match_token(&TokenType::NEWLINE) {
self.advance();
}
// Stop at end of current method body
if self.match_token(&TokenType::RBRACE) { break; }
if self.match_token(&TokenType::RBRACE) {
break;
}
// Optional seam guard: if the upcoming tokens form a method head
// like `ident '(' ... ')' NEWLINE* '{'`, bail out so the caller
// (static box member parser) can handle it as a declaration, not
// as a function call expression inside this body.
if std::env::var("NYASH_PARSER_METHOD_BODY_STRICT").ok().as_deref() == Some("1") {
if std::env::var("NYASH_PARSER_METHOD_BODY_STRICT")
.ok()
.as_deref()
== Some("1")
{
if looks_like_method_head(self) {
break;
}

View File

@ -8,8 +8,8 @@
*/
use crate::ast::{ASTNode, Span};
use crate::parser::{NyashParser, ParseError};
use crate::parser::common::ParserUtils;
use crate::parser::{NyashParser, ParseError};
use crate::tokenizer::TokenType;
impl NyashParser {
@ -123,7 +123,10 @@ impl NyashParser {
}
}
Ok(ASTNode::UsingStatement { namespace_name: namespace, span: Span::unknown() })
Ok(ASTNode::UsingStatement {
namespace_name: namespace,
span: Span::unknown(),
})
}
/// Parse from statement: from Parent.method(args)

View File

@ -8,9 +8,9 @@
*/
use crate::ast::{ASTNode, Span};
use crate::parser::{NyashParser, ParseError};
use crate::parser::common::ParserUtils;
use crate::parser::cursor::TokenCursor;
use crate::parser::{NyashParser, ParseError};
use crate::tokenizer::TokenType;
impl NyashParser {
@ -29,10 +29,14 @@ impl NyashParser {
/// Parse local variable declaration: local var1, var2, var3 or local x = 10
pub(super) fn parse_local(&mut self) -> Result<ASTNode, ParseError> {
let debug_parse_local = std::env::var("NYASH_DEBUG_PARSE_LOCAL").ok().as_deref() == Some("1");
let debug_parse_local =
std::env::var("NYASH_DEBUG_PARSE_LOCAL").ok().as_deref() == Some("1");
if debug_parse_local {
eprintln!("[parse_local] entry: current_token={:?} at line {}",
self.current_token().token_type, self.current_token().line);
eprintln!(
"[parse_local] entry: current_token={:?} at line {}",
self.current_token().token_type,
self.current_token().line
);
}
// Always skip leading NEWLINEs before consuming 'local' keyword
@ -54,8 +58,11 @@ impl NyashParser {
}
if debug_parse_local {
eprintln!("[parse_local] after advance: current_token={:?} at line {}",
self.current_token().token_type, self.current_token().line);
eprintln!(
"[parse_local] after advance: current_token={:?} at line {}",
self.current_token().token_type,
self.current_token().line
);
}
let mut names = Vec::new();
@ -107,8 +114,11 @@ impl NyashParser {
} else {
// Enhanced error message for debugging
if debug_parse_local {
eprintln!("[parse_local] ERROR: Expected IDENTIFIER, found {:?} at line {}",
self.current_token().token_type, self.current_token().line);
eprintln!(
"[parse_local] ERROR: Expected IDENTIFIER, found {:?} at line {}",
self.current_token().token_type,
self.current_token().line
);
eprintln!("[parse_local] ERROR: Previous 3 tokens:");
for i in 1..=3 {
if self.current >= i {
@ -168,4 +178,4 @@ impl NyashParser {
})
}
}
}
}