A Seriously-Crafted Hobby Language
From Zero to Native Binary in 20 Days - The AI-Powered Language Revolution
🇯🇵 日本語版はこちら / Japanese Version
Developer quickstart: see docs/DEV_QUICKSTART.md
. Changelog highlights: CHANGELOG.md
.
Self‑hosting one‑pager: 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 note: Core‑13 minimal kernel is enforced by default (NYASH_MIR_CORE13=1). Legacy ops are normalized (Array/Ref→BoxCall; TypeCheck/Cast/Barrier/WeakRef unified).
Pure mode: set NYASH_MIR_CORE13_PURE=1
to enable strict Core‑13. The optimizer rewrites a few ops (Load/Store/NewBox/Unary) to Core‑13 forms, and the compiler rejects any remaining non‑Core‑13 ops. This may break execution temporarily by design to surface MIR violations early.
Note: JIT runtime execution is currently disabled to reduce debugging overhead. Use Interpreter/VM for running and AOT (Cranelift/LLVM) for distribution.
No installation needed - experience Nyash instantly in your web browser!
September 2, 2025 - 🔥 ABI as a Box! Nyash ABI itself implemented as TypeBox (C language) - path to self-hosting clear! September 1, 2025 - Revolutionary TypeBox ABI unification achieved! C ABI + Nyash ABI seamlessly integrated. August 29, 2025 - Just 20 days after inception, Nyash can now compile to native executables!
# From Nyash source to native binary (Cranelift required)
cargo build --release --features cranelift-jit
./tools/build_aot.sh program.nyash -o app # Native EXE
./app # Standalone execution!
What we achieved in 24 days:
// Traditional languages have complex type systems
// Nyash: One concept rules them all - Box
static box Main {
main() {
// Every value is a Box - unified, safe, simple
local name = new StringBox("Nyash")
local count = new IntegerBox(42)
local data = new MapBox()
// Even Python objects are Boxes!
local py = new PyRuntimeBox()
local math = py.import("math")
print("sqrt(9) = " + math.getattr("sqrt").call(9).str())
return 0
}
}
// Any functionality can be a plugin Box
local file = new FileBox() // File I/O plugin
local http = new HttpClientBox() // Network plugin
local py = new PyRuntimeBox() // Python plugin
// Plugins compile to native code too!
Important: JIT runtime execution is sealed for now. Use Interpreter/VM for running, and Cranelift AOT/LLVM AOT for native executables.
./target/release/nyash program.nyash
./target/release/nyash --backend vm program.nyash
# Build once (Cranelift)
cargo build --release --features cranelift-jit
./tools/build_aot.sh program.nyash -o myapp
./myapp # Standalone executable!
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
# Link and run
cc nyash_llvm_temp.o -L crates/nyrt/target/release -Wl,--whole-archive -lnyrt -Wl,--no-whole-archive -lpthread -ldl -lm -o myapp
./myapp
Quick smoke test (VM vs EXE):
tools/smoke_aot_vs_vm.sh examples/aot_min_string_len.nyash
NYASH_LLVM_OBJ_OUT
: Path to emit .o
when running --backend llvm
.
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
: Debug-only fallback for plugin calls by name when by-id isn’t available.
nyash.plugin.invoke_by_name_i64
for development.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
(expects VInvokeRc: 42
)NYASH_LLVM_VINVOKE_RET_SMOKE=1 ./tools/llvm_smoke.sh release
(expects Result: 42
and Result: 1
for size())NYASH_LLVM_ALLOW_BY_NAME=1
).NYASH_LLVM_VINVOKE_TRACE=1
.NYASH_LLVM_VINVOKE_PREFER_I64=1
(prefer integer for Unknown return) or NYASH_LLVM_VINVOKE_BYNAME_WRAP_I64=1
(wrap by-name i64 as IntegerBox). These are diagnostic toggles and not needed for normal smokes.cargo build --release --features wasm-backend
./target/release/nyash --compile-wasm program.nyash
nyash --build
Reads nyash.toml
, builds plugins → core → emits AOT object → links an executable in one shot.
Basic (Cranelift AOT)
./target/release/nyash --build nyash.toml \
--app apps/egui-hello-plugin/main.nyash \
--out app_egui
Key options (minimal)
--build <path>
: path to nyash.toml--app <file>
: entry .nyash
--out <name>
: output executable (default: app
/app.exe
)--build-aot cranelift|llvm
(default: cranelift)--profile release|debug
(default: release)--target <triple>
(only when needed)Notes
LLVM_SYS_180_PREFIX
).docs/guides/cranelift_aot_egui_hello.md
(Wayland→X11).Real-world benchmark results (ny_bench.nyash):
Mode | Time | Relative Speed
---------------|-----------|---------------
Interpreter | 110.10ms | 1.0x (baseline)
VM | 8.14ms | 13.5x faster
Cranelift AOT | ~4–6ms | ~20–27x faster
Native (LLVM) | ~4ms | ~27x faster
box GameCharacter {
private { name, health, skills }
// Birth constructor - giving life to Boxes!
birth(characterName) {
me.name = characterName
me.health = 100
me.skills = new ArrayBox()
print("🌟 " + characterName + " has been born!")
}
learnSkill(skill) {
me.skills.push(skill)
return me // Method chaining
}
}
// Usage
local hero = new GameCharacter("Neko")
hero.learnSkill("Fire Magic").learnSkill("Healing")
// Concurrent operations made simple
nowait task1 = fetchDataFromAPI()
nowait task2 = processLocalFiles()
// Do other work while waiting
updateUI()
// Collect results
local apiData = await task1
local files = await task2
// Composition over inheritance
box EnhancedArray from ArrayBox {
private { logger }
override push(item) {
me.logger.log("Adding: " + item)
from ArrayBox.push(item) // Delegate to parent
}
}
“Everything is Box” Philosophy - Even ABI is a Box!
// TypeBox - Type information as a Box (enables cross-plugin creation)
typedef struct {
uint32_t abi_tag; // 'TYBX'
const char* name; // "ArrayBox"
void* (*create)(void); // Box creation function
} NyrtTypeBox;
// NEW: Nyash ABI itself as a TypeBox! (C implementation, no Rust)
typedef struct {
uint32_t abi_tag; // 'NABI'
const char* name; // "NyashABIProvider"
void* (*create)(void); // ABI provider creation
// ... Nyash operations (call, retain, release)
} NyashABITypeBox;
Revolutionary Achievement: ABI implementation in pure C enables self-hosting!
# nyash.toml v3.0 - Unified plugin support
[plugins.map]
path = "plugins/map.so"
abi = "c" # Traditional C ABI
[plugins.advanced_map]
path = "plugins/adv_map.so"
abi = "nyash" # Type-safe Nyash ABI
[plugins.hybrid]
path = "plugins/hybrid.so"
abi = "unified" # Both ABIs supported!
Key Innovation: TypeBox enables cross-plugin Box creation without circular dependencies. MapBox can now return ArrayBox seamlessly!
# Clone and build
git clone https://github.com/moe-charm/nyash.git
cd nyash
cargo build --release --features cranelift-jit
# Run your first program
echo 'print("Hello Nyash!")' > hello.nyash
./target/release/nyash hello.nyash
# Cross-compile for Windows
cargo install cargo-xwin
cargo xwin build --target x86_64-pc-windows-msvc --release
# Use target/x86_64-pc-windows-msvc/release/nyash.exe
# Native EXE (AOT) on Windows (requires Cranelift and MSYS2/WSL toolchain for linking)
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
// Use Python libraries from Nyash!
local py = new PyRuntimeBox()
local np = py.import("numpy")
local array = np.getattr("array").call([1, 2, 3])
print("NumPy array: " + array.str())
local server = new HttpServerBox()
server.start(8080)
loop(true) {
local request = server.accept()
local response = new HttpResponseBox()
response.setStatus(200)
response.write("Hello from Nyash!")
request.respond(response)
}
box GameObject {
public { x, y, sprite }
update(deltaTime) {
// Physics simulation
me.y = me.y + gravity * deltaTime
}
render(canvas) {
canvas.drawImage(me.sprite, me.x, me.y)
}
}
Join the revolution! We welcome:
See also: Contributor guide in AGENTS.md
(Repository Guidelines) for project layout, build/test commands, and PR expectations.
MIT License - Use freely in your projects!
charmpic - Hobby Language Developer
24 days from zero to self-hosting capability - a new record in language development!
🚀 Nyash - Where Everything is a Box, and Boxes Compile to Native Code!
Built with ❤️, 🤖 AI collaboration, and the belief that programming languages can be created at the speed of thought