selfhost(pyvm): MiniVmPrints – prefer JSON route early-return (ok==1) to avoid fallback loops; keep default behavior unchanged elsewhere

This commit is contained in:
Selfhosting Dev
2025-09-22 07:54:25 +09:00
parent 27568eb4a6
commit 8e4cadd349
348 changed files with 9981 additions and 30074 deletions

View File

@ -176,12 +176,39 @@ impl NyashParser {
break;
}
// 🔥 static { } ブロックの処理
// 🔥 static 初期化子の処理
// Gate: NYASH_PARSER_STATIC_INIT_STRICT=1 のとき、
// - 直後が '{' の場合のみ static 初期化子として扱う
// - 直後が 'box' or 'function' の場合は、トップレベル宣言の開始とみなし、この box 本体を閉じる
// 既定ゲートOFFは従来挙動常に static { ... } を期待)
if self.match_token(&TokenType::STATIC) {
self.advance(); // consume 'static'
let static_body = self.parse_block_statements()?;
static_init = Some(static_body);
continue;
let strict = std::env::var("NYASH_PARSER_STATIC_INIT_STRICT").ok().as_deref() == Some("1");
if strict {
match self.peek_token() {
TokenType::LBRACE => {
self.advance(); // consume 'static'
let static_body = self.parse_block_statements()?;
static_init = Some(static_body);
continue;
}
TokenType::BOX | TokenType::FUNCTION => {
// トップレベルの `static box|function` が続くシーム: ここで box を閉じる
break;
}
_ => {
// 不明な形は従来通り initializer として解釈(互換重視)
self.advance();
let static_body = self.parse_block_statements()?;
static_init = Some(static_body);
continue;
}
}
} else {
self.advance(); // consume 'static'
let static_body = self.parse_block_statements()?;
static_init = Some(static_body);
continue;
}
}
// initブロックの処理

View File

@ -175,7 +175,50 @@ impl NyashParser {
input: impl Into<String>,
fuel: Option<usize>,
) -> Result<ASTNode, ParseError> {
let mut tokenizer = crate::tokenizer::NyashTokenizer::new(input);
// Normalize logical operators '||'/'&&' to 'or'/'and' before tokenization (outside strings/comments)
fn normalize_logical_ops(src: &str) -> String {
let mut out = String::with_capacity(src.len());
let mut it = src.chars().peekable();
let mut in_str = false;
let mut in_line = false;
let mut in_block = false;
while let Some(c) = it.next() {
if in_line {
out.push(c);
if c == '\n' { in_line = false; }
continue;
}
if in_block {
out.push(c);
if c == '*' && matches!(it.peek(), Some('/')) { out.push('/'); it.next(); in_block = false; }
continue;
}
if in_str {
out.push(c);
if c == '\\' { if let Some(nc) = it.next() { out.push(nc); } continue; }
if c == '"' { in_str = false; }
continue;
}
match c {
'"' => { in_str = true; out.push(c); }
'/' => {
match it.peek() { Some('/') => { out.push('/'); out.push('/'); it.next(); in_line = true; }, Some('*') => { out.push('/'); out.push('*'); it.next(); in_block = true; }, _ => out.push('/') }
}
'#' => { in_line = true; out.push('#'); }
'|' => {
if matches!(it.peek(), Some('|')) { out.push_str(" or "); it.next(); } else if matches!(it.peek(), Some('>')) { out.push('|'); out.push('>'); it.next(); } else { out.push('|'); }
}
'&' => {
if matches!(it.peek(), Some('&')) { out.push_str(" and "); it.next(); } else { out.push('&'); }
}
_ => out.push(c),
}
}
out
}
let input_s: String = input.into();
let pre = normalize_logical_ops(&input_s);
let mut tokenizer = crate::tokenizer::NyashTokenizer::new(pre);
let tokens = tokenizer.tokenize()?;
let mut parser = Self::new(tokens);