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:
@ -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 {
|
||||
|
||||
@ -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 {
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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(),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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 {
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user