Language reference
Keywords, operators, literals, and quick lookup — everything the lexer and parser accept today.
Keywords
Full reserved-word list, @ raw identifiers, and #[…] attributes: Nyra Keywords.
| Keyword | Purpose |
|---|---|
fn | Function definition |
let / let mut | Immutable / mutable binding |
const | Compile-time constant name |
comptime | Optional compile-time evaluation — file module, #[comptime], or comptime { } block (guide) |
if / else | Conditional |
while | Loop |
for / in | Range loop: for i in 0..10 |
return | Return from function |
match | Pattern match on enums / values |
struct / enum | User-defined types |
impl | Methods on a type; impl Trait for Type |
for (in types) | HRTB binder: for<'a> fn(...) |
import | Load another .ny file — import "path", as alias, or import { name } from "path" |
module | Module declaration (parsed) |
extern / export | FFI declare / export symbol |
test | Test function |
print | Built-in stdout (keyword); optional color: for ANSI output |
spawn | Concurrent block |
defer | Scope-exit call (LIFO) — Extended; prefer auto-drop / impl Drop |
unsafe | Block for raw memory (deref, ptr arithmetic, raw casts) |
asm | Inline assembly: asm "template" (inside unsafe) |
as | Type cast: expr as Type; also import alias / selective rename |
no_std | Top-level directive — skip runtime link; no print/spawn |
move / clone | Unary prefixes at call sites — explicit move or clone |
async / await | Stable Extended — promises + await; not on wasm32 |
trait / dyn | Stable Extended — impl Trait for Type, trait objects dyn Trait |
macro | Extended — parsed and expanded |
self | Method receiver in impl |
Built-in call names (no import)
Resolved in the typechecker like keywords. Full lookup: Built-in methods · Standard library → Built-ins.
print,write,println,flush,inputdate()— returnsDatewith.year,.month,.day,.hour, …time_start,time_end,mem_start,mem_end
String methods (no import): .length(), .split(), .trim(), .contains(), .replace(), .to_upper(), … — see Built-in methods → Strings.
Type names
Every type Nyra supports in source annotations and inference. All optional unless inference fails.
| Type | Ownership | Notes |
|---|---|---|
i8 … i128 | Copy | Signed integers; i32 default for int literals |
u8 … u128 | Copy | Unsigned integers |
isize, usize | Copy | Pointer-sized integers |
f32 | Copy | IEEE-754 single (LLVM float); suffix f32 |
f64 | Copy | IEEE-754 double (LLVM double); default float literal |
char | Copy | Unicode scalar; 'a', '\n' |
bool | Copy | true / false |
string | Move | UTF-8 bytes; literals static, heap values auto-dropped |
VecStr | Copy (handle) | .split(sep) result; for x in parts; optional annotation |
void | — | Function with no return value |
ptr | Copy | Opaque FFI handle (Send) |
*T | Copy | Typed raw pointer (!Send / !Sync) |
&T / &mut T | Borrow | Immutable / mutable reference |
&'a T | Borrow | Explicit lifetime on reference (Extended) |
for<'a> fn(...) | — | Higher-ranked function pointer type (Extended) |
[T; N] | Depends on T | Fixed-size array |
(T, U, …) | Depends on fields | Tuple |
Vec<T> | Depends on T | Stdlib growable vector (monomorphized) |
StructName | Copy or Move | Auto-Copy when all fields Copy; Move if any field is Move |
EnumName | Copy | Enum tag + optional payload |
option / result | Copy | Built-in enum tags |
T (generic param) | — | Inferred at generic call site when omitted |
Struct Send Sync | — | Thread-safety markers on struct declaration |
Comments
| Form | Example | Notes |
|---|---|---|
| Line | // comment to EOL | Core — ignored by lexer |
| Block | /* … */ | Core — multiline OK; non-nested; unclosed /* → lexer error |
// file header
let x = 1 /* inline */ + 2
/*
* multiline doc
*/// file header
let x = 1 /* inline */ + 2
/*
* multiline doc
*/See Learn → Comments · Tests: tests/nyra/block_comments_test.ny · CONF-COMMENT-*
Literals
| Form | Example | Type |
|---|---|---|
| Integer | 42, 0xff, 1_000_000, 255u8 | i32 (default) or suffix width |
| Float | 3.14, 1.5f32, 1e-3 | f64 default; f32 with suffix or annotation |
| Character | 'a', '\n' | char |
| Boolean | true, false | bool |
| String | "hello" | string (static, not heap-freed) |
| Template | `Hello, ${name}!` | string (interpolates i32, f64, string) |
| Array | [1, 2, 3], [0; 8], [-1; STROKE_MAX] | [i32; N] when annotated; repeat count may be a module const |
| Tuple | (1, "a") | (i32, string) when annotated |
Template strings: backticks with ${expr} — e.g. `score: ${n}`. See Learn → Strings.
Numeric separators: underscores between digits are ignored — 10_00000 equals 100000. Hex integers: 0xFF, 0xffu8.
Operators
| Category | Operators |
|---|---|
| Arithmetic | + - * / % |
| Comparison | == != < > <= >= — ptr values compare string content (except function pointers) |
| Logical | && || ! |
| Bitwise | << >> & | ^ (integers) |
| Nullish / optional | ?? ?. ?.method() — desugar to Option match; Option.Some(v) payload bind on ?? |
| Reference | &x (shared), &mut x (exclusive) |
| Raw (unsafe) | *ptr load, *ptr = v store, ptr + i32, ptr - i32 |
| Cast | expr as Type — e.g. &x as *i32, ptr as i32 |
| Field | obj.field |
| Call | f(a, b), obj.method(a) |
Statements
let name = expr/let mut name = exprfn f(mut x: i32)— mutable parameter (reassignable in body);mut s: Structupdates the caller's struct in place (passed by pointer)const NAME = exprname = expr(assign; requiresmut)if cond { } else { }while cond { }for var in start..end { }— half-open integer rangefor x in arr { }— iterate array elementsfor x in str { }— string chars (char)for x in parts { }— split list (VecStrfrom.split())return expr/returnprint(expr)/print(expr, color: spec)defer expr— runs at block exit (after other statements, before parent scope)spawn { statements }unsafe { statements }asm "template"— LLVM inline asm (insideunsafe)*ptr = expr— pointer store (insideunsafe)no_std— file-level directive (first statement)import "path.ny"/import "path.ny" as aliasimport { a, b as c } from "path.ny"— selective (only namedpubsymbols)- Expression statement: bare call, e.g.
free(s)
Expressions
- Literals, variables, unary
-/!/&/&mut/move/clone - Binary arithmetic, comparison, logic
if cond { a } else { b }as expressioncond ? a : b— ternary shorthand (same asifexpression)match scrutinee { Arm => expr }- Struct literal:
Point { x: 1, y: 2 }or sugarPoint(1, 2) - Enum variant:
Color.Red,Option.Some(1) - Array literal:
[1, 2, 3] - Method call:
obj.method(args)— struct methods and built-in string methods - Field access:
obj.field— structs, tuples,Datefromdate() - Grouped:
(expr) await expr(parsed; MVP handle typei32)- Template literal:
`text ${expr} more` - Arrow function:
(x) => expr,x => expr,((a, b)) => expr, or typed(a: i32) => { ... }— see Closures expr as Type— cast (raw-pointer casts requireunsafe)
Unsafe & raw pointers
Nyra is safe by default. Low-level memory requires unsafe { }:
mut x = 42
unsafe {
let p = &x as *i32
*p = 99
print(*p)
}mut x = 42
unsafe {
let p = &x as *i32
*p = 99
print(*p)
}Inside unsafe | Outside unsafe |
|---|---|
*ptr load / *ptr = v store on *T or ptr | &T / &mut T only |
ptr + i32, ptr - i32 | Rejected |
expr as *T, ptr as i32 | Safe casts only (no raw pointers) |
| Borrow checker bypassed | Full NLL + move rules |
ptr = opaque FFI handle. *T = typed raw pointer for drivers/MMIO. Inline asm: asm "nop" inside unsafe. OS APIs: import "stdlib/os.ny". See Memory → unsafe, Stdlib → os.
Ownership quick ref
| Action | Copy type (i32) | Move type (string heap) |
|---|---|---|
let b = a | Both usable | a invalidated |
| Pass to function | Copied (unless mut) | Moved (unless mut) |
| Scope end | Stack discard | Auto free if heap-owned |
&a / &mut a | NLL borrows — end at last use of ref | Same + auto-drop at scope |
spawn { } | Copy captures OK | Move must be Send; moved into thread |
Beginner track: Nyra Ownership → Nyra Borrowing. Full rules: Memory & ownership. Developer UX: Ownership UX (auto-borrow, auto-Copy, inference).
Ownership UX
| Feature | What you write | What the compiler does |
|---|---|---|
| Auto-borrow | save(user) | save(&user) when param is &User |
| Auto-Copy | let p2 = p1 on Point | Both bindings valid if all fields Copy |
| Return inference | fn f() { return 1 } | Infers -> i32 or void |
| Generic call inference | id(7) | Monomorph id__i32 |
| Clone | clone user or user.clone() | Heap duplicate; binding kept |
| Move | move user | Explicit move; skips auto-borrow |
Diagnostics name the callee and suggest fixes. Conformance: CONF-INF-*, CONF-COERCE-*, CONF-DIAG-*, CONF-COPY-*, CONF-F64-*.
Lifetimes & HRTB
- Function lifetime params:
fn pick<'a>(a: &'a string) -> &'a string - Elision: one input
&T→ return&Tshares that lifetime - Ambiguous elision (multiple input refs, no annotation) → compile error
- HRTB callback type:
for<'a> fn(&'a string) -> &'a string
Traits (Drop)
impl Drop for MyType {
fn drop(self) {
// custom cleanup
}
}impl Drop for MyType {
fn drop(self) {
// custom cleanup
}
}Drop and Clone are wired in the compiler. User traits: trait defs, impl Trait for Type, and dynamic dispatch via dyn Trait / value as dyn Trait (Extended MVP). See Traits & macros and examples/trait_dyn.ny.
Compiler pipeline
Source (.ny) → Lexer → Parser → Macro expand → Monomorph (+ generic call inference) → Auto-borrow coercion → Typecheck → Ownership (Copy inference) → Borrow + Lifetimes + Send/Sync → Drop plan → LLVM IR (f64/double, spawn, custom drop) → opt → clang + Nyra runtime → binary
Stop early: nyra check . or nyra diag .. See Toolchain.