diff --git a/src/config/env.rs b/src/config/env.rs index 1049dcd7..56d9687d 100644 --- a/src/config/env.rs +++ b/src/config/env.rs @@ -2,6 +2,19 @@ //! //! Consolidates NYASH_* environment variables across subsystems and //! optionally applies overrides from `nyash.toml`. +//! +//! # Modular Organization +//! +//! Environment flags are now organized into focused Box modules: +//! - `joinir_flags` - JoinIR-related flags (30+ functions) +//! - `mir_flags` - MIR-related flags (20+ functions) +//! - `vm_backend_flags` - VM/Backend flags (15+ functions) +//! - `parser_flags` - Parser flags (10+ functions) +//! - `using_flags` - Using/namespace flags (10+ functions) +//! - `verification_flags` - Verification flags (8+ functions) +//! - `selfhost_flags` - Selfhost compiler flags (10+ functions) +//! +//! All functions are re-exported at the top level for backward compatibility. mod catalog; pub mod dump; @@ -10,12 +23,31 @@ pub mod dump; pub mod joinir_dev; pub mod stage1; +// New modular organization +mod joinir_flags; +mod mir_flags; +mod vm_backend_flags; +mod parser_flags; +mod using_flags; +mod verification_flags; +mod selfhost_flags; + pub use catalog::{env_vars, AppliesTo, EnvVarMeta}; pub use dump::*; // Phase 124: hako_check exports removed (JoinIR-only consolidation) // pub use hako_check::*; pub use joinir_dev::*; pub use stage1::*; + +// Backward-compatible re-exports (NO BREAKING CHANGES!) +pub use joinir_flags::*; +pub use mir_flags::*; +pub use vm_backend_flags::*; +pub use parser_flags::*; +pub use using_flags::*; +pub use verification_flags::*; +pub use selfhost_flags::*; + use std::collections::BTreeMap; #[derive(Debug, Clone, Default)] @@ -47,12 +79,10 @@ impl NyashEnv { // Global current env config (thread-safe) use once_cell::sync::OnceCell; use std::collections::HashSet; -use std::sync::{Mutex, Once, RwLock}; +use std::sync::Mutex; -static GLOBAL_ENV: OnceCell> = OnceCell::new(); +static GLOBAL_ENV: OnceCell> = OnceCell::new(); static WARNED_ALIASES: OnceCell>> = OnceCell::new(); -static WARNED_JOINIR_CORE_OFF: Once = Once::new(); -// フェーズM.2: PHI_ON_GATED_WARNED削除(phi-legacy簡略化により不要) pub fn current() -> NyashEnv { if let Some(lock) = GLOBAL_ENV.get() { @@ -70,7 +100,7 @@ pub fn set_current(cfg: NyashEnv) { return; } } - let _ = GLOBAL_ENV.set(RwLock::new(cfg)); + let _ = GLOBAL_ENV.set(std::sync::RwLock::new(cfg)); } /// Load overrides from nyash.toml `[env]` table and apply them to process env. @@ -122,56 +152,6 @@ pub fn bootstrap_from_toml_env() { set_current(cur); } -/// Get await maximum milliseconds, centralized here for consistency. -pub fn await_max_ms() -> u64 { - std::env::var("NYASH_AWAIT_MAX_MS") - .ok() - .and_then(|s| s.parse().ok()) - .unwrap_or(5000) -} - -// ---- MIR PHI / PHI-less (edge-copy) mode ---- -/// Enable MIR PHI non-generation for Bridge compatibility mode only. -/// フェーズM.2: MirBuilder/LoopBuilderでPHI統一済み、Bridge層の互換性制御のみ -/// Default: PHI-ON (Phase 15 direction), override with NYASH_MIR_NO_PHI=1 -pub fn mir_no_phi() -> bool { - env_bool("NYASH_MIR_NO_PHI") -} - -/// Allow verifier to skip SSA/dominance/merge checks for PHI-less MIR. -pub fn verify_allow_no_phi() -> bool { - std::env::var("NYASH_VERIFY_ALLOW_NO_PHI").ok().as_deref() == Some("1") || mir_no_phi() -} - -/// Enable strict edge-copy policy verification in PHI-off mode. -/// When enabled, merge blocks must receive merged values via predecessor copies only, -/// and the merge block itself must not introduce a self-copy to the merged destination. -pub fn verify_edge_copy_strict() -> bool { - env_bool("NYASH_VERIFY_EDGE_COPY_STRICT") -} - -/// Enforce purity of return blocks: no side-effecting instructions allowed before Return -/// Default: OFF. Enable with NYASH_VERIFY_RET_PURITY=1 in dev/profiling sessions. -pub fn verify_ret_purity() -> bool { - env_bool("NYASH_VERIFY_RET_PURITY") -} - -/// Stage-B/selfhost 専用の dev verify トグル(SSA などの厳格チェックを一時緩和するためのスイッチ) -/// Default: ON(現行挙動)。NYASH_STAGEB_DEV_VERIFY=0 で Stage-B 経路の dev verify をスキップ。 -pub fn stageb_dev_verify_enabled() -> bool { - env_flag("NYASH_STAGEB_DEV_VERIFY").unwrap_or(true) -} - -// ---- LLVM harness toggle (llvmlite) ---- -pub fn llvm_use_harness() -> bool { - // Phase 15: デフォルトON(LLVMバックエンドはPythonハーネス使用) - // NYASH_LLVM_USE_HARNESS=0 で明示的に無効化可能 - match std::env::var("NYASH_LLVM_USE_HARNESS").ok().as_deref() { - Some("0") | Some("false") | Some("off") => false, - _ => true, // デフォルト: ON(ハーネス使用) - } -} - /// Generic boolean env parser: accepts 1/true/on (case-insensitive) as true. pub fn env_bool(key: &str) -> bool { match std::env::var(key).ok() { @@ -194,698 +174,13 @@ pub fn env_bool_default(key: &str, default: bool) -> bool { } } -fn nyash_features_list() -> Option> { - let raw = std::env::var("NYASH_FEATURES").ok()?; - let list: Vec = raw - .split(',') - .filter_map(|s| { - let trimmed = s.trim(); - if trimmed.is_empty() { - None - } else { - Some(trimmed.to_ascii_lowercase()) - } - }) - .collect(); - if list.is_empty() { - None - } else { - Some(list) - } -} - -fn feature_stage3_enabled() -> bool { - if let Some(list) = nyash_features_list() { - for item in list { - let normalized = item.replace(['-', '_'], ""); - if normalized == "stage3" || normalized == "parserstage3" { - return true; - } - } - } - false -} - -/// Global fail-fast policy for runtime fallbacks. -/// Default: ON (true) to prohibit silent/different-route fallbacks in Rust layer. -/// Set NYASH_FAIL_FAST=0 to temporarily allow legacy fallbacks during bring-up. -pub fn fail_fast() -> bool { - env_bool_default("NYASH_FAIL_FAST", true) -} - -// ---- Phase 29/30 JoinIR toggles ---- -/// JoinIR experiment mode. Required for JoinIR-related experimental paths. -/// Set NYASH_JOINIR_EXPERIMENT=1 to enable. -pub fn joinir_experiment_enabled() -> bool { - env_bool("NYASH_JOINIR_EXPERIMENT") -} - -/// JoinIR core policy: **always ON** after LoopBuilder removal. -/// - `NYASH_JOINIR_CORE` is deprecated(0 を指定しても警告して無視する) -/// - JoinIR を OFF にするモードは提供しない(Fail-Fast 原則、フォールバックなし) -pub fn joinir_core_enabled() -> bool { - if let Some(v) = env_flag("NYASH_JOINIR_CORE") { - if !v { - warn_joinir_core_off_ignored(); - } - } - true -} - -fn warn_joinir_core_off_ignored() { - WARNED_JOINIR_CORE_OFF.call_once(|| { - eprintln!( - "[deprecate/env] NYASH_JOINIR_CORE=0 is ignored; JoinIR core is always on (LoopBuilder is removed)" - ); - }); -} - -/// JoinIR VM bridge mode. When enabled with NYASH_JOINIR_EXPERIMENT=1, -/// specific functions can be executed via JoinIR → VM bridge instead of direct MIR → VM. -/// Set NYASH_JOINIR_VM_BRIDGE=1 to enable. -pub fn joinir_vm_bridge_enabled() -> bool { - joinir_core_enabled() && env_bool("NYASH_JOINIR_VM_BRIDGE") -} - -/// JoinIR strict mode: when enabled, JoinIR 対象のフォールバックを禁止する。 -/// 既定OFF。NYASH_JOINIR_STRICT=1 のときのみ有効。 -pub fn joinir_strict_enabled() -> bool { - env_flag("NYASH_JOINIR_STRICT").unwrap_or(false) -} - -/// JoinIR VM bridge debug output. Enables verbose logging of JoinIR→MIR conversion. -/// Set NYASH_JOINIR_VM_BRIDGE_DEBUG=1 to enable. -pub fn joinir_vm_bridge_debug() -> bool { - env_bool("NYASH_JOINIR_VM_BRIDGE_DEBUG") -} - -/// JoinIR LLVM experiment mode. When enabled with NYASH_JOINIR_EXPERIMENT=1, -/// enables experimental JoinIR→MIR'→LLVM path for specific functions (e.g., Main.skip/1). -/// This is a dev-only toggle for testing PHI normalization via JoinIR in the LLVM path. -/// Set NYASH_JOINIR_LLVM_EXPERIMENT=1 to enable. -pub fn joinir_llvm_experiment_enabled() -> bool { - joinir_core_enabled() && env_bool("NYASH_JOINIR_LLVM_EXPERIMENT") -} - -/// Phase 33: JoinIR If Select 実験の有効化 -/// Primary: HAKO_JOINIR_IF_SELECT (Phase 33-8+). -pub fn joinir_if_select_enabled() -> bool { - // Core ON なら既定で有効化(JoinIR 本線化を優先) - if joinir_core_enabled() { - return true; - } - // Primary: HAKO_JOINIR_IF_SELECT - if let Some(v) = env_flag("HAKO_JOINIR_IF_SELECT") { - return v; - } - false -} - -/// Phase 33-8: JoinIR Stage-1 rollout toggle -/// Set HAKO_JOINIR_STAGE1=1 to enable JoinIR lowering for Stage-1 functions. -pub fn joinir_stage1_enabled() -> bool { - // Primary: HAKO_JOINIR_STAGE1 - if let Some(v) = env_flag("HAKO_JOINIR_STAGE1") { - return v; - } - false -} - -/// Phase 33-8: JoinIR debug log level (0-3) -/// - 0: No logs (default) -/// - 1: Basic logs (which functions were lowered) -/// - 2: Pattern matching details (CFG analysis) -/// - 3: Full dump (all variables, all instructions) -pub fn joinir_debug_level() -> u8 { - // Primary: HAKO_JOINIR_DEBUG - if let Ok(v) = std::env::var("HAKO_JOINIR_DEBUG") { - return v.parse().unwrap_or(0); - } - // Fallback: NYASH_JOINIR_DEBUG (deprecated) - if let Ok(v) = std::env::var("NYASH_JOINIR_DEBUG") { - warn_alias_once("NYASH_JOINIR_DEBUG", "HAKO_JOINIR_DEBUG"); - return v.parse().unwrap_or(0); - } - 0 -} - -/// Dev-only convenience switch to bundle experimental JoinIR knobs. -/// - NYASH_JOINIR_DEV=1 enables -/// - Otherwise inherits from joinir_debug_level()>0 (opt-in debug) -pub fn joinir_dev_enabled() -> bool { - env_bool("NYASH_JOINIR_DEV") || joinir_debug_level() > 0 -} - -/// Phase 61-2: If-in-loop JoinIR dry-run有効化 -/// -/// `HAKO_JOINIR_IF_IN_LOOP_DRYRUN=1` でdry-runモードを有効化 -/// -/// dry-runモード: -/// - JoinIR経路でPHI仕様を計算 -/// - PhiBuilderBox経路と比較 -/// - 実際のPHI生成はPhiBuilderBoxを使用(安全) -pub fn joinir_if_in_loop_dryrun_enabled() -> bool { - env_bool("HAKO_JOINIR_IF_IN_LOOP_DRYRUN") -} - -/// Phase 61-3: If-in-loop JoinIR本番経路有効化 -/// -/// `HAKO_JOINIR_IF_IN_LOOP_ENABLE=1` でJoinIR本番経路を有効化 -/// -/// 動作: -/// - ON: JoinIR + IfInLoopPhiEmitter経路(PhiBuilderBox不使用) -/// - OFF: PhiBuilderBox経路(既存フォールバック) -/// -/// 前提条件: -/// - JoinIR IfSelect 基盤(Phase 33)の有効化 -/// - dry-runモードとは独立(HAKO_JOINIR_IF_IN_LOOP_DRYRUN) -/// -/// デフォルト: OFF(安全第一) -pub fn joinir_if_in_loop_enable() -> bool { - env_bool("HAKO_JOINIR_IF_IN_LOOP_ENABLE") -} - -/// Phase 61-4: ループ外If JoinIR経路有効化 -/// -/// `HAKO_JOINIR_IF_TOPLEVEL=1` でループ外IfのJoinIR経路を有効化 -/// -/// 動作: -/// - ON: try_lower_if_to_joinir経路(if_form.rsで使用) -/// - OFF: PhiBuilderBox経路(既存) -/// -/// 前提条件: -/// - HAKO_JOINIR_IF_SELECT=1(Phase 33基盤) -/// -/// デフォルト: OFF(安全第一) -pub fn joinir_if_toplevel_enabled() -> bool { - env_bool("HAKO_JOINIR_IF_TOPLEVEL") -} - -/// Phase 61-4: ループ外If JoinIR dry-run有効化 -/// -/// `HAKO_JOINIR_IF_TOPLEVEL_DRYRUN=1` でdry-runモードを有効化 -/// -/// dry-runモード: -/// - JoinIR経路を試行しログ出力 -/// - 実際のPHI生成は既存経路を使用(安全) -pub fn joinir_if_toplevel_dryrun_enabled() -> bool { - env_bool("HAKO_JOINIR_IF_TOPLEVEL_DRYRUN") -} - -// VM legacy by-name call fallback was removed (Phase 2 complete). -// Phase 40-4.1: use_joinir_for_array_filter() removed (Route B now default). - -// ---- Phase 11.8 MIR cleanup toggles ---- -/// Core-13 minimal MIR mode toggle. Default ON unless NYASH_MIR_CORE13=0. -pub fn mir_core13() -> bool { - match std::env::var("NYASH_MIR_CORE13").ok() { - Some(v) => { - let lv = v.to_ascii_lowercase(); - !(lv == "0" || lv == "false" || lv == "off") - } - None => true, - } -} -pub fn mir_ref_boxcall() -> bool { - std::env::var("NYASH_MIR_REF_BOXCALL").ok().as_deref() == Some("1") || mir_core13() -} -pub fn mir_array_boxcall() -> bool { - std::env::var("NYASH_MIR_ARRAY_BOXCALL").ok().as_deref() == Some("1") || mir_core13() -} -pub fn mir_plugin_invoke() -> bool { - std::env::var("NYASH_MIR_PLUGIN_INVOKE").ok().as_deref() == Some("1") -} -pub fn plugin_only() -> bool { - std::env::var("NYASH_PLUGIN_ONLY").ok().as_deref() == Some("1") -} - -/// Core-13 "pure" mode: only the 13 canonical ops are allowed (verifier rejects others). -pub fn mir_core13_pure() -> bool { - env_bool("NYASH_MIR_CORE13_PURE") -} - -// ---- Optimizer diagnostics ---- -pub fn opt_debug() -> bool { - std::env::var("NYASH_OPT_DEBUG").is_ok() -} -pub fn opt_diag() -> bool { - std::env::var("NYASH_OPT_DIAG").is_ok() -} -pub fn opt_diag_forbid_legacy() -> bool { - std::env::var("NYASH_OPT_DIAG_FORBID_LEGACY").is_ok() -} -pub fn opt_diag_fail() -> bool { - std::env::var("NYASH_OPT_DIAG_FAIL").is_ok() -} - -// ---- Legacy compatibility (dev-only) ---- -/// Enable legacy InstanceBox fields (SharedNyashBox map) for compatibility. -/// Default: OFF. Set NYASH_LEGACY_FIELDS_ENABLE=1 to materialize and use legacy fields. -pub fn legacy_fields_enable() -> bool { - env_bool("NYASH_LEGACY_FIELDS_ENABLE") -} - -// ---- GC/Runtime tracing (execution-affecting visibility) ---- -pub fn gc_trace() -> bool { - env_bool("NYASH_GC_TRACE") -} -pub fn gc_barrier_trace() -> bool { - env_bool("NYASH_GC_BARRIER_TRACE") -} -pub fn runtime_checkpoint_trace() -> bool { - env_bool("NYASH_RUNTIME_CHECKPOINT_TRACE") -} -pub fn gc_barrier_strict() -> bool { - std::env::var("NYASH_GC_BARRIER_STRICT").ok().as_deref() == Some("1") -} - -/// Return 0 (off) to 3 (max) for `NYASH_GC_TRACE`. -pub fn gc_trace_level() -> u8 { - match std::env::var("NYASH_GC_TRACE").ok().as_deref() { - Some("1") => 1, - Some("2") => 2, - Some("3") => 3, - Some(_) => 1, - None => 0, - } -} - -// ---- GC mode and instrumentation ---- -/// Return current GC mode string (auto default = "rc+cycle"). -/// Allowed: "auto", "rc+cycle", "minorgen", "stw", "rc", "off" -pub fn gc_mode() -> String { - match std::env::var("NYASH_GC_MODE").ok() { - Some(m) if !m.trim().is_empty() => m, - _ => "rc+cycle".to_string(), - } -} -/// Brief metrics emission (text) -pub fn gc_metrics() -> bool { - std::env::var("NYASH_GC_METRICS").ok().as_deref() == Some("1") -} -/// JSON metrics emission (single line) -pub fn gc_metrics_json() -> bool { - std::env::var("NYASH_GC_METRICS_JSON").ok().as_deref() == Some("1") -} -/// Optional allocation threshold; if Some(n) and exceeded, print warning -pub fn gc_alloc_threshold() -> Option { - std::env::var("NYASH_GC_ALLOC_THRESHOLD").ok()?.parse().ok() -} - -// ---- Cleanup (method-level postfix) policy toggles ---- -/// Allow `return` inside a cleanup block. Default: false (0) -pub fn cleanup_allow_return() -> bool { - match std::env::var("NYASH_CLEANUP_ALLOW_RETURN").ok() { - Some(v) => { - let lv = v.to_ascii_lowercase(); - !(lv == "0" || lv == "false" || lv == "off") - } - None => false, - } -} - -/// Allow `throw` inside a cleanup block. Default: false (0) -pub fn cleanup_allow_throw() -> bool { - match std::env::var("NYASH_CLEANUP_ALLOW_THROW").ok() { - Some(v) => { - let lv = v.to_ascii_lowercase(); - !(lv == "0" || lv == "false" || lv == "off") - } - None => false, - } -} - -/// Run a collection every N safepoints (if Some) -pub fn gc_collect_sp_interval() -> Option { - std::env::var("NYASH_GC_COLLECT_SP").ok()?.parse().ok() -} -/// Run a collection when allocated bytes since last >= N (if Some) -pub fn gc_collect_alloc_bytes() -> Option { - std::env::var("NYASH_GC_COLLECT_ALLOC").ok()?.parse().ok() -} - -// ---- Rewriter flags (optimizer transforms) -pub fn rewrite_debug() -> bool { - std::env::var("NYASH_REWRITE_DEBUG").ok().as_deref() == Some("1") -} -pub fn rewrite_safepoint() -> bool { - std::env::var("NYASH_REWRITE_SAFEPOINT").ok().as_deref() == Some("1") -} -pub fn rewrite_future() -> bool { - std::env::var("NYASH_REWRITE_FUTURE").ok().as_deref() == Some("1") -} - -// ---- Phase 12: Nyash ABI (vtable) toggles ---- -pub fn abi_vtable() -> bool { - std::env::var("NYASH_ABI_VTABLE").ok().as_deref() == Some("1") -} -/// ABI strict diagnostics: missing vtable methods become errors when enabled. -pub fn abi_strict() -> bool { - std::env::var("NYASH_ABI_STRICT").ok().as_deref() == Some("1") -} - -// ---- Operator Boxes adopt defaults ---- -/// CompareOperator.apply adopt: default ON (prod/devともに採用) -pub fn operator_box_compare_adopt() -> bool { - match std::env::var("NYASH_OPERATOR_BOX_COMPARE_ADOPT") - .ok() - .as_deref() - .map(|v| v.to_ascii_lowercase()) - { - Some(ref s) if s == "0" || s == "false" || s == "off" => false, - Some(ref s) if s == "1" || s == "true" || s == "on" => true, - _ => true, // default ON - } -} -/// AddOperator.apply adopt: default OFF(順次昇格のため) -pub fn operator_box_add_adopt() -> bool { - match std::env::var("NYASH_OPERATOR_BOX_ADD_ADOPT") - .ok() - .as_deref() - .map(|v| v.to_ascii_lowercase()) - { - Some(ref s) if s == "0" || s == "false" || s == "off" => false, - _ => true, // default ON (promoted after validation) - } -} - -// ---- Null/Missing Boxes (dev-only observe → adopt) ---- -/// Enable NullBox/MissingBox observation path (no behavior change by default). -/// Default: OFF. Turn ON with `NYASH_NULL_MISSING_BOX=1`. May be auto-enabled in --dev later. -pub fn null_missing_box_enabled() -> bool { - std::env::var("NYASH_NULL_MISSING_BOX").ok().as_deref() == Some("1") -} -/// Strict null policy for operators (when enabled): null in arithmetic/compare is an error. -/// Default: OFF (null propagates). Effective only when `null_missing_box_enabled()` is true. -pub fn null_strict() -> bool { - std::env::var("NYASH_NULL_STRICT").ok().as_deref() == Some("1") -} - -// ---- Phase 12: thresholds and routing policies ---- -// ---- Runner/CLI common toggles (hot-path centralization) -pub fn cli_verbose() -> bool { - cli_verbose_level() > 0 -} -pub fn enable_using() -> bool { - // Phase 15: デフォルトON(using systemはメイン機能) - // NYASH_ENABLE_USING=0 で明示的に無効化可能。HAKO_ENABLE_USING は互換のため受理(警告)。 - match std::env::var("NYASH_ENABLE_USING").ok().as_deref() { - Some("0") | Some("false") | Some("off") => return false, - Some(_) => return true, - None => {} - } - // Fallback to alias - if let Some(v) = std::env::var("HAKO_ENABLE_USING").ok() { - warn_alias_once("HAKO_ENABLE_USING", "NYASH_ENABLE_USING"); - let lv = v.to_ascii_lowercase(); - return !(lv == "0" || lv == "false" || lv == "off"); - } - true // default ON -} - -// ---- Using profiles (dev|ci|prod) ---- -/// Return using profile string; default is "dev". -pub fn using_profile() -> String { - std::env::var("NYASH_USING_PROFILE").unwrap_or_else(|_| "dev".to_string()) -} -/// True when using profile is prod (disables some dev-only behaviors). -pub fn using_is_prod() -> bool { - using_profile().eq_ignore_ascii_case("prod") -} -/// True when using profile is ci. -pub fn using_is_ci() -> bool { - using_profile().eq_ignore_ascii_case("ci") -} -/// True when using profile is dev (default). -pub fn using_is_dev() -> bool { - using_profile().eq_ignore_ascii_case("dev") -} -/// Allow `using "path"` statements in source (dev-only by default). -pub fn allow_using_file() -> bool { - // SSOT 徹底: 全プロファイルで既定禁止(nyash.toml を唯一の真実に) - // 明示オーバーライドでのみ許可(開発用緊急時) - match std::env::var("NYASH_ALLOW_USING_FILE").ok().as_deref() { - Some("1") | Some("true") | Some("on") => true, - _ => false, - } -} -/// Determine whether AST prelude merge for `using` is enabled. -/// Precedence: -/// 1) Explicit env `NYASH_USING_AST` = 1/true/on → enabled, = 0/false/off → disabled -/// 2) Default by profile: dev/ci → ON, prod → OFF -pub fn using_ast_enabled() -> bool { - match std::env::var("NYASH_USING_AST") - .ok() - .as_deref() - .map(|v| v.to_ascii_lowercase()) - { - Some(ref s) if s == "1" || s == "true" || s == "on" => true, - Some(ref s) if s == "0" || s == "false" || s == "off" => false, - _ => !using_is_prod(), // dev/ci → true, prod → false - } -} -/// Policy: allow VM to fallback-dispatch user Instance BoxCall (dev only by default). -/// - prod: default false (disallow) -/// - dev/ci: default true (allow, with WARN) -/// Override with NYASH_VM_USER_INSTANCE_BOXCALL={0|1} -pub fn vm_allow_user_instance_boxcall() -> bool { - match std::env::var("NYASH_VM_USER_INSTANCE_BOXCALL") - .ok() - .as_deref() - .map(|v| v.to_ascii_lowercase()) - { - Some(ref s) if s == "0" || s == "false" || s == "off" => false, - Some(ref s) if s == "1" || s == "true" || s == "on" => true, - _ => !using_is_prod(), - } -} -// Legacy resolve_fix_braces() removed (Phase 15 cleanup) -// AST-based integration handles syntax properly without text-level brace fixing -pub fn vm_use_py() -> bool { - std::env::var("NYASH_VM_USE_PY").ok().as_deref() == Some("1") -} -pub fn pipe_use_pyvm() -> bool { - std::env::var("NYASH_PIPE_USE_PYVM").ok().as_deref() == Some("1") -} -/// (Deprecated) use dispatch-based VM route; currently disabled. -pub fn vm_use_dispatch() -> bool { - false -} -/// Force VM fallback interpreter route (dev-only escape hatch). -pub fn vm_use_fallback() -> bool { - std::env::var("NYASH_VM_USE_FALLBACK").ok().as_deref() == Some("1") -} -/// Trace VM route selection decisions. -pub fn vm_route_trace() -> bool { - std::env::var("NYASH_VM_ROUTE_TRACE").ok().as_deref() == Some("1") -} - -// Self-host compiler knobs -pub fn ny_compiler_timeout_ms() -> u64 { - std::env::var("NYASH_NY_COMPILER_TIMEOUT_MS") - .ok() - .and_then(|s| s.parse().ok()) - .unwrap_or(2000) -} -/// Emit-only flag for selfhost compiler (default ON to avoid execution). -pub fn ny_compiler_emit_only() -> bool { - std::env::var("NYASH_NY_COMPILER_EMIT_ONLY").unwrap_or_else(|_| "1".to_string()) == "1" -} -/// Path to external selfhost compiler executable (when enabled). -pub fn use_ny_compiler_exe() -> bool { - std::env::var("NYASH_USE_NY_COMPILER_EXE").ok().as_deref() == Some("1") -} -/// Path to external selfhost compiler executable (when enabled). -pub fn ny_compiler_exe_path() -> Option { - std::env::var("NYASH_NY_COMPILER_EXE_PATH").ok() -} -/// Pass `-- --min-json` to child selfhost compiler (minimal JSON output). -pub fn ny_compiler_min_json() -> bool { - std::env::var("NYASH_NY_COMPILER_MIN_JSON").ok().as_deref() == Some("1") -} -/// When true, child reads tmp/ny_parser_input.ny instead of stdin/source text. -pub fn selfhost_read_tmp() -> bool { - std::env::var("NYASH_SELFHOST_READ_TMP").ok().as_deref() == Some("1") -} -/// Pass `-- --stage3` to child selfhost compiler to allow Stage-3 surface. -pub fn ny_compiler_stage3() -> bool { - std::env::var("NYASH_NY_COMPILER_STAGE3").ok().as_deref() == Some("1") -} -/// Core (Rust) parser Stage-3 gate (default ON). -/// Precedence: -/// 1) NYASH_FEATURES contains `stage3`/`parser-stage3` -/// 2) Legacy env aliases (NYASH_PARSER_STAGE3 / HAKO_PARSER_STAGE3) -/// 3) Default true (Stage-3 is standard syntax) -pub fn parser_stage3_enabled() -> bool { - if feature_stage3_enabled() { - return true; - } - if let Some(v) = env_flag("NYASH_PARSER_STAGE3") { - warn_alias_once("NYASH_PARSER_STAGE3", "NYASH_FEATURES=stage3"); - return v; - } - if let Some(v) = env_flag("HAKO_PARSER_STAGE3") { - warn_alias_once("HAKO_PARSER_STAGE3", "NYASH_FEATURES=stage3"); - return v; - } - true -} - -#[deprecated(note = "Use parser_stage3_enabled() instead")] -pub fn parser_stage3() -> bool { - parser_stage3_enabled() -} - -/// Parser gate for Block‑Postfix Catch acceptance -/// Enabled when either NYASH_BLOCK_CATCH=1 or Stage‑3 gate is on. -/// Phase 15.5 allows parsing a standalone `{ ... }` block optionally followed by -/// a single `catch (...) { ... }` and/or `finally { ... }`, which is folded into -/// ASTNode::TryCatch with the preceding block as the try body. -pub fn block_postfix_catch() -> bool { - std::env::var("NYASH_BLOCK_CATCH").ok().as_deref() == Some("1") || parser_stage3_enabled() -} - -/// Bridge lowering: use Result-style try/throw lowering instead of MIR Catch/Throw -/// When on, try/catch is lowered using structured blocks and direct jumps, -/// without emitting MIR Throw/Catch. The thrown value is routed to catch via -/// block parameters (PHI-off uses edge-copy). -pub fn try_result_mode() -> bool { - std::env::var("NYASH_TRY_RESULT_MODE").ok().as_deref() == Some("1") -} - -/// Parser gate for method-level postfix catch/finally acceptance on method definitions. -/// Enabled when either NYASH_METHOD_CATCH=1 or Stage‑3 gate is on. -pub fn method_catch() -> bool { - std::env::var("NYASH_METHOD_CATCH").ok().as_deref() == Some("1") || parser_stage3_enabled() -} - -/// Entry policy: allow top-level `main` resolution in addition to `Main.main`. -/// Default: true (prefer `Main.main` when both exist; otherwise accept `main`). -pub fn entry_allow_toplevel_main() -> bool { - match std::env::var("NYASH_ENTRY_ALLOW_TOPLEVEL_MAIN").ok() { - Some(v) => { - let v = v.to_ascii_lowercase(); - v == "1" || v == "true" || v == "on" - } - None => true, - } -} - -/// Parser gate for expression-level postfix catch/cleanup acceptance. -/// Enabled when Stage-3 gate is on (NYASH_FEATURES=stage3 or legacy aliases). Separate gate can -/// be introduced in future if needed, but we keep minimal toggles now. -pub fn expr_postfix_catch() -> bool { - parser_stage3_enabled() -} -/// Parser gate for Unified Members (stored/computed/once/birth_once). -/// Default: ON during Phase-15 (set NYASH_ENABLE_UNIFIED_MEMBERS=0|false|off to disable). -pub fn unified_members() -> bool { - match std::env::var("NYASH_ENABLE_UNIFIED_MEMBERS").ok() { - Some(v) => { - let lv = v.to_ascii_lowercase(); - !(lv == "0" || lv == "false" || lv == "off") - } - None => true, - } -} -pub fn ny_compiler_child_args() -> Option { - // Pass-through args to selfhost child (space-separated). - std::env::var("NYASH_NY_COMPILER_CHILD_ARGS").ok() -} -pub fn ny_compiler_use_tmp_only() -> bool { - std::env::var("NYASH_NY_COMPILER_USE_TMP_ONLY") - .ok() - .as_deref() - == Some("1") -} - -/// Use Python MVP harness for Ny compiler (NYASH_NY_COMPILER_USE_PY=1). -pub fn ny_compiler_use_py() -> bool { - std::env::var("NYASH_NY_COMPILER_USE_PY").ok().as_deref() == Some("1") -} - -/// Macro pre-expand mode for selfhost (NYASH_MACRO_SELFHOST_PRE_EXPAND). -/// Returns "1", "auto", or None. -pub fn macro_selfhost_pre_expand() -> Option { - std::env::var("NYASH_MACRO_SELFHOST_PRE_EXPAND").ok() -} - -/// ScopeBox enable flag (NYASH_SCOPEBOX_ENABLE=1). -pub fn scopebox_enable() -> bool { - std::env::var("NYASH_SCOPEBOX_ENABLE").ok().as_deref() == Some("1") -} - -/// LoopForm normalize flag (NYASH_LOOPFORM_NORMALIZE=1). -pub fn loopform_normalize() -> bool { - std::env::var("NYASH_LOOPFORM_NORMALIZE").ok().as_deref() == Some("1") -} - -/// Dev-only escape hatch: force inline selfhost path (NYASH_SELFHOST_INLINE_FORCE=1). -pub fn selfhost_inline_force() -> bool { - std::env::var("NYASH_SELFHOST_INLINE_FORCE").ok().as_deref() == Some("1") -} - -/// Unicode decode toggle for string literals (\uXXXX, optional surrogate pairs). -/// Enabled when either HAKO_PARSER_DECODE_UNICODE=1 or NYASH_PARSER_DECODE_UNICODE=1. -/// Default: OFF (for strict backward compatibility). -pub fn parser_decode_unicode() -> bool { - env_flag("HAKO_PARSER_DECODE_UNICODE") - .or_else(|| env_flag("NYASH_PARSER_DECODE_UNICODE")) - .unwrap_or(false) -} -fn env_flag(var: &str) -> Option { +pub(crate) fn env_flag(var: &str) -> Option { std::env::var(var).ok().map(|v| { let lv = v.to_ascii_lowercase(); lv == "1" || lv == "true" || lv == "on" }) } -pub fn nyvm_core_wrapper() -> bool { - env_flag("HAKO_NYVM_CORE") - .or_else(|| env_flag("NYASH_NYVM_CORE")) - .unwrap_or(false) -} - -pub fn nyvm_bridge_inject_singleton() -> bool { - env_flag("HAKO_BRIDGE_INJECT_SINGLETON") - .or_else(|| env_flag("NYASH_BRIDGE_INJECT_SINGLETON")) - .unwrap_or(false) -} - -pub fn nyvm_bridge_early_phi_materialize() -> bool { - env_flag("HAKO_BRIDGE_EARLY_PHI_MATERIALIZE") - .or_else(|| env_flag("NYASH_BRIDGE_EARLY_PHI_MATERIALIZE")) - .unwrap_or(false) -} - -pub fn nyvm_v1_downconvert() -> bool { - env_flag("HAKO_NYVM_V1_DOWNCONVERT") - .or_else(|| env_flag("NYASH_NYVM_V1_DOWNCONVERT")) - .unwrap_or(false) -} - -/// Gate‑C(Core) strict OOB handling: when enabled, any observed OOB tag -/// (emitted by runtime during ArrayBox get/set with HAKO_OOB_STRICT=1) should -/// cause non‑zero exit at the end of JSON→VM execution. -pub fn oob_strict_fail() -> bool { - env_flag("HAKO_OOB_STRICT_FAIL") - .or_else(|| env_flag("NYASH_OOB_STRICT_FAIL")) - .unwrap_or(false) -} - -/// Primary verification route: return true when Hakorune VM is requested as primary. -/// Accepts HAKO_VERIFY_PRIMARY=hakovm (preferred) or legacy HAKO_ROUTE_HAKOVM=1 (deprecated, warns). -pub fn verify_primary_is_hakovm() -> bool { - if std::env::var("HAKO_VERIFY_PRIMARY").ok().as_deref() == Some("hakovm") { - return true; - } - if env_bool("HAKO_ROUTE_HAKOVM") { - warn_alias_once("HAKO_ROUTE_HAKOVM", "HAKO_VERIFY_PRIMARY=hakovm"); - return true; - } - false -} - pub(crate) fn warn_alias_once(alias: &str, primary: &str) { let set = WARNED_ALIASES.get_or_init(|| Mutex::new(HashSet::new())); if let Ok(mut s) = set.lock() { @@ -898,51 +193,3 @@ pub(crate) fn warn_alias_once(alias: &str, primary: &str) { } } } - -// ---- ENV consolidation helpers (Phase 21.10/22.1) ---- -/// LLVM opt level (primary: NYASH_LLVM_OPT_LEVEL; alias: HAKO_LLVM_OPT_LEVEL) -/// Returns string level (e.g., "0", "1", ...). Default: "0" when unset. -pub fn llvm_opt_level() -> String { - if let Some(v) = std::env::var("NYASH_LLVM_OPT_LEVEL").ok() { - return v; - } - if let Some(v) = std::env::var("HAKO_LLVM_OPT_LEVEL").ok() { - warn_alias_once("HAKO_LLVM_OPT_LEVEL", "NYASH_LLVM_OPT_LEVEL"); - return v; - } - "0".to_string() -} - -/// Gate‑C(Core) route request (primary: NYASH_GATE_C_CORE; alias: HAKO_GATE_C_CORE) -pub fn gate_c_core() -> bool { - if env_bool("NYASH_GATE_C_CORE") { - return true; - } - if env_bool("HAKO_GATE_C_CORE") { - warn_alias_once("HAKO_GATE_C_CORE", "NYASH_GATE_C_CORE"); - return true; - } - false -} - -/// Consolidated toggle for selfhost NY compiler pipeline. -/// Primary: NYASH_USE_NY_COMPILER=0|1(明示指定のみ有効)。Legacy disables accepted (with warning): -/// NYASH_DISABLE_NY_COMPILER/HAKO_DISABLE_NY_COMPILER (any true value disables). -pub fn use_ny_compiler() -> bool { - // Primary knob takes precedence when explicitly set - if let Some(v) = std::env::var("NYASH_USE_NY_COMPILER").ok() { - let lv = v.trim().to_ascii_lowercase(); - return lv == "1" || lv == "true" || lv == "on"; - } - // Legacy disable aliases — if any is true, treat as disabled and warn - if env_bool("NYASH_DISABLE_NY_COMPILER") { - warn_alias_once("NYASH_DISABLE_NY_COMPILER", "NYASH_USE_NY_COMPILER=0"); - return false; - } - if env_bool("HAKO_DISABLE_NY_COMPILER") { - warn_alias_once("HAKO_DISABLE_NY_COMPILER", "NYASH_USE_NY_COMPILER=0"); - return false; - } - // Phase 25.1b: Default OFF(selfhost NY compiler は明示 opt-in のみ) - false -}