Files
hakorune/docs/guides/user-macros.md

154 lines
6.9 KiB
Markdown
Raw Normal View History

# User Macros (MacroBoxSpec) — Phase 2
Status: PoC complete; PyVM sandbox route wired. This guide explains how to author and run user macros in Nyash.
## Quickstart
- Register user macros (recommended minimal env):
- `NYASH_MACRO_ENABLE=1`
- `NYASH_MACRO_PATHS=apps/macros/examples/echo_macro.nyash`
- Run your program as usual (macro expansion happens once before MIR):
- `./target/release/nyash --backend vm apps/tests/ternary_basic.nyash`
Environment overview (recommended minimal set)
- `NYASH_MACRO_ENABLE=1`既定ON
- `NYASH_MACRO_PATHS=...`カンマ区切りのNyashマクロファイル
- `NYASH_MACRO_STRICT=1`(既定: 厳格)
- `NYASH_MACRO_TRACE=0|1`(開発用トレース)
- Runner route is defaultselfhosting優先。内部子ルートは非推奨`NYASH_MACRO_BOX_CHILD_RUNNER=0` でのみ有効)。
Backward compat (deprecated)
- `NYASH_MACRO_BOX_NY=1` + `NYASH_MACRO_BOX_NY_PATHS=...` → 今後は `NYASH_MACRO_PATHS` を使ってね
## Philosophy
- Hybrid approach: built-in (Rust) for minimal/core derives; user macros in Nyash (PyVM) for flexibility.
- Deterministic, sandboxed execution: default denies IO/NET/ENV.
- Unified interface: AST JSON v0 + MacroCtx. Expansion occurs pre-MIR.
MacroCtx (MVP)
- Rust側に最小の `MacroCtx``MacroCaps` を用意将来のAPI統合のため
- フィールド/メソッドMVP:
- `MacroCtx::from_env()` → 環境からcapabilitiesを組み立て親プロセス
- `ctx.gensym(prefix)` → 衛生識別子生成
- `ctx.report(level, message)` → 開発用レポート(標準エラー)
- `ctx.get_env(key)` → 環境取得(`NYASH_MACRO_CAP_ENV=1` のときのみ)
- 実行契約PoCランナーは `expand(json, ctx)` を優先し、失敗した場合は `expand(json)` にフォールバックします(後方互換)。
## Authoring a Macro
Create a Nyash file that defines `MacroBoxSpec` with a static `expand(json[, ctx])` returning a JSON string (AST JSON v0):
```nyash
static box MacroBoxSpec {
static function expand(json, ctx) {
// json: string (AST JSON v0)
// ctx: string (JSON; {caps:{io,net,env}} MVP). Optional for backward compatibility.
// return: string (AST JSON v0)
return json // identity for MVP
}
}
```
Example (repo): `apps/macros/examples/echo_macro.nyash`.
Editing template (string literal uppercasing)
- Example: `apps/macros/examples/upper_string_macro.nyash`
- Behavior: if a string literal value starts with `UPPER:`, the suffix is uppercased.
- Input: `print("UPPER:hello")` → Output: `print("HELLO")`
## Running your Macro
Register and run via env (simple):
```bash
export NYASH_MACRO_ENABLE=1
export NYASH_MACRO_PATHS=apps/macros/examples/echo_macro.nyash
# Run your program (macro expansion happens before MIR)
./target/release/nyash --backend vm apps/tests/ternary_basic.nyash
```
Selfhost pathNYASH_USE_NY_COMPILER=1での前展開開発用
```bash
NYASH_USE_NY_COMPILER=1 \
NYASH_MACRO_SELFHOST_PRE_EXPAND=1 \
NYASH_VM_USE_PY=1 \
./target/release/nyash --backend vm apps/tests/ternary_basic.nyash
```
Notes: 現状は PyVM ルートのみ対応。`NYASH_VM_USE_PY=1` が必須。
CLI プロファイル(推奨)
- `--profile dev`(既定相当: マクロON/厳格ON
- `--profile lite`マクロOFFの軽量モード
- `--profile ci|strict`マクロON/厳格ON
- 例: `./target/release/nyash --profile dev --backend vm apps/tests/ternary_basic.nyash`
Notes
- Built-in child route (stdin JSON -> stdout JSON) remains available when `NYASH_MACRO_BOX_CHILD_RUNNER=0`.
- Internal child can receive ctx via env: `NYASH_MACRO_CTX_JSON='{"caps":{"io":false,"net":false,"env":true}}'`
- CLI からも指定可能: `--macro-ctx-json '{"caps":{"io":false,"net":false,"env":true}}'`
- Strict mode: `NYASH_MACRO_STRICT=1` (default) fails build on macro child error/timeout; set `0` to fallback to identity.
- Timeout: `NYASH_NY_COMPILER_TIMEOUT_MS` (default `2000`).
Testing
feat: GC機能復活&VM整理&json_native調査完了 ## 🎉 ChatGPT×Claude協働成果 - ✅ **GC機能復活**: vm-legacy削除で失われたGC機能を新実装で復活 - GCメトリクス追跡システム実装(alloc/collect/pause計測) - 3種類のGCモード対応(counting/mark_sweep/generational) - host_handles.rsでハンドル管理復活 - ✅ **VM整理とエイリアス追加**: 混乱していた名前を整理 - MirInterpreter = NyashVm = VM のエイリアス統一 - vm-legacyとインタープリターの違いを明確化 - 壊れていたvm.rsの互換性修復 - ✅ **スモークテスト整理**: v2構造でプラグイン/コア分離 - plugins/ディレクトリにプラグインテスト移動 - gc_metrics.sh, gc_mode_off.sh, async_await.sh追加 - _ensure_fixture.shでプラグイン事前ビルド確認 ## 📊 json_native調査結果 - **現状**: 25%完成(配列/オブジェクトパース未実装) - **将来性**: 並行処理でyyjson超えの可能性大 - 100KB以上のJSONで2-10倍速の可能性 - Nyash ABI実装後はゼロコピー最適化 - **判断**: 現時点では置換不可、将来の大きな足場 ## 🔍 技術的発見 - vm-legacy = 完全なVM実装(GC付き)だった - MirInterpreter = 現在のRust VM(712行、Arc使用) - 200行簡易JSONは既に削除済み(存在しない) ChatGPT爆速修復×Claude詳細調査の完璧な協働! 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-24 23:27:59 +09:00
- Smokes (v2): `tools/smokes/v2/run.sh --profile quick --filter "macro"`
- Golden (identity): `tools/test/golden/macro/identity_user_macro_golden.sh`
- Golden (upper string): `tools/test/golden/macro/upper_string_user_macro_golden.sh`
- Golden (array prepend 0): `tools/test/golden/macro/array_prepend_zero_user_macro_golden.sh`
- Golden (map insert tag): `tools/test/golden/macro/map_insert_tag_user_macro_golden.sh`
feat: GC機能復活&VM整理&json_native調査完了 ## 🎉 ChatGPT×Claude協働成果 - ✅ **GC機能復活**: vm-legacy削除で失われたGC機能を新実装で復活 - GCメトリクス追跡システム実装(alloc/collect/pause計測) - 3種類のGCモード対応(counting/mark_sweep/generational) - host_handles.rsでハンドル管理復活 - ✅ **VM整理とエイリアス追加**: 混乱していた名前を整理 - MirInterpreter = NyashVm = VM のエイリアス統一 - vm-legacyとインタープリターの違いを明確化 - 壊れていたvm.rsの互換性修復 - ✅ **スモークテスト整理**: v2構造でプラグイン/コア分離 - plugins/ディレクトリにプラグインテスト移動 - gc_metrics.sh, gc_mode_off.sh, async_await.sh追加 - _ensure_fixture.shでプラグイン事前ビルド確認 ## 📊 json_native調査結果 - **現状**: 25%完成(配列/オブジェクトパース未実装) - **将来性**: 並行処理でyyjson超えの可能性大 - 100KB以上のJSONで2-10倍速の可能性 - Nyash ABI実装後はゼロコピー最適化 - **判断**: 現時点では置換不可、将来の大きな足場 ## 🔍 技術的発見 - vm-legacy = 完全なVM実装(GC付き)だった - MirInterpreter = 現在のRust VM(712行、Arc使用) - 200行簡易JSONは既に削除済み(存在しない) ChatGPT爆速修復×Claude詳細調査の完璧な協働! 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-24 23:27:59 +09:00
- Negative (timeout strict fail): covered by v2 smokes (legacy paths removed)
- Negative (invalid JSON strict/nonstrict): covered by v2 smokeslegacy paths removed
Array/Map editing examples
- Array prepend zero: `apps/macros/examples/array_prepend_zero_macro.nyash`
- Transforms every `{"kind":"Array","elements":[...]}` into one with a leading `0` literal element.
- Example input: `print([1, 2])` → Expanded: elements `[0, 1, 2]`.
- Map insert tag: `apps/macros/examples/map_insert_tag_macro.nyash`
- Transforms every `{"kind":"Map","entries":[...]}` by inserting the first entry `{k:"__macro", v: "on"}`.
- Example input: `print({"a": 1})` → Expanded entries: `[{"__macro":"on"}, {"a":1}]`.
## Inspect Expanded AST
```bash
./target/release/nyash --dump-expanded-ast-json apps/tests/ternary_basic.nyash
```
Outputs AST JSON v0 after expansion; use this for golden comparison.
## AST JSON v0 Schema
See `docs/reference/ir/ast-json-v0.md` for the minimal schema used in Phase 2.
## Troubleshooting
- Child timeout: increase `NYASH_NY_COMPILER_TIMEOUT_MS` or simplify macro code; strict mode fails fast.
- Invalid JSON from child: ensure `expand(json)` returns a valid AST JSON v0 string.
- No changes observed: confirm your macro is registered and the runner route is enabled.
- Capability denied: set caps explicitlyデフォルトは全OFF
- `NYASH_MACRO_CAP_IO=1` → IO系BoxFile/Path/Dir許可
- `NYASH_MACRO_CAP_NET=1` → NET系BoxHTTP/Socket許可
- `NYASH_MACRO_CAP_ENV=1``MacroCtx.get_env` 許可(将来拡張)
## Roadmap
- MacroCtx capabilities (io/net/env) expressed via nyash.toml per-macro.
- Diagnostics: JSONL tracing (`NYASH_MACRO_TRACE_JSONL`) and span/source maps.
- Golden tests for expanded JSON; strict mode as default.
## Capabilities (io/net/env)
Purpose: restrict sideeffects and ensure deterministic macro expansion.
- Default: all OFF (io=false, net=false, env=false)
- Behavior:
- io=false → no FileBox/FS access inside macro; AST JSON only
- net=false → no Http/Socket inside macro
- env=false → MacroCtx.getEnv disabled; child inherits scrubbed env
- Planned configuration (nyash.toml): see `docs/reference/macro/capabilities.md`
- PoC mapping: child is always `NYASH_VM_USE_PY=1`, `NYASH_DISABLE_PLUGINS=1`, timeout via `NYASH_NY_COMPILER_TIMEOUT_MS`
## Top-level static MacroBoxSpec (safety)
- 既定では無効(`NYASH_MACRO_TOPLEVEL_ALLOW=0`。Box宣言なしで `static function MacroBoxSpec.expand` を受理したい場合は `--macro-top-level-allow` を指定してください。