Files
hakorune/src/runner/pipeline.rs

695 lines
26 KiB
Rust
Raw Normal View History

/*!
* Runner pipeline helpers using/modules/env pre-processing
*
* Extracts the early-phase setup from runner/mod.rs:
* - load nyash.toml [modules] and [using.paths]
* - merge with defaults and env overrides
* - expose context (using_paths, pending_modules) for downstream resolution
*/
use super::*;
use crate::using::spec::{PackageKind, UsingPackage};
Phase 22.1 WIP: SSOT resolver + TLV infrastructure + Hako MIR builder setup Setup infrastructure for Phase 22.1 (TLV C shim & Resolver SSOT): Core changes: - Add nyash_tlv, nyash_c_core, nyash_kernel_min_c crates (opt-in) - Implement SSOT resolver bridge (src/using/ssot_bridge.rs) - Add HAKO_USING_SSOT=1 / HAKO_USING_SSOT_HAKO=1 env support - Add HAKO_TLV_SHIM=1 infrastructure (requires --features tlv-shim) MIR builder improvements: - Fix using/alias consistency in Hako MIR builder - Add hako.mir.builder.internal.{prog_scan,pattern_util} to nyash.toml - Normalize LLVM extern calls: nyash.console.* → nyash_console_* Smoke tests: - Add phase2211 tests (using_ssot_hako_parity_canary_vm.sh) - Add phase2220, phase2230, phase2231 test structure - Add phase2100 S3 backend selector tests - Improve test_runner.sh with quiet/timeout controls Documentation: - Add docs/ENV_VARS.md (Phase 22.1 env vars reference) - Add docs/development/runtime/C_CORE_ABI.md - Update de-rust-roadmap.md with Phase 22.x details Tools: - Add tools/hakorune_emit_mir.sh (Hako-first MIR emission wrapper) - Add tools/tlv_roundtrip_smoke.sh placeholder - Improve ny_mir_builder.sh with better backend selection Known issues (to be fixed): - Parser infinite loop in static method parameter parsing - Stage-B output contamination with "RC: 0" (needs NYASH_JSON_ONLY=1) - phase2211/using_ssot_hako_parity_canary_vm.sh fork bomb (needs recursion guard) Next steps: Fix parser infinite loop + Stage-B quiet mode for green tests
2025-11-09 15:11:18 +09:00
use crate::using::ssot_bridge::{call_using_resolve_ssot, SsotCtx};
use std::collections::HashMap;
/// Using/module resolution context accumulated from config/env/nyash.toml
pub(super) struct UsingContext {
pub using_paths: Vec<String>,
pub pending_modules: Vec<(String, String)>,
📚 docs: Record field declaration design discussion in papers ## Summary Documented the "init block vs fields-at-top" design discussion as a valuable example of AI-human collaboration in language design. ## Changes ### Paper G (AI Collaboration) - Added field-declaration-design.md documenting the entire discussion flow - Showcased how complex init block proposal evolved to simple "fields at top" rule - Demonstrates AI's tendency toward complexity vs human intuition for simplicity ### Paper H (AI Practical Patterns) - Added Pattern #17: "Gradual Refinement Pattern" (段階的洗練型) - Documents the process: Complex AI proposal → Detailed analysis → Human insight → Convergence - Field declaration design as a typical example ### Paper K (Explosive Incidents) - Added Incident #046: "init block vs fields-at-top incident" - Updated total count to 46 incidents - Shows how a single human comment redirected entire design approach ## Design Decision After analysis, decided that BoxIndex should remain a compiler-internal structure, not a core Box: - Core Boxes: User-instantiable runtime values (String, Integer, Array, Map) - Compiler internals: BoxIndex for name resolution (compile-time only) - Clear separation of concerns between language features and compiler tools ## Philosophy This discussion exemplifies key principles: - The best design needs no explanation - Constraints provide clarity, not limitation - "Everything is Box" doesn't mean "compiler internals are Boxes" - AI tends toward theoretical completeness; humans toward practical simplicity 🐱 Sometimes the simplest answer is right in front of us\!
2025-09-16 14:57:05 +09:00
pub aliases: std::collections::HashMap<String, String>,
pub packages: std::collections::HashMap<String, UsingPackage>,
}
impl NyashRunner {
/// Initialize using/module context from defaults, nyash.toml and env
pub(super) fn init_using_context(&self) -> UsingContext {
let mut using_paths: Vec<String> = Vec::new();
let mut pending_modules: Vec<(String, String)> = Vec::new();
let mut aliases: std::collections::HashMap<String, String> =
std::collections::HashMap::new();
let mut packages: std::collections::HashMap<String, UsingPackage> =
std::collections::HashMap::new();
// Defaults
using_paths.extend(["apps", "lib", "."].into_iter().map(|s| s.to_string()));
// nyash.toml: delegate to using resolver (keeps existing behavior)
fix(using): StringUtils using resolution - dual root cause fix 🎯 Phase 21.7++ - using StringUtils as StringUtils 完全動作化! ## Root Cause #1: TOML Parse Error (lang/src/llvm_ir/hako_module.toml) **Problem:** ```toml line 18: aot_prep = "boxes/aot_prep.hako" # scalar line 19: aot_prep.passes.strlen = "..." # table - CONFLICT! ``` → TOML parse error prevented ALL aliases from loading → populate_from_toml() returned Err, aliases.len() = 0 **Fix:** Commented out conflicting line 18: ```toml # aot_prep = "boxes/aot_prep.hako" # Commented out: conflicts with aot_prep.passes.* below aot_prep.passes.strlen = "boxes/aot_prep/passes/strlen.hako" ``` **Result:** ✅ populate_from_toml() succeeds ✅ 4 aliases loaded including StringUtils → string_utils ## Root Cause #2: Missing Arity Suffix (src/backend/mir_interpreter/handlers/calls/global.rs) **Problem:** - MIR functions stored as "BoxName.method/arity" - VM looked up "StringUtils.starts_with" (no arity) - Function table had "StringUtils.starts_with/2" (with /2) → Lookup failed with "Unknown: StringUtils.starts_with" **Fix:** Auto-append arity from args.len() if missing: ```rust let mut canonical = crate::mir::naming::normalize_static_global_name(func_name); if !canonical.contains('/') { canonical = format!("{}/{}", canonical, args.len()); } ``` **Result:** ✅ "StringUtils.starts_with" + args.len()=2 → "StringUtils.starts_with/2" ✅ VM function lookup succeeds ## Debug Infrastructure **Added comprehensive debug logging:** 1. src/runner/pipeline.rs:36-55 - NYASH_DEBUG_USING=1 for alias loading 2. src/backend/mir_interpreter/handlers/calls/global.rs:17-42 - NYASH_DEBUG_FUNCTION_LOOKUP=1 for VM lookup ## Test Coverage **src/tests/json_lint_stringutils_min_vm.rs:** - Rewrote to test arity auto-completion (not using resolution) - Inlined StringUtils implementation to avoid pipeline dependency - Tests that VM can call "StringUtils.starts_with" without arity suffix - ✅ Test passes **CLI Verification:** ```bash NYASH_PARSER_STAGE3=1 HAKO_PARSER_STAGE3=1 NYASH_DISABLE_PLUGINS=1 \ ./target/release/hakorune apps/tests/json_lint_stringutils_min.hako # Output: OK # RC: 0 ``` ## Impact - ✅ using StringUtils as StringUtils fully functional - ✅ All using aliases load successfully - ✅ VM can find functions with/without arity suffix - ✅ No breaking changes to existing code - ✅ Debug logging for future troubleshooting ## Files Modified - lang/src/llvm_ir/hako_module.toml (TOML fix) - src/runner/pipeline.rs (debug logging) - src/backend/mir_interpreter/handlers/calls/global.rs (arity fix + logging) - src/tests/json_lint_stringutils_min_vm.rs (rewrite + enable) - src/tests/mod.rs (register test) Co-authored-by: Task Agent <task@anthropic.com> Co-authored-by: Claude Code <claude@anthropic.com>
2025-11-22 01:21:38 +09:00
let toml_result = crate::using::resolver::populate_from_toml(
&mut using_paths,
&mut pending_modules,
&mut aliases,
&mut packages,
);
fix(using): StringUtils using resolution - dual root cause fix 🎯 Phase 21.7++ - using StringUtils as StringUtils 完全動作化! ## Root Cause #1: TOML Parse Error (lang/src/llvm_ir/hako_module.toml) **Problem:** ```toml line 18: aot_prep = "boxes/aot_prep.hako" # scalar line 19: aot_prep.passes.strlen = "..." # table - CONFLICT! ``` → TOML parse error prevented ALL aliases from loading → populate_from_toml() returned Err, aliases.len() = 0 **Fix:** Commented out conflicting line 18: ```toml # aot_prep = "boxes/aot_prep.hako" # Commented out: conflicts with aot_prep.passes.* below aot_prep.passes.strlen = "boxes/aot_prep/passes/strlen.hako" ``` **Result:** ✅ populate_from_toml() succeeds ✅ 4 aliases loaded including StringUtils → string_utils ## Root Cause #2: Missing Arity Suffix (src/backend/mir_interpreter/handlers/calls/global.rs) **Problem:** - MIR functions stored as "BoxName.method/arity" - VM looked up "StringUtils.starts_with" (no arity) - Function table had "StringUtils.starts_with/2" (with /2) → Lookup failed with "Unknown: StringUtils.starts_with" **Fix:** Auto-append arity from args.len() if missing: ```rust let mut canonical = crate::mir::naming::normalize_static_global_name(func_name); if !canonical.contains('/') { canonical = format!("{}/{}", canonical, args.len()); } ``` **Result:** ✅ "StringUtils.starts_with" + args.len()=2 → "StringUtils.starts_with/2" ✅ VM function lookup succeeds ## Debug Infrastructure **Added comprehensive debug logging:** 1. src/runner/pipeline.rs:36-55 - NYASH_DEBUG_USING=1 for alias loading 2. src/backend/mir_interpreter/handlers/calls/global.rs:17-42 - NYASH_DEBUG_FUNCTION_LOOKUP=1 for VM lookup ## Test Coverage **src/tests/json_lint_stringutils_min_vm.rs:** - Rewrote to test arity auto-completion (not using resolution) - Inlined StringUtils implementation to avoid pipeline dependency - Tests that VM can call "StringUtils.starts_with" without arity suffix - ✅ Test passes **CLI Verification:** ```bash NYASH_PARSER_STAGE3=1 HAKO_PARSER_STAGE3=1 NYASH_DISABLE_PLUGINS=1 \ ./target/release/hakorune apps/tests/json_lint_stringutils_min.hako # Output: OK # RC: 0 ``` ## Impact - ✅ using StringUtils as StringUtils fully functional - ✅ All using aliases load successfully - ✅ VM can find functions with/without arity suffix - ✅ No breaking changes to existing code - ✅ Debug logging for future troubleshooting ## Files Modified - lang/src/llvm_ir/hako_module.toml (TOML fix) - src/runner/pipeline.rs (debug logging) - src/backend/mir_interpreter/handlers/calls/global.rs (arity fix + logging) - src/tests/json_lint_stringutils_min_vm.rs (rewrite + enable) - src/tests/mod.rs (register test) Co-authored-by: Task Agent <task@anthropic.com> Co-authored-by: Claude Code <claude@anthropic.com>
2025-11-22 01:21:38 +09:00
// 🔍 Debug: Check if aliases are loaded
if std::env::var("NYASH_DEBUG_USING").ok().as_deref() == Some("1") {
eprintln!("[DEBUG/using] populate_from_toml result: {:?}", toml_result);
eprintln!("[DEBUG/using] Loaded {} aliases", aliases.len());
for (k, v) in aliases.iter() {
eprintln!("[DEBUG/using] alias: '{}' => '{}'", k, v);
}
eprintln!("[DEBUG/using] Loaded {} packages", packages.len());
for (k, v) in packages.iter() {
eprintln!("[DEBUG/using] package: '{}' => path='{}'", k, v.path);
}
}
feat(phase-0): 観測ライン緊急構築完了 - Silent Failure 根絶 Phase 21.7++ Phase 0: 開発者体験を劇的に向上させる3つの改善 ## 🎯 実装内容 ### ✅ Phase 0.1: populate_from_toml エラー即座表示 **ファイル**: src/runner/pipeline.rs:57-65 **Before**: TOML parse エラーが silent failure **After**: エラーを即座に警告表示 + デバッグ方法提示 ``` ⚠️ [using/workspace] Failed to load TOML modules: Error: TOML parse error at line 18... → All 'using' aliases will be unavailable → Fix TOML syntax errors in workspace modules 💡 Debug: NYASH_DEBUG_USING=1 for detailed logs ``` **効果**: 今回の StringUtils バグなら即発見できた! ### ✅ Phase 0.2: VM 関数ルックアップ常時提案 **ファイル**: src/backend/mir_interpreter/handlers/calls/global.rs:179-206 **Before**: "Unknown: StringUtils.starts_with" だけ **After**: 類似関数を自動提案 + デバッグ方法提示 ``` Function not found: StringUtils.starts_with 💡 Did you mean: - StringUtils.starts_with/2 - StringUtils.ends_with/2 🔍 Debug: NYASH_DEBUG_FUNCTION_LOOKUP=1 for full lookup trace ``` **効果**: arity 問題を即発見!環境変数不要で親切! ### ✅ Phase 0.3: using not found 詳細化 **ファイル**: src/runner/modes/common_util/resolve/strip.rs:354-389 **Before**: "'StringUtils' not found" だけ **After**: 類似モジュール提案 + 利用可能数 + 修正方法提示 ``` using: 'StringUtil' not found in nyash.toml [using]/[modules] 💡 Did you mean: - StringUtils - JsonUtils Available modules: 4 aliases 📝 Suggestions: - Add an alias in nyash.toml: [using.aliases] YourModule = "path/to/module" - Use the alias: using YourModule as YourModule - Dev/test mode: NYASH_PREINCLUDE=1 🔍 Debug: NYASH_DEBUG_USING=1 for detailed logs ``` **効果**: タイポを即発見!TOML エラーとの因果関係も提示! ## 📊 Phase 0 成果まとめ **工数**: 約2.5時間(予想: 2-3時間)✅ **効果**: Silent Failure 完全根絶 🎉 ### Before Phase 0 - TOML エラー: 無言で失敗 - 関数が見つからない: "Unknown" だけ - using が見つからない: "not found" だけ - デバッグ方法: 環境変数を知ってる人だけ ### After Phase 0 - TOML エラー: 即座に警告 + 影響範囲説明 - 関数が見つからない: 類似関数提案 + デバッグ方法 - using が見つからない: 類似モジュール提案 + 修正方法 + デバッグ方法 - すべてのエラーが親切 🎊 ## ✅ テスト結果 - StringUtils テスト: ✅ PASS - 既存テスト: ✅ 337 passed(16 failed は元々の失敗) - ビルド: ✅ SUCCESS - 退行: ❌ なし ## 🎉 開発者体験の改善 今回のような StringUtils using バグが起きても: 1. **TOML エラー**: 即発見(数秒) 2. **arity 問題**: 提案から即解決(数分) 3. **タイポ**: 提案から即修正(数秒) **Before**: 数時間のデバッグ **After**: 数分で解決 🚀 次のステップ: Phase 1(基盤整備)に進む準備完了!
2025-11-22 02:13:10 +09:00
// ⚠️ Phase 0.1: Immediate error display for TOML parse failures
if let Err(e) = &toml_result {
eprintln!("⚠️ [using/workspace] Failed to load TOML modules:");
eprintln!(" Error: {}", e);
eprintln!(" → All 'using' aliases will be unavailable");
eprintln!(" → Fix TOML syntax errors in workspace modules");
eprintln!();
eprintln!(" 💡 Debug: NYASH_DEBUG_USING=1 for detailed logs");
}
// Env overrides: modules and using paths
if let Ok(ms) = std::env::var("NYASH_MODULES") {
for ent in ms.split(',') {
if let Some((k, v)) = ent.split_once('=') {
let k = k.trim();
let v = v.trim();
if !k.is_empty() && !v.is_empty() {
pending_modules.push((k.to_string(), v.to_string()));
}
}
}
}
if let Ok(p) = std::env::var("NYASH_USING_PATH") {
for s in p.split(':') {
let s = s.trim();
if !s.is_empty() {
using_paths.push(s.to_string());
}
}
}
📚 docs: Record field declaration design discussion in papers ## Summary Documented the "init block vs fields-at-top" design discussion as a valuable example of AI-human collaboration in language design. ## Changes ### Paper G (AI Collaboration) - Added field-declaration-design.md documenting the entire discussion flow - Showcased how complex init block proposal evolved to simple "fields at top" rule - Demonstrates AI's tendency toward complexity vs human intuition for simplicity ### Paper H (AI Practical Patterns) - Added Pattern #17: "Gradual Refinement Pattern" (段階的洗練型) - Documents the process: Complex AI proposal → Detailed analysis → Human insight → Convergence - Field declaration design as a typical example ### Paper K (Explosive Incidents) - Added Incident #046: "init block vs fields-at-top incident" - Updated total count to 46 incidents - Shows how a single human comment redirected entire design approach ## Design Decision After analysis, decided that BoxIndex should remain a compiler-internal structure, not a core Box: - Core Boxes: User-instantiable runtime values (String, Integer, Array, Map) - Compiler internals: BoxIndex for name resolution (compile-time only) - Clear separation of concerns between language features and compiler tools ## Philosophy This discussion exemplifies key principles: - The best design needs no explanation - Constraints provide clarity, not limitation - "Everything is Box" doesn't mean "compiler internals are Boxes" - AI tends toward theoretical completeness; humans toward practical simplicity 🐱 Sometimes the simplest answer is right in front of us\!
2025-09-16 14:57:05 +09:00
// Env aliases: comma-separated k=v pairs
if let Ok(raw) = std::env::var("NYASH_ALIASES") {
for ent in raw.split(',') {
if let Some((k, v)) = ent.split_once('=') {
let k = k.trim();
let v = v.trim();
if !k.is_empty() && !v.is_empty() {
aliases.insert(k.to_string(), v.to_string());
}
📚 docs: Record field declaration design discussion in papers ## Summary Documented the "init block vs fields-at-top" design discussion as a valuable example of AI-human collaboration in language design. ## Changes ### Paper G (AI Collaboration) - Added field-declaration-design.md documenting the entire discussion flow - Showcased how complex init block proposal evolved to simple "fields at top" rule - Demonstrates AI's tendency toward complexity vs human intuition for simplicity ### Paper H (AI Practical Patterns) - Added Pattern #17: "Gradual Refinement Pattern" (段階的洗練型) - Documents the process: Complex AI proposal → Detailed analysis → Human insight → Convergence - Field declaration design as a typical example ### Paper K (Explosive Incidents) - Added Incident #046: "init block vs fields-at-top incident" - Updated total count to 46 incidents - Shows how a single human comment redirected entire design approach ## Design Decision After analysis, decided that BoxIndex should remain a compiler-internal structure, not a core Box: - Core Boxes: User-instantiable runtime values (String, Integer, Array, Map) - Compiler internals: BoxIndex for name resolution (compile-time only) - Clear separation of concerns between language features and compiler tools ## Philosophy This discussion exemplifies key principles: - The best design needs no explanation - Constraints provide clarity, not limitation - "Everything is Box" doesn't mean "compiler internals are Boxes" - AI tends toward theoretical completeness; humans toward practical simplicity 🐱 Sometimes the simplest answer is right in front of us\!
2025-09-16 14:57:05 +09:00
}
}
}
UsingContext {
using_paths,
pending_modules,
aliases,
packages,
}
}
}
/// Suggest candidate files by leaf name within limited bases (apps/lib/.)
#[allow(dead_code)]
pub(super) fn suggest_in_base(base: &str, leaf: &str, out: &mut Vec<String>) {
use std::fs;
fn walk(dir: &std::path::Path, leaf: &str, out: &mut Vec<String>, depth: usize) {
if depth == 0 || out.len() >= 5 {
return;
}
if let Ok(entries) = fs::read_dir(dir) {
for e in entries.flatten() {
let path = e.path();
if path.is_dir() {
walk(&path, leaf, out, depth - 1);
if out.len() >= 5 {
return;
}
} else if let Some(ext) = path.extension().and_then(|s| s.to_str()) {
if ext == "nyash" || ext == "hako" {
if let Some(stem) = path.file_stem().and_then(|s| s.to_str()) {
if stem == leaf {
out.push(path.to_string_lossy().to_string());
if out.len() >= 5 {
return;
}
}
}
}
}
}
}
}
let p = std::path::Path::new(base);
walk(p, leaf, out, 4);
}
/// Resolve a using target according to priority: modules > relative > using-paths
/// Returns Ok(resolved_path_or_token). On strict mode, ambiguous matches cause error.
pub(super) fn resolve_using_target(
tgt: &str,
is_path: bool,
modules: &[(String, String)],
using_paths: &[String],
📚 docs: Record field declaration design discussion in papers ## Summary Documented the "init block vs fields-at-top" design discussion as a valuable example of AI-human collaboration in language design. ## Changes ### Paper G (AI Collaboration) - Added field-declaration-design.md documenting the entire discussion flow - Showcased how complex init block proposal evolved to simple "fields at top" rule - Demonstrates AI's tendency toward complexity vs human intuition for simplicity ### Paper H (AI Practical Patterns) - Added Pattern #17: "Gradual Refinement Pattern" (段階的洗練型) - Documents the process: Complex AI proposal → Detailed analysis → Human insight → Convergence - Field declaration design as a typical example ### Paper K (Explosive Incidents) - Added Incident #046: "init block vs fields-at-top incident" - Updated total count to 46 incidents - Shows how a single human comment redirected entire design approach ## Design Decision After analysis, decided that BoxIndex should remain a compiler-internal structure, not a core Box: - Core Boxes: User-instantiable runtime values (String, Integer, Array, Map) - Compiler internals: BoxIndex for name resolution (compile-time only) - Clear separation of concerns between language features and compiler tools ## Philosophy This discussion exemplifies key principles: - The best design needs no explanation - Constraints provide clarity, not limitation - "Everything is Box" doesn't mean "compiler internals are Boxes" - AI tends toward theoretical completeness; humans toward practical simplicity 🐱 Sometimes the simplest answer is right in front of us\!
2025-09-16 14:57:05 +09:00
aliases: &HashMap<String, String>,
packages: &HashMap<String, UsingPackage>,
context_dir: Option<&std::path::Path>,
strict: bool,
verbose: bool,
) -> Result<String, String> {
// Dev toggle: try SSOT common resolver first, then fall back to legacy path.
// This helps migrate behavior gradually without changing defaults.
if std::env::var("HAKO_USING_RESOLVER_FIRST").ok().as_deref() == Some("1") {
match crate::using::resolver::resolve_using_target_common(
tgt,
modules,
using_paths,
packages,
context_dir,
strict,
verbose,
) {
Ok(val) => return Ok(val),
Err(_) => { /* fall through to legacy path */ }
}
}
Phase 22.1 WIP: SSOT resolver + TLV infrastructure + Hako MIR builder setup Setup infrastructure for Phase 22.1 (TLV C shim & Resolver SSOT): Core changes: - Add nyash_tlv, nyash_c_core, nyash_kernel_min_c crates (opt-in) - Implement SSOT resolver bridge (src/using/ssot_bridge.rs) - Add HAKO_USING_SSOT=1 / HAKO_USING_SSOT_HAKO=1 env support - Add HAKO_TLV_SHIM=1 infrastructure (requires --features tlv-shim) MIR builder improvements: - Fix using/alias consistency in Hako MIR builder - Add hako.mir.builder.internal.{prog_scan,pattern_util} to nyash.toml - Normalize LLVM extern calls: nyash.console.* → nyash_console_* Smoke tests: - Add phase2211 tests (using_ssot_hako_parity_canary_vm.sh) - Add phase2220, phase2230, phase2231 test structure - Add phase2100 S3 backend selector tests - Improve test_runner.sh with quiet/timeout controls Documentation: - Add docs/ENV_VARS.md (Phase 22.1 env vars reference) - Add docs/development/runtime/C_CORE_ABI.md - Update de-rust-roadmap.md with Phase 22.x details Tools: - Add tools/hakorune_emit_mir.sh (Hako-first MIR emission wrapper) - Add tools/tlv_roundtrip_smoke.sh placeholder - Improve ny_mir_builder.sh with better backend selection Known issues (to be fixed): - Parser infinite loop in static method parameter parsing - Stage-B output contamination with "RC: 0" (needs NYASH_JSON_ONLY=1) - phase2211/using_ssot_hako_parity_canary_vm.sh fork bomb (needs recursion guard) Next steps: Fix parser infinite loop + Stage-B quiet mode for green tests
2025-11-09 15:11:18 +09:00
// Phase 22.1: Thin SSOT hook (future wiring). No behavior change for now.
if std::env::var("HAKO_USING_SSOT").ok().as_deref() == Some("1")
&& std::env::var("HAKO_USING_SSOT_INVOKING").ok().as_deref() != Some("1")
Phase 22.1 WIP: SSOT resolver + TLV infrastructure + Hako MIR builder setup Setup infrastructure for Phase 22.1 (TLV C shim & Resolver SSOT): Core changes: - Add nyash_tlv, nyash_c_core, nyash_kernel_min_c crates (opt-in) - Implement SSOT resolver bridge (src/using/ssot_bridge.rs) - Add HAKO_USING_SSOT=1 / HAKO_USING_SSOT_HAKO=1 env support - Add HAKO_TLV_SHIM=1 infrastructure (requires --features tlv-shim) MIR builder improvements: - Fix using/alias consistency in Hako MIR builder - Add hako.mir.builder.internal.{prog_scan,pattern_util} to nyash.toml - Normalize LLVM extern calls: nyash.console.* → nyash_console_* Smoke tests: - Add phase2211 tests (using_ssot_hako_parity_canary_vm.sh) - Add phase2220, phase2230, phase2231 test structure - Add phase2100 S3 backend selector tests - Improve test_runner.sh with quiet/timeout controls Documentation: - Add docs/ENV_VARS.md (Phase 22.1 env vars reference) - Add docs/development/runtime/C_CORE_ABI.md - Update de-rust-roadmap.md with Phase 22.x details Tools: - Add tools/hakorune_emit_mir.sh (Hako-first MIR emission wrapper) - Add tools/tlv_roundtrip_smoke.sh placeholder - Improve ny_mir_builder.sh with better backend selection Known issues (to be fixed): - Parser infinite loop in static method parameter parsing - Stage-B output contamination with "RC: 0" (needs NYASH_JSON_ONLY=1) - phase2211/using_ssot_hako_parity_canary_vm.sh fork bomb (needs recursion guard) Next steps: Fix parser infinite loop + Stage-B quiet mode for green tests
2025-11-09 15:11:18 +09:00
{
if let Some(ssot_res) = try_resolve_using_target_ssot(
tgt,
is_path,
modules,
using_paths,
aliases,
packages,
context_dir,
strict,
verbose,
Phase 22.1 WIP: SSOT resolver + TLV infrastructure + Hako MIR builder setup Setup infrastructure for Phase 22.1 (TLV C shim & Resolver SSOT): Core changes: - Add nyash_tlv, nyash_c_core, nyash_kernel_min_c crates (opt-in) - Implement SSOT resolver bridge (src/using/ssot_bridge.rs) - Add HAKO_USING_SSOT=1 / HAKO_USING_SSOT_HAKO=1 env support - Add HAKO_TLV_SHIM=1 infrastructure (requires --features tlv-shim) MIR builder improvements: - Fix using/alias consistency in Hako MIR builder - Add hako.mir.builder.internal.{prog_scan,pattern_util} to nyash.toml - Normalize LLVM extern calls: nyash.console.* → nyash_console_* Smoke tests: - Add phase2211 tests (using_ssot_hako_parity_canary_vm.sh) - Add phase2220, phase2230, phase2231 test structure - Add phase2100 S3 backend selector tests - Improve test_runner.sh with quiet/timeout controls Documentation: - Add docs/ENV_VARS.md (Phase 22.1 env vars reference) - Add docs/development/runtime/C_CORE_ABI.md - Update de-rust-roadmap.md with Phase 22.x details Tools: - Add tools/hakorune_emit_mir.sh (Hako-first MIR emission wrapper) - Add tools/tlv_roundtrip_smoke.sh placeholder - Improve ny_mir_builder.sh with better backend selection Known issues (to be fixed): - Parser infinite loop in static method parameter parsing - Stage-B output contamination with "RC: 0" (needs NYASH_JSON_ONLY=1) - phase2211/using_ssot_hako_parity_canary_vm.sh fork bomb (needs recursion guard) Next steps: Fix parser infinite loop + Stage-B quiet mode for green tests
2025-11-09 15:11:18 +09:00
) {
return Ok(ssot_res);
}
}
// Invalidate and rebuild index/cache if env or nyash.toml changed
super::box_index::rebuild_if_env_changed();
if is_path {
return Ok(tgt.to_string());
}
let trace = verbose || crate::config::env::env_bool("NYASH_RESOLVE_TRACE");
let idx = super::box_index::get_box_index();
let mut strict_effective = strict || idx.plugins_require_prefix_global;
if crate::config::env::env_bool("NYASH_PLUGIN_REQUIRE_PREFIX") {
strict_effective = true;
}
let meta_for_target = idx.plugin_meta_by_box.get(tgt).cloned();
let mut require_prefix_target = meta_for_target
.as_ref()
.map(|m| m.require_prefix)
.unwrap_or(false);
if let Some(m) = &meta_for_target {
if !m.expose_short_names {
require_prefix_target = true;
}
}
let mut is_plugin_short = meta_for_target.is_some();
if !is_plugin_short {
is_plugin_short = idx.plugin_boxes.contains(tgt)
|| super::box_index::BoxIndex::is_known_plugin_short(tgt);
}
if (strict_effective || require_prefix_target) && is_plugin_short && !tgt.contains('.') {
let mut msg = format!("plugin short name '{}' requires prefix", tgt);
if let Some(meta) = &meta_for_target {
if let Some(pref) = &meta.prefix {
msg.push_str(&format!(" (use '{}.{}')", pref, tgt));
📚 docs: Record field declaration design discussion in papers ## Summary Documented the "init block vs fields-at-top" design discussion as a valuable example of AI-human collaboration in language design. ## Changes ### Paper G (AI Collaboration) - Added field-declaration-design.md documenting the entire discussion flow - Showcased how complex init block proposal evolved to simple "fields at top" rule - Demonstrates AI's tendency toward complexity vs human intuition for simplicity ### Paper H (AI Practical Patterns) - Added Pattern #17: "Gradual Refinement Pattern" (段階的洗練型) - Documents the process: Complex AI proposal → Detailed analysis → Human insight → Convergence - Field declaration design as a typical example ### Paper K (Explosive Incidents) - Added Incident #046: "init block vs fields-at-top incident" - Updated total count to 46 incidents - Shows how a single human comment redirected entire design approach ## Design Decision After analysis, decided that BoxIndex should remain a compiler-internal structure, not a core Box: - Core Boxes: User-instantiable runtime values (String, Integer, Array, Map) - Compiler internals: BoxIndex for name resolution (compile-time only) - Clear separation of concerns between language features and compiler tools ## Philosophy This discussion exemplifies key principles: - The best design needs no explanation - Constraints provide clarity, not limitation - "Everything is Box" doesn't mean "compiler internals are Boxes" - AI tends toward theoretical completeness; humans toward practical simplicity 🐱 Sometimes the simplest answer is right in front of us\!
2025-09-16 14:57:05 +09:00
}
}
return Err(msg);
📚 docs: Record field declaration design discussion in papers ## Summary Documented the "init block vs fields-at-top" design discussion as a valuable example of AI-human collaboration in language design. ## Changes ### Paper G (AI Collaboration) - Added field-declaration-design.md documenting the entire discussion flow - Showcased how complex init block proposal evolved to simple "fields at top" rule - Demonstrates AI's tendency toward complexity vs human intuition for simplicity ### Paper H (AI Practical Patterns) - Added Pattern #17: "Gradual Refinement Pattern" (段階的洗練型) - Documents the process: Complex AI proposal → Detailed analysis → Human insight → Convergence - Field declaration design as a typical example ### Paper K (Explosive Incidents) - Added Incident #046: "init block vs fields-at-top incident" - Updated total count to 46 incidents - Shows how a single human comment redirected entire design approach ## Design Decision After analysis, decided that BoxIndex should remain a compiler-internal structure, not a core Box: - Core Boxes: User-instantiable runtime values (String, Integer, Array, Map) - Compiler internals: BoxIndex for name resolution (compile-time only) - Clear separation of concerns between language features and compiler tools ## Philosophy This discussion exemplifies key principles: - The best design needs no explanation - Constraints provide clarity, not limitation - "Everything is Box" doesn't mean "compiler internals are Boxes" - AI tends toward theoretical completeness; humans toward practical simplicity 🐱 Sometimes the simplest answer is right in front of us\!
2025-09-16 14:57:05 +09:00
}
let key = {
let base = context_dir.and_then(|p| p.to_str()).unwrap_or("");
format!(
"{}|{}|{}|{}",
tgt,
base,
strict as i32,
using_paths.join(":")
)
📚 docs: Record field declaration design discussion in papers ## Summary Documented the "init block vs fields-at-top" design discussion as a valuable example of AI-human collaboration in language design. ## Changes ### Paper G (AI Collaboration) - Added field-declaration-design.md documenting the entire discussion flow - Showcased how complex init block proposal evolved to simple "fields at top" rule - Demonstrates AI's tendency toward complexity vs human intuition for simplicity ### Paper H (AI Practical Patterns) - Added Pattern #17: "Gradual Refinement Pattern" (段階的洗練型) - Documents the process: Complex AI proposal → Detailed analysis → Human insight → Convergence - Field declaration design as a typical example ### Paper K (Explosive Incidents) - Added Incident #046: "init block vs fields-at-top incident" - Updated total count to 46 incidents - Shows how a single human comment redirected entire design approach ## Design Decision After analysis, decided that BoxIndex should remain a compiler-internal structure, not a core Box: - Core Boxes: User-instantiable runtime values (String, Integer, Array, Map) - Compiler internals: BoxIndex for name resolution (compile-time only) - Clear separation of concerns between language features and compiler tools ## Philosophy This discussion exemplifies key principles: - The best design needs no explanation - Constraints provide clarity, not limitation - "Everything is Box" doesn't mean "compiler internals are Boxes" - AI tends toward theoretical completeness; humans toward practical simplicity 🐱 Sometimes the simplest answer is right in front of us\!
2025-09-16 14:57:05 +09:00
};
if let Some(hit) = crate::runner::box_index::cache_get(&key) {
if trace {
crate::runner::trace::log(format!("[using/cache] '{}' -> '{}'", tgt, hit));
}
📚 docs: Record field declaration design discussion in papers ## Summary Documented the "init block vs fields-at-top" design discussion as a valuable example of AI-human collaboration in language design. ## Changes ### Paper G (AI Collaboration) - Added field-declaration-design.md documenting the entire discussion flow - Showcased how complex init block proposal evolved to simple "fields at top" rule - Demonstrates AI's tendency toward complexity vs human intuition for simplicity ### Paper H (AI Practical Patterns) - Added Pattern #17: "Gradual Refinement Pattern" (段階的洗練型) - Documents the process: Complex AI proposal → Detailed analysis → Human insight → Convergence - Field declaration design as a typical example ### Paper K (Explosive Incidents) - Added Incident #046: "init block vs fields-at-top incident" - Updated total count to 46 incidents - Shows how a single human comment redirected entire design approach ## Design Decision After analysis, decided that BoxIndex should remain a compiler-internal structure, not a core Box: - Core Boxes: User-instantiable runtime values (String, Integer, Array, Map) - Compiler internals: BoxIndex for name resolution (compile-time only) - Clear separation of concerns between language features and compiler tools ## Philosophy This discussion exemplifies key principles: - The best design needs no explanation - Constraints provide clarity, not limitation - "Everything is Box" doesn't mean "compiler internals are Boxes" - AI tends toward theoretical completeness; humans toward practical simplicity 🐱 Sometimes the simplest answer is right in front of us\!
2025-09-16 14:57:05 +09:00
return Ok(hit);
}
// Resolve aliases early推移的に
// - ループ/循環を検出して早期エラー
// - 10段まで防衛的
if let Some(_) = aliases.get(tgt) {
use std::collections::HashSet;
let mut seen: HashSet<String> = HashSet::new();
let mut cur = tgt.to_string();
let mut depth = 0usize;
while let Some(next) = aliases.get(&cur).cloned() {
if trace {
crate::runner::trace::log(format!("[using/resolve] alias '{}' -> '{}'", cur, next));
}
if !seen.insert(cur.clone()) {
return Err(format!("alias cycle detected at '{}'", cur));
}
cur = next;
depth += 1;
if depth > 10 {
return Err(format!("alias resolution too deep starting at '{}'", tgt));
}
// Continue while next is also an alias; break when concrete
if !aliases.contains_key(&cur) {
break;
}
}
// Recurse once into final target to materialize path/token
let rec = resolve_using_target(
&cur,
false,
modules,
using_paths,
aliases,
packages,
context_dir,
strict,
verbose,
)?;
crate::runner::box_index::cache_put(&key, rec.clone());
return Ok(rec);
}
// Named packages (nyash.toml [using.<name>])
if let Some(pkg) = packages.get(tgt) {
match pkg.kind {
PackageKind::Dylib => {
// Return a marker token to avoid inlining attempts; loader will consume later stages
let out = format!("dylib:{}", pkg.path);
if trace {
crate::runner::trace::log(format!(
"[using/resolve] dylib '{}' -> '{}'",
tgt, out
));
}
crate::runner::box_index::cache_put(&key, out.clone());
return Ok(out);
}
PackageKind::Package => {
// Compute entry: main or <dir_last>.hako
let base = std::path::Path::new(&pkg.path);
let out = if let Some(m) = &pkg.main {
if matches!(
base.extension().and_then(|s| s.to_str()),
Some("nyash") | Some("hako")
) {
// path is a file; ignore main and use as-is
pkg.path.clone()
} else {
base.join(m).to_string_lossy().to_string()
}
} else {
if matches!(
base.extension().and_then(|s| s.to_str()),
Some("nyash") | Some("hako")
) {
pkg.path.clone()
} else {
let leaf = base.file_name().and_then(|s| s.to_str()).unwrap_or(tgt);
// prefer .hako when package path points to a directory without explicit main
let hako = base.join(format!("{}.hako", leaf));
if hako.exists() {
hako.to_string_lossy().to_string()
} else {
base.join(format!("{}.hako", leaf))
.to_string_lossy()
.to_string()
}
}
};
if trace {
crate::runner::trace::log(format!(
"[using/resolve] package '{}' -> '{}'",
tgt, out
));
}
crate::runner::box_index::cache_put(&key, out.clone());
return Ok(out);
}
}
📚 docs: Record field declaration design discussion in papers ## Summary Documented the "init block vs fields-at-top" design discussion as a valuable example of AI-human collaboration in language design. ## Changes ### Paper G (AI Collaboration) - Added field-declaration-design.md documenting the entire discussion flow - Showcased how complex init block proposal evolved to simple "fields at top" rule - Demonstrates AI's tendency toward complexity vs human intuition for simplicity ### Paper H (AI Practical Patterns) - Added Pattern #17: "Gradual Refinement Pattern" (段階的洗練型) - Documents the process: Complex AI proposal → Detailed analysis → Human insight → Convergence - Field declaration design as a typical example ### Paper K (Explosive Incidents) - Added Incident #046: "init block vs fields-at-top incident" - Updated total count to 46 incidents - Shows how a single human comment redirected entire design approach ## Design Decision After analysis, decided that BoxIndex should remain a compiler-internal structure, not a core Box: - Core Boxes: User-instantiable runtime values (String, Integer, Array, Map) - Compiler internals: BoxIndex for name resolution (compile-time only) - Clear separation of concerns between language features and compiler tools ## Philosophy This discussion exemplifies key principles: - The best design needs no explanation - Constraints provide clarity, not limitation - "Everything is Box" doesn't mean "compiler internals are Boxes" - AI tends toward theoretical completeness; humans toward practical simplicity 🐱 Sometimes the simplest answer is right in front of us\!
2025-09-16 14:57:05 +09:00
}
// Also consult env aliases
if let Ok(raw) = std::env::var("NYASH_ALIASES") {
for ent in raw.split(',') {
if let Some((k, v)) = ent.split_once('=') {
📚 docs: Record field declaration design discussion in papers ## Summary Documented the "init block vs fields-at-top" design discussion as a valuable example of AI-human collaboration in language design. ## Changes ### Paper G (AI Collaboration) - Added field-declaration-design.md documenting the entire discussion flow - Showcased how complex init block proposal evolved to simple "fields at top" rule - Demonstrates AI's tendency toward complexity vs human intuition for simplicity ### Paper H (AI Practical Patterns) - Added Pattern #17: "Gradual Refinement Pattern" (段階的洗練型) - Documents the process: Complex AI proposal → Detailed analysis → Human insight → Convergence - Field declaration design as a typical example ### Paper K (Explosive Incidents) - Added Incident #046: "init block vs fields-at-top incident" - Updated total count to 46 incidents - Shows how a single human comment redirected entire design approach ## Design Decision After analysis, decided that BoxIndex should remain a compiler-internal structure, not a core Box: - Core Boxes: User-instantiable runtime values (String, Integer, Array, Map) - Compiler internals: BoxIndex for name resolution (compile-time only) - Clear separation of concerns between language features and compiler tools ## Philosophy This discussion exemplifies key principles: - The best design needs no explanation - Constraints provide clarity, not limitation - "Everything is Box" doesn't mean "compiler internals are Boxes" - AI tends toward theoretical completeness; humans toward practical simplicity 🐱 Sometimes the simplest answer is right in front of us\!
2025-09-16 14:57:05 +09:00
if k.trim() == tgt {
let out = v.trim().to_string();
if trace {
crate::runner::trace::log(format!(
"[using/resolve] env-alias '{}' -> '{}'",
tgt, out
));
}
📚 docs: Record field declaration design discussion in papers ## Summary Documented the "init block vs fields-at-top" design discussion as a valuable example of AI-human collaboration in language design. ## Changes ### Paper G (AI Collaboration) - Added field-declaration-design.md documenting the entire discussion flow - Showcased how complex init block proposal evolved to simple "fields at top" rule - Demonstrates AI's tendency toward complexity vs human intuition for simplicity ### Paper H (AI Practical Patterns) - Added Pattern #17: "Gradual Refinement Pattern" (段階的洗練型) - Documents the process: Complex AI proposal → Detailed analysis → Human insight → Convergence - Field declaration design as a typical example ### Paper K (Explosive Incidents) - Added Incident #046: "init block vs fields-at-top incident" - Updated total count to 46 incidents - Shows how a single human comment redirected entire design approach ## Design Decision After analysis, decided that BoxIndex should remain a compiler-internal structure, not a core Box: - Core Boxes: User-instantiable runtime values (String, Integer, Array, Map) - Compiler internals: BoxIndex for name resolution (compile-time only) - Clear separation of concerns between language features and compiler tools ## Philosophy This discussion exemplifies key principles: - The best design needs no explanation - Constraints provide clarity, not limitation - "Everything is Box" doesn't mean "compiler internals are Boxes" - AI tends toward theoretical completeness; humans toward practical simplicity 🐱 Sometimes the simplest answer is right in front of us\!
2025-09-16 14:57:05 +09:00
crate::runner::box_index::cache_put(&key, out.clone());
return Ok(out);
}
}
}
}
// 2) Special handling for built-in namespaces
if tgt == "nyashstd" {
let out = "builtin:nyashstd".to_string();
if trace {
crate::runner::trace::log(format!("[using/resolve] builtin '{}' -> '{}'", tgt, out));
}
crate::runner::box_index::cache_put(&key, out.clone());
return Ok(out);
}
// 3) delegate resolution to using::resolver (SSOT)
match crate::using::resolver::resolve_using_target_common(
tgt,
modules,
using_paths,
packages,
context_dir,
strict,
verbose,
) {
Ok(val) => {
crate::runner::box_index::cache_put(&key, val.clone());
Ok(val)
}
Err(e) => {
// Maintain previous behavior: return original name and log when unresolved
if trace {
crate::runner::trace::log(format!("[using] unresolved '{}' ({})", tgt, e));
} else {
eprintln!("[using] not found: '{}'", tgt);
}
Ok(tgt.to_string())
📚 docs: Record field declaration design discussion in papers ## Summary Documented the "init block vs fields-at-top" design discussion as a valuable example of AI-human collaboration in language design. ## Changes ### Paper G (AI Collaboration) - Added field-declaration-design.md documenting the entire discussion flow - Showcased how complex init block proposal evolved to simple "fields at top" rule - Demonstrates AI's tendency toward complexity vs human intuition for simplicity ### Paper H (AI Practical Patterns) - Added Pattern #17: "Gradual Refinement Pattern" (段階的洗練型) - Documents the process: Complex AI proposal → Detailed analysis → Human insight → Convergence - Field declaration design as a typical example ### Paper K (Explosive Incidents) - Added Incident #046: "init block vs fields-at-top incident" - Updated total count to 46 incidents - Shows how a single human comment redirected entire design approach ## Design Decision After analysis, decided that BoxIndex should remain a compiler-internal structure, not a core Box: - Core Boxes: User-instantiable runtime values (String, Integer, Array, Map) - Compiler internals: BoxIndex for name resolution (compile-time only) - Clear separation of concerns between language features and compiler tools ## Philosophy This discussion exemplifies key principles: - The best design needs no explanation - Constraints provide clarity, not limitation - "Everything is Box" doesn't mean "compiler internals are Boxes" - AI tends toward theoretical completeness; humans toward practical simplicity 🐱 Sometimes the simplest answer is right in front of us\!
2025-09-16 14:57:05 +09:00
}
}
📚 docs: Record field declaration design discussion in papers ## Summary Documented the "init block vs fields-at-top" design discussion as a valuable example of AI-human collaboration in language design. ## Changes ### Paper G (AI Collaboration) - Added field-declaration-design.md documenting the entire discussion flow - Showcased how complex init block proposal evolved to simple "fields at top" rule - Demonstrates AI's tendency toward complexity vs human intuition for simplicity ### Paper H (AI Practical Patterns) - Added Pattern #17: "Gradual Refinement Pattern" (段階的洗練型) - Documents the process: Complex AI proposal → Detailed analysis → Human insight → Convergence - Field declaration design as a typical example ### Paper K (Explosive Incidents) - Added Incident #046: "init block vs fields-at-top incident" - Updated total count to 46 incidents - Shows how a single human comment redirected entire design approach ## Design Decision After analysis, decided that BoxIndex should remain a compiler-internal structure, not a core Box: - Core Boxes: User-instantiable runtime values (String, Integer, Array, Map) - Compiler internals: BoxIndex for name resolution (compile-time only) - Clear separation of concerns between language features and compiler tools ## Philosophy This discussion exemplifies key principles: - The best design needs no explanation - Constraints provide clarity, not limitation - "Everything is Box" doesn't mean "compiler internals are Boxes" - AI tends toward theoretical completeness; humans toward practical simplicity 🐱 Sometimes the simplest answer is right in front of us\!
2025-09-16 14:57:05 +09:00
}
Phase 22.1 WIP: SSOT resolver + TLV infrastructure + Hako MIR builder setup Setup infrastructure for Phase 22.1 (TLV C shim & Resolver SSOT): Core changes: - Add nyash_tlv, nyash_c_core, nyash_kernel_min_c crates (opt-in) - Implement SSOT resolver bridge (src/using/ssot_bridge.rs) - Add HAKO_USING_SSOT=1 / HAKO_USING_SSOT_HAKO=1 env support - Add HAKO_TLV_SHIM=1 infrastructure (requires --features tlv-shim) MIR builder improvements: - Fix using/alias consistency in Hako MIR builder - Add hako.mir.builder.internal.{prog_scan,pattern_util} to nyash.toml - Normalize LLVM extern calls: nyash.console.* → nyash_console_* Smoke tests: - Add phase2211 tests (using_ssot_hako_parity_canary_vm.sh) - Add phase2220, phase2230, phase2231 test structure - Add phase2100 S3 backend selector tests - Improve test_runner.sh with quiet/timeout controls Documentation: - Add docs/ENV_VARS.md (Phase 22.1 env vars reference) - Add docs/development/runtime/C_CORE_ABI.md - Update de-rust-roadmap.md with Phase 22.x details Tools: - Add tools/hakorune_emit_mir.sh (Hako-first MIR emission wrapper) - Add tools/tlv_roundtrip_smoke.sh placeholder - Improve ny_mir_builder.sh with better backend selection Known issues (to be fixed): - Parser infinite loop in static method parameter parsing - Stage-B output contamination with "RC: 0" (needs NYASH_JSON_ONLY=1) - phase2211/using_ssot_hako_parity_canary_vm.sh fork bomb (needs recursion guard) Next steps: Fix parser infinite loop + Stage-B quiet mode for green tests
2025-11-09 15:11:18 +09:00
/// Thin SSOT wrapper — returns Some(resolved) when an alternative SSOT path is available.
/// MVP: return None to keep current behavior. Future: call into Hako `UsingResolveSSOTBox`.
#[allow(clippy::too_many_arguments)]
fn try_resolve_using_target_ssot(
tgt: &str,
is_path: bool,
modules: &[(String, String)],
using_paths: &[String],
aliases: &HashMap<String, String>,
packages: &HashMap<String, UsingPackage>,
context_dir: Option<&std::path::Path>,
strict: bool,
verbose: bool,
) -> Option<String> {
// Phase 22.1 MVP: Build context and consult SSOT bridge (modules-only).
let trace = verbose || crate::config::env::env_bool("NYASH_RESOLVE_TRACE");
let mut map: HashMap<String, String> = HashMap::new();
for (k, v) in modules {
map.insert(k.clone(), v.clone());
}
let cwd_str = context_dir.and_then(|p| p.to_str()).map(|s| s.to_string());
let ctx = SsotCtx {
modules: map,
using_paths: using_paths.to_vec(),
cwd: cwd_str,
};
Phase 22.1 WIP: SSOT resolver + TLV infrastructure + Hako MIR builder setup Setup infrastructure for Phase 22.1 (TLV C shim & Resolver SSOT): Core changes: - Add nyash_tlv, nyash_c_core, nyash_kernel_min_c crates (opt-in) - Implement SSOT resolver bridge (src/using/ssot_bridge.rs) - Add HAKO_USING_SSOT=1 / HAKO_USING_SSOT_HAKO=1 env support - Add HAKO_TLV_SHIM=1 infrastructure (requires --features tlv-shim) MIR builder improvements: - Fix using/alias consistency in Hako MIR builder - Add hako.mir.builder.internal.{prog_scan,pattern_util} to nyash.toml - Normalize LLVM extern calls: nyash.console.* → nyash_console_* Smoke tests: - Add phase2211 tests (using_ssot_hako_parity_canary_vm.sh) - Add phase2220, phase2230, phase2231 test structure - Add phase2100 S3 backend selector tests - Improve test_runner.sh with quiet/timeout controls Documentation: - Add docs/ENV_VARS.md (Phase 22.1 env vars reference) - Add docs/development/runtime/C_CORE_ABI.md - Update de-rust-roadmap.md with Phase 22.x details Tools: - Add tools/hakorune_emit_mir.sh (Hako-first MIR emission wrapper) - Add tools/tlv_roundtrip_smoke.sh placeholder - Improve ny_mir_builder.sh with better backend selection Known issues (to be fixed): - Parser infinite loop in static method parameter parsing - Stage-B output contamination with "RC: 0" (needs NYASH_JSON_ONLY=1) - phase2211/using_ssot_hako_parity_canary_vm.sh fork bomb (needs recursion guard) Next steps: Fix parser infinite loop + Stage-B quiet mode for green tests
2025-11-09 15:11:18 +09:00
if let Some(hit) = call_using_resolve_ssot(tgt, &ctx) {
if trace {
crate::runner::trace::log(format!("[using/ssot] '{}' -> '{}'", tgt, hit));
}
return Some(hit);
}
// Optional relative inference (Runner-side, guarded): prefer cwd > using_paths
if std::env::var("HAKO_USING_SSOT_RELATIVE").ok().as_deref() == Some("1") {
let rel_hako = tgt.replace('.', "/") + ".hako";
let rel_ny = tgt.replace('.', "/") + ".nyash";
let mut try_paths: Vec<std::path::PathBuf> = Vec::new();
if let Some(dir) = context_dir {
try_paths.push(dir.join(&rel_hako));
try_paths.push(dir.join(&rel_ny));
}
for base in using_paths {
let p = std::path::Path::new(base);
try_paths.push(p.join(&rel_hako));
try_paths.push(p.join(&rel_ny));
}
let mut found: Vec<String> = Vec::new();
for p in try_paths {
if p.exists() {
found.push(p.to_string_lossy().to_string());
}
}
if !found.is_empty() {
if found.len() > 1 && strict {
if trace {
let total = found.len();
// Allow customizing the number of shown candidates via env (bounded 1..=10)
let n_show: usize = std::env::var("HAKO_USING_SSOT_RELATIVE_AMBIG_FIRST_N")
.ok()
.and_then(|s| s.parse::<usize>().ok())
.map(|n| n.clamp(1, 10))
.unwrap_or(3);
let shown: Vec<String> = found.iter().take(n_show).cloned().collect();
// Standardized message: count + first N + explicit delegation policy
crate::runner::trace::log(format!(
"[using/ssot:relative ambiguous] name='{}' count={} first=[{}] -> delegate=legacy(strict)",
tgt,
total,
shown.join(", ")
));
}
// Strict ambiguity: delegate to legacy resolver (behavior unchanged)
} else {
let out = found.remove(0);
if trace {
crate::runner::trace::log(format!(
"[using/ssot:relative] '{}' -> '{}' (priority=cwd>using_paths)",
tgt, out
));
}
return Some(out);
}
}
}
// Fallback: keep parity by delegating to existing resolver within the same gate
let prev = std::env::var("HAKO_USING_SSOT_INVOKING").ok();
std::env::set_var("HAKO_USING_SSOT_INVOKING", "1");
let res = resolve_using_target(
tgt,
is_path,
modules,
using_paths,
aliases,
packages,
context_dir,
strict,
verbose,
Phase 22.1 WIP: SSOT resolver + TLV infrastructure + Hako MIR builder setup Setup infrastructure for Phase 22.1 (TLV C shim & Resolver SSOT): Core changes: - Add nyash_tlv, nyash_c_core, nyash_kernel_min_c crates (opt-in) - Implement SSOT resolver bridge (src/using/ssot_bridge.rs) - Add HAKO_USING_SSOT=1 / HAKO_USING_SSOT_HAKO=1 env support - Add HAKO_TLV_SHIM=1 infrastructure (requires --features tlv-shim) MIR builder improvements: - Fix using/alias consistency in Hako MIR builder - Add hako.mir.builder.internal.{prog_scan,pattern_util} to nyash.toml - Normalize LLVM extern calls: nyash.console.* → nyash_console_* Smoke tests: - Add phase2211 tests (using_ssot_hako_parity_canary_vm.sh) - Add phase2220, phase2230, phase2231 test structure - Add phase2100 S3 backend selector tests - Improve test_runner.sh with quiet/timeout controls Documentation: - Add docs/ENV_VARS.md (Phase 22.1 env vars reference) - Add docs/development/runtime/C_CORE_ABI.md - Update de-rust-roadmap.md with Phase 22.x details Tools: - Add tools/hakorune_emit_mir.sh (Hako-first MIR emission wrapper) - Add tools/tlv_roundtrip_smoke.sh placeholder - Improve ny_mir_builder.sh with better backend selection Known issues (to be fixed): - Parser infinite loop in static method parameter parsing - Stage-B output contamination with "RC: 0" (needs NYASH_JSON_ONLY=1) - phase2211/using_ssot_hako_parity_canary_vm.sh fork bomb (needs recursion guard) Next steps: Fix parser infinite loop + Stage-B quiet mode for green tests
2025-11-09 15:11:18 +09:00
);
if let Some(val) = prev {
std::env::set_var("HAKO_USING_SSOT_INVOKING", val);
} else {
let _ = std::env::remove_var("HAKO_USING_SSOT_INVOKING");
}
Phase 22.1 WIP: SSOT resolver + TLV infrastructure + Hako MIR builder setup Setup infrastructure for Phase 22.1 (TLV C shim & Resolver SSOT): Core changes: - Add nyash_tlv, nyash_c_core, nyash_kernel_min_c crates (opt-in) - Implement SSOT resolver bridge (src/using/ssot_bridge.rs) - Add HAKO_USING_SSOT=1 / HAKO_USING_SSOT_HAKO=1 env support - Add HAKO_TLV_SHIM=1 infrastructure (requires --features tlv-shim) MIR builder improvements: - Fix using/alias consistency in Hako MIR builder - Add hako.mir.builder.internal.{prog_scan,pattern_util} to nyash.toml - Normalize LLVM extern calls: nyash.console.* → nyash_console_* Smoke tests: - Add phase2211 tests (using_ssot_hako_parity_canary_vm.sh) - Add phase2220, phase2230, phase2231 test structure - Add phase2100 S3 backend selector tests - Improve test_runner.sh with quiet/timeout controls Documentation: - Add docs/ENV_VARS.md (Phase 22.1 env vars reference) - Add docs/development/runtime/C_CORE_ABI.md - Update de-rust-roadmap.md with Phase 22.x details Tools: - Add tools/hakorune_emit_mir.sh (Hako-first MIR emission wrapper) - Add tools/tlv_roundtrip_smoke.sh placeholder - Improve ny_mir_builder.sh with better backend selection Known issues (to be fixed): - Parser infinite loop in static method parameter parsing - Stage-B output contamination with "RC: 0" (needs NYASH_JSON_ONLY=1) - phase2211/using_ssot_hako_parity_canary_vm.sh fork bomb (needs recursion guard) Next steps: Fix parser infinite loop + Stage-B quiet mode for green tests
2025-11-09 15:11:18 +09:00
res.ok()
}
📚 docs: Record field declaration design discussion in papers ## Summary Documented the "init block vs fields-at-top" design discussion as a valuable example of AI-human collaboration in language design. ## Changes ### Paper G (AI Collaboration) - Added field-declaration-design.md documenting the entire discussion flow - Showcased how complex init block proposal evolved to simple "fields at top" rule - Demonstrates AI's tendency toward complexity vs human intuition for simplicity ### Paper H (AI Practical Patterns) - Added Pattern #17: "Gradual Refinement Pattern" (段階的洗練型) - Documents the process: Complex AI proposal → Detailed analysis → Human insight → Convergence - Field declaration design as a typical example ### Paper K (Explosive Incidents) - Added Incident #046: "init block vs fields-at-top incident" - Updated total count to 46 incidents - Shows how a single human comment redirected entire design approach ## Design Decision After analysis, decided that BoxIndex should remain a compiler-internal structure, not a core Box: - Core Boxes: User-instantiable runtime values (String, Integer, Array, Map) - Compiler internals: BoxIndex for name resolution (compile-time only) - Clear separation of concerns between language features and compiler tools ## Philosophy This discussion exemplifies key principles: - The best design needs no explanation - Constraints provide clarity, not limitation - "Everything is Box" doesn't mean "compiler internals are Boxes" - AI tends toward theoretical completeness; humans toward practical simplicity 🐱 Sometimes the simplest answer is right in front of us\!
2025-09-16 14:57:05 +09:00
/// Lint: enforce "fields must be at the top of box" rule.
/// - Warns by default (when verbose); when `strict` is true, returns Err on any violation.
pub(super) fn lint_fields_top(code: &str, strict: bool, verbose: bool) -> Result<(), String> {
let mut brace: i32 = 0;
let mut in_box = false;
let mut box_depth: i32 = 0;
let mut seen_method = false;
let mut cur_box: String = String::new();
let mut violations: Vec<(usize, String, String)> = Vec::new(); // (line, field, box)
for (idx, line) in code.lines().enumerate() {
let lno = idx + 1;
let pre_brace = brace;
let trimmed = line.trim();
// Count braces for this line
let opens = line.matches('{').count() as i32;
let closes = line.matches('}').count() as i32;
// Enter box on same-line K&R style: `box Name {` or `static box Name {`
if !in_box && trimmed.starts_with("box ") || trimmed.starts_with("static box ") {
// capture name
let mut name = String::new();
let after = if let Some(rest) = trimmed.strip_prefix("static box ") {
rest
} else {
trimmed.strip_prefix("box ").unwrap_or("")
};
📚 docs: Record field declaration design discussion in papers ## Summary Documented the "init block vs fields-at-top" design discussion as a valuable example of AI-human collaboration in language design. ## Changes ### Paper G (AI Collaboration) - Added field-declaration-design.md documenting the entire discussion flow - Showcased how complex init block proposal evolved to simple "fields at top" rule - Demonstrates AI's tendency toward complexity vs human intuition for simplicity ### Paper H (AI Practical Patterns) - Added Pattern #17: "Gradual Refinement Pattern" (段階的洗練型) - Documents the process: Complex AI proposal → Detailed analysis → Human insight → Convergence - Field declaration design as a typical example ### Paper K (Explosive Incidents) - Added Incident #046: "init block vs fields-at-top incident" - Updated total count to 46 incidents - Shows how a single human comment redirected entire design approach ## Design Decision After analysis, decided that BoxIndex should remain a compiler-internal structure, not a core Box: - Core Boxes: User-instantiable runtime values (String, Integer, Array, Map) - Compiler internals: BoxIndex for name resolution (compile-time only) - Clear separation of concerns between language features and compiler tools ## Philosophy This discussion exemplifies key principles: - The best design needs no explanation - Constraints provide clarity, not limitation - "Everything is Box" doesn't mean "compiler internals are Boxes" - AI tends toward theoretical completeness; humans toward practical simplicity 🐱 Sometimes the simplest answer is right in front of us\!
2025-09-16 14:57:05 +09:00
for ch in after.chars() {
if ch.is_alphanumeric() || ch == '_' {
name.push(ch);
} else {
break;
}
📚 docs: Record field declaration design discussion in papers ## Summary Documented the "init block vs fields-at-top" design discussion as a valuable example of AI-human collaboration in language design. ## Changes ### Paper G (AI Collaboration) - Added field-declaration-design.md documenting the entire discussion flow - Showcased how complex init block proposal evolved to simple "fields at top" rule - Demonstrates AI's tendency toward complexity vs human intuition for simplicity ### Paper H (AI Practical Patterns) - Added Pattern #17: "Gradual Refinement Pattern" (段階的洗練型) - Documents the process: Complex AI proposal → Detailed analysis → Human insight → Convergence - Field declaration design as a typical example ### Paper K (Explosive Incidents) - Added Incident #046: "init block vs fields-at-top incident" - Updated total count to 46 incidents - Shows how a single human comment redirected entire design approach ## Design Decision After analysis, decided that BoxIndex should remain a compiler-internal structure, not a core Box: - Core Boxes: User-instantiable runtime values (String, Integer, Array, Map) - Compiler internals: BoxIndex for name resolution (compile-time only) - Clear separation of concerns between language features and compiler tools ## Philosophy This discussion exemplifies key principles: - The best design needs no explanation - Constraints provide clarity, not limitation - "Everything is Box" doesn't mean "compiler internals are Boxes" - AI tends toward theoretical completeness; humans toward practical simplicity 🐱 Sometimes the simplest answer is right in front of us\!
2025-09-16 14:57:05 +09:00
}
// require K&R brace on same line to start tracking
if opens > 0 {
in_box = true;
cur_box = name;
box_depth = pre_brace + 1; // assume one level for box body
seen_method = false;
}
}
if in_box {
// Top-level inside box only
if pre_brace == box_depth {
// Skip empty/comment lines
if !trimmed.is_empty() && !trimmed.starts_with("//") {
// Detect method: name(args) {
let is_method = {
// starts with identifier then '(' and later '{'
let mut it = trimmed.chars();
let mut ident = String::new();
while let Some(c) = it.next() {
if c.is_whitespace() {
continue;
}
if c.is_alphabetic() || c == '_' {
ident.push(c);
break;
} else {
break;
}
}
while let Some(c) = it.next() {
if c.is_alphanumeric() || c == '_' {
ident.push(c);
} else {
break;
}
}
📚 docs: Record field declaration design discussion in papers ## Summary Documented the "init block vs fields-at-top" design discussion as a valuable example of AI-human collaboration in language design. ## Changes ### Paper G (AI Collaboration) - Added field-declaration-design.md documenting the entire discussion flow - Showcased how complex init block proposal evolved to simple "fields at top" rule - Demonstrates AI's tendency toward complexity vs human intuition for simplicity ### Paper H (AI Practical Patterns) - Added Pattern #17: "Gradual Refinement Pattern" (段階的洗練型) - Documents the process: Complex AI proposal → Detailed analysis → Human insight → Convergence - Field declaration design as a typical example ### Paper K (Explosive Incidents) - Added Incident #046: "init block vs fields-at-top incident" - Updated total count to 46 incidents - Shows how a single human comment redirected entire design approach ## Design Decision After analysis, decided that BoxIndex should remain a compiler-internal structure, not a core Box: - Core Boxes: User-instantiable runtime values (String, Integer, Array, Map) - Compiler internals: BoxIndex for name resolution (compile-time only) - Clear separation of concerns between language features and compiler tools ## Philosophy This discussion exemplifies key principles: - The best design needs no explanation - Constraints provide clarity, not limitation - "Everything is Box" doesn't mean "compiler internals are Boxes" - AI tends toward theoretical completeness; humans toward practical simplicity 🐱 Sometimes the simplest answer is right in front of us\!
2025-09-16 14:57:05 +09:00
trimmed.contains('(') && trimmed.ends_with('{') && !ident.is_empty()
};
if is_method {
seen_method = true;
}
📚 docs: Record field declaration design discussion in papers ## Summary Documented the "init block vs fields-at-top" design discussion as a valuable example of AI-human collaboration in language design. ## Changes ### Paper G (AI Collaboration) - Added field-declaration-design.md documenting the entire discussion flow - Showcased how complex init block proposal evolved to simple "fields at top" rule - Demonstrates AI's tendency toward complexity vs human intuition for simplicity ### Paper H (AI Practical Patterns) - Added Pattern #17: "Gradual Refinement Pattern" (段階的洗練型) - Documents the process: Complex AI proposal → Detailed analysis → Human insight → Convergence - Field declaration design as a typical example ### Paper K (Explosive Incidents) - Added Incident #046: "init block vs fields-at-top incident" - Updated total count to 46 incidents - Shows how a single human comment redirected entire design approach ## Design Decision After analysis, decided that BoxIndex should remain a compiler-internal structure, not a core Box: - Core Boxes: User-instantiable runtime values (String, Integer, Array, Map) - Compiler internals: BoxIndex for name resolution (compile-time only) - Clear separation of concerns between language features and compiler tools ## Philosophy This discussion exemplifies key principles: - The best design needs no explanation - Constraints provide clarity, not limitation - "Everything is Box" doesn't mean "compiler internals are Boxes" - AI tends toward theoretical completeness; humans toward practical simplicity 🐱 Sometimes the simplest answer is right in front of us\!
2025-09-16 14:57:05 +09:00
// Detect field: ident ':' Type (rough heuristic)
let is_field = {
let parts: Vec<&str> = trimmed.split(':').collect();
if parts.len() == 2 {
let lhs = parts[0].trim();
let rhs = parts[1].trim();
let lhs_ok = !lhs.is_empty()
&& lhs
.chars()
.next()
.map(|c| c.is_alphabetic() || c == '_')
.unwrap_or(false);
let rhs_ok = !rhs.is_empty()
&& rhs
.chars()
.next()
.map(|c| c.is_alphabetic() || c == '_')
.unwrap_or(false);
📚 docs: Record field declaration design discussion in papers ## Summary Documented the "init block vs fields-at-top" design discussion as a valuable example of AI-human collaboration in language design. ## Changes ### Paper G (AI Collaboration) - Added field-declaration-design.md documenting the entire discussion flow - Showcased how complex init block proposal evolved to simple "fields at top" rule - Demonstrates AI's tendency toward complexity vs human intuition for simplicity ### Paper H (AI Practical Patterns) - Added Pattern #17: "Gradual Refinement Pattern" (段階的洗練型) - Documents the process: Complex AI proposal → Detailed analysis → Human insight → Convergence - Field declaration design as a typical example ### Paper K (Explosive Incidents) - Added Incident #046: "init block vs fields-at-top incident" - Updated total count to 46 incidents - Shows how a single human comment redirected entire design approach ## Design Decision After analysis, decided that BoxIndex should remain a compiler-internal structure, not a core Box: - Core Boxes: User-instantiable runtime values (String, Integer, Array, Map) - Compiler internals: BoxIndex for name resolution (compile-time only) - Clear separation of concerns between language features and compiler tools ## Philosophy This discussion exemplifies key principles: - The best design needs no explanation - Constraints provide clarity, not limitation - "Everything is Box" doesn't mean "compiler internals are Boxes" - AI tends toward theoretical completeness; humans toward practical simplicity 🐱 Sometimes the simplest answer is right in front of us\!
2025-09-16 14:57:05 +09:00
lhs_ok && rhs_ok && !trimmed.contains('(') && !trimmed.contains(')')
} else {
false
}
📚 docs: Record field declaration design discussion in papers ## Summary Documented the "init block vs fields-at-top" design discussion as a valuable example of AI-human collaboration in language design. ## Changes ### Paper G (AI Collaboration) - Added field-declaration-design.md documenting the entire discussion flow - Showcased how complex init block proposal evolved to simple "fields at top" rule - Demonstrates AI's tendency toward complexity vs human intuition for simplicity ### Paper H (AI Practical Patterns) - Added Pattern #17: "Gradual Refinement Pattern" (段階的洗練型) - Documents the process: Complex AI proposal → Detailed analysis → Human insight → Convergence - Field declaration design as a typical example ### Paper K (Explosive Incidents) - Added Incident #046: "init block vs fields-at-top incident" - Updated total count to 46 incidents - Shows how a single human comment redirected entire design approach ## Design Decision After analysis, decided that BoxIndex should remain a compiler-internal structure, not a core Box: - Core Boxes: User-instantiable runtime values (String, Integer, Array, Map) - Compiler internals: BoxIndex for name resolution (compile-time only) - Clear separation of concerns between language features and compiler tools ## Philosophy This discussion exemplifies key principles: - The best design needs no explanation - Constraints provide clarity, not limitation - "Everything is Box" doesn't mean "compiler internals are Boxes" - AI tends toward theoretical completeness; humans toward practical simplicity 🐱 Sometimes the simplest answer is right in front of us\!
2025-09-16 14:57:05 +09:00
};
if is_field && seen_method {
violations.push((lno, trimmed.to_string(), cur_box.clone()));
}
}
}
// Exit box when closing brace reduces depth below box_depth
let post_brace = pre_brace + opens - closes;
if post_brace < box_depth {
in_box = false;
cur_box.clear();
}
📚 docs: Record field declaration design discussion in papers ## Summary Documented the "init block vs fields-at-top" design discussion as a valuable example of AI-human collaboration in language design. ## Changes ### Paper G (AI Collaboration) - Added field-declaration-design.md documenting the entire discussion flow - Showcased how complex init block proposal evolved to simple "fields at top" rule - Demonstrates AI's tendency toward complexity vs human intuition for simplicity ### Paper H (AI Practical Patterns) - Added Pattern #17: "Gradual Refinement Pattern" (段階的洗練型) - Documents the process: Complex AI proposal → Detailed analysis → Human insight → Convergence - Field declaration design as a typical example ### Paper K (Explosive Incidents) - Added Incident #046: "init block vs fields-at-top incident" - Updated total count to 46 incidents - Shows how a single human comment redirected entire design approach ## Design Decision After analysis, decided that BoxIndex should remain a compiler-internal structure, not a core Box: - Core Boxes: User-instantiable runtime values (String, Integer, Array, Map) - Compiler internals: BoxIndex for name resolution (compile-time only) - Clear separation of concerns between language features and compiler tools ## Philosophy This discussion exemplifies key principles: - The best design needs no explanation - Constraints provide clarity, not limitation - "Everything is Box" doesn't mean "compiler internals are Boxes" - AI tends toward theoretical completeness; humans toward practical simplicity 🐱 Sometimes the simplest answer is right in front of us\!
2025-09-16 14:57:05 +09:00
}
// Update brace after processing
brace += opens - closes;
}
if violations.is_empty() {
return Ok(());
}
if strict {
// Compose error message
let mut msg =
String::from("Field declarations must appear at the top of box. Violations:\n");
📚 docs: Record field declaration design discussion in papers ## Summary Documented the "init block vs fields-at-top" design discussion as a valuable example of AI-human collaboration in language design. ## Changes ### Paper G (AI Collaboration) - Added field-declaration-design.md documenting the entire discussion flow - Showcased how complex init block proposal evolved to simple "fields at top" rule - Demonstrates AI's tendency toward complexity vs human intuition for simplicity ### Paper H (AI Practical Patterns) - Added Pattern #17: "Gradual Refinement Pattern" (段階的洗練型) - Documents the process: Complex AI proposal → Detailed analysis → Human insight → Convergence - Field declaration design as a typical example ### Paper K (Explosive Incidents) - Added Incident #046: "init block vs fields-at-top incident" - Updated total count to 46 incidents - Shows how a single human comment redirected entire design approach ## Design Decision After analysis, decided that BoxIndex should remain a compiler-internal structure, not a core Box: - Core Boxes: User-instantiable runtime values (String, Integer, Array, Map) - Compiler internals: BoxIndex for name resolution (compile-time only) - Clear separation of concerns between language features and compiler tools ## Philosophy This discussion exemplifies key principles: - The best design needs no explanation - Constraints provide clarity, not limitation - "Everything is Box" doesn't mean "compiler internals are Boxes" - AI tends toward theoretical completeness; humans toward practical simplicity 🐱 Sometimes the simplest answer is right in front of us\!
2025-09-16 14:57:05 +09:00
for (lno, fld, bx) in violations.iter().take(10) {
msg.push_str(&format!(
" line {} in box {}: '{}",
lno,
if bx.is_empty() { "<unknown>" } else { bx },
fld
));
📚 docs: Record field declaration design discussion in papers ## Summary Documented the "init block vs fields-at-top" design discussion as a valuable example of AI-human collaboration in language design. ## Changes ### Paper G (AI Collaboration) - Added field-declaration-design.md documenting the entire discussion flow - Showcased how complex init block proposal evolved to simple "fields at top" rule - Demonstrates AI's tendency toward complexity vs human intuition for simplicity ### Paper H (AI Practical Patterns) - Added Pattern #17: "Gradual Refinement Pattern" (段階的洗練型) - Documents the process: Complex AI proposal → Detailed analysis → Human insight → Convergence - Field declaration design as a typical example ### Paper K (Explosive Incidents) - Added Incident #046: "init block vs fields-at-top incident" - Updated total count to 46 incidents - Shows how a single human comment redirected entire design approach ## Design Decision After analysis, decided that BoxIndex should remain a compiler-internal structure, not a core Box: - Core Boxes: User-instantiable runtime values (String, Integer, Array, Map) - Compiler internals: BoxIndex for name resolution (compile-time only) - Clear separation of concerns between language features and compiler tools ## Philosophy This discussion exemplifies key principles: - The best design needs no explanation - Constraints provide clarity, not limitation - "Everything is Box" doesn't mean "compiler internals are Boxes" - AI tends toward theoretical completeness; humans toward practical simplicity 🐱 Sometimes the simplest answer is right in front of us\!
2025-09-16 14:57:05 +09:00
msg.push_str("'\n");
}
if violations.len() > 10 {
msg.push_str(&format!(" ... and {} more\n", violations.len() - 10));
}
📚 docs: Record field declaration design discussion in papers ## Summary Documented the "init block vs fields-at-top" design discussion as a valuable example of AI-human collaboration in language design. ## Changes ### Paper G (AI Collaboration) - Added field-declaration-design.md documenting the entire discussion flow - Showcased how complex init block proposal evolved to simple "fields at top" rule - Demonstrates AI's tendency toward complexity vs human intuition for simplicity ### Paper H (AI Practical Patterns) - Added Pattern #17: "Gradual Refinement Pattern" (段階的洗練型) - Documents the process: Complex AI proposal → Detailed analysis → Human insight → Convergence - Field declaration design as a typical example ### Paper K (Explosive Incidents) - Added Incident #046: "init block vs fields-at-top incident" - Updated total count to 46 incidents - Shows how a single human comment redirected entire design approach ## Design Decision After analysis, decided that BoxIndex should remain a compiler-internal structure, not a core Box: - Core Boxes: User-instantiable runtime values (String, Integer, Array, Map) - Compiler internals: BoxIndex for name resolution (compile-time only) - Clear separation of concerns between language features and compiler tools ## Philosophy This discussion exemplifies key principles: - The best design needs no explanation - Constraints provide clarity, not limitation - "Everything is Box" doesn't mean "compiler internals are Boxes" - AI tends toward theoretical completeness; humans toward practical simplicity 🐱 Sometimes the simplest answer is right in front of us\!
2025-09-16 14:57:05 +09:00
return Err(msg);
}
if verbose || crate::config::env::env_bool("NYASH_RESOLVE_TRACE") {
📚 docs: Record field declaration design discussion in papers ## Summary Documented the "init block vs fields-at-top" design discussion as a valuable example of AI-human collaboration in language design. ## Changes ### Paper G (AI Collaboration) - Added field-declaration-design.md documenting the entire discussion flow - Showcased how complex init block proposal evolved to simple "fields at top" rule - Demonstrates AI's tendency toward complexity vs human intuition for simplicity ### Paper H (AI Practical Patterns) - Added Pattern #17: "Gradual Refinement Pattern" (段階的洗練型) - Documents the process: Complex AI proposal → Detailed analysis → Human insight → Convergence - Field declaration design as a typical example ### Paper K (Explosive Incidents) - Added Incident #046: "init block vs fields-at-top incident" - Updated total count to 46 incidents - Shows how a single human comment redirected entire design approach ## Design Decision After analysis, decided that BoxIndex should remain a compiler-internal structure, not a core Box: - Core Boxes: User-instantiable runtime values (String, Integer, Array, Map) - Compiler internals: BoxIndex for name resolution (compile-time only) - Clear separation of concerns between language features and compiler tools ## Philosophy This discussion exemplifies key principles: - The best design needs no explanation - Constraints provide clarity, not limitation - "Everything is Box" doesn't mean "compiler internals are Boxes" - AI tends toward theoretical completeness; humans toward practical simplicity 🐱 Sometimes the simplest answer is right in front of us\!
2025-09-16 14:57:05 +09:00
for (lno, fld, bx) in violations {
eprintln!(
"[lint] fields-top: line {} in box {} -> {}",
lno,
if bx.is_empty() { "<unknown>" } else { &bx },
fld
);
📚 docs: Record field declaration design discussion in papers ## Summary Documented the "init block vs fields-at-top" design discussion as a valuable example of AI-human collaboration in language design. ## Changes ### Paper G (AI Collaboration) - Added field-declaration-design.md documenting the entire discussion flow - Showcased how complex init block proposal evolved to simple "fields at top" rule - Demonstrates AI's tendency toward complexity vs human intuition for simplicity ### Paper H (AI Practical Patterns) - Added Pattern #17: "Gradual Refinement Pattern" (段階的洗練型) - Documents the process: Complex AI proposal → Detailed analysis → Human insight → Convergence - Field declaration design as a typical example ### Paper K (Explosive Incidents) - Added Incident #046: "init block vs fields-at-top incident" - Updated total count to 46 incidents - Shows how a single human comment redirected entire design approach ## Design Decision After analysis, decided that BoxIndex should remain a compiler-internal structure, not a core Box: - Core Boxes: User-instantiable runtime values (String, Integer, Array, Map) - Compiler internals: BoxIndex for name resolution (compile-time only) - Clear separation of concerns between language features and compiler tools ## Philosophy This discussion exemplifies key principles: - The best design needs no explanation - Constraints provide clarity, not limitation - "Everything is Box" doesn't mean "compiler internals are Boxes" - AI tends toward theoretical completeness; humans toward practical simplicity 🐱 Sometimes the simplest answer is right in front of us\!
2025-09-16 14:57:05 +09:00
}
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use tempfile::tempdir;
#[test]
fn plugin_meta_requires_prefix_even_when_relaxed() {
let dir = tempdir().expect("tempdir");
let old = std::env::current_dir().expect("cwd");
std::env::set_current_dir(dir.path()).expect("chdir");
let toml = r#"
[plugins]
require_prefix = false
[plugins."test-plugin"]
prefix = "test"
require_prefix = true
expose_short_names = false
boxes = ["ArrayBox"]
"#;
std::fs::write("nyash.toml", toml).expect("write nyash.toml");
crate::runner::box_index::refresh_box_index();
crate::runner::box_index::cache_clear();
let res = resolve_using_target(
"ArrayBox",
false,
&[],
&[],
&HashMap::new(),
&std::collections::HashMap::<String, crate::using::spec::UsingPackage>::new(),
None,
false,
false,
);
assert!(res.is_err(), "expected prefix enforcement");
let err = res.err().unwrap();
assert!(err.contains("requires prefix"));
assert!(err.contains("test."));
std::env::set_current_dir(old).expect("restore cwd");
crate::runner::box_index::refresh_box_index();
crate::runner::box_index::cache_clear();
}
}