Operation Language Reference
Introduction
This page contains the summary and examples for every statement in the operation language of DMLA. It also contains the brief description of the type system used by DMLA.
Type System
Primitive Types
DMLA supports three primitive types that correspond to classical primitive types in most other languages are only compatible with their own types:
- String
- Number
- Bool
Entity Types
Every entity - both custom and pre-defined - in DMLA comes with their own type, similarly to classes in the object-oriented world. An entity is compatible with its meta entities. For example, if an operation expects entity A, then it accepts entity B if A is the meta of B, but not vice versa.
The Entity keyword refers to any entity type, but not primitive types. The Object keyword refers to either an entity or primitive type. These keywords can be used to define variables (see later) or as operation parameters.
Array Types
Arrays have their own base type (e.g. a Number array or a Product array). Their type compatibility follows the same rules as non-array types, according to their base type. Arrays can be returned by built-in operations or iterated using a foreach statement, but cannot be explicitly instantiated. Arrays can only be one-dimensional.
Nullability
Any type can be marked nullable using the ? symbol. Non-nullable types are incompatible with nullable types. An expression of nullable type can be made non-nullable by using the nullbang (!!) operator. Be aware that this can cause runtime exceptions if a non-nullable type gets assigned a null value.
Examples:
Instance Of and Cast Expressions
Use is or as to check or cast types.
Examples:
x is Product; // Check if `x` is a `Product`
y as Entity?; // Cast `y` to an optional (nullable) `Entity`
Expressions
Primary Expressions
Primary expressions include literals, variable references, or other basic building blocks. Expressions can stand alone or be used in more complex expressions.
Examples:
true // A boolean literal
42 // A number literal
"Hello" // A string literal
MyEntity // A variable (referencing an entity)
Index Expressions
Index expressions access specific elements in an array. Indexing starts from zero. Indexing out of bounds causes an exception.
Examples:
arr[0]; // Access the first element of `arr`
slotList[index + 1]; // Access an element in `slotList` via an expression using the `index` variable
This Expressions
The this expression refers to the entity that directly runs the current operation. The entity directly running the current operation may be different from the entity in which the operation is actually defined. This can occur when an entity runs an operation defined in one of its (direct or indirect) meta entities.
Examples:
this.Name; // Access the `Name` attribute of the current entity
if (includeSelf && meta==this) // `this` can be used in expressions as well
Operation Call Expressions
Operation calls invoke either global operations or operations of entities. These expressions can stand alone or can be a part of a more complex expression.
Examples:
PrintError("Error"); // Call a global operation
MyEntity.MyOperation(); // Call an operation on `MyEntity` (which is an entity ID)
myVar.MyOperation(); // Call an operation on `MyEntity` (which is a variable referring to an entity)
this.SupportedDeviceModels.Contains(deviceModel) // Calls the `Contains` operation on the `SupportedDeviceModels` slot of `this` entity
Prefix and Postfix Expressions
These expressions use increment (++) or decrement (--) operators before or after a variable. These operators only work on variables of typeNumber.
Examples:
++x; // Prefix increment: Increment `x` before using it
y--; // Postfix decrement: Use `y` first, then decrement
Logical Expressions
Logical expressions can combine the classical Boolean logical operators (<, >, <=, >=, ==, !=) with the && (and) or || (or) operators.
Examples:
Arithmetic Expressions
Arithmetic expressions perform calculations using the classical arithmetic operators +, -, *, /, and %.
Examples:
Ternary Expressions
Ternary expressions are compact if-else expressions.
Examples:
Elvis Expressions
The Elvis operator (?:) provides a default value when the first operand is null.
Examples:
Parenthesized Expressions
By using parentheses, expressions can be grouped explicitly, modifying the precedence of operators.
Examples:
Negation Expressions
The ! operator negates a logical expression or a variable of type Bool.
Examples:
String Interpolation
String literals can contain one or more placeholders which are replaced at runtime with their corresponding values. Placeholders can be defined using the following syntax: ${placeholder}.
Examples:
PrintError("ERROR: ${GetID(ent)} is invalid: ${errorMsg}\n\r"); // Contains two placeholders: `GetID(ent)` - a built-in operation call and `errorMsg` - a variable
Variable Definition
Variables are defined by their type and their name. A variable must always be assigned an initial value which must be a valid expression. The variable's type can either be a primitive type, a specific Entity type (e.g., Product), or a general entity type using the Object or Entity keywords (see the differences in the type system). If a variable is of an entity type, a new entity must be instantiated using the new keyword. Alternatively, an existing entity can be assigned to the variable's value via its ID.
Variables can also be defined as an array of a specific type. An array can either be static (by assigning a maximum size) or dynamic. Variables of an array type are no exceptions, they too must be assigned an initial value. Similarly to instantiating a new entity, creating a new array must be done using the new keyword.
Examples:
Number index = 0;
Bool result = false;
String text = "test";
Product p = new Product; // Assign a newly instantiated entity to a variable (`new Product')
Entity e = MyProduct.Price; // Assign an existing entity to a variable via its ID (`MyProduct.Price`)
Number[10] priorities = new Number[10];
Machine[] machines = this.Machines;
Assignment Statement
Assignment statements modify the value of an existing variable. Use the = operator for direct assignment or the compound operators +=, -=, *=, or /= for combining assignment with arithmetic operators.
Examples:
x = 42; // Assign a new value to `x`
myEntity = Product.Price; // Assign a new value to `myEntity`
y += 10; // Add 10 to `y` and reassign its value
z *= 2; // Double the value of `z`
If Statement
The if statement evaluates a condition and executes a statement block if the condition is true. Optionally, it can include an else block.
Examples:
if (x > 0) {
y = 10;
}
else {
y = -10;
}
if (errorMsg!=null)
PrintError("ERROR: ${GetID(ent)} is invalid: ${errorMsg}\n\r");
While Statement
The while statement repeats a block of code as long as its condition evaluates to true.
Examples:
while (currentMeta != null) {
// Do something with currentMeta...
currentMeta = GetMeta(currentMeta!!);
}
For Statement
The for statement includes initialization, condition, and update expressions to iterate a block of code.
Examples:
Foreach Statement
The foreach statement iterates over elements in an array.
Examples:
Return Statement
The return statement exits an operation and optionally returns a value. Only operations with a return type of void can return without a value.
Examples:
Throw Statement
The throw statement raises an exception, optionally initializing it with data. In addition to newly instantiated exceptions, variables that are of an exception type can also be thrown.
Examples:
throw myException; // Throw a variable without initialization since `myException` has its original value
// Throw a newly instantiated `ValidationException`, initializing it with data
throw new ValidationException {
ValidationSource = this;
Meta = GetMeta(subject);
Instances = new Base[subject];
Category = "BS/Slot";
ErrorCode = "BS_Slot_1";
Message = "Invalid slot ${GetID(subject)}, cannot instantiate Slot directly (use Base.Fields instead)";
};
Try-Catch Statement
The try-catch statement handles exceptions in a block of code.
Examples:
Break Statement
The break statement exits a loop prematurely.
Examples:
Continue Statement
The continue statement skips the current iteration of a loop and proceeds with the next.
Examples: