Arithmetic operations are the most basic forms of calculations in simorg. Just like any other programming language, simorg supports basic mathematical operations at the engine level, including addition, subtraction, multiplication, division and modulo.
As we shared briefly in the Number section, simorg does type coercion automatically for numbers. For example, depending on certain situations the engine may decide to use an Integer portion of a Decimal number. All these cases will be shared when we meet them in future sections.
Basic Binary Operations
19 $numA
2 $numB
numA + numB $add
numA - numB $sub
numA * numB $mul
numA / numB $div
numA % numB $mod
add? // 21
sub? // 17
mul? // 38
div? // 9.5
mod? // 1
These binary operators always consume operands from their right side.
$$$AlertBox type=WARNING title=Be Careful About Subtraction Operator message= The subtraction operator is a bit different because it can be used as the negative sign of a number. If you intend to use it as the subtraction operator make sure to include a space between - and the token after it. Otherwise it will be considered a negative sign. The reason behind this behavior will be discussed in the Dataflow chapter.$$$
$$$AlertBox type=WARNING title=Concerning Addition Operator message= Using a unary + sign beside a number e.g. +10, is not necessary. Later in the Dataflow chapter we will see how this operator is interpreted by the engine. So classical unary behavior in this case is not applied.$$$
Basic Unary Operations
Simorg is using two unary calculation operations,
19 $numA
2 $numB
numA ++ ? // 20
numB -- ? // 1
For now it is enough to mention that data is moving from left into the operator and passing through to the right.
Unary nature of these operators doesn't require any operand.
If the value is not a number, an INVALID_ARGUMENT error will be logged.
Syntactic Sugars
It's important to be aware that simorg has one Primitive data type for calculations and it is <<<Number>>>.
One exception is when the <<<+>>> operator is used with <<<String>>> and <<<Buffer>>>. <<<Concatenation>>> is a frequent operation when working with String and Buffer types. So for these types, the <<<+>>> operator can be used as a syntactic sugar representing concatenation.
The priority of type coercion in this case is first with <<<Buffer>>> then <<<String>>> and finally <<<Number>>>, so if one operand is <<<Buffer>>> then the data of all other operands will be converted into <<<Buffer>>>.
Please check this example,
"Hello " $strA
"World!" $strB
// Addition when all the operands are numbers
100 + 20 $num // 120
// + operator will concatenate strings
strA + strB $strC // Hello World!
// here type coercion priority is with String
// so all the operands will be considered String
// result will be String
strC + 100 + 20 $strD // Hello World!10020
// here type coercion priority is with Buffer
// so all the operands will be considered Buffer
// result will be Buffer
0x00 + strA + 10 $buffer // [00,48,65,6c,6c,6f,20,00,00,00,00,00,00,00,0a]
Please note when type coercion happens from <<<Number>>> to <<<Buffer>>>, it will always be in Little Endian (LE) format, which is file, network and IoT friendly.
$$$AlertBox type=INFO title=More Utilities message=More advanced mathematical operations will be supported by plugin artifacts, for example Math plugin from simorg's stl.$$$
$$$AlertBox type=INFO title=Operator Precedence message=Simorg arithmetic operators do not follow the classical operator precedence conventions common among CPLs. Instead the priority is from left to right. So expressions like "1 + 1 * 2" are evaluated from left to right, first evaluating "1 + 1" to 2, and then "2 * 2" to 4.$$$
Now the reason is clear. Every single operator in simorg is a dataflow operator, receiving data from left side of it, depending on its nature doing possible processing, and passing it through to the right. Some operators require operand and they consider the next token as their operand. This is how data naturally passes through different layers with no need for specific precedence between operators. For example,
1 + 2 * 5 / 15? // 1
<<<+>>> is an operator that always requires operand so number <<<2>>> is the object of the operator and will be considered its operand. But in the following example,
Due to natural dataflow direction, no parentheses are required to affect evaluation priority. Don't forget that a classical pair of parentheses doesn't exist in simorg. If you use parentheses in the middle of a calculation, that will be interpreted as a gate! For example,
10 + 5 - (120 + 2) ?
will result in an invalid operand error, """ sim -f parentheses.art """ [ERROR][DATAFLOW_SHELL][INVALID_OPERAND] Invalid dataflow operand! !!!!
Unary operators do not require an object or operand,
1 ++ 10 ? // 10
<<<++>>> doesn't require any operand; it increases the incoming value by one and passes it through. So in this case value 1 is entering the pipeline, increased by 1 and then hitting value <<<10>>> which is a value literal shell causing it to vibrate. Adding a logger in between helps to see this behavior,
1 ++ ? 10 ? // 2
// 10