Browse the documentation

Preview documentation for AEL Beta 0.0.1 — launching soon

Control flow

AEL, the Agent Engineering Language, will have four ways to direct control: if, while, match and return. Each will be a statement, and the check will make sure that every path through a function ends the way its type says.

Status

Planned for AEL Beta 0.0.1. AEL is not available yet.

if and else

Preview syntax — may change before launch
fn shipping(weight: u32, express: bool) -> u32 {
    if express {
        return 20;
    } else {
        if weight > 1_000 {
            return 12;
        }
    }
    return 5;
}
  • The condition will have to be a bool. An integer, text or Option will never be a condition.
  • The condition will need no parentheses; the blocks will always need braces.
  • else will take a block. To test a further condition, put an if inside that block, as above.
  • Only the chosen block will run.

while

Preview syntax — may change before launch
fn sum_to(limit: u64) -> u64 {
    let mut total: u64 = 0;
    let mut n: u64 = 1;
    while n <= limit {
        total = total + n;
        n = n + 1;
    }
    return total;
}
  • The condition will be checked before every pass, including the first, so the body may run zero times.
  • There will be no break or continue. End a loop through its condition, or leave the function with return.

match

match will compare one value against patterns, in order, and run the block of the first that fits.

Preview syntax — may change before launch
enum Reply {
    Empty,
    Text(Str<200>),
    Code(u16, Str<40>),
}

fn status(reply: Reply) -> u16 {
    match reply {
        Reply::Empty => { return 204; }
        Reply::Code(code, _) => { return code; }
        _ => { return 200; }
    }
}
  • The value will be evaluated once.
  • The patterns will have to cover every possible value, and none may repeat another. A pattern after _ could never be reached, so it will be refused.
  • An enum will need every variant, or _. A bool will need true and false, or _. Integer patterns, such as 0 or -1, will need a final _.
  • You will be able to bind a variant's values to names, as code above, or skip them with _. Binding a value will move it out of the matched value; see Ownership.
  • Each arm will be a block. Its names will be visible only inside it.
  • Patterns will be the wildcard, true and false, integers and enum variants. Structs, text, lists and references will be inspected with ordinary code instead, and a pattern will not be able to carry an extra condition.

Option and Result will be enums, so match will be how you handle them:

Preview syntax — may change before launch
fn port_or_default(configured: Option<u16>) -> u16 {
    match configured {
        Option::Some(port) => { return port; }
        Option::None => { return 8080; }
    }
}

return

  • return value; will leave the function with a value of exactly its result type.
  • A function that returns unit will be able to write return;, or simply reach the end of its body.
  • Every path through a function with a result will have to end in a return. The check will count a while loop as possibly running zero times, so a return that appears only inside a loop is not enough: add one after the loop.

Statements, not expressions

if and match will not produce values, and a block will not produce the value of its last line. To choose a value, give a binding its value in every branch:

Preview syntax — may change before launch
fn fee(member: bool) -> u32 {
    let amount: u32;
    if member {
        amount = 0;
    } else {
        amount = 3;
    }
    return amount;
}

The check will make sure that amount has a value on every path before it is read. Ownership describes the rule.

Loops and waiting

On a microcontroller, one handler will run at a time, until it waits for something. A loop that never waits will keep every other handler waiting, so keep the work between waits bounded. Concurrency describes scheduling.