Lesson 1: Basics

1.1 Variables and Values

AetherShell uses immutable bindings by default. Use = for immutable, := for mutable.

// Immutable binding (cannot be reassigned)
x = 10
print(x)  // 10

// Mutable binding (can be reassigned)
y := 20
y = 30
print(y)  // 30

// String values
name = "Alice"
greeting = "Hello, ${name}!"
print(greeting)  // "Hello, Alice!"

1.2 Basic Types

// Numbers
integer = 42           // Int
floating = 3.14        // Float

// Strings
text = "Hello"         // Str

// Booleans
flag = true            // Bool
condition = false      // Bool

// Arrays
numbers = [1, 2, 3]    // Array
mixed = [1, "two", 3]  // Arrays can be heterogeneous

// Null
nothing = null         // Null

1.3 Operators

// Arithmetic
10 + 5    // 15
10 - 5    // 5
10 * 5    // 50
10 / 5    // 2
10 % 3    // 1

// Comparison
10 == 10  // true
10 != 5   // true
10 > 5    // true
10 < 20   // true
10 >= 10  // true
10 <= 10  // true

// Logical
true && false   // false
true || false   // true
!true           // false

// String concatenation
"Hello" + " " + "World"  // "Hello World"
Exercise: Try calculating the area of a circle with radius 5 using pi = 3.14.

Lesson 2: Pipelines - The Heart of AetherShell

2.1 What are Pipelines?

Pipelines let you chain operations together, passing data from left to right using the | operator.

// Simple pipeline
[1, 2, 3] | print

// Multi-step pipeline
[1, 2, 3, 4, 5]
| map(fn(x) => x * 2)      // [2, 4, 6, 8, 10]
| where(fn(x) => x > 5)    // [6, 8, 10]
| reduce(fn(a,b) => a+b, 0) // 24
| print

2.2 Pipeline with map

// Double all numbers
[1, 2, 3] | map(fn(x) => x * 2)
// Result: [2, 4, 6]

// Square all numbers
range(1, 6) | map(fn(n) => n * n)
// Result: [1, 4, 9, 16, 25]

// Convert to uppercase
["hello", "world"] | map(fn(s) => upper(s))
// Result: ["HELLO", "WORLD"]

2.3 Pipeline with where (filter)

// Filter even numbers
[1, 2, 3, 4, 5, 6] | where(fn(x) => x % 2 == 0)
// Result: [2, 4, 6]

// Filter long strings
["a", "bb", "ccc"] | where(fn(s) => len(s) > 1)
// Result: ["bb", "ccc"]

2.4 Pipeline with reduce

// Sum of array
[1, 2, 3, 4, 5] | reduce(fn(a, b) => a + b, 0)
// Result: 15

// Product of array
[1, 2, 3, 4] | reduce(fn(a, b) => a * b, 1)
// Result: 24

// Find maximum
[3, 7, 2, 9, 1] | reduce(fn(a, b) => max(a, b), 0)
// Result: 9

2.5 Complex Pipeline Example

// Calculate sum of squares of even numbers from 1-10
range(1, 11)
| where(fn(x) => x % 2 == 0)           // [2, 4, 6, 8, 10]
| map(fn(x) => x * x)                   // [4, 16, 36, 64, 100]
| reduce(fn(acc, val) => acc + val, 0)  // 220
| print
Exercise: Create a pipeline that finds all odd numbers from 1-20, triples them, and sums the result.

Lesson 3: Functions

3.1 Lambda Syntax

// Single parameter
double = fn(x) => x * 2
print(double(5))  // 10

// Multiple parameters
add = fn(a, b) => a + b
multiply = fn(a, b) => a * b

print(add(3, 4))       // 7
print(multiply(3, 4))  // 12

// No parameters
get_pi = fn() => 3.14159
print(get_pi())  // 3.14159

3.2 Functions in Pipelines

// Inline functions
[1, 2, 3] | map(fn(x) => x * x)

// Named functions
square = fn(x) => x * x
[1, 2, 3] | map(square)

// Both work the same!

3.3 Higher-Order Functions

// Function that returns a function
make_adder = fn(n) => fn(x) => x + n

add5 = make_adder(5)
add10 = make_adder(10)

print(add5(3))   // 8
print(add10(3))  // 13

// Function composition
compose = fn(f, g) => fn(x) => f(g(x))

times2 = fn(x) => x * 2
plus3 = fn(x) => x + 3

times2_then_plus3 = compose(plus3, times2)
print(times2_then_plus3(5))  // 13 (5*2=10, 10+3=13)
Pro Tip: AetherShell supports closures - functions can capture variables from their enclosing scope!

Lesson 4: Type System

4.1 Type Inference

AetherShell uses Hindley-Milner type inference. Types are automatically inferred!

// Types are inferred, not declared
x = 42              // Inferred as Int
y = 3.14            // Inferred as Float
s = "hello"         // Inferred as Str
arr = [1, 2, 3]     // Inferred as Array

// Check types at runtime
print(type_of(x))    // "Int"
print(type_of(y))    // "Float"
print(type_of(s))    // "Str"
print(type_of(arr))  // "Array"

4.2 Structured Types

// Records (like objects/structs)
person = {
    name: "Alice",
    age: 30,
    active: true
}

print(person.name)   // "Alice"
print(person.age)    // 30

// Arrays of records
users = [
    {name: "Alice", age: 30},
    {name: "Bob", age: 25},
    {name: "Charlie", age: 35}
]

// Filter and transform
adults = users | where(fn(u) => u.age >= 30)
names = adults | map(fn(u) => u.name)

4.3 Type Safety

// Operations must be type-compatible
x = 10
// x + "hello"  // Error: cannot add Int and Str

// But you can convert types
num_str = "42"
// num = parse_int(num_str)  // Convert string to int

Lesson 5: Records & Tables

5.1 Working with Records

// Create a record
user = {
    id: 1,
    name: "Alice",
    email: "alice@example.com",
    roles: ["admin", "user"]
}

// Access fields
print(user.name)      // "Alice"
print(user.roles)     // ["admin", "user"]

// Get all keys
keys(user)  // ["id", "name", "email", "roles"]

5.2 Tables (Arrays of Records)

// File listings are tables!
files = ls(".")

// Filter large files
large_files = files | where(fn(f) => f.size > 10000)

// Get just names
file_names = large_files | map(fn(f) => f.name)

// Count files
total = files | len
print("Total files: ${total}")

5.3 Table Transformations

// Create a table
products = [
    {name: "Laptop", price: 999, stock: 5},
    {name: "Mouse", price: 25, stock: 50},
    {name: "Keyboard", price: 75, stock: 20}
]

// Find expensive items
expensive = products | where(fn(p) => p.price > 50)

// Calculate total value
total_value = products 
| map(fn(p) => p.price * p.stock)
| reduce(fn(a, b) => a + b, 0)

print("Total inventory value: $${total_value}")

Lesson 6: File Operations

6.1 Listing Files

// List current directory
files = ls(".")
print(files)

// Filter by type
dirs = files | where(fn(f) => f.type == "directory")
regular = files | where(fn(f) => f.type == "file")

6.2 Reading Files

// Read entire file
content = cat("README.md")
print(content)

// Read first 10 lines
preview = head("README.md", 10)

// Read last 10 lines
tail_lines = tail("logfile.txt", 10)

6.3 Searching Files

// Find all Rust files
rust_files = find(".", "*.rs")
print(rust_files)

// Search file content
matches = grep("README.md", "AetherShell")
print(matches)

6.4 Processing Text Files

// Read file and process lines
cat("data.csv")
| split("\n")                    // Split into lines
| where(fn(line) => len(line) > 0)  // Remove empty lines
| map(fn(line) => split(line, ",")) // Split each line by comma
| print

Lesson 7: AI Basics

7.1 Simple AI Agent

// Deploy an agent with a goal
result = agent("Count all .rs files in src/", "ls,find", 5)
print(result)

7.2 AgenticBinary Protocol

// Encode a message
ping_msg = ab_encode("command", "ping", "hello")
print(ping_msg)  // [0, 5, 104, 101, 108, 108, 111]

// Decode the message
decoded = ab_decode(ping_msg)
print(decoded.msg_type)  // "Command"
print(decoded.opcode)    // "PING"
print(decoded.payload)   // "hello"

7.3 All Message Types

// Command messages
cmd = ab_encode("command", "exec", "run_task")

// Query messages
query = ab_encode("query", "query", "get_status")

// Response messages
resp = ab_encode("response", "ack", "received")

// Event messages
event = ab_encode("event", "sync", "state_update")
Note: AI features require setting up environment variables like OPENAI_API_KEY or running local models with Ollama.

Lesson 8: Multi-Agent Systems

8.1 Agent Communication

// Worker registers with coordinator
worker_ready = ab_encode("response", "ack", "worker1:ready")

// Coordinator delegates task
task = ab_encode("command", "delegate", "analyze_logs")

// Worker executes
exec = ab_encode("command", "exec", "started:analysis")

// Worker reports result
result = ab_encode("response", "data", "analysis_complete")

8.2 Agent Collaboration

// Agent requests help
collab_req = ab_encode("command", "collaborate", "agent2:need_data")

// Agent shares knowledge
learn_msg = ab_encode("command", "learn", "protocol:new_syntax")

// Agent acknowledges learning
ack = ab_encode("response", "ack", "learned:new_syntax")

8.3 Error Handling

// Agent encounters error
error = ab_encode("response", "error", "task_failed:timeout")

// Coordinator reassigns
retry = ab_encode("command", "delegate", "retry_task")

Lesson 9: Syntax Knowledge Base

9.1 Discovering Protocols

// List all available protocols
protocols = syntax_list("protocol")
print(protocols)  // ["ab", "jsonrpc", "http"]

// Get protocol details
ab_spec = syntax_get("ab")
print(ab_spec.name)           // "AgenticBinary Protocol"
print(ab_spec.specification)  // Full spec...

9.2 Searching Syntax

// Search for binary-related syntax
results = syntax_search("binary")
print(results)  // ["ab"]

// Search for all protocols
all_protos = syntax_search("protocol")
print(all_protos)

9.3 Adding Custom Syntax

// Define custom protocol
my_protocol = {
    id: "myproto",
    name: "My Custom Protocol",
    category: "protocol",
    specification: "Custom communication protocol...",
    examples: ["example 1", "example 2"]
}

// Add to knowledge base
syntax_add(my_protocol)

// Retrieve it later
retrieved = syntax_get("myproto")
print(retrieved.name)  // "My Custom Protocol"

Lesson 10: Advanced Patterns

10.1 Factorial with Reduce

// Calculate 5! = 120
factorial = fn(n) =>
    range(1, n + 1)
    | reduce(fn(a, b) => a * b, 1)

print(factorial(5))  // 120
print(factorial(10)) // 3628800

10.2 Fibonacci Sequence

// Generate first N fibonacci numbers
fib = fn(n) => {
    a := 0
    b := 1
    result := [0, 1]
    i := 2
    while (i < n) {
        next = a + b
        result = push(result, next)
        a = b
        b = next
        i = i + 1
    }
    result
}

print(fib(10))  // [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

10.3 Data Processing Pipeline

// Process CSV data
cat("data.csv")
| split("\n")                          // Lines
| where(fn(line) => len(line) > 0)    // Non-empty
| map(fn(line) => split(line, ","))   // Parse CSV
| where(fn(row) => len(row) > 2)      // Valid rows
| map(fn(row) => {                    // Extract fields
    name: row[0],
    age: row[1],
    city: row[2]
  })
| where(fn(person) => person.age > "30")  // Filter
| map(fn(p) => p.name)                 // Get names
| print

10.4 Multi-Agent Task Distribution

// Complete workflow example
// See examples/13_agent_coordination.ae for full implementation

// 1. Workers learn protocol
spec = syntax_get("ab")

// 2. Workers signal ready
worker1_ready = ab_encode("response", "ack", "worker1:ready")

// 3. Coordinator delegates tasks
task1 = ab_encode("command", "delegate", "analyze_data")
task2 = ab_encode("command", "delegate", "process_logs")

// 4. Workers execute and report
exec1 = ab_encode("command", "exec", "started:analyze")
result1 = ab_encode("response", "data", "complete:results.json")

// 5. Coordinator reflects
reflection = ab_encode("command", "reflect", "efficiency:95%")

🎓 Congratulations!

You've completed the AetherShell tutorial! You now know:

Next Steps