EIRIAD is an interpreter-first programming language runtime implemented in Rust. It runs in two places:
- CLI (
eiriadcommand) - Browser (WebAssembly runtime)
- What Is EIRIAD
- Language Features
- Quick Start
- Linux Installation
- CLI Usage
- Core Server API
- Browser and WASM Usage
- Tutorial: Write and Run an EIRIAD WASM App
- HTTP in EIRIAD
- Examples
- Language and Runtime Architecture
- Extending EIRIAD
- GitHub Pages Demo Deployment
- Project Notes and Roadmap
EIRIAD currently focuses on a tree-walk interpreter pipeline with a semantic checker and a shared runtime for both CLI and browser/WASM execution.
- Mutable and immutable bindings (
mut,let) - Assignment for mutable bindings
- Numeric and boolean expressions with precedence
- Operators:
+ - * / % ^ == != < <= > >= && || ! - User functions:
fn name(params) { expr } - Lambdas and closures:
(a, b) -> expr - Pipe operator:
value |> fn(args...) - Option/Result-style values:
None,Some(x),Ok(x),Err(x) - Option/Result helpers:
unwrap_or,is_some,is_none,is_ok,is_err - Match expressions with patterns:
Some(_),None,Ok(_),Err(_),_ - Built-ins:
print,len,sqrt,typeof,fetch, HTTP built-ins - Core server built-ins (native/CLI):
serve,request_method,request_path,request_body,response - Terminators: newline or
; - Trailing
\line continuation
| Concept | Syntax | Example |
|---|---|---|
| Immutable binding | let <name> = <expr> |
let radius = 9 |
| Mutable binding | mut <name> = <expr> |
mut total = 0 |
| Assignment | <name> = <expr> |
total = total + 1 |
| Function declaration | fn name(params) { expr } |
fn sq(x) { x * x } |
| Lambda | (a, b) -> expr |
let add = (a, b) -> a + b |
| Pipe | `value | > fn(args...)` |
| Match | match value { pattern -> expr } |
match r { Ok(v) -> v Err(e) -> e } |
| Option/Result constructors | Some(x), None, Ok(x), Err(x) |
let maybe = Some(42) |
print(value) |
print("hello") |
|
| HTTP GET | http_get(url) |
http_get("https://httpbin.org/get") |
| HTTP with body | http_post(url, body) |
http_post("https://httpbin.org/post", "{\"x\":1}") |
| Start server | serve(port, handler) |
serve(3000, app) |
| Build response | response(status, body) |
response(200, "ok") |
Install and run:
cargo install --path . --force
eiriad
eiriad examples/demo.eicurl -fsSL https://raw.githubusercontent.com/gwhitdev/Eiriad-Programming-Language/main/scripts/install_linux.sh | bashcurl -fsSL https://raw.githubusercontent.com/gwhitdev/Eiriad-Programming-Language/main/scripts/install_linux.sh | bash -s -- --method git./scripts/install_linux.sh --method sourceWhat the installer does:
- Ensures Linux is the current OS
- Installs Rust/cargo via rustup if missing
- Installs the
eiriadCLI withcargo install - Prints PATH guidance if
~/.cargo/binis not active yet
Run REPL:
eiriadRun a file:
eiriad examples/demo.eiOther modes:
eiriad -c 'print("hello")'
cat examples/demo.ei | eiriad -Development fallback without install:
cargo run --bin eiriad -- examples/demo.eiCompatibility binary:
eiriad-repldelegates to the same shared CLI implementation.
Shebang support:
#!/usr/bin/env eiriad
print("hello from shebang")
chmod +x hello.ei
./hello.eiREPL commands:
:quit/:q:env:reset
Eiriad now includes a built-in native server API inspired by Node.js/Bun style ergonomics for quick backend scripts.
Built-ins:
serve(port, handler)request_method(req)request_path(req)request_body(req)response(status, body)
Example (examples/server_basic.ei):
fn app(req) {
let method = request_method(req)
let path = request_path(req)
let body = request_body(req)
response(200, "method=" + method + " path=" + path + " body=" + body)
}
print("listening on http://127.0.0.1:3000")
serve(3000, app)
Run it:
eiriad examples/server_basic.eiThen test in another terminal:
curl -X POST http://127.0.0.1:3000/hello -d 'ping'Notes:
serveis currently native/CLI only.- Browser/WASM runtime cannot open listening sockets.
- Handler can return:
response(status, body)Str(treated as HTTP 200)()(treated as HTTP 204)
Build WASM and serve locally:
wasm-pack build --target web --features wasm
python3 -m http.server 8080Open:
http://localhost:8080/web/(browser REPL)http://localhost:8080/web/todo.html(WASM TODO app)
One-line command:
wasm-pack build --target web --features wasm && python3 -m http.server 8080Make target:
make wasm-demoPackage a .ei file as a WASM web app:
make wasm-ei APP=examples/demo.eiCustom output name:
make wasm-ei APP=examples/http_methods.ei NAME=http-methodsGenerated output goes under web/generated/<name>/.
Create examples/hello_web.ei:
print("Hello from Eiriad WASM")
mut count = 41
count = count + 1
print("count = " + count)
count
make wasm-ei APP=examples/hello_web.ei NAME=hello-webThis builds the WASM runtime and creates:
web/generated/hello-web/index.htmlweb/generated/hello-web/main.js
python3 -m http.server 8080Open:
http://localhost:8080/web/generated/hello-web/
Edit examples/hello_web.ei, regenerate, then hard refresh:
make wasm-ei APP=examples/hello_web.ei NAME=hello-webExample:
let response = http_get("https://httpbin.org/get")
let body = match response {
Ok(text) -> text
Err(e) -> "request failed: " + e
}
print(body)
Other methods:
let created = http_post("https://httpbin.org/post", "{\"name\":\"eiriad\"}")
let replaced = http_put("https://httpbin.org/put", "replace")
let changed = http_patch("https://httpbin.org/patch", "patch")
let removed = http_delete("https://httpbin.org/delete")
let headers_only = http_head("https://httpbin.org/get")
let options = http_options("https://httpbin.org/get")
Run examples:
eiriad examples/<file>.eiAvailable examples:
examples/demo.eiexamples/fn_decl.eiexamples/lambda_closure.eiexamples/match_option_result.eiexamples/option_result_helpers.eiexamples/http_get_fetch.eiexamples/http_methods.eiexamples/line_continuation.ei
Pipeline:
- Lexer
- Parser
- Semantic checker
- Runtime evaluator
Core code locations:
src/lexer.rssrc/parser.rssrc/checker.rssrc/runtime.rssrc/lib.rs
Typical change flow:
- Add AST representation
- Add lexer/parser support
- Add checker rules
- Add runtime execution behavior
- Add an example under
examples/
Useful extension points:
- Built-ins in
src/runtime.rsandsrc/checker.rs - New syntax nodes in
src/ast.rsand parser hooks - WASM API surface in
src/lib.rs(wasmfeature)
Deployment workflow:
.github/workflows/deploy-pages.yml
Publish steps:
- Push to
main - In GitHub settings, enable Pages with source set to GitHub Actions
- Wait for Pages workflow completion
Live URL patterns:
https://<your-user>.github.io/<your-repo>/https://<your-user>.github.io/<your-repo>/web/todo.htmlhttps://<your-user>.github.io/<your-repo>/web/generated/<name>/
- Interpreter-first implementation (tree-walk)
- Parser currently ignores type annotations in declarations
- Browser HTTP requests use
XmlHttpRequestand are subject to CORS - Broader language features (async/classes/traits/generics/reactivity) remain roadmap work