»Language: Boolean Expressions

Boolean expressions are expressions that evaluate to a boolean value from the result of a combination of one or more comparisons and logical operators. Boolean expressions form the basis of policy since policy can be broken down to a set of logical decisions that turn into true or false.

A single boolean expression is the body of a rule. Additionally, boolean expressions are used with conditionals, and more.

»Order of Operations

The precedence of operators is shown below. Operators with higher precedence values (larger numbers) are evaluated first. Operators with the same precedence value are evaluated left-to-right.

Precedence    Operator
    6             *  /  %
    5             +  -
    4             else
    3             ==  !=  <  <=  >  >= "is" "is not" "matches" "contains" "in"
    2             and
    1             or  xor

Examples of this precedence are shown below:

4 * 5 / 5 // 4
4 * 5 + 2 // 22
4 + 5 * 2 // 14

»Logical Operators

Logical operators are used to change or combine logical expressions. There are three binary operators and, or, and xor. There is a single unary operator not (which can also be specified as !).

The binary operators require two boolean operands and the unary operator requires a single boolean operand. In both case, the operands are values or expressions that are boolean types.

Below is a basic explanation of the logical operators directly from the specification:

and    conditional AND    p and q  is  "if p then q else false"
or     conditional OR     p or q   is  "if p then true else q"
xor    conditional XOR    p xor q  is  "if p and not q or not p and q then true"
!      NOT                !p       is  "not p"
not    NOT                !p       is  "not p"

Using parentheses to group boolean expressions, you can combine boolean expressions to become more complex or affect ordering:

(p and q) or r
p and (q or r)

»Comparison Operators

Comparison operators compare two operands and yield a boolean value.

For any comparison, the two operands must be equivalent types. The one exception are integers and floats. When an integer is compared with a float, the integer is promoted to a floating point value.

The available comparison operators are:

==       equal
!=       not equal
<        less
<=       less or equal
>        greater
>=       greater or equal
"is"     equal
"is not" not equal

The behavior of is with == and is not with != is identical.

Example comparisons:

name is "Mitchell"
idnumber > 42
idnumber <= 12

Using the logical operators, these can be combined:

name is "Mitchell" and idnumber > 42

The language specification provides more detail on exactly how comparison behaves.

»Set Operators

The set operators contains and in test for inclusion in a collection (a list or map).

Set operators may be negated by prefixing the operator with not, such as not contains and not in. This is equivalent to wrapping the expression in a unary not but results in a more readable form.

contains tests if the left-hand collection contains the right-hand value. in tests if the right-hand collection contains the left-hand value. For maps, "contains" looks at the keys, not the values.


[1, 2, 3] contains 2            // true
[1, 2, 3] contains 5            // false
[1, 2, 3] contains "value"      // false
[1, 2, 3] not contains "value"  // true

{ "a": 1, "b": 2 } contains "a"     // true
{ "a": 1, "b": 2 } contains "c"     // false
{ "a": 1, "b": 2 } contains 2       // false
{ "a": 1, "b": 2 } not contains 2   // true

»Matches Operator

The matches operator tests if a string matches a regular expression. The matches operator can be negated by prefixing the operator with not, such as not matches.

The left-hand value is the string to test. The right-hand value is a string value representing a regular expression. The syntax of the regular expression is the same general syntax used by Python, Ruby, and other languages. The precise syntax accepted is the syntax accepted by RE2.

Regular expressions are not anchored by default; any anchoring must be explicitly specified.

"test" matches "e"            // true
"test" matches "^e"           // false
"TEST" matches "test"         // false
"TEST" matches "(?i)test"     // true
"ABC123" matches "[A-Z]+\\d+" // true
"test" not matches "e"        // false

»Any, All Expressions

any and all expressions allow testing that any or all elements of a collection match some boolean expression. The result of an any and all expression is a boolean.

any returns the boolean value true if any value in the collection expression results in the body expression evaluating to true. If the body expression evalutes to false for all values, the any expression returns false.

all returns the boolean true if all values in the collection expression result in the body expression evaluating to true. If any value in the collection expression result in the body expression evaluating to false, the all expression returns false.

For empty collections, any returns false and all returns true.

all group.tasks as t { t.driver is "vmware" }
any group.tasks as t { t.driver is "vmware" }

Since any and all expressions are themselves boolean expressions, they can be combined with other operators:

any ["a", "b"] as char { char is "a" } or
other_value is "another"

»Emptiness Comparison

The expressions is empty and is not empty provide a convenience method for determining the emptiness of a value. It supports the same types as the built-in length, collections and strings.

[] is empty            // true
[] is not empty        // false
["foo"] is empty       // false
["foo"] is not empty   // true
undefined is empty     // undefined
undefined is not empty // undefined