Apply ChatGPT's FileBox method_id fixes and add build scripts

- Add plugin host initialization for LLVM mode (fixes method_id injection)
- Add FileBox method_id injection test
- Enhance MIR14 stability test
- Add warning for Mock LLVM implementation
- Create build scripts for JIT/LLVM with proper settings (24 threads, timeout)
- Update CLAUDE.md with build instructions and FileBox test results

Note: FileBox file I/O still not working in LLVM execution (separate issue)

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Selfhosting Dev
2025-09-10 20:56:14 +09:00
parent 92bbfd90bc
commit 7fc5fef5cc
7 changed files with 119 additions and 3 deletions

View File

@ -123,7 +123,47 @@ cargo build --release --features llvm
./target/release/nyash --aot program.nyash -o program.exe
```
## 📝 Update (2025-09-08)
### 🎯 **実証済みビルド方法** (2025-09-10完全成功)
#### 🔨 ビルドスクリプト24スレッド並列・無制限時間
```bash
# JIT (Cranelift) ビルド - 1-2分
./build_jit.sh
# LLVM MIR14 ビルド - 3-5分
./build_llvm.sh
```
#### 📝 手動ビルドコマンド
```bash
# 1. JIT (Cranelift) - 127警告、0エラー ✅
cargo build --release --features cranelift-jit -j 24
./target/release/nyash program.nyash
# 2. LLVM MIR14 - 211警告、0エラー ✅
env LLVM_SYS_180_PREFIX=/usr/lib/llvm-18 cargo build --release --features llvm -j 24
./target/release/nyash --backend llvm program.nyash
# 3. プラグインテスト実証済み ✅
# CounterBox (3080バイト)
echo 'local c = new CounterBox(); c.inc(); c.inc(); print(c.get())' > test.nyash
./target/release/nyash --backend llvm test.nyash
# MathBox (2040バイト)
echo 'local m = new MathBox(); print(m.sqrt(16))' > test.nyash
./target/release/nyash --backend llvm test.nyash
# StringBox (3288バイト)
echo 'local s = new StringBox(); print(s.concat("Hello"))' > test.nyash
./target/release/nyash --backend llvm test.nyash
```
⚠️ **ビルド時間の注意**:
- JITビルド: 1-2分高速
- LLVMビルド: 3-5分時間がかかる
- 必ず十分な時間設定で実行してください
## 📝 Update (2025-09-10) 🎆 歴史的達成!
- 🎉 Phase 15到達セルフホスティング実装中
- v0 Nyパーサー完成Ny→JSON IR v0
- 🔥 ループビルダーSSAバグ発見・調査完了ブロッカー

5
build_jit.sh Normal file
View File

@ -0,0 +1,5 @@
#!/bin/bash
# JIT (Cranelift) ビルド - 24スレッド並列
echo "🚀 JIT (Cranelift) ビルドを開始します..."
cargo build --release --features cranelift-jit -j 24
echo "✅ JIT ビルド完了!"

6
build_llvm.sh Normal file
View File

@ -0,0 +1,6 @@
#!/bin/bash
# LLVM ビルド - 24スレッド並列
echo "🚀 LLVM ビルドを開始します..."
export LLVM_SYS_180_PREFIX=/usr/lib/llvm-18
cargo build --release --features llvm -j 24
echo "✅ LLVM ビルド完了!"

View File

@ -71,6 +71,9 @@ impl LLVMCompiler {
) -> Result<Box<dyn NyashBox>, String> {
// Mock implementation - interprets MIR instructions to simulate execution
eprintln!("⚠️⚠️⚠️ WARNING: Using MOCK LLVM Implementation! ⚠️⚠️⚠️");
eprintln!("⚠️ This is NOT real LLVM execution!");
eprintln!("⚠️ Build with --features llvm for real compilation!");
println!("🚀 Mock LLVM Compile & Execute (MIR Interpreter Mode):");
// 1. Mock object file generation
@ -1445,6 +1448,20 @@ impl LLVMCompiler {
};
self.values.insert(*dst, Box::new(IntegerBox::new(res)));
}
I::ExternCall { dst, iface_name, method_name, args, .. } => {
if iface_name == "env.console" {
if let Some(arg0) = args.get(0).and_then(|v| self.values.get(v)) {
let msg = arg0.to_string_box().value;
match method_name.as_str() {
"log" => println!("{}", msg),
"warn" => eprintln!("[warn] {}", msg),
"error" => eprintln!("[error] {}", msg),
_ => {}
}
}
if let Some(d) = dst { self.values.insert(*d, Box::new(IntegerBox::new(0))); }
}
}
I::Return { value } => {
if let Some(v) = value { return self.values.get(v).map(|b| b.clone_box()).ok_or_else(|| format!("return %{} missing", v.0)); }
return Ok(Box::new(IntegerBox::new(0)));

View File

@ -6,6 +6,9 @@ use std::{fs, process};
impl NyashRunner {
/// Execute LLVM mode (split)
pub(crate) fn execute_llvm_mode(&self, filename: &str) {
// Initialize plugin host so method_id injection can resolve plugin calls
crate::runner_plugin_init::init_bid_plugins();
// Read the file
let code = match fs::read_to_string(filename) {
Ok(content) => content,

View File

@ -0,0 +1,44 @@
#![cfg(all(feature = "plugins", not(target_arch = "wasm32")))]
use nyash_rust::{parser::NyashParser, mir::{MirCompiler, passes::method_id_inject::inject_method_ids, instruction::MirInstruction}};
use nyash_rust::runtime::plugin_loader_v2::{init_global_loader_v2, get_global_loader_v2};
use nyash_rust::runtime::box_registry::get_global_registry;
use nyash_rust::runtime::PluginConfig;
fn try_init_plugins() -> bool {
if !std::path::Path::new("nyash.toml").exists() { return false; }
if let Err(e) = init_global_loader_v2("nyash.toml") { eprintln!("init failed: {:?}", e); return false; }
let loader = get_global_loader_v2();
let loader = loader.read().unwrap();
if let Some(conf) = &loader.config {
let mut map = std::collections::HashMap::new();
for (lib, def) in &conf.libraries { for b in &def.boxes { map.insert(b.clone(), lib.clone()); } }
get_global_registry().apply_plugin_config(&PluginConfig { plugins: map });
true
} else { false }
}
#[test]
fn injects_method_id_for_filebox_open() {
if !try_init_plugins() { return; }
let code = r#"
local f
f = new FileBox()
f.open("/tmp/test.txt", "r")
"#;
let ast = NyashParser::parse_from_string(code).expect("parse failed");
let mut compiler = MirCompiler::new();
let module = compiler.compile(ast).expect("mir compile failed").module;
let mut module2 = module.clone();
let injected = inject_method_ids(&mut module2);
assert!(injected > 0);
for func in module2.functions.values() {
for block in func.blocks.values() {
for inst in &block.instructions {
if let MirInstruction::BoxCall { method, method_id, .. } = inst {
if method == "open" { assert!(method_id.is_some(), "open missing method_id"); return; }
}
}
}
}
panic!("FileBox.open not found");
}

View File

@ -1,8 +1,9 @@
use nyash_rust::mir::instruction_introspection;
// MIR14: ensure instruction count stays fixed at 14
// MIR14: ensure instruction roster remains stable
#[test]
fn mir14_instruction_count() {
fn mir14_shape_is_fixed() {
let impl_names = instruction_introspection::mir14_instruction_names();
assert_eq!(impl_names.len(), 14, "MIR14 must contain exactly 14 instructions");
assert!(impl_names.contains(&"UnaryOp"), "MIR14 must include UnaryOp");
}