- Keep essential information within 500 lines (now 395 lines) - Maintain important syntax examples and development principles - Move detailed information to appropriate docs files: - Development practices → docs/guides/development-practices.md - Testing guide → docs/guides/testing-guide.md - Claude issues → docs/tools/claude-issues.md - Add proper links to all referenced documentation - Balance between minimal entry point and practical usability
231 lines
5.7 KiB
Markdown
231 lines
5.7 KiB
Markdown
# Technical Details
|
||
|
||
## 1. ライフサイクル設計の詳細
|
||
|
||
### 1.1 所有権の森(Ownership Forest)
|
||
|
||
```
|
||
A (strong owner)
|
||
├── B (strong)
|
||
│ └── D (strong)
|
||
└── C (strong)
|
||
└── E (weak) → B
|
||
```
|
||
|
||
**不変条件**:
|
||
- 各ノードの強参照in-degreeは最大1
|
||
- weakエッジは所有権に関与しない
|
||
- サイクルはweakエッジでのみ許可
|
||
|
||
### 1.2 決定的破棄順序
|
||
|
||
```rust
|
||
// ScopeTrackerの実装
|
||
impl ScopeTracker {
|
||
fn exit_scope(&mut self) {
|
||
// LIFO順で破棄
|
||
while let Some(box_id) = self.scope_stack.pop() {
|
||
if let Some(pbox) = self.get_box(box_id) {
|
||
// finiを呼ぶ
|
||
pbox.call_fini();
|
||
}
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
## 2. プラグインシステムの実装
|
||
|
||
### 2.1 TLVエンコーディング
|
||
|
||
```rust
|
||
// Type定義
|
||
const TLV_BOOL: u16 = 1; // 1 byte: 0 or 1
|
||
const TLV_I64: u16 = 3; // 8 bytes: little endian
|
||
const TLV_STRING: u16 = 4; // n bytes: UTF-8
|
||
const TLV_HANDLE: u16 = 8; // 8 bytes: type_id(4) + instance_id(4)
|
||
const TLV_VOID: u16 = 9; // 0 bytes
|
||
|
||
// エンコード例
|
||
fn encode_string(s: &str) -> Vec<u8> {
|
||
let mut buf = vec![];
|
||
buf.extend(&TLV_STRING.to_le_bytes());
|
||
buf.extend(&(s.len() as u16).to_le_bytes());
|
||
buf.extend(s.as_bytes());
|
||
buf
|
||
}
|
||
```
|
||
|
||
### 2.2 プラグイン実装例(StringBox)
|
||
|
||
```rust
|
||
// StringBoxプラグイン
|
||
struct StringInstance {
|
||
data: String,
|
||
}
|
||
|
||
static INSTANCES: Lazy<Mutex<HashMap<u32, StringInstance>>> =
|
||
Lazy::new(|| Mutex::new(HashMap::new()));
|
||
|
||
#[no_mangle]
|
||
extern "C" fn nyash_plugin_invoke(
|
||
type_id: u32,
|
||
method_id: u32,
|
||
instance_id: u32,
|
||
args: *const u8,
|
||
args_len: usize,
|
||
result: *mut u8,
|
||
result_len: *mut usize,
|
||
) -> i32 {
|
||
match method_id {
|
||
METHOD_BIRTH => {
|
||
// 新しいインスタンス作成
|
||
let inst = StringInstance {
|
||
data: String::new(),
|
||
};
|
||
let id = INSTANCE_COUNTER.fetch_add(1, Ordering::SeqCst);
|
||
INSTANCES.lock().unwrap().insert(id, inst);
|
||
write_tlv_handle(type_id, id, result, result_len)
|
||
}
|
||
METHOD_LENGTH => {
|
||
// 文字列長を返す
|
||
let instances = INSTANCES.lock().unwrap();
|
||
if let Some(inst) = instances.get(&instance_id) {
|
||
let len = inst.data.len() as i64;
|
||
write_tlv_i64(len, result, result_len)
|
||
} else {
|
||
NYB_E_INVALID_HANDLE
|
||
}
|
||
}
|
||
METHOD_FINI => {
|
||
// インスタンス破棄(Dropが自動実行)
|
||
INSTANCES.lock().unwrap().remove(&instance_id);
|
||
NYB_OK
|
||
}
|
||
_ => NYB_E_INVALID_METHOD,
|
||
}
|
||
}
|
||
```
|
||
|
||
## 3. JIT統合
|
||
|
||
### 3.1 プラグイン呼び出しのJITコンパイル
|
||
|
||
```rust
|
||
// LowerCoreでのプラグイン呼び出し生成
|
||
fn lower_box_call(&mut self, method: &str, args: &[ValueId]) {
|
||
if let Ok(h) = plugin_host.resolve_method("StringBox", method) {
|
||
// スタックに引数を積む
|
||
self.builder.emit_param_i64(receiver_idx);
|
||
for arg in args {
|
||
self.push_value(arg);
|
||
}
|
||
|
||
// プラグイン呼び出し命令を生成
|
||
self.builder.emit_plugin_invoke(
|
||
h.type_id,
|
||
h.method_id,
|
||
args.len() + 1,
|
||
has_return
|
||
);
|
||
}
|
||
}
|
||
```
|
||
|
||
### 3.2 Craneliftでのコード生成
|
||
|
||
```rust
|
||
// nyash_plugin_invoke3_i64 シムの実装
|
||
extern "C" fn nyash_plugin_invoke3_i64(
|
||
type_id: i64,
|
||
method_id: i64,
|
||
argc: i64,
|
||
a0: i64, // receiver (param index)
|
||
a1: i64, // arg1
|
||
a2: i64, // arg2
|
||
) -> i64 {
|
||
// レシーバーをVMの引数から解決
|
||
let instance_id = resolve_instance_from_vm_args(a0);
|
||
|
||
// TLVエンコードで引数準備
|
||
let mut tlv_args = encode_tlv_header(argc - 1);
|
||
if argc >= 2 { encode_i64(&mut tlv_args, a1); }
|
||
if argc >= 3 { encode_i64(&mut tlv_args, a2); }
|
||
|
||
// プラグイン呼び出し
|
||
let mut result = [0u8; 32];
|
||
let mut result_len = result.len();
|
||
let rc = invoke_plugin(
|
||
type_id as u32,
|
||
method_id as u32,
|
||
instance_id,
|
||
&tlv_args,
|
||
&mut result,
|
||
&mut result_len
|
||
);
|
||
|
||
// 結果をデコードして返す
|
||
decode_tlv_i64(&result[..result_len]).unwrap_or(0)
|
||
}
|
||
```
|
||
|
||
## 4. GCオン/オフ等価性
|
||
|
||
### 4.1 アノテーション処理
|
||
|
||
```rust
|
||
enum BoxAnnotation {
|
||
MustDrop, // @must_drop - 即時破棄必須
|
||
GCable, // @gcable - GC可能(遅延OK)
|
||
}
|
||
|
||
impl GarbageCollector {
|
||
fn should_collect(&self, box_type: &BoxType) -> bool {
|
||
match box_type.annotation {
|
||
BoxAnnotation::MustDrop => false, // GC対象外
|
||
BoxAnnotation::GCable => self.gc_enabled,
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### 4.2 観測不可能性の保証
|
||
|
||
```rust
|
||
// テストケース:GCオン/オフで同じ結果
|
||
#[test]
|
||
fn test_gc_equivalence() {
|
||
let output_gc_on = run_with_gc(true, "test.nyash");
|
||
let output_gc_off = run_with_gc(false, "test.nyash");
|
||
|
||
assert_eq!(output_gc_on.io_trace, output_gc_off.io_trace);
|
||
assert_eq!(output_gc_on.result, output_gc_off.result);
|
||
}
|
||
```
|
||
|
||
## 5. 静的リンクによる最適化
|
||
|
||
### 5.1 AOT変換
|
||
|
||
```bash
|
||
# NyashからCLIFへ
|
||
nyashc --emit-clif program.nyash > program.clif
|
||
|
||
# CLIFからオブジェクトファイルへ
|
||
cranelift-objdump program.clif -o program.o
|
||
|
||
# 静的リンク(PLT回避)
|
||
cc program.o -static \
|
||
-L. -lnyrt \
|
||
-lnyplug_array \
|
||
-lnyplug_string \
|
||
-o program
|
||
```
|
||
|
||
### 5.2 パフォーマンス比較
|
||
|
||
```
|
||
動的リンク(PLT経由): ~15ns/call
|
||
静的リンク(直接呼出): ~2ns/call
|
||
インライン展開後: ~0.5ns/call
|
||
``` |