The followind types of constants are available in VTCL:
In case of model element constants, a corresponding element should be present in the model space (at compile time), otherwise an error message is issued.
machine vtcl_constants { rule main() = seq { // Undefined constant println(undef); // Boolean constants println(true); println(false); // String constants print("Hello VIATRA2 world!"); // Integer constants println(4); println(-4); // Double constants print(4.6); print(-4.7); print(6.6e2); print(10e-2); // Model elemenent constants // (provided that entity testing.models.manager exists in model space) print(fqn(testing.models.manager)); print(fqn('testing')); // Multiplicity constant print(one_to_one); print(one_to_many); print(many_to_one); print(many_to_many); } }
Logical terms consist of usual binary Boolean operators such as "&&" (and), "||" (or), "xor" (exclusive or), and unary operator "!" (not).
The precedence of Boolean operators are as follows: "!" (highest), "&&", { "||"; "xor" } (lowest). Operator precedence can be overridden by parenthesis. All previous operators tie as usual (to the left)
Equality (and inequality) operators, namely, "==" (equal), and "!=" (not equal), are also allowed for Boolean values.
There are two logical constants: "true" and "false".
machine logical_operators{ rule main() = seq { print(!true); print(!false); print(true && false); print(true || false); print(true xor false); print(true == true); print(false != true); // The internal pairs of parenthesis are not needed print((true && false) || (true && true)); print((true == true) != false)); // The internal pairs of parenthesis are needed print((true || false) && (true || false)); print(true == (true != false)); } }
Arithmetic terms can be constructed by binary and unary operators in the following way:
Binary operators
Unary operators:
For numerical values, they are treated as in Java, for instance.
machine arithmetic_terms_1 { rule main() = seq { // Add print(3 + 4); print(4.0 + 3); // also 3+4.0 is correct print(5.9 + 4.5); // Subtract print(3 - 4.0); print(4 - 3); print(4.5 - 5.9); // Multiply print(3 * 4); print(4.0 * 3); print(5.9 * 4.5); // Divide print(10 / 4.0); print(6.0 / 3); print(6 / 3); print(9.0 / 4.5); // Remainder: for integers print(14 % 4); } }
Strings can be added with any other kind of terms, but no other operations are allowed.
machine arithmetic_terms_2 { rule main() = seq { print(3 + "hello"); print(3.9 + "hello");
print("hello" + 4); print("hello" + 3.4); print("hello" + "test"); print("hello" + true); print(false + "hello");
print("hello" + one_to_many); print(many_to_one + "hello"); } }
Finally, it should be pointed out that any arithmetic operations are allowed for the undef constant regardless of the type of the other operand
The relational operators of the VTCL language are the following:
Any numerical types can be compared to
machine relation_operations_1 { rule main() = seq { // Integers and doubles (interchangeably) print(4.0 != 4.0); print(4 == 4); print(4.0 <= 4.0); print(4 >= 4.0); print(4.0 < 4.1); print(4 > 3); // Strings print("apple" == "melon"); print("apple" != "melon"); // Boolean print(true == false); print(true != false); // Multiplicities print(many_to_one == many_to_many); // false print(many_to_one != many_to_many); // true print(many_to_one <= many_to_many); // true print(many_to_one >= many_to_many); // false print(many_to_one < many_to_many); // true print(many_to_one > many_to_many); // false
// Undef (in all relational operation // with all kinds of values) print(undef == 4); print(undef < 4); } }
The following conversion functions are available to create different values of a certain type from other elements:
The undefined value can be converted to any other type.
machine conversion_operations_1 { rule main() = seq { // toString() print(toString(true)); print(toString("abc")); print(toString("3.14")); print(toString(1)); print(toString(1.0)); print(toString(one_to_one)); print(toString(undef)); //toBoolean() print(toBoolean(true)); print(toBoolean("viatra")); print(toBoolean(1)); print(toBoolean(1.0)); print(toBoolean(undef)); //toInteger() print(toInteger("1")); print(toInteger(1)); print(toInteger(1.5)); print(toInteger(undef)); //toDouble() print(toDouble("2.2")); print(toDouble(1)); print(toDouble(2.2)); print(toDouble(undef)); //toMultiplicity() print(toMultiplicity("one_to_one")); print(toMultiplicity(undef)); //name(), fqn(), ref() print(name(a.b.c)); // Element a.b.c should exist in the model space (at compile time) print(fqn(a.b.c)); // Element a.b.c should exist in the model space (at compile time) print(ref("a.b.c")); // Element a.b.c should exist in the model space (at runtime) } }