MIR: lexical scoping + builder vars modules
This commit is contained in:
@ -92,6 +92,12 @@ pub struct MirBuilder {
|
||||
/// Phase 25.1: HashMap → BTreeMap(PHI生成の決定性確保)
|
||||
pub(super) variable_map: BTreeMap<String, ValueId>,
|
||||
|
||||
/// Lexical scope stack for block-scoped `local` declarations.
|
||||
///
|
||||
/// This tracks per-block shadowing so `local x` inside `{...}` restores the
|
||||
/// outer binding when the block ends.
|
||||
lexical_scope_stack: Vec<vars::lexical_scope::LexicalScopeFrame>,
|
||||
|
||||
/// Pending phi functions to be inserted
|
||||
#[allow(dead_code)]
|
||||
pub(super) pending_phis: Vec<(BasicBlockId, ValueId, String)>,
|
||||
@ -266,6 +272,7 @@ impl MirBuilder {
|
||||
block_gen: BasicBlockIdGenerator::new(),
|
||||
compilation_context: None, // 箱理論: デフォルトは従来モード
|
||||
variable_map: BTreeMap::new(), // Phase 25.1: 決定性確保
|
||||
lexical_scope_stack: Vec::new(),
|
||||
pending_phis: Vec::new(),
|
||||
value_origin_newbox: BTreeMap::new(), // Phase 25.1: 決定性確保
|
||||
user_defined_boxes: HashSet::new(),
|
||||
@ -546,37 +553,45 @@ impl MirBuilder {
|
||||
if let Some(&value_id) = self.variable_map.get(&name) {
|
||||
Ok(value_id)
|
||||
} else {
|
||||
// Enhance diagnostics using Using simple registry (Phase 1)
|
||||
let mut msg = format!("Undefined variable: {}", name);
|
||||
|
||||
// Stage-3 keyword diagnostic (local/flow/try/catch/throw)
|
||||
if name == "local" && !crate::config::env::parser_stage3_enabled() {
|
||||
msg.push_str("\nHint: 'local' is a Stage-3 keyword. Prefer NYASH_FEATURES=stage3 (legacy: NYASH_PARSER_STAGE3=1 / HAKO_PARSER_STAGE3=1 for Stage-B).");
|
||||
msg.push_str("\nFor AotPrep verification, use tools/hakorune_emit_mir.sh which sets these automatically.");
|
||||
} else if (name == "flow" || name == "try" || name == "catch" || name == "throw")
|
||||
&& !crate::config::env::parser_stage3_enabled()
|
||||
{
|
||||
msg.push_str(&format!("\nHint: '{}' is a Stage-3 keyword. Prefer NYASH_FEATURES=stage3 (legacy: NYASH_PARSER_STAGE3=1 / HAKO_PARSER_STAGE3=1 for Stage-B).", name));
|
||||
}
|
||||
|
||||
let suggest = crate::using::simple_registry::suggest_using_for_symbol(&name);
|
||||
if !suggest.is_empty() {
|
||||
msg.push_str("\nHint: symbol appears in using module(s): ");
|
||||
msg.push_str(&suggest.join(", "));
|
||||
msg.push_str(
|
||||
"\nConsider adding 'using <module> [as Alias]' or check nyash.toml [using].",
|
||||
);
|
||||
}
|
||||
Err(msg)
|
||||
Err(self.undefined_variable_message(&name))
|
||||
}
|
||||
}
|
||||
|
||||
pub(in crate::mir::builder) fn undefined_variable_message(&self, name: &str) -> String {
|
||||
// Enhance diagnostics using Using simple registry (Phase 1)
|
||||
let mut msg = format!("Undefined variable: {}", name);
|
||||
|
||||
// Stage-3 keyword diagnostic (local/flow/try/catch/throw)
|
||||
if name == "local" && !crate::config::env::parser_stage3_enabled() {
|
||||
msg.push_str("\nHint: 'local' is a Stage-3 keyword. Prefer NYASH_FEATURES=stage3 (legacy: NYASH_PARSER_STAGE3=1 / HAKO_PARSER_STAGE3=1 for Stage-B).");
|
||||
msg.push_str("\nFor AotPrep verification, use tools/hakorune_emit_mir.sh which sets these automatically.");
|
||||
} else if (name == "flow" || name == "try" || name == "catch" || name == "throw")
|
||||
&& !crate::config::env::parser_stage3_enabled()
|
||||
{
|
||||
msg.push_str(&format!("\nHint: '{}' is a Stage-3 keyword. Prefer NYASH_FEATURES=stage3 (legacy: NYASH_PARSER_STAGE3=1 / HAKO_PARSER_STAGE3=1 for Stage-B).", name));
|
||||
}
|
||||
|
||||
let suggest = crate::using::simple_registry::suggest_using_for_symbol(name);
|
||||
if !suggest.is_empty() {
|
||||
msg.push_str("\nHint: symbol appears in using module(s): ");
|
||||
msg.push_str(&suggest.join(", "));
|
||||
msg.push_str("\nConsider adding 'using <module> [as Alias]' or check nyash.toml [using].");
|
||||
}
|
||||
|
||||
msg
|
||||
}
|
||||
|
||||
/// Build assignment
|
||||
pub(super) fn build_assignment(
|
||||
&mut self,
|
||||
var_name: String,
|
||||
value: ASTNode,
|
||||
) -> Result<ValueId, String> {
|
||||
// SSOT (LANGUAGE_REFERENCE_2025 / syntax-cheatsheet):
|
||||
// - Assignment to an undeclared name is an error.
|
||||
// - Use `local name = ...` (or `local name; name = ...`) to declare.
|
||||
vars::assignment_resolver::AssignmentResolverBox::ensure_declared(self, &var_name)?;
|
||||
|
||||
let value_id = self.build_expression(value)?;
|
||||
|
||||
// Step 5-5-E: FIX variable map corruption bug
|
||||
|
||||
Reference in New Issue
Block a user