Files
hakorune/src/using/resolver.rs

96 lines
4.0 KiB
Rust
Raw Normal View History

use crate::using::errors::UsingError;
use crate::using::policy::UsingPolicy;
use crate::using::spec::{PackageKind, UsingPackage};
use std::collections::HashMap;
/// Populate using context vectors from nyash.toml (if present).
/// Keeps behavior aligned with existing runner pipeline:
/// - Adds [using.paths] entries to `using_paths`
/// - Flattens [modules] into (name, path) pairs appended to `pending_modules`
/// - Reads optional [aliases] table (k -> v)
pub fn populate_from_toml(
using_paths: &mut Vec<String>,
pending_modules: &mut Vec<(String, String)>,
aliases: &mut HashMap<String, String>,
packages: &mut HashMap<String, UsingPackage>,
) -> Result<UsingPolicy, UsingError> {
let mut policy = UsingPolicy::default();
feat(stage-b): Add FLOW keyword support + fix Stage-3 keyword conflicts ## ✅ Fixed Issues ### 1. `local` keyword tokenization (commit 9aab64f7) - Added Stage-3 gate for LOCAL/TRY/CATCH/THROW keywords - LOCAL now only active when NYASH_PARSER_STAGE3=1 ### 2. `env.local.get` keyword conflict - File: `lang/src/compiler/entry/compiler_stageb.hako:21-23` - Problem: `.local` in member access tokenized as `.LOCAL` keyword - Fix: Commented out `env.local.get("HAKO_SOURCE")` line - Fallback: Use `--source` argument (still functional) ### 3. `flow` keyword missing - Added FLOW to TokenType enum (`src/tokenizer/kinds.rs`) - Added "flow" → TokenType::FLOW mapping (`src/tokenizer/lex_ident.rs`) - Added FLOW to Stage-3 gate (requires NYASH_PARSER_STAGE3=1) - Added FLOW to parser statement dispatch (`src/parser/statements/mod.rs`) - Added FLOW to declaration handler (`src/parser/statements/declarations.rs`) - Updated box_declaration parser to accept BOX or FLOW (`src/parser/declarations/box_definition.rs`) - Treat `flow FooBox {}` as syntactic sugar for `box FooBox {}` ### 4. Module namespace conversion - Renamed `lang.compiler.builder.ssa.local` → `localvar` (avoid keyword) - Renamed file `local.hako` → `local_ssa.hako` - Converted 152 path-based using statements to namespace format - Added 26+ entries to `nyash.toml` [modules] section ## ⚠️ Remaining Issues ### Stage-B selfhost compiler performance - Stage-B compiler not producing output (hangs/times out after 10+ seconds) - Excessive PHI debug output suggests compilation loop issue - Needs investigation: infinite loop or N² algorithm in hako compiler ### Fallback JSON version mismatch - Rust fallback (`--emit-mir-json`) emits MIR v1 JSON (schema_version: "1.0") - Smoke tests expect MIR v0 JSON (`"version":0, "kind":"Program"`) - stageb_helpers.sh fallback needs adjustment ## Test Status - Parse errors: FIXED ✅ - Keyword conflicts: FIXED ✅ - Stage-B smoke tests: STILL FAILING ❌ (performance issue) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-02 04:13:17 +09:00
// Prefer CWD nyash.toml; if missing, honor NYASH_ROOT/nyash.toml for tools that run from subdirs
let path = std::path::Path::new("nyash.toml");
feat(stage-b): Add FLOW keyword support + fix Stage-3 keyword conflicts ## ✅ Fixed Issues ### 1. `local` keyword tokenization (commit 9aab64f7) - Added Stage-3 gate for LOCAL/TRY/CATCH/THROW keywords - LOCAL now only active when NYASH_PARSER_STAGE3=1 ### 2. `env.local.get` keyword conflict - File: `lang/src/compiler/entry/compiler_stageb.hako:21-23` - Problem: `.local` in member access tokenized as `.LOCAL` keyword - Fix: Commented out `env.local.get("HAKO_SOURCE")` line - Fallback: Use `--source` argument (still functional) ### 3. `flow` keyword missing - Added FLOW to TokenType enum (`src/tokenizer/kinds.rs`) - Added "flow" → TokenType::FLOW mapping (`src/tokenizer/lex_ident.rs`) - Added FLOW to Stage-3 gate (requires NYASH_PARSER_STAGE3=1) - Added FLOW to parser statement dispatch (`src/parser/statements/mod.rs`) - Added FLOW to declaration handler (`src/parser/statements/declarations.rs`) - Updated box_declaration parser to accept BOX or FLOW (`src/parser/declarations/box_definition.rs`) - Treat `flow FooBox {}` as syntactic sugar for `box FooBox {}` ### 4. Module namespace conversion - Renamed `lang.compiler.builder.ssa.local` → `localvar` (avoid keyword) - Renamed file `local.hako` → `local_ssa.hako` - Converted 152 path-based using statements to namespace format - Added 26+ entries to `nyash.toml` [modules] section ## ⚠️ Remaining Issues ### Stage-B selfhost compiler performance - Stage-B compiler not producing output (hangs/times out after 10+ seconds) - Excessive PHI debug output suggests compilation loop issue - Needs investigation: infinite loop or N² algorithm in hako compiler ### Fallback JSON version mismatch - Rust fallback (`--emit-mir-json`) emits MIR v1 JSON (schema_version: "1.0") - Smoke tests expect MIR v0 JSON (`"version":0, "kind":"Program"`) - stageb_helpers.sh fallback needs adjustment ## Test Status - Parse errors: FIXED ✅ - Keyword conflicts: FIXED ✅ - Stage-B smoke tests: STILL FAILING ❌ (performance issue) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-02 04:13:17 +09:00
let text = if path.exists() {
std::fs::read_to_string(path)
} else if let Ok(root) = std::env::var("NYASH_ROOT") {
let alt = std::path::Path::new(&root).join("nyash.toml");
if alt.exists() { std::fs::read_to_string(alt) } else { return Ok(policy); }
} else {
return Ok(policy);
}
.map_err(|e| UsingError::ReadToml(e.to_string()))?;
let doc = toml::from_str::<toml::Value>(&text)
.map_err(|e| UsingError::ParseToml(e.to_string()))?;
// [modules] table flatten: supports nested namespaces (a.b.c = "path")
if let Some(mods) = doc.get("modules").and_then(|v| v.as_table()) {
fn visit(prefix: &str, tbl: &toml::value::Table, out: &mut Vec<(String, String)>) {
for (k, v) in tbl.iter() {
let name = if prefix.is_empty() { k.to_string() } else { format!("{}.{}", prefix, k) };
if let Some(s) = v.as_str() {
out.push((name, s.to_string()));
} else if let Some(t) = v.as_table() {
visit(&name, t, out);
}
}
}
visit("", mods, pending_modules);
}
// [using.paths] array
if let Some(using_tbl) = doc.get("using").and_then(|v| v.as_table()) {
// paths
if let Some(paths_arr) = using_tbl.get("paths").and_then(|v| v.as_array()) {
for p in paths_arr {
if let Some(s) = p.as_str() {
let s = s.trim();
if !s.is_empty() {
using_paths.push(s.to_string());
policy.search_paths.push(s.to_string());
}
}
}
}
// aliases
if let Some(alias_tbl) = using_tbl.get("aliases").and_then(|v| v.as_table()) {
for (k, v) in alias_tbl.iter() {
if let Some(target) = v.as_str() {
aliases.insert(k.to_string(), target.to_string());
}
}
}
// named packages: any subtable not paths/aliases is a package
for (k, v) in using_tbl.iter() {
if k == "paths" || k == "aliases" { continue; }
if let Some(tbl) = v.as_table() {
let kind = tbl.get("kind").and_then(|x| x.as_str()).map(PackageKind::from_str).unwrap_or(PackageKind::Package);
// path is required
if let Some(path_s) = tbl.get("path").and_then(|x| x.as_str()) {
let path = path_s.to_string();
let main = tbl.get("main").and_then(|x| x.as_str()).map(|s| s.to_string());
let bid = tbl.get("bid").and_then(|x| x.as_str()).map(|s| s.to_string());
packages.insert(k.to_string(), UsingPackage { kind, path, main, bid });
}
}
}
}
// legacy top-level [aliases] also accepted (migration)
if let Some(alias_tbl) = doc.get("aliases").and_then(|v| v.as_table()) {
for (k, v) in alias_tbl.iter() {
if let Some(target) = v.as_str() {
aliases.insert(k.to_string(), target.to_string());
}
}
}
Ok(policy)
}