LOG IN SIGN UP
Documentation

Operators

Fastly's VCL provides various arithmetic and conditional operators. Operators are syntactic items which evaluate to a value. Syntax is given in a BNF-like form with the following conventions:

Where a binary operator is provided, not all types are implemented on either side. This is a limitation of the current implementation. The following placeholder grammatical clauses are used in this document to indicate which types are valid operands. These are not precisely defined until the grammar has been formally specified, and are intended as a guide for operator context only.

Operator precedence

Operator precedence defines the order of operations when evaluating an expression. Higher precedence operators are evaluated before those with lower precedence. Operators are listed in the following table as the highest precedence first. For example, a || b && c reads as a || (b && c) because && has higher precedence than ||.

Operator associativity determines which side binds first for multiple instances of the same operator at equal precedence. For example, a && b && c reads as (a && b) && c because && has left to right associativity.

Operator Name Associativity
( ) Grouping for precedence left to right
! Boolean NOT right to left
&& Boolean AND left to right
|| Boolean OR left to right

Negation

Numeric literals may be negated by prefixing the - unary operator. This operator may only be applied to literals, and not to numeric values in other contexts.

:= [ "-" ] CNUM
 | [ "-" ] CNUM "." [ CNUM ]

String concatenation

Adjacent strings are concatenated implicitly, but may also be concatenated explicitly by the + operator:

:= string-expr string-expr
 | string-expr "+" _string-expr

For example, "abc" "def" is equivalent to "abcdef".

Assignment and arithmetic operators

The set syntax is the only situation in which these operators may be used. Since the operator may only occur once in a set statement, these operators are mutually exclusive, so precedence between them is nonsensical.

The values the operators produce are used for assignment only. The set statement assigns this value to a variable, but does not itself evaluate to a value.

FLOAT arithmetic has special cases for operands which are NaN: Arithmetic operators evaluate to NaN when either operand is NaN.

FLOAT arithmetic has special cases for operands which are floating point infinities: In general all arithmetic operations evaluate to positive or negative infinity when either operand is infinity. However some situations evaluate to NaN instead. Some of these situations are domain errors, in which case fastly.error is set to "EDOM" accordingly. Others situations are not domain errors: ∞ − ∞ and 0 × ∞. These evaluate to NaN but do not set fastly.error.

Assignment

Assignment is provided by the = operator:

:= "set" variable "=" assignment-expr ";"

Addition and subtraction

Addition and subtraction are provided by the += and -= operators respectively:

:= "set" variable "+=" assignment-expr ";"
 | "set" variable "-=" assignment-expr ";"

Multiplication, division and modulus

Multiplication, division and modulus are provided by the *=, /= and %= operators respectively:

:= "set" variable "*=" assignment-expr ";"
 | "set" variable "/=" assignment-expr ";"
 | "set" variable "%=" assignment-expr ";"

Bitwise operators

:= "set" variable "|=" assignment-expr ";"
 | "set" variable "&=" assignment-expr ";"
 | "set" variable "^=" assignment-expr ";"
 | "set" variable ">>=" assignment-expr ";"
 | "set" variable "<<=" assignment-expr ";"
 | "set" variable "ror=" assignment-expr ";"
 | "set" variable "rol=" assignment-expr ";"

Right shifts sign-extend negative numbers. For example, -32 >> 5 gives -1.

Shift and rotate operations with negative shift widths perform the operation in the opposite direction. For example, 32 << -5 gives 1. For right operands larger than the width of INTEGER, shifts will yield zero or -1 and rotates will use the operand modulo the width of INTEGER.

Logical operators

Logical AND and OR operators are provided by the &&= and ||= operators respectively:

:= "set" variable "&&=" assignment-expr ";"
 | "set" variable "||=" assignment-expr ";"

These are short-circuit operators; see below.

Conditional operators

Conditional operators produce BOOL values, suitable for use in if statement conditions.

Logical operators

Conditional expressions may be inverted by prefixing the ! operator:

:= "!" conditional-expr

Boolean AND and OR operators (&& and || respectively) are defined for conditional expressions:

:= conditional-expr "&&" conditional-expr
 | conditional-expr "||" conditional-expr

These boolean operators have short-circuit evaluation, whereby the right-hand operand is only evaluated when necessary in order to compute the resulting value. For example, given a && b when the left-hand operand is false, the resulting value will always be false, regardless of the value of the right-hand operand. So in this situation, the right-hand operand will not be evaluated. This can be seen when the right-hand operand has a visible side effect, such as a call to a function which performs some action.

Comparison operators

FLOAT comparisons have special cases for operands which are NaN: The != operator always evaluates to true when either operand is NaN. All other conditional operators always evaluate to false when either operand is NaN. For example, if a given variable is NaN, that variable will compare unequal to itself: both var.nan == var.nan and var.nan >= var.nan will be false.

STRING comparisons have special cases for operands which are not set (as opposed to empty): The != and !~ operators always evaluate to true when either operand is not set. All other conditional operators always evaluate to false when either operand is not set. For example, if a given variable is not set, that variable will compare unequal to itself: both req.http.unset == req.http.unset and req.http.unset ~ ".?" will be false.

Floating point infinities are signed, and compare as beyond the maximum and minimum values for FLOAT types, such that for any finite value: −∞ < n < +∞

The comparison operators are:

lg-op := "<" | ">" | "<=" | ">="
eq-op := "==" | "!="
re-op := "~" | "!~"

Equality is defined for all types:

:= expr eq-op expr

Inequalities are defined for numeric types and TIME:

:= numeric-expr lg-op numeric-expr
 | time-expr lg-op time-expr

Note that as there are currently no numeric expressions in general; these operators are limited to use with specific operands. For example, var.i < 5 is permitted but 2 < 5 is not.

Regular expression conditional operators are defined for STRING types and ACLs only:

:= string-expr re-op STRING
 | acl re-op STRING

The right-hand operand must be a literal string (regular expressions cannot be constructed dynamically).

Reserved punctuation

Punctuation appears in various syntactic roles which are not operators (that is, they do not produce a value).

Punctuation Example Uses
{ } Block syntax
[ ] Stats ranges
( ) Syntax around if conditions, function argument lists
/ Netmasks for ACLs
, Separator for function arguments
; Separator for statements and various other syntactic things
! Invert ACL entry
. To prefix fields in backend declarations
: Port numbers for backend declarations, and used in the stats syntax

The following lexical tokens are reserved, but not used: * & | >> << ++ -- %


Back to Top