Skip to content

Expressions

Shaye Garg edited this page Sep 29, 2021 · 3 revisions

An expression is something that can result in a value. behave has many types of expressions.

None

This expression has no type and no value:

none

Literals

Literal expressions, and the types they generate, have been explained here.

Blocks

In behave, blocks are expressions. This allows you to evaluate multiple expressions and combine them in places where a single expression is expected. This is also used to easily return values from functions.

{
    <statement>;
    ...
    <expr> // Note the absence of a semicolon
}
/// Which would be:
{
    let a = some_value();
    let b = some_other_value();
    [a, b]
}

This block expression results in an array containing the return values of the functions some_value and some_other_value.

Code

Code expressions are unique to behave. They consist of RPN code that will be executed in Microsoft Flight Simulator when passed to appropriate template expressions.

Code expressions are created by prefixing a block with @:

@{
    let a = @"L:MyCustomLocalVariable";
    a
}

In code expressions, you cannot create maps, arrays, or structs. However, you can access values declared outside the code block.

You can read from and assign to MSFS variable by prefixing an expression that results in a str with @. The above code reads the value from (L:MyCustomLocalVariable). You can also add units after the variable:

@"A:SomeAircraftVariable, Bool"

Access

You can access variables declared simply by referring to their name:

let a = 10;
a

Index

You can index into arrays and maps with the appropriate values:

<ident>[<expr>]
/// Which would be:
let a = [0, 1];
a[0]

Assignment

You can assign variables and elements in an array or map.

let a = 5;
a = 10;
let b = ["Hi": "Bye"];
b["Hi"] = "You should say hi";

Assignments result in the same value as the value that was assigned:

a = b = c = 10;

This would set a, b, and c to 10.

Unary expressions

You can use the not operator (!) to flip the value of a boolean.

You can use the negation operator (-) to negate a number.

Binary expressions

You can add (+) strings, numbers, arrays, and maps together.

You can subtract (-) numbers from each other.

You can multiply (*) and divide (/) numbers.

You can do a logical and (and) and logical or (or) on booleans.

You can equate all data types (== and !=).

You can compare numbers (>, >=, <, <=).

Calls

You can call functions:

<path>(<expr>, ...)
/// Which would be:
my_function(1 + 1)

behave has an inbuilt function for formatting: format. Don't try to pass it as an argument anywhere or do anything with it other than call it. You'll probably crash the compiler.

Use it like:

format("String I want to format: {}", 420);

Format replacements are denoted by {}, and currently there is no way to change how to format values.

The types that can be formatted are:

  1. str
  2. num
  3. bool

Ifs

You can have branching in expressions:

if <expr> {
    <block>
} else if <expr> {
    <block>
} else {
    <block>
}

All blocks must return the same type or you're gonna have a bad day.

Switches

You can even have switch expressions:

switch <expr> {
    <expr> -> <expr>,
    ...
}

The switch expression evaluates the expression and then finds the first case that is equal to it. It then evaluates the expression belonging to the case and then returns the value.

If none of the cases match, it returns none.

Is

You can use an is expression to check the type of an expression. This used to check what value was passed into a sum type, and results in a boolean:

<expr> is <type>
/// Which would be:
a is num

As

You can use an as expression to cast types in RPN code. The valid casts are:

  1. RPN value read as an 'Enum' to any enum.
  2. Boolean to num.

Return

A return expression returns out of the current function or quits RPN evaluation with the value provided to it:

return
return <expr>
/// Which would be:
return
return 1 + 1

Clone this wiki locally