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 (3.0 or "Hello World")
-
Data Types and Variables ($myVar or $iglobal[0])
-
Operators and Intrinsic Functions (+ or <<)
-
Aerotech Standard Library API Functions (specifically those that return a value, StatusGetAxisItem())
-
User-Defined Functions (specifically those that return a value, MyAdd())
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.
$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]*"."[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.
$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.
$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).
// 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.
// 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.
// 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.
// 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.
// 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.
// 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.
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 |
Unary plus 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 |
Bitwise shift left Bitwise shift right |
Left-to-right |
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).
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 $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.
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 $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 $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.
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 $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