diff --git a/.gitignore b/.gitignore index 14f3577c..4478fc27 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,7 @@ __pycache__/ *$py.class *.so .Python -env/ +/env/ venv/ .venv/ pip-log.txt diff --git a/src/config/env/dump.rs b/src/config/env/dump.rs new file mode 100644 index 00000000..bcb3d91a --- /dev/null +++ b/src/config/env/dump.rs @@ -0,0 +1,27 @@ +//! Dump / diagnostics env helpers. + +/// Optional dump path for MIR printer output (JSON v0 route only). +pub fn rust_mir_dump_path() -> Option { + std::env::var("RUST_MIR_DUMP_PATH") + .ok() + .map(|s| s.trim().to_string()) + .filter(|s| !s.is_empty()) +} + +/// CLI verbose level (0=quiet, 1=verbose, 2=trace). +pub fn cli_verbose_level() -> u8 { + match std::env::var("NYASH_CLI_VERBOSE").ok().as_deref() { + Some("2") => 2, + Some("1") => 1, + _ => 0, + } +} + +/// Leak report level (0=off, 1=summary, 2=verbose). +pub fn leak_log_level() -> u8 { + match std::env::var("NYASH_LEAK_LOG").ok().as_deref() { + Some("2") => 2, + Some("1") => 1, + _ => 0, + } +} diff --git a/src/config/env/mir_flags.rs b/src/config/env/mir_flags.rs new file mode 100644 index 00000000..72ff3cad --- /dev/null +++ b/src/config/env/mir_flags.rs @@ -0,0 +1,227 @@ +//! MIR-related environment flags +//! +//! This module groups all MIR feature flags and environment variable controls. +//! Use this for IDE autocomplete to discover MIR flags easily. + +use super::env_bool; + +// ---- 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") +} + +// ---- 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() +} + +// ---- 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") +} + +// ---- 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: 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") +} + +// ---- 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() +} + +/// 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) +} diff --git a/src/config/env/parser_flags.rs b/src/config/env/parser_flags.rs new file mode 100644 index 00000000..012c29c4 --- /dev/null +++ b/src/config/env/parser_flags.rs @@ -0,0 +1,136 @@ +//! Parser-related environment flags +//! +//! This module groups all parser and language feature flags. +//! Use this for IDE autocomplete to discover parser flags easily. + +use super::warn_alias_once; + +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 +} + +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" + }) +} + +/// 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() +} + +/// 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() +} + +/// 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, + } +} + +/// 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) +} + +/// 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, + } +} + +/// 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") +} diff --git a/src/config/env/selfhost_flags.rs b/src/config/env/selfhost_flags.rs new file mode 100644 index 00000000..f839c0be --- /dev/null +++ b/src/config/env/selfhost_flags.rs @@ -0,0 +1,98 @@ +//! Selfhost compiler-related environment flags +//! +//! This module groups all selfhost NY compiler flags. +//! Use this for IDE autocomplete to discover selfhost compiler flags easily. + +use super::warn_alias_once; + +// 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") +} + +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") +} + +/// 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") +} + +/// 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 { + fn env_bool(key: &str) -> bool { + match std::env::var(key).ok() { + Some(v) => { + let lv = v.to_ascii_lowercase(); + lv == "1" || lv == "true" || lv == "on" + } + None => false, + } + } + + // 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 +} diff --git a/src/config/env/stage1.rs b/src/config/env/stage1.rs new file mode 100644 index 00000000..887b49f7 --- /dev/null +++ b/src/config/env/stage1.rs @@ -0,0 +1,109 @@ +//! Stage-1 / selfhost CLI environment helpers (SSOT). + +use crate::config::env::{env_bool, warn_alias_once}; + +/// Primary toggle: enable Stage-1 stub routing. +pub fn enabled() -> bool { + env_bool("NYASH_USE_STAGE1_CLI") + || env_bool("HAKO_STAGE1_ENABLE") + || env_bool("HAKO_EMIT_PROGRAM_JSON") + || env_bool("HAKO_EMIT_MIR_JSON") +} + +/// Recursion guard when Stage-1 stub calls back into the runner. +pub fn child_invocation() -> bool { + env_bool("NYASH_STAGE1_CLI_CHILD") +} + +/// Stage-1 mode hint (emit-program / emit-mir / run). +pub fn mode() -> Option { + if let Some(m) = std::env::var("HAKO_STAGE1_MODE") + .ok() + .or_else(|| std::env::var("NYASH_STAGE1_MODE").ok()) + { + let trimmed = m.trim(); + if !trimmed.is_empty() { + return Some(trimmed.to_ascii_lowercase().replace('_', "-")); + } + } + if std::env::var("HAKO_EMIT_PROGRAM_JSON").ok().as_deref() == Some("1") { + return Some("emit-program".into()); + } + if std::env::var("HAKO_EMIT_MIR_JSON").ok().as_deref() == Some("1") { + return Some("emit-mir".into()); + } + if std::env::var("STAGE1_EMIT_PROGRAM_JSON").ok().as_deref() == Some("1") { + return Some("emit-program".into()); + } + if std::env::var("STAGE1_EMIT_MIR_JSON").ok().as_deref() == Some("1") { + return Some("emit-mir".into()); + } + if enabled() { + return Some("run".into()); + } + None +} + +/// True when Stage-1 should emit Program(JSON v0). +pub fn emit_program_json() -> bool { + matches!( + mode().as_deref(), + Some("emit-program" | "emit-program-json") + ) +} + +/// True when Stage-1 should emit MIR(JSON). +pub fn emit_mir_json() -> bool { + matches!(mode().as_deref(), Some("emit-mir" | "emit-mir-json")) +} + +/// Input source path passed to Stage-1 stub (aliases included). +pub fn input_path() -> Option { + std::env::var("HAKO_STAGE1_INPUT") + .ok() + .or_else(|| std::env::var("NYASH_STAGE1_INPUT").ok()) + .or_else(|| std::env::var("STAGE1_SOURCE").ok()) + .or_else(|| std::env::var("STAGE1_INPUT").ok()) +} + +/// Program(JSON v0) path for Stage-1 emit-mir mode (aliases included). +pub fn program_json_path() -> Option { + std::env::var("HAKO_STAGE1_PROGRAM_JSON") + .ok() + .or_else(|| std::env::var("NYASH_STAGE1_PROGRAM_JSON").ok()) + .or_else(|| std::env::var("STAGE1_PROGRAM_JSON").ok()) +} + +/// Backend hint for Stage-1 run mode (aliases included). +pub fn backend_hint() -> Option { + std::env::var("HAKO_STAGE1_BACKEND") + .ok() + .or_else(|| std::env::var("NYASH_STAGE1_BACKEND").ok()) + .or_else(|| std::env::var("STAGE1_BACKEND").ok()) +} + +/// Optional override for Stage-1 CLI entry path. +pub fn entry_override() -> Option { + std::env::var("STAGE1_CLI_ENTRY") + .ok() + .or_else(|| std::env::var("HAKORUNE_STAGE1_ENTRY").ok()) +} + +/// Optional Stage-1 child args (passed through to stub). +pub fn child_args_env() -> Option { + std::env::var("NYASH_SCRIPT_ARGS_JSON").ok() +} + +/// Stage-1 debug flag (verbose child stderr). +pub fn debug() -> bool { + std::env::var("STAGE1_CLI_DEBUG").ok().as_deref() == Some("1") +} + +/// Alias compatibility for backends (warn once). +pub fn backend_alias_warned() -> Option { + if let Some(be) = std::env::var("STAGE1_BACKEND").ok() { + warn_alias_once("STAGE1_BACKEND", "NYASH_STAGE1_BACKEND"); + return Some(be); + } + None +} diff --git a/src/config/env/using_flags.rs b/src/config/env/using_flags.rs new file mode 100644 index 00000000..c916585d --- /dev/null +++ b/src/config/env/using_flags.rs @@ -0,0 +1,70 @@ +//! Using/namespace-related environment flags +//! +//! This module groups all `using` system and namespace flags. +//! Use this for IDE autocomplete to discover using/namespace flags easily. + +use super::warn_alias_once; + +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 + } +} diff --git a/src/config/env/verification_flags.rs b/src/config/env/verification_flags.rs new file mode 100644 index 00000000..11e4371b --- /dev/null +++ b/src/config/env/verification_flags.rs @@ -0,0 +1,61 @@ +//! Verification and checking-related environment flags +//! +//! This module groups all verification, checking, and testing flags. +//! Use this for IDE autocomplete to discover verification flags easily. + +use super::{env_bool, env_bool_default}; + +/// 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() +} + +fn mir_no_phi() -> bool { + env_bool("NYASH_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 { + 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" + }) + } + env_flag("NYASH_STAGEB_DEV_VERIFY").unwrap_or(true) +} + +/// 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) +} + +/// 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") +} + +/// Runner/CLI common toggles (hot-path centralization) +pub fn cli_verbose() -> bool { + // Use cli_verbose_level from dump module + super::dump::cli_verbose_level() > 0 +} diff --git a/src/config/env/vm_backend_flags.rs b/src/config/env/vm_backend_flags.rs new file mode 100644 index 00000000..ee38b487 --- /dev/null +++ b/src/config/env/vm_backend_flags.rs @@ -0,0 +1,135 @@ +//! VM and backend-related environment flags +//! +//! This module groups all VM execution and backend selection flags. +//! Use this for IDE autocomplete to discover VM/backend flags easily. + +use super::{env_bool, env_flag, warn_alias_once}; + +// ---- 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(ハーネス使用) + } +} + +/// 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() +} + +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") +} + +/// 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(), + } +} + +// Import using profile functions needed for vm_allow_user_instance_boxcall +fn using_is_prod() -> bool { + using_profile().eq_ignore_ascii_case("prod") +} + +fn using_profile() -> String { + std::env::var("NYASH_USING_PROFILE").unwrap_or_else(|_| "dev".to_string()) +} + +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) 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 +} + +/// 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 +}