You are reading the documentation for an outdated Corteza release. 2023.9 is the latest stable Corteza release.

Expressions

Corteza defines an expression language which is used when defining field expressions, workflow steps, as well as contextual roles.

Under the hood, we use Gval as the expression evaluation engine. Refer to the official documentation for technical details.

Syntax

The most basic form of an expression would follow the following pattern:
<variable|constant|function> <operator> <variable|constant|function>

In later texts, we alias the above string and its variations with expression.

To examplify:
lead.values.totalCost / 10

You can expand the expression by applying additional constructs such as addition and division.

To examplify:
average(min(lead.values.a, lead.values.b), abs(lead.values.c))

Variables

The expression engine does not allow you to define custom variables within the expression itself. All variables are defined by the system where the expression is being executed in.

The available variables are either documented in the system’s user interface or in dedicated documentation pages.

Objects

Objects allow you to encapsulate different bits of information into a single variable, such as a user, role, or record.

The primitive object-like data types include KV and KVV; other component defined object-like data types can be found here

In the simplest form, an object is defined like so:
{
  "username": "testUser",
  "email": "test@mail.tld"
}
If we would like to reference the entire object, we would reference the variable; for example:
newUser // results with { "username": "testUser", "email": "test@mail.tld" }
If we would like to reference specific properties of the object, we would use a selector; for example:
newUser.username // results with "testUser"
newUser["username"] // results with "testUser"

An object selector can use either the ["<selector>"] or the .<selector> notation.

Missing properties

Accessing missing (non-existing) properties throws an error:

myKV = { "a": "value-of-a" }
myB = myKV.b // throws an error: unknown parameter myKV.b
Use the ternay operator to make a simple, one-line test expression.
myB = has(myKV, "b") ? myKV.b : "b does not exist"
Deeper structures can also be checked in a similar way
deepKV = { "a": { "b": 42 } }
myB = has(deepKV, "a") && has(deepKV.a, "b") ? deepKV.a.b : "a.b does not exist"

Missing record values

Record values can be accessed in the same way as object and other key-value types. Underlying selector mechanism on record values performs extra checks and allows selection (reading) of unset values as long as the module field exists.

// Accessing defined fields on a record
hit1 = myRecord.values.existingFieldWithValueSet
hit2 = myRecord.values.existingFieldWithoutAValue

// Accessing undefined fields on a record
miss = myRecord.values.unknownField // will raise an error: "unknown parameter myRecord.values.unknownField"
Use the null coalescing operator to make a simple one-line test expression for unset fields.
failsafe = myRecord.values.existingFieldWithoutAValue ?? 'value was not yet set'

Arrays

Arrays allow you to encapsulate a series of values into a single variable, such as a list of leads or contacts we would like to create.

Array is the only native array data type. An array can contain any data type, including another array.

Nested arrays allow you to define a multidimensional matrix.

In the simplest form, an array is defined like so:
[{
  "username": "testUser1",
  "email": "test+1@mail.tld"
}, {
  "username": "testUser2",
  "email": "test+2@mail.tld"
}]
If we would like to reference the entire array, we would reference the variable; for example:
newUsers // results with [{ "username": "testUser1", "email": "test+1@mail.tld" }, { "username": "testUser2", "email": "test+2@mail.tld" }]
If we would like to reference specific elements of the array, we would use a selector; for example:
newUser[0] // results with { "username": "testUser1", "email": "test+1@mail.tld" }
newUser[1] // results with { "username": "testUser2", "email": "test+2@mail.tld" }
If we wanted to access a property of the object that is inside an array, we would add an object selector:
newUser[0]["email"] // results with "test+1@mail.tld"

An array selector can only use the [] notation.

Operators

Arithmetic

  • + (addition)

  • - (subtraction)

  • * (multiplication)

  • ** (power of)

  • / (division)

  • % (modulo)

Comparison

  • < (less then)

  • (less or equal then)

  • > (greater then)

  • >= (greater or equal then)

  • == (equal)

  • != (not equal)

String comparison only:
  • =~ (equal regular expression)

  • !~ (not equal regular expression)

Boolean algebra

  • && (and)

  • || (or)

  • ! (not)

Bit operations

  • << (shift)

  • >> (un shift)

  • & (bitwise and)

  • | (bitwise or)

Ternary conditional

  • ?: (ternary: a?b:c if-a-then-b-else-c)

  • ?? (null coalescing operator: a??b if-a-is-not-null-then-a-else-b)

Order of execution

Expressions follow "the usual order" of execution where the order is initially based on operator precedence where the operators with equal precedence are executed left to right.

To examplify; the order of execution for the expression of a + b + (c + d * e) would be:

  1. d * e (x1)

  2. c + x1 (x2)

  3. a + b (x3)

  4. x3 + x2

The execution order may be controlled by enclosing parts of the expression within brackets ().

Operator precedence

0

left to right

  • ()

  • []

  • .

1

right to left

  • +

  • -

  • !

2

left to right

  • *

  • **

  • /

  • %

3

left to right

  • +

  • -

4

left to right

  • <<

  • >>

5

left to right

  • <

  • >

  • >=

6

left to right

  • ==

  • !=

  • =~

  • !~

7

left to right

  • &

8

left to right

  • |

9

left to right

  • &&

10

left to right

  • ||