Files
lux/docs/reference/syntax.md
Brandon Lucas 44f88afcf8 docs: add comprehensive language documentation
Documentation structure inspired by Rust Book, Elm Guide, and others:

Guide (10 chapters):
- Introduction and setup
- Basic types (Int, String, Bool, List, Option, Result)
- Functions (closures, higher-order, composition)
- Data types (ADTs, pattern matching, records)
- Effects (the core innovation)
- Handlers (patterns and techniques)
- Modules (imports, exports, organization)
- Error handling (Fail, Option, Result)
- Standard library reference
- Advanced topics (traits, generics, optimization)

Reference:
- Complete syntax reference

Tutorials:
- Calculator (parsing, evaluation, REPL)
- Dependency injection (testing with effects)
- Project ideas (16 projects by difficulty)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-13 17:43:41 -05:00

6.8 KiB

Language Reference: Syntax

Complete syntax reference for Lux.

Lexical Structure

Comments

// Single-line comment

/* Multi-line
   comment */

/// Documentation comment (for declarations)

Identifiers

identifier     = letter (letter | digit | '_')*
type_name      = upper_letter (letter | digit)*

Examples: foo, myVar, Type, Option

Literals

// Integers
42
-17
1_000_000      // Underscores for readability
0xFF           // Hexadecimal
0b1010         // Binary

// Floats
3.14
2.5e10
-1.5e-3

// Strings
"hello"
"line1\nline2"              // Escape sequences
"value: ${expression}"      // String interpolation
"multi
line
string"

// Characters
'a'
'\n'
'🎉'

// Booleans
true
false

// Unit
()

// Lists
[]
[1, 2, 3]
["a", "b", "c"]

// Records
{}
{ x: 1, y: 2 }
{ name: "Alice", age: 30 }

Escape Sequences

Sequence Meaning
\n Newline
\t Tab
\r Carriage return
\\ Backslash
\" Double quote
\' Single quote
\$ Dollar sign

Declarations

Functions

// Basic function
fn name(param: Type): ReturnType = body

// Multiple parameters
fn add(a: Int, b: Int): Int = a + b

// Block body
fn complex(x: Int): Int = {
    let y = x * 2
    y + 1
}

// With effects
fn greet(name: String): Unit with {Console} =
    Console.print("Hello, " + name)

// With type parameters
fn identity<T>(x: T): T = x

// With constraints
fn show<T>(x: T): String where T: Show = x.show()

// With behavioral properties
fn pure_add(a: Int, b: Int): Int is pure = a + b

// With visibility
pub fn exported(): Int = 42

// With documentation
/// Computes the factorial of n
pub fn factorial(n: Int): Int =
    if n <= 1 then 1 else n * factorial(n - 1)

Types

// Type alias
type UserId = Int

// Enum (sum type)
type Color =
    | Red
    | Green
    | Blue

// With data
type Option<T> =
    | Some(T)
    | None

// With named fields
type Person =
    | Person { name: String, age: Int }

// Record type
type Point = { x: Int, y: Int }

// With visibility
pub type PublicType = ...

Effects

effect EffectName {
    fn operation1(param: Type): ReturnType
    fn operation2(): Type
}

// Example
effect Logger {
    fn log(level: String, message: String): Unit
    fn getLevel(): String
}

Handlers

handler handlerName: EffectName {
    fn operation1(param) = {
        // implementation
        resume(value)
    }
}

// Example
handler consoleLogger: Logger {
    fn log(level, msg) = {
        Console.print("[" + level + "] " + msg)
        resume(())
    }
    fn getLevel() = resume("debug")
}

Traits

trait TraitName {
    fn method(self): ReturnType
    fn method2(self, param: Type): ReturnType
}

impl TraitName for Type {
    fn method(self): ReturnType = ...
    fn method2(self, param: Type): ReturnType = ...
}

Let Bindings

// Top-level
let name = value
let name: Type = value
pub let exported = value

// Local (in blocks)
let x = 42
let (a, b) = (1, 2)

Expressions

Literals

See Lexical Structure above.

Variables

x
myVariable
Some

Function Application

f(x)
f(x, y, z)
moduleName.function(arg)

Operators

// Arithmetic
a + b    // Addition
a - b    // Subtraction
a * b    // Multiplication
a / b    // Division
a % b    // Remainder
-a       // Negation

// Comparison
a == b   // Equal
a != b   // Not equal
a < b    // Less than
a > b    // Greater than
a <= b   // Less or equal
a >= b   // Greater or equal

// Boolean
a && b   // And
a || b   // Or
!a       // Not

// String
s1 + s2  // Concatenation

Conditionals

if condition then expr1 else expr2

if condition then
    expr1
else
    expr2

// Chained
if c1 then e1
else if c2 then e2
else e3

Match Expressions

match value {
    pattern1 => expr1,
    pattern2 => expr2,
    _ => default
}

// With guards
match value {
    n if n > 0 => "positive",
    n if n < 0 => "negative",
    _ => "zero"
}

// Nested patterns
match expr {
    Add(Num(0), x) => x,
    Mul(x, Num(1)) => x,
    _ => expr
}

Blocks

{
    statement1
    statement2
    result_expression
}

// Statements can be:
// - let bindings
// - expressions (for side effects)

Lambda Expressions

fn(x: Type): ReturnType => body

// Examples
fn(x: Int): Int => x * 2
fn(a: Int, b: Int): Int => a + b
fn(): Unit => Console.print("hi")

Run Expressions

run expr with {}

run expr with {
    Effect1 = handler1,
    Effect2 = handler2
}

// Example
run computation() with {
    Logger = consoleLogger,
    Database = mockDb
}

Field Access

record.field
module.function

Tuple Construction

(a, b)
(x, y, z)

Record Construction

{ field1: value1, field2: value2 }

// Update
{ ...existing, field: newValue }

List Construction

[]
[1, 2, 3]
[head, ...tail]

Patterns

Used in match expressions and let bindings:

// Literal
42
"hello"
true

// Variable (binds the value)
x
name

// Wildcard (matches anything)
_

// Constructor
Some(x)
None
Pair(a, b)

// Tuple
(x, y)
(a, b, c)

// List
[]
[x]
[x, y]
[head, ...tail]

// Record
{ name, age }
{ name: n, age: a }

// With guard
x if x > 0

Type Expressions

// Primitive
Int
Float
Bool
String
Char
Unit

// Named
TypeName
ModuleName.TypeName

// Generic application
Option<Int>
Result<String, Error>
List<T>

// Function
fn(Int): Int
fn(Int, String): Bool
fn(T): T with {Effect}

// Tuple
(Int, String)
(A, B, C)

// Record
{ x: Int, y: Int }
{ name: String, age: Int }

// List
List<Int>

Modules

Imports

// Full module
import path/to/module

// With alias
import path/to/module as alias

// Selective
import path/to/module.{item1, item2}

// Wildcard
import path/to/module.*

Exports

// Public declarations
pub fn publicFunction(): Int = ...
pub type PublicType = ...
pub let publicValue = ...

// Private (default)
fn privateFunction(): Int = ...

Grammar Summary

program      = import* declaration*

import       = 'import' path ('as' ident)?
             | 'import' path '.{' ident (',' ident)* '}'
             | 'import' path '.*'

declaration  = function | type | effect | handler | trait | impl | let

function     = 'pub'? 'fn' ident type_params? '(' params ')' ':' type
               ('with' '{' effects '}')? ('is' properties)?
               ('where' constraints)? '=' expr

type         = 'pub'? 'type' ident type_params? '=' type_def

effect       = 'effect' ident '{' operation* '}'

handler      = 'handler' ident ':' ident '{' impl* '}'

expr         = literal | ident | application | binary | unary
             | if | match | block | lambda | run | field

pattern      = literal | ident | '_' | constructor | tuple | list | record