diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 724e3054..cc0a1f74 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -156,7 +156,10 @@ impl NyashParser { } /// 文字列からパース (トークナイズ + パース) + /// Note: Reads environment variables (NYASH_PARSER_STAGE3, etc.) for using-chain parsing pub fn parse_from_string(input: impl Into) -> Result { + // Ensure Stage-3 features are enabled when parsing using-chain files + // if the parent process has NYASH_PARSER_STAGE3=1 set Self::parse_from_string_with_fuel(input, Some(100_000)) } diff --git a/src/runner/modes/common_util/resolve/strip.rs b/src/runner/modes/common_util/resolve/strip.rs index b059740e..4da67e55 100644 --- a/src/runner/modes/common_util/resolve/strip.rs +++ b/src/runner/modes/common_util/resolve/strip.rs @@ -443,18 +443,59 @@ pub fn parse_preludes_to_asts( runner: &NyashRunner, prelude_paths: &[String], ) -> Result, String> { + let debug = std::env::var("NYASH_STRIP_DEBUG").ok().as_deref() == Some("1"); + if debug { + eprintln!("[strip-debug] parse_preludes_to_asts: {} files total", prelude_paths.len()); + for (idx, p) in prelude_paths.iter().enumerate() { + eprintln!("[strip-debug] [{}] {}", idx, p); + } + } let mut out: Vec = Vec::with_capacity(prelude_paths.len()); - for prelude_path in prelude_paths { + for (idx, prelude_path) in prelude_paths.iter().enumerate() { + if debug { + eprintln!("[strip-debug] [{}/{}] Processing: {}", idx + 1, prelude_paths.len(), prelude_path); + } let src = std::fs::read_to_string(prelude_path) .map_err(|e| format!("using: error reading {}: {}", prelude_path, e))?; let (clean_src, _nested) = collect_using_and_strip(runner, &src, prelude_path)?; - match crate::parser::NyashParser::parse_from_string(&clean_src) { - Ok(ast) => out.push(ast), - Err(e) => return Err(format!( - "Parse error in using prelude {}: {}", - prelude_path, e - )), + + // Debug: dump clean_src if NYASH_STRIP_DEBUG=1 + if debug { + eprintln!("[strip-debug] [{}/{}] About to parse: {}", idx + 1, prelude_paths.len(), prelude_path); + eprintln!("[strip-debug] clean_src first 500 chars:\n{}\n---", + &clean_src.chars().take(500).collect::()); } + + match crate::parser::NyashParser::parse_from_string(&clean_src) { + Ok(ast) => { + if debug { + eprintln!("[strip-debug] [{}/{}] ✅ Parse SUCCESS: {}", idx + 1, prelude_paths.len(), prelude_path); + } + out.push(ast) + } + Err(e) => { + // Always output debug info on parse failure if NYASH_STRIP_DEBUG=1 + let debug = std::env::var("NYASH_STRIP_DEBUG").ok().as_deref() == Some("1"); + eprintln!("[strip-debug] Parse FAILED for: {} (debug={})", prelude_path, debug); + if debug { + eprintln!("[strip-debug] Error: {}", e); + let lines: Vec<&str> = clean_src.lines().collect(); + eprintln!("[strip-debug] Total lines: {}", lines.len()); + eprintln!("[strip-debug] Lines 15-25:"); + for (idx, line) in lines.iter().enumerate().skip(14).take(11) { + eprintln!(" {:3}: {}", idx + 1, line); + } + eprintln!("[strip-debug] Full clean_src:\n{}\n---", clean_src); + } + return Err(format!( + "Parse error in using prelude {}: {}", + prelude_path, e + )); + } + } + } + if debug { + eprintln!("[strip-debug] parse_preludes_to_asts: ✅ All {} files parsed successfully", out.len()); } Ok(out) } diff --git a/src/runner/modes/vm.rs b/src/runner/modes/vm.rs index 73ff6a90..8eef5ef9 100644 --- a/src/runner/modes/vm.rs +++ b/src/runner/modes/vm.rs @@ -144,10 +144,24 @@ impl NyashRunner { code_ref = &preexpanded_owned; // Parse to AST + if std::env::var("NYASH_STRIP_DEBUG").ok().as_deref() == Some("1") { + eprintln!("[vm-debug] About to parse main source ({} bytes)", code_ref.len()); + eprintln!("[vm-debug] First 20 lines:"); + for (idx, line) in code_ref.lines().enumerate().take(20) { + eprintln!(" {:3}: {}", idx + 1, line); + } + } let main_ast = match NyashParser::parse_from_string(code_ref) { Ok(ast) => ast, Err(e) => { eprintln!("❌ Parse error: {}", e); + if std::env::var("NYASH_STRIP_DEBUG").ok().as_deref() == Some("1") { + eprintln!("[vm-debug] Parse failed for main source"); + eprintln!("[vm-debug] Line 15-25 of source:"); + for (idx, line) in code_ref.lines().enumerate().skip(14).take(11) { + eprintln!(" {:3}: {}", idx + 1, line); + } + } process::exit(1); } }; diff --git a/src/tokenizer/lex_ident.rs b/src/tokenizer/lex_ident.rs index 1244dd12..2ff3bccb 100644 --- a/src/tokenizer/lex_ident.rs +++ b/src/tokenizer/lex_ident.rs @@ -61,6 +61,39 @@ impl NyashTokenizer { _ => TokenType::IDENTIFIER(identifier.clone()), }; + // Stage-3 gate: LOCAL/TRY/CATCH/THROW require NYASH_PARSER_STAGE3=1 + let stage3_enabled = crate::config::env::parser_stage3(); + if !stage3_enabled { + let is_stage3 = matches!( + tok, + TokenType::LOCAL + | TokenType::TRY + | TokenType::CATCH + | TokenType::THROW + ); + if is_stage3 { + if std::env::var("NYASH_TOK_TRACE").ok().as_deref() == Some("1") { + eprintln!("[tok-stage3] Degrading {:?} to IDENTIFIER (NYASH_PARSER_STAGE3={})", + tok, stage3_enabled); + } + tok = TokenType::IDENTIFIER(identifier.clone()); + } + } else { + if std::env::var("NYASH_TOK_TRACE").ok().as_deref() == Some("1") { + let is_stage3 = matches!( + tok, + TokenType::LOCAL + | TokenType::TRY + | TokenType::CATCH + | TokenType::THROW + ); + if is_stage3 { + eprintln!("[tok-stage3] Keeping {:?} as keyword (NYASH_PARSER_STAGE3={})", + tok, stage3_enabled); + } + } + } + // 12.7 Strict mode: fallback extended keywords to IDENTIFIER if Self::strict_12_7() { let is_extended = matches!(