📖 Syntax Reference
Complete AetherShell language specification
Overview
AetherShell is a functional-first, typed shell language with AST-based evaluation and Hindley-Milner type inference. Every construct is an expression that returns a value.
Key Principle: In AetherShell, data flows as structured
Value types (Int,
Float, String, Array, Record, Lambda), not raw text.
Literals
Numbers
| Type | Syntax | Examples |
|---|---|---|
| Integer | digits |
42, 0, -123 |
| Float | digits.digits |
3.14, 0.5, -2.718 |
Strings
| Form | Syntax | Example |
|---|---|---|
| Plain | "text" |
"Hello, world!" |
| Interpolated | "text ${expr} text" |
"Result: ${x + 1}" |
| Escapes | \n \t \\ \" |
"Line 1\nLine 2" |
Booleans & Null
true // Boolean true
false // Boolean false
null // Null value
Arrays
[] // Empty array
[1, 2, 3] // Integer array
["a", "b", "c"] // String array
[1, "two", 3.0] // Heterogeneous array
[[1,2], [3,4]] // Nested arrays
Records (Objects)
{} // Empty record
{x: 10} // Single field
{name: "Alice", age: 30} // Multiple fields
{x: 1, nested: {y: 2}} // Nested records
Variables
Immutable Bindings
x = 10 // Immutable - cannot reassign
name = "Alice" // Immutable string
list = [1,2,3] // Immutable reference
// x = 20 // ERROR: Cannot reassign immutable binding
Mutable Bindings
y := 10 // Mutable - can reassign
y = 20 // OK
y = y + 5 // OK
counter := 0
counter = counter + 1 // OK
Important: Use
= for immutable (default), := for mutable
bindings.
Operators
Arithmetic Operators
| Operator | Description | Example | Result |
|---|---|---|---|
+ |
Addition | 10 + 5 |
15 |
- |
Subtraction | 10 - 5 |
5 |
* |
Multiplication | 10 * 5 |
50 |
/ |
Division | 10 / 5 |
2 |
% |
Modulo | 10 % 3 |
1 |
Comparison Operators
| Operator | Description | Example | Result |
|---|---|---|---|
== |
Equal | 10 == 10 |
true |
!= |
Not equal | 10 != 5 |
true |
< |
Less than | 5 < 10 |
true |
> |
Greater than | 10 > 5 |
true |
<= |
Less or equal | 10 <= 10 |
true |
>= |
Greater or equal | 10 >= 10 |
true |
Logical Operators
| Operator | Description | Example | Result |
|---|---|---|---|
&& |
Logical AND | true && false |
false |
|| |
Logical OR | true || false |
true |
! |
Logical NOT | !true |
false |
String Operators
// Concatenation
"Hello" + " " + "World" // "Hello World"
// Interpolation
name = "Alice"
"Hello, ${name}!" // "Hello, Alice!"
Functions (Lambdas)
Lambda Syntax
// General form: fn(params) => expression
// No parameters
get_pi = fn() => 3.14159
// Single parameter
double = fn(x) => x * 2
// Multiple parameters
add = fn(a, b) => a + b
multiply = fn(x, y, z) => x * y * z
// Block body
complex = fn(x) => {
temp = x * 2
result = temp + 10
result
}
Function Application
// Direct call
double = fn(x) => x * 2
result = double(5) // 10
// In pipeline
[1,2,3] | map(fn(x) => x * 2)
// As argument
apply = fn(f, x) => f(x)
apply(double, 5) // 10
Closures
// Functions capture outer scope
make_adder = fn(n) => fn(x) => x + n
add5 = make_adder(5)
add5(3) // 8
add5(10) // 15
Pipeline Operator
Basic Pipeline
// Syntax: expr | function
value | print
[1,2,3] | len
// Chaining
[1,2,3] | map(fn(x) => x * 2) | print
Multi-line Pipelines
[1, 2, 3, 4, 5, 6]
| where(fn(x) => x % 2 == 0) // [2, 4, 6]
| map(fn(x) => x * x) // [4, 16, 36]
| reduce(fn(a, b) => a + b, 0) // 56
| print
Pipeline Context
The value on the left is passed as the first argument to the function on the right.
// These are equivalent:
[1,2,3] | map(fn(x) => x * 2)
map([1,2,3], fn(x) => x * 2)
// Explicit vs piped
len([1,2,3]) // Direct call
[1,2,3] | len // Piped call
Control Flow
If Expression
// Syntax: if condition { expr } else { expr }
x = 10
result = if x > 5 {
"large"
} else {
"small"
}
// result = "large"
// Nested if
status = if x > 10 {
"high"
} else if x > 5 {
"medium"
} else {
"low"
}
Match Expression
// Pattern matching
value = 2
result = match value {
1 => "one",
2 => "two",
3 => "three",
_ => "other"
}
// result = "two"
// Match with guards (future feature)
// match x {
// n if n > 0 => "positive",
// 0 => "zero",
// _ => "negative"
// }
While Loop
// Syntax: while condition { statements }
i := 0
sum := 0
while (i < 10) {
sum = sum + i
i = i + 1
}
// sum = 45
Note: Prefer functional approaches (map, reduce, filter) over loops when possible.
Record Access
Field Access
person = {name: "Alice", age: 30}
// Dot notation
person.name // "Alice"
person.age // 30
// Nested access
data = {user: {name: "Bob", id: 123}}
data.user.name // "Bob"
Array Indexing
arr = [10, 20, 30, 40]
// Zero-indexed
arr[0] // 10
arr[2] // 30
arr[-1] // 40 (last element)
// Nested
matrix = [[1,2], [3,4]]
matrix[0][1] // 2
Comments
// Single-line comment
x = 10 // Inline comment
// Multi-line comments:
// Line 1
// Line 2
// Line 3
/* Block comments (if supported)
Multi-line
Comment block
*/
Blocks & Scope
Block Expressions
// Block evaluates to last expression
result = {
x = 10
y = 20
x + y
}
// result = 30
Lexical Scoping
x = 10
{
x = 20 // Shadows outer x
print(x) // 20
}
print(x) // Still 10 (outer scope unchanged with =)
Mutable Scoping
x := 10
{
x = 20 // Modifies outer x (mutable)
print(x) // 20
}
print(x) // 20 (outer x was modified)
Type Annotations (Future)
Note: Type inference is automatic. Explicit annotations may be added in future
versions.
// Current (inferred)
add = fn(a, b) => a + b
// Future possibility (annotated)
// add: (Int, Int) => Int = fn(a, b) => a + b
// name: Str = "Alice"
// items: [Int] = [1, 2, 3]
Reserved Keywords
| Keyword | Usage |
|---|---|
fn |
Lambda definition |
if |
Conditional |
else |
Alternative branch |
match |
Pattern matching |
while |
Loop |
true |
Boolean literal |
false |
Boolean literal |
null |
Null literal |
Grammar Summary (EBNF-style)
Program = Statement*
Statement = VarDecl | Expression
VarDecl = Ident "=" Expression // Immutable
| Ident ":=" Expression // Mutable
Expression = Literal
| Ident
| Lambda
| Pipeline
| BinaryOp
| UnaryOp
| IfExpr
| MatchExpr
| WhileExpr
| Block
| Call
| FieldAccess
| IndexAccess
Literal = Int | Float | String | Bool | Null | Array | Record
Lambda = "fn" "(" Params? ")" "=>" (Expression | Block)
Pipeline = Expression "|" Expression
BinaryOp = Expression Operator Expression
Operator = "+" | "-" | "*" | "/" | "%" | "==" | "!=" | "<" | ">" | "<=" | ">=" | "&&" | "||"
UnaryOp = "!" Expression | "-" Expression
IfExpr = "if" Expression Block ("else" (Block | IfExpr))?
MatchExpr = "match" Expression "{" MatchArm+ "}"
MatchArm = Pattern "=>" Expression ","
WhileExpr = "while" "(" Expression ")" Block
Block = "{" Statement* Expression? "}"
Call = Expression "(" Args? ")"
FieldAccess = Expression "." Ident
IndexAccess = Expression "[" Expression "]"
Operator Precedence
| Precedence | Operator | Associativity |
|---|---|---|
| 1 (Highest) | . [] () |
Left |
| 2 | ! - (unary) |
Right |
| 3 | * / % |
Left |
| 4 | + - |
Left |
| 5 | < > <= >= |
Left |
| 6 | == != |
Left |
| 7 | && |
Left |
| 8 | || |
Left |
| 9 | | (pipeline) |
Left |
| 10 (Lowest) | = := |
Right |
Quick Reference Card
Essential Syntax
// Variables
x = 10 // Immutable
y := 20 // Mutable
// Functions
fn(x) => x * 2
fn(a, b) => a + b
// Pipelines
[1,2,3] | map(fn(x) => x * 2)
// Arrays & Records
[1, 2, 3]
{name: "Alice", age: 30}
// Control flow
if x > 0 { "pos" } else { "neg" }
match x { 1 => "one", _ => "other" }
while (i < 10) { i = i + 1 }
// Operators
+ - * / % // Arithmetic
== != < > <= >= // Comparison
&& || ! // Logical
| // Pipeline
Next: Check out Built-in Functions for all available
operations, or Type System to understand type inference.