A scripting language
with simpler syntax than Python.
azro means “stone” in Tamazight — small, solid, and built to last. No let. No return. No colons. No print() boilerplate. Just the logic.
git clone … && cd azro-lang && ./install.shSmall surface, solid foundation
azro is designed around a single principle — simplicity. The features below reflect that goal.
Minimal syntax
No let, no return, no trailing colons, no print() boilerplate. Just the idea you wanted to express.
? "hi"Built in safe Rust
Wrapping arithmetic, never panics, embeddable in untrusted contexts. A 64 MB worker stack and sandbox defaults.
wrapping_add(a, b)Multilingual
Write azro in English, Arabic, Hindi, or Python-style via syntax profiles — a pure source-level transformation.
azro syntax init --template hindiDecentralized packages
Install from GitHub shorthand (User/Lib), a raw Git URL, or the official registry. No central gatekeeper.
azro install User/LibEmbeddable
SecurityLimits, instruction budget, sandbox defaults. Add azro-interpreter to any Cargo project.
SecurityLimits { ..sandbox() }Well-tested
32 unit + integration tests, clippy-clean, rustfmt-clean. 22 standard-library modules out of the box.
cargo test --workspaceAzro compared to Python
The same idea, side by side. Azro reduces the ceremony without reducing the power.
fn greet name
$"Hello, $name!"
? greet("world")Same output. Less ceremony. The pipeline and implicit return do the work thatreturn,for, and.append()used to.
| Feature | azro | Python | Lua |
|---|---|---|---|
| Print to stdout | ? "hi" | print("hi") | print("hi") |
| Define a function | fn f(n)
n * n | def f(n):
return n * n | function f(n)
return n * n
end |
| Implicit return | yes | no | no |
| Trailing colons | none | required | none |
| Variable declaration | x = 1 | x = 1 | local x = 1 |
| Pipeline operator | x |> f | f(x) | f(x) |
| Null-coalesce | a ?? b | a or b | a or b |
| Implementation language | Rust (safe) | C | C |
| Embeddable sandbox | built-in | via AST | limited |
Comparisons are about ceremony, not capability. Python and Lua are far more mature ecosystems — azro is the small, embeddable option.
The migration cheat sheet
Coming from Python? Here's how common tasks translate. Same intent, less ceremony — every time.
| Task | Python | Azro |
|---|---|---|
| Print a value | print("hello") | ? "hello" |
| String interpolation | f"Hello, {name}!" | $"Hello, $name!" |
| Define a function | def add(a, b):
return a + b | fn add(a, b)
a + b |
| Arrow / lambda | double = lambda x: x * 2 | double = x => x * 2 |
| List comprehension | [x*2 for x in nums if x > 0] | nums |> filter(x => x > 0) |> map(x => x * 2) |
| Read a file | with open("f.txt") as f:
data = f.read() | data = fs.read("f.txt") |
| Parse JSON | import json
obj = json.loads(text) | obj = json.parse(text) |
| HTTP GET | import requests
r = requests.get(url) | r = api.get(url) |
| Null-coalesce | name = user.name or 'guest' | name = user.name ?? "guest" |
| Match / switch | match status:
case 200: ...
case _: ... | match status
200
? "OK"
else
? "?" |
Why not just use Python, Lua, or Rust?
Skeptical? Good. Here's azro against the languages you're already considering — including where azro loses.
| Criterion | azro | Python | Lua | Rust |
|---|---|---|---|---|
| Target use case | embedded scripting | general-purpose | embedded scripting | systems programming |
| Implementation | Rust (safe) | C | C | self-hosted |
| Runtime footprint | ~3 MB | ~12 MB | ~0.3 MB | varies |
| Sandbox built-in | ✓yes — SecurityLimits | via AST/hooks | limited | no (unsafe) |
| Syntax ceremony | ✓minimal | medium | minimal | explicit |
| Package manager | decentralized | pip/PyPI | LuaRocks | cargo |
| Multilingual source | ✓yes — profiles | no | no | no |
| Speed (hot loops) | slow (no JIT) | slow (CPython) | fast (LuaJIT) | very fast |
| Maturity | v0.1.0 — young | mature | mature | mature |
azro doesn't “win” this table — it occupies a specific niche: a tiny, sandboxed, multilingual scripting layer for Rust hosts. If you don't need that, the others are better choices.
See the language, end to end
Switch between the tabs to walk through the core syntax. Every snippet is real azro.
# ? is the print shorthand — one character
? "Hello, world!"
? $"2 + 2 = ${2 + 2}"
# print(...) still works if you prefer it
print("Both styles work together")Hello, world!
2 + 2 = 4
Both styles work togetherazroc run print.az22 modules, batteries included
From math and strings to crypto, HTTP, and terminal UI — the stdlib covers the common ground without external dependencies. Hover any module to see what it does.
Data structures
4 moduleslistcreate, filter, map, reduce, sortdictkeys, values, merge, iterationstringsplit, join, replace, formatjsonparse & stringify
Math & randomness
2 modulesmathtrig, log, floor, ceil, constantsrandomint, float, choice, shuffle
System & I/O
5 modulesosenvironment, processes, exit codesfsread, write, list, walk filesiostdin, stdout, print, inputenvget & set environment variablesprocessspawn, pipes, signals
Network & web
1 moduleapiHTTP GET/POST/PUT/DELETE client
Encoding & crypto
4 modulescryptohash, hmac, sha256, md5base64encode & decodeuuidv4, v7 generationregexmatch, find, replace, capture
Time & terminal UI
4 modulestimenow, sleep, format, parseterminalcolors, cursor, clear, sizekeyboardread key, modifier statemouseposition, click events
Decentralized packages
Install from GitHub shorthand, a raw Git URL, or the official registry.
Syntax profiles
Write azro in Arabic, Hindi, or Python-style — a pure source-level translation.
Sandbox by default
SecurityLimits, instruction budgets, and file I/O gating for untrusted scripts.
How fast is it, honestly?
azro is a tree-walking interpreter — comparable to CPython for typical scripts, not a JIT. Here's where it sits, and why.
| Task | azro | Python (CPython) | Lua | Note |
|---|---|---|---|---|
| Hello world startup | ~8 ms | ~30 ms | ~5 ms | Rust binary, no JIT warmup |
| Fibonacci(35) recursive | ~6.5 s | ~4.8 s | ~7.2 s | Tree-walking, no JIT |
| List map + filter (10k items) | ~1.2 ms | ~0.9 ms | ~1.4 ms | Comparable to CPython |
| JSON parse (100 KB) | ~0.4 ms | ~0.6 ms | ~0.8 ms | Rust-backed stdlib |
| Binary size (runtime) | ~3 MB | ~12 MB | ~0.3 MB | Statically linked |
Not a JIT
azro is a tree-walking interpreter. Hot numeric loops are slower than PyPy or LuaJIT. Use native (Rust) packages for hot paths.
Sandboxed by default
Every script runs under SecurityLimits. The overhead is tiny, but the safety is real — no arbitrary memory access, ever.
Native FFI escape hatch
When a loop is too slow, drop to Rust via kind = native. Keep the glue in azro, keep the heat in Rust.
Numbers are illustrative reference points, not formal benchmarks — see the performance tutorial for methodology and how to run them yourself.
Where azro isn't ready yet
Every young language hides its rough edges. azro doesn't. Here's what's missing, broken, or planned — so you can decide if it fits your use case.
No JIT, no bytecode
azro is a pure tree-walking interpreter. Hot numeric loops (millions of iterations) will be slower than PyPy or LuaJIT. Use native (Rust) packages for those.
Rc cycles leak memory
The interpreter uses Rc<RefCell> for shared values. Reference cycles (a → b → a) are not collected and will leak. Documented in SECURITY.md. A future GC is planned.
Single-threaded execution
azro scripts run on one thread. The host can run multiple interpreters in parallel, but a single script has no shared-memory concurrency. Async/await is planned.
Young ecosystem
v0.1.0 — the API may change before v1.0. Few third-party packages exist yet. Don't bet critical infrastructure on it without evaluating the risk.
No stable ABI yet
Native (Rust/C) extensions use a C ABI, but the azro-side Value ABI is not frozen. Rebuilding native packages against new azro versions may be required until v1.0.
Editor support is basic
VS Code, Vim, and Emacs get syntax highlighting + snippets. No language server (LSP) yet — no autocomplete, go-to-definition, or hover docs. Planned for v0.2.
The full list lives in SECURITY.md and CHANGELOG.md.
Errors that actually help
You'll judge a language by its stack traces. azro shows the line, the column, the offending expression, and a hint to fix it — not just 'TypeError: null'.
Every runtime error includes the file, line, and column; a source snippet with the offending expression underlined; the error type and message; and — when possible — a hint suggesting the fix.
- Source span with the exact token highlighted
- Error type (TypeError, NameError, …) + plain message
- Contextual hint when a fix is known
- Never a raw Rust panic — wrapping arithmetic, graceful exits
error: TypeError
in example.az:4:5
2 │ nums = [1, 2, 3]
3 │ name = null
4 │ ? name.upper()
^^^^^^^^^^
Cannot call .upper() on null
hint: check if the value is null first:
? (name ?? "").upper()Questions you might be asking
Straight answers — including the ones that aren't flattering.
What are you building?
Pick the path that fits — we'll show you the right first step. The full learning path is 37 focused tutorials either way.