phase: 20.49 COMPLETE; 20.50 Flow+String minimal reps; 20.51 selfhost v0/v1 minimal (Option A/B); hv1-inline binop/unop/copy; docs + run_all + CURRENT_TASK -> 21.0

This commit is contained in:
nyash-codex
2025-11-06 15:41:52 +09:00
parent 2dc370223d
commit 77d4fd72b3
1658 changed files with 6288 additions and 2612 deletions

View File

@ -47,7 +47,7 @@ impl NyashRunner {
/// Execute Nyash file with interpreter (common helper)
pub(crate) fn execute_nyash_file(&self, filename: &str) {
let quiet_pipe = std::env::var("NYASH_JSON_ONLY").ok().as_deref() == Some("1");
let quiet_pipe = crate::config::env::env_bool("NYASH_JSON_ONLY");
// Ensure runtime and plugins are initialized via unified helper (idempotent)
let groups = self.config.as_groups();
self.init_runtime_and_plugins(&groups);
@ -124,7 +124,7 @@ impl NyashRunner {
} else { main_ast };
// Optional: dump AST statement kinds for quick diagnostics
if std::env::var("NYASH_AST_DUMP").ok().as_deref() == Some("1") {
if crate::config::env::env_bool("NYASH_AST_DUMP") {
use nyash_rust::ast::ASTNode;
eprintln!("[ast] dump start");
if let ASTNode::Program { statements, .. } = &ast {
@ -168,7 +168,7 @@ impl NyashRunner {
}
let exists = p.exists();
if !exists {
if std::env::var("NYASH_USING_STRICT").ok().as_deref() == Some("1") {
if crate::config::env::env_bool("NYASH_USING_STRICT") {
eprintln!(
"❌ import: path not found: {} (from {})",
p.display(),
@ -176,7 +176,7 @@ impl NyashRunner {
);
process::exit(1);
} else if crate::config::env::cli_verbose()
|| std::env::var("NYASH_IMPORT_TRACE").ok().as_deref() == Some("1")
|| crate::config::env::env_bool("NYASH_IMPORT_TRACE")
{
eprintln!("[import] path not found (continuing): {}", p.display());
}

View File

@ -15,34 +15,17 @@ pub fn looks_like_hako_code(s: &str) -> bool {
/// Remove leading `local ` declarations at line head to keep Nyash parser stable
pub fn strip_local_decl(s: &str) -> String {
let mut out = String::with_capacity(s.len());
for line in s.lines() {
let leading = line.len() - line.trim_start().len();
let (indent, rest) = line.split_at(leading);
if rest.starts_with("local ") || rest.starts_with("local\t") {
let bytes = rest.as_bytes();
let mut i = 5; // after 'local'
while i < bytes.len() && (bytes[i] == b' ' || bytes[i] == b'\t') {
i += 1;
break;
}
out.push_str(indent);
out.push_str(&rest[i..]);
out.push('\n');
} else {
out.push_str(line);
out.push('\n');
}
}
out
// Stage3 パーサでは 'local' を受理できるため、変換は行わず原文を返す
s.to_string()
}
/// Policy toggle: fail fast when Hako-like code enters Nyash VM path
/// Default: ON (true)
pub fn fail_fast_on_hako() -> bool {
// Default: OFF仕様不変拡張子だけで拒否しない
// 明示時のみ ONbring-up やデバッグ用途)。
match std::env::var("HAKO_FAIL_FAST_ON_HAKO_IN_NYASH_VM").ok().as_deref() {
Some("0") | Some("false") | Some("off") => false,
_ => true,
Some("1") | Some("true") | Some("on") => true,
_ => false,
}
}

View File

@ -24,6 +24,7 @@ pub mod seam;
pub mod using_resolution;
pub mod prelude_manager;
pub mod selfhost_pipeline;
pub mod path_util;
// 📦 箱化モジュールの公開にゃ!
pub use using_resolution::{

View File

@ -0,0 +1,20 @@
//! path_util — helpers for using target path detection (SSOT)
/// Determine if an original using target string should be treated as a file path.
/// Original means it may still contain surrounding quotes.
pub fn is_using_target_path_original(target: &str) -> bool {
if target.starts_with('"') {
return true;
}
let t = target.trim_matches('"');
is_using_target_path_unquoted(t)
}
/// Determine if an unquoted using target string is a file path.
pub fn is_using_target_path_unquoted(target_unquoted: &str) -> bool {
target_unquoted.starts_with("./")
|| target_unquoted.starts_with('/')
|| target_unquoted.ends_with(".hako")
|| target_unquoted.ends_with(".nyash")
}

View File

@ -19,9 +19,8 @@ pub fn collect_using_and_strip(
}
let using_ctx = runner.init_using_context();
let prod = crate::config::env::using_is_prod();
let strict = std::env::var("NYASH_USING_STRICT").ok().as_deref() == Some("1");
let verbose = crate::config::env::cli_verbose()
|| std::env::var("NYASH_RESOLVE_TRACE").ok().as_deref() == Some("1");
let strict = crate::config::env::env_bool("NYASH_USING_STRICT");
let verbose = crate::config::env::cli_verbose() || crate::config::env::env_bool("NYASH_RESOLVE_TRACE");
let ctx_dir = std::path::Path::new(filename).parent();
let mut out = String::with_capacity(code.len());
@ -61,7 +60,7 @@ pub fn collect_using_and_strip(
} else {
(rest0.to_string(), None)
};
// Strip quotes from target for alias/module lookup
// Strip quotes from target for alias/module lookup and path detection
let target_unquoted = target.trim_matches('"').to_string();
// Check if this is a known alias or module FIRST before treating as file path
@ -73,11 +72,8 @@ pub fn collect_using_and_strip(
// Known alias/module - don't treat as file path even if quoted
false
} else {
// Only treat as file path if not a known alias/module
target.starts_with("./")
|| target.starts_with('/')
|| target.ends_with(".nyash")
|| target.ends_with(".hako")
// SSOT: delegate path pattern check
crate::runner::modes::common_util::resolve::path_util::is_using_target_path_unquoted(&target_unquoted)
};
if is_path {
// SSOT: Disallow file-using at top-level; allow only for sources located
@ -91,7 +87,7 @@ pub fn collect_using_and_strip(
target
));
}
let path = target.trim_matches('"').to_string();
let path = target_unquoted.clone();
// Resolve relative to current file dir
let mut p = std::path::PathBuf::from(&path);
if p.is_relative() {
@ -197,7 +193,7 @@ pub fn collect_using_and_strip(
.file_name()
.and_then(|s| s.to_str())
.unwrap_or(&pkg_name);
base.join(format!("{}.nyash", leaf))
base.join(format!("{}.hako", leaf))
.to_string_lossy()
.to_string()
};
@ -257,8 +253,8 @@ pub fn collect_using_and_strip(
) {
Ok(value) => {
// Only file paths are candidates for AST prelude merge
if value.ends_with(".nyash") || value.contains('/') || value.contains('\\')
{
if crate::runner::modes::common_util::resolve::path_util::is_using_target_path_unquoted(&value)
{
// Resolve relative
let mut p = std::path::PathBuf::from(&value);
if p.is_relative() {
@ -338,7 +334,7 @@ pub fn collect_using_and_strip(
out.push('\n');
}
// Optional prelude boundary comment (helps manual inspection; parser ignores comments)
if std::env::var("NYASH_RESOLVE_SEAM_DEBUG").ok().as_deref() == Some("1") {
if crate::config::env::env_bool("NYASH_RESOLVE_SEAM_DEBUG") {
let mut with_marker = String::with_capacity(out.len() + 64);
with_marker.push_str("\n/* --- using boundary (AST) --- */\n");
with_marker.push_str(&out);
@ -364,7 +360,7 @@ pub fn resolve_prelude_paths_profiled(
// must be discovered so that their definitions are present at runtime
// (e.g., runner_min -> lower_* boxes). Previously this only ran when
// NYASH_USING_AST=1, which caused unresolved calls in inline flows.
let ast_on = std::env::var("NYASH_USING_AST").ok().as_deref() == Some("1");
let ast_on = crate::config::env::env_bool("NYASH_USING_AST");
let mut out: Vec<String> = Vec::new();
let mut seen: std::collections::HashSet<String> = std::collections::HashSet::new();
fn normalize_path(path: &str) -> (String, String) {
@ -404,14 +400,14 @@ pub fn resolve_prelude_paths_profiled(
}
// Operator Boxes prelude injection観測“常時ON”のため
// stringify/compare/add は常に注入存在時。その他bitwise等は ALL 指定時のみ。
let opbox_all = std::env::var("NYASH_OPERATOR_BOX_ALL").ok().as_deref() == Some("1")
|| std::env::var("NYASH_BUILDER_OPERATOR_BOX_ALL_CALL").ok().as_deref() == Some("1");
let opbox_all = crate::config::env::env_bool("NYASH_OPERATOR_BOX_ALL")
|| crate::config::env::env_bool("NYASH_BUILDER_OPERATOR_BOX_ALL_CALL");
if let Ok(root) = std::env::var("NYASH_ROOT") {
let must_have = [
"apps/lib/std/operators/stringify.nyash",
"apps/lib/std/operators/compare.nyash",
"apps/lib/std/operators/add.nyash",
"apps/lib/std/operators/stringify.hako",
"apps/lib/std/operators/compare.hako",
"apps/lib/std/operators/add.hako",
];
for rel in must_have.iter() {
let p = std::path::Path::new(&root).join(rel);
@ -427,19 +423,19 @@ pub fn resolve_prelude_paths_profiled(
if opbox_all {
if let Ok(root) = std::env::var("NYASH_ROOT") {
let rels = vec![
"apps/lib/std/operators/sub.nyash",
"apps/lib/std/operators/mul.nyash",
"apps/lib/std/operators/div.nyash",
"apps/lib/std/operators/mod.nyash",
"apps/lib/std/operators/sub.hako",
"apps/lib/std/operators/mul.hako",
"apps/lib/std/operators/div.hako",
"apps/lib/std/operators/mod.hako",
// Shifts / bitwise (parser tokens now supported)
"apps/lib/std/operators/shl.nyash",
"apps/lib/std/operators/shr.nyash",
"apps/lib/std/operators/bitand.nyash",
"apps/lib/std/operators/bitor.nyash",
"apps/lib/std/operators/bitxor.nyash",
"apps/lib/std/operators/neg.nyash",
"apps/lib/std/operators/not.nyash",
"apps/lib/std/operators/bitnot.nyash",
"apps/lib/std/operators/shl.hako",
"apps/lib/std/operators/shr.hako",
"apps/lib/std/operators/bitand.hako",
"apps/lib/std/operators/bitor.hako",
"apps/lib/std/operators/bitxor.hako",
"apps/lib/std/operators/neg.hako",
"apps/lib/std/operators/not.hako",
"apps/lib/std/operators/bitnot.hako",
];
for rel in rels {
let p = std::path::Path::new(&root).join(rel);
@ -465,7 +461,7 @@ pub fn parse_preludes_to_asts(
runner: &NyashRunner,
prelude_paths: &[String],
) -> Result<Vec<nyash_rust::ast::ASTNode>, String> {
let debug = std::env::var("NYASH_STRIP_DEBUG").ok().as_deref() == Some("1");
let debug = crate::config::env::env_bool("NYASH_STRIP_DEBUG");
if debug {
eprintln!("[strip-debug] parse_preludes_to_asts: {} files total", prelude_paths.len());
for (idx, p) in prelude_paths.iter().enumerate() {
@ -506,7 +502,7 @@ pub fn parse_preludes_to_asts(
}
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");
let debug = crate::config::env::env_bool("NYASH_STRIP_DEBUG");
eprintln!("[strip-debug] Parse FAILED for: {} (debug={})", prelude_path, debug);
if debug {
eprintln!("[strip-debug] Error: {}", e);
@ -659,7 +655,7 @@ pub fn merge_prelude_text(
source: &str,
filename: &str,
) -> Result<String, String> {
let trace = std::env::var("NYASH_RESOLVE_TRACE").ok().as_deref() == Some("1");
let trace = crate::config::env::env_bool("NYASH_RESOLVE_TRACE");
// First pass: collect and resolve prelude paths
let (cleaned_main, prelude_paths) = resolve_prelude_paths_profiled(runner, source, filename)?;
@ -737,7 +733,7 @@ pub fn merge_prelude_text(
}
// Add boundary marker if debug mode
if std::env::var("NYASH_RESOLVE_SEAM_DEBUG").ok().as_deref() == Some("1") {
if crate::config::env::env_bool("NYASH_RESOLVE_SEAM_DEBUG") {
merged.push_str("\n/* --- using prelude/main boundary --- */\n\n");
}

View File

@ -46,9 +46,9 @@ impl<'a> UsingResolutionBox<'a> {
let using_ctx = runner.init_using_context();
let config = UsingConfig {
prod: crate::config::env::using_is_prod(),
strict: std::env::var("NYASH_USING_STRICT").ok().as_deref() == Some("1"),
strict: crate::config::env::env_bool("NYASH_USING_STRICT"),
verbose: crate::config::env::cli_verbose()
|| std::env::var("NYASH_RESOLVE_TRACE").ok().as_deref() == Some("1"),
|| crate::config::env::env_bool("NYASH_RESOLVE_TRACE"),
allow_file_using: crate::config::env::allow_using_file(),
};
@ -113,10 +113,7 @@ impl<'a> UsingResolutionBox<'a> {
let is_path = if is_known_alias_or_module {
false
} else {
target.starts_with("./")
|| target.starts_with('/')
|| target.ends_with(".nyash")
|| target.ends_with(".hako")
crate::runner::modes::common_util::resolve::path_util::is_using_target_path_unquoted(&target_unquoted)
};
Some(UsingTarget {

View File

@ -2,7 +2,7 @@ use std::path::Path;
/// Run a Nyash program as a child (`nyash --backend vm <program>`) and capture the first JSON v0 line.
/// - `exe`: path to nyash executable
/// - `program`: path to the Nyash script to run (e.g., apps/selfhost/compiler/compiler.nyash)
/// - `program`: path to the Nyash script to run (e.g., apps/selfhost/compiler/compiler.hako)
/// - `timeout_ms`: kill child after this duration
/// - `extra_args`: additional args to pass after program (e.g., "--", "--read-tmp")
/// - `env_remove`: environment variable names to remove for the child

View File

@ -36,7 +36,7 @@ pub fn run_pyvm_module(module: &MirModule, label: &str) -> Option<i32> {
eprintln!("❌ PyVM MIR JSON emit error: {}", e);
return None;
}
if std::env::var("NYASH_CLI_VERBOSE").ok().as_deref() == Some("1") {
if crate::config::env::cli_verbose() {
eprintln!("[Bridge] using PyVM ({}) → {}", label, mir_json_path.display());
}
// Select entry (prefer Main.main; top-level main only if allowed)

View File

@ -4,7 +4,7 @@ use std::{fs, process};
/// Execute using PyVM only (no Rust VM runtime). Emits MIR(JSON) and invokes tools/pyvm_runner.py.
pub fn execute_pyvm_only(runner: &NyashRunner, filename: &str) {
if std::env::var("NYASH_PYVM_TRACE").ok().as_deref() == Some("1") { eprintln!("[pyvm] entry"); }
if crate::config::env::env_bool("NYASH_PYVM_TRACE") { eprintln!("[pyvm] entry"); }
// Read the file
let code = match fs::read_to_string(filename) {
Ok(content) => content,
@ -76,7 +76,7 @@ pub fn execute_pyvm_only(runner: &NyashRunner, filename: &str) {
code = normalize_logical_ops(&code);
// Parse to AST
if std::env::var("NYASH_PYVM_DUMP_CODE").ok().as_deref() == Some("1") {
if crate::config::env::env_bool("NYASH_PYVM_DUMP_CODE") {
eprintln!("[pyvm-code]\n{}", code);
}
let ast = match NyashParser::parse_from_string(&code) {
@ -100,13 +100,13 @@ pub fn execute_pyvm_only(runner: &NyashRunner, filename: &str) {
};
// Optional: VM-only escape analysis elision pass retained for parity with VM path
if std::env::var("NYASH_VM_ESCAPE_ANALYSIS").ok().as_deref() == Some("1") {
if crate::config::env::env_bool("NYASH_VM_ESCAPE_ANALYSIS") {
let removed = nyash_rust::mir::passes::escape::escape_elide_barriers_vm(&mut compile_result.module);
if removed > 0 { crate::cli_v!("[PyVM] escape_elide_barriers: removed {} barriers", removed); }
}
// Optional: delegate to Ny selfhost executor (Stage 0 scaffold: no-op)
if std::env::var("NYASH_SELFHOST_EXEC").ok().as_deref() == Some("1") {
if crate::config::env::env_bool("NYASH_SELFHOST_EXEC") {
// Emit MIR JSON to a temp file and invoke Ny runner script.
let tmp_dir = std::path::Path::new("tmp");
let _ = std::fs::create_dir_all(tmp_dir);
@ -117,7 +117,7 @@ pub fn execute_pyvm_only(runner: &NyashRunner, filename: &str) {
}
// Resolve nyash executable and runner path
let exe = std::env::current_exe().unwrap_or_else(|_| std::path::PathBuf::from("target/release/nyash"));
let runner = std::path::Path::new("apps/selfhost-runtime/runner.nyash");
let runner = std::path::Path::new("apps/selfhost-runtime/runner.hako");
if !runner.exists() {
eprintln!("❌ Selfhost runner missing: {}", runner.display());
process::exit(1);

View File

@ -19,7 +19,7 @@ impl NyashRunner {
// This function is only called after plugin initialization has already occurred.
// Quiet mode for child pipelines (e.g., selfhost compiler JSON emit)
let quiet_pipe = std::env::var("NYASH_JSON_ONLY").ok().as_deref() == Some("1");
let quiet_pipe = crate::config::env::env_bool("NYASH_JSON_ONLY");
// Enforce plugin-first policy for VM on this branch (deterministic):
// - Initialize plugin host if not yet loaded
// - Prefer plugin implementations for core boxes
@ -35,7 +35,7 @@ impl NyashRunner {
.unwrap_or(true)
};
if need_init {
let _ = nyash_rust::runtime::init_global_plugin_host("nyash.toml");
// Let init_bid_plugins resolve hakorune.toml/nyash.toml and configure
crate::runner_plugin_init::init_bid_plugins();
}
// Prefer plugin-builtins for core types unless explicitly disabled
@ -70,7 +70,7 @@ impl NyashRunner {
std::env::set_var("NYASH_PLUGIN_OVERRIDE_TYPES", override_types.join(","));
// Strict mode: verify providers exist for override types
if std::env::var("NYASH_VM_PLUGIN_STRICT").ok().as_deref() == Some("1") {
if crate::config::env::env_bool("NYASH_VM_PLUGIN_STRICT") {
let v2 = nyash_rust::runtime::get_global_registry();
let mut missing: Vec<String> = Vec::new();
for t in [
@ -158,7 +158,7 @@ impl NyashRunner {
let code_ref: &str = &preexpanded_owned;
// Parse to AST
if std::env::var("NYASH_STRIP_DEBUG").ok().as_deref() == Some("1") {
if crate::config::env::env_bool("NYASH_STRIP_DEBUG") {
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) {
@ -170,7 +170,7 @@ impl NyashRunner {
Err(e) => {
eprintln!("❌ Parse error in main source ({}): {}",
cfg.file.as_ref().map(|s| s.as_str()).unwrap_or("<stdin>"), e);
if std::env::var("NYASH_STRIP_DEBUG").ok().as_deref() == Some("1") {
if crate::config::env::env_bool("NYASH_STRIP_DEBUG") {
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) {
@ -233,14 +233,14 @@ impl NyashRunner {
}
// Optional: dump MIR for diagnostics
if std::env::var("NYASH_VM_DUMP_MIR").ok().as_deref() == Some("1") {
if crate::config::env::env_bool("NYASH_VM_DUMP_MIR") {
let p = nyash_rust::mir::MirPrinter::new();
eprintln!("{}", p.print_module(&compile_result.module));
}
// Optional: VM-only escape analysis to elide barriers before execution
let mut module_vm = compile_result.module.clone();
if std::env::var("NYASH_VM_ESCAPE_ANALYSIS").ok().as_deref() == Some("1") {
if crate::config::env::env_bool("NYASH_VM_ESCAPE_ANALYSIS") {
let removed = nyash_rust::mir::passes::escape::escape_elide_barriers_vm(&mut module_vm);
if removed > 0 { crate::cli_v!("[VM] escape_elide_barriers: removed {} barriers", removed); }
}
@ -534,10 +534,7 @@ impl NyashRunner {
type_parameters: type_parameters.clone(),
};
if let Ok(mut map) = runtime.box_declarations.write() {
if std::env::var("NYASH_BOX_DECL_TRACE")
.ok()
.as_deref()
== Some("1")
if crate::config::env::env_bool("NYASH_BOX_DECL_TRACE")
{
eprintln!("[box-decl] register {}", name);
}

View File

@ -26,32 +26,25 @@ impl NyashRunner {
process::exit(1);
}
};
// Using preprocessing with AST-prelude merge (when NYASH_USING_AST=1)
let mut code2 = code;
let use_ast_prelude =
crate::config::env::enable_using() && crate::config::env::using_ast_enabled();
// Using preprocessing: 仕様維持のためテキスト・プレリュード統合を既定にASTマージは任意
let mut code2 = code.clone();
if crate::config::env::enable_using() {
// Always perform text-prelude merge when using+AST is enabled to ensure alias/file modules are materialized.
if use_ast_prelude {
match crate::runner::modes::common_util::resolve::merge_prelude_text(self, &code2, filename) {
Ok(merged) => {
if std::env::var("NYASH_RESOLVE_TRACE").ok().as_deref() == Some("1") {
eprintln!("[using/text-merge] applied (vm-fallback): {} bytes", merged.len());
}
code2 = merged;
match crate::runner::modes::common_util::resolve::merge_prelude_text(self, &code2, filename) {
Ok(merged) => {
if std::env::var("NYASH_RESOLVE_TRACE").ok().as_deref() == Some("1") {
eprintln!("[using/text-merge] applied (vm-fallback): {} bytes", merged.len());
}
Err(e) => { eprintln!("❌ using text merge error: {}", e); process::exit(1); }
}
} else {
match crate::runner::modes::common_util::resolve::resolve_prelude_paths_profiled(self, &code2, filename) {
Ok((_clean, paths)) => {
if !paths.is_empty() {
eprintln!("❌ using: prelude merge is disabled in this profile. Enable NYASH_USING_AST=1 or remove 'using' lines.");
process::exit(1);
}
}
Err(e) => { eprintln!("{}", e); process::exit(1); }
code2 = merged;
}
Err(e) => { eprintln!("❌ using text merge error: {}", e); process::exit(1); }
}
} else {
// using disabled: detect and fail fast if present
if code.contains("\nusing ") || code.trim_start().starts_with("using ") {
eprintln!(
"❌ using: prelude merge is disabled in this profile. Enable NYASH_USING_AST=1 or remove 'using' lines."
);
process::exit(1);
}
}
// Dev sugar pre-expand: @name = expr → local name = expr
@ -242,7 +235,7 @@ impl NyashRunner {
// Optional barrier-elision for parity with VM path
let mut module_vm = compile.module.clone();
if std::env::var("NYASH_VM_ESCAPE_ANALYSIS").ok().as_deref() == Some("1") {
if crate::config::env::env_bool("NYASH_VM_ESCAPE_ANALYSIS") {
let removed = crate::mir::passes::escape::escape_elide_barriers_vm(&mut module_vm);
if removed > 0 {
crate::cli_v!(
@ -253,7 +246,7 @@ impl NyashRunner {
}
// Optional: dump MIR for diagnostics (parity with vm path)
if std::env::var("NYASH_VM_DUMP_MIR").ok().as_deref() == Some("1") {
if crate::config::env::env_bool("NYASH_VM_DUMP_MIR") {
let p = crate::mir::MirPrinter::new();
eprintln!("{}", p.print_module(&module_vm));
}
@ -261,7 +254,7 @@ impl NyashRunner {
// Execute via MIR interpreter
let mut vm = MirInterpreter::new();
// Optional: verify MIR before execution (dev-only)
if std::env::var("NYASH_VM_VERIFY_MIR").ok().as_deref() == Some("1") {
if crate::config::env::env_bool("NYASH_VM_VERIFY_MIR") {
let mut verifier = crate::mir::verification::MirVerifier::new();
for (name, func) in module_vm.functions.iter() {
if let Err(errors) = verifier.verify_function(func) {

View File

@ -38,7 +38,13 @@ impl NyashRunner {
// Determine output file
let groups = self.config.as_groups();
let output = groups.output_file.as_deref().unwrap_or_else(|| {
if filename.ends_with(".nyash") { filename.strip_suffix(".nyash").unwrap_or(filename) } else { filename }
if filename.ends_with(".hako") {
filename.strip_suffix(".hako").unwrap_or(filename)
} else if filename.ends_with(".nyash") {
filename.strip_suffix(".nyash").unwrap_or(filename)
} else {
filename
}
});
let output_file = format!("{}.wat", output);