KL expressions

When you invoke any command, for each parameter of the command you can supply an expression (except where expressions are disallowed). An expression is usually an arithmetic calculation (but other types of expressions are also possible). The calculated/evaluated result of the expression is passed to the command.

An expression consists of invocations of functions. A function accepts a number of operands, does something with them, and then returns a new value (the result/answer). A function always has exactly 1 return value (but it is possible for the single return value to contain multiple components). The return value or result of a function can be supplied as an operand to another function, creating a hierarchy of function invocations.

Expressions are written in a style of prefix notation by default. Infix notation with symbol operators can optionally be used as shortcut syntax in some cases. Shortcuts will be explained in more detail further ahead.

To add 2 numbers together using the normal/default form of expression, the expression is written like this:

```
Add[56, 89]

```

"Add" is the name of a function. "56" is the first operand, and "89" is the second operand. Commas are used to separate operands. The square brackets mark the beginning and end of the operands for this function. No whitespace characters are permitted to be present between the function name and the open-square-bracket character, however they can be present within the brackets.

Each operand can be a literal number, the name of a variable, or another function to calculate first. In the following example, 56 is added with the result of 89 multiplied by 3.

```
Add[56, Mul[89, 3]]

```

In the following example, 56 is multiplied by 4, and 89 is multiplied by 3, and those 2 products are added together.

```
Add[Mul[56,4], Mul[89,3]]

```

An operand in an expression can be one of these:

* A constant value specified literally.
* A constant value specified by name (a named constant or enumeration value).
* A local variable (a variable in the current Command Implementation).
* A variable/attribute in a record instance (attribute name must be specified along with a local reference variable containing a reference to the record instance).
* A parameter variable (one of the parameters of the current Command Implementation).

In mathematics and computer science, the arity of a function/operator/operation is the number of operands or incoming values. For example, the arity of the addition function is 2 because 2 numbers are added together to form a result. The arity of the "not" function is 1 because 1 value is toggled between true and false and returned as the result.

An arity of zero is possible. For example, the number 56 or a name representing the number 56 can be thought of as a function that has zero operands, and simply returns the value 56 (its own value). Zero-arity functions are required to be written without square brackets.

This prefix-style expression syntax was chosen as the normal/main expression syntax because it supports functions/operators of any arity (any constant number of operands), and also variadic funtions (varying number of operands), and can therefore be considered a "universal" or "all-powerful" expression syntax. Whereas infix notation (for example) supports only functions/operators with an arity of 2.

## Variadic Functions

The "Add" function is variadic, meaning that it can accept a varying number of operands (minimum 2). All the operands are added together. For example, the following 2 expressions are equivalent.

```
Add[Add[1, 2], 3]
Add[1, 2, 3]

```

Other functions are also variadic, if it makes sense and is useful for them to be variadic. The "Min" (return lowest) and "Max" (return highest) functions are variadic, for example the following will evaluate to whichever of the 4 specified variables contains the lowest number:

```
Min[a,b,c,d]

```

## Unary Prefix Shortcut

If a function accepts only 1 operand, then the square brackets can optionally be omitted, as a shortcut. For example, the following 2 expressions are equivalent:

```
Not[x]
Not x

```

Likewise, the following 2 expressions are also equivalent:

```
Not[Equal[a,b]]
Not Equal[a,b]

```

And these 2 expressions are equivalent:

```
Not[EqualNull[v]]
Not EqualNull v

```

And these 2 expressions are equivalent:

```
Not[a] && b
Not a && b

```

This shortcut happens to be especially convenient for variable/attribute type expressions (expressions that specify the type of a variable or attribute).

If a function is variadic and the square brackets are omitted, it becomes non-variadic (assumes a default number of operands).

## Symbol Infix Shortcut

All functions have a name. Some functions have a symbol in addition to their name. Functions with a symbol can optionally be written in infix notation, as a shortcut. For example, the following 2 expressions are equivalent:

```
Add[56, 89]
56 + 89

```

Another example, consider a calculation where you want to start with the variable "a", then multiply by "b", then divide by "c", then add "d", then subtract "e". The following 2 equivalent expressions perform that calculation:

```
Sub[Add[Div[Mul[a, b], c], d], e]
a * b / c + d - e

```

When using the infix shortcut, there is no operator precedence. The expression is evaluated in the order that it appears (simply left to right). Multiplication and division are NOT evaluated ahead of addition and subtraction. If you disagree with this behavior, then read the Operator Precedence section for the reasoning behind this design decision.

The order of operations in an infix expression can be changed by inserting round brackets (parentheses). They group/isolate a sub-expression. If writing an expression in the prefix style, round brackets are unnecessary. The following 2 expressions are equivalent:

```
n + (a * b)
Add[n, Mul[a,b]]

```

Round brackets can be nested. The following 2 expressions are equivalent:

```
a + ((b / 2) * (c / 2))
Add[a, Mul[Div[b,2], Div[c,2]] ]

```

The compiler analyzes expressions and removes any unnecessary round brackets, reordering/rearranging the expression if necessary to achieve the minimally-bracketed form.

The infix and prefix styles can be mixed, meaning they can both be used in the same expression. The following 2 expressions are equivalent:

```
Div[a * b, 100]
Div[Mul[a,b], 100]

```

And these 2 are equivalent:

```
56 + Div[89,14]
Add[56, Div[89,14]]

```

And these 2 are equivalent:

```
a + b / Add[x,y*(6/3)] - (52 * Sub[34,1])
Sub[Div[Add[a,b], Add[x,Mul[y,Div[6,3]]]], Mul[52,Sub[34,1]]]

```

All function invocations using a symbol accept exactly 2 operands. If the function is variadic, it becomes non-variadic when specified by symbol. Infix notation only works with exactly 2 operands whereas the default prefix style supports any number of operands.

A function symbol can consist of 1 or more symbolic (non-alphabetic) characters. Adjacent symbol characters (without whitespace characters between them) other than brackets are grouped together and considered to be a single symbol operator (allowing for multi-character symbol operators). Whitespace, alphabetic, numeric digit characters, and underscore separate symbol operators. Adjacent bracket characters (round, square, or curly) are not grouped together, they are always considered to be separate 1-character symbol operators.

Having a reasonably small number of symbols is convenient. Having a large number of symbols would make the source code difficult to read, and it would be easy to forget the meaning of symbols. Thus the number of symbols should be kept reasonably low.

If you wonder why a double equals sign ("==") is used for the "Equal" function and not a single equals sign ("="), then consider the difference between making 2 things equal versus testing/checking if 2 things are equal. Assignment versus equality. In mathematics and general usage, "a=b" normally means that "a" is assigned the value of "b" ("a" is made equal to "b"). The "Equal" function determines if its 2 operands are equal (without changing them), thus a double equals sign was chosen to mean equality testing, as distinguished from the single equals sign normally meaning assignment.

## Functions

None of these functions modify any of their operands (no side-effects). Rather they return a value.

Some of the functions have a long/full name, and a short/abbreviated name. Either can be used.

Extra mathematical functions:

## Setting a Variable

A variable can be set to the result of an expression using the "set" command. The first parameter to the "set" command is the variable to set. The second parameter is the expression. For example:

```
set res, Add[Sub[a, b], c];
set res, a - b + c;

```

The variable being set can be used in the expression, as in the following 2 non-equivalent examples. The value of "res" used in the expression is the value of "res" before it is changed by the "set" command.

```
set res, a - b + res;
set res, res * 2 + n;

```

## Invert Sign (Negate)

To invert the sign of a variable (also known as "negate"), use the "InvSign" function. If the operand is positive, it is returned as negative, else if the operand is negative, it is returned as positive.

The "InvSign" function has no corresponding symbol shortcut. "-" is the symbol shortcut for the "Sub" (Subtract) function and is not shared with "InvSign".

"-" can be used for subtraction and also to specify a literal negative number. If being used for subtraction, then if the second operand (the right-side operand) is a literal number, then there must be whitespace present between the subtract operator ("-") and the literal number ("a - 3" not "a-3"). If being used to specify a literal negative number, then there must be NO whitespace between the "-" and the digits of the number ("-3" not "- 3").

Problems with the idea of using "-" to invert the sign of a variable:

1. It looks like the variable/value is being made into a negative number, whereas actually the sign is being inverted and the result may be positive despite the presence of the negative sign.
2. It is already being used for the subtract function.
3. It would introduce an inconsistency into the language because "-" as negate would act as a prefix operator whereas normally symbols act as infix operators (and the nearest equivalent to infix for a unary operator is actually postfix not prefix).

## Differences Between Functions and Commands

Functions and commands have similarities, but are different.

* Functions are encouraged to be purely functional (referentially transparent), meaning causing no side-effects. Whereas commands often have side-effects.
* Functions must have a single return value. Commands can return/output multiple separate values or none at all.
* Functions are analogous to mathematical functions (functions as defined in the field of mathematics). Commands do not really have a mathematical equivalent.
* A function invocation can contain other function invocations for operands, whereas a command invocation cannot contain other command invocations (although the Command Implementation does).
* Command invocations are organized as a linear/sequential/flat list (with conditionally skippable sections), whereas function invocations are organized as a hierarchy/tree with a base/root node. Thus command invocations are terminated and separated with the semicolon character, forming a list of invocations rather than a hierarchy of invocations.
* Functions can be used/invoked within expressions. Commands cannot be used/invoked within expressions.
* Functions cannot be used/invoked outside of (or without) an invocation of a command. Commands can be invoked without use of functions.
* Some functions can be invoked using a symbol instead of their name. Commands are always named.

## Defining Your Own Functions

Various intrinsic (built-in) functions can be used in expressions. It is undecided whether the ability to write your own functions to use in expressions will be implemented. It is debatable whether it would be of significant benefit.

You can write your own commands. Commands cannot be used/invoked within expressions. If you want to use a command in an expression, then you must split the expression into 2 expressions at the point where you want to invoke the command, and one of the halves of the expression is supplied separately with the invocation of the command. For example:

```
set r, Add[a, MyFunc[p,q,j]];

```

That can be split as follows:

```
MyFunc f, p, q, j;
set r, Add[a, f];

```

If writing your own functions was supported, there is a question of whether your function could contain invocations of commands, or only invocations of other functions (taking into consideration the fact that functions are restricted to being purely functional but commands are not).

The easiest solution to implement, but also the least powerful, is allowing new functions to be defined only in terms of other functions, and when the new function is used, it is inlined not called.