超真面目に作っている趣味言語
20日でゼロからネイティブバイナリへ - AI駆動の言語革命
開発者向けクイックスタート: docs/DEV_QUICKSTART.md
セルフホスト1枚ガイド: docs/self-hosting.md
docs/self-hosting.md
NYASH_DISABLE_PLUGINS=1 ./target/release/nyash --backend vm apps/selfhost-minimal/main.nyash
bash tools/jit_smoke.sh
/ bash tools/selfhost_vm_smoke.sh
make run-minimal
, make smoke-selfhost
MIR注記: Core‑13 最小カーネルは既定で有効(NYASH_MIR_CORE13=1)。旧命令は正規化されます(Array/Ref→BoxCall、TypeCheck/Cast/Barrier/WeakRefの統一)。
純化モード: NYASH_MIR_CORE13_PURE=1
を有効にすると、Optimizer が Load/Store/NewBox/Unary を Core‑13 形に書き換え、残存する非Core‑13命令があればコンパイルを失敗させます。あえて実行が壊れる可能性がありますが、MIR違反を早期に発見するための設計です。
変更履歴(要点): CHANGELOG.md
👉 ブラウザプレイグラウンドを起動 👈
インストール不要 - ウェブブラウザで即座にNyashを体験!
2025年8月29日 - 誕生からわずか20日で、Nyashがネイティブ実行ファイルへのコンパイルを実現!
# Nyashソースからネイティブバイナリへ(Craneliftが必要)
cargo build --release --features cranelift-jit
./tools/build_aot.sh program.nyash -o app # ネイティブEXE
./app # スタンドアロン実行!
20日間で達成したこと:
// 従来の言語は複雑な型システムを持つ
// Nyash: 一つの概念がすべてを支配する - Box
static box Main {
main() {
// すべての値はBox - 統一、安全、シンプル
local name = new StringBox("Nyash")
local count = new IntegerBox(42)
local data = new MapBox()
// PythonオブジェクトもBox!
local py = new PyRuntimeBox()
local math = py.import("math")
print("sqrt(9) = " + math.getattr("sqrt").call(9).str())
return 0
}
}
// あらゆる機能がプラグインBoxになれる
local file = new FileBox() // ファイルI/Oプラグイン
local http = new HttpClientBox() // ネットワークプラグイン
local py = new PyRuntimeBox() // Pythonプラグイン
// プラグインもネイティブコードにコンパイル!
重要: 現在、JIT ランタイム実行はデバッグ容易性のため封印しています。実行は「インタープリター/VM」、配布は「Cranelift AOT(EXE)/LLVM AOT(EXE)」の4体制です。
./target/release/nyash program.nyash
./target/release/nyash --backend vm program.nyash
# 事前ビルド(Cranelift)
cargo build --release --features cranelift-jit
./tools/build_aot.sh program.nyash -o myapp
./myapp # スタンドアロン実行!
LLVM_SYS_180_PREFIX=$(llvm-config-18 --prefix) \
cargo build --release --features llvm
NYASH_LLVM_OBJ_OUT=$PWD/nyash_llvm_temp.o \
./target/release/nyash --backend llvm program.nyash
# リンクして実行
cc nyash_llvm_temp.o -L crates/nyrt/target/release -Wl,--whole-archive -lnyrt -Wl,--no-whole-archive -lpthread -ldl -lm -o myapp
./myapp
簡易スモークテスト(VM と EXE の出力一致確認):
tools/smoke_aot_vs_vm.sh examples/aot_min_string_len.nyash
NYASH_LLVM_OBJ_OUT
: --backend llvm
実行時に .o
を出力するパス。
NYASH_LLVM_OBJ_OUT=$PWD/nyash_llvm_temp.o ./target/release/nyash --backend llvm apps/ny-llvm-smoke/main.nyash
NYASH_LLVM_ALLOW_BY_NAME=1
: デバッグ専用の by-name フォールバック(by-id が未提供の場合の暫定措置)。
LLVM_SYS_180_PREFIX=$(llvm-config-18 --prefix) cargo build --release --features llvm
NYASH_LLVM_BITOPS_SMOKE=1 ./tools/llvm_smoke.sh release
NYASH_LLVM_ARRAY_SMOKE=1 ./tools/llvm_smoke.sh release
NYASH_LLVM_ECHO_SMOKE=1 ./tools/llvm_smoke.sh release
NYASH_LLVM_MAP_SMOKE=1 ./tools/llvm_smoke.sh release
NYASH_LLVM_VINVOKE_SMOKE=1 ./tools/llvm_smoke.sh release
(期待: VInvokeRc: 42
)NYASH_LLVM_VINVOKE_RET_SMOKE=1 ./tools/llvm_smoke.sh release
(期待: Result: 42
と Result: 1
(size()))NYASH_LLVM_ALLOW_BY_NAME=1
)。NYASH_LLVM_VINVOKE_TRACE=1
で有効化できます。NYASH_LLVM_VINVOKE_PREFER_I64=1
(Unknown返りを整数優先)または NYASH_LLVM_VINVOKE_BYNAME_WRAP_I64=1
(by-nameの i64 を IntegerBox 化)を試してください。通常のスモークでは不要です。cargo build --release --features wasm-backend
./target/release/nyash --compile-wasm program.nyash
nyash.toml
の [tasks]
と [env]
で、ビルド/スモークなどのタスクを簡単に実行できます(MVP)。
例(nyash.toml の末尾に追記):
[env]
RUST_BACKTRACE = "1"
[tasks]
build_llvm = "LLVM_SYS_180_PREFIX=$(llvm-config-18 --prefix) cargo build --release --features llvm"
smoke_obj_array = "NYASH_LLVM_OBJ_OUT={root}/nyash_llvm_temp.o ./target/release/nyash --backend llvm apps/ny-llvm-smoke/main.nyash"
実行:
./target/release/nyash --run-task build_llvm
./target/release/nyash --run-task smoke_obj_array
補足:
[env]
の値は実行前に環境へ適用されます。{root}
は現在のプロジェクトルートに展開されます。nyash --build
nyash.toml
を読み、プラグイン → コア → AOT → リンクまでを一発実行する最小ビルド機能です。
基本(Cranelift AOT)
./target/release/nyash --build nyash.toml \
--app apps/egui-hello-plugin/main.nyash \
--out app_egui
主なオプション(最小)
--build <path>
: nyash.toml の場所--app <file>
: エントリ .nyash
--out <name>
: 出力EXE名(既定: app
/app.exe
)--build-aot cranelift|llvm
(既定: cranelift)--profile release|debug
(既定: release)--target <triple>
(必要時のみ)注意
LLVM_SYS_180_PREFIX
を設定)。docs/guides/cranelift_aot_egui_hello.md
のWSL Tips(Wayland→X11切替)を参照。実世界ベンチマーク結果 (ny_bench.nyash):
モード | 時間 | 相対速度
----------------|-----------|---------------
インタープリター | 110.10ms | 1.0x (基準)
VM | 8.14ms | 13.5倍高速
Cranelift AOT | ~4–6ms | ~20–27倍高速
ネイティブ(LLVM)| ~4ms | ~27倍高速
box GameCharacter {
private { name, health, skills }
// birthコンストラクタ - Boxに生命を与える!
birth(characterName) {
me.name = characterName
me.health = 100
me.skills = new ArrayBox()
print("🌟 " + characterName + " が誕生しました!")
}
learnSkill(skill) {
me.skills.push(skill)
return me // メソッドチェーン
}
}
// 使用例
local hero = new GameCharacter("ネコ")
hero.learnSkill("火魔法").learnSkill("回復")
// シンプルな並行処理
nowait task1 = fetchDataFromAPI()
nowait task2 = processLocalFiles()
// 待機中に他の作業
updateUI()
// 結果収集
local apiData = await task1
local files = await task2
// 継承よりコンポジション
box EnhancedArray from ArrayBox {
private { logger }
override push(item) {
me.logger.log("追加中: " + item)
from ArrayBox.push(item) // 親に委譲
}
}
Nyashは「Everything is Plugin」アーキテクチャを開拓:
# nyash.toml - プラグイン設定
[libraries."libnyash_python_plugin.so"]
boxes = ["PyRuntimeBox", "PyObjectBox"]
[libraries."libnyash_net_plugin.so"]
boxes = ["HttpServerBox", "HttpClientBox", "WebSocketBox"]
C/Rustで独自のBox型を作成してシームレスに統合!
# クローンとビルド
git clone https://github.com/moe-charm/nyash.git
cd nyash
cargo build --release --features cranelift-jit
# 最初のプログラムを実行
echo 'print("Hello Nyash!")' > hello.nyash
./target/release/nyash hello.nyash
# Windows向けクロスコンパイル
cargo install cargo-xwin
cargo xwin build --target x86_64-pc-windows-msvc --release
# target/x86_64-pc-windows-msvc/release/nyash.exe を使用
# WindowsでのネイティブEXE(AOT)ビルド(Cranelift と MSYS2/WSL が必要)
cargo build --release --features cranelift-jit
powershell -ExecutionPolicy Bypass -File tools\build_aot.ps1 -Input examples\aot_min_string_len.nyash -Out app.exe
./app.exe
// NyashからPythonライブラリを使用!
local py = new PyRuntimeBox()
local np = py.import("numpy")
local array = np.getattr("array").call([1, 2, 3])
print("NumPy配列: " + array.str())
local server = new HttpServerBox()
server.start(8080)
loop(true) {
local request = server.accept()
local response = new HttpResponseBox()
response.setStatus(200)
response.write("Nyashからこんにちは!")
request.respond(response)
}
box GameObject {
public { x, y, sprite }
update(deltaTime) {
// 物理シミュレーション
me.y = me.y + gravity * deltaTime
}
render(canvas) {
canvas.drawImage(me.sprite, me.x, me.y)
}
}
革命に参加しよう!以下を歓迎します:
詳細は AGENTS.md
(Repository Guidelines)をご参照ください。プロジェクト構成、ビルド/テスト手順、PRの要件を簡潔にまとめています。
MIT ライセンス - プロジェクトで自由に使用してください!
charmpic - 趣味で言語作ってる人
ゼロからネイティブバイナリまで20日間 - 言語開発の新記録!
🚀 Nyash - すべてがBoxであり、Boxがネイティブコードにコンパイルされる場所!
❤️、🤖 AIコラボレーション、そしてプログラミング言語は思考の速度で作れるという信念で構築