Scripting documentation
General explanation of the scripting
Some properties for components and structures support dynamically evaluated values, that are evaluated on-demand by the configuration engine. These properties can be scripted in an expression based declarative domain specific language. The scripts can refer to other properties, including other scriptable properties. However, cyclic dependencies are not allowed.
Examples
- Parent is connected to right:
this.Parent.IsConnectedRight
- Parent is connected to left:
this.Parent.IsConnectedLeft
- Parent is connected to left and connected to right:
this.Parent.IsConnectedLeft AND this.Parent.IsConnectedRight
- Parent is connected either to left or to right but not both directions at the same time:
this.Parent.IsConnectedLeft XOR this.Parent.IsConnectedRight
Basic logic features (operators)
Arithmetic operators
Multiplicative
- Times:
*
- Divide:
/
Additive
- Plus:
+
- Minus:
-
Equality operators
- Equals:
==
- Not equals:
!=
Relational operators
- Less:
<
- Less or equal:
<=
- Greater:
>
- Greater or equal:
>=
Logical Operators
- Negate:
NOT
- And:
AND
- Exclusive Or:
XOR
- Or:
OR
- Coalesce:
??
Reserved Words
- true: - True, boolean value
- false: - False, boolean value
- null: - null object
- if: - conditional if, followed by a boolean expression.
- then: - conditional then, followed by a value used in case the 'if' condition is true
- else: - conditional else, followed by a value used in case the 'if' condition is false
Operator precedence
In an expression with multiple operators, the operators with higher precedence are evaluated before the operators with lower precedence. For grouping and enforcing the operation precedence you can use .
Parentheses ()
can be used to group operands with their correct operator. They can be used in both logic and in arithmetic operations. Also like arithmetic operators, logical operators have precedence that determines how things are grouped in the absence of parentheses.
In an expression, the operator with the highest precedence is grouped with its operand(s) first, then the next highest operator will be grouped with its operands, and so on. If there are several logical operators of the same precedence, they will be examined left to right.
Examples
Grouping happens automatically based on the logical precedence for example:
A * B + C * D
is parsed as(A * B) + (C * D)
A + B * C + D
is parsed asA + (B * C) + D
A + B * C / D
is parsed asA + ((B * C) / D)
For logical operations
A AND B OR C
is parsed as(A AND B) OR C
A OR B AND C
is parsed asA OR (B AND C)
A AND B OR C AND D
is parsed as(A AND B) OR (C AND D)
A AND B AND C OR D
is parsed as((A AND B) AND C) OR D
Exclusive or can be decomposed into multiple Ands and Ors. i.e.:
A XOR B
equals(A AND (NOT B)) OR ((NOT A) AND B)
Of course, logical and arithmetic operations can be combined
(A + B > D) AND (A + B < E)
if-then-else
It is possible to use values based on a condition by using an if then else
statement.
if A > B then C else D
Also if-then-else can be used inside of another if-then-else as in the example below
=if 4>2 then
true
else if 5>2 then
false
else
true
If the value in then
or else
part is the main value of the scriptable property, they should be of the same type.
The 'condition', 'then' and 'else' values do not need to be surrounded by parentheses but in case of more complex scenarios one can use them to enforce a certain behavior.
Variables
Temporary values can be stored to variables by using custom properties.
Type system
The scripting features an implicit type system. Each script expression is type checked to ensure that the result matches the expected value type.
Primitive types
Type | Description | Example values |
---|---|---|
String | String | 'Hello!' |
Number | A floating point value | 2 , 5.7 |
Boolean | A truth value | true , false |
Null | The unit type | null |
Error | A result from erroneous calculation | 3 * false |
Vector / List
A vector or list is a value consisting of multiple values.
A new vector or a list can be constructed by using square brackets: [1, 2, 3]
Vector members can be accessed in two ways: Vector.X
or Vector[0]
.
Record
Record represents a collection of key-value pairs. Record entries can be accessed with the dot syntax this.Value
.
It is not currently possible to introduce custom record types.
Union
Union represents a value with multiple possible types. Union members are accessed implicitly.
Properties
Scripts are executed in the context of a specific component or structure, which can be accessed using the this
-keyword. It is also possible to omit the keyword, meaning that both this.Value
and Value
resolve to the same result. Properties can be discovered by using the debugger.
For a linear structure
- ComponentCount - Number of components in the linear structure
For a linear component
- IsConnectedLeft - True, if current element is connected to the left
- IsConnectedRight - True, if current element is connected to the right
- LeftComponent - Reference to the element connected to the left
- RightComponent - Reference to the element connected to the right
For a component
- this - Reference to the current element
- Parent - Reference to the parent element, ItemLists are skipped
For an editable value structure
- Value - Current value
For a slot structure
- IsConnected - True, if the slot is connected
- Component - The component currently connected to the slot
Error types
- Unknown: "Unknown Error",
- Unexpected type: "Expected '' but received ''.",
- Missing property: "Type '' does not contain a property ''.",
- Missing variant: "Union '' does not contain a variant with discriminant ''.",
- Invalid property access: "A value of type '' does not support property access ''.",
- Invalid unary op application: "Can't apply unary operator ({op.Symbol()}) to value of type ''.",
- Invalid binary op application: "Can't apply operator ({op.Symbol()}) to values of type '' and ''.",
- Invalid type conversion: "A value of type '' does not support property access ''.",
- Empty union: "Union '' has no valid variants.",
- Runtime error
Script Debugging
Script values can be debugged in the context of a configured product configuration. When viewing a plan inside the manager, a show debugger button is available under the library. The debugger gives detailed information
Ancestors
All of the parent components of the currently selected component, forming a route to the root component. Selecting a component will update the debugger to show info about that component.
Children
A list of all the child components the currently selected component has. Child components are organized by the structure they belong to. Selecting a component will update the debugger to show info about that component.
Properties
Lists all the properties with their values of the selected component. Includes both built-in and custom scripted properties. If a property value is a reference to another component, it becomes a link to navigate to that component. Properties that are record or vector types contain nested values. These are collapsed by default, and can be expanded.