Syntax Reference
NAIDE uses indentation-based blocks, keyword-driven statements, and explicit type annotations. The first token on each line determines intent.
Variables
Variables are immutable by default (const). Use mut for mutable bindings (let).
str name = "hello" # immutable (const)
int count = 42
num price = 9.99
bool active = true
list items = [1, 2, 3]
map config = {host: "localhost"}
any data = null
mut int counter = 0 # mutable (let)
mut str label = "init"
Available Types
| Type | Description | JavaScript |
|---|---|---|
str | String | string |
int | Integer number | number |
num | Any number (accepts int) | number |
bool | Boolean | boolean |
list | Array | Array |
map | Object / dictionary | Object |
any | Any type | (untyped) |
json | JSON-compatible value | (untyped) |
void | No return value | void |
String Interpolation
Double-quoted strings with {expr} are automatically interpolated into template literals:
str greeting = "Hello {name}, you have {count} items"
Compiles to:
const greeting = `Hello ${name}, you have ${count} items`;
Functions
Functions use fn, with optional typed parameters and return type:
fn add(int a, int b) -> int:
ret a + b
fn greet(str name, str prefix = "Hello"):
log "{prefix}, {name}!"
Rest Parameters
fn sum(...int nums) -> int:
mut int total = 0
each n in nums:
total += n
ret total
Async Functions
fn.async fetchUser(str id) -> map:
any res = await fetch("/api/users/{id}")
ret await res.json()
Control Flow
If / Elif / Else
if count > 10:
log "many"
elif count > 5:
log "some"
else:
log "few"
Ternary Expression
str size = if count > 10 then "big" else "small"
Loops
each — Iterate Arrays
each item in items:
log item
each — Iterate Object Keys/Values
each key, val in config:
log "{key}: {val}"
for — Numeric Range
for i in 0..10:
log i
while
while active:
log "running"
active = false
Pattern Matching
match status:
"ok": log "success"
"error": log "failed"
_: log "unknown"
Compiles to a switch statement. Use _ for the default case.
Error Handling
try:
data = await fetchData(url)
fail e:
log.error e.message
ensure:
log "request completed"
fail is NAIDE's catch. ensure is NAIDE's finally — the block always runs whether the try succeeds or fails. Both fail and ensure are optional:
try:
conn = await openConnection()
ret await conn.query("SELECT 1")
ensure:
conn.close()
Type Checking
if typeof data == "string":
log "is string"
if err instanceof TypeError:
log "type error"
typeof returns the type as a string. instanceof checks if a value is an instance of a class or constructor.
Classes (model)
Use model to define classes with typed properties:
model User:
str name
str email
int age = 0
fn greet() -> str:
ret "Hi, I'm {self.name}"
model Admin extends User:
str role = "admin"
fn permissions() -> list:
ret ["read", "write", "delete"]
self refers to the current instance (compiles to this).
Pipe Operator
list result = data
|> filter((x) => x.active)
|> map((x) => x.name)
|> sort()
Pipes chain method calls for readable data transformations.
Imports & Exports
Imports
use express
use {readFile, writeFile} from "fs/promises"
use axios from "axios"
use compiles to import. When importing between NAIDE files, extensions are automatically rewritten to .mjs:
use {handleUser} from "./routes.naide"
Exports
pub fn helper() -> str:
ret "exported"
pub str VERSION = "1.0.0"
pub marks functions and variables as exported (export).
Environment Variables
env:
PORT int default(3000)
JWT_SECRET str required
DB_URL str default("data/")
Variables become constants read from process.env. Missing required variables cause the process to exit with an error.
Built-in Functions
str id = uuid() # UUID generation
str hashed = hash("password") # scrypt hash
bool ok = verify("password", hashed) # timing-safe verify
str token = sign({id: 1}) # JWT (uses auth secret)
str token = sign({id: 1}, "my-secret") # JWT (explicit secret)
These are auto-imported from the NAIDE runtime when used.
HTTP Client
fn.async getUsers() -> any:
any users = await api.get("https://api.example.com/users")
ret users
fn.async createUser(map data) -> any:
any result = await api.post("https://api.example.com/users", data)
ret result
Available methods: api.get(url), api.post(url, body), api.put(url, body), api.del(url), api.raw(url, opts).
Plugin System
registerPlugin("logger", (opts) =>
ret {log: (msg) => log "[{opts.prefix}] {msg}"}
)
any logger = usePlugin("logger", {prefix: "APP"})
logger.log("started")
list names = listPlugins()
registerPlugin(name, setup) registers a plugin factory. usePlugin(name, opts?) initializes on first call and returns cached exports. listPlugins() returns registered plugin names.