feat: Prepare for code modularization and cleanup
- Archive old documentation and test files to `docs/archive/` and `local_tests/`. - Remove various temporary and old files from the project root. - Add `nekocode-rust` analysis tool and its output files (`nekocode/`, `.nekocode_sessions/`, `analysis.json`). - Minor updates to `apps/chip8_nyash/chip8_emulator.nyash` and `local_tests` files. This commit cleans up the repository and sets the stage for further code modularization efforts, particularly in the `src/interpreter` and `src/parser` modules, based on recent analysis.
This commit is contained in:
File diff suppressed because it is too large
Load Diff
163983
analysis.json
Normal file
163983
analysis.json
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,11 +1,11 @@
|
||||
// 🎮 Chip-8 Emulator in Nyash - Phase 10.2
|
||||
// Testing fini propagation and weak reference lifecycle
|
||||
// Testing fini propagation and reference lifecycle
|
||||
|
||||
// Chip8CPU - Central processing unit with fini propagation
|
||||
static box Chip8CPU {
|
||||
init { memory, graphics, sound, program_counter, registers }
|
||||
|
||||
pack() {
|
||||
constructor() {
|
||||
me.program_counter = 512 // 0x200 = 512 decimal - Standard Chip-8 start address
|
||||
me.registers = new ArrayBox() // 16 general registers V0-VF
|
||||
|
||||
@ -94,11 +94,11 @@ static box Chip8CPU {
|
||||
}
|
||||
}
|
||||
|
||||
// Chip8Memory - Memory system with weak CPU reference
|
||||
// Chip8Memory - Memory system with CPU reference
|
||||
static box Chip8Memory {
|
||||
init { ram, weak cpu_ref } // CPU reference is weak to prevent cycles
|
||||
init { ram, cpu_ref } // CPU reference is to prevent cycles
|
||||
|
||||
pack(cpu_instance) {
|
||||
constructor(cpu_instance) {
|
||||
me.ram = new ArrayBox()
|
||||
|
||||
// Initialize 4KB of RAM (4096 bytes)
|
||||
@ -108,14 +108,14 @@ static box Chip8Memory {
|
||||
i = i + 1
|
||||
}
|
||||
|
||||
// Create weak reference to CPU
|
||||
me.cpu_ref = weak cpu_instance
|
||||
// Create reference to CPU
|
||||
me.cpu_ref = cpu_instance
|
||||
|
||||
print("💾 Memory initialized: 4KB RAM + weak CPU reference")
|
||||
print("💾 Memory initialized: 4KB RAM + CPU reference")
|
||||
me.load_test_program()
|
||||
}
|
||||
|
||||
// ⭐ Phase 10: weak reference life cycle test
|
||||
// ⭐ Phase 10: reference life cycle test
|
||||
read_byte(address) {
|
||||
// Check if CPU is still alive before accessing memory
|
||||
if (me.cpu_ref != null) {
|
||||
@ -169,9 +169,9 @@ static box Chip8Memory {
|
||||
|
||||
// Chip8Graphics - Display system
|
||||
static box Chip8Graphics {
|
||||
init { screen, weak cpu_ref }
|
||||
init { screen, cpu_ref }
|
||||
|
||||
pack(cpu_instance) {
|
||||
constructor(cpu_instance) {
|
||||
me.screen = new ArrayBox()
|
||||
|
||||
// Initialize 64x32 pixel display (2048 pixels)
|
||||
@ -181,8 +181,8 @@ static box Chip8Graphics {
|
||||
i = i + 1
|
||||
}
|
||||
|
||||
me.cpu_ref = weak cpu_instance
|
||||
print("🖼️ Graphics initialized: 64x32 display + weak CPU reference")
|
||||
me.cpu_ref = cpu_instance
|
||||
print("🖼️ Graphics initialized: 64x32 display + CPU reference")
|
||||
}
|
||||
|
||||
draw_sprite(x, y, sprite_data) {
|
||||
@ -219,12 +219,12 @@ static box Chip8Graphics {
|
||||
|
||||
// Chip8Sound - Audio system
|
||||
static box Chip8Sound {
|
||||
init { beep_timer, weak cpu_ref }
|
||||
init { beep_timer, cpu_ref }
|
||||
|
||||
pack(cpu_instance) {
|
||||
constructor(cpu_instance) {
|
||||
me.beep_timer = 0
|
||||
me.cpu_ref = weak cpu_instance
|
||||
print("🔊 Sound initialized with weak CPU reference")
|
||||
me.cpu_ref = cpu_instance
|
||||
print("🔊 Sound initialized with CPU reference")
|
||||
}
|
||||
|
||||
play_beep() {
|
||||
@ -261,28 +261,28 @@ static box Chip8System {
|
||||
|
||||
main() {
|
||||
print("🎮 Starting Chip-8 Emulator - Phase 10.2")
|
||||
print("Testing fini propagation and weak reference lifecycle")
|
||||
print("Testing fini propagation and reference lifecycle")
|
||||
|
||||
// Create CPU first
|
||||
me.cpu = new Chip8CPU()
|
||||
me.cpu.pack()
|
||||
me.cpu.constructor()
|
||||
|
||||
// Create subsystems with weak references to CPU
|
||||
// Create subsystems with references to CPU
|
||||
me.memory = new Chip8Memory()
|
||||
me.memory.pack(me.cpu)
|
||||
me.memory.constructor(me.cpu)
|
||||
|
||||
me.graphics = new Chip8Graphics()
|
||||
me.graphics.pack(me.cpu)
|
||||
me.graphics.constructor(me.cpu)
|
||||
|
||||
me.sound = new Chip8Sound()
|
||||
me.sound.pack(me.cpu)
|
||||
me.sound.constructor(me.cpu)
|
||||
|
||||
// Link components to CPU for fini propagation
|
||||
me.cpu.memory = me.memory
|
||||
me.cpu.graphics = me.graphics
|
||||
me.cpu.sound = me.sound
|
||||
|
||||
print("🔗 All components linked with weak references")
|
||||
print("🔗 All components linked with references")
|
||||
|
||||
// Run a few emulation cycles
|
||||
me.run_emulation()
|
||||
@ -292,8 +292,8 @@ static box Chip8System {
|
||||
me.cpu.fini()
|
||||
me.cpu = null
|
||||
|
||||
// Test weak reference after CPU destruction
|
||||
print("🧪 Testing weak references after CPU destruction...")
|
||||
// Test reference after CPU destruction
|
||||
print("🧪 Testing references after CPU destruction...")
|
||||
me.test_weak_references()
|
||||
|
||||
return "Chip-8 emulation and memory management test complete"
|
||||
|
||||
@ -1,21 +0,0 @@
|
||||
(module
|
||||
(func $main (result i32)
|
||||
(local $x i32)
|
||||
(local $y i32)
|
||||
(local $result i32)
|
||||
|
||||
i32.const 10
|
||||
local.set $x
|
||||
|
||||
i32.const 20
|
||||
local.set $y
|
||||
|
||||
local.get $x
|
||||
local.get $y
|
||||
i32.add
|
||||
local.set $result
|
||||
|
||||
local.get $result
|
||||
)
|
||||
(export "main" (func $main))
|
||||
)
|
||||
@ -1,66 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "🚀 真のWASM実行性能ベンチマーク"
|
||||
echo "================================="
|
||||
|
||||
# 実行回数
|
||||
ITERATIONS=100
|
||||
|
||||
echo "📊 測定回数: $ITERATIONS"
|
||||
echo
|
||||
|
||||
# 1. インタープリター測定
|
||||
echo "1️⃣ インタープリター実行測定"
|
||||
interpreter_total=0
|
||||
for i in $(seq 1 $ITERATIONS); do
|
||||
start_time=$(date +%s%N)
|
||||
./target/release/nyash test_local_vars.nyash >/dev/null 2>&1
|
||||
end_time=$(date +%s%N)
|
||||
duration=$((($end_time - $start_time) / 1000000)) # ms
|
||||
interpreter_total=$(($interpreter_total + $duration))
|
||||
done
|
||||
interpreter_avg=$(echo "scale=2; $interpreter_total / $ITERATIONS" | bc)
|
||||
echo " 平均実行時間: ${interpreter_avg} ms"
|
||||
|
||||
# 2. VM測定
|
||||
echo "2️⃣ VM実行測定"
|
||||
vm_total=0
|
||||
for i in $(seq 1 $ITERATIONS); do
|
||||
start_time=$(date +%s%N)
|
||||
./target/release/nyash --backend vm test_local_vars.nyash >/dev/null 2>&1
|
||||
end_time=$(date +%s%N)
|
||||
duration=$((($end_time - $start_time) / 1000000)) # ms
|
||||
vm_total=$(($vm_total + $duration))
|
||||
done
|
||||
vm_avg=$(echo "scale=2; $vm_total / $ITERATIONS" | bc)
|
||||
echo " 平均実行時間: ${vm_avg} ms"
|
||||
|
||||
# 3. WASM実行測定(wasmtime)
|
||||
echo "3️⃣ WASM実行測定(wasmtime)"
|
||||
wasm_total=0
|
||||
for i in $(seq 1 $ITERATIONS); do
|
||||
start_time=$(date +%s%N)
|
||||
$HOME/.wasmtime/bin/wasmtime run bench_simple.wat --invoke main >/dev/null 2>&1
|
||||
end_time=$(date +%s%N)
|
||||
duration=$((($end_time - $start_time) / 1000000)) # ms
|
||||
wasm_total=$(($wasm_total + $duration))
|
||||
done
|
||||
wasm_avg=$(echo "scale=2; $wasm_total / $ITERATIONS" | bc)
|
||||
echo " 平均実行時間: ${wasm_avg} ms"
|
||||
|
||||
# 4. 結果比較
|
||||
echo
|
||||
echo "📈 性能比較結果"
|
||||
echo "==============="
|
||||
echo "インタープリター: ${interpreter_avg} ms (1x baseline)"
|
||||
echo "VM: ${vm_avg} ms"
|
||||
echo "WASM (wasmtime): ${wasm_avg} ms"
|
||||
|
||||
# 速度比計算
|
||||
vm_speedup=$(echo "scale=1; $interpreter_avg / $vm_avg" | bc)
|
||||
wasm_speedup=$(echo "scale=1; $interpreter_avg / $wasm_avg" | bc)
|
||||
|
||||
echo
|
||||
echo "🏆 速度向上比較"
|
||||
echo "VM: ${vm_speedup}x faster"
|
||||
echo "WASM: ${wasm_speedup}x faster"
|
||||
@ -1,2 +0,0 @@
|
||||
#!/bin/bash
|
||||
cargo check 2>&1 | grep -B2 -A2 "unresolved import"
|
||||
204
clean_test.wat
204
clean_test.wat
@ -1,204 +0,0 @@
|
||||
(module
|
||||
(import "env" "print" (func $print (param i32) ))
|
||||
(memory (export "memory") 1)
|
||||
(global $heap_ptr (mut i32) (i32.const 2048))
|
||||
(func $malloc (param $size i32) (result i32)
|
||||
(local $ptr i32)
|
||||
(local $aligned_size i32)
|
||||
|
||||
;; Align size to 4-byte boundary
|
||||
local.get $size
|
||||
i32.const 3
|
||||
i32.add
|
||||
i32.const -4
|
||||
i32.and
|
||||
local.set $aligned_size
|
||||
|
||||
;; Get current heap pointer
|
||||
global.get $heap_ptr
|
||||
local.set $ptr
|
||||
|
||||
;; Advance heap pointer by aligned size
|
||||
global.get $heap_ptr
|
||||
local.get $aligned_size
|
||||
i32.add
|
||||
global.set $heap_ptr
|
||||
|
||||
;; Return allocated pointer
|
||||
local.get $ptr
|
||||
)
|
||||
(func $box_alloc (param $type_id i32) (param $field_count i32) (result i32)
|
||||
(local $ptr i32)
|
||||
(local $total_size i32)
|
||||
|
||||
;; Calculate total size: header (12) + fields (field_count * 4)
|
||||
local.get $field_count
|
||||
i32.const 4
|
||||
i32.mul
|
||||
i32.const 12
|
||||
i32.add
|
||||
local.set $total_size
|
||||
|
||||
;; Allocate memory
|
||||
local.get $total_size
|
||||
call $malloc
|
||||
local.set $ptr
|
||||
|
||||
;; Initialize type_id
|
||||
local.get $ptr
|
||||
local.get $type_id
|
||||
i32.store
|
||||
|
||||
;; Initialize ref_count to 1
|
||||
local.get $ptr
|
||||
i32.const 4
|
||||
i32.add
|
||||
i32.const 1
|
||||
i32.store
|
||||
|
||||
;; Initialize field_count
|
||||
local.get $ptr
|
||||
i32.const 8
|
||||
i32.add
|
||||
local.get $field_count
|
||||
i32.store
|
||||
|
||||
;; Return box pointer
|
||||
local.get $ptr
|
||||
)
|
||||
(func $alloc_stringbox (result i32)
|
||||
(local $ptr i32)
|
||||
|
||||
;; Allocate memory for box
|
||||
i32.const 20
|
||||
call $malloc
|
||||
local.set $ptr
|
||||
|
||||
;; Initialize type_id
|
||||
local.get $ptr
|
||||
i32.const 4097
|
||||
i32.store
|
||||
|
||||
;; Initialize ref_count to 1
|
||||
local.get $ptr
|
||||
i32.const 4
|
||||
i32.add
|
||||
i32.const 1
|
||||
i32.store
|
||||
|
||||
;; Initialize field_count
|
||||
local.get $ptr
|
||||
i32.const 8
|
||||
i32.add
|
||||
i32.const 2
|
||||
i32.store
|
||||
|
||||
;; Return box pointer
|
||||
local.get $ptr
|
||||
)
|
||||
(func $alloc_integerbox (result i32)
|
||||
(local $ptr i32)
|
||||
|
||||
;; Allocate memory for box
|
||||
i32.const 16
|
||||
call $malloc
|
||||
local.set $ptr
|
||||
|
||||
;; Initialize type_id
|
||||
local.get $ptr
|
||||
i32.const 4098
|
||||
i32.store
|
||||
|
||||
;; Initialize ref_count to 1
|
||||
local.get $ptr
|
||||
i32.const 4
|
||||
i32.add
|
||||
i32.const 1
|
||||
i32.store
|
||||
|
||||
;; Initialize field_count
|
||||
local.get $ptr
|
||||
i32.const 8
|
||||
i32.add
|
||||
i32.const 1
|
||||
i32.store
|
||||
|
||||
;; Return box pointer
|
||||
local.get $ptr
|
||||
)
|
||||
(func $alloc_boolbox (result i32)
|
||||
(local $ptr i32)
|
||||
|
||||
;; Allocate memory for box
|
||||
i32.const 16
|
||||
call $malloc
|
||||
local.set $ptr
|
||||
|
||||
;; Initialize type_id
|
||||
local.get $ptr
|
||||
i32.const 4099
|
||||
i32.store
|
||||
|
||||
;; Initialize ref_count to 1
|
||||
local.get $ptr
|
||||
i32.const 4
|
||||
i32.add
|
||||
i32.const 1
|
||||
i32.store
|
||||
|
||||
;; Initialize field_count
|
||||
local.get $ptr
|
||||
i32.const 8
|
||||
i32.add
|
||||
i32.const 1
|
||||
i32.store
|
||||
|
||||
;; Return box pointer
|
||||
local.get $ptr
|
||||
)
|
||||
(func $alloc_databox (result i32)
|
||||
(local $ptr i32)
|
||||
|
||||
;; Allocate memory for box
|
||||
i32.const 16
|
||||
call $malloc
|
||||
local.set $ptr
|
||||
|
||||
;; Initialize type_id
|
||||
local.get $ptr
|
||||
i32.const 4101
|
||||
i32.store
|
||||
|
||||
;; Initialize ref_count to 1
|
||||
local.get $ptr
|
||||
i32.const 4
|
||||
i32.add
|
||||
i32.const 1
|
||||
i32.store
|
||||
|
||||
;; Initialize field_count
|
||||
local.get $ptr
|
||||
i32.const 8
|
||||
i32.add
|
||||
i32.const 1
|
||||
i32.store
|
||||
|
||||
;; Return box pointer
|
||||
local.get $ptr
|
||||
)
|
||||
(func $main (local $0 i32) (local $1 i32) (local $2 i32)
|
||||
nop
|
||||
i32.const 10
|
||||
local.set $0
|
||||
i32.const 20
|
||||
local.set $1
|
||||
local.get $0
|
||||
local.get $1
|
||||
i32.add
|
||||
local.set $2
|
||||
local.get $2
|
||||
return
|
||||
)
|
||||
(export "main" (func $main))
|
||||
)
|
||||
|
||||
@ -1,192 +0,0 @@
|
||||
// 🔍 デバッグ版SocketBox - 全操作を詳細ログ出力
|
||||
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::fs::OpenOptions;
|
||||
use std::io::Write;
|
||||
|
||||
// デバッグログをファイルに出力
|
||||
fn debug_log(message: &str) {
|
||||
let timestamp = std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_millis();
|
||||
|
||||
let log_message = format!("[{}] {}\n", timestamp, message);
|
||||
|
||||
if let Ok(mut file) = OpenOptions::new()
|
||||
.create(true)
|
||||
.append(true)
|
||||
.open("debug_socketbox.log")
|
||||
{
|
||||
let _ = file.write_all(log_message.as_bytes());
|
||||
let _ = file.flush();
|
||||
}
|
||||
|
||||
// コンソールにも出力
|
||||
print!("{}", log_message);
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DebugSocketBox {
|
||||
id: u64,
|
||||
listener: Arc<Mutex<Option<std::net::TcpListener>>>,
|
||||
is_server: Arc<Mutex<bool>>,
|
||||
}
|
||||
|
||||
impl DebugSocketBox {
|
||||
pub fn new() -> Self {
|
||||
let id = std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_nanos() as u64;
|
||||
|
||||
let instance = Self {
|
||||
id,
|
||||
listener: Arc::new(Mutex::new(None)),
|
||||
is_server: Arc::new(Mutex::new(false)),
|
||||
};
|
||||
|
||||
debug_log(&format!("🆕 NEW SocketBox created: id={}, is_server_ptr={:p}",
|
||||
instance.id, &*instance.is_server));
|
||||
|
||||
instance
|
||||
}
|
||||
|
||||
pub fn bind(&self, addr: &str, port: &str) -> bool {
|
||||
debug_log(&format!("🔗 BIND called on id={}, is_server_ptr={:p}",
|
||||
self.id, &*self.is_server));
|
||||
|
||||
let socket_addr = format!("{}:{}", addr, port);
|
||||
debug_log(&format!("🔗 BIND address: {}", socket_addr));
|
||||
|
||||
match std::net::TcpListener::bind(&socket_addr) {
|
||||
Ok(listener) => {
|
||||
// listener設定
|
||||
match self.listener.lock() {
|
||||
Ok(mut listener_guard) => {
|
||||
*listener_guard = Some(listener);
|
||||
debug_log(&format!("✅ BIND listener set successfully on id={}", self.id));
|
||||
},
|
||||
Err(e) => {
|
||||
debug_log(&format!("❌ BIND listener lock failed: {:?}", e));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// is_server=true設定
|
||||
debug_log(&format!("🔧 BIND setting is_server=true on id={}, ptr={:p}",
|
||||
self.id, &*self.is_server));
|
||||
|
||||
match self.is_server.lock() {
|
||||
Ok(mut is_server_guard) => {
|
||||
let old_value = *is_server_guard;
|
||||
*is_server_guard = true;
|
||||
debug_log(&format!("✅ BIND is_server changed: {} -> true on id={}",
|
||||
old_value, self.id));
|
||||
},
|
||||
Err(e) => {
|
||||
debug_log(&format!("❌ BIND is_server lock failed: {:?}", e));
|
||||
}
|
||||
}
|
||||
|
||||
debug_log(&format!("🎉 BIND completed successfully on id={}", self.id));
|
||||
true
|
||||
},
|
||||
Err(e) => {
|
||||
debug_log(&format!("❌ BIND failed: {:?}", e));
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_server(&self) -> bool {
|
||||
debug_log(&format!("❓ IS_SERVER called on id={}, ptr={:p}",
|
||||
self.id, &*self.is_server));
|
||||
|
||||
match self.is_server.lock() {
|
||||
Ok(is_server_guard) => {
|
||||
let value = *is_server_guard;
|
||||
debug_log(&format!("📖 IS_SERVER result: {} on id={}", value, self.id));
|
||||
value
|
||||
},
|
||||
Err(e) => {
|
||||
debug_log(&format!("❌ IS_SERVER lock failed: {:?}", e));
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for DebugSocketBox {
|
||||
fn clone(&self) -> Self {
|
||||
debug_log(&format!("🔄 CLONE called on id={}", self.id));
|
||||
debug_log(&format!("🔄 CLONE original is_server_ptr={:p}", &*self.is_server));
|
||||
|
||||
let new_id = std::time::SystemTime::now()
|
||||
.duration_since(std::time::UNIX_EPOCH)
|
||||
.unwrap()
|
||||
.as_nanos() as u64;
|
||||
|
||||
let cloned = Self {
|
||||
id: new_id, // 新しいID
|
||||
listener: Arc::clone(&self.listener),
|
||||
is_server: Arc::clone(&self.is_server), // ✅ Arc共有
|
||||
};
|
||||
|
||||
debug_log(&format!("🔄 CLONE created: old_id={} -> new_id={}", self.id, cloned.id));
|
||||
debug_log(&format!("🔄 CLONE new is_server_ptr={:p}", &*cloned.is_server));
|
||||
debug_log(&format!("🔄 CLONE Arc共有確認: {} == {}",
|
||||
Arc::as_ptr(&self.is_server) as *const _ as usize,
|
||||
Arc::as_ptr(&cloned.is_server) as *const _ as usize));
|
||||
|
||||
cloned
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_debug_socketbox() {
|
||||
// ログファイルをクリア
|
||||
std::fs::write("debug_socketbox.log", "").unwrap();
|
||||
|
||||
debug_log("🚀 === DEBUG TEST START ===");
|
||||
|
||||
// Step 1: 作成
|
||||
let socket = DebugSocketBox::new();
|
||||
debug_log(&format!("Step 1 completed: id={}", socket.id));
|
||||
|
||||
// Step 2: bind実行
|
||||
debug_log("🔥 Step 2: BIND execution");
|
||||
let bind_result = socket.bind("127.0.0.1", "18080");
|
||||
debug_log(&format!("Step 2 completed: bind_result={}", bind_result));
|
||||
|
||||
// Step 3: 状態確認
|
||||
debug_log("🔥 Step 3: Check state after bind");
|
||||
let is_server1 = socket.is_server();
|
||||
debug_log(&format!("Step 3 completed: is_server={}", is_server1));
|
||||
|
||||
// Step 4: clone実行
|
||||
debug_log("🔥 Step 4: CLONE execution");
|
||||
let socket_cloned = socket.clone();
|
||||
|
||||
// Step 5: clone後の状態確認
|
||||
debug_log("🔥 Step 5: Check state after clone");
|
||||
let is_server2 = socket_cloned.is_server();
|
||||
debug_log(&format!("Step 5 completed: cloned is_server={}", is_server2));
|
||||
|
||||
// Step 6: 元の状態確認
|
||||
debug_log("🔥 Step 6: Check original after clone");
|
||||
let is_server3 = socket.is_server();
|
||||
debug_log(&format!("Step 6 completed: original is_server={}", is_server3));
|
||||
|
||||
debug_log("🎉 === DEBUG TEST COMPLETED ===");
|
||||
|
||||
assert!(bind_result, "bind should succeed");
|
||||
assert!(is_server1, "is_server should be true after bind");
|
||||
assert!(is_server2, "cloned is_server should be true (shared Arc)");
|
||||
assert!(is_server3, "original is_server should still be true");
|
||||
}
|
||||
}
|
||||
BIN
debug_test
BIN
debug_test
Binary file not shown.
@ -1,47 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "🚀 Nyash Phase 8.4 AST→MIR Lowering Demonstration"
|
||||
echo "=================================================="
|
||||
|
||||
echo ""
|
||||
echo "✅ Test 1: Basic User-Defined Box (Previously Failed)"
|
||||
echo "------------------------------------------------------"
|
||||
echo "Code: box DataBox { init { value } }"
|
||||
echo " local obj = new DataBox(42)"
|
||||
echo " return obj.value"
|
||||
echo ""
|
||||
./target/debug/nyash --dump-mir test_user_defined_box.nyash 2>/dev/null | tail -8
|
||||
|
||||
echo ""
|
||||
echo "✅ Test 2: Method Calls (Previously Failed)"
|
||||
echo "--------------------------------------------"
|
||||
echo "Code: c.increment() // Method call on user-defined box"
|
||||
echo ""
|
||||
./target/debug/nyash --dump-mir test_field_operations.nyash 2>/dev/null | tail -8
|
||||
|
||||
echo ""
|
||||
echo "✅ Test 3: Delegation Syntax (Previously Failed)"
|
||||
echo "-------------------------------------------------"
|
||||
echo "Code: from Parent.greet() // Delegation call"
|
||||
echo ""
|
||||
./target/debug/nyash --dump-mir test_delegation_basic.nyash 2>/dev/null | tail -8
|
||||
|
||||
echo ""
|
||||
echo "✅ Test 4: Static Main Compatibility (Preserved)"
|
||||
echo "------------------------------------------------"
|
||||
echo "Code: static box Main { main() { return 42 } }"
|
||||
echo ""
|
||||
./target/debug/nyash --dump-mir test_static_main_compatibility.nyash 2>/dev/null | tail -6
|
||||
|
||||
echo ""
|
||||
echo "🎯 Summary: AST→MIR Lowering for Everything is Box"
|
||||
echo "=================================================="
|
||||
echo "• User-defined boxes: ✅ Working"
|
||||
echo "• Object creation: ✅ Working (RefNew)"
|
||||
echo "• Field access: ✅ Working (RefGet)"
|
||||
echo "• Method calls: ✅ Working (BoxCall)"
|
||||
echo "• Delegation: ✅ Working (from calls)"
|
||||
echo "• me references: ✅ Working"
|
||||
echo "• Static Main: ✅ Preserved"
|
||||
echo ""
|
||||
echo "🚀 Phase 8.3 WASM Box operations can now be tested!"
|
||||
@ -1,64 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Phase 8.5 MIR 25-Instruction Demo Script
|
||||
|
||||
echo "🚀 Phase 8.5: MIR 25-Instruction Hierarchical Implementation Demo"
|
||||
echo "================================================================="
|
||||
echo ""
|
||||
|
||||
echo "🔧 Building Nyash with Phase 8.5 improvements..."
|
||||
cd /home/runner/work/nyash/nyash
|
||||
cargo build --release
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "✅ Build successful!"
|
||||
else
|
||||
echo "❌ Build failed!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "🧪 Running Phase 8.5 MIR Tests..."
|
||||
echo "- Testing 25-instruction specification"
|
||||
echo "- Testing 4-category effect system"
|
||||
echo "- Testing ownership forest verification"
|
||||
|
||||
# Run our specific tests
|
||||
cargo test instruction_v2 --lib
|
||||
cargo test ownership_verifier_simple --lib
|
||||
|
||||
echo ""
|
||||
echo "📊 Phase 8.5 Implementation Summary:"
|
||||
echo "====================================="
|
||||
echo ""
|
||||
echo "✅ Tier-0 Universal Core: 8 instructions implemented"
|
||||
echo " • Const, BinOp, Compare, Branch, Jump, Phi, Call, Return"
|
||||
echo ""
|
||||
echo "✅ Tier-1 Nyash Semantics: 12 instructions implemented"
|
||||
echo " • NewBox, BoxFieldLoad/Store, BoxCall, Safepoint"
|
||||
echo " • RefGet/Set, WeakNew/Load/Check, Send, Recv"
|
||||
echo ""
|
||||
echo "✅ Tier-2 Implementation Assistance: 5 instructions implemented"
|
||||
echo " • TailCall, Adopt, Release, MemCopy, AtomicFence"
|
||||
echo ""
|
||||
echo "✅ 4-Category Effect System: Pure/Mut/Io/Control"
|
||||
echo "✅ Ownership Forest Verification: Strong cycle detection + Weak safety"
|
||||
echo "✅ Total: Exactly 25 MIR instructions as specified"
|
||||
echo ""
|
||||
echo "🎯 Revolutionary Achievement: Complete ChatGPT5 + AI Council MIR specification!"
|
||||
echo " - Mathematically sound ownership forest constraints"
|
||||
echo " - Effect-driven optimization framework"
|
||||
echo " - Hierarchical 3-tier instruction architecture"
|
||||
echo " - Production-ready for JIT/AOT compilation"
|
||||
echo ""
|
||||
echo "🚀 Ready for Phase 8.5B: Backend Integration!"
|
||||
|
||||
# Show instruction count verification
|
||||
echo ""
|
||||
echo "🔍 Instruction Count Verification:"
|
||||
echo "================================="
|
||||
# This will be shown in the test output above
|
||||
grep -A 5 -B 5 "Total instruction count must be exactly 25" tests/mir_phase8_5_hierarchical_25_instructions.rs
|
||||
|
||||
echo ""
|
||||
echo "Demo completed successfully! 🎉"
|
||||
55
docs/archive/basic_box_static_consultation.txt
Normal file
55
docs/archive/basic_box_static_consultation.txt
Normal file
@ -0,0 +1,55 @@
|
||||
Nyashプログラミング言語の根本的設計哲学について深い相談です。
|
||||
|
||||
【Everything is Box哲学と実用性の矛盾】
|
||||
- Nyashは「Everything is Box」を掲げ、全ての値がBoxオブジェクト
|
||||
- しかしStringBox等の基本Box型で継承チェーン問題が発生
|
||||
- 基本的な機能を使うのに過度な複雑性が要求される
|
||||
|
||||
【現在の問題例】
|
||||
box Simple from StringBox {
|
||||
toString() {
|
||||
return "Prefix: " + from StringBox.toString()
|
||||
}
|
||||
}
|
||||
|
||||
box Complex from Simple {
|
||||
toString() {
|
||||
# ❌ エラー: ComplexはStringBoxに直接fromしていない
|
||||
return "Complex: " + from Simple.toString() # Simple内でStringBoxが呼ばれる
|
||||
}
|
||||
}
|
||||
|
||||
【static提供案】
|
||||
StringBoxのような基本Box型をstatic methodsとして提供:
|
||||
|
||||
box Simple {
|
||||
init { content }
|
||||
toString() {
|
||||
return "Simple: " + StringBox.toString(me.content) # static呼び出し
|
||||
}
|
||||
}
|
||||
|
||||
box Complex from Simple {
|
||||
toString() {
|
||||
return "Complex: " + from Simple.toString() # 問題なし
|
||||
}
|
||||
}
|
||||
|
||||
【哲学的ジレンマ】
|
||||
1. **Everything is Box一貫性**: 全てがBoxであるべき vs 基本型の特別扱い
|
||||
2. **実用性 vs 純粋性**: 使いやすさ vs 設計哲学の一貫性
|
||||
3. **二重体系の懸念**: Box型とstatic関数の併存は混乱を招くか
|
||||
|
||||
【他言語の例】
|
||||
- Java: String.valueOf()等のstatic methods + Stringオブジェクト
|
||||
- Python: str()関数 + strオブジェクト
|
||||
- Rust: String::new() + インスタンスメソッド
|
||||
|
||||
【具体的質問】
|
||||
1. 基本Box型(StringBox, IntegerBox, MathBox等)をstatic提供すべきか?
|
||||
2. Everything is Box哲学を維持しながら実用性を確保する方法は?
|
||||
3. Hybrid approach(Box型 + static methods併存)は設計として健全か?
|
||||
4. 基本的すぎるBox型の「特別扱い」は言語設計として妥当か?
|
||||
5. 継承チェーン問題を根本解決する他のアプローチは?
|
||||
|
||||
プログラミング言語の設計哲学と実用性のバランスについて、専門的見解をお聞かせください。
|
||||
165
docs/archive/gemini_consultation_include_namespace.md
Normal file
165
docs/archive/gemini_consultation_include_namespace.md
Normal file
@ -0,0 +1,165 @@
|
||||
# Nyashプログラミング言語のinclude/namespace/usingシステム設計相談
|
||||
|
||||
## 🎯 現在の状況
|
||||
|
||||
### 1. namespace & using設計完了
|
||||
IDE補完最優先システム設計済み:
|
||||
```nyash
|
||||
# 名前空間定義
|
||||
namespace nyashstd {
|
||||
static box string {
|
||||
static upper(str) {
|
||||
return StringBox.upper(str) # 既存実装活用
|
||||
}
|
||||
static lower(str) { ... }
|
||||
}
|
||||
static box math {
|
||||
static sin(x) { ... }
|
||||
}
|
||||
}
|
||||
|
||||
# using文での使用
|
||||
using nyashstd
|
||||
string.upper("hello") # 短い&明確
|
||||
math.sin(3.14)
|
||||
|
||||
# 完全修飾名(常時利用可能)
|
||||
nyashstd.string.upper("hello")
|
||||
```
|
||||
|
||||
### 2. 既存include実装
|
||||
単純なファイル読み込み+実行システム:
|
||||
```nyash
|
||||
include "myfile.nyash" # ファイル内容をパース・実行
|
||||
```
|
||||
|
||||
- 重複読み込み防止機能あり
|
||||
- しかし依存関係管理・名前空間分離なし
|
||||
|
||||
### 3. 新たな課題:統合問題
|
||||
includeとnamespace/usingの統合が必要:
|
||||
- ファイル間依存関係システムが必要
|
||||
- 循環依存の検出・防止
|
||||
- 読み込み順序の決定アルゴリズム
|
||||
|
||||
## 🚨 技術的課題
|
||||
|
||||
### A. 依存関係解決の複雑性
|
||||
```nyash
|
||||
# main.nyash
|
||||
using nyashstd # ← nyashstd.nyashの読み込みが必要
|
||||
using mylib # ← mylib.nyashの読み込みが必要
|
||||
string.upper("hello") # nyashstdから
|
||||
mylib.custom() # mylibから
|
||||
```
|
||||
|
||||
### B. include vs using の設計統合
|
||||
- **include**: 即座にファイル実行(現在の実装)
|
||||
- **using**: 名前空間のインポートのみ(新設計)
|
||||
- 両者の統合・共存方法が不明
|
||||
|
||||
### C. ファイル探索・解決
|
||||
- `using nyashstd` → どのファイルを読み込む?
|
||||
- 標準ライブラリ vs ユーザーライブラリの区別
|
||||
- パス解決アルゴリズム
|
||||
|
||||
## 💡 検討中の解決案:nyash.linkファイル方式
|
||||
|
||||
### 基本アイデア
|
||||
Cargo.toml/package.json類似の依存関係管理ファイル:
|
||||
|
||||
```toml
|
||||
# nyash.link (プロジェクトルート)
|
||||
[dependencies]
|
||||
nyashstd = "./stdlib/nyashstd.nyash"
|
||||
mylib = "./libs/mylib.nyash"
|
||||
|
||||
[search_paths]
|
||||
stdlib = "./stdlib/"
|
||||
libs = "./libs/"
|
||||
```
|
||||
|
||||
### 動作イメージ
|
||||
1. `using nyashstd` 実行時
|
||||
2. nyash.linkを読み取り
|
||||
3. `"./stdlib/nyashstd.nyash"` を特定
|
||||
4. ファイル読み込み・名前空間登録
|
||||
5. `string.upper()` が使用可能に
|
||||
|
||||
## 🤔 深く検討してほしい技術的論点
|
||||
|
||||
### 1. nyash.linkファイル方式の妥当性
|
||||
- **実装複雑度**: 依存関係グラフ構築・解決アルゴリズム
|
||||
- **パフォーマンス**: キャッシュ・遅延読み込みの必要性
|
||||
- **他言語比較**: Rust Cargo、Node.js、Python等の実装からの学習
|
||||
|
||||
### 2. 既存includeとの共存戦略
|
||||
**選択肢A**: includeを低レベルAPIとして残す
|
||||
```nyash
|
||||
include "config.nyash" # 即座実行(設定ファイル等)
|
||||
using mylib # 名前空間インポート(ライブラリ)
|
||||
```
|
||||
|
||||
**選択肢B**: includeを廃止、usingに統一
|
||||
```nyash
|
||||
using config # 設定も名前空間として扱う
|
||||
using mylib # ライブラリも名前空間
|
||||
```
|
||||
|
||||
**選択肢C**: includeをusingの内部実装として隠蔽
|
||||
|
||||
### 3. 段階的実装戦略
|
||||
- **最小実装**: 固定パスでのusing実装
|
||||
- **中級実装**: nyash.link基本機能
|
||||
- **完全実装**: 循環依存検出・パッケージ管理
|
||||
|
||||
### 4. IDE補完・Language Server連携
|
||||
- nyash.linkによる依存関係情報の活用
|
||||
- 補完候補の動的生成
|
||||
- エラー検出・警告システム
|
||||
|
||||
### 5. 標準ライブラリ管理
|
||||
- nyashstdの標準配置場所(相対パス?絶対パス?)
|
||||
- ユーザーライブラリとの区別方法
|
||||
- 将来のパッケージ管理システムへの発展性
|
||||
|
||||
## 🎯 具体的な質問
|
||||
|
||||
1. **nyash.linkファイル方式は技術的に健全で実装可能か?**
|
||||
- 依存関係解決アルゴリズムの実装困難度
|
||||
- 他言語での類似実装の成功例・失敗例
|
||||
|
||||
2. **includeとusingの最適な関係性は?**
|
||||
- 両方残すべき?統一すべき?
|
||||
- それぞれの用途・使い分け
|
||||
|
||||
3. **最小実装からの段階的発展戦略は?**
|
||||
- Phase 1で何を実装すべき?
|
||||
- 段階的機能追加の優先順位
|
||||
|
||||
4. **パフォーマンスへの影響は許容範囲内か?**
|
||||
- ファイル読み込みオーバーヘッド
|
||||
- 名前解決の計算コスト
|
||||
|
||||
5. **他に考慮すべき設計上の課題はあるか?**
|
||||
- 見落としている技術的問題
|
||||
- より良い代替案の存在
|
||||
|
||||
## 🌟 Nyashの設計哲学との整合性
|
||||
|
||||
- **Everything is Box**: 名前空間もBoxとして扱うべき?
|
||||
- **明示性重視**: 依存関係の明示的記述(nyash.link)は哲学と合致
|
||||
- **初心者フレンドリー**: include廃止は学習コストを下げるか?
|
||||
|
||||
## 🔥 期待する回答
|
||||
|
||||
プログラミング言語設計・実装の専門的視点から:
|
||||
- nyash.link方式の実現可能性・妥当性評価
|
||||
- 実装戦略の具体的提案
|
||||
- 潜在的課題の指摘・解決策
|
||||
- 他言語実装例からの学習ポイント
|
||||
- Nyash哲学との整合性確保方法
|
||||
|
||||
---
|
||||
|
||||
**深い技術検討をお願いします!🐾**
|
||||
58
docs/archive/hybrid_approach_consultation.txt
Normal file
58
docs/archive/hybrid_approach_consultation.txt
Normal file
@ -0,0 +1,58 @@
|
||||
Nyashプログラミング言語のハイブリッドアプローチ設計について相談です。
|
||||
|
||||
【ハイブリッドアプローチ提案】
|
||||
前回の「静的メソッド vs Everything is Box」議論を踏まえ、実用性と哲学を両立する設計を提案します。
|
||||
|
||||
【核心設計】
|
||||
1. **文字列リテラル = 箱化**: "hello" → 自動的にStringBox
|
||||
2. **名前空間 = static class名**: StringBox.upper()で明示的アクセス
|
||||
3. **インスタンスメソッド併用**: obj.method()も継続利用可能
|
||||
4. **継承は特殊拡張のみ**: 基本操作は名前空間、特殊な拡張のみ継承
|
||||
5. **nobox最適化**: パフォーマンス重視時のプリミティブ化
|
||||
|
||||
【具体例】
|
||||
// Everything is Box哲学維持
|
||||
local msg = "hello" // 自動StringBox化
|
||||
|
||||
// 名前空間経由(明示的・継承不要)
|
||||
local upper = StringBox.upper(msg) // "HELLO"
|
||||
local len = StringBox.length(msg) // 5
|
||||
local result = MathBox.sin(3.14) // 計算
|
||||
|
||||
// インスタンスメソッド(従来通り)
|
||||
print(msg.upper()) // "HELLO"
|
||||
print(msg.length()) // 5
|
||||
|
||||
// 特殊拡張のみ継承(継承チェーン問題回避)
|
||||
box LoggedString from StringBox {
|
||||
init { access_count }
|
||||
override toString() {
|
||||
me.access_count++
|
||||
return from StringBox.toString()
|
||||
}
|
||||
}
|
||||
|
||||
// 将来の最適化
|
||||
nobox local fast_str = "hello" // プリミティブ文字列
|
||||
local optimized = StringBox.upper(fast_str) // 高速処理
|
||||
|
||||
【設計の利点】
|
||||
1. **Everything is Box維持**: 哲学的一貫性確保
|
||||
2. **継承チェーン問題回避**: 基本操作は名前空間で解決
|
||||
3. **明示性重視**: StringBox.method()で何をしているか明確
|
||||
4. **実用性確保**: いちいち継承しなくても基本操作可能
|
||||
5. **段階的最適化**: noboxで性能チューニング可能
|
||||
|
||||
【懸念点・質問】
|
||||
1. **二重API問題**: StringBox.upper() vs obj.upper() の併存は混乱を招くか?
|
||||
2. **名前空間汚染**: 多数のstatic methodsがBox名前空間を占有する問題は?
|
||||
3. **学習コスト**: どちらを使うべきかの判断基準をユーザーが覚える負担は?
|
||||
4. **パフォーマンス**: 自動箱化のオーバーヘッドは許容範囲か?
|
||||
5. **他言語比較**: このハイブリッド設計は主流言語と比較して自然か?
|
||||
|
||||
【他言語の参考例】
|
||||
- Python: str.upper() + "hello".upper() 併存
|
||||
- Java: String.valueOf() + obj.toString() 併存
|
||||
- JavaScript: String.fromCharCode() + str.charAt() 併存
|
||||
|
||||
Nyashの哲学(明示性・Everything is Box)を維持しながら、実用的で学習コストの低いハイブリッド設計として成立するか、専門的見解をお聞かせください。
|
||||
64
docs/archive/ide_completion_design.txt
Normal file
64
docs/archive/ide_completion_design.txt
Normal file
@ -0,0 +1,64 @@
|
||||
NyashプログラミングIDE補完機能との相性を考慮した名前空間設計について相談です。
|
||||
|
||||
【発見した重要な問題】
|
||||
プレリュード(自動インポート)は、IDE補完機能との相性が悪い。
|
||||
|
||||
【具体例】
|
||||
// プレリュード方式
|
||||
string.upper("hello") // ❌ stringがどこから来たか不明、補完が効かない
|
||||
|
||||
// 明示的名前空間方式
|
||||
nyashstd.string.upper("hello") // ✅ ny と打つだけで全候補表示!
|
||||
|
||||
【IDE補完の重要性】
|
||||
1. **探索可能性(Discoverability)**: 初心者が「何が使えるか」を発見
|
||||
2. **学習曲線**: 補完で関数名・引数を学べる
|
||||
3. **生産性**: タイプ数削減、タイポ防止
|
||||
4. **ドキュメント**: 補完時にドキュメント表示
|
||||
|
||||
【検討している設計案】
|
||||
|
||||
案1: nyashstd名前空間(超明示的)
|
||||
nyashstd.string.upper("hello")
|
||||
nyashstd.array.push(arr, item)
|
||||
nyashstd.math.sin(3.14)
|
||||
// 利点: ny で全部補完、最高の探索可能性
|
||||
// 欠点: 毎回長い
|
||||
|
||||
案2: using nyashstd(バランス型)
|
||||
using nyashstd
|
||||
string.upper("hello")
|
||||
array.push(arr, item)
|
||||
// 利点: 補完も効く、短い
|
||||
// 欠点: using忘れると動かない
|
||||
|
||||
案3: 階層的アプローチ(段階的)
|
||||
// レベル1: 完全明示(初心者)
|
||||
nyashstd.string.upper("hello")
|
||||
|
||||
// レベル2: using(中級者)
|
||||
using nyashstd
|
||||
string.upper("hello")
|
||||
|
||||
// レベル3: プレリュード(上級者)
|
||||
upper("hello") // 最頻出のみ
|
||||
|
||||
案4: エイリアス提供
|
||||
// 両方提供
|
||||
nyashstd.string.upper // 明示版
|
||||
str.upper // 短縮版(プレリュード)
|
||||
|
||||
【VSCode等のIDE対応を考慮した質問】
|
||||
1. IDE補完を最優先にすべきか、簡潔性を優先すべきか?
|
||||
2. nyashstd.* という統一名前空間は良い設計か?
|
||||
3. 複数の書き方を許可するのは混乱を招くか?
|
||||
4. 他言語でIDE補完に優しい設計例は?
|
||||
5. Language Serverとの相性を考慮した最適解は?
|
||||
|
||||
【参考:他言語のアプローチ】
|
||||
- Rust: std::string::String (明示的、補完◎)
|
||||
- Go: strings.ToUpper() (パッケージ明示、補完◎)
|
||||
- Python: str.upper() (組み込み、補完△)
|
||||
- JavaScript: "".toUpperCase() (プロトタイプ、補完○)
|
||||
|
||||
モダンなIDE連携を前提とした、初心者にも優しい名前空間設計をご提案ください。
|
||||
59
docs/archive/modern_dependency_consultation.txt
Normal file
59
docs/archive/modern_dependency_consultation.txt
Normal file
@ -0,0 +1,59 @@
|
||||
現代的プログラミング言語の依存関係システムについて深い相談です。
|
||||
|
||||
【#include地獄からの脱却】
|
||||
C/C++の#includeシステムの問題:
|
||||
- 循環参照が頻発
|
||||
- Makefileが複雑すぎる
|
||||
- 重複インクルード問題
|
||||
- 依存関係の把握が困難
|
||||
|
||||
【現代言語の革新的解決策調査】
|
||||
Rust: Cargo.toml + use文
|
||||
Go: go.mod + import文
|
||||
TypeScript: package.json + import/export
|
||||
Python: pyproject.toml + import文
|
||||
C#: .csproj + using文
|
||||
|
||||
【共通する革新ポイント】
|
||||
1. パッケージマネージャー統合
|
||||
2. 明示的依存宣言ファイル
|
||||
3. モジュール/パッケージ単位管理
|
||||
4. ビルドツール統合
|
||||
5. 循環依存の静的検出
|
||||
|
||||
【Nyash独自アプローチ提案:nyash.link】
|
||||
# nyash.link - 依存管理専用ファイル
|
||||
project:
|
||||
name: "my-app"
|
||||
version: "1.0.0"
|
||||
|
||||
dependencies:
|
||||
nyashstd: "builtin"
|
||||
nyash-http: "^2.1.0"
|
||||
"./utils": "local"
|
||||
|
||||
modules:
|
||||
main: []
|
||||
utils: ["data"]
|
||||
data: []
|
||||
# 循環依存自動検出・エラー
|
||||
|
||||
build:
|
||||
target: "wasm"
|
||||
optimize: true
|
||||
|
||||
【設計哲学の問い】
|
||||
1. #includeを完全に捨てて、宣言的依存管理にすべきか?
|
||||
2. nyash.linkのような専用ファイルは過剰か、必要か?
|
||||
3. 循環依存を言語レベルで禁止すべきか?
|
||||
4. パッケージマネージャーとビルドシステムの統合度は?
|
||||
5. 既存言語と差別化できる革新的な仕組みは?
|
||||
|
||||
【技術的課題】
|
||||
- 依存解決アルゴリズムの効率性
|
||||
- バージョン管理との統合
|
||||
- IDE/Language Serverとの連携
|
||||
- インクリメンタルビルドとの相性
|
||||
- WebAssemblyターゲットでの最適化
|
||||
|
||||
現代のソフトウェア開発における依存関係管理のベストプラクティスと、Nyash言語に最適な革新的依存システムをご提案ください。
|
||||
38
docs/archive/multi_delegation_consultation.txt
Normal file
38
docs/archive/multi_delegation_consultation.txt
Normal file
@ -0,0 +1,38 @@
|
||||
Nyashプログラミング言語の多重デリゲーション設計について深い相談です。
|
||||
|
||||
【現在の状況】
|
||||
- Everything is Box哲学でデリゲーション優先設計
|
||||
- 明示性重視(何が起きているかを隠さない)
|
||||
- 単一デリゲーション(box Child from Parent)は完全実装済み
|
||||
|
||||
【多重デリゲーション候補】
|
||||
box MultiChild from ParentA, ParentB {
|
||||
method() {
|
||||
from ParentA.methodA()
|
||||
from ParentB.methodB()
|
||||
}
|
||||
}
|
||||
|
||||
【Diamond Problem(菱形継承問題)】
|
||||
box Middle from StringBox { ... }
|
||||
box Diamond from Middle, StringBox {
|
||||
toString() {
|
||||
local a = from Middle.toString() # Middle内でStringBox.toString()呼び出し
|
||||
local b = from StringBox.toString() # 直接StringBox.toString()呼び出し
|
||||
# 同じStringBoxに2回アクセス→状態変更重複・パフォーマンス問題
|
||||
}
|
||||
}
|
||||
|
||||
【解決策候補】
|
||||
1. **上書き方式**: 後から指定した方を優先(from Middle, StringBox → StringBoxが優先)
|
||||
2. **明示的解決**: 曖昧性をコンパイル時エラーにして、ユーザーに解決を強制
|
||||
3. **完全禁止**: 多重デリゲーション自体を禁止、コンポジション推奨
|
||||
|
||||
【質問】
|
||||
1. Nyash明示性哲学に最も適した解決策は?
|
||||
2. 上書き方式は「明示性」に反するか?
|
||||
3. Diamond Problemを根本的に避ける設計は?
|
||||
4. 実用性vs安全性のバランスをどう取るべき?
|
||||
5. 他言語(Go, Rust, Kotlin等)の参考になる設計は?
|
||||
|
||||
プログラミング言語設計の専門的視点から、Nyashの哲学に最適な多重デリゲーション設計を分析してください。
|
||||
75
docs/archive/namespace_binding_consultation.txt
Normal file
75
docs/archive/namespace_binding_consultation.txt
Normal file
@ -0,0 +1,75 @@
|
||||
Nyashプログラミング言語の名前空間結びつけ設計について深い相談です。
|
||||
|
||||
【前提】
|
||||
ハイブリッドアプローチ(文字列リテラル箱化 + 静的メソッド)を採用予定。
|
||||
static class string{}, static class math{} が存在する状況での名前空間設計。
|
||||
|
||||
【現在の課題】
|
||||
- namespace string, namespace math は明示的だが記述が煩雑
|
||||
- namespace nyash と書いて、nyashとstring/mathを結びつけたい
|
||||
- 明示性と簡潔性の完璧なバランスを求める
|
||||
|
||||
【検討中の設計パターン】
|
||||
|
||||
Pattern 1: namespace集約 + imports
|
||||
namespace nyash imports string, math {
|
||||
// この中では直接アクセス可能
|
||||
local msg = string.upper("hello")
|
||||
local result = math.sin(3.14)
|
||||
print(msg) // nyash組み込み関数
|
||||
}
|
||||
|
||||
Pattern 2: static class nyash階層
|
||||
static class nyash {
|
||||
static class string {
|
||||
upper(str) { ... }
|
||||
length(str) { ... }
|
||||
}
|
||||
static class math {
|
||||
sin(x) { ... }
|
||||
cos(x) { ... }
|
||||
}
|
||||
}
|
||||
// 使用: nyash.string.upper("hello")
|
||||
|
||||
Pattern 3: static class nyash直接定義
|
||||
static class nyash {
|
||||
string_upper(str) { ... }
|
||||
math_sin(x) { ... }
|
||||
print(msg) { ... }
|
||||
}
|
||||
// 使用: nyash.string_upper("hello")
|
||||
|
||||
Pattern 4: using システム
|
||||
using nyash.string as string
|
||||
using nyash.math as math
|
||||
// その後: string.upper("hello")
|
||||
|
||||
【Nyash設計哲学との整合性】
|
||||
1. Everything is Box: 全てがBoxオブジェクト
|
||||
2. 明示性重視: 何が起きているかを隠さない
|
||||
3. 初心者フレンドリー: 学習コストの低減
|
||||
4. 実用性確保: 日常的な使いやすさ
|
||||
|
||||
【重要な検討点】
|
||||
1. **明示性 vs 簡潔性**: どこまで簡潔にしても明示性を保てるか?
|
||||
2. **スコープ管理**: namespace内での名前衝突回避方法は?
|
||||
3. **階層 vs フラット**: nyash.string.upper vs nyash.string_upper どちらが自然?
|
||||
4. **学習コスト**: ユーザーが覚えるべきルールの複雑さは?
|
||||
5. **IDE支援**: 補完・ナビゲーション機能との相性は?
|
||||
|
||||
【他言語の参考例】
|
||||
- Python: from math import sin, cos
|
||||
- JavaScript: import { upper } from 'string-utils'
|
||||
- C#: using System; using System.Math;
|
||||
- Rust: use std::collections::HashMap;
|
||||
- Go: import "math", import "strings"
|
||||
|
||||
【質問】
|
||||
1. Nyash哲学に最も適した名前空間結びつけ方法は?
|
||||
2. namespace nyash概念の技術的実装可能性は?
|
||||
3. 明示性を保ちながら最も簡潔な記述方法は?
|
||||
4. static class階層 vs namespace imports どちらが優れているか?
|
||||
5. 初心者にとって最も理解しやすい設計は?
|
||||
|
||||
プログラミング言語の名前空間設計の専門的視点から、Nyashに最適な解決策をご提案ください。
|
||||
281
docs/予定/native-plan/issues/phase_9_75e_namespace_using_system.md
Normal file
281
docs/予定/native-plan/issues/phase_9_75e_namespace_using_system.md
Normal file
@ -0,0 +1,281 @@
|
||||
# Phase 9.75e: namespace & using システム実装
|
||||
|
||||
## 🎯 背景・目的
|
||||
|
||||
IDE補完機能との相性を最優先にした、現代的な名前空間・インポートシステムの実装。
|
||||
|
||||
### 問題意識
|
||||
- プレリュード方式:IDE補完が効かない、探索可能性が低い
|
||||
- 全機能明示:冗長、タイプ数が多い
|
||||
- 理想:`ny` と打つだけで全標準機能が補完される
|
||||
|
||||
### 目標
|
||||
```nyash
|
||||
# IDE補完完璧
|
||||
nyashstd.string.upper("hello") # ny → 全候補表示
|
||||
|
||||
# using文で簡潔
|
||||
using nyashstd
|
||||
string.upper("hello") # 短い&明確
|
||||
math.sin(3.14) # 探索可能性維持
|
||||
```
|
||||
|
||||
## 📋 要求仕様
|
||||
|
||||
### 1. namespace構文
|
||||
```nyash
|
||||
# ファイル:nyashstd.nyash
|
||||
namespace nyashstd {
|
||||
static box string {
|
||||
static upper(str) {
|
||||
return StringBox.upper(str) # 既存実装活用
|
||||
}
|
||||
static lower(str) { ... }
|
||||
static split(str, sep) { ... }
|
||||
}
|
||||
|
||||
static box math {
|
||||
static sin(x) { ... }
|
||||
static cos(x) { ... }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. using構文(2パターン)
|
||||
```nyash
|
||||
# パターンA: 完全インポート
|
||||
using nyashstd
|
||||
string.upper("hello")
|
||||
math.sin(3.14)
|
||||
|
||||
# パターンB: 選択インポート(将来拡張)
|
||||
using nyashstd.string
|
||||
using nyashstd.math
|
||||
string.upper("hello")
|
||||
math.sin(3.14)
|
||||
```
|
||||
|
||||
### 3. 完全修飾名(常時利用可能)
|
||||
```nyash
|
||||
# using なしでも常に使える
|
||||
nyashstd.string.upper("hello")
|
||||
nyashstd.math.sin(3.14)
|
||||
```
|
||||
|
||||
## 🔧 技術的課題
|
||||
|
||||
### A. パーサー拡張
|
||||
1. **namespace宣言解析**
|
||||
- `namespace identifier { ... }` 構文
|
||||
- ネストしたstatic box解析
|
||||
- スコープ管理
|
||||
|
||||
2. **using文解析**
|
||||
- `using namespace_path` 構文
|
||||
- ファイル先頭での使用制限
|
||||
- 重複インポート検出
|
||||
|
||||
3. **修飾名解析**
|
||||
- `identifier.identifier.identifier` 構文
|
||||
- 名前解決の段階的処理
|
||||
|
||||
### B. インタープリター/VM拡張
|
||||
1. **名前空間レジストリ**
|
||||
- グローバル名前空間管理
|
||||
- 階層的名前解決
|
||||
- キャッシュ機能
|
||||
|
||||
2. **using解決**
|
||||
- インポートされた名前の局所化
|
||||
- 名前衝突検出・エラー処理
|
||||
- スコープ境界管理
|
||||
|
||||
### C. ファイル間依存関係システム
|
||||
```nyash
|
||||
# ファイル: main.nyash
|
||||
using nyashstd # ← nyashstd.nyash の読み込みが必要
|
||||
string.upper("hello")
|
||||
|
||||
# ファイル: nyashstd.nyash
|
||||
namespace nyashstd { ... }
|
||||
```
|
||||
|
||||
**課題:**
|
||||
- ファイル読み込み順序の決定
|
||||
- 循環依存の検出・防止
|
||||
- 依存関係解決アルゴリズム
|
||||
- パフォーマンス(キャッシュ・遅延読み込み)
|
||||
|
||||
## 🚀 実装方針
|
||||
|
||||
### Step 1: パーサー拡張
|
||||
```rust
|
||||
// AST拡張
|
||||
pub enum Statement {
|
||||
// 既存...
|
||||
NamespaceDeclaration {
|
||||
name: String,
|
||||
body: Vec<Statement>,
|
||||
},
|
||||
UsingStatement {
|
||||
namespace_path: Vec<String>, // ["nyashstd", "string"]
|
||||
},
|
||||
}
|
||||
|
||||
// 修飾名アクセス
|
||||
pub enum Expression {
|
||||
// 既存...
|
||||
QualifiedAccess {
|
||||
path: Vec<String>, // ["nyashstd", "string", "upper"]
|
||||
args: Vec<Expression>,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### Step 2: 名前空間レジストリ
|
||||
```rust
|
||||
// グローバル名前空間管理
|
||||
pub struct NamespaceRegistry {
|
||||
namespaces: HashMap<String, NamespaceDefinition>,
|
||||
using_imports: HashMap<String, Vec<String>>, // ファイル別インポート
|
||||
}
|
||||
|
||||
pub struct NamespaceDefinition {
|
||||
static_boxes: HashMap<String, StaticBoxDefinition>,
|
||||
}
|
||||
|
||||
pub struct StaticBoxDefinition {
|
||||
static_methods: HashMap<String, MethodDefinition>,
|
||||
}
|
||||
```
|
||||
|
||||
### Step 3: 依存関係解決
|
||||
```rust
|
||||
// ファイル依存関係グラフ
|
||||
pub struct DependencyResolver {
|
||||
file_dependencies: HashMap<PathBuf, Vec<PathBuf>>,
|
||||
load_order: Vec<PathBuf>,
|
||||
}
|
||||
|
||||
impl DependencyResolver {
|
||||
// 循環依存検出
|
||||
pub fn detect_cycles(&self) -> Result<(), Vec<PathBuf>>;
|
||||
|
||||
// 読み込み順序決定
|
||||
pub fn resolve_load_order(&self) -> Result<Vec<PathBuf>, DependencyError>;
|
||||
}
|
||||
```
|
||||
|
||||
## 🧪 必須テストケース
|
||||
|
||||
### 1. 基本動作テスト
|
||||
```nyash
|
||||
# test_namespace_basic.nyash
|
||||
namespace test_ns {
|
||||
static box example {
|
||||
static hello() {
|
||||
return "Hello from namespace!"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
local result = test_ns.example.hello()
|
||||
assert(result == "Hello from namespace!")
|
||||
```
|
||||
|
||||
### 2. using文テスト
|
||||
```nyash
|
||||
# test_using_basic.nyash
|
||||
using nyashstd
|
||||
|
||||
local upper = string.upper("hello")
|
||||
assert(upper == "HELLO")
|
||||
|
||||
local result = math.sin(0)
|
||||
assert(result == 0)
|
||||
```
|
||||
|
||||
### 3. 名前衝突テスト
|
||||
```nyash
|
||||
# test_name_collision.nyash
|
||||
using nyashstd
|
||||
|
||||
# ❌ これはエラーになるべき
|
||||
static box string {
|
||||
static custom() { return "custom" }
|
||||
}
|
||||
# Error: 'string' already imported from nyashstd
|
||||
```
|
||||
|
||||
### 4. 依存関係テスト
|
||||
```nyash
|
||||
# File: dependency_test_main.nyash
|
||||
using dependency_test_lib
|
||||
local result = helper.process("data")
|
||||
|
||||
# File: dependency_test_lib.nyash
|
||||
namespace dependency_test_lib {
|
||||
static box helper {
|
||||
static process(data) { return "processed: " + data }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5. 循環依存エラーテスト
|
||||
```nyash
|
||||
# File: circular_a.nyash
|
||||
using circular_b
|
||||
# ...
|
||||
|
||||
# File: circular_b.nyash
|
||||
using circular_a # ← Error: Circular dependency detected
|
||||
# ...
|
||||
```
|
||||
|
||||
## ✅ 完了条件
|
||||
|
||||
### パーサー
|
||||
- [ ] namespace宣言の正常解析
|
||||
- [ ] using文の正常解析
|
||||
- [ ] 修飾名アクセスの正常解析
|
||||
- [ ] 構文エラーの適切な報告
|
||||
|
||||
### インタープリター/VM
|
||||
- [ ] 名前空間レジストリ動作
|
||||
- [ ] using解決機能
|
||||
- [ ] 名前衝突検出・エラー処理
|
||||
- [ ] パフォーマンス許容範囲(既存の90%以上)
|
||||
|
||||
### 依存関係システム
|
||||
- [ ] ファイル間依存解決
|
||||
- [ ] 循環依存検出・エラー報告
|
||||
- [ ] 適切な読み込み順序決定
|
||||
- [ ] キャッシュ機能(同一ファイル重複読み込み防止)
|
||||
|
||||
### テスト
|
||||
- [ ] 全テストケース通過
|
||||
- [ ] エラーケース適切処理
|
||||
- [ ] IDE補完対応確認(Language Server連携)
|
||||
|
||||
## 🔗 関連Phase
|
||||
- Phase 8.9: birth()統一システム(完了)
|
||||
- Phase 9: AOT WASM実装(完了)
|
||||
- Phase 10: 高度メモリ管理(完了)
|
||||
- **Phase 11**: FFI/外部ライブラリ統合(予定)
|
||||
|
||||
## 📝 実装ノート
|
||||
|
||||
### 優先順位
|
||||
1. **High**: パーサー拡張(namespace, using)
|
||||
2. **High**: 基本名前解決機能
|
||||
3. **Medium**: 依存関係システム
|
||||
4. **Low**: パフォーマンス最適化
|
||||
|
||||
### 既存コードとの互換性
|
||||
- 既存のStringBox等は変更なし
|
||||
- static box string は既存Boxのラッパーとして実装
|
||||
- 段階的移行可能な設計
|
||||
|
||||
---
|
||||
|
||||
**🐾 Copilot様、この詳細仕様で namespace & using システムの実装をお願いします!**
|
||||
267
docs/予定/nyash.link/README.md
Normal file
267
docs/予定/nyash.link/README.md
Normal file
@ -0,0 +1,267 @@
|
||||
# nyash.linkシステム設計 - モジュール・依存関係管理革命
|
||||
|
||||
## 🎯 設計背景
|
||||
|
||||
### 📊 現状調査結果
|
||||
- **include使用状況**: 主にexamples/text_adventureで10件程度、実用性は限定的
|
||||
- **usingキーワード**: **未実装**(トークナイザーにも存在しない)
|
||||
- **namespace設計**: Phase 9.75eで仕様完成、実装待ち
|
||||
|
||||
### 🌟 Gemini先生の推奨
|
||||
> 「技術的に非常に妥当であり、現代的なプログラミング言語の設計として強く推奨される」
|
||||
|
||||
**結論**: includeほぼ未使用 + using未実装 = 完全に新設計で進められる!🎉
|
||||
|
||||
## 🚀 設計方針
|
||||
|
||||
### 💡 基本コンセプト
|
||||
```
|
||||
依存関係管理(nyash.link) + モジュールインポート(using) = 完璧な統合
|
||||
```
|
||||
|
||||
### 🎯 他言語成功モデル
|
||||
- **Rust**: `Cargo.toml + mod/use` - 厳格で分かりやすい
|
||||
- **Node.js**: `package.json + import/export` - エコシステム成功
|
||||
- **Python**: `pyproject.toml + import` - 依存関係分離
|
||||
|
||||
## 📋 nyash.linkファイル仕様
|
||||
|
||||
### 基本フォーマット
|
||||
```toml
|
||||
# nyash.link (プロジェクトルート)
|
||||
[project]
|
||||
name = "my-nyash-project"
|
||||
version = "0.1.0"
|
||||
description = "素晴らしいNyashプロジェクト"
|
||||
|
||||
[dependencies]
|
||||
# 標準ライブラリ
|
||||
nyashstd = { path = "./stdlib/nyashstd.nyash" }
|
||||
|
||||
# ユーザーライブラリ
|
||||
mylib = { path = "./libs/mylib.nyash" }
|
||||
utils = { path = "./src/utils.nyash" }
|
||||
|
||||
# 将来の外部パッケージ(例)
|
||||
# http_client = { version = "1.0.0", registry = "nyash-pkg" }
|
||||
|
||||
[search_paths]
|
||||
stdlib = "./stdlib/"
|
||||
libs = "./libs/"
|
||||
src = "./src/"
|
||||
|
||||
[build]
|
||||
entry_point = "./src/main.nyash"
|
||||
```
|
||||
|
||||
### 依存関係タイプ
|
||||
|
||||
#### 1. **ローカル依存**
|
||||
```toml
|
||||
[dependencies]
|
||||
my_module = { path = "./src/my_module.nyash" }
|
||||
```
|
||||
|
||||
#### 2. **標準ライブラリ**
|
||||
```toml
|
||||
[dependencies]
|
||||
nyashstd = { stdlib = true } # 特別扱い
|
||||
```
|
||||
|
||||
#### 3. **将来の外部パッケージ**
|
||||
```toml
|
||||
[dependencies]
|
||||
awesome_lib = { version = "^1.2.0", registry = "nyash-pkg" }
|
||||
```
|
||||
|
||||
## 🔧 usingシステム設計
|
||||
|
||||
### 1. トークナイザー拡張
|
||||
```rust
|
||||
// src/tokenizer.rs に追加
|
||||
pub enum TokenType {
|
||||
// 既存...
|
||||
USING, // using (モジュールインポート)
|
||||
NAMESPACE, // namespace (名前空間宣言)
|
||||
}
|
||||
```
|
||||
|
||||
### 2. パーサー拡張
|
||||
```rust
|
||||
// AST拡張
|
||||
pub enum Statement {
|
||||
// 既存...
|
||||
UsingStatement {
|
||||
module_path: Vec<String>, // ["nyashstd", "string"]
|
||||
alias: Option<String>, // using nyashstd.string as str
|
||||
},
|
||||
NamespaceDeclaration {
|
||||
name: String,
|
||||
body: Vec<Statement>,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 基本構文
|
||||
```nyash
|
||||
// ===== using構文パターン =====
|
||||
|
||||
// パターンA: 名前空間全体
|
||||
using nyashstd
|
||||
string.upper("hello") // nyashstd.string.upper
|
||||
math.sin(3.14) // nyashstd.math.sin
|
||||
|
||||
// パターンB: 特定機能(将来拡張)
|
||||
using nyashstd.string
|
||||
upper("hello") // string.upperを直接
|
||||
|
||||
// パターンC: エイリアス(将来拡張)
|
||||
using nyashstd.string as str
|
||||
str.upper("hello")
|
||||
|
||||
// パターンD: 完全修飾名(常時利用可能)
|
||||
nyashstd.string.upper("hello") // using不要
|
||||
```
|
||||
|
||||
## 📁 推奨ディレクトリ構造
|
||||
|
||||
### 基本プロジェクト構造
|
||||
```
|
||||
my-nyash-project/
|
||||
├── nyash.link # 依存関係定義
|
||||
├── src/
|
||||
│ ├── main.nyash # エントリーポイント
|
||||
│ ├── utils.nyash # ユーティリティモジュール
|
||||
│ └── models/
|
||||
│ └── user.nyash # モデル定義
|
||||
├── libs/ # プロジェクト固有ライブラリ
|
||||
│ └── mylib.nyash
|
||||
├── stdlib/ # 標準ライブラリ(システム配布)
|
||||
│ └── nyashstd.nyash
|
||||
└── tests/ # テストファイル
|
||||
└── test_main.nyash
|
||||
```
|
||||
|
||||
### 標準ライブラリ構造
|
||||
```
|
||||
stdlib/
|
||||
├── nyashstd.nyash # メインエントリー
|
||||
├── string/
|
||||
│ └── mod.nyash # string関連機能
|
||||
├── math/
|
||||
│ └── mod.nyash # 数学関数
|
||||
├── http/
|
||||
│ └── mod.nyash # HTTP関連
|
||||
└── io/
|
||||
└── mod.nyash # I/O関連
|
||||
```
|
||||
|
||||
## 🔄 動作フロー
|
||||
|
||||
### 1. プロジェクト初期化
|
||||
```bash
|
||||
# 将来のCLI例
|
||||
nyash init my-project # nyash.linkテンプレート生成
|
||||
cd my-project
|
||||
```
|
||||
|
||||
### 2. 実行時解決
|
||||
```
|
||||
main.nyash実行
|
||||
↓
|
||||
nyash.link読み込み
|
||||
↓
|
||||
using nyashstd解析
|
||||
↓
|
||||
./stdlib/nyashstd.nyash読み込み
|
||||
↓
|
||||
namespace nyashstd解析・登録
|
||||
↓
|
||||
string.upper()利用可能
|
||||
```
|
||||
|
||||
### 3. 名前解決アルゴリズム
|
||||
```
|
||||
string.upper() 呼び出し
|
||||
↓
|
||||
1. ローカルスコープ検索
|
||||
2. usingでインポートされた名前空間検索
|
||||
3. 完全修飾名として解釈
|
||||
4. エラー(未定義)
|
||||
```
|
||||
|
||||
## 🧪 実装段階
|
||||
|
||||
### Phase 1: 最小実装
|
||||
```nyash
|
||||
// ✅ 実装目標
|
||||
using mylib // 単純パス解決
|
||||
mylib.hello() // 関数呼び出し
|
||||
|
||||
// nyash.link
|
||||
[dependencies]
|
||||
mylib = { path = "./mylib.nyash" }
|
||||
```
|
||||
|
||||
### Phase 2: 名前空間サポート
|
||||
```nyash
|
||||
// ✅ 実装目標
|
||||
using nyashstd
|
||||
string.upper("hello")
|
||||
|
||||
// nyashstd.nyash
|
||||
namespace nyashstd {
|
||||
static box string {
|
||||
static upper(str) { ... }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Phase 3: 高度機能
|
||||
- エイリアス(`using ... as ...`)
|
||||
- 選択インポート(`using nyashstd.string`)
|
||||
- 循環依存検出
|
||||
- パッケージレジストリ連携
|
||||
|
||||
## ⚡ 実装優先順位
|
||||
|
||||
### 🚨 Critical(即時)
|
||||
1. **UsingTokenizer実装** - Token::USINGを追加
|
||||
2. **基本パーサー** - using文AST構築
|
||||
3. **nyash.link解析** - TOML読み込み機能
|
||||
|
||||
### ⚡ High(今週)
|
||||
4. **名前解決エンジン** - モジュール→ファイル解決
|
||||
5. **基本テスト** - using mylib動作確認
|
||||
6. **エラー処理** - 未定義モジュール等
|
||||
|
||||
### 📝 Medium(来週)
|
||||
7. **namespace構文** - static box解析
|
||||
8. **標準ライブラリ設計** - nyashstd.nyash作成
|
||||
9. **完全修飾名** - nyashstd.string.upper()
|
||||
|
||||
### 🔮 Future(今後)
|
||||
10. **IDE連携** - Language Server補完
|
||||
11. **パッケージマネージャー** - 外部レジストリ
|
||||
12. **循環依存検出** - 高度エラー処理
|
||||
|
||||
## 🎉 期待効果
|
||||
|
||||
### 📈 開発体験向上
|
||||
- **IDE補完**: `ny`→全標準機能表示
|
||||
- **探索可能性**: モジュール構造が明確
|
||||
- **エラー削減**: 名前衝突・未定義の事前検出
|
||||
|
||||
### 🏗️ プロジェクト管理
|
||||
- **依存関係明確化**: nyash.linkで一元管理
|
||||
- **ビルド再現性**: 他環境での確実な動作
|
||||
- **スケーラビリティ**: 大規模プロジェクト対応
|
||||
|
||||
### 🌍 エコシステム発展
|
||||
- **ライブラリ共有**: 標準化されたモジュール形式
|
||||
- **コミュニティ成長**: パッケージレジストリ基盤
|
||||
- **言語成熟度**: モダンな言語仕様
|
||||
|
||||
---
|
||||
|
||||
**🐾 この設計でNyashが真にモダンなプログラミング言語になるにゃ!**
|
||||
654
docs/予定/nyash.link/bid-using-integration.md
Normal file
654
docs/予定/nyash.link/bid-using-integration.md
Normal file
@ -0,0 +1,654 @@
|
||||
# BID×usingシステム統合:技術実装詳細
|
||||
|
||||
## 🎯 統合設計の核心
|
||||
|
||||
### 📊 既存システムとの整合性
|
||||
- ✅ **MIR ExternCall**: 既にFFI-ABI対応実装済み
|
||||
- ✅ **WASM RuntimeImports**: BID→WASM自動生成基盤あり
|
||||
- ✅ **VM ExternStub**: スタブ実行環境実装済み
|
||||
- 🔧 **統合課題**: usingシステムとBIDの橋渡し実装
|
||||
|
||||
### 🚀 統合アーキテクチャ概要
|
||||
```
|
||||
User Code (using statements)
|
||||
↓
|
||||
UniversalNamespaceRegistry
|
||||
↓
|
||||
CallTarget Resolution
|
||||
↓ ↓ ↓
|
||||
Builtin FFI-ABI NyashModule
|
||||
↓ ↓ ↓
|
||||
MIR Generation (BuiltinCall/ExternCall/ModuleCall)
|
||||
↓
|
||||
Backend Execution (VM/WASM/AOT)
|
||||
```
|
||||
|
||||
## 🏗️ 詳細技術実装
|
||||
|
||||
### 1. BID定義システム
|
||||
|
||||
#### **BIDファイル構造拡張**
|
||||
```yaml
|
||||
# apis/enhanced_canvas.yaml
|
||||
version: 1
|
||||
metadata:
|
||||
name: "Enhanced Canvas API"
|
||||
description: "Extended Canvas API with batch operations"
|
||||
target_environments: ["browser", "node-canvas", "skia"]
|
||||
nyash_namespace: "canvas_api" # usingで使用する名前空間
|
||||
|
||||
interfaces:
|
||||
- name: canvas_api.canvas
|
||||
box: Canvas
|
||||
methods:
|
||||
# 基本描画
|
||||
- name: fillRect
|
||||
params:
|
||||
- {string: canvas_id, description: "Canvas element ID"}
|
||||
- {i32: x, description: "X coordinate"}
|
||||
- {i32: y, description: "Y coordinate"}
|
||||
- {i32: width, description: "Rectangle width"}
|
||||
- {i32: height, description: "Rectangle height"}
|
||||
- {string: color, description: "Fill color (CSS format)"}
|
||||
returns: void
|
||||
effect: io
|
||||
optimization_hints:
|
||||
batch_compatible: true # バッチ処理可能
|
||||
gpu_accelerated: true # GPU加速対応
|
||||
|
||||
# バッチ描画(最適化版)
|
||||
- name: fillRectBatch
|
||||
params:
|
||||
- {string: canvas_id}
|
||||
- {array_of_rect: rects, element_type: "CanvasRect"}
|
||||
returns: void
|
||||
effect: io
|
||||
optimization_hints:
|
||||
prefer_over: ["fillRect"] # 複数fillRectの代替
|
||||
min_batch_size: 3
|
||||
|
||||
# テキスト描画
|
||||
- name: fillText
|
||||
params:
|
||||
- {string: canvas_id}
|
||||
- {string: text}
|
||||
- {i32: x}
|
||||
- {i32: y}
|
||||
- {string: font}
|
||||
- {string: color}
|
||||
returns: void
|
||||
effect: io
|
||||
|
||||
# カスタム型定義
|
||||
custom_types:
|
||||
- name: CanvasRect
|
||||
fields:
|
||||
- {i32: x}
|
||||
- {i32: y}
|
||||
- {i32: width}
|
||||
- {i32: height}
|
||||
- {string: color}
|
||||
```
|
||||
|
||||
#### **BID読み込み・検証システム**
|
||||
```rust
|
||||
// 新ファイル: src/bid/mod.rs
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct BidDefinition {
|
||||
pub version: u32,
|
||||
pub metadata: BidMetadata,
|
||||
pub interfaces: Vec<BidInterface>,
|
||||
pub custom_types: Option<Vec<BidCustomType>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct BidMetadata {
|
||||
pub name: String,
|
||||
pub description: String,
|
||||
pub target_environments: Vec<String>,
|
||||
pub nyash_namespace: String, // using文で使用する名前空間名
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct BidInterface {
|
||||
pub name: String, // "canvas_api.canvas"
|
||||
pub box_name: String, // "Canvas"
|
||||
pub methods: Vec<BidMethod>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct BidMethod {
|
||||
pub name: String,
|
||||
pub params: Vec<BidParam>,
|
||||
pub returns: BidType,
|
||||
pub effect: BidEffect,
|
||||
pub optimization_hints: Option<BidOptimizationHints>,
|
||||
pub description: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Deserialize, Serialize)]
|
||||
pub struct BidOptimizationHints {
|
||||
pub batch_compatible: Option<bool>,
|
||||
pub gpu_accelerated: Option<bool>,
|
||||
pub prefer_over: Option<Vec<String>>,
|
||||
pub min_batch_size: Option<usize>,
|
||||
}
|
||||
|
||||
impl BidDefinition {
|
||||
pub fn load_from_file(path: &Path) -> Result<Self, BidError> {
|
||||
let content = std::fs::read_to_string(path)?;
|
||||
let bid: BidDefinition = serde_yaml::from_str(&content)?;
|
||||
|
||||
// バリデーション
|
||||
bid.validate()?;
|
||||
|
||||
Ok(bid)
|
||||
}
|
||||
|
||||
pub fn validate(&self) -> Result<(), BidError> {
|
||||
// バージョン確認
|
||||
if self.version > 1 {
|
||||
return Err(BidError::UnsupportedVersion(self.version));
|
||||
}
|
||||
|
||||
// 名前空間重複チェック
|
||||
let mut interface_names = HashSet::new();
|
||||
for interface in &self.interfaces {
|
||||
if interface_names.contains(&interface.name) {
|
||||
return Err(BidError::DuplicateInterface(interface.name.clone()));
|
||||
}
|
||||
interface_names.insert(interface.name.clone());
|
||||
}
|
||||
|
||||
// パラメータ型確認
|
||||
for interface in &self.interfaces {
|
||||
for method in &interface.methods {
|
||||
for param in &method.params {
|
||||
self.validate_type(¶m.param_type)?;
|
||||
}
|
||||
self.validate_type(&method.returns)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn resolve_method(&self, box_name: &str, method_name: &str)
|
||||
-> Option<&BidMethod> {
|
||||
|
||||
for interface in &self.interfaces {
|
||||
// インターフェース名から最後の部分を取得
|
||||
// "canvas_api.canvas" → "canvas"
|
||||
let interface_box_name = interface.name.split('.').last().unwrap_or(&interface.name);
|
||||
|
||||
if interface_box_name == box_name {
|
||||
for method in &interface.methods {
|
||||
if method.name == method_name {
|
||||
return Some(method);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 統合名前空間レジストリ詳細
|
||||
|
||||
#### **UniversalNamespaceRegistry実装**
|
||||
```rust
|
||||
// src/registry/universal.rs
|
||||
use crate::stdlib::BuiltinStdlib;
|
||||
use crate::bid::BidDefinition;
|
||||
use crate::module::ExternalModule;
|
||||
use crate::mir::Effect;
|
||||
|
||||
pub struct UniversalNamespaceRegistry {
|
||||
/// 組み込み標準ライブラリ
|
||||
builtin_stdlib: Arc<BuiltinStdlib>,
|
||||
|
||||
/// FFI-ABI定義(BID)
|
||||
bid_definitions: HashMap<String, Arc<BidDefinition>>,
|
||||
|
||||
/// Nyashモジュール(従来)
|
||||
nyash_modules: HashMap<String, Arc<ExternalModule>>,
|
||||
|
||||
/// ファイル別usingコンテキスト
|
||||
using_contexts: Arc<RwLock<HashMap<String, UsingContext>>>,
|
||||
|
||||
/// 最適化情報キャッシュ
|
||||
optimization_cache: Arc<RwLock<OptimizationCache>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct UsingContext {
|
||||
pub file_id: String,
|
||||
pub builtin_namespaces: Vec<String>, // ["nyashstd"]
|
||||
pub bid_namespaces: Vec<String>, // ["canvas_api", "console_api"]
|
||||
pub module_namespaces: Vec<String>, // ["mylib", "utils"]
|
||||
}
|
||||
|
||||
impl UniversalNamespaceRegistry {
|
||||
pub fn new() -> Self {
|
||||
UniversalNamespaceRegistry {
|
||||
builtin_stdlib: Arc::new(BuiltinStdlib::new()),
|
||||
bid_definitions: HashMap::new(),
|
||||
nyash_modules: HashMap::new(),
|
||||
using_contexts: Arc::new(RwLock::new(HashMap::new())),
|
||||
optimization_cache: Arc::new(RwLock::new(OptimizationCache::new())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load_from_nyash_link(&mut self, nyash_link: &NyashLink)
|
||||
-> Result<(), RegistryError> {
|
||||
|
||||
// BID依存関係読み込み
|
||||
for (namespace_name, dependency) in &nyash_link.dependencies {
|
||||
match dependency {
|
||||
Dependency::Bid { bid_path, .. } => {
|
||||
let bid = BidDefinition::load_from_file(Path::new(bid_path))?;
|
||||
self.bid_definitions.insert(namespace_name.clone(), Arc::new(bid));
|
||||
},
|
||||
Dependency::Path { path } => {
|
||||
let module = ExternalModule::load_from_file(Path::new(path))?;
|
||||
self.nyash_modules.insert(namespace_name.clone(), Arc::new(module));
|
||||
},
|
||||
Dependency::Builtin { .. } => {
|
||||
// 組み込みライブラリは既に初期化済み
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// 統合using処理
|
||||
pub fn process_using(&mut self, namespace_name: &str, file_id: &str)
|
||||
-> Result<(), RuntimeError> {
|
||||
|
||||
let mut contexts = self.using_contexts.write().unwrap();
|
||||
let context = contexts.entry(file_id.to_string()).or_insert_with(|| {
|
||||
UsingContext {
|
||||
file_id: file_id.to_string(),
|
||||
builtin_namespaces: Vec::new(),
|
||||
bid_namespaces: Vec::new(),
|
||||
module_namespaces: Vec::new(),
|
||||
}
|
||||
});
|
||||
|
||||
// 組み込み標準ライブラリチェック
|
||||
if self.builtin_stdlib.has_namespace(namespace_name) {
|
||||
if !context.builtin_namespaces.contains(&namespace_name.to_string()) {
|
||||
context.builtin_namespaces.push(namespace_name.to_string());
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// BID定義チェック
|
||||
if let Some(bid) = self.bid_definitions.get(namespace_name) {
|
||||
if !context.bid_namespaces.contains(&namespace_name.to_string()) {
|
||||
context.bid_namespaces.push(namespace_name.to_string());
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Nyashモジュールチェック
|
||||
if let Some(_module) = self.nyash_modules.get(namespace_name) {
|
||||
if !context.module_namespaces.contains(&namespace_name.to_string()) {
|
||||
context.module_namespaces.push(namespace_name.to_string());
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
Err(RuntimeError::UndefinedNamespace(namespace_name.to_string()))
|
||||
}
|
||||
|
||||
/// 統合関数解決
|
||||
pub fn resolve_call(&self, file_id: &str, call_path: &[String])
|
||||
-> Result<ResolvedCall, RuntimeError> {
|
||||
|
||||
if call_path.len() != 2 {
|
||||
return Err(RuntimeError::InvalidCallPath(call_path.join(".")));
|
||||
}
|
||||
|
||||
let box_name = &call_path[0];
|
||||
let method_name = &call_path[1];
|
||||
|
||||
let contexts = self.using_contexts.read().unwrap();
|
||||
if let Some(context) = contexts.get(file_id) {
|
||||
|
||||
// 1. 組み込み標準ライブラリ解決
|
||||
for namespace in &context.builtin_namespaces {
|
||||
if let Some(method) = self.builtin_stdlib.resolve_method(namespace, box_name, method_name) {
|
||||
return Ok(ResolvedCall::Builtin {
|
||||
namespace: namespace.clone(),
|
||||
box_name: box_name.clone(),
|
||||
method_name: method_name.clone(),
|
||||
method_info: method,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 2. BID定義解決
|
||||
for namespace in &context.bid_namespaces {
|
||||
if let Some(bid) = self.bid_definitions.get(namespace) {
|
||||
if let Some(method) = bid.resolve_method(box_name, method_name) {
|
||||
return Ok(ResolvedCall::BidCall {
|
||||
namespace: namespace.clone(),
|
||||
interface_name: format!("{}.{}", namespace, box_name),
|
||||
method_name: method_name.clone(),
|
||||
method_info: method.clone(),
|
||||
bid_definition: bid.clone(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Nyashモジュール解決
|
||||
for namespace in &context.module_namespaces {
|
||||
if let Some(module) = self.nyash_modules.get(namespace) {
|
||||
if let Some(function) = module.resolve_function(box_name, method_name) {
|
||||
return Ok(ResolvedCall::ModuleCall {
|
||||
namespace: namespace.clone(),
|
||||
module_name: namespace.clone(),
|
||||
function_name: format!("{}.{}", box_name, method_name),
|
||||
function_info: function,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Err(RuntimeError::UndefinedMethod(format!("{}.{}", box_name, method_name)))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum ResolvedCall {
|
||||
Builtin {
|
||||
namespace: String,
|
||||
box_name: String,
|
||||
method_name: String,
|
||||
method_info: BuiltinMethodInfo,
|
||||
},
|
||||
BidCall {
|
||||
namespace: String,
|
||||
interface_name: String,
|
||||
method_name: String,
|
||||
method_info: BidMethod,
|
||||
bid_definition: Arc<BidDefinition>,
|
||||
},
|
||||
ModuleCall {
|
||||
namespace: String,
|
||||
module_name: String,
|
||||
function_name: String,
|
||||
function_info: ModuleFunctionInfo,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### 3. MIR生成統合
|
||||
|
||||
#### **統合MIR Builder**
|
||||
```rust
|
||||
// src/mir/builder.rs拡張
|
||||
impl MirBuilder {
|
||||
pub fn build_unified_method_call(&mut self, resolved_call: ResolvedCall, args: Vec<ValueId>)
|
||||
-> Result<Option<ValueId>, MirError> {
|
||||
|
||||
match resolved_call {
|
||||
ResolvedCall::Builtin { method_info, .. } => {
|
||||
let result = self.new_value_id();
|
||||
|
||||
self.emit(MirInstruction::BuiltinCall {
|
||||
qualified_name: method_info.qualified_name(),
|
||||
args,
|
||||
result,
|
||||
effect: method_info.effect(),
|
||||
});
|
||||
|
||||
Ok(Some(result))
|
||||
},
|
||||
|
||||
ResolvedCall::BidCall { interface_name, method_name, method_info, .. } => {
|
||||
let result = if method_info.returns == BidType::Void {
|
||||
None
|
||||
} else {
|
||||
Some(self.new_value_id())
|
||||
};
|
||||
|
||||
self.emit(MirInstruction::ExternCall {
|
||||
interface: interface_name,
|
||||
method: method_name,
|
||||
args,
|
||||
result,
|
||||
effect: self.bid_effect_to_mir_effect(&method_info.effect),
|
||||
bid_signature: BidSignature::from_method(&method_info),
|
||||
});
|
||||
|
||||
Ok(result)
|
||||
},
|
||||
|
||||
ResolvedCall::ModuleCall { module_name, function_name, function_info, .. } => {
|
||||
let result = self.new_value_id();
|
||||
|
||||
self.emit(MirInstruction::ModuleCall {
|
||||
module: module_name,
|
||||
function: function_name,
|
||||
args,
|
||||
result,
|
||||
effect: Effect::Io, // Nyashモジュールはデフォルトでio
|
||||
});
|
||||
|
||||
Ok(Some(result))
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn bid_effect_to_mir_effect(&self, bid_effect: &BidEffect) -> Effect {
|
||||
match bid_effect {
|
||||
BidEffect::Pure => Effect::Pure,
|
||||
BidEffect::Mut => Effect::Mut,
|
||||
BidEffect::Io => Effect::Io,
|
||||
BidEffect::Control => Effect::Control,
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. バックエンド統合
|
||||
|
||||
#### **WASM生成統合**
|
||||
```rust
|
||||
// src/backend/wasm/codegen.rs拡張
|
||||
impl WasmCodegen {
|
||||
pub fn generate_unified_call(&mut self, instruction: &MirInstruction)
|
||||
-> Result<(), WasmError> {
|
||||
|
||||
match instruction {
|
||||
MirInstruction::ExternCall { interface, method, args, bid_signature, .. } => {
|
||||
// BIDから自動生成されたWASM import名
|
||||
let wasm_import_name = self.bid_to_wasm_import_name(interface, method);
|
||||
|
||||
// 引数の型変換・マーシャリング
|
||||
let marshalled_args = self.marshal_args_for_wasm(args, &bid_signature.params)?;
|
||||
|
||||
// WASM関数呼び出し生成
|
||||
self.emit_call(&wasm_import_name, &marshalled_args)?;
|
||||
|
||||
// 戻り値のアンマーシャリング
|
||||
if bid_signature.returns != BidType::Void {
|
||||
self.unmarshal_return_value(&bid_signature.returns)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
},
|
||||
|
||||
// 他の命令は既存実装
|
||||
_ => self.generate_instruction_legacy(instruction),
|
||||
}
|
||||
}
|
||||
|
||||
fn bid_to_wasm_import_name(&self, interface: &str, method: &str) -> String {
|
||||
// "canvas_api.canvas" + "fillRect" → "canvas_api_canvas_fillRect"
|
||||
format!("{}_{}", interface.replace(".", "_"), method)
|
||||
}
|
||||
|
||||
fn marshal_args_for_wasm(&mut self, args: &[ValueId], params: &[BidParam])
|
||||
-> Result<Vec<WasmValue>, WasmError> {
|
||||
|
||||
let mut marshalled = Vec::new();
|
||||
|
||||
for (i, param) in params.iter().enumerate() {
|
||||
let arg_value = self.get_value(args[i])?;
|
||||
|
||||
match ¶m.param_type {
|
||||
BidType::String => {
|
||||
// 文字列を (ptr, len) にマーシャル
|
||||
let (ptr, len) = self.string_to_wasm_memory(&arg_value)?;
|
||||
marshalled.push(WasmValue::I32(ptr));
|
||||
marshalled.push(WasmValue::I32(len));
|
||||
},
|
||||
BidType::I32 => {
|
||||
marshalled.push(WasmValue::I32(arg_value.to_i32()?));
|
||||
},
|
||||
BidType::F64 => {
|
||||
marshalled.push(WasmValue::F64(arg_value.to_f64()?));
|
||||
},
|
||||
// その他の型...
|
||||
}
|
||||
}
|
||||
|
||||
Ok(marshalled)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### **VM実行統合**
|
||||
```rust
|
||||
// src/backend/vm.rs拡張
|
||||
impl VmBackend {
|
||||
pub fn execute_unified_instruction(&mut self, instruction: &MirInstruction)
|
||||
-> Result<(), VmError> {
|
||||
|
||||
match instruction {
|
||||
MirInstruction::ExternCall { interface, method, args, bid_signature, .. } => {
|
||||
// VM環境ではスタブまたはネイティブ呼び出し
|
||||
let evaluated_args = self.evaluate_args(args)?;
|
||||
|
||||
if let Some(native_impl) = self.find_native_implementation(interface, method) {
|
||||
// ネイティブ実装がある場合(例:ファイルI/O)
|
||||
let result = native_impl.call(evaluated_args, bid_signature)?;
|
||||
if let Some(result_id) = &instruction.result {
|
||||
self.set_value(*result_id, result);
|
||||
}
|
||||
} else {
|
||||
// スタブ実装(ログ出力等)
|
||||
self.execute_stub_call(interface, method, evaluated_args, bid_signature)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
},
|
||||
|
||||
// 他の命令は既存実装
|
||||
_ => self.execute_instruction_legacy(instruction),
|
||||
}
|
||||
}
|
||||
|
||||
fn find_native_implementation(&self, interface: &str, method: &str)
|
||||
-> Option<&dyn NativeImplementation> {
|
||||
|
||||
// VM環境で利用可能なネイティブ実装を検索
|
||||
match (interface, method) {
|
||||
("env.console", "log") => Some(&self.console_impl),
|
||||
("env.filesystem", "read") => Some(&self.filesystem_impl),
|
||||
("env.filesystem", "write") => Some(&self.filesystem_impl),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🧪 統合テスト戦略
|
||||
|
||||
### Phase別テスト実装
|
||||
|
||||
#### **Phase 0: 基本統合テスト**
|
||||
```nyash
|
||||
# test_basic_integration.nyash
|
||||
using nyashstd
|
||||
|
||||
# 組み込み標準ライブラリのみ
|
||||
assert(string.upper("test") == "TEST")
|
||||
assert(math.sin(0) == 0)
|
||||
```
|
||||
|
||||
#### **Phase 1: BID統合テスト**
|
||||
```nyash
|
||||
# test_bid_integration.nyash
|
||||
using nyashstd
|
||||
using console_api
|
||||
|
||||
# 組み込み + FFI-ABI
|
||||
string.upper("hello") # 組み込み
|
||||
console.log("Testing") # FFI-ABI
|
||||
```
|
||||
|
||||
#### **Phase 2: 完全統合テスト**
|
||||
```nyash
|
||||
# test_full_integration.nyash
|
||||
using nyashstd
|
||||
using console_api
|
||||
using mylib
|
||||
|
||||
# 3種類すべて
|
||||
string.upper("test") # 組み込み
|
||||
console.log("Integration") # FFI-ABI
|
||||
mylib.process("data") # Nyashモジュール
|
||||
```
|
||||
|
||||
### エラーハンドリングテスト
|
||||
```nyash
|
||||
# test_error_handling.nyash
|
||||
try {
|
||||
using nonexistent_api
|
||||
} catch error {
|
||||
assert(error.type == "UndefinedNamespace")
|
||||
}
|
||||
|
||||
try {
|
||||
console.nonexistent_method("test")
|
||||
} catch error {
|
||||
assert(error.type == "UndefinedMethod")
|
||||
assert(error.message.contains("Available methods:"))
|
||||
}
|
||||
```
|
||||
|
||||
## 📊 実装マイルストーン
|
||||
|
||||
### ✅ Phase 0完了条件
|
||||
- [ ] UniversalNamespaceRegistry基盤実装
|
||||
- [ ] 組み込み標準ライブラリ統合
|
||||
- [ ] 基本using文処理
|
||||
- [ ] MIR BuiltinCall生成
|
||||
|
||||
### ✅ Phase 1完了条件
|
||||
- [ ] BID定義読み込み・検証
|
||||
- [ ] BID→MIR ExternCall統合
|
||||
- [ ] WASM RuntimeImports自動生成
|
||||
- [ ] VM スタブ実行
|
||||
|
||||
### ✅ Phase 2完了条件
|
||||
- [ ] Nyashモジュール統合
|
||||
- [ ] 統合エラーハンドリング
|
||||
- [ ] 最適化キャッシュ
|
||||
- [ ] 全バックエンド対応
|
||||
|
||||
---
|
||||
|
||||
**🎯 この詳細実装により、BIDとusingシステムの完全統合が実現でき、「なんでもAPI計画」の技術基盤が完成するにゃ!🚀🐱**
|
||||
456
docs/予定/nyash.link/builtin-stdlib-architecture.md
Normal file
456
docs/予定/nyash.link/builtin-stdlib-architecture.md
Normal file
@ -0,0 +1,456 @@
|
||||
# 組み込みnyashstd名前空間アーキテクチャ設計
|
||||
|
||||
## 🏗️ 技術的実装アーキテクチャ
|
||||
|
||||
### 📊 現在のインタープリター構造分析
|
||||
|
||||
#### **NyashInterpreter構造**
|
||||
```rust
|
||||
pub struct NyashInterpreter {
|
||||
pub(super) shared: SharedState, // 共有状態
|
||||
pub(super) local_vars: HashMap<String, SharedNyashBox>,
|
||||
pub(super) outbox_vars: HashMap<String, SharedNyashBox>,
|
||||
// その他の制御フロー状態...
|
||||
}
|
||||
```
|
||||
|
||||
#### **設計判断:SharedStateに組み込み**
|
||||
- **理由**: 標準ライブラリは不変・全インタープリターで共有可能
|
||||
- **利点**: メモリ効率、パフォーマンス向上
|
||||
- **実装**: SharedStateに`builtin_stdlib`フィールド追加
|
||||
|
||||
## 🌟 最適化されたアーキテクチャ設計
|
||||
|
||||
### 1. SharedState拡張
|
||||
|
||||
#### **src/interpreter/core.rs**
|
||||
```rust
|
||||
#[derive(Clone)]
|
||||
pub struct SharedState {
|
||||
// 既存フィールド...
|
||||
pub global_vars: Arc<RwLock<HashMap<String, SharedNyashBox>>>,
|
||||
pub functions: Arc<RwLock<HashMap<String, Function>>>,
|
||||
pub box_definitions: Arc<RwLock<HashMap<String, Box<UserDefinedBoxDefinition>>>>,
|
||||
pub loop_counter: Arc<AtomicU64>,
|
||||
pub included_files: Arc<RwLock<HashSet<String>>>,
|
||||
|
||||
// 🌟 新規追加: 組み込み標準ライブラリ
|
||||
pub builtin_stdlib: Arc<BuiltinStdlib>,
|
||||
pub using_imports: Arc<RwLock<HashMap<String, UsingContext>>>, // ファイル別インポート管理
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct UsingContext {
|
||||
pub imported_namespaces: Vec<String>, // ["nyashstd"]
|
||||
pub file_id: String, // インポート元ファイル識別
|
||||
}
|
||||
```
|
||||
|
||||
### 2. BuiltinStdlib効率化設計
|
||||
|
||||
#### **新ファイル: src/stdlib/builtin.rs**
|
||||
```rust
|
||||
//! 🚀 高性能組み込み標準ライブラリ
|
||||
//!
|
||||
//! 設計方針:
|
||||
//! - Zero-allocation関数実行
|
||||
//! - 高速名前解決
|
||||
//! - 既存Box実装の最大活用
|
||||
|
||||
use crate::boxes::*;
|
||||
use std::collections::HashMap;
|
||||
|
||||
/// 組み込み標準ライブラリのメイン構造体
|
||||
#[derive(Debug)]
|
||||
pub struct BuiltinStdlib {
|
||||
/// 高速アクセス用:フラットな関数マップ
|
||||
/// "string.upper" -> BuiltinFunction
|
||||
pub flat_functions: HashMap<String, BuiltinFunction>,
|
||||
|
||||
/// IDE補完用:階層構造
|
||||
/// "nyashstd" -> { "string" -> ["upper", "lower", ...] }
|
||||
pub hierarchical_map: HashMap<String, HashMap<String, Vec<String>>>,
|
||||
}
|
||||
|
||||
/// 組み込み関数の実装
|
||||
pub struct BuiltinFunction {
|
||||
pub namespace: &'static str, // "nyashstd"
|
||||
pub box_name: &'static str, // "string"
|
||||
pub method_name: &'static str, // "upper"
|
||||
pub implementation: BuiltinMethodImpl,
|
||||
pub arg_count: Option<usize>, // None = 可変長
|
||||
pub description: &'static str, // エラーメッセージ・ヘルプ用
|
||||
}
|
||||
|
||||
/// 高性能関数実装
|
||||
pub type BuiltinMethodImpl = fn(&[Box<dyn NyashBox>]) -> Result<Box<dyn NyashBox>, RuntimeError>;
|
||||
|
||||
impl BuiltinStdlib {
|
||||
/// 🚀 標準ライブラリ初期化(起動時1回のみ)
|
||||
pub fn new() -> Self {
|
||||
let mut stdlib = BuiltinStdlib {
|
||||
flat_functions: HashMap::new(),
|
||||
hierarchical_map: HashMap::new(),
|
||||
};
|
||||
|
||||
// 標準関数登録
|
||||
stdlib.register_all_functions();
|
||||
|
||||
stdlib
|
||||
}
|
||||
|
||||
/// ⚡ 高速関数解決
|
||||
pub fn get_function(&self, qualified_name: &str) -> Option<&BuiltinFunction> {
|
||||
// "string.upper" で直接アクセス
|
||||
self.flat_functions.get(qualified_name)
|
||||
}
|
||||
|
||||
/// 🔍 IDE補完用:利用可能関数一覧取得
|
||||
pub fn get_available_methods(&self, namespace: &str, box_name: &str) -> Option<&Vec<String>> {
|
||||
self.hierarchical_map.get(namespace)?.get(box_name)
|
||||
}
|
||||
|
||||
/// 📋 全名前空間取得(IDE補完用)
|
||||
pub fn get_all_namespaces(&self) -> Vec<&String> {
|
||||
self.hierarchical_map.keys().collect()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 標準関数実装(高性能版)
|
||||
|
||||
#### **文字列関数実装**
|
||||
```rust
|
||||
impl BuiltinStdlib {
|
||||
fn register_all_functions(&mut self) {
|
||||
// === nyashstd.string.* ===
|
||||
self.register_function("string.upper", BuiltinFunction {
|
||||
namespace: "nyashstd",
|
||||
box_name: "string",
|
||||
method_name: "upper",
|
||||
implementation: |args| {
|
||||
if args.len() != 1 {
|
||||
return Err(RuntimeError::InvalidArguments(
|
||||
"string.upper(str) takes exactly 1 argument".to_string()
|
||||
));
|
||||
}
|
||||
|
||||
// 🚀 既存StringBox実装活用
|
||||
let input_str = args[0].to_string_box().value;
|
||||
let result = StringBox::new(&input_str.to_uppercase());
|
||||
Ok(Box::new(result))
|
||||
},
|
||||
arg_count: Some(1),
|
||||
description: "Convert string to uppercase",
|
||||
});
|
||||
|
||||
self.register_function("string.lower", BuiltinFunction {
|
||||
namespace: "nyashstd",
|
||||
box_name: "string",
|
||||
method_name: "lower",
|
||||
implementation: |args| {
|
||||
if args.len() != 1 {
|
||||
return Err(RuntimeError::InvalidArguments(
|
||||
"string.lower(str) takes exactly 1 argument".to_string()
|
||||
));
|
||||
}
|
||||
|
||||
let input_str = args[0].to_string_box().value;
|
||||
let result = StringBox::new(&input_str.to_lowercase());
|
||||
Ok(Box::new(result))
|
||||
},
|
||||
arg_count: Some(1),
|
||||
description: "Convert string to lowercase",
|
||||
});
|
||||
|
||||
self.register_function("string.split", BuiltinFunction {
|
||||
namespace: "nyashstd",
|
||||
box_name: "string",
|
||||
method_name: "split",
|
||||
implementation: |args| {
|
||||
if args.len() != 2 {
|
||||
return Err(RuntimeError::InvalidArguments(
|
||||
"string.split(str, separator) takes exactly 2 arguments".to_string()
|
||||
));
|
||||
}
|
||||
|
||||
// 🚀 既存StringBox.split()メソッド活用
|
||||
let string_box = StringBox::new(&args[0].to_string_box().value);
|
||||
let separator = &args[1].to_string_box().value;
|
||||
string_box.split(separator)
|
||||
},
|
||||
arg_count: Some(2),
|
||||
description: "Split string by separator into array",
|
||||
});
|
||||
|
||||
// === nyashstd.math.* ===
|
||||
self.register_function("math.sin", BuiltinFunction {
|
||||
namespace: "nyashstd",
|
||||
box_name: "math",
|
||||
method_name: "sin",
|
||||
implementation: |args| {
|
||||
if args.len() != 1 {
|
||||
return Err(RuntimeError::InvalidArguments(
|
||||
"math.sin(x) takes exactly 1 argument".to_string()
|
||||
));
|
||||
}
|
||||
|
||||
// 🚀 既存MathBox実装活用
|
||||
let math_box = MathBox::new();
|
||||
let x = args[0].to_integer_box().value as f64;
|
||||
let result = math_box.sin(x)?;
|
||||
Ok(result)
|
||||
},
|
||||
arg_count: Some(1),
|
||||
description: "Calculate sine of x (in radians)",
|
||||
});
|
||||
|
||||
// 階層マップも同時構築
|
||||
self.build_hierarchical_map();
|
||||
}
|
||||
|
||||
fn register_function(&mut self, qualified_name: &str, function: BuiltinFunction) {
|
||||
self.flat_functions.insert(qualified_name.to_string(), function);
|
||||
}
|
||||
|
||||
fn build_hierarchical_map(&mut self) {
|
||||
for (qualified_name, function) in &self.flat_functions {
|
||||
let namespace_map = self.hierarchical_map
|
||||
.entry(function.namespace.to_string())
|
||||
.or_insert_with(HashMap::new);
|
||||
|
||||
let method_list = namespace_map
|
||||
.entry(function.box_name.to_string())
|
||||
.or_insert_with(Vec::new);
|
||||
|
||||
method_list.push(function.method_name.to_string());
|
||||
}
|
||||
|
||||
// ソートして一貫性確保
|
||||
for namespace_map in self.hierarchical_map.values_mut() {
|
||||
for method_list in namespace_map.values_mut() {
|
||||
method_list.sort();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. インタープリター統合
|
||||
|
||||
#### **NyashInterpreter拡張**
|
||||
```rust
|
||||
impl NyashInterpreter {
|
||||
/// using文実行
|
||||
pub fn execute_using(&mut self, namespace_name: &str) -> Result<(), RuntimeError> {
|
||||
// 組み込み名前空間存在チェック
|
||||
if !self.shared.builtin_stdlib.hierarchical_map.contains_key(namespace_name) {
|
||||
return Err(RuntimeError::UndefinedNamespace(namespace_name.to_string()));
|
||||
}
|
||||
|
||||
// 現在ファイルのusingコンテキスト更新
|
||||
let file_id = self.get_current_file_id();
|
||||
let mut using_imports = self.shared.using_imports.write().unwrap();
|
||||
|
||||
let context = using_imports.entry(file_id.clone()).or_insert(UsingContext {
|
||||
imported_namespaces: Vec::new(),
|
||||
file_id: file_id.clone(),
|
||||
});
|
||||
|
||||
if !context.imported_namespaces.contains(&namespace_name.to_string()) {
|
||||
context.imported_namespaces.push(namespace_name.to_string());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// ⚡ 高速名前解決:string.upper() → nyashstd.string.upper()
|
||||
pub fn resolve_qualified_call(&self, path: &[String]) -> Option<String> {
|
||||
if path.len() != 2 {
|
||||
return None; // Phase 0では2段階のみ対応
|
||||
}
|
||||
|
||||
let box_name = &path[0];
|
||||
let method_name = &path[1];
|
||||
let file_id = self.get_current_file_id();
|
||||
|
||||
// 現在ファイルのusingインポート確認
|
||||
if let Ok(using_imports) = self.shared.using_imports.read() {
|
||||
if let Some(context) = using_imports.get(&file_id) {
|
||||
for namespace in &context.imported_namespaces {
|
||||
let qualified_name = format!("{}.{}", box_name, method_name);
|
||||
|
||||
// 実際に関数が存在するかチェック
|
||||
if self.shared.builtin_stdlib.get_function(&qualified_name).is_some() {
|
||||
return Some(qualified_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
/// 🚀 組み込み関数実行
|
||||
pub fn call_builtin_function(&self, qualified_name: &str, args: Vec<Box<dyn NyashBox>>)
|
||||
-> Result<Box<dyn NyashBox>, RuntimeError> {
|
||||
|
||||
if let Some(function) = self.shared.builtin_stdlib.get_function(qualified_name) {
|
||||
// 引数数チェック
|
||||
if let Some(expected_count) = function.arg_count {
|
||||
if args.len() != expected_count {
|
||||
return Err(RuntimeError::InvalidArguments(
|
||||
format!("{}.{}() takes exactly {} arguments, got {}",
|
||||
function.box_name, function.method_name,
|
||||
expected_count, args.len())
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// 関数実行
|
||||
(function.implementation)(&args)
|
||||
} else {
|
||||
Err(RuntimeError::UndefinedMethod(qualified_name.to_string()))
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5. 式実行統合
|
||||
|
||||
#### **src/interpreter/expressions.rs修正**
|
||||
```rust
|
||||
impl NyashInterpreter {
|
||||
pub fn execute_expression(&mut self, node: &ASTNode) -> Result<Box<dyn NyashBox>, RuntimeError> {
|
||||
match node {
|
||||
// 既存のケース...
|
||||
|
||||
// メソッド呼び出し処理修正
|
||||
ASTNode::MethodCall { object, method, args, .. } => {
|
||||
// オブジェクトが単純な識別子かチェック
|
||||
if let ASTNode::Variable { name: box_name, .. } = object.as_ref() {
|
||||
// using経由での短縮呼び出しチェック
|
||||
let path = vec![box_name.clone(), method.clone()];
|
||||
if let Some(qualified_name) = self.resolve_qualified_call(&path) {
|
||||
// 引数評価
|
||||
let evaluated_args = self.evaluate_arguments(args)?;
|
||||
// 組み込み関数実行
|
||||
return self.call_builtin_function(&qualified_name, evaluated_args);
|
||||
}
|
||||
}
|
||||
|
||||
// 既存のメソッド呼び出し処理
|
||||
// ...
|
||||
}
|
||||
|
||||
// using文実行
|
||||
ASTNode::UsingStatement { namespace_name, .. } => {
|
||||
self.execute_using(namespace_name)?;
|
||||
Ok(Box::new(VoidBox::new()))
|
||||
}
|
||||
|
||||
// 他の既存ケース...
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📊 パフォーマンス特性
|
||||
|
||||
### ⚡ 最適化ポイント
|
||||
|
||||
#### **1. Zero-Allocation関数解決**
|
||||
```rust
|
||||
// ❌ 遅い:毎回文字列生成
|
||||
let qualified = format!("{}.{}", box_name, method_name);
|
||||
|
||||
// ✅ 高速:事前計算済みマップ
|
||||
if let Some(func) = stdlib.flat_functions.get(&qualified_name) { ... }
|
||||
```
|
||||
|
||||
#### **2. 高速名前解決**
|
||||
```rust
|
||||
// O(1)アクセス:HashMap直接ルックアップ
|
||||
// "string.upper" -> BuiltinFunction
|
||||
```
|
||||
|
||||
#### **3. 既存Box実装活用**
|
||||
```rust
|
||||
// 既存の最適化済みStringBox.split()を直接使用
|
||||
string_box.split(separator) // 新規実装不要
|
||||
```
|
||||
|
||||
## 🧪 テストカバレッジ
|
||||
|
||||
### Phase 0必須テスト
|
||||
|
||||
#### **基本機能テスト**
|
||||
```nyash
|
||||
# test_builtin_stdlib_basic.nyash
|
||||
using nyashstd
|
||||
|
||||
# 文字列操作
|
||||
assert(string.upper("hello") == "HELLO")
|
||||
assert(string.lower("WORLD") == "world")
|
||||
assert(string.split("a,b,c", ",").length() == 3)
|
||||
|
||||
# 数学関数
|
||||
assert(math.sin(0) == 0)
|
||||
assert(math.cos(0) == 1)
|
||||
|
||||
# 配列操作
|
||||
local arr = [1, 2, 3]
|
||||
assert(array.length(arr) == 3)
|
||||
assert(array.get(arr, 1) == 2)
|
||||
```
|
||||
|
||||
#### **エラーハンドリング**
|
||||
```nyash
|
||||
# test_builtin_stdlib_errors.nyash
|
||||
using nyashstd
|
||||
|
||||
# 引数数エラー
|
||||
try {
|
||||
string.upper("hello", "extra") # 2引数でエラー
|
||||
assert(false, "Should have thrown error")
|
||||
} catch e {
|
||||
assert(e.contains("takes exactly 1 argument"))
|
||||
}
|
||||
|
||||
# 未定義名前空間
|
||||
try {
|
||||
using nonexistent
|
||||
assert(false, "Should have thrown error")
|
||||
} catch e {
|
||||
assert(e.contains("UndefinedNamespace"))
|
||||
}
|
||||
```
|
||||
|
||||
#### **IDE補完サポート**
|
||||
```rust
|
||||
// テスト:補完候補取得
|
||||
let methods = stdlib.get_available_methods("nyashstd", "string");
|
||||
assert!(methods.unwrap().contains(&"upper".to_string()));
|
||||
assert!(methods.unwrap().contains(&"lower".to_string()));
|
||||
```
|
||||
|
||||
## 🎯 実装順序
|
||||
|
||||
### 🚨 Critical(即時実装)
|
||||
1. **BuiltinStdlib基盤** - src/stdlib/builtin.rs作成
|
||||
2. **SharedState統合** - builtin_stdlibフィールド追加
|
||||
3. **using文パーサー** - ASTNode::UsingStatement
|
||||
|
||||
### ⚡ High(今週中)
|
||||
4. **string関数4種** - upper, lower, split, join
|
||||
5. **基本テスト** - using nyashstd動作確認
|
||||
6. **エラーハンドリング** - 適切なエラーメッセージ
|
||||
|
||||
### 📝 Medium(来週)
|
||||
7. **math関数5種** - sin, cos, sqrt, floor, random
|
||||
8. **array関数4種** - length, get, push, slice
|
||||
9. **io関数3種** - print, println, debug
|
||||
|
||||
---
|
||||
|
||||
**⚡ この高性能アーキテクチャで、複雑なファイル依存関係なしに即座に実用的なnamespace/usingが実現できるにゃ!🚀**
|
||||
394
docs/予定/nyash.link/examples.md
Normal file
394
docs/予定/nyash.link/examples.md
Normal file
@ -0,0 +1,394 @@
|
||||
# nyash.linkシステム使用例
|
||||
|
||||
## 🎯 基本的な使用例
|
||||
|
||||
### 📁 プロジェクト構造例
|
||||
```
|
||||
my-awesome-app/
|
||||
├── nyash.link # 依存関係定義
|
||||
├── src/
|
||||
│ ├── main.nyash # メインファイル
|
||||
│ ├── models/
|
||||
│ │ └── user.nyash # ユーザーモデル
|
||||
│ └── utils/
|
||||
│ └── helpers.nyash # ヘルパー関数
|
||||
├── libs/
|
||||
│ └── custom_lib.nyash # カスタムライブラリ
|
||||
└── stdlib/
|
||||
└── nyashstd.nyash # 標準ライブラリ
|
||||
```
|
||||
|
||||
### 📋 nyash.linkファイル例
|
||||
```toml
|
||||
[project]
|
||||
name = "my-awesome-app"
|
||||
version = "1.0.0"
|
||||
description = "Everything is Box philosophy in action!"
|
||||
|
||||
[dependencies]
|
||||
# 標準ライブラリ
|
||||
nyashstd = { path = "./stdlib/nyashstd.nyash" }
|
||||
|
||||
# プロジェクト内モジュール
|
||||
user_model = { path = "./src/models/user.nyash" }
|
||||
helpers = { path = "./src/utils/helpers.nyash" }
|
||||
|
||||
# カスタムライブラリ
|
||||
custom_lib = { path = "./libs/custom_lib.nyash" }
|
||||
|
||||
[search_paths]
|
||||
stdlib = "./stdlib/"
|
||||
src = "./src/"
|
||||
libs = "./libs/"
|
||||
|
||||
[build]
|
||||
entry_point = "./src/main.nyash"
|
||||
```
|
||||
|
||||
## 🌟 実用的なコード例
|
||||
|
||||
### 1. 基本的なusing使用
|
||||
```nyash
|
||||
# ===== src/main.nyash =====
|
||||
using nyashstd
|
||||
using helpers
|
||||
|
||||
static box Main {
|
||||
init { console }
|
||||
|
||||
main() {
|
||||
me.console = new ConsoleBox()
|
||||
|
||||
# 標準ライブラリ使用
|
||||
local text = "hello world"
|
||||
local upper_text = string.upper(text) # nyashstd.string.upper
|
||||
me.console.log("Upper: " + upper_text)
|
||||
|
||||
# ヘルパー関数使用
|
||||
local processed = helpers.process_data("sample data")
|
||||
me.console.log("Processed: " + processed)
|
||||
|
||||
# 数学関数
|
||||
local result = math.sin(3.14159)
|
||||
me.console.log("Sin: " + result.toString())
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 標準ライブラリ定義例
|
||||
```nyash
|
||||
# ===== stdlib/nyashstd.nyash =====
|
||||
namespace nyashstd {
|
||||
static box string {
|
||||
static upper(str) {
|
||||
local string_box = new StringBox(str)
|
||||
return string_box.upper()
|
||||
}
|
||||
|
||||
static lower(str) {
|
||||
local string_box = new StringBox(str)
|
||||
return string_box.lower()
|
||||
}
|
||||
|
||||
static split(str, separator) {
|
||||
local string_box = new StringBox(str)
|
||||
return string_box.split(separator)
|
||||
}
|
||||
|
||||
static join(array, separator) {
|
||||
local sep_box = new StringBox(separator)
|
||||
return sep_box.join(array)
|
||||
}
|
||||
}
|
||||
|
||||
static box math {
|
||||
static sin(x) {
|
||||
local math_box = new MathBox()
|
||||
return math_box.sin(x)
|
||||
}
|
||||
|
||||
static cos(x) {
|
||||
local math_box = new MathBox()
|
||||
return math_box.cos(x)
|
||||
}
|
||||
|
||||
static random() {
|
||||
local random_box = new RandomBox()
|
||||
return random_box.nextFloat()
|
||||
}
|
||||
|
||||
static floor(x) {
|
||||
local math_box = new MathBox()
|
||||
return math_box.floor(x)
|
||||
}
|
||||
}
|
||||
|
||||
static box io {
|
||||
static read_file(path) {
|
||||
local file_box = new FileBox()
|
||||
return file_box.read(path)
|
||||
}
|
||||
|
||||
static write_file(path, content) {
|
||||
local file_box = new FileBox()
|
||||
return file_box.write(path, content)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. ヘルパーモジュール例
|
||||
```nyash
|
||||
# ===== src/utils/helpers.nyash =====
|
||||
using nyashstd
|
||||
|
||||
static function process_data(data) {
|
||||
# データ処理のヘルパー
|
||||
local trimmed = string.trim(data)
|
||||
local upper = string.upper(trimmed)
|
||||
return "PROCESSED: " + upper
|
||||
}
|
||||
|
||||
static function calculate_score(points, multiplier) {
|
||||
local result = points * multiplier
|
||||
return math.floor(result)
|
||||
}
|
||||
|
||||
static function format_user_name(first, last) {
|
||||
return string.upper(first) + " " + string.upper(last)
|
||||
}
|
||||
```
|
||||
|
||||
### 4. モデル定義例
|
||||
```nyash
|
||||
# ===== src/models/user.nyash =====
|
||||
using nyashstd
|
||||
using helpers
|
||||
|
||||
box User {
|
||||
init { name, email, score }
|
||||
|
||||
birth(user_name, user_email) {
|
||||
me.name = user_name
|
||||
me.email = user_email
|
||||
me.score = 0
|
||||
}
|
||||
|
||||
add_points(points) {
|
||||
me.score = me.score + points
|
||||
return me.score
|
||||
}
|
||||
|
||||
get_formatted_name() {
|
||||
local parts = string.split(me.name, " ")
|
||||
if parts.length() >= 2 {
|
||||
return helpers.format_user_name(parts.get(0), parts.get(1))
|
||||
} else {
|
||||
return string.upper(me.name)
|
||||
}
|
||||
}
|
||||
|
||||
save_to_file() {
|
||||
local data = "User: " + me.name + ", Email: " + me.email + ", Score: " + me.score.toString()
|
||||
local filename = "user_" + string.lower(me.name) + ".txt"
|
||||
io.write_file(filename, data)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🎮 実用アプリケーション例
|
||||
|
||||
### 1. シンプルなWebサーバー
|
||||
```nyash
|
||||
# ===== web_server.nyash =====
|
||||
using nyashstd
|
||||
using custom_lib
|
||||
|
||||
static box WebServer {
|
||||
init { server, port }
|
||||
|
||||
birth(server_port) {
|
||||
me.port = server_port
|
||||
me.server = new HttpServerBox()
|
||||
}
|
||||
|
||||
start() {
|
||||
me.server.bind("localhost", me.port)
|
||||
|
||||
me.server.on("request", me.handle_request)
|
||||
|
||||
local console = new ConsoleBox()
|
||||
console.log("Server started on port " + me.port.toString())
|
||||
|
||||
me.server.listen()
|
||||
}
|
||||
|
||||
handle_request(request, response) {
|
||||
local url = request.getUrl()
|
||||
|
||||
if url == "/" {
|
||||
local html = io.read_file("./public/index.html")
|
||||
response.setStatus(200)
|
||||
response.setHeader("Content-Type", "text/html")
|
||||
response.send(html)
|
||||
} else {
|
||||
response.setStatus(404)
|
||||
response.send("Not Found")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# メイン実行
|
||||
local server = new WebServer(3000)
|
||||
server.start()
|
||||
```
|
||||
|
||||
### 2. データ処理パイプライン
|
||||
```nyash
|
||||
# ===== data_processor.nyash =====
|
||||
using nyashstd
|
||||
using helpers
|
||||
|
||||
static box DataProcessor {
|
||||
init { input_file, output_file }
|
||||
|
||||
birth(input_path, output_path) {
|
||||
me.input_file = input_path
|
||||
me.output_file = output_path
|
||||
}
|
||||
|
||||
process() {
|
||||
# データ読み込み
|
||||
local raw_data = io.read_file(me.input_file)
|
||||
local lines = string.split(raw_data, "\n")
|
||||
|
||||
# 処理済みデータ配列
|
||||
local processed_lines = new ArrayBox()
|
||||
|
||||
# 各行を処理
|
||||
local i = 0
|
||||
loop(i < lines.length()) {
|
||||
local line = lines.get(i)
|
||||
local processed = helpers.process_data(line)
|
||||
processed_lines.push(processed)
|
||||
i = i + 1
|
||||
}
|
||||
|
||||
# 結果をファイルに保存
|
||||
local result = string.join(processed_lines, "\n")
|
||||
io.write_file(me.output_file, result)
|
||||
|
||||
return processed_lines.length()
|
||||
}
|
||||
}
|
||||
|
||||
# メイン処理
|
||||
local processor = new DataProcessor("input.txt", "output.txt")
|
||||
local count = processor.process()
|
||||
|
||||
local console = new ConsoleBox()
|
||||
console.log("Processed " + count.toString() + " lines")
|
||||
```
|
||||
|
||||
## 🔧 高度な使用パターン
|
||||
|
||||
### 1. 条件付きモジュール読み込み(将来拡張)
|
||||
```nyash
|
||||
# 開発環境では詳細ログ、本番環境ではシンプルログ
|
||||
using nyashstd
|
||||
|
||||
static function get_logger() {
|
||||
local env = os.get_env("NYASH_ENV")
|
||||
|
||||
if env == "development" {
|
||||
using dev_logger
|
||||
return new dev_logger.DetailLogger()
|
||||
} else {
|
||||
using prod_logger
|
||||
return new prod_logger.SimpleLogger()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. エイリアス使用例(将来拡張)
|
||||
```nyash
|
||||
# 長い名前空間のエイリアス
|
||||
using very.long.namespace.name as short
|
||||
|
||||
local result = short.helper_function("data")
|
||||
|
||||
# 複数の類似ライブラリ
|
||||
using json_v1 as json1
|
||||
using json_v2 as json2
|
||||
|
||||
local data1 = json1.parse(input)
|
||||
local data2 = json2.parse(input)
|
||||
```
|
||||
|
||||
### 3. 部分インポート(将来拡張)
|
||||
```nyash
|
||||
# 名前空間全体ではなく特定機能のみ
|
||||
using nyashstd.string
|
||||
using nyashstd.math
|
||||
|
||||
# これで直接呼び出せる
|
||||
local result = upper("hello") # string.upper不要
|
||||
local sin_val = sin(3.14) # math.sin不要
|
||||
```
|
||||
|
||||
## 📊 移行例:既存includeからusingへ
|
||||
|
||||
### Before(現在のinclude使用)
|
||||
```nyash
|
||||
# ===== 既存のtext_adventure例 =====
|
||||
include "text_adventure/items.nyash"
|
||||
include "text_adventure/rooms.nyash"
|
||||
|
||||
# アイテム作成
|
||||
local sword = new Weapon("Sword", 10)
|
||||
```
|
||||
|
||||
### After(新しいusing使用)
|
||||
```nyash
|
||||
# ===== nyash.link =====
|
||||
[dependencies]
|
||||
game_items = { path = "./text_adventure/items.nyash" }
|
||||
game_rooms = { path = "./text_adventure/rooms.nyash" }
|
||||
|
||||
# ===== main.nyash =====
|
||||
using game_items
|
||||
using game_rooms
|
||||
|
||||
# アイテム作成(名前空間経由)
|
||||
local sword = game_items.create_weapon("Sword", 10)
|
||||
```
|
||||
|
||||
## 🎉 期待される開発体験
|
||||
|
||||
### IDE補完の改善
|
||||
```nyash
|
||||
using nyashstd
|
||||
|
||||
# "st" と入力すると...
|
||||
st → string (補完候補)
|
||||
|
||||
# "string." と入力すると...
|
||||
string. → upper, lower, split, join, trim, ... (全メソッド表示)
|
||||
```
|
||||
|
||||
### エラーメッセージの改善
|
||||
```nyash
|
||||
using nyashstd
|
||||
|
||||
# 間違った呼び出し
|
||||
local result = string.uppper("hello") # typo
|
||||
|
||||
# エラー:
|
||||
# Error: Method 'uppper' not found in nyashstd.string
|
||||
# Did you mean: 'upper'?
|
||||
# Available methods: upper, lower, split, join, trim
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**🌟 これらの例でnyash.linkシステムの実用性と美しさが伝わるにゃ!🐱**
|
||||
406
docs/予定/nyash.link/final-implementation-strategy.md
Normal file
406
docs/予定/nyash.link/final-implementation-strategy.md
Normal file
@ -0,0 +1,406 @@
|
||||
# 最終実装戦略:標準関数優先namespace/usingシステム
|
||||
|
||||
## 🎯 実装戦略まとめ
|
||||
|
||||
### 📋 設計完了項目
|
||||
- ✅ **基本戦略**: nyash.link前の段階的実装
|
||||
- ✅ **アーキテクチャ**: SharedState統合による高性能設計
|
||||
- ✅ **標準関数**: 組み込みnyashstd名前空間
|
||||
- ✅ **実装順序**: Critical → High → Medium
|
||||
|
||||
### 🚀 最終実装ロードマップ
|
||||
|
||||
## Phase 0: 組み込みnyashstd基盤(1-2週間)
|
||||
|
||||
### 🚨 Critical実装(即時)
|
||||
|
||||
#### **1. トークナイザー拡張**
|
||||
```rust
|
||||
// src/tokenizer.rs
|
||||
pub enum TokenType {
|
||||
// 既存...
|
||||
USING, // using キーワード追加
|
||||
}
|
||||
|
||||
// キーワード認識
|
||||
fn tokenize_keyword(word: &str) -> TokenType {
|
||||
match word {
|
||||
// 既存...
|
||||
"using" => TokenType::USING,
|
||||
_ => TokenType::IDENTIFIER(word.to_string()),
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### **2. AST最小拡張**
|
||||
```rust
|
||||
// src/ast.rs
|
||||
pub enum ASTNode {
|
||||
// 既存...
|
||||
UsingStatement {
|
||||
namespace_name: String, // Phase 0: "nyashstd"のみ
|
||||
span: Span,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
#### **3. BuiltinStdlib基盤**
|
||||
```rust
|
||||
// 新ファイル: src/stdlib/mod.rs
|
||||
pub mod builtin;
|
||||
pub use builtin::*;
|
||||
|
||||
// 新ファイル: src/stdlib/builtin.rs
|
||||
// (前回設計したBuiltinStdlib実装)
|
||||
```
|
||||
|
||||
#### **4. SharedState統合**
|
||||
```rust
|
||||
// src/interpreter/core.rs
|
||||
#[derive(Clone)]
|
||||
pub struct SharedState {
|
||||
// 既存フィールド...
|
||||
pub builtin_stdlib: Arc<BuiltinStdlib>,
|
||||
pub using_imports: Arc<RwLock<HashMap<String, UsingContext>>>,
|
||||
}
|
||||
|
||||
impl SharedState {
|
||||
pub fn new() -> Self {
|
||||
SharedState {
|
||||
// 既存初期化...
|
||||
builtin_stdlib: Arc::new(BuiltinStdlib::new()),
|
||||
using_imports: Arc::new(RwLock::new(HashMap::new())),
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### ⚡ High実装(今週中)
|
||||
|
||||
#### **5. using文パーサー**
|
||||
```rust
|
||||
// src/parser/statements.rs
|
||||
impl NyashParser {
|
||||
pub fn parse_statement(&mut self) -> Result<ASTNode, ParseError> {
|
||||
match &self.current_token().token_type {
|
||||
// 既存ケース...
|
||||
TokenType::USING => self.parse_using(),
|
||||
// 他の既存ケース...
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_using(&mut self) -> Result<ASTNode, ParseError> {
|
||||
let start_span = self.current_token().span.clone();
|
||||
self.advance(); // consume 'using'
|
||||
|
||||
if let TokenType::IDENTIFIER(namespace_name) = &self.current_token().token_type {
|
||||
let name = namespace_name.clone();
|
||||
self.advance();
|
||||
|
||||
// Phase 0制限:nyashstdのみ許可
|
||||
if name != "nyashstd" {
|
||||
return Err(ParseError::UnsupportedFeature(
|
||||
format!("Only 'nyashstd' namespace is supported in Phase 0, got '{}'", name)
|
||||
));
|
||||
}
|
||||
|
||||
Ok(ASTNode::UsingStatement {
|
||||
namespace_name: name,
|
||||
span: start_span,
|
||||
})
|
||||
} else {
|
||||
Err(ParseError::ExpectedIdentifier(
|
||||
"Expected namespace name after 'using'".to_string()
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### **6. 基本string関数実装**
|
||||
```rust
|
||||
// src/stdlib/builtin.rs拡張
|
||||
impl BuiltinStdlib {
|
||||
fn register_string_functions(&mut self) {
|
||||
// string.upper
|
||||
self.register_function("string.upper", BuiltinFunction {
|
||||
namespace: "nyashstd",
|
||||
box_name: "string",
|
||||
method_name: "upper",
|
||||
implementation: |args| {
|
||||
if args.len() != 1 {
|
||||
return Err(RuntimeError::InvalidArguments(
|
||||
"string.upper() takes exactly 1 argument".to_string()
|
||||
));
|
||||
}
|
||||
|
||||
let input = &args[0].to_string_box().value;
|
||||
let result = StringBox::new(&input.to_uppercase());
|
||||
Ok(Box::new(result))
|
||||
},
|
||||
arg_count: Some(1),
|
||||
description: "Convert string to uppercase",
|
||||
});
|
||||
|
||||
// string.lower
|
||||
self.register_function("string.lower", BuiltinFunction {
|
||||
namespace: "nyashstd",
|
||||
box_name: "string",
|
||||
method_name: "lower",
|
||||
implementation: |args| {
|
||||
if args.len() != 1 {
|
||||
return Err(RuntimeError::InvalidArguments(
|
||||
"string.lower() takes exactly 1 argument".to_string()
|
||||
));
|
||||
}
|
||||
|
||||
let input = &args[0].to_string_box().value;
|
||||
let result = StringBox::new(&input.to_lowercase());
|
||||
Ok(Box::new(result))
|
||||
},
|
||||
arg_count: Some(1),
|
||||
description: "Convert string to lowercase",
|
||||
});
|
||||
|
||||
// string.split
|
||||
self.register_function("string.split", BuiltinFunction {
|
||||
namespace: "nyashstd",
|
||||
box_name: "string",
|
||||
method_name: "split",
|
||||
implementation: |args| {
|
||||
if args.len() != 2 {
|
||||
return Err(RuntimeError::InvalidArguments(
|
||||
"string.split() takes exactly 2 arguments".to_string()
|
||||
));
|
||||
}
|
||||
|
||||
let string_box = StringBox::new(&args[0].to_string_box().value);
|
||||
let separator = &args[1].to_string_box().value;
|
||||
string_box.split(separator)
|
||||
},
|
||||
arg_count: Some(2),
|
||||
description: "Split string by separator",
|
||||
});
|
||||
|
||||
// string.join
|
||||
self.register_function("string.join", BuiltinFunction {
|
||||
namespace: "nyashstd",
|
||||
box_name: "string",
|
||||
method_name: "join",
|
||||
implementation: |args| {
|
||||
if args.len() != 2 {
|
||||
return Err(RuntimeError::InvalidArguments(
|
||||
"string.join() takes exactly 2 arguments".to_string()
|
||||
));
|
||||
}
|
||||
|
||||
let array_arg = &args[0];
|
||||
let separator = &args[1].to_string_box().value;
|
||||
let separator_box = StringBox::new(separator);
|
||||
separator_box.join(array_arg.clone())
|
||||
},
|
||||
arg_count: Some(2),
|
||||
description: "Join array elements with separator",
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### **7. インタープリター統合**
|
||||
```rust
|
||||
// src/interpreter/expressions.rs
|
||||
impl NyashInterpreter {
|
||||
pub fn execute_expression(&mut self, node: &ASTNode) -> Result<Box<dyn NyashBox>, RuntimeError> {
|
||||
match node {
|
||||
// using文処理
|
||||
ASTNode::UsingStatement { namespace_name, .. } => {
|
||||
self.execute_using(namespace_name)?;
|
||||
Ok(Box::new(VoidBox::new()))
|
||||
}
|
||||
|
||||
// メソッド呼び出し処理拡張
|
||||
ASTNode::MethodCall { object, method, args, .. } => {
|
||||
// 組み込み関数チェック
|
||||
if let ASTNode::Variable { name: box_name, .. } = object.as_ref() {
|
||||
let path = vec![box_name.clone(), method.clone()];
|
||||
if let Some(qualified_name) = self.resolve_qualified_call(&path) {
|
||||
let evaluated_args = self.evaluate_arguments(args)?;
|
||||
return self.call_builtin_function(&qualified_name, evaluated_args);
|
||||
}
|
||||
}
|
||||
|
||||
// 既存のメソッド呼び出し処理
|
||||
// ...
|
||||
}
|
||||
|
||||
// 既存の他のケース...
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 📝 Medium実装(来週)
|
||||
|
||||
#### **8. math関数実装**
|
||||
```rust
|
||||
// math.sin, cos, sqrt, floor, random
|
||||
```
|
||||
|
||||
#### **9. array関数実装**
|
||||
```rust
|
||||
// array.length, get, push, slice
|
||||
```
|
||||
|
||||
#### **10. io関数実装**
|
||||
```rust
|
||||
// io.print, println, debug
|
||||
```
|
||||
|
||||
## Phase 1: 拡張機能(2-3週間後)
|
||||
|
||||
### 🌟 完全修飾名対応
|
||||
```nyash
|
||||
# using不要でも使える
|
||||
nyashstd.string.upper("hello")
|
||||
nyashstd.math.sin(3.14)
|
||||
```
|
||||
|
||||
#### **実装**
|
||||
```rust
|
||||
// ASTNode::QualifiedCall追加
|
||||
ASTNode::QualifiedCall {
|
||||
path: Vec<String>, // ["nyashstd", "string", "upper"]
|
||||
args: Vec<ASTNode>,
|
||||
span: Span,
|
||||
}
|
||||
|
||||
// パーサーで "identifier.identifier.identifier()" 構文解析
|
||||
```
|
||||
|
||||
### 🔧 エラーハンドリング強化
|
||||
```rust
|
||||
// より詳細なエラーメッセージ
|
||||
RuntimeError::UndefinedBuiltinMethod {
|
||||
namespace: String,
|
||||
box_name: String,
|
||||
method_name: String,
|
||||
available_methods: Vec<String>, // "Did you mean: ..."
|
||||
span: Span,
|
||||
}
|
||||
```
|
||||
|
||||
### 📊 IDE補完サポート
|
||||
```rust
|
||||
// Language Server連携用API
|
||||
impl BuiltinStdlib {
|
||||
pub fn get_completion_candidates(&self, prefix: &str) -> Vec<CompletionItem> {
|
||||
// "ny" -> ["nyashstd"]
|
||||
// "nyashstd." -> ["string", "math", "array", "io"]
|
||||
// "nyashstd.string." -> ["upper", "lower", "split", "join"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Phase 2: nyash.link準備(1ヶ月後)
|
||||
|
||||
### 🔗 外部モジュール対応基盤
|
||||
```rust
|
||||
// ModuleResolver拡張
|
||||
pub enum NamespaceSource {
|
||||
Builtin(Arc<BuiltinStdlib>), // 組み込み
|
||||
External(PathBuf), // nyash.linkで管理
|
||||
}
|
||||
|
||||
// NamespaceRegistry統合
|
||||
pub struct NamespaceRegistry {
|
||||
builtin: Arc<BuiltinStdlib>,
|
||||
external: HashMap<String, ExternalModule>,
|
||||
}
|
||||
```
|
||||
|
||||
### 📁 nyash.link対応
|
||||
```toml
|
||||
[dependencies]
|
||||
mylib = { path = "./mylib.nyash" }
|
||||
|
||||
# using mylib # Phase 2で対応
|
||||
```
|
||||
|
||||
## 🧪 段階的テスト戦略
|
||||
|
||||
### Phase 0テスト
|
||||
```nyash
|
||||
# test_phase0_basic.nyash
|
||||
using nyashstd
|
||||
|
||||
# 基本動作
|
||||
assert(string.upper("hello") == "HELLO")
|
||||
assert(string.lower("WORLD") == "world")
|
||||
|
||||
# エラー処理
|
||||
try {
|
||||
using unknown_namespace
|
||||
} catch e {
|
||||
assert(e.contains("nyashstd"))
|
||||
}
|
||||
```
|
||||
|
||||
### Phase 1テスト
|
||||
```nyash
|
||||
# test_phase1_qualified.nyash
|
||||
# using不要のテスト
|
||||
assert(nyashstd.string.upper("hello") == "HELLO")
|
||||
assert(nyashstd.math.sin(0) == 0)
|
||||
```
|
||||
|
||||
### Phase 2テスト
|
||||
```nyash
|
||||
# test_phase2_external.nyash
|
||||
using mylib
|
||||
|
||||
assert(mylib.custom.process("data") == "processed: data")
|
||||
```
|
||||
|
||||
## 📊 実装マイルストーン
|
||||
|
||||
### ✅ Phase 0完了条件
|
||||
- [ ] USINGトークン認識
|
||||
- [ ] using nyashstd構文解析
|
||||
- [ ] 組み込みstring関数4種動作
|
||||
- [ ] 基本テスト全通過
|
||||
- [ ] エラーハンドリング適切
|
||||
|
||||
### ✅ Phase 1完了条件
|
||||
- [ ] 完全修飾名 nyashstd.string.upper() 動作
|
||||
- [ ] math/array/io関数実装
|
||||
- [ ] IDE補完候補API実装
|
||||
- [ ] 詳細エラーメッセージ
|
||||
|
||||
### ✅ Phase 2完了条件
|
||||
- [ ] 外部モジュール基盤実装
|
||||
- [ ] nyash.link基本対応
|
||||
- [ ] 依存関係解決機能
|
||||
- [ ] 全機能統合テスト
|
||||
|
||||
## 🔥 即座に開始すべき実装
|
||||
|
||||
### 今日やること
|
||||
1. **src/stdlib/mod.rs作成** - モジュール基盤
|
||||
2. **TokenType::USING追加** - トークナイザー拡張
|
||||
3. **BuiltinStdlib::new()実装** - 空の基盤作成
|
||||
|
||||
### 今週やること
|
||||
4. **using文パーサー実装** - 基本構文解析
|
||||
5. **string.upper()実装** - 最初の関数
|
||||
6. **基本テスト作成** - 動作確認
|
||||
|
||||
### 来週やること
|
||||
7. **string関数完成** - lower, split, join
|
||||
8. **math関数開始** - sin, cos, sqrt
|
||||
9. **IDE補完設計** - Language Server準備
|
||||
|
||||
---
|
||||
|
||||
**🎯 この段階的戦略で、複雑なnyash.linkなしに即座に実用的なnamespace/usingシステムが実現できるにゃ!**
|
||||
|
||||
**🚀 Phase 0実装を今すぐ開始して、Nyashをモダンなプログラミング言語に進化させよう!🐱✨**
|
||||
471
docs/予定/nyash.link/implementation-plan.md
Normal file
471
docs/予定/nyash.link/implementation-plan.md
Normal file
@ -0,0 +1,471 @@
|
||||
# nyash.linkシステム実装計画
|
||||
|
||||
## 🎯 実装戦略
|
||||
|
||||
### 📊 現状確認
|
||||
- ✅ **include**: 限定的使用(text_adventure例のみ)→廃止OK
|
||||
- ✅ **using**: 未実装→完全新規作成
|
||||
- ✅ **namespace**: 設計完了→実装のみ
|
||||
- ✅ **Gemini推奨**: 技術的妥当性確認済み
|
||||
|
||||
## 📋 段階的実装ロードマップ
|
||||
|
||||
### 🚀 **Phase 1: 基盤構築(1-2週間)**
|
||||
|
||||
#### 1.1 トークナイザー拡張
|
||||
```rust
|
||||
// src/tokenizer.rs
|
||||
pub enum TokenType {
|
||||
// 既存...
|
||||
USING, // using キーワード
|
||||
NAMESPACE, // namespace キーワード
|
||||
AS, // as キーワード(将来のエイリアス用)
|
||||
}
|
||||
|
||||
// キーワード認識追加
|
||||
fn tokenize_identifier(input: &str) -> TokenType {
|
||||
match input {
|
||||
// 既存...
|
||||
"using" => TokenType::USING,
|
||||
"namespace" => TokenType::NAMESPACE,
|
||||
"as" => TokenType::AS,
|
||||
_ => TokenType::IDENTIFIER(input.to_string()),
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 1.2 AST拡張
|
||||
```rust
|
||||
// src/ast.rs
|
||||
pub enum ASTNode {
|
||||
// 既存...
|
||||
UsingStatement {
|
||||
module_path: Vec<String>, // ["nyashstd"] or ["mylib"]
|
||||
alias: Option<String>, // using mylib as lib
|
||||
span: Span,
|
||||
},
|
||||
NamespaceDeclaration {
|
||||
name: String,
|
||||
body: Vec<ASTNode>,
|
||||
span: Span,
|
||||
},
|
||||
QualifiedCall {
|
||||
path: Vec<String>, // ["nyashstd", "string", "upper"]
|
||||
args: Vec<ASTNode>,
|
||||
span: Span,
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
#### 1.3 パーサー基本実装
|
||||
```rust
|
||||
// src/parser/statements.rs
|
||||
impl NyashParser {
|
||||
pub fn parse_using(&mut self) -> Result<ASTNode, ParseError> {
|
||||
self.advance(); // consume 'using'
|
||||
|
||||
let module_path = self.parse_module_path()?;
|
||||
// using mylib → ["mylib"]
|
||||
// using nyashstd.string → ["nyashstd", "string"]
|
||||
|
||||
Ok(ASTNode::UsingStatement {
|
||||
module_path,
|
||||
alias: None, // Phase 1では未サポート
|
||||
span: self.current_span(),
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_module_path(&mut self) -> Result<Vec<String>, ParseError> {
|
||||
let mut path = vec![];
|
||||
|
||||
// 最初の識別子
|
||||
if let TokenType::IDENTIFIER(name) = &self.current_token().token_type {
|
||||
path.push(name.clone());
|
||||
self.advance();
|
||||
} else {
|
||||
return Err(ParseError::ExpectedIdentifier);
|
||||
}
|
||||
|
||||
// ドット区切りで追加パス(将来拡張)
|
||||
// using nyashstd.string のような構文
|
||||
|
||||
Ok(path)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### ⚡ **Phase 2: nyash.link基盤(2-3週間)**
|
||||
|
||||
#### 2.1 nyash.linkパーサー
|
||||
```rust
|
||||
// 新ファイル: src/link_file.rs
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct NyashLink {
|
||||
pub project: Option<ProjectInfo>,
|
||||
pub dependencies: HashMap<String, Dependency>,
|
||||
pub search_paths: Option<HashMap<String, String>>,
|
||||
pub build: Option<BuildConfig>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct ProjectInfo {
|
||||
pub name: String,
|
||||
pub version: String,
|
||||
pub description: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(untagged)]
|
||||
pub enum Dependency {
|
||||
Path { path: String },
|
||||
Stdlib { stdlib: bool },
|
||||
Registry { version: String, registry: String },
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub struct BuildConfig {
|
||||
pub entry_point: Option<String>,
|
||||
}
|
||||
|
||||
impl NyashLink {
|
||||
pub fn from_file(path: &Path) -> Result<Self, LinkError> {
|
||||
let content = std::fs::read_to_string(path)?;
|
||||
let link: NyashLink = toml::from_str(&content)?;
|
||||
Ok(link)
|
||||
}
|
||||
|
||||
pub fn resolve_dependency(&self, name: &str) -> Option<PathBuf> {
|
||||
if let Some(dep) = self.dependencies.get(name) {
|
||||
match dep {
|
||||
Dependency::Path { path } => Some(PathBuf::from(path)),
|
||||
Dependency::Stdlib { .. } => {
|
||||
// 標準ライブラリパス解決ロジック
|
||||
self.resolve_stdlib_path(name)
|
||||
}
|
||||
_ => None, // Phase 2では未サポート
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 2.2 依存関係解決エンジン
|
||||
```rust
|
||||
// 新ファイル: src/module_resolver.rs
|
||||
pub struct ModuleResolver {
|
||||
nyash_link: NyashLink,
|
||||
loaded_modules: HashMap<String, Arc<ParsedModule>>,
|
||||
loading_stack: Vec<String>, // 循環依存検出用
|
||||
}
|
||||
|
||||
impl ModuleResolver {
|
||||
pub fn new(link_path: &Path) -> Result<Self, ResolverError> {
|
||||
let nyash_link = NyashLink::from_file(link_path)?;
|
||||
Ok(ModuleResolver {
|
||||
nyash_link,
|
||||
loaded_modules: HashMap::new(),
|
||||
loading_stack: Vec::new(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn resolve_using(&mut self, module_name: &str) -> Result<Arc<ParsedModule>, ResolverError> {
|
||||
// 既にロード済みかチェック
|
||||
if let Some(module) = self.loaded_modules.get(module_name) {
|
||||
return Ok(module.clone());
|
||||
}
|
||||
|
||||
// 循環依存チェック
|
||||
if self.loading_stack.contains(&module_name.to_string()) {
|
||||
return Err(ResolverError::CircularDependency(
|
||||
self.loading_stack.clone()
|
||||
));
|
||||
}
|
||||
|
||||
// ファイルパス解決
|
||||
let file_path = self.nyash_link.resolve_dependency(module_name)
|
||||
.ok_or(ResolverError::ModuleNotFound(module_name.to_string()))?;
|
||||
|
||||
// 再帰的読み込み防止
|
||||
self.loading_stack.push(module_name.to_string());
|
||||
|
||||
// ファイル読み込み・パース
|
||||
let content = std::fs::read_to_string(&file_path)?;
|
||||
let ast = NyashParser::parse_from_string(&content)?;
|
||||
|
||||
// モジュール作成
|
||||
let module = Arc::new(ParsedModule {
|
||||
name: module_name.to_string(),
|
||||
file_path,
|
||||
ast,
|
||||
exports: self.extract_exports(&ast)?,
|
||||
});
|
||||
|
||||
// キャッシュに保存
|
||||
self.loaded_modules.insert(module_name.to_string(), module.clone());
|
||||
self.loading_stack.pop();
|
||||
|
||||
Ok(module)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 📈 **Phase 3: 名前空間システム(3-4週間)**
|
||||
|
||||
#### 3.1 namespace解析
|
||||
```rust
|
||||
impl NyashParser {
|
||||
pub fn parse_namespace(&mut self) -> Result<ASTNode, ParseError> {
|
||||
self.advance(); // consume 'namespace'
|
||||
|
||||
let name = self.expect_identifier()?;
|
||||
self.expect_token(TokenType::LBRACE)?;
|
||||
|
||||
let mut body = vec![];
|
||||
while !self.check_token(&TokenType::RBRACE) {
|
||||
body.push(self.parse_statement()?);
|
||||
}
|
||||
|
||||
self.expect_token(TokenType::RBRACE)?;
|
||||
|
||||
Ok(ASTNode::NamespaceDeclaration {
|
||||
name,
|
||||
body,
|
||||
span: self.current_span(),
|
||||
})
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 3.2 名前空間レジストリ
|
||||
```rust
|
||||
// 新ファイル: src/namespace_registry.rs
|
||||
pub struct NamespaceRegistry {
|
||||
namespaces: HashMap<String, Namespace>,
|
||||
using_imports: HashMap<String, Vec<String>>, // ファイル別インポート
|
||||
}
|
||||
|
||||
pub struct Namespace {
|
||||
pub name: String,
|
||||
pub static_boxes: HashMap<String, StaticBox>,
|
||||
}
|
||||
|
||||
pub struct StaticBox {
|
||||
pub name: String,
|
||||
pub static_methods: HashMap<String, MethodSignature>,
|
||||
}
|
||||
|
||||
impl NamespaceRegistry {
|
||||
pub fn register_namespace(&mut self, name: String, namespace: Namespace) {
|
||||
self.namespaces.insert(name, namespace);
|
||||
}
|
||||
|
||||
pub fn add_using_import(&mut self, file_id: String, namespace_name: String) {
|
||||
self.using_imports
|
||||
.entry(file_id)
|
||||
.or_insert_with(Vec::new)
|
||||
.push(namespace_name);
|
||||
}
|
||||
|
||||
pub fn resolve_call(&self, file_id: &str, path: &[String]) -> Option<MethodSignature> {
|
||||
// 例: string.upper() → nyashstd.string.upper()
|
||||
if path.len() == 2 {
|
||||
let box_name = &path[0];
|
||||
let method_name = &path[1];
|
||||
|
||||
// usingでインポートされた名前空間を検索
|
||||
if let Some(imports) = self.using_imports.get(file_id) {
|
||||
for namespace_name in imports {
|
||||
if let Some(namespace) = self.namespaces.get(namespace_name) {
|
||||
if let Some(static_box) = namespace.static_boxes.get(box_name) {
|
||||
if let Some(method) = static_box.static_methods.get(method_name) {
|
||||
return Some(method.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 🎯 **Phase 4: インタープリター統合(4-5週間)**
|
||||
|
||||
#### 4.1 using文実行
|
||||
```rust
|
||||
// src/interpreter/core.rs
|
||||
impl NyashInterpreter {
|
||||
pub fn execute_using(&mut self, module_path: &[String]) -> Result<(), RuntimeError> {
|
||||
let module_name = module_path.join(".");
|
||||
|
||||
// モジュール解決・読み込み
|
||||
let module = self.module_resolver.resolve_using(&module_name)?;
|
||||
|
||||
// 名前空間登録
|
||||
if let Some(namespace) = self.extract_namespace_from_module(&module) {
|
||||
self.namespace_registry.register_namespace(module_name.clone(), namespace);
|
||||
self.namespace_registry.add_using_import(
|
||||
self.current_file_id.clone(),
|
||||
module_name
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn extract_namespace_from_module(&self, module: &ParsedModule) -> Option<Namespace> {
|
||||
// ASTからnamespace宣言を探して解析
|
||||
for node in &module.ast {
|
||||
if let ASTNode::NamespaceDeclaration { name, body, .. } = node {
|
||||
return Some(self.build_namespace_from_body(name, body));
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 4.2 qualified call実行
|
||||
```rust
|
||||
impl NyashInterpreter {
|
||||
pub fn execute_qualified_call(&mut self, path: &[String], args: &[ASTNode])
|
||||
-> Result<Box<dyn NyashBox>, RuntimeError> {
|
||||
|
||||
// 名前解決
|
||||
if let Some(method_sig) = self.namespace_registry.resolve_call(
|
||||
&self.current_file_id,
|
||||
path
|
||||
) {
|
||||
// 引数評価
|
||||
let evaluated_args = self.evaluate_args(args)?;
|
||||
|
||||
// メソッド実行(既存のBox呼び出しシステム活用)
|
||||
return self.call_static_method(&method_sig, evaluated_args);
|
||||
}
|
||||
|
||||
// 完全修飾名として試行
|
||||
if path.len() >= 3 {
|
||||
// nyashstd.string.upper() の場合
|
||||
let namespace_name = &path[0];
|
||||
let box_name = &path[1];
|
||||
let method_name = &path[2];
|
||||
|
||||
if let Some(namespace) = self.namespace_registry.namespaces.get(namespace_name) {
|
||||
if let Some(static_box) = namespace.static_boxes.get(box_name) {
|
||||
if let Some(method) = static_box.static_methods.get(method_name) {
|
||||
let evaluated_args = self.evaluate_args(args)?;
|
||||
return self.call_static_method(method, evaluated_args);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Err(RuntimeError::UndefinedMethod(path.join(".")))
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🧪 テスト戦略
|
||||
|
||||
### Phase 1テスト
|
||||
```nyash
|
||||
# test_basic_using.nyash
|
||||
# 基本using文テスト
|
||||
|
||||
# ファイル: mylib.nyash
|
||||
static function hello() {
|
||||
return "Hello from mylib!"
|
||||
}
|
||||
|
||||
# ファイル: main.nyash
|
||||
using mylib
|
||||
local result = mylib.hello()
|
||||
assert(result == "Hello from mylib!")
|
||||
```
|
||||
|
||||
### Phase 2テスト
|
||||
```nyash
|
||||
# test_nyash_link.nyash
|
||||
# nyash.linkファイル連携テスト
|
||||
|
||||
# nyash.link内容:
|
||||
# [dependencies]
|
||||
# mylib = { path = "./mylib.nyash" }
|
||||
|
||||
using mylib
|
||||
local result = mylib.process("data")
|
||||
assert(result == "processed: data")
|
||||
```
|
||||
|
||||
### Phase 3テスト
|
||||
```nyash
|
||||
# test_namespace.nyash
|
||||
# 名前空間システムテスト
|
||||
|
||||
# nyashstd.nyash:
|
||||
# namespace nyashstd {
|
||||
# static box string {
|
||||
# static upper(str) { ... }
|
||||
# }
|
||||
# }
|
||||
|
||||
using nyashstd
|
||||
local result = string.upper("hello")
|
||||
assert(result == "HELLO")
|
||||
|
||||
# 完全修飾名
|
||||
local result2 = nyashstd.string.upper("world")
|
||||
assert(result2 == "WORLD")
|
||||
```
|
||||
|
||||
## 📊 実装マイルストーン
|
||||
|
||||
### ✅ 完了条件
|
||||
|
||||
#### Phase 1
|
||||
- [ ] USING/NAMESPACE トークン認識
|
||||
- [ ] using文AST構築
|
||||
- [ ] 基本パーサーテスト通過
|
||||
|
||||
#### Phase 2
|
||||
- [ ] nyash.linkファイル読み込み
|
||||
- [ ] 依存関係解決
|
||||
- [ ] モジュールキャッシュ機能
|
||||
|
||||
#### Phase 3
|
||||
- [ ] namespace宣言解析
|
||||
- [ ] 名前空間レジストリ動作
|
||||
- [ ] 静的メソッド解決
|
||||
|
||||
#### Phase 4
|
||||
- [ ] インタープリター統合
|
||||
- [ ] qualified call実行
|
||||
- [ ] 全テストケース通過
|
||||
|
||||
## 🔮 将来拡張
|
||||
|
||||
### Phase 5: 高度機能
|
||||
- エイリアス(`using mylib as lib`)
|
||||
- 選択インポート(`using nyashstd.string`)
|
||||
- 動的モジュール読み込み
|
||||
|
||||
### Phase 6: 標準ライブラリ
|
||||
- nyashstd.nyash完全実装
|
||||
- string/math/io/http モジュール
|
||||
- ドキュメント生成
|
||||
|
||||
### Phase 7: エコシステム
|
||||
- パッケージレジストリ設計
|
||||
- CLI ツール(nyash init/install)
|
||||
- IDE Language Server連携
|
||||
|
||||
---
|
||||
|
||||
**🎯 この実装計画でnyash.linkシステムを段階的に完成させるにゃ!**
|
||||
372
docs/予定/nyash.link/master-architecture.md
Normal file
372
docs/予定/nyash.link/master-architecture.md
Normal file
@ -0,0 +1,372 @@
|
||||
# なんでもAPI計画:最終統合アーキテクチャ
|
||||
|
||||
## 🌟 革命的ビジョンの実現
|
||||
|
||||
### 📊 統合設計完了状況
|
||||
- ✅ **nyash.link基盤**: 依存関係管理システム設計完了
|
||||
- ✅ **FFI-ABI統合**: BID×MIR×バックエンド統合設計完了
|
||||
- ✅ **usingシステム**: 3種類API統一インポート設計完了
|
||||
- ✅ **実世界例**: ゲーム・データサイエンス・Web・システムプログラミング実証
|
||||
- 🎯 **最終統合**: 全システム統合による革命的開発体験実現
|
||||
|
||||
### 🚀 完成後の開発体験
|
||||
```nyash
|
||||
# === たった一つの構文ですべてが使える ===
|
||||
using nyashstd # 組み込み標準ライブラリ
|
||||
using browser_api # ブラウザAPI(Canvas, DOM, WebAudio...)
|
||||
using system_api # システムAPI(libc, filesystem, network...)
|
||||
using ml_api # 機械学習(TensorFlow, PyTorch, OpenCV...)
|
||||
using game_api # ゲーム開発(SDL, OpenGL, Vulkan...)
|
||||
using mylib # 自作Nyashモジュール
|
||||
|
||||
# 全部同じ記法・同じパフォーマンス・同じエラーハンドリング!
|
||||
string.upper("hello") # 組み込み標準
|
||||
browser.canvas.fillRect("game", 10, 10, 100, 100, "red") # ブラウザAPI
|
||||
system.file.read("/etc/passwd") # システムAPI
|
||||
ml.opencv.loadImage("photo.jpg") # 機械学習API
|
||||
game.sdl.createWindow("Game", 800, 600) # ゲームAPI
|
||||
mylib.processData("input") # 自作モジュール
|
||||
```
|
||||
|
||||
## 🏗️ 最終統合アーキテクチャ
|
||||
|
||||
### 1. 全体システム構成
|
||||
```
|
||||
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
||||
│ Nyash Code │ │ nyash.link │ │ BID Files │
|
||||
│ │ │ │ │ │
|
||||
│ using browser_api│ │ [dependencies] │ │ browser_api: │
|
||||
│ using system_api │───▶│ browser_api = │───▶│ canvas.yaml │
|
||||
│ using mylib │ │ {bid=...} │ │ dom.yaml │
|
||||
│ canvas.fillRect │ │ system_api = │ │ system_api: │
|
||||
│ file.read │ │ {bid=...} │ │ libc.yaml │
|
||||
│ mylib.process │ │ mylib = {path} │ │ filesystem.yaml│
|
||||
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
||||
│ │ │
|
||||
└────────────────────────┼────────────────────────┘
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ UniversalNamespaceRegistry │
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │
|
||||
│ │BuiltinStdlib│ │BidDefinition│ │ExternalModules │ │
|
||||
│ │ │ │ │ │ │ │
|
||||
│ │nyashstd.* │ │browser_api.*│ │mylib.* │ │
|
||||
│ │string.upper │ │canvas.fill* │ │custom functions │ │
|
||||
│ │math.sin │ │dom.events │ │ │ │
|
||||
│ │array.length │ │system.file* │ │ │ │
|
||||
│ └─────────────┘ └─────────────┘ └─────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ MIR Generation │
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │
|
||||
│ │BuiltinCall │ │ExternCall │ │ModuleCall │ │
|
||||
│ │ │ │ │ │ │ │
|
||||
│ │string.upper │ │canvas.fill* │ │mylib.process │ │
|
||||
│ │effect:pure │ │effect:io │ │effect:io │ │
|
||||
│ │optimize:yes │ │gpu_accel:yes│ │ │ │
|
||||
│ └─────────────┘ └─────────────┘ └─────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ Backend Execution │
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │
|
||||
│ │ VM │ │ WASM │ │ AOT │ │
|
||||
│ │ │ │ │ │ │ │
|
||||
│ │Native Impl │ │RuntimeImport│ │LLVM ExternFunc │ │
|
||||
│ │Stub Calls │ │Auto-generated│ │Native Libraries │ │
|
||||
│ │ │ │from BID │ │ │ │
|
||||
│ └─────────────┘ └─────────────┘ └─────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 2. nyash.link統合仕様(最終版)
|
||||
```toml
|
||||
# nyash.link - 全API統一管理設定
|
||||
[project]
|
||||
name = "ultimate-nyash-app"
|
||||
version = "2.0.0"
|
||||
description = "Everything is accessible through unified APIs"
|
||||
license = "MIT"
|
||||
|
||||
[dependencies]
|
||||
# === 組み込み標準ライブラリ ===
|
||||
nyashstd = { builtin = true }
|
||||
|
||||
# === ブラウザ・Web API ===
|
||||
browser_api = {
|
||||
bid = ["./apis/canvas.yaml", "./apis/dom.yaml", "./apis/webaudio.yaml"],
|
||||
target_environments = ["browser"]
|
||||
}
|
||||
webgl_api = {
|
||||
bid = "./apis/webgl.yaml",
|
||||
target_environments = ["browser"]
|
||||
}
|
||||
|
||||
# === システム・OS API ===
|
||||
system_api = {
|
||||
bid = ["./apis/libc.yaml", "./apis/filesystem.yaml", "./apis/network.yaml"],
|
||||
library = "system",
|
||||
target_environments = ["linux", "macos", "windows"]
|
||||
}
|
||||
posix_api = {
|
||||
bid = "./apis/posix.yaml",
|
||||
library = "system",
|
||||
target_environments = ["linux", "macos"]
|
||||
}
|
||||
|
||||
# === 機械学習・データサイエンス ===
|
||||
ml_api = {
|
||||
bid = ["./apis/opencv.yaml", "./apis/numpy.yaml"],
|
||||
library = ["./libs/opencv.so", "./libs/numpy.so"],
|
||||
target_environments = ["linux", "macos"]
|
||||
}
|
||||
tensorflow_api = {
|
||||
bid = "./apis/tensorflow.yaml",
|
||||
library = "./libs/tensorflow.so",
|
||||
optional = true # 環境によってオプション
|
||||
}
|
||||
|
||||
# === ゲーム開発 ===
|
||||
game_api = {
|
||||
bid = ["./apis/sdl.yaml", "./apis/opengl.yaml"],
|
||||
library = ["SDL2", "OpenGL"],
|
||||
target_environments = ["linux", "macos", "windows"]
|
||||
}
|
||||
|
||||
# === データベース ===
|
||||
database_api = {
|
||||
bid = ["./apis/sqlite.yaml", "./apis/postgresql.yaml"],
|
||||
library = ["sqlite3", "pq"],
|
||||
}
|
||||
|
||||
# === ネットワーク・Web ===
|
||||
http_api = {
|
||||
bid = "./apis/http_client.yaml",
|
||||
library = "curl"
|
||||
}
|
||||
|
||||
# === Nyashモジュール(従来通り) ===
|
||||
mylib = { path = "./src/mylib.nyash" }
|
||||
utils = { path = "./src/utils/" }
|
||||
models = { path = "./src/models.nyash" }
|
||||
|
||||
# === 将来の外部パッケージ ===
|
||||
awesome_lib = {
|
||||
version = "^1.2.0",
|
||||
registry = "nyash-pkg",
|
||||
bid = "auto" # パッケージレジストリから自動取得
|
||||
}
|
||||
|
||||
[build]
|
||||
entry_point = "./src/main.nyash"
|
||||
backends = ["vm", "wasm", "aot"]
|
||||
optimization_level = "release"
|
||||
|
||||
[targets]
|
||||
browser = ["browser_api", "webgl_api"]
|
||||
desktop = ["system_api", "game_api", "ml_api"]
|
||||
server = ["system_api", "database_api", "http_api"]
|
||||
|
||||
[optimization]
|
||||
# MIRレベル最適化設定
|
||||
enable_effect_optimization = true
|
||||
enable_batch_optimization = true # FFI-ABI呼び出しバッチ化
|
||||
enable_gpu_acceleration = true
|
||||
cache_bid_compilation = true
|
||||
```
|
||||
|
||||
### 3. BIDエコシステム(標準API集)
|
||||
```
|
||||
nyash-std-apis/ # 標準APIライブラリ
|
||||
├── browser/
|
||||
│ ├── canvas.yaml # Canvas API
|
||||
│ ├── dom.yaml # DOM API
|
||||
│ ├── webaudio.yaml # Web Audio API
|
||||
│ ├── webgl.yaml # WebGL API
|
||||
│ └── fetch.yaml # Fetch API
|
||||
├── system/
|
||||
│ ├── libc.yaml # C標準ライブラリ
|
||||
│ ├── filesystem.yaml # ファイルシステム
|
||||
│ ├── network.yaml # ネットワーク
|
||||
│ ├── process.yaml # プロセス管理
|
||||
│ └── threads.yaml # スレッド・並行処理
|
||||
├── ml/
|
||||
│ ├── opencv.yaml # コンピューターヴィジョン
|
||||
│ ├── numpy.yaml # 数値計算
|
||||
│ ├── tensorflow.yaml # 機械学習
|
||||
│ └── pytorch.yaml # 深層学習
|
||||
├── game/
|
||||
│ ├── sdl.yaml # SDL2ライブラリ
|
||||
│ ├── opengl.yaml # OpenGL API
|
||||
│ ├── vulkan.yaml # Vulkan API
|
||||
│ └── physics.yaml # 物理エンジン
|
||||
├── database/
|
||||
│ ├── sqlite.yaml # SQLite
|
||||
│ ├── postgresql.yaml # PostgreSQL
|
||||
│ ├── mysql.yaml # MySQL
|
||||
│ └── redis.yaml # Redis
|
||||
└── crypto/
|
||||
├── openssl.yaml # OpenSSL
|
||||
├── libsodium.yaml # libsodium
|
||||
└── bcrypt.yaml # bcrypt
|
||||
```
|
||||
|
||||
## 🚀 段階的実装戦略(現実的ロードマップ)
|
||||
|
||||
### Phase 0: 基盤構築(2-3週間)
|
||||
```rust
|
||||
// 🎯 最小実装目標
|
||||
// using nyashstd → 動作
|
||||
```
|
||||
|
||||
#### **実装内容**
|
||||
1. **USINGトークナイザー** - `TokenType::USING`追加
|
||||
2. **基本パーサー** - `using nyashstd`構文解析
|
||||
3. **BuiltinStdlib基盤** - 組み込み標準ライブラリ
|
||||
4. **基本string関数** - upper, lower, split, join
|
||||
|
||||
#### **テスト**
|
||||
```nyash
|
||||
using nyashstd
|
||||
assert(string.upper("hello") == "HELLO")
|
||||
```
|
||||
|
||||
### Phase 1: BID基盤(4-6週間)
|
||||
```rust
|
||||
// 🎯 外部API基盤目標
|
||||
// using console_api → 動作(VM Stub)
|
||||
```
|
||||
|
||||
#### **実装内容**
|
||||
1. **BID読み込み** - YAML解析・検証システム
|
||||
2. **UniversalNamespaceRegistry** - 統合名前空間管理
|
||||
3. **MIR ExternCall統合** - BID→MIR変換
|
||||
4. **VM Stub実装** - console.log等の基本スタブ
|
||||
|
||||
#### **テスト**
|
||||
```nyash
|
||||
using nyashstd
|
||||
using console_api
|
||||
string.upper("test")
|
||||
console.log("BID integration works!")
|
||||
```
|
||||
|
||||
### Phase 2: WASM統合(6-8週間)
|
||||
```rust
|
||||
// 🎯 WASM動作目標
|
||||
// ブラウザでCanvas API動作
|
||||
```
|
||||
|
||||
#### **実装内容**
|
||||
1. **WASM RuntimeImports自動生成** - BID→WASM import
|
||||
2. **文字列マーシャリング** - UTF-8 (ptr,len)対応
|
||||
3. **Canvas API完全実装** - fillRect, fillText等
|
||||
4. **ブラウザテスト環境** - HTML/JS統合
|
||||
|
||||
#### **テスト**
|
||||
```nyash
|
||||
using browser_api
|
||||
canvas.fillRect("game-canvas", 10, 10, 100, 100, "red")
|
||||
```
|
||||
|
||||
### Phase 3: システムAPI統合(8-12週間)
|
||||
```rust
|
||||
// 🎯 ネイティブライブラリ動作目標
|
||||
// ファイルI/O, システムコール等
|
||||
```
|
||||
|
||||
#### **実装内容**
|
||||
1. **AOTバックエンド統合** - LLVM IR外部関数
|
||||
2. **システムライブラリ連携** - libc, filesystem等
|
||||
3. **エラーハンドリング統合** - 統一エラーモデル
|
||||
4. **パフォーマンス最適化** - バッチ処理・GPU加速
|
||||
|
||||
#### **テスト**
|
||||
```nyash
|
||||
using system_api
|
||||
local content = file.read("/etc/passwd")
|
||||
file.write("./output.txt", content)
|
||||
```
|
||||
|
||||
### Phase 4: 完全エコシステム(12-16週間)
|
||||
```rust
|
||||
// 🎯 実用的アプリケーション開発
|
||||
// ゲーム・ML・Webアプリ等
|
||||
```
|
||||
|
||||
#### **実装内容**
|
||||
1. **標準APIライブラリ** - nyash-std-apis完成
|
||||
2. **パッケージレジストリ** - BID共有システム
|
||||
3. **IDE Language Server** - 統合補完・エラー検出
|
||||
4. **最適化エンジン** - Effect System活用
|
||||
|
||||
#### **実用例**
|
||||
```nyash
|
||||
# 本格的なゲーム開発
|
||||
using game_api
|
||||
using audio_api
|
||||
game.sdl.createWindow("My Game", 1024, 768)
|
||||
audio.mixer.playMusic("bgm.ogg")
|
||||
```
|
||||
|
||||
## 📊 既存実装との整合性
|
||||
|
||||
### Phase 9.75eとの関係
|
||||
```
|
||||
Phase 9.75e (既存計画) なんでもAPI計画 (新設計)
|
||||
↓ ↓
|
||||
namespace構文 using統一構文
|
||||
依存関係システム → nyash.link統合管理
|
||||
外部ファイル読み込み → BID統合システム
|
||||
↓
|
||||
完全統合アーキテクチャ
|
||||
```
|
||||
|
||||
### 既存MIR/バックエンドとの統合
|
||||
- ✅ **MIR ExternCall**: 既存実装活用
|
||||
- ✅ **WASM RuntimeImports**: 既存基盤拡張
|
||||
- ✅ **VM Backend**: 既存スタブシステム活用
|
||||
- 🔧 **統合課題**: usingシステムとの橋渡し
|
||||
|
||||
## 🌟 長期ビジョン:Nyashの未来
|
||||
|
||||
### 2025年目標
|
||||
- **Phase 0-1完了**: 基盤・BID統合
|
||||
- **実用アプリ**: シンプルなブラウザゲーム・ツール
|
||||
- **コミュニティ**: 開発者コミュニティ形成
|
||||
|
||||
### 2026年目標
|
||||
- **Phase 2-3完了**: WASM・システムAPI統合
|
||||
- **本格アプリ**: ゲーム・データサイエンス・Webアプリ
|
||||
- **エコシステム**: BIDライブラリエコシステム
|
||||
|
||||
### 2027年目標
|
||||
- **Phase 4完了**: 完全エコシステム
|
||||
- **産業利用**: 企業での実用的活用
|
||||
- **言語標準化**: BID標準の業界採用
|
||||
|
||||
## 🎯 即座に開始すべき実装
|
||||
|
||||
### 今日のアクション
|
||||
1. **src/stdlib/mod.rs作成** - 組み込み標準ライブラリ基盤
|
||||
2. **TokenType::USING追加** - トークナイザー拡張
|
||||
3. **Phase 0実装開始** - using nyashstd基本動作
|
||||
|
||||
### 今週のアクション
|
||||
4. **BuiltinStdlib::new()実装** - string関数4種
|
||||
5. **基本テスト作成** - using動作確認
|
||||
6. **Phase 1設計** - BID統合詳細設計
|
||||
|
||||
### 来週のアクション
|
||||
7. **BID読み込み基盤** - YAML解析システム
|
||||
8. **UniversalNamespaceRegistry** - 統合名前空間管理
|
||||
9. **console.log実装** - 最初のBID統合テスト
|
||||
|
||||
---
|
||||
|
||||
**🎉 この最終統合アーキテクチャにより、Nyashが真に「なんでもできる」革命的プログラミング言語になるにゃ!**
|
||||
|
||||
**🚀 今すぐPhase 0実装を開始して、プログラミング言語の未来を創造しよう!🐱✨**
|
||||
435
docs/予定/nyash.link/minimal-stdlib-first.md
Normal file
435
docs/予定/nyash.link/minimal-stdlib-first.md
Normal file
@ -0,0 +1,435 @@
|
||||
# 最小実装:標準関数優先namespace/usingシステム
|
||||
|
||||
## 🎯 基本戦略:nyash.link前の段階的実装
|
||||
|
||||
### 📊 現状分析
|
||||
- **既存Box型**: 25種類以上の豊富なBox実装
|
||||
- **include使用**: 限定的(text_adventure例のみ)
|
||||
- **using実装**: 完全未実装→新規作成可能
|
||||
- **最優先課題**: 複雑なファイル依存関係システムより、まず標準関数のIDE補完
|
||||
|
||||
### 🌟 段階的実装アプローチ
|
||||
|
||||
#### **Phase 0: 組み込みnyashstd(最小実装)**
|
||||
```
|
||||
ファイル読み込み一切なし → インタープリターに直接組み込み
|
||||
```
|
||||
|
||||
#### **Phase 1: using構文**
|
||||
```nyash
|
||||
using nyashstd
|
||||
string.upper("hello") # ✅ 動作
|
||||
```
|
||||
|
||||
#### **Phase 2: 将来のnyash.link対応**
|
||||
```
|
||||
外部ファイル・依存関係システム(後日実装)
|
||||
```
|
||||
|
||||
## 🏗️ 組み込みnyashstd設計
|
||||
|
||||
### 優先順位別Box分類
|
||||
|
||||
#### 🚨 **Tier 1: 最優先基本機能**
|
||||
```rust
|
||||
// 使用頻度最高・IDE補完必須
|
||||
- string_box.rs → nyashstd.string.*
|
||||
- math_box.rs → nyashstd.math.*
|
||||
- array/mod.rs → nyashstd.array.*
|
||||
- console_box.rs → nyashstd.io.*
|
||||
```
|
||||
|
||||
#### ⚡ **Tier 2: 重要機能**
|
||||
```rust
|
||||
// 標準的な機能
|
||||
- time_box.rs → nyashstd.time.*
|
||||
- random_box.rs → nyashstd.random.*
|
||||
- map_box.rs → nyashstd.map.*
|
||||
```
|
||||
|
||||
#### 📝 **Tier 3: 特殊用途**
|
||||
```rust
|
||||
// 特定用途・後で追加
|
||||
- debug_box.rs → nyashstd.debug.*
|
||||
- http_server_box.rs → nyashstd.http.*
|
||||
- p2p_box.rs → nyashstd.p2p.*
|
||||
```
|
||||
|
||||
### 最小実装スコープ(Phase 0)
|
||||
|
||||
#### **nyashstd.string機能**
|
||||
```nyash
|
||||
using nyashstd
|
||||
|
||||
string.upper("hello") # "HELLO"
|
||||
string.lower("WORLD") # "world"
|
||||
string.split("a,b,c", ",") # ["a", "b", "c"]
|
||||
string.join(["a","b"], "-") # "a-b"
|
||||
string.length("test") # 4
|
||||
```
|
||||
|
||||
#### **nyashstd.math機能**
|
||||
```nyash
|
||||
using nyashstd
|
||||
|
||||
math.sin(3.14159) # 0.0 (approximately)
|
||||
math.cos(0) # 1.0
|
||||
math.sqrt(16) # 4.0
|
||||
math.floor(3.7) # 3
|
||||
math.random() # 0.0-1.0のランダム値
|
||||
```
|
||||
|
||||
#### **nyashstd.array機能**
|
||||
```nyash
|
||||
using nyashstd
|
||||
|
||||
array.length([1,2,3]) # 3
|
||||
array.push([1,2], 3) # [1,2,3]
|
||||
array.get([1,2,3], 1) # 2
|
||||
array.slice([1,2,3,4], 1, 3) # [2,3]
|
||||
```
|
||||
|
||||
#### **nyashstd.io機能**
|
||||
```nyash
|
||||
using nyashstd
|
||||
|
||||
io.print("Hello") # コンソール出力
|
||||
io.println("World") # 改行付き出力
|
||||
io.debug("Debug info") # デバッグ出力
|
||||
```
|
||||
|
||||
## 💻 技術実装戦略
|
||||
|
||||
### 1. インタープリター組み込み方式
|
||||
|
||||
#### **新ファイル: `src/stdlib/mod.rs`**
|
||||
```rust
|
||||
//! 組み込み標準ライブラリ
|
||||
//! nyash.linkなしで動作する基本的な標準関数群
|
||||
|
||||
use crate::boxes::*;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub struct BuiltinStdlib {
|
||||
pub namespaces: HashMap<String, BuiltinNamespace>,
|
||||
}
|
||||
|
||||
pub struct BuiltinNamespace {
|
||||
pub name: String,
|
||||
pub static_boxes: HashMap<String, BuiltinStaticBox>,
|
||||
}
|
||||
|
||||
pub struct BuiltinStaticBox {
|
||||
pub name: String,
|
||||
pub methods: HashMap<String, BuiltinMethod>,
|
||||
}
|
||||
|
||||
pub type BuiltinMethod = fn(&[Box<dyn NyashBox>]) -> Result<Box<dyn NyashBox>, RuntimeError>;
|
||||
|
||||
impl BuiltinStdlib {
|
||||
pub fn new() -> Self {
|
||||
let mut stdlib = BuiltinStdlib {
|
||||
namespaces: HashMap::new(),
|
||||
};
|
||||
|
||||
// nyashstd名前空間登録
|
||||
stdlib.register_nyashstd();
|
||||
|
||||
stdlib
|
||||
}
|
||||
|
||||
fn register_nyashstd(&mut self) {
|
||||
let mut nyashstd = BuiltinNamespace {
|
||||
name: "nyashstd".to_string(),
|
||||
static_boxes: HashMap::new(),
|
||||
};
|
||||
|
||||
// string static box
|
||||
nyashstd.static_boxes.insert("string".to_string(), self.create_string_box());
|
||||
// math static box
|
||||
nyashstd.static_boxes.insert("math".to_string(), self.create_math_box());
|
||||
// array static box
|
||||
nyashstd.static_boxes.insert("array".to_string(), self.create_array_box());
|
||||
// io static box
|
||||
nyashstd.static_boxes.insert("io".to_string(), self.create_io_box());
|
||||
|
||||
self.namespaces.insert("nyashstd".to_string(), nyashstd);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### **文字列関数実装例**
|
||||
```rust
|
||||
impl BuiltinStdlib {
|
||||
fn create_string_box(&self) -> BuiltinStaticBox {
|
||||
let mut string_box = BuiltinStaticBox {
|
||||
name: "string".to_string(),
|
||||
methods: HashMap::new(),
|
||||
};
|
||||
|
||||
// string.upper(str) -> String
|
||||
string_box.methods.insert("upper".to_string(), |args| {
|
||||
if args.len() != 1 {
|
||||
return Err(RuntimeError::InvalidArguments(
|
||||
"string.upper() takes exactly 1 argument".to_string()
|
||||
));
|
||||
}
|
||||
|
||||
let string_arg = args[0].to_string_box();
|
||||
let result = StringBox::new(&string_arg.value.to_uppercase());
|
||||
Ok(Box::new(result))
|
||||
});
|
||||
|
||||
// string.lower(str) -> String
|
||||
string_box.methods.insert("lower".to_string(), |args| {
|
||||
if args.len() != 1 {
|
||||
return Err(RuntimeError::InvalidArguments(
|
||||
"string.lower() takes exactly 1 argument".to_string()
|
||||
));
|
||||
}
|
||||
|
||||
let string_arg = args[0].to_string_box();
|
||||
let result = StringBox::new(&string_arg.value.to_lowercase());
|
||||
Ok(Box::new(result))
|
||||
});
|
||||
|
||||
// string.split(str, separator) -> Array
|
||||
string_box.methods.insert("split".to_string(), |args| {
|
||||
if args.len() != 2 {
|
||||
return Err(RuntimeError::InvalidArguments(
|
||||
"string.split() takes exactly 2 arguments".to_string()
|
||||
));
|
||||
}
|
||||
|
||||
let string_arg = args[0].to_string_box();
|
||||
let sep_arg = args[1].to_string_box();
|
||||
|
||||
let string_box = StringBox::new(&string_arg.value);
|
||||
let result = string_box.split(&sep_arg.value)?;
|
||||
Ok(result)
|
||||
});
|
||||
|
||||
string_box
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. インタープリター統合
|
||||
|
||||
#### **インタープリター拡張: `src/interpreter/core.rs`**
|
||||
```rust
|
||||
use crate::stdlib::BuiltinStdlib;
|
||||
|
||||
pub struct NyashInterpreter {
|
||||
// 既存フィールド...
|
||||
pub builtin_stdlib: BuiltinStdlib,
|
||||
pub using_imports: HashMap<String, Vec<String>>, // ファイル別インポート
|
||||
}
|
||||
|
||||
impl NyashInterpreter {
|
||||
pub fn new() -> Self {
|
||||
NyashInterpreter {
|
||||
// 既存初期化...
|
||||
builtin_stdlib: BuiltinStdlib::new(),
|
||||
using_imports: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
// using文実行
|
||||
pub fn execute_using(&mut self, namespace_name: &str) -> Result<(), RuntimeError> {
|
||||
// 組み込み名前空間かチェック
|
||||
if self.builtin_stdlib.namespaces.contains_key(namespace_name) {
|
||||
// 現在ファイルのインポートリストに追加
|
||||
self.using_imports
|
||||
.entry(self.current_file_id.clone())
|
||||
.or_insert_with(Vec::new)
|
||||
.push(namespace_name.to_string());
|
||||
|
||||
Ok(())
|
||||
} else {
|
||||
Err(RuntimeError::UndefinedNamespace(namespace_name.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
// 短縮名解決: string.upper() -> nyashstd.string.upper()
|
||||
pub fn resolve_short_call(&self, box_name: &str, method_name: &str)
|
||||
-> Option<(&str, &str, &str)> { // (namespace, box, method)
|
||||
|
||||
if let Some(imports) = self.using_imports.get(&self.current_file_id) {
|
||||
for namespace_name in imports {
|
||||
if let Some(namespace) = self.builtin_stdlib.namespaces.get(namespace_name) {
|
||||
if namespace.static_boxes.contains_key(box_name) {
|
||||
return Some((namespace_name, box_name, method_name));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
// 組み込み関数呼び出し
|
||||
pub fn call_builtin_method(&self, namespace: &str, box_name: &str, method_name: &str, args: Vec<Box<dyn NyashBox>>)
|
||||
-> Result<Box<dyn NyashBox>, RuntimeError> {
|
||||
|
||||
if let Some(ns) = self.builtin_stdlib.namespaces.get(namespace) {
|
||||
if let Some(static_box) = ns.static_boxes.get(box_name) {
|
||||
if let Some(method) = static_box.methods.get(method_name) {
|
||||
return method(&args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Err(RuntimeError::UndefinedMethod(
|
||||
format!("{}.{}.{}", namespace, box_name, method_name)
|
||||
))
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. パーサー最小拡張
|
||||
|
||||
#### **トークナイザー: `src/tokenizer.rs`**
|
||||
```rust
|
||||
pub enum TokenType {
|
||||
// 既存...
|
||||
USING, // using キーワード
|
||||
// NAMESPACE は後のPhaseで追加
|
||||
}
|
||||
```
|
||||
|
||||
#### **AST最小拡張: `src/ast.rs`**
|
||||
```rust
|
||||
pub enum ASTNode {
|
||||
// 既存...
|
||||
UsingStatement {
|
||||
namespace_name: String, // "nyashstd" のみ対応
|
||||
span: Span,
|
||||
},
|
||||
// QualifiedCall は後のPhaseで追加
|
||||
}
|
||||
```
|
||||
|
||||
#### **パーサー: `src/parser/statements.rs`**
|
||||
```rust
|
||||
impl NyashParser {
|
||||
pub fn parse_using(&mut self) -> Result<ASTNode, ParseError> {
|
||||
self.advance(); // consume 'using'
|
||||
|
||||
if let TokenType::IDENTIFIER(namespace_name) = &self.current_token().token_type {
|
||||
let name = namespace_name.clone();
|
||||
self.advance();
|
||||
|
||||
// Phase 0では "nyashstd" のみ許可
|
||||
if name != "nyashstd" {
|
||||
return Err(ParseError::UnsupportedNamespace(name));
|
||||
}
|
||||
|
||||
Ok(ASTNode::UsingStatement {
|
||||
namespace_name: name,
|
||||
span: self.current_span(),
|
||||
})
|
||||
} else {
|
||||
Err(ParseError::ExpectedIdentifier)
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🧪 テスト戦略
|
||||
|
||||
### Phase 0テストケース
|
||||
|
||||
#### **基本using文テスト**
|
||||
```nyash
|
||||
# test_using_basic.nyash
|
||||
using nyashstd
|
||||
|
||||
local result = string.upper("hello")
|
||||
assert(result == "HELLO")
|
||||
|
||||
local lower = string.lower("WORLD")
|
||||
assert(lower == "world")
|
||||
```
|
||||
|
||||
#### **数学関数テスト**
|
||||
```nyash
|
||||
# test_math_basic.nyash
|
||||
using nyashstd
|
||||
|
||||
local sin_result = math.sin(0)
|
||||
assert(sin_result == 0)
|
||||
|
||||
local sqrt_result = math.sqrt(16)
|
||||
assert(sqrt_result == 4)
|
||||
```
|
||||
|
||||
#### **配列操作テスト**
|
||||
```nyash
|
||||
# test_array_basic.nyash
|
||||
using nyashstd
|
||||
|
||||
local arr = [1, 2, 3]
|
||||
local length = array.length(arr)
|
||||
assert(length == 3)
|
||||
|
||||
local item = array.get(arr, 1)
|
||||
assert(item == 2)
|
||||
```
|
||||
|
||||
## 📊 実装マイルストーン
|
||||
|
||||
### ✅ Phase 0完了条件
|
||||
- [ ] USING トークン認識
|
||||
- [ ] using nyashstd 構文解析
|
||||
- [ ] 組み込みnyashstd.string実装
|
||||
- [ ] 組み込みnyashstd.math実装
|
||||
- [ ] 組み込みnyashstd.array実装
|
||||
- [ ] 組み込みnyashstd.io実装
|
||||
- [ ] 基本テストケース全通過
|
||||
|
||||
### 🔮 将来の発展
|
||||
|
||||
#### **Phase 1: 完全修飾名対応**
|
||||
```nyash
|
||||
# using不要でも使える
|
||||
nyashstd.string.upper("hello")
|
||||
```
|
||||
|
||||
#### **Phase 2: namespace構文対応**
|
||||
```nyash
|
||||
# 組み込み以外の名前空間
|
||||
namespace mylib {
|
||||
static box utils {
|
||||
static process(data) { ... }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### **Phase 3: nyash.link統合**
|
||||
```toml
|
||||
# nyash.link
|
||||
[dependencies]
|
||||
mylib = { path = "./mylib.nyash" }
|
||||
```
|
||||
|
||||
## 🎯 実装優先順位
|
||||
|
||||
### 🚨 Critical(今すぐ)
|
||||
1. **USINGトークナイザー** - Token::USING追加
|
||||
2. **using文パーサー** - "using nyashstd"解析
|
||||
3. **BuiltinStdlib基盤** - src/stdlib/mod.rs作成
|
||||
|
||||
### ⚡ High(今週中)
|
||||
4. **string関数実装** - upper, lower, split, join
|
||||
5. **math関数実装** - sin, cos, sqrt, floor
|
||||
6. **基本テスト** - using nyashstd動作確認
|
||||
|
||||
### 📝 Medium(来週)
|
||||
7. **array関数実装** - length, get, push, slice
|
||||
8. **io関数実装** - print, println, debug
|
||||
9. **エラーハンドリング** - 適切なエラーメッセージ
|
||||
|
||||
---
|
||||
|
||||
**🎉 この戦略なら複雑なファイル依存関係システムなしで、すぐに実用的なnamespace/usingが実現できるにゃ!🐱**
|
||||
625
docs/予定/nyash.link/real-world-examples.md
Normal file
625
docs/予定/nyash.link/real-world-examples.md
Normal file
@ -0,0 +1,625 @@
|
||||
# なんでもAPI計画:実世界での具体例
|
||||
|
||||
## 🌟 革命的開発体験の実例
|
||||
|
||||
### 🎮 ゲーム開発例:Nyashブラウザゲーム
|
||||
```nyash
|
||||
# === nyash.link ===
|
||||
[dependencies]
|
||||
nyashstd = { builtin = true }
|
||||
canvas_api = { bid = "./apis/canvas.yaml" }
|
||||
dom_api = { bid = "./apis/dom.yaml" }
|
||||
audio_api = { bid = "./apis/webaudio.yaml" }
|
||||
|
||||
# === game.nyash ===
|
||||
using nyashstd
|
||||
using canvas_api
|
||||
using dom_api
|
||||
using audio_api
|
||||
|
||||
static box Game {
|
||||
init { canvas_id, score, player_x, player_y, enemies }
|
||||
|
||||
main() {
|
||||
me.canvas_id = "game-canvas"
|
||||
me.score = 0
|
||||
me.player_x = 200
|
||||
me.player_y = 300
|
||||
me.enemies = new ArrayBox()
|
||||
|
||||
# DOMイベント設定(FFI-ABI経由)
|
||||
dom.addEventListener("keydown", me.handleKeyDown)
|
||||
|
||||
# ゲームループ開始
|
||||
me.gameLoop()
|
||||
}
|
||||
|
||||
gameLoop() {
|
||||
loop(true) {
|
||||
me.update()
|
||||
me.render()
|
||||
|
||||
# ブラウザのrequestAnimationFrame(FFI-ABI)
|
||||
dom.requestAnimationFrame(me.gameLoop)
|
||||
}
|
||||
}
|
||||
|
||||
update() {
|
||||
# 敵の移動(組み込み標準ライブラリ)
|
||||
local i = 0
|
||||
loop(i < array.length(me.enemies)) {
|
||||
local enemy = array.get(me.enemies, i)
|
||||
enemy.y = enemy.y + enemy.speed
|
||||
i = i + 1
|
||||
}
|
||||
|
||||
# 当たり判定(組み込み数学関数)
|
||||
local distance = math.sqrt(
|
||||
math.pow(me.player_x - enemy.x, 2) +
|
||||
math.pow(me.player_y - enemy.y, 2)
|
||||
)
|
||||
|
||||
if distance < 30 {
|
||||
me.gameOver()
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
# 画面クリア(Canvas API - FFI-ABI)
|
||||
canvas.fillRect(me.canvas_id, 0, 0, 800, 600, "black")
|
||||
|
||||
# プレイヤー描画
|
||||
canvas.fillRect(me.canvas_id, me.player_x, me.player_y, 20, 20, "blue")
|
||||
|
||||
# 敵描画
|
||||
local i = 0
|
||||
loop(i < array.length(me.enemies)) {
|
||||
local enemy = array.get(me.enemies, i)
|
||||
canvas.fillRect(me.canvas_id, enemy.x, enemy.y, 15, 15, "red")
|
||||
i = i + 1
|
||||
}
|
||||
|
||||
# スコア表示
|
||||
local score_text = "Score: " + string.toString(me.score)
|
||||
canvas.fillText(me.canvas_id, score_text, 10, 30, "20px Arial", "white")
|
||||
}
|
||||
|
||||
handleKeyDown(event) {
|
||||
# キーボード入力処理(DOM API経由)
|
||||
local key = dom.getEventKey(event)
|
||||
|
||||
if key == "ArrowLeft" {
|
||||
me.player_x = me.player_x - 10
|
||||
} else if key == "ArrowRight" {
|
||||
me.player_x = me.player_x + 10
|
||||
} else if key == " " { # スペースキー
|
||||
me.shoot()
|
||||
}
|
||||
}
|
||||
|
||||
shoot() {
|
||||
# 効果音再生(Web Audio API - FFI-ABI)
|
||||
audio.playSound("shoot.wav")
|
||||
|
||||
# 弾の生成・発射処理
|
||||
# ...
|
||||
}
|
||||
|
||||
gameOver() {
|
||||
# ゲームオーバー処理
|
||||
audio.playSound("gameover.wav")
|
||||
dom.alert("Game Over! Score: " + string.toString(me.score))
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 🔬 データサイエンス例:画像処理アプリ
|
||||
```nyash
|
||||
# === nyash.link ===
|
||||
[dependencies]
|
||||
nyashstd = { builtin = true }
|
||||
opencv_api = { bid = "./apis/opencv.yaml", library = "./libs/opencv.so" }
|
||||
numpy_api = { bid = "./apis/numpy.yaml", library = "./libs/numpy.so" }
|
||||
matplotlib_api = { bid = "./apis/matplotlib.yaml", library = "./libs/matplotlib.so" }
|
||||
file_api = { bid = "./apis/file.yaml" }
|
||||
|
||||
# === image_processor.nyash ===
|
||||
using nyashstd
|
||||
using opencv_api
|
||||
using numpy_api
|
||||
using matplotlib_api
|
||||
using file_api
|
||||
|
||||
static box ImageProcessor {
|
||||
init { input_path, output_path, processed_data }
|
||||
|
||||
main() {
|
||||
me.input_path = "./images/input.jpg"
|
||||
me.output_path = "./images/output.jpg"
|
||||
|
||||
# 画像読み込み(OpenCV - FFI-ABI)
|
||||
local image = opencv.imread(me.input_path)
|
||||
|
||||
# 前処理
|
||||
local gray = opencv.cvtColor(image, "BGR2GRAY")
|
||||
local blurred = opencv.gaussianBlur(gray, 5, 5)
|
||||
|
||||
# エッジ検出
|
||||
local edges = opencv.canny(blurred, 50, 150)
|
||||
|
||||
# NumPy配列操作(NumPy - FFI-ABI)
|
||||
local edge_array = numpy.fromOpenCV(edges)
|
||||
local normalized = numpy.normalize(edge_array, 0, 255)
|
||||
|
||||
# 統計計算(組み込み標準ライブラリ)
|
||||
local edge_count = me.countEdgePixels(normalized)
|
||||
local percentage = (edge_count * 100) / (image.width * image.height)
|
||||
|
||||
# 結果表示
|
||||
io.println("Edge pixels: " + string.toString(edge_count))
|
||||
io.println("Edge percentage: " + string.toString(percentage) + "%")
|
||||
|
||||
# 結果画像保存(OpenCV)
|
||||
opencv.imwrite(me.output_path, edges)
|
||||
|
||||
# グラフ生成(Matplotlib - FFI-ABI)
|
||||
me.generateHistogram(normalized)
|
||||
}
|
||||
|
||||
countEdgePixels(image_array) {
|
||||
local count = 0
|
||||
local height = numpy.shape(image_array, 0)
|
||||
local width = numpy.shape(image_array, 1)
|
||||
|
||||
local y = 0
|
||||
loop(y < height) {
|
||||
local x = 0
|
||||
loop(x < width) {
|
||||
local pixel = numpy.get(image_array, y, x)
|
||||
if pixel > 0 {
|
||||
count = count + 1
|
||||
}
|
||||
x = x + 1
|
||||
}
|
||||
y = y + 1
|
||||
}
|
||||
|
||||
return count
|
||||
}
|
||||
|
||||
generateHistogram(image_array) {
|
||||
# ヒストグラム計算(NumPy)
|
||||
local histogram = numpy.histogram(image_array, 256)
|
||||
|
||||
# グラフ描画(Matplotlib)
|
||||
matplotlib.figure(800, 600)
|
||||
matplotlib.plot(histogram.bins, histogram.values)
|
||||
matplotlib.title("Edge Pixel Histogram")
|
||||
matplotlib.xlabel("Pixel Intensity")
|
||||
matplotlib.ylabel("Frequency")
|
||||
matplotlib.savefig("./images/histogram.png")
|
||||
matplotlib.show()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 🌐 Webサーバー例:RESTful API
|
||||
```nyash
|
||||
# === nyash.link ===
|
||||
[dependencies]
|
||||
nyashstd = { builtin = true }
|
||||
http_server_api = { bid = "./apis/http_server.yaml" }
|
||||
sqlite_api = { bid = "./apis/sqlite.yaml", library = "./libs/sqlite.so" }
|
||||
json_api = { bid = "./apis/json.yaml" }
|
||||
crypto_api = { bid = "./apis/crypto.yaml", library = "./libs/openssl.so" }
|
||||
|
||||
# === api_server.nyash ===
|
||||
using nyashstd
|
||||
using http_server_api
|
||||
using sqlite_api
|
||||
using json_api
|
||||
using crypto_api
|
||||
|
||||
static box ApiServer {
|
||||
init { server, database, port }
|
||||
|
||||
main() {
|
||||
me.port = 8080
|
||||
me.server = http_server.create()
|
||||
me.database = sqlite.open("./data/app.db")
|
||||
|
||||
# データベース初期化
|
||||
me.initDatabase()
|
||||
|
||||
# ルート設定
|
||||
http_server.route(me.server, "GET", "/api/users", me.getUsers)
|
||||
http_server.route(me.server, "POST", "/api/users", me.createUser)
|
||||
http_server.route(me.server, "PUT", "/api/users/:id", me.updateUser)
|
||||
http_server.route(me.server, "DELETE", "/api/users/:id", me.deleteUser)
|
||||
|
||||
# サーバー開始
|
||||
io.println("Server starting on port " + string.toString(me.port))
|
||||
http_server.listen(me.server, me.port)
|
||||
}
|
||||
|
||||
initDatabase() {
|
||||
local sql = "CREATE TABLE IF NOT EXISTS users (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
email TEXT UNIQUE NOT NULL,
|
||||
password_hash TEXT NOT NULL,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
)"
|
||||
|
||||
sqlite.exec(me.database, sql)
|
||||
}
|
||||
|
||||
getUsers(request, response) {
|
||||
# クエリ実行(SQLite - FFI-ABI)
|
||||
local sql = "SELECT id, name, email, created_at FROM users"
|
||||
local results = sqlite.query(me.database, sql)
|
||||
|
||||
# JSON変換(JSON API - FFI-ABI)
|
||||
local json_response = json.stringify(results)
|
||||
|
||||
# レスポンス送信(HTTP Server API)
|
||||
http_server.setHeader(response, "Content-Type", "application/json")
|
||||
http_server.setStatus(response, 200)
|
||||
http_server.send(response, json_response)
|
||||
}
|
||||
|
||||
createUser(request, response) {
|
||||
# リクエストボディ解析
|
||||
local body = http_server.getBody(request)
|
||||
local user_data = json.parse(body)
|
||||
|
||||
# バリデーション(組み込み標準ライブラリ)
|
||||
if string.length(user_data.name) < 2 {
|
||||
me.sendError(response, 400, "Name must be at least 2 characters")
|
||||
return
|
||||
}
|
||||
|
||||
if not me.isValidEmail(user_data.email) {
|
||||
me.sendError(response, 400, "Invalid email format")
|
||||
return
|
||||
}
|
||||
|
||||
# パスワードハッシュ化(Crypto API - FFI-ABI)
|
||||
local password_hash = crypto.hashPassword(user_data.password)
|
||||
|
||||
# データベース挿入
|
||||
local sql = "INSERT INTO users (name, email, password_hash) VALUES (?, ?, ?)"
|
||||
local params = [user_data.name, user_data.email, password_hash]
|
||||
|
||||
try {
|
||||
local user_id = sqlite.insert(me.database, sql, params)
|
||||
|
||||
# 作成されたユーザー情報を返す
|
||||
local created_user = map.create()
|
||||
map.set(created_user, "id", user_id)
|
||||
map.set(created_user, "name", user_data.name)
|
||||
map.set(created_user, "email", user_data.email)
|
||||
|
||||
local json_response = json.stringify(created_user)
|
||||
|
||||
http_server.setHeader(response, "Content-Type", "application/json")
|
||||
http_server.setStatus(response, 201)
|
||||
http_server.send(response, json_response)
|
||||
|
||||
} catch error {
|
||||
io.println("Database error: " + error.message)
|
||||
me.sendError(response, 500, "Failed to create user")
|
||||
}
|
||||
}
|
||||
|
||||
isValidEmail(email) {
|
||||
# 簡単なメール検証(組み込み文字列関数)
|
||||
local at_pos = string.indexOf(email, "@")
|
||||
local dot_pos = string.lastIndexOf(email, ".")
|
||||
|
||||
return at_pos > 0 and dot_pos > at_pos and dot_pos < string.length(email) - 1
|
||||
}
|
||||
|
||||
sendError(response, status, message) {
|
||||
local error_obj = map.create()
|
||||
map.set(error_obj, "error", message)
|
||||
|
||||
local json_error = json.stringify(error_obj)
|
||||
|
||||
http_server.setHeader(response, "Content-Type", "application/json")
|
||||
http_server.setStatus(response, status)
|
||||
http_server.send(response, json_error)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 🔧 システムプログラミング例:ファイル監視ツール
|
||||
```nyash
|
||||
# === nyash.link ===
|
||||
[dependencies]
|
||||
nyashstd = { builtin = true }
|
||||
libc_api = { bid = "./apis/libc.yaml", library = "system" }
|
||||
inotify_api = { bid = "./apis/inotify.yaml", library = "system" }
|
||||
filesystem_api = { bid = "./apis/filesystem.yaml" }
|
||||
|
||||
# === file_monitor.nyash ===
|
||||
using nyashstd
|
||||
using libc_api
|
||||
using inotify_api
|
||||
using filesystem_api
|
||||
|
||||
static box FileMonitor {
|
||||
init { watch_path, inotify_fd, watch_descriptors, callbacks }
|
||||
|
||||
main() {
|
||||
me.watch_path = "./watched_directory"
|
||||
me.watch_descriptors = new ArrayBox()
|
||||
me.callbacks = map.create()
|
||||
|
||||
# inotify初期化(Linux inotify - FFI-ABI)
|
||||
me.inotify_fd = inotify.init()
|
||||
|
||||
if me.inotify_fd < 0 {
|
||||
io.println("Failed to initialize inotify")
|
||||
return
|
||||
}
|
||||
|
||||
# ディレクトリ監視設定
|
||||
me.addWatch(me.watch_path)
|
||||
|
||||
# コールバック設定
|
||||
me.setupCallbacks()
|
||||
|
||||
io.println("File monitor started. Watching: " + me.watch_path)
|
||||
|
||||
# メインループ
|
||||
me.eventLoop()
|
||||
}
|
||||
|
||||
addWatch(path) {
|
||||
# 監視フラグ(inotify constants)
|
||||
local flags = inotify.IN_CREATE or inotify.IN_DELETE or
|
||||
inotify.IN_MODIFY or inotify.IN_MOVED_FROM or
|
||||
inotify.IN_MOVED_TO
|
||||
|
||||
local wd = inotify.addWatch(me.inotify_fd, path, flags)
|
||||
|
||||
if wd >= 0 {
|
||||
array.push(me.watch_descriptors, wd)
|
||||
io.println("Added watch for: " + path)
|
||||
} else {
|
||||
io.println("Failed to add watch for: " + path)
|
||||
}
|
||||
}
|
||||
|
||||
setupCallbacks() {
|
||||
# ファイル作成コールバック
|
||||
map.set(me.callbacks, "CREATE", static function(event) {
|
||||
io.println("File created: " + event.name)
|
||||
|
||||
# ファイル情報取得(Filesystem API)
|
||||
local file_info = filesystem.stat(event.path)
|
||||
local size = file_info.size
|
||||
local permissions = file_info.permissions
|
||||
|
||||
io.println(" Size: " + string.toString(size) + " bytes")
|
||||
io.println(" Permissions: " + permissions)
|
||||
})
|
||||
|
||||
# ファイル変更コールバック
|
||||
map.set(me.callbacks, "MODIFY", static function(event) {
|
||||
io.println("File modified: " + event.name)
|
||||
|
||||
# 変更時刻記録
|
||||
local timestamp = time.now()
|
||||
local formatted_time = time.format(timestamp, "%Y-%m-%d %H:%M:%S")
|
||||
io.println(" Modified at: " + formatted_time)
|
||||
})
|
||||
|
||||
# ファイル削除コールバック
|
||||
map.set(me.callbacks, "DELETE", static function(event) {
|
||||
io.println("File deleted: " + event.name)
|
||||
|
||||
# ログファイルに記録
|
||||
me.logEvent("DELETE", event.name, time.now())
|
||||
})
|
||||
}
|
||||
|
||||
eventLoop() {
|
||||
local buffer_size = 4096
|
||||
local buffer = libc.malloc(buffer_size)
|
||||
|
||||
loop(true) {
|
||||
# inotify eventsを読み取り(blocking read)
|
||||
local bytes_read = libc.read(me.inotify_fd, buffer, buffer_size)
|
||||
|
||||
if bytes_read > 0 {
|
||||
me.processEvents(buffer, bytes_read)
|
||||
} else if bytes_read == 0 {
|
||||
# EOF
|
||||
break
|
||||
} else {
|
||||
# エラー
|
||||
local error_code = libc.errno()
|
||||
io.println("Read error: " + string.toString(error_code))
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
libc.free(buffer)
|
||||
}
|
||||
|
||||
processEvents(buffer, bytes_read) {
|
||||
local offset = 0
|
||||
|
||||
loop(offset < bytes_read) {
|
||||
# inotify_event構造体解析(libc memory operations)
|
||||
local event = inotify.parseEvent(buffer, offset)
|
||||
|
||||
# イベントタイプ判定
|
||||
local event_type = me.getEventType(event.mask)
|
||||
|
||||
# 対応するコールバック実行
|
||||
if map.has(me.callbacks, event_type) {
|
||||
local callback = map.get(me.callbacks, event_type)
|
||||
callback(event)
|
||||
}
|
||||
|
||||
# 次のイベントへ
|
||||
offset = offset + event.size
|
||||
}
|
||||
}
|
||||
|
||||
getEventType(mask) {
|
||||
if mask and inotify.IN_CREATE {
|
||||
return "CREATE"
|
||||
} else if mask and inotify.IN_MODIFY {
|
||||
return "MODIFY"
|
||||
} else if mask and inotify.IN_DELETE {
|
||||
return "DELETE"
|
||||
} else if mask and inotify.IN_MOVED_FROM {
|
||||
return "MOVE_FROM"
|
||||
} else if mask and inotify.IN_MOVED_TO {
|
||||
return "MOVE_TO"
|
||||
} else {
|
||||
return "UNKNOWN"
|
||||
}
|
||||
}
|
||||
|
||||
logEvent(event_type, filename, timestamp) {
|
||||
local log_entry = time.format(timestamp, "%Y-%m-%d %H:%M:%S") +
|
||||
" [" + event_type + "] " + filename + "\n"
|
||||
|
||||
# ログファイルに追記(Filesystem API)
|
||||
filesystem.appendFile("./file_monitor.log", log_entry)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📊 MIR同時拡張による最適化効果
|
||||
|
||||
### 🚀 最適化前後の比較
|
||||
|
||||
#### **従来の実装(最適化なし)**
|
||||
```mir
|
||||
; 非効率:毎回関数呼び出し
|
||||
%1 = ExternCall env.canvas.fillRect ["canvas", 10, 10, 100, 100, "red"]
|
||||
%2 = ExternCall env.canvas.fillRect ["canvas", 110, 10, 100, 100, "blue"]
|
||||
%3 = ExternCall env.canvas.fillRect ["canvas", 220, 10, 100, 100, "green"]
|
||||
```
|
||||
|
||||
#### **MIR最適化後(バッチ処理)**
|
||||
```mir
|
||||
; 効率化:バッチ処理
|
||||
%rects = ArrayConstruct [
|
||||
{x: 10, y: 10, w: 100, h: 100, color: "red"},
|
||||
{x: 110, y: 10, w: 100, h: 100, color: "blue"},
|
||||
{x: 220, y: 10, w: 100, h: 100, color: "green"}
|
||||
]
|
||||
%1 = ExternCall env.canvas.fillRectBatch ["canvas", %rects]
|
||||
```
|
||||
|
||||
#### **Effect Systemによる並列化**
|
||||
```mir
|
||||
; pure関数は並列実行可能
|
||||
%1 = BuiltinCall string.upper ["hello"] ; effect: pure
|
||||
%2 = BuiltinCall math.sin [3.14] ; effect: pure
|
||||
%3 = BuiltinCall string.lower ["WORLD"] ; effect: pure
|
||||
; ↑ これらは並列実行される
|
||||
|
||||
%4 = ExternCall env.console.log [%1] ; effect: io
|
||||
%5 = ExternCall env.console.log [%2] ; effect: io
|
||||
; ↑ これらは順序保持される
|
||||
```
|
||||
|
||||
### 🎯 バックエンド別最適化
|
||||
|
||||
#### **WASM最適化**
|
||||
```wasm
|
||||
;; BIDから自動生成された最適化WASM
|
||||
(func $optimized_canvas_batch
|
||||
(param $canvas_id i32) (param $canvas_id_len i32)
|
||||
(param $rects_ptr i32) (param $rect_count i32)
|
||||
|
||||
;; ループ展開による高速化
|
||||
(local $i i32)
|
||||
(local $rect_ptr i32)
|
||||
|
||||
loop $rect_loop
|
||||
;; 直接メモリアクセス(境界チェック済み)
|
||||
local.get $rect_ptr
|
||||
i32.load ;; x
|
||||
local.get $rect_ptr
|
||||
i32.load offset=4 ;; y
|
||||
;; ... 高速描画処理
|
||||
|
||||
local.get $rect_ptr
|
||||
i32.const 20
|
||||
i32.add
|
||||
local.set $rect_ptr
|
||||
|
||||
local.get $i
|
||||
i32.const 1
|
||||
i32.add
|
||||
local.tee $i
|
||||
local.get $rect_count
|
||||
i32.lt_u
|
||||
br_if $rect_loop
|
||||
end
|
||||
)
|
||||
```
|
||||
|
||||
#### **AOT最適化(LLVM IR)**
|
||||
```llvm
|
||||
; LLVM IRレベルでの最適化
|
||||
define void @optimized_image_processing(i8* %image_data, i32 %width, i32 %height) {
|
||||
entry:
|
||||
; ベクトル化された画像処理
|
||||
%0 = bitcast i8* %image_data to <16 x i8>*
|
||||
|
||||
; SIMD命令による並列処理
|
||||
br label %loop.header
|
||||
|
||||
loop.header:
|
||||
%i = phi i32 [ 0, %entry ], [ %i.next, %loop.body ]
|
||||
%cmp = icmp ult i32 %i, %height
|
||||
br i1 %cmp, label %loop.body, label %exit
|
||||
|
||||
loop.body:
|
||||
; 16ピクセル同時処理(AVX2/NEON活用)
|
||||
%pixel_ptr = getelementptr <16 x i8>, <16 x i8>* %0, i32 %i
|
||||
%pixels = load <16 x i8>, <16 x i8>* %pixel_ptr
|
||||
|
||||
; ベクトル化されたエッジ検出
|
||||
%edges = call <16 x i8> @vectorized_edge_detection(<16 x i8> %pixels)
|
||||
|
||||
store <16 x i8> %edges, <16 x i8>* %pixel_ptr
|
||||
|
||||
%i.next = add i32 %i, 1
|
||||
br label %loop.header
|
||||
|
||||
exit:
|
||||
ret void
|
||||
}
|
||||
```
|
||||
|
||||
## 🌟 革命的効果
|
||||
|
||||
### 🚀 開発者体験の向上
|
||||
- **学習コスト**: 一つの構文ですべてのAPIが使える
|
||||
- **IDE統合**: 全APIの統一補完・エラー検出
|
||||
- **デバッグ**: 統一エラーモデルによる一貫したデバッグ体験
|
||||
|
||||
### ⚡ パフォーマンス向上
|
||||
- **MIRレベル最適化**: すべてのAPIで同じ最適化技術
|
||||
- **Effect System**: 安全な並列化・順序最適化
|
||||
- **バックエンド最適化**: WASM/AOT固有の最適化
|
||||
|
||||
### 🌍 エコシステム拡大
|
||||
- **ライブラリ統合**: 既存C/Rustライブラリの簡単統合
|
||||
- **クロスプラットフォーム**: 同じコードが全環境で動作
|
||||
- **標準化**: BIDによる外部API標準化
|
||||
|
||||
---
|
||||
|
||||
**🎉 これが「なんでもAPI計画」の真の実力だにゃ!あらゆる開発が統一された美しい構文で実現できるにゃ!🚀🐱**
|
||||
563
docs/予定/nyash.link/universal-api-integration.md
Normal file
563
docs/予定/nyash.link/universal-api-integration.md
Normal file
@ -0,0 +1,563 @@
|
||||
# なんでもAPI計画:nyash.link × FFI-ABI × MIR 統合設計
|
||||
|
||||
## 🌟 革命的統合ビジョン
|
||||
|
||||
### 📊 現状把握
|
||||
- ✅ **nyash.linkシステム**: 標準関数・モジュール管理設計完了
|
||||
- ✅ **FFI-ABI仕様**: BID(Box Interface Definition)による外部API統一
|
||||
- ✅ **MIR ExternCall**: 外部関数呼び出しのMIRレベル実装
|
||||
- 🎯 **統合目標**: 3つのシステムを統合し「なんでもAPI」を実現
|
||||
|
||||
### 🚀 統合後の開発体験
|
||||
```nyash
|
||||
# === 単一のusing構文ですべてが使える! ===
|
||||
using nyashstd # 組み込み標準ライブラリ
|
||||
using console_api # ブラウザConsole API (FFI-ABI)
|
||||
using canvas_api # Canvas API (FFI-ABI)
|
||||
using opencv_api # OpenCV外部ライブラリ (FFI-ABI)
|
||||
using mylib # 自作Nyashモジュール
|
||||
|
||||
# 全部同じ記法で使える!
|
||||
string.upper("hello") # 組み込み標準ライブラリ
|
||||
console.log("Hello Nyash!") # ブラウザAPI
|
||||
canvas.fillRect("game", 10, 10, 80, 60, "red") # Canvas API
|
||||
opencv.loadImage("photo.jpg") # 外部ライブラリ
|
||||
mylib.processData("input") # 自作モジュール
|
||||
```
|
||||
|
||||
## 🏗️ 統合アーキテクチャ設計
|
||||
|
||||
### 1. 拡張nyash.link仕様
|
||||
|
||||
#### **依存関係タイプの統合**
|
||||
```toml
|
||||
# nyash.link - 全API統一管理
|
||||
[project]
|
||||
name = "awesome-nyash-app"
|
||||
version = "1.0.0"
|
||||
|
||||
[dependencies]
|
||||
# === 組み込み標準ライブラリ ===
|
||||
nyashstd = { builtin = true }
|
||||
|
||||
# === FFI-ABI経由外部API ===
|
||||
console_api = { bid = "./apis/console.yaml" }
|
||||
canvas_api = { bid = "./apis/canvas.yaml" }
|
||||
webgl_api = { bid = "./apis/webgl.yaml" }
|
||||
dom_api = { bid = "./apis/dom.yaml" }
|
||||
|
||||
# === システムライブラリ ===
|
||||
libc = { bid = "./apis/libc.yaml", library = "system" }
|
||||
math_lib = { bid = "./apis/math.yaml", library = "libm" }
|
||||
|
||||
# === 外部共有ライブラリ ===
|
||||
opencv = { bid = "./apis/opencv.yaml", library = "./libs/opencv.so" }
|
||||
sqlite = { bid = "./apis/sqlite.yaml", library = "./libs/sqlite.so" }
|
||||
|
||||
# === Nyashモジュール(従来通り) ===
|
||||
mylib = { path = "./src/mylib.nyash" }
|
||||
utils = { path = "./src/utils.nyash" }
|
||||
models = { path = "./src/models/" }
|
||||
|
||||
# === 将来の外部パッケージ ===
|
||||
# http_client = { version = "1.0.0", registry = "nyash-pkg" }
|
||||
|
||||
[build]
|
||||
entry_point = "./src/main.nyash"
|
||||
backends = ["vm", "wasm", "aot"] # 対象バックエンド指定
|
||||
```
|
||||
|
||||
#### **BIDファイル例**
|
||||
```yaml
|
||||
# apis/console.yaml - Console API定義
|
||||
version: 0
|
||||
metadata:
|
||||
name: "Browser Console API"
|
||||
description: "Standard browser console interface"
|
||||
target_environments: ["browser", "node"]
|
||||
|
||||
interfaces:
|
||||
- name: console_api.console
|
||||
box: Console
|
||||
namespace: console_api
|
||||
methods:
|
||||
- name: log
|
||||
params: [ {string: message} ]
|
||||
returns: void
|
||||
effect: io
|
||||
description: "Output message to console"
|
||||
|
||||
- name: warn
|
||||
params: [ {string: message} ]
|
||||
returns: void
|
||||
effect: io
|
||||
|
||||
- name: error
|
||||
params: [ {string: message} ]
|
||||
returns: void
|
||||
effect: io
|
||||
|
||||
# apis/canvas.yaml - Canvas API定義
|
||||
version: 0
|
||||
interfaces:
|
||||
- name: canvas_api.canvas
|
||||
box: Canvas
|
||||
namespace: canvas_api
|
||||
methods:
|
||||
- name: fillRect
|
||||
params:
|
||||
- {string: canvas_id}
|
||||
- {i32: x}
|
||||
- {i32: y}
|
||||
- {i32: width}
|
||||
- {i32: height}
|
||||
- {string: color}
|
||||
returns: void
|
||||
effect: io
|
||||
|
||||
- name: fillText
|
||||
params:
|
||||
- {string: canvas_id}
|
||||
- {string: text}
|
||||
- {i32: x}
|
||||
- {i32: y}
|
||||
- {string: font}
|
||||
- {string: color}
|
||||
returns: void
|
||||
effect: io
|
||||
```
|
||||
|
||||
### 2. 統合名前空間レジストリ
|
||||
|
||||
#### **UniversalNamespaceRegistry設計**
|
||||
```rust
|
||||
// 新ファイル: src/registry/universal.rs
|
||||
use crate::stdlib::BuiltinStdlib;
|
||||
use crate::bid::BidDefinition;
|
||||
use crate::module::ExternalModule;
|
||||
|
||||
pub struct UniversalNamespaceRegistry {
|
||||
/// 組み込み標準ライブラリ
|
||||
builtin: Arc<BuiltinStdlib>,
|
||||
|
||||
/// FFI-ABI経由の外部API
|
||||
ffi_apis: HashMap<String, Arc<BidDefinition>>,
|
||||
|
||||
/// Nyashモジュール
|
||||
nyash_modules: HashMap<String, Arc<ExternalModule>>,
|
||||
|
||||
/// using imports(ファイル別)
|
||||
using_imports: Arc<RwLock<HashMap<String, UsingContext>>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct UsingContext {
|
||||
pub builtin_imports: Vec<String>, // ["nyashstd"]
|
||||
pub ffi_imports: Vec<String>, // ["console_api", "canvas_api"]
|
||||
pub module_imports: Vec<String>, // ["mylib", "utils"]
|
||||
pub file_id: String,
|
||||
}
|
||||
|
||||
impl UniversalNamespaceRegistry {
|
||||
pub fn new(nyash_link: &NyashLink) -> Result<Self, RegistryError> {
|
||||
let mut registry = UniversalNamespaceRegistry {
|
||||
builtin: Arc::new(BuiltinStdlib::new()),
|
||||
ffi_apis: HashMap::new(),
|
||||
nyash_modules: HashMap::new(),
|
||||
using_imports: Arc::new(RwLock::new(HashMap::new())),
|
||||
};
|
||||
|
||||
// nyash.linkからFFI-ABI定義読み込み
|
||||
registry.load_ffi_apis(nyash_link)?;
|
||||
|
||||
// Nyashモジュール読み込み
|
||||
registry.load_nyash_modules(nyash_link)?;
|
||||
|
||||
Ok(registry)
|
||||
}
|
||||
|
||||
/// 統合using文処理
|
||||
pub fn execute_using(&mut self, namespace_name: &str, file_id: &str)
|
||||
-> Result<(), RuntimeError> {
|
||||
|
||||
let context = self.using_imports
|
||||
.write().unwrap()
|
||||
.entry(file_id.to_string())
|
||||
.or_insert_with(|| UsingContext {
|
||||
builtin_imports: Vec::new(),
|
||||
ffi_imports: Vec::new(),
|
||||
module_imports: Vec::new(),
|
||||
file_id: file_id.to_string(),
|
||||
});
|
||||
|
||||
// 組み込み標準ライブラリ
|
||||
if self.builtin.has_namespace(namespace_name) {
|
||||
if !context.builtin_imports.contains(&namespace_name.to_string()) {
|
||||
context.builtin_imports.push(namespace_name.to_string());
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// FFI-ABI API
|
||||
if self.ffi_apis.contains_key(namespace_name) {
|
||||
if !context.ffi_imports.contains(&namespace_name.to_string()) {
|
||||
context.ffi_imports.push(namespace_name.to_string());
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Nyashモジュール
|
||||
if self.nyash_modules.contains_key(namespace_name) {
|
||||
if !context.module_imports.contains(&namespace_name.to_string()) {
|
||||
context.module_imports.push(namespace_name.to_string());
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
Err(RuntimeError::UndefinedNamespace(namespace_name.to_string()))
|
||||
}
|
||||
|
||||
/// 統合関数解決
|
||||
pub fn resolve_call(&self, file_id: &str, path: &[String])
|
||||
-> Result<CallTarget, RuntimeError> {
|
||||
|
||||
if path.len() != 2 {
|
||||
return Err(RuntimeError::InvalidQualifiedName(path.join(".")));
|
||||
}
|
||||
|
||||
let box_name = &path[0];
|
||||
let method_name = &path[1];
|
||||
|
||||
if let Ok(imports) = self.using_imports.read() {
|
||||
if let Some(context) = imports.get(file_id) {
|
||||
|
||||
// 1. 組み込み標準ライブラリ検索
|
||||
for namespace in &context.builtin_imports {
|
||||
if let Some(target) = self.builtin.resolve_call(namespace, box_name, method_name) {
|
||||
return Ok(CallTarget::Builtin(target));
|
||||
}
|
||||
}
|
||||
|
||||
// 2. FFI-ABI API検索
|
||||
for namespace in &context.ffi_imports {
|
||||
if let Some(bid) = self.ffi_apis.get(namespace) {
|
||||
if let Some(target) = bid.resolve_method(box_name, method_name) {
|
||||
return Ok(CallTarget::FfiAbi(target));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Nyashモジュール検索
|
||||
for namespace in &context.module_imports {
|
||||
if let Some(module) = self.nyash_modules.get(namespace) {
|
||||
if let Some(target) = module.resolve_method(box_name, method_name) {
|
||||
return Ok(CallTarget::NyashModule(target));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Err(RuntimeError::UndefinedMethod(format!("{}.{}", box_name, method_name)))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum CallTarget {
|
||||
Builtin(BuiltinMethodTarget),
|
||||
FfiAbi(FfiMethodTarget),
|
||||
NyashModule(NyashMethodTarget),
|
||||
}
|
||||
```
|
||||
|
||||
### 3. MIRレベル統合
|
||||
|
||||
#### **MIR命令拡張**
|
||||
```rust
|
||||
// src/mir/instruction.rs拡張
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum MirInstruction {
|
||||
// 既存命令...
|
||||
|
||||
// === 統合関数呼び出し ===
|
||||
|
||||
/// 組み込み標準ライブラリ呼び出し
|
||||
BuiltinCall {
|
||||
target: String, // "string.upper"
|
||||
args: Vec<ValueId>,
|
||||
result: ValueId,
|
||||
effect: Effect,
|
||||
},
|
||||
|
||||
/// FFI-ABI外部API呼び出し
|
||||
ExternCall {
|
||||
interface: String, // "console_api.console"
|
||||
method: String, // "log"
|
||||
args: Vec<ValueId>,
|
||||
result: Option<ValueId>,
|
||||
effect: Effect,
|
||||
bid_signature: BidMethodSignature,
|
||||
},
|
||||
|
||||
/// Nyashモジュール関数呼び出し
|
||||
ModuleCall {
|
||||
module: String, // "mylib"
|
||||
function: String, // "processData"
|
||||
args: Vec<ValueId>,
|
||||
result: ValueId,
|
||||
effect: Effect,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Effect {
|
||||
Pure, // 副作用なし、並び替え可能
|
||||
Mut, // 同リソース内で順序保持
|
||||
Io, // プログラム順序保持
|
||||
Control, // 制御フロー影響
|
||||
}
|
||||
```
|
||||
|
||||
#### **MIR生成統合**
|
||||
```rust
|
||||
// src/mir/builder.rs拡張
|
||||
impl MirBuilder {
|
||||
pub fn build_unified_call(&mut self, target: CallTarget, args: Vec<ValueId>)
|
||||
-> Result<ValueId, MirError> {
|
||||
|
||||
match target {
|
||||
CallTarget::Builtin(builtin_target) => {
|
||||
let result = self.new_value_id();
|
||||
self.emit(MirInstruction::BuiltinCall {
|
||||
target: builtin_target.qualified_name(),
|
||||
args,
|
||||
result,
|
||||
effect: builtin_target.effect(),
|
||||
});
|
||||
Ok(result)
|
||||
},
|
||||
|
||||
CallTarget::FfiAbi(ffi_target) => {
|
||||
let result = if ffi_target.returns_void() {
|
||||
None
|
||||
} else {
|
||||
Some(self.new_value_id())
|
||||
};
|
||||
|
||||
self.emit(MirInstruction::ExternCall {
|
||||
interface: ffi_target.interface_name(),
|
||||
method: ffi_target.method_name(),
|
||||
args,
|
||||
result,
|
||||
effect: ffi_target.effect(),
|
||||
bid_signature: ffi_target.signature().clone(),
|
||||
});
|
||||
|
||||
result.ok_or(MirError::VoidReturn)
|
||||
},
|
||||
|
||||
CallTarget::NyashModule(module_target) => {
|
||||
let result = self.new_value_id();
|
||||
self.emit(MirInstruction::ModuleCall {
|
||||
module: module_target.module_name(),
|
||||
function: module_target.function_name(),
|
||||
args,
|
||||
result,
|
||||
effect: Effect::Io, // デフォルト
|
||||
});
|
||||
Ok(result)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. バックエンド統合実装
|
||||
|
||||
#### **VM実行統合**
|
||||
```rust
|
||||
// src/backend/vm.rs拡張
|
||||
impl VmBackend {
|
||||
pub fn execute_instruction(&mut self, instr: &MirInstruction)
|
||||
-> Result<(), VmError> {
|
||||
|
||||
match instr {
|
||||
MirInstruction::BuiltinCall { target, args, result, .. } => {
|
||||
let evaluated_args = self.evaluate_args(args)?;
|
||||
let output = self.builtin_executor.call(target, evaluated_args)?;
|
||||
self.set_value(*result, output);
|
||||
Ok(())
|
||||
},
|
||||
|
||||
MirInstruction::ExternCall { interface, method, args, result, bid_signature, .. } => {
|
||||
// VM環境ではスタブ実装
|
||||
let evaluated_args = self.evaluate_args(args)?;
|
||||
let output = self.extern_stub.call(interface, method, evaluated_args, bid_signature)?;
|
||||
if let Some(res_id) = result {
|
||||
self.set_value(*res_id, output);
|
||||
}
|
||||
Ok(())
|
||||
},
|
||||
|
||||
MirInstruction::ModuleCall { module, function, args, result, .. } => {
|
||||
let evaluated_args = self.evaluate_args(args)?;
|
||||
let output = self.module_executor.call(module, function, evaluated_args)?;
|
||||
self.set_value(*result, output);
|
||||
Ok(())
|
||||
},
|
||||
|
||||
// 既存命令処理...
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### **WASM生成統合**
|
||||
```rust
|
||||
// src/backend/wasm/codegen.rs拡張
|
||||
impl WasmCodegen {
|
||||
pub fn generate_instruction(&mut self, instr: &MirInstruction)
|
||||
-> Result<(), WasmError> {
|
||||
|
||||
match instr {
|
||||
MirInstruction::BuiltinCall { target, args, result, .. } => {
|
||||
// 組み込み関数は直接実装
|
||||
self.generate_builtin_call(target, args, *result)
|
||||
},
|
||||
|
||||
MirInstruction::ExternCall { interface, method, args, bid_signature, .. } => {
|
||||
// BIDから自動生成されたWASM import呼び出し
|
||||
let import_name = format!("{}_{}",
|
||||
interface.replace(".", "_"),
|
||||
method
|
||||
);
|
||||
|
||||
self.generate_extern_call(&import_name, args, bid_signature)
|
||||
},
|
||||
|
||||
MirInstruction::ModuleCall { module, function, args, result, .. } => {
|
||||
// 内部関数呼び出し
|
||||
let function_name = format!("{}_{}", module, function);
|
||||
self.generate_function_call(&function_name, args, *result)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// BIDからWASM RuntimeImports自動生成
|
||||
pub fn generate_runtime_imports(&mut self, bid_definitions: &[BidDefinition])
|
||||
-> Result<String, WasmError> {
|
||||
|
||||
let mut imports = String::new();
|
||||
|
||||
for bid in bid_definitions {
|
||||
for interface in &bid.interfaces {
|
||||
for method in &interface.methods {
|
||||
let import_name = format!("{}_{}",
|
||||
interface.name.replace(".", "_"),
|
||||
method.name
|
||||
);
|
||||
|
||||
let signature = self.bid_to_wasm_signature(&method.params, &method.returns)?;
|
||||
imports.push_str(&format!(
|
||||
"(import \"env\" \"{}\" {})\n",
|
||||
import_name, signature
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(imports)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### **AOT生成統合**
|
||||
```rust
|
||||
// src/backend/aot/compiler.rs拡張
|
||||
impl AotCompiler {
|
||||
pub fn compile_instruction(&mut self, instr: &MirInstruction)
|
||||
-> Result<(), AotError> {
|
||||
|
||||
match instr {
|
||||
MirInstruction::ExternCall { interface, method, args, bid_signature, .. } => {
|
||||
// LLVM IR外部関数宣言生成
|
||||
let extern_func_name = format!("{}_{}",
|
||||
interface.replace(".", "_"),
|
||||
method
|
||||
);
|
||||
|
||||
let signature = self.bid_to_llvm_signature(bid_signature)?;
|
||||
self.declare_external_function(&extern_func_name, &signature)?;
|
||||
self.generate_call(&extern_func_name, args)?;
|
||||
|
||||
Ok(())
|
||||
},
|
||||
|
||||
// その他の命令処理...
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🎯 段階的実装戦略
|
||||
|
||||
### Phase 0: 基盤統合(2-3週間)
|
||||
1. **UniversalNamespaceRegistry実装** - 全API統一管理
|
||||
2. **nyash.link拡張** - BID依存関係サポート
|
||||
3. **統合using文** - 3種類のAPI統一インポート
|
||||
|
||||
### Phase 1: FFI-ABI統合(3-4週間)
|
||||
1. **BID読み込み機能** - YAML解析・検証
|
||||
2. **MIR ExternCall統合** - FFI-ABI→MIR変換
|
||||
3. **WASM RuntimeImports自動生成** - BID→WASM import
|
||||
|
||||
### Phase 2: 完全統合(4-6週間)
|
||||
1. **全バックエンド対応** - VM/WASM/AOT統合実装
|
||||
2. **エラーハンドリング統合** - 統一エラーモデル
|
||||
3. **パフォーマンス最適化** - 高速名前解決
|
||||
|
||||
## 🧪 統合テスト戦略
|
||||
|
||||
### 基本統合テスト
|
||||
```nyash
|
||||
# test_universal_integration.nyash
|
||||
using nyashstd
|
||||
using console_api
|
||||
using mylib
|
||||
|
||||
# 3種類のAPIが同じように使える
|
||||
assert(string.upper("test") == "TEST") # 組み込み
|
||||
console.log("Integration test successful") # FFI-ABI
|
||||
assert(mylib.process("data") == "processed") # Nyash
|
||||
```
|
||||
|
||||
### FFI-ABI統合テスト
|
||||
```nyash
|
||||
# test_ffi_abi_integration.nyash
|
||||
using canvas_api
|
||||
|
||||
# Canvas API経由での描画
|
||||
canvas.fillRect("game-canvas", 10, 10, 100, 100, "red")
|
||||
canvas.fillText("game-canvas", "Score: 100", 10, 30, "16px Arial", "white")
|
||||
```
|
||||
|
||||
## 🌟 期待される革命的効果
|
||||
|
||||
### 🚀 開発者体験
|
||||
- **統一API**: 組み込み・外部・自作すべて同じ書き方
|
||||
- **IDE補完**: すべてのAPIが`ny`で補完される
|
||||
- **エラー処理**: 統一エラーモデルで一貫性
|
||||
|
||||
### 🏗️ アーキテクチャ
|
||||
- **MIRレベル統合**: 全バックエンドで同じパフォーマンス最適化
|
||||
- **Effect System**: pure/mut/io/controlによる安全性保証
|
||||
- **言語非依存**: BIDによる外部ライブラリ標準化
|
||||
|
||||
### 🌍 エコシステム
|
||||
- **なんでもAPI**: あらゆる外部ライブラリがNyashから使える
|
||||
- **バックエンド統一**: 同じコードがVM/WASM/AOTで動作
|
||||
- **将来拡張**: パッケージレジストリでBID共有
|
||||
|
||||
---
|
||||
|
||||
**🎉 この統合設計で、Nyashが真に「なんでもできる」モダン言語になるにゃ!🚀🐱**
|
||||
@ -1,392 +0,0 @@
|
||||
# 🚀 Phase 9.75D 段階的移行計画
|
||||
|
||||
## 📅 移行期間: 2025-08-15 〜 2025-08-22 (7日間)
|
||||
## 🎯 目標: clone_box() vs share_box() 責務分離完全実装
|
||||
|
||||
## 📋 **移行フェーズ概要**
|
||||
|
||||
| フェーズ | 期間 | 内容 | リスク |
|
||||
|---------|------|------|-------|
|
||||
| **Phase A** | 1日 | 基盤整備・トレイト拡張 | 低 |
|
||||
| **Phase B** | 2日 | ArrayBox修正・コアテスト | 中 |
|
||||
| **Phase C** | 2日 | 主要ステートフルBox展開 | 中 |
|
||||
| **Phase D** | 1日 | バックエンド横展開 | 高 |
|
||||
| **Phase E** | 1日 | 残りBox・最終検証 | 低 |
|
||||
|
||||
## 🔧 **Phase A: 基盤整備 (Day 1)**
|
||||
|
||||
### **目標**: コンパイル可能な基盤構築
|
||||
|
||||
### **A1: NyashBoxトレイト拡張**
|
||||
**ファイル**: `src/boxes/traits.rs`
|
||||
|
||||
```rust
|
||||
// 追加するメソッド
|
||||
trait NyashBox: Send + Sync + BoxCore + DynClone + Any {
|
||||
// ... 既存メソッド ...
|
||||
|
||||
/// 状態を共有する新しいハンドルを作成
|
||||
/// 変数アクセス・代入時に使用
|
||||
fn share_box(&self) -> Box<dyn NyashBox>;
|
||||
}
|
||||
```
|
||||
|
||||
### **A2: 全Box型への仮実装追加**
|
||||
**対象ファイル**: 以下の20個のBox実装
|
||||
```
|
||||
src/boxes/array/mod.rs ← 最重要
|
||||
src/boxes/map_box.rs
|
||||
src/boxes/string_box.rs
|
||||
src/boxes/integer_box.rs
|
||||
src/boxes/bool_box.rs
|
||||
src/boxes/socket_box.rs
|
||||
src/boxes/p2p_box.rs
|
||||
src/boxes/file/mod.rs
|
||||
src/boxes/stream/mod.rs
|
||||
src/boxes/http_server_box.rs
|
||||
src/boxes/simple_intent_box.rs
|
||||
src/boxes/intent_box.rs
|
||||
src/boxes/egui_box.rs
|
||||
src/boxes/random_box.rs
|
||||
src/boxes/debug_box.rs
|
||||
src/boxes/future/mod.rs
|
||||
src/boxes/json/mod.rs
|
||||
src/boxes/http/mod.rs
|
||||
src/boxes/regex/mod.rs
|
||||
src/boxes/buffer/mod.rs
|
||||
```
|
||||
|
||||
**仮実装コード**:
|
||||
```rust
|
||||
impl NyashBox for XxxBox {
|
||||
// ... 既存メソッド ...
|
||||
|
||||
/// 仮実装: clone_boxと同じ(後で正しく修正)
|
||||
fn share_box(&self) -> Box<dyn NyashBox> {
|
||||
self.clone_box()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### **A3: コンパイル確認**
|
||||
```bash
|
||||
cargo check --lib
|
||||
cargo build --lib -j32
|
||||
```
|
||||
|
||||
**完了条件**: 全ての型チェックエラーが解消され、コンパイル成功
|
||||
|
||||
---
|
||||
|
||||
## 🎯 **Phase B: ArrayBox修正・コアテスト (Day 2-3)**
|
||||
|
||||
### **目標**: 状態保持問題の直接解決
|
||||
|
||||
### **B1: ArrayBox構造体修正**
|
||||
**ファイル**: `src/boxes/array/mod.rs`
|
||||
|
||||
```rust
|
||||
// 現在の構造体
|
||||
pub struct ArrayBox {
|
||||
pub items: RwLock<Vec<Box<dyn NyashBox>>>,
|
||||
base: BoxBase,
|
||||
}
|
||||
|
||||
// 修正後の構造体
|
||||
pub struct ArrayBox {
|
||||
pub items: Arc<RwLock<Vec<Box<dyn NyashBox>>>>, // Arc追加
|
||||
base: BoxBase,
|
||||
}
|
||||
```
|
||||
|
||||
### **B2: ArrayBox::new()修正**
|
||||
```rust
|
||||
impl ArrayBox {
|
||||
pub fn new() -> Self {
|
||||
ArrayBox {
|
||||
items: Arc::new(RwLock::new(Vec::new())), // Arc::new追加
|
||||
base: BoxBase::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_with_elements(elements: Vec<Box<dyn NyashBox>>) -> Self {
|
||||
ArrayBox {
|
||||
items: Arc::new(RwLock::new(elements)), // Arc::new追加
|
||||
base: BoxBase::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### **B3: ArrayBox::share_box()正しい実装**
|
||||
```rust
|
||||
impl NyashBox for ArrayBox {
|
||||
fn share_box(&self) -> Box<dyn NyashBox> {
|
||||
let new_instance = ArrayBox {
|
||||
items: Arc::clone(&self.items), // 🎯 状態共有
|
||||
base: BoxBase::new(), // 新しいID
|
||||
};
|
||||
Box::new(new_instance)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### **B4: ArrayBox::Clone修正**
|
||||
```rust
|
||||
impl Clone for ArrayBox {
|
||||
fn clone(&self) -> Self {
|
||||
let items_guard = self.items.read().unwrap();
|
||||
let cloned_items: Vec<Box<dyn NyashBox>> = items_guard.iter()
|
||||
.map(|item| item.clone_box())
|
||||
.collect();
|
||||
|
||||
ArrayBox {
|
||||
items: Arc::new(RwLock::new(cloned_items)), // 新しいArc
|
||||
base: BoxBase::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### **B5: インタープリター修正**
|
||||
**ファイル**: `src/interpreter/expressions.rs`
|
||||
|
||||
```rust
|
||||
// Line 108周辺
|
||||
ASTNode::Variable { name, .. } => {
|
||||
let shared_var = self.resolve_variable(name)?;
|
||||
Ok((*shared_var).share_box()) // clone_box() → share_box()
|
||||
}
|
||||
|
||||
// 他のclone_box()呼び出し箇所も確認・修正
|
||||
```
|
||||
|
||||
### **B6: 状態保持テスト追加**
|
||||
**ファイル**: `tests/array_state_sharing_test.rs` (新規作成)
|
||||
|
||||
```rust
|
||||
#[test]
|
||||
fn test_arraybox_state_sharing_after_push() {
|
||||
// 問題再現テスト
|
||||
let mut interpreter = Interpreter::new();
|
||||
let program = r#"
|
||||
arr = new ArrayBox()
|
||||
arr.push("hello")
|
||||
result = arr.length()
|
||||
"#;
|
||||
|
||||
let result = interpreter.execute_program(program).unwrap();
|
||||
// 1を返すことを確認(0ではない)
|
||||
assert_eq!(extract_integer(result), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_arraybox_share_vs_clone() {
|
||||
let arr1 = ArrayBox::new();
|
||||
arr1.push(StringBox::new("hello"));
|
||||
|
||||
// share_box: 状態共有
|
||||
let arr2 = arr1.share_box();
|
||||
let arr2_array = arr2.as_any().downcast_ref::<ArrayBox>().unwrap();
|
||||
assert_eq!(arr2_array.len(), 1);
|
||||
|
||||
// clone_box: 独立
|
||||
let arr3 = arr1.clone_box();
|
||||
let arr3_array = arr3.as_any().downcast_ref::<ArrayBox>().unwrap();
|
||||
arr1.push(StringBox::new("world"));
|
||||
assert_eq!(arr3_array.len(), 1); // 影響なし
|
||||
}
|
||||
```
|
||||
|
||||
### **B7: テスト実行・修正**
|
||||
```bash
|
||||
cargo test array_state_sharing_test
|
||||
./target/debug/nyash tests/array_debug.nyash
|
||||
```
|
||||
|
||||
**完了条件**: ArrayBoxの状態保持が正常に動作することを確認
|
||||
|
||||
---
|
||||
|
||||
## 📈 **Phase C: 主要ステートフルBox展開 (Day 4-5)**
|
||||
|
||||
### **目標**: 利用頻度の高いステートフルBox修正
|
||||
|
||||
### **C1: 優先順位リスト**
|
||||
1. **MapBox** - コレクション系、使用頻度大
|
||||
2. **SocketBox** - 既知の状態保持問題
|
||||
3. **P2PBox** - 複雑な状態管理
|
||||
4. **FileBox** - I/O状態管理
|
||||
5. **StreamBox** - バッファ状態
|
||||
|
||||
### **C2: MapBox修正**
|
||||
**ファイル**: `src/boxes/map_box.rs`
|
||||
|
||||
現在の構造確認→Arc追加→share_box()実装→テスト
|
||||
|
||||
### **C3: SocketBox修正**
|
||||
**ファイル**: `src/boxes/socket_box.rs`
|
||||
|
||||
既知の状態保持問題(is_server)を根本解決
|
||||
|
||||
### **C4: 各Box修正パターン**
|
||||
```rust
|
||||
// 共通パターン
|
||||
pub struct XxxBox {
|
||||
pub state_field: Arc<RwLock<StateType>>, // Arc追加
|
||||
base: BoxBase,
|
||||
}
|
||||
|
||||
impl NyashBox for XxxBox {
|
||||
fn share_box(&self) -> Box<dyn NyashBox> {
|
||||
let new_instance = XxxBox {
|
||||
state_field: Arc::clone(&self.state_field),
|
||||
base: BoxBase::new(),
|
||||
};
|
||||
Box::new(new_instance)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### **C5: 段階的テスト**
|
||||
各Box修正後に個別テスト実行
|
||||
|
||||
**完了条件**: 主要5個のステートフルBoxで状態保持が正常動作
|
||||
|
||||
---
|
||||
|
||||
## 🌐 **Phase D: バックエンド横展開 (Day 6)**
|
||||
|
||||
### **目標**: VM・WASMでの一貫性確保
|
||||
|
||||
### **D1: VM Backend確認**
|
||||
**ファイル**: `src/backend/vm.rs`
|
||||
|
||||
```bash
|
||||
# clone_box()呼び出し箇所を検索
|
||||
grep -n "clone_box" src/backend/vm.rs
|
||||
```
|
||||
|
||||
**Line 764周辺**: 配列要素アクセスの意図確認
|
||||
- 値コピーが必要→`clone_box()`維持
|
||||
- 参照共有が適切→`share_box()`に修正
|
||||
|
||||
### **D2: WASM Backend確認**
|
||||
**ファイル**: `src/backend/wasm/`
|
||||
|
||||
WASMの独自メモリ管理での`clone_box()`使用状況確認
|
||||
|
||||
### **D3: バックエンド別テスト**
|
||||
```bash
|
||||
# VM実行テスト
|
||||
./target/release/nyash --backend vm tests/array_debug.nyash
|
||||
|
||||
# WASM実行テスト
|
||||
./target/release/nyash --backend wasm tests/array_debug.nyash
|
||||
```
|
||||
|
||||
**完了条件**: 3バックエンド全てで一貫した動作確認
|
||||
|
||||
---
|
||||
|
||||
## 🎯 **Phase E: 残りBox・最終検証 (Day 7)**
|
||||
|
||||
### **目標**: 完全修正・リグレッション確認
|
||||
|
||||
### **E1: 残りステートフルBox修正**
|
||||
- HTTPServerBox, IntentBox, SimpleIntentBox
|
||||
- EguiBox, RandomBox, DebugBox
|
||||
- FutureBox, JSONBox, BufferBox
|
||||
|
||||
### **E2: 全体テスト実行**
|
||||
```bash
|
||||
# 基本機能テスト
|
||||
cargo test
|
||||
|
||||
# 実用アプリテスト
|
||||
./target/release/nyash app_dice_rpg.nyash
|
||||
./target/release/nyash app_statistics.nyash
|
||||
|
||||
# 性能テスト
|
||||
./target/release/nyash --benchmark --iterations 100
|
||||
```
|
||||
|
||||
### **E3: 性能確認**
|
||||
- WASM: 13.5倍高速化維持
|
||||
- VM: 20.4倍高速化維持
|
||||
- インタープリター: 状態保持正常化
|
||||
|
||||
### **E4: ドキュメント更新**
|
||||
- `CURRENT_TASK.md`: Phase 9.75D完了報告
|
||||
- `clone-box-vs-share-box-design.md`: 実装結果反映
|
||||
|
||||
**完了条件**: 全テスト通過・性能維持・ドキュメント完備
|
||||
|
||||
---
|
||||
|
||||
## 🚨 **リスク管理**
|
||||
|
||||
### **Phase A リスク (低)**
|
||||
- **コンパイルエラー**: 仮実装で対応済み
|
||||
- **対策**: 段階的なトレイト追加
|
||||
|
||||
### **Phase B リスク (中)**
|
||||
- **ArrayBox破壊**: 既存機能への影響
|
||||
- **対策**: 詳細なunit test、段階的修正
|
||||
|
||||
### **Phase C リスク (中)**
|
||||
- **複数Box同時破壊**: 相互依存の問題
|
||||
- **対策**: 1個ずつ修正・テスト
|
||||
|
||||
### **Phase D リスク (高)**
|
||||
- **バックエンド非互換**: VM・WASMでの動作不一致
|
||||
- **対策**: 各バックエンドでの詳細テスト
|
||||
|
||||
### **Phase E リスク (低)**
|
||||
- **パフォーマンス劣化**: Arc<RwLock>オーバーヘッド
|
||||
- **対策**: ベンチマークでの詳細測定
|
||||
|
||||
---
|
||||
|
||||
## 📊 **進捗追跡**
|
||||
|
||||
### **Daily Check List**
|
||||
|
||||
**Day 1 (Phase A)**:
|
||||
- [ ] NyashBoxトレイト拡張
|
||||
- [ ] 20個のBox型仮実装追加
|
||||
- [ ] cargo check成功
|
||||
|
||||
**Day 2-3 (Phase B)**:
|
||||
- [ ] ArrayBox構造体修正
|
||||
- [ ] share_box()正しい実装
|
||||
- [ ] インタープリター修正
|
||||
- [ ] 状態保持テスト追加・通過
|
||||
|
||||
**Day 4-5 (Phase C)**:
|
||||
- [ ] MapBox修正完了
|
||||
- [ ] SocketBox修正完了
|
||||
- [ ] P2PBox, FileBox, StreamBox修正完了
|
||||
|
||||
**Day 6 (Phase D)**:
|
||||
- [ ] VM Backend確認・修正
|
||||
- [ ] WASM Backend確認・修正
|
||||
- [ ] 3バックエンド一貫性確認
|
||||
|
||||
**Day 7 (Phase E)**:
|
||||
- [ ] 残り10個のBox修正完了
|
||||
- [ ] 全テスト通過
|
||||
- [ ] 性能ベンチマーク確認
|
||||
- [ ] ドキュメント更新
|
||||
|
||||
---
|
||||
|
||||
## 🎉 **成功条件**
|
||||
|
||||
1. **機能正常性**: ArrayBoxの状態保持問題が完全解決
|
||||
2. **一貫性**: 3バックエンド全てで同じセマンティクス
|
||||
3. **性能維持**: WASM 13.5倍、VM 20.4倍高速化維持
|
||||
4. **互換性**: 既存のNyashプログラムが正常動作
|
||||
5. **拡張性**: 新しいBox型追加時のガイドライン確立
|
||||
|
||||
**Phase 9.75D完了により、Nyashの状態管理が根本的に安定化し、Phase 9.5以降の開発が安心して進行可能になる。**
|
||||
Binary file not shown.
@ -1 +1 @@
|
||||
print("Simple test")
|
||||
static box Main { main() { return 42 } }
|
||||
|
||||
@ -1,35 +1,14 @@
|
||||
// 🧪 新Box作成テスト - メソッド呼び出しなし
|
||||
box SimpleBox {
|
||||
init { value }
|
||||
|
||||
pack(v) {
|
||||
me.value = v
|
||||
}
|
||||
}
|
||||
|
||||
print("=== New Box Creation Test ===")
|
||||
|
||||
// 📊 BufferBox Test
|
||||
print("🔹 Creating BufferBox...")
|
||||
local buffer
|
||||
buffer = new BufferBox()
|
||||
print("✅ BufferBox created successfully!")
|
||||
|
||||
// 🔍 RegexBox Test
|
||||
print("🔹 Creating RegexBox...")
|
||||
local regex
|
||||
regex = new RegexBox("[0-9]+")
|
||||
print("✅ RegexBox created successfully!")
|
||||
|
||||
// 📋 JSONBox Test
|
||||
print("🔹 Creating JSONBox...")
|
||||
local json
|
||||
json = new JSONBox("{\"name\": \"test\"}")
|
||||
print("✅ JSONBox created successfully!")
|
||||
|
||||
// 🌊 StreamBox Test
|
||||
print("🔹 Creating StreamBox...")
|
||||
local stream
|
||||
stream = new StreamBox()
|
||||
print("✅ StreamBox created successfully!")
|
||||
|
||||
// 🌐 HTTPClientBox Test
|
||||
print("🔹 Creating HTTPClientBox...")
|
||||
local http
|
||||
http = new HTTPClientBox()
|
||||
print("✅ HTTPClientBox created successfully!")
|
||||
|
||||
print("\n🎉 All Arc<Mutex> Boxes created successfully!")
|
||||
static box Main {
|
||||
main() {
|
||||
local obj = new SimpleBox(100)
|
||||
return 200
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user