Expressions

An expression is a sequence of operators and their operands. An expression produces a result. For example, the expression (3 * 4) produces a result of 12. An expression may also produce side effects. For example, a function may update the value of a controller global variable (which is not directly part of the expression) before returning a value.

An expression can consist of one or more of the following.

Literals

A literal is a token with a constant value that is known at compilation time, such as 1.5. This is unlike expressions that are known only at runtime, such as the position command of an axis.

Numeric Literals

Numeric literals include both integer literals and floating-point literals.

Integer Literals

Integer literals are any constant value that can be represented by the fundamental integer data type (integer). Integer literals can be either of the following types.

  • Decimal literals (base 10)

    0|[1-9][0-9]*
  • Hexadecimal literals (base 16)

    0x[0-9A-Fa-f]+

The following example shows proper usage of integer literal types.

$ival = 123
$hexval
= 0xBEEF
$myVal
= -0xaf
$xorVal
= 0xA0A0A0A0 ^ 0xFFFFFFFF

Floating-Point Literals

Floating-point literals are any constant value that can be represented by a fundamental floating-point type (real). Floating-point literals include all of the strings that match the following regular expressions. Note that floating-point literals contain a superset of integer literals (for example, 1234 is a valid floating-point literal).

[0-9]+[Ee][+-]?[0-9]+
[0-9]*"."[0-9]+([Ee][+-]?
[0-9]+)?
[0-9]+"."[0-9]*([Ee][+-]?[0-9]+)?

The following example shows many different ways that proper floating-point literals can be formed.

$fval = 1.0
$myVar
= -8
$expVal
= 2E+09
$three
= 3.
$dVal
= -1e-3
$someVal
= .3
$decimal = 0.25
$oneThousand = 1.e3

Care must be taken when using exponential notation with G-code due to the existence of the E command, which is part of the G-code dialect. Refer to G-Code and Exponential Notation for more information.

String Literals

A string literal is defined as a sequence of zero or more characters surrounded by double quote characters, as described by the following regular expression.

\"(\\.|[^\\"])*\"

The previous regular expression can be broken down into:

  • An opening double quote character (")

  • Any number (zero or more) of the following:

    • A backslash character (\) followed by any other character

    • Any character that is not a double quote character (any character except ")

  • A closing double quote character (")

The need for this seemingly odd way of specifying a string literal is due to the need to support escape sequences (such as the newline escape sequence \n) within a string literal. The escape sequence \" inserts a double quote character (") into the text of the string literal itself. Therefore, "Hello\" is an invalid string literal because the trailing double quote character (") is actually part of the escape sequence \", and not the string literal as a whole.

The example that follows shows proper usage of string literal types.

var $myStr as string(32) = "Hello World!\n"
$myStr = StringUpper("abc123")
$myStr = ""
$myStr
= "Hello" + "World"

String Character Escape Sequences

In addition to normal printable characters, escape sequences may be used in a string in order to use special characters that can’t be represented with normal keys on a keyboard.

Escape sequences can be useful for when a string must be displayed or printed, or be sent to another device (e.g., over a serial communication protocol or through a network socket).

// When printed, this string will display as the following:
// Hello

// World!

$myStr
= "Hello\nWorld!"
 
// This string will be indented due to the tab (\t) escape sequence:
//     Hey

$myStr2
= "\tHey"

Acceptable escape sequences are as follows. Specifying an invalid escape sequence, such as \c, within a string literal will cause a compiler error.

Escape Sequence

Meaning

\a

Alert (“bell”)

\b

Backspace

\f

Form feed

\n

Newline (or line-feed)

\r

Carriage return

\t

Horizontal tab

\v

Vertical tab

\"

Double quote

\\

Backslash

\nnn

ASCII character with given octal value (n=an octal digit 0-7)1

\xhh

ASCII character with given hex value (hh=one or two hex digits 0-F)2

\Uhhhh

Unicode 16-bit code point (h=a hex digit 0-F)

\Uhhhhhhhh

Unicode 32-bit code point (h=a hex digit 0-F)

1. Octal escape sequences can only contain up to 3 octal digits. After parsing 3 octal digits, the compiler will continue parsing a string literal as normal, even if there are more octal digits. For example, the "\1024" string will be parsed as "\102" (the ASCII character "B") followed by the character "4", so "B4" is the resulting string literal. Notice that the largest representable octal escape sequence "\777" (511 in decimal) does not represent a valid ASCII character, and the compiler will produce an error if you specify invalid octal escape sequences.

2. Hexadecimal escape sequences may contain any number of hexadecimal characters (0-F). However, this escape sequence can only be used to specify individual bytes, so sequences such as "\xFFFF" that are larger than the range that can be specified within a byte will be considered a compilation error.

Operators and Intrinsic Functions

Mathematical, Logical, and Bitwise Operators

The following tables show a list of all operators that can be performed with numeric (those having a data type of integer or real) operands.

Assignment and Compound Assignment Operators

Assignment operators assign a value to a variable. Therefore, each of these operators must have a variable on the left hand side. However, the right hand side may be any expression whose data type is valid for the variable on the left hand side.

Operator

Description

a = b

Simple assignment

a += b

Addition assignment

a -= b

Subtraction assignment

a *= b

Multiplication assignment

a /= b

Division assignment

Increment/Decrement Operators

Increment and decrement operators increase or decrease a variable by a value of 1, respectively. The operand must be a variable.

Operator

Description

a++

Increment

a--

Decrement

Arithmetic Operators

Operator

Description

-a

Unary negation

+a

Unary plus

a + b

Addition

a - b

Subtraction

a * b

Multiplication

a / b

Division

a % b

Modulo (Remainder)

a ** b

Exponentiation (Power)

Comparison (Relational) Operators

Operator

Description

a == b

Test equality

a != b

Test inequality

a > b

Test greater than

a >= b

Test greater than or equal to

a < b

Test less than

a <= b

Test less than or equal to

Logical Operators

Operator

Description

!a

Returns true if its operand is false; otherwise returns false

a && b

Returns true if both of its operands can be converted to true; otherwise returns false

a || b

Returns true if at least one of its operands can be converted to true; otherwise returns false

Bitwise Operators

Note that bitwise operators are only valid on integer operands. However, they are also valid on real operands, provided that the value stored in the real represents a valid integer (e.g., 3.00000).

Operator

Description

a & b

Returns a bitwise AND of its two operands

a | b

Returns a bitwise OR of its two operands

a ^ b

Returns a bitwise XOR of its two operands

~a

Returns a bitwise NOT (complement) of its operand

a << b

Returns the value of the first operand bitwise shifted left by the value of the second operand

a >> b

Returns the value of the first operand bitwise arithmetically (signed) shifted right by the value of the second operand

Member Access Operators

Operator

Description

a[b]

Array element indexing

a.b

Structure member access

String Operators

These operators accept operands with the string data type.

Operator

Description

a = b

String assignment

a += b

String concatenation assignment

a + b

String concatenation

Miscellaneous Operators and Intrinsic Functions

Operator

Description

@a

Converts operand (integer, real, or string) to an axis

length(a)

Returns the length (number of elements) of an array operand

Operation Result Data Type

An operation with two numeric operands of the same type will yield a result of the same type. For example, the addition of an integer and another integer produces an integer.

When performing an assignment, arithmetic, or relational operation with two numeric operands, one of the operands may be promoted to a different type before the operation takes place. For example, adding an integer value to a real value produces a result whose type is real. Bitwise operations always produce an integer value, regardless of the types of the operands.

A string can only be part of an operation with other string values. For example, you cannot add an integer value to a string value. However, functionality exists in the API to convert between types explicitly. See Variable Type Conversions for more information on this topic.

Other data types, such as axis and handle, can only be used in very specific operations. For example, an error will occur during compilation for an operation where an axis is added to an integer, or a handle is multiplied by a real.

Short-Circuiting

Short-circuiting is when the result of a conditional expression is able to be determined before all of its arguments have been evaluated. This behavior can improve the performance of program execution because in some cases, not all expressions need to be completely evaluated.

Two of the logical operators, && (logical AND) and || (logical OR), have short-circuiting behavior. If the first operand to the && operator is false, then the operation returns false regardless of the value of the second operand. The second operand does not have to be evaluated in this case. If the first operand to the || operator is true, then the operation returns true regardless of the second operand. Again, the second operand does not need to be evaluated in this case.

if (0 && ($iglobal[0] > 0))
   // This code is never executed regardless of the value of $iglobal[0]
   Enable(X)
end
 
if (1 || $rglobal[0])
   // This code is always executed regardless of the value of $rglobal[0]
   Enable(X)
end

Short-circuiting behavior can be used to avoid side effects. In the following example, MyFunc() will not execute if $rglobal[0] is less than or equal to 0.

if (($rglobal[0] > 0) && MyFunc())
   // MyFunc() won't execute in the above conditional
end

Short-circuiting is also commonly used to prevent a value from being used in a conditional expression further to the right, for example, if the programmer knows that evaluating some condition may cause an error. In C/C++, short-circuiting is used in many cases to prevent NULL pointers from being used in an expression. Another example is as follows, where short-circuiting can be used to prevent a division by zero within the conditional expression.

if ($rglobal[0] != 0.0) && ((1.0 / $rglobal[0]) < 0.5)
   // The expression on the right is not evaluated if $rglobal[0] == 0
   // ...
   // ...
end

Operator Precedence

Operator precedence defines the rules for specifying the order in which operators in an expression are evaluated. These rules closely match the mathematical rules for order of operation, but are expanded to include operators that aren’t found in normal mathematics, such as bitwise operators. For example, multiplication has higher precedence than addition.

// In the below expression, (2 * 3) is calculated first
// The expression then becomes $myVal = $myVal + 6

// (the expression does not become $myVal = ($myVal + 2) * 3)

$myVal
= $myVal + 2 * 3

Operator associativity is used to determine how to group operands with the same precedence. Left-associative operations, such as addition and multiplication, group operands starting from the left. Right-associative operations, such as exponentiation or variable assignment, group operands starting from the right.

// Multiplication is left-associative
// The expression below is evaluated as $result = ($valA * $valB) * $valC
$result = $valA * $valB * $valC
 
// Exponentiation is right-associative
// The expression below is evaluated as $result = $valA ** ($valB ** $valC)
$result
= $valA ** $valB ** $valC

Parentheses should be used to force operations in an expression to have a specific precedence. In addition, precedence rules vary slightly between languages, and using multiple operators in an expression is error-prone, so parentheses should be used to clarify the intent of an expression.

// Multiplication has higher precedence than addition, so $val1 = 11
var
$val1 = 1 + 2 * 3 + 4
 
// Adding parentheses overrides the default precedence, so $val2 = 21

var
$val2 = (1 + 2) * (3 + 4)

The table that follows shows the precedence of each operator in the language. Operators that are listed higher in the table have precedence over operators that are listed lower in the table. Operators in the same row have the same precedence.

Operator

Description

Associativity

a[b]

a()

a.b

Array element access

Function call

Structure member access

Left-to-right

a ** b

Exponentiation

Right-to-left

+a
-a

!a

~a

@a

Unary plus
Unary negation

Logical NOT

Bitwise NOT

Axis index

Right-to-left

a * b

a / b

a % b

Multiplication

Division

Modulo

Left-to-right

a + b

a - b

Addition

Subtraction

Left-to-right

a << b
a >> b

Bitwise shift left

Bitwise shift right

Left-to-right

a < b

a <= b

a > b
a >= b

Test less than

Test less than or equal

Test greater than

Test greater than or equal

Left-to-right

a == b

a != b

Test equality

Test inequality

Left-to-right

a & b

Bitwise AND

Left-to-right

a ^ b

Bitwise XOR

Left-to-right

a | b

Bitwise OR

Left-to-right

a && b

Logical AND

Left-to-right

a || b

Logical OR

Left-to-right

a = b

a += b

a -= b

a *= b

a /= b

a %= b

a++

a--

Simple assignment

Addition assignment

Subtraction assignment

Multiplication assignment

Division assignment

Modulo assignment

Variable increment

Variable decrement

Right-to-left

Array Manipulation

Array Manipulation Overview

An array is a data structure that consists of a collection of elements, each having the same data type. Each element in an array can be accessed by its index. Array indices are zero-based, meaning that the first element in an array has an index of 0, and the last element in the array has an index of (array length - 1).

// Declare an array of 5 integers
var
$array[5] as integer
 
// Set the first element in the array to 10
$array
[0] = 10
 
// Set the last element in the array to 20
$array
[4] = 20
 
// The following causes an error because the array index is out of bounds

$array
[8] = 30

Array indices may be constant values or the result of an expression. Array indices can be specified with an integer or real value, but they must be whole numbers.

var $array[5] as integer
var
$index as integer
 
$index = 3
 
// Set $array[4] to 3
$array[$index + 1] = 5
 
// This is valid because the index is a whole number
// Set $array[3] to 3

$array
[3.00000] = 3
 
// The following will generate an error
$array[2.5] = 123

Advanced Array Manipulation

Every array has a length (number of elements) that cannot be changed after it is created. Users can retrieve the length of an array by using the intrinsic length() function. This is especially useful in cases where the length of an array is not known, such as when an array is passed into a function that accepts an array of any length.

program
   var $arr1[] as axis = [X, Y, Z]
   var $arr2[6] as axis = [X, Y, Z, U, A, B]
 
   MyEnable($arr1)
   MyEnable($arr2)
   MyEnable([D])
end
 
function MyEnable($axes[] as axis)
   // The arrays of axes passed in can be any size
   // Use the length function to get the actual size of the array
   var $numAxes as integer = length($axes)
   var $index as integer
 
   for $index = 0 to $numAxes - 1
      Enable($axes[$index])
   end
end

The intrinsic length() function behaves in a straightforward way with one-dimensional arrays. However, for multi-dimensional arrays, the length() function returns the number of elements in the dimension that is specified.

var $myArray[4][1][7] as real
var $len as integer
 
// Sets $len to 4 because the first dimension of $myArray contains 4
// elements

$len
= length($myArray)
 
// Sets $len to 1 because the second dimension of $myArray contains 1
// element
$len
= length($myArray[0])
 
// Sets $len to 7 because the third dimension of $myArray contains 7
// elements
$len = length($myArray[1][2])
 
// Causes an error because $myArray[0][0][0] is a scalar (not an array)
$len
= length($myArray[0][0][0])

As an alternative to finding the length of an array and iterating over each array element by its index in a for loop, a foreach loop can be used to iterate over an array without needing to take its length into account.

var $ints[10] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
var
$sum as integer = 0
 
// Iterate through each element of $ints[], using $int as the "iterator"
foreach var
$int in $ints
   $sum += $int
end

Multi-dimensional arrays can be considered an “array of arrays.” For example, a variable that is a 3-by-3 array can also be thought of as an array with 3 elements, and each of those elements is itself an array with 3 elements. This is particularly useful in a case like the following scenario.

program
   var $matrix[3][3] as integer = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
   var $sum as integer = 0
 
   // SumRow() takes 1D arrays, but $matrix is a 2D array
   // However, $matrix[0], $matrix[1], and $matrix[2] are each 1D arrays
   $sum += SumRow($matrix[0])
   $sum += SumRow($matrix[1])
   $sum += SumRow($matrix[2])
end

 
// The following function takes a 1-dimensional array and returns its sum

function
SumRow($row[] as integer) as integer
   var $sum as integer = 0
 
   foreach var $val in $row
      $sum += $val
   end
 
   return $sum
end

String Manipulation

The string data type is immutable, meaning that the value of a string cannot be changed. As a result, each string modification actually results in the creation of a new string.

var $myStr as string(32)
var
$str2 as string
 
// Assign a string variable to a string "object"
$myStr
= "Hello"
 
// Create a new string from the character at index 1 in $myStr ("e")
$str2
= StringCharacterAt($myStr, 1)
 
// Create a new string from a substring of a string
// The following sets $str2 to "ello"

$str2
= StringSubstring($myStr, 1, StringLength($myStr))
 
// Modifying a character in a string can be accomplished by creating a new
// string from an existing string. The following produces "Yello"

$myStr
= "Y" + StringSubstring($myStr, 1, 4)

Next Topic: Statements