builder/vm: stabilize json_lint_vm under unified calls
- Fix condition_fn resolution: Value call path + dev safety + stub injection - VM bridge: handle Method::birth via BoxCall; ArrayBox push/get/length/set direct bridge - Receiver safety: pin receiver in method_call_handlers to avoid undefined use across blocks - Local vars: materialize on declaration (use init ValueId; void for uninit) - Prefer legacy BoxCall for Array/Map/String/user boxes in emit_box_or_plugin_call (stability-first) - Test runner: update LLVM hint to llvmlite harness (remove LLVM_SYS_180_PREFIX guidance) - Docs/roadmap: update CURRENT_TASK with unified default-ON + guards Note: NYASH_DEV_BIRTH_INJECT_BUILTINS=1 can re-enable builtin birth() injection during migration.
This commit is contained in:
@ -1,172 +1,14 @@
|
||||
# Nyash JSON Native
|
||||
Layer Guard — json_native
|
||||
|
||||
> yyjson(C依存)→ 完全Nyash実装で外部依存完全排除
|
||||
Scope and responsibility
|
||||
- This layer implements a minimal native JSON library in Ny.
|
||||
- Responsibilities: scanning, tokenizing, and parsing JSON; building node structures.
|
||||
- Forbidden: runtime/VM specifics, code generation, non‑JSON language concerns.
|
||||
|
||||
## 🎯 プロジェクト目標
|
||||
Imports policy (SSOT)
|
||||
- Dev/CI: file-using allowed for development convenience.
|
||||
- Prod: use only `nyash.toml` using entries (no ad‑hoc file imports).
|
||||
|
||||
- **C依存ゼロ**: yyjsonからの完全脱却
|
||||
- **Everything is Box**: 全てをNyash Boxで実装
|
||||
- **80/20ルール**: 動作優先、最適化は後
|
||||
- **段階切り替え**: `NYASH_JSON_PROVIDER=nyash|yyjson|serde`
|
||||
|
||||
## 📦 アーキテクチャ設計
|
||||
|
||||
### 🔍 yyjson分析結果
|
||||
```c
|
||||
// yyjson核心設計パターン
|
||||
struct yyjson_val {
|
||||
uint64_t tag; // 型+サブタイプ+長さ
|
||||
yyjson_val_uni uni; // ペイロード(union)
|
||||
};
|
||||
```
|
||||
|
||||
### 🎨 Nyash版設計 (Everything is Box)
|
||||
```nyash
|
||||
// 🌟 JSON値を表現するBox
|
||||
box JsonNode {
|
||||
kind: StringBox // "null"|"bool"|"int"|"string"|"array"|"object"
|
||||
value: Box // 実際の値(種類に応じて)
|
||||
children: ArrayBox // 配列・オブジェクト用(オプション)
|
||||
keys: ArrayBox // オブジェクトのキー配列(オプション)
|
||||
}
|
||||
|
||||
// 🔧 JSON字句解析器
|
||||
box JsonLexer {
|
||||
text: StringBox // 入力文字列
|
||||
pos: IntegerBox // 現在位置
|
||||
tokens: ArrayBox // トークン配列
|
||||
}
|
||||
|
||||
// 🏗️ JSON構文解析器
|
||||
box JsonParser {
|
||||
lexer: JsonLexer // 字句解析器
|
||||
current: IntegerBox // 現在のトークン位置
|
||||
}
|
||||
```
|
||||
|
||||
## 📂 ファイル構造
|
||||
|
||||
```
|
||||
apps/lib/json_native/
|
||||
├── README.md # この設計ドキュメント
|
||||
├── lexer.nyash # JSON字句解析器(状態機械ベース)
|
||||
├── parser.nyash # JSON構文解析器(再帰下降)
|
||||
├── node.nyash # JsonNode実装(Everything is Box)
|
||||
├── tests/ # テストケース
|
||||
│ ├── lexer_test.nyash
|
||||
│ ├── parser_test.nyash
|
||||
│ └── integration_test.nyash
|
||||
└── examples/ # 使用例
|
||||
├── simple_parse.nyash
|
||||
└── complex_object.nyash
|
||||
```
|
||||
|
||||
## 🎯 実装戦略
|
||||
|
||||
### Phase 1: JsonNode基盤(1週目)
|
||||
- [x] JsonNode Box実装
|
||||
- [x] 基本的な値型サポート(null, bool, int, string)
|
||||
- [x] 配列・オブジェクト構造サポート
|
||||
|
||||
### Phase 2: JsonLexer実装(2週目)
|
||||
- [ ] トークナイザー実装(状態機械ベース)
|
||||
- [ ] エラーハンドリング
|
||||
- [ ] 位置情報追跡
|
||||
|
||||
### Phase 3: JsonParser実装(3週目)
|
||||
- [ ] 再帰下降パーサー実装
|
||||
- [ ] JsonNode構築
|
||||
- [ ] ネストされた構造サポート
|
||||
|
||||
### Phase 4: 統合&最適化(4週目)
|
||||
- [ ] C ABI Bridge(最小実装)
|
||||
- [ ] 既存JSONBoxとの互換性
|
||||
- [ ] 性能測定・最適化
|
||||
|
||||
## 🔄 既存システムとの統合
|
||||
|
||||
### 段階的移行戦略
|
||||
```bash
|
||||
# 環境変数で切り替え
|
||||
export NYASH_JSON_PROVIDER=nyash # 新実装
|
||||
export NYASH_JSON_PROVIDER=yyjson # 既存C実装
|
||||
export NYASH_JSON_PROVIDER=serde # Rust実装
|
||||
```
|
||||
|
||||
### 既存APIとの互換性
|
||||
```nyash
|
||||
// 既存JSONBox APIを維持
|
||||
local json = new JSONBox()
|
||||
json.parse("{\"key\": \"value\"}") // 内部でNyash実装を使用
|
||||
```
|
||||
|
||||
## 🎨 設計思想
|
||||
|
||||
### Everything is Box原則
|
||||
- **JsonNode**: 完全なBox実装
|
||||
- **境界明確化**: 各コンポーネントをBox化
|
||||
- **差し替え可能**: プロバイダー切り替え対応
|
||||
|
||||
### 80/20ルール適用
|
||||
- **80%**: まず動く実装(文字列操作ベース)
|
||||
- **20%**: 後で最適化(バイナリ処理、SIMD等)
|
||||
|
||||
### フォールバック戦略
|
||||
- **エラー時**: 既存実装に安全復帰
|
||||
- **性能不足時**: yyjsonに切り替え可能
|
||||
- **互換性**: 既存APIを100%維持
|
||||
|
||||
## 🧪 テスト戦略
|
||||
|
||||
### 基本テストケース
|
||||
```json
|
||||
{"null": null}
|
||||
{"bool": true}
|
||||
{"int": 42}
|
||||
{"string": "hello"}
|
||||
{"array": [1,2,3]}
|
||||
{"object": {"nested": "value"}}
|
||||
```
|
||||
|
||||
### エラーケース
|
||||
```
|
||||
{invalid} // 不正なJSON
|
||||
{"unclosed": "str // 閉じられていない文字列
|
||||
[1,2, // 不完全な配列
|
||||
```
|
||||
|
||||
### 性能テストケース
|
||||
```
|
||||
大きなJSONファイル(10MB+)
|
||||
深くネストされた構造(100レベル+)
|
||||
多数の小さなオブジェクト(10万個+)
|
||||
```
|
||||
|
||||
## 🚀 実行例
|
||||
|
||||
```nyash
|
||||
// 基本的な使用例
|
||||
using "apps/lib/json_native/node.nyash" as JsonNative
|
||||
|
||||
// JSON文字列をパース
|
||||
local text = "{\"name\": \"Nyash\", \"version\": 1}"
|
||||
local node = JsonNative.parse(text)
|
||||
|
||||
// 値にアクセス
|
||||
print(node.get("name").str()) // "Nyash"
|
||||
print(node.get("version").int()) // 1
|
||||
|
||||
// JSON文字列に戻す
|
||||
print(node.stringify()) // {"name":"Nyash","version":1}
|
||||
```
|
||||
|
||||
## 📊 進捗追跡
|
||||
|
||||
- [ ] Week 1: JsonNode基盤
|
||||
- [ ] Week 2: JsonLexer実装
|
||||
- [ ] Week 3: JsonParser実装
|
||||
- [ ] Week 4: 統合&最適化
|
||||
|
||||
**開始日**: 2025-09-22
|
||||
**目標完了**: 2025-10-20
|
||||
**実装者**: Claude × User協働
|
||||
Notes
|
||||
- Error messages aim to include: “Error at line X, column Y: …”.
|
||||
- Unterminated string → tokenizer emits "Unterminated string literal" (locked by quick smoke).
|
||||
|
||||
@ -59,9 +59,14 @@ box JsonParser {
|
||||
// Step 2: 構文解析
|
||||
local result = me.parse_value()
|
||||
|
||||
// Step 3: 余剰トークンチェック
|
||||
// Step 3: 余剰トークンチェック(詳細情報付き)
|
||||
if result != null and not me.is_at_end() {
|
||||
me.add_error("Unexpected tokens after JSON value")
|
||||
local extra = me.current_token()
|
||||
if extra != null {
|
||||
me.add_error("Unexpected tokens after JSON value: " + extra.get_type() + "(" + extra.get_value() + ")")
|
||||
} else {
|
||||
me.add_error("Unexpected tokens after JSON value")
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user