feat: Complete internal field access identification for visibility system
- Add internal access tracking to distinguish me.field from external.field access - Interpreter correctly allows methods to access their own private fields - VM tracks object class context during method calls for visibility checks - Fix VM nested box declaration collection in collect_box_declarations - Both interpreter and VM now pass all visibility tests consistently Test results: - visibility_ok.nyash: ✅ Internal private access allowed in methods - visibility_error.nyash: ✅ External private access correctly blocked - All private fields accessible from within their own methods - Public fields remain accessible from anywhere 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
64
docs/reference/language/field-visibility-and-delegation.md
Normal file
64
docs/reference/language/field-visibility-and-delegation.md
Normal file
@ -0,0 +1,64 @@
|
||||
# フィールド可視性とデリゲーション設計(提案/仕様草案)
|
||||
|
||||
本書は Nyash 言語の「フィールド可視性」と「デリゲーション(from/override)」の設計をまとめた仕様草案です。実装は段階的に進めます。
|
||||
|
||||
## 1. フィールド可視性(Blocks)
|
||||
- 構文
|
||||
```nyash
|
||||
box User {
|
||||
private { age, passwordHash, internalCache }
|
||||
public { name, email, displayName }
|
||||
|
||||
init { name, email, displayName, age }
|
||||
// ... methods ...
|
||||
}
|
||||
```
|
||||
- ルール
|
||||
- `private`: box 内のメソッドからのみアクセス可(外部アクセス不可)
|
||||
- `public`: 外部から `obj.field` で参照可
|
||||
- いずれにも属さないフィールドはエラー(明示主義)
|
||||
- `me.field` は可視性に関わらず常に許可(自身の内部)
|
||||
- init は現状どおり public(将来 `public/private init` の導入は別途検討)
|
||||
- エラー例
|
||||
- 外部から `user.age` → Compile/Interpret Error: private field access
|
||||
- 親の private フィールド参照 → Error: parent private field not accessible
|
||||
|
||||
実装フェーズ(予定)
|
||||
1. パーサ: `private { ... }` / `public { ... }` の受理、AST/宣言モデルに可視性付与
|
||||
2. 解決/実行: 外部アクセス時に public のみ許可、`me.field` は常にOK
|
||||
3. MIR/VM: 既存の `RefGet/RefSet` に可視性チェックフックを追加
|
||||
|
||||
## 2. デリゲーション(from/override)
|
||||
目標: ビルトイン/プラグイン/ユーザー定義の全Boxで、同一の書き味(from/override/super呼び出し)を提供しつつ、安全性を担保する。
|
||||
|
||||
- 基本方針
|
||||
- 継承モデルは維持(「委譲の糖衣」ではない)
|
||||
- 親の内部フィールドは不可視(private は子からも見えない)
|
||||
- メソッド解決規則は統一:子の override → なければ親へ解決
|
||||
- 親がビルトイン/プラグインの場合、親メソッド呼び出しは `BoxCall` に lower(ローダ経由)
|
||||
|
||||
- 書式例
|
||||
```nyash
|
||||
box MyFile from FileBox {
|
||||
override write(x) {
|
||||
// 前処理
|
||||
from FileBox.write(x)
|
||||
// 後処理
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- 安全性
|
||||
- 親の状態は親の実体としてのみ存在(フィールド継承しない)
|
||||
- `from Parent.method()` は親タイプ名での明示ディスパッチ(暗黙の内包はしない)
|
||||
- MIR では `BoxCall` を生成し、VM/Interpreter はローダへ委譲
|
||||
|
||||
実装フェーズ(予定)
|
||||
1. MIR Lowering: 親がビルトイン/プラグインの `from` を常に `BoxCall` へ(現状踏襲)
|
||||
2. VM/Interpreter: 既存どおりローダ委譲(Handle/BoxRef を統一処理)
|
||||
|
||||
## 3. 参考
|
||||
- BoxRef/Handle 仕様: `docs/reference/plugin-system/boxref-behavior.md`
|
||||
- nyash.toml v2.1–v2.2: `docs/reference/plugin-system/nyash-toml-v2_1-spec.md`
|
||||
- 実装箇所(予定): `src/parser/declarations/box_definition.rs`, `src/core/model.rs`, `src/interpreter/expressions/access.rs`, `src/mir/*`, `src/backend/vm.rs`
|
||||
|
||||
53
docs/reference/plugin-system/boxref-behavior.md
Normal file
53
docs/reference/plugin-system/boxref-behavior.md
Normal file
@ -0,0 +1,53 @@
|
||||
# BoxRef/Handle Behavior (v2.1–v2.2)
|
||||
|
||||
本書は、プラグインBoxの引数/返り値としてのBox参照(BoxRef/Handle)の扱いと、VM/インタプリタ/ローダ/プラグインにまたがる設計上の注意点をまとめます。
|
||||
|
||||
## 1. TLV仕様(BID-1)
|
||||
- ヘッダ: `ver:u16=1, argc:u16`
|
||||
- エントリ: `tag:u8, rsv:u8=0, size:u16, payload...`
|
||||
- 主要タグ:
|
||||
- `6 = String(UTF-8)`, `7 = Bytes`
|
||||
- `8 = Handle(BoxRef)` → payload: `type_id:u32 + instance_id:u32`(計8バイト, LE)
|
||||
- `2 = I32`, `3 = I64`, `1 = Bool`, `9 = Void`
|
||||
|
||||
## 2. nyash.toml(v2.1〜)
|
||||
- 引数宣言に `args=[{ kind="box", category="plugin" }]` を追加可能。
|
||||
- 例:
|
||||
```toml
|
||||
[libraries."libnyash_filebox_plugin.so".FileBox.methods]
|
||||
copyFrom = { method_id = 7, args = [ { kind = "box", category = "plugin" } ] }
|
||||
cloneSelf = { method_id = 8 }
|
||||
```
|
||||
- ローダは `args` の型宣言に基づいて実引数を検証。型不一致は `InvalidArgs`。
|
||||
|
||||
## 3. 返り値(v2.2)
|
||||
- プラグインが `tag=8` を返した場合、ローダは `type_id` を `nyash.toml` で逆引きし、
|
||||
`PluginBoxV2 { box_type, type_id, invoke_fn, instance_id, fini_method_id }` を構築して返す。
|
||||
|
||||
## 4. VM/インタプリタの扱い
|
||||
- メソッド呼び出しはローダ経由に統一(TLV/Handle処理もローダ側)。
|
||||
- MIR Loweringは以下を厳守:
|
||||
- ユーザー定義Boxのみ関数化(Call)最適化可。
|
||||
- プラグイン/ビルトインは常に `BoxCall` を出す(VMでローダに委譲)。
|
||||
- VMのBoxRefは共有ハンドルとして扱う:
|
||||
- `clone_box()` ではなく `share_box()` を使用(不意のbirth回避)。
|
||||
|
||||
## 5. プラグイン実装の注意
|
||||
- `open` のモードによっては `read` ができない(例: "w")。`copyFrom` は `file.read` が失敗したら `buffer` にフォールバックする。
|
||||
- `write` 実装では、成功後に `buffer` を更新しておくと `copyFrom` のフォールバックで活きる。
|
||||
- 典型メソッドID(例: FileBox)
|
||||
- `0=birth`, `1=open`, `2=read`, `3=write`, `4=close`, `0xFFFFFFFF=fini`, `7=copyFrom`, `8=cloneSelf`
|
||||
|
||||
## 6. トラブルシュート
|
||||
- rc=-4 `Invalid arguments`
|
||||
- `args` 型宣言と実引数が不一致。ローダログの引数エンコードを確認(String化フォールバックが出ていないか)。
|
||||
- rc=-5 `Plugin internal error`
|
||||
- プラグイン内部のread/write/lock失敗など。`copyFrom` のfile→bufferフォールバック不備を疑う。
|
||||
- rc=-8 `Invalid handle`
|
||||
- 存在しない `instance_id` に対する呼び出し。VMで `clone_box` を使っていないか(`share_box` へ)。
|
||||
|
||||
## 7. 参考
|
||||
- 仕様: `docs/reference/plugin-system/nyash-toml-v2_1-spec.md`
|
||||
- 実装: `src/runtime/plugin_loader_v2.rs`(引数検証/Handle戻り値復元)
|
||||
- 例: `docs/examples/plugin_boxref_return.nyash`
|
||||
|
||||
Reference in New Issue
Block a user