User Tools

Site Tools


math_operators

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

math_operators [2007/09/01 05:53] (current)
Line 1: Line 1:
 +======Math operators======
 +The client'​s expression mode supports a large number of operators. ​ This 
 +document will explain all of them and the most important concepts.
 +
 +=====Tokens=====
 +All expressions are broken into tokens. ​ A token is either an operand, or
 +an operator. ​ An operand is a "​thing"​ that is operated upon, and an operator
 +is the action that you apply to operands. ​ In the expression 3 + 4, 3 and 4
 +are the operands, and + is the operator.
 +
 +There are three types of operands: rvalues, lvalues, and numbers. ​ An rvalue
 +is an operand that provides a value that you can use.  An lvalue is an 
 +operand that can be used as the target of an assignment operator. ​ A number
 +is, well, a number.
 +
 +As an example, an lvalue is a variable name.  In the expression foo = 5, foo
 +is the lvalue. ​ An rvalue is an operand that is used for its value, rather
 +than to assign to it.  In the expression var1 = var2, var2 is the rvalue.
 +Rvalues also include string literals.
 +
 +Numbers are different, because numbers look like lvalues, but behave like
 +rvalues. ​ Some of the operators behave differently with numbers than with
 +rvalues.
 +
 +^PRECEDENCE ^OPERATOR ​       ^USAGE ​               ^REDUCES TO ^ASSOCIATIVITY ^
 +| 1 | Sub-expression ​        | ( **op** )                  | **op** ​   | L->R |
 +| 2 | Logical NOT      | ! **bool** ​                  | **bool** ​ | R->L |
 +| 2 | Bitwise NOT      | ~ **int** ​                   | **int** ​  | R->L |
 +| 2 | Prefix Decrement  ​    | %%--%% **[[lval]]** ​         | **int** ​  | R->L |
 +| 2 | Prefix Increment  ​    | %%++%% **[[lval]]** ​         | **int** ​  | R->L |
 +| 2 | Suffix Decrement ​      | **[[lval]]** %%--%% ​         | **int** ​  | R->L |
 +| 2 | Suffix Increment ​      | **[[lval]]** %%++%% ​         | **int** ​  | R->L |
 +| 2 | Unary Plus      | + **float** ​               | **float** | R->L |
 +| 2 | Unary Minus  ​    | - **float** ​                 | **float** | R->L |
 +| 2 | String length  ​    | @ [**op**] ​                  | **int** ​  | R->L |
 +| 2 | Word Count  ​    | # [**op**] ​                  | **int** ​  | R->L |
 +| 2 | Variable Dereference ​  | * [**rval**] ​                | **lval** ​ | R->L |
 +| 2 | Variable Dereference ​  | * [**number**] ​              | **rval** ​ | R->L |
 +| 2 | Double Expansion ​      | ** [**op**] ​                 | **op** ​   | R->L |
 +| 3 | Exponent  ​    | **float** ​ %%**%% ​ **float** | **float** | R->L |
 +| 4 | Multiplication  ​    | **float** ​ %%*%%  **float** ​ | **float** | L->R |
 +| 4 | Division  ​    | **float** ​ %%/%%  **float** ​ | **float** | L->R |
 +| 4 | Modulus  ​    | **float** % **int** ​         | **float** | L->R |
 +| 5 | Addition ​              | **float** ​ %%+%%  **float** ​ | **float** | L->R |
 +| 5 | Subtraction ​           | **float** - **float** ​       | **float** | L->R |
 +| 5 | String Catenation ​     | **op** ​ %%##​%% ​ **op** ​      | **op** ​   | L->R |
 +| 6 | Bitwise shift left     | **int** ​ %%<<​%% ​ **int** ​    | **int** ​  | L->R |
 +| 6 | Bitwise shift right    | **int** ​ %%>>​%% ​ **int** ​    | **int** ​  | L->R |
 +| 7 | Less Than              | **op** ​ %%<​%% ​ **op** ​       | **int** ​  | L->R |
 +| 7 | Less than or equal to  | **op** ​ %%<​=%% ​ **op** ​      | **int** ​  | L->R |
 +| 7 | Greater than           | **op** ​ %%>​%% ​ **op** ​       | **int** ​  | L->R |
 +| 7 | Greater than or equal to | **op** ​ %%>​=%% ​ **op** ​    | **int** ​  | L->R |
 +| 8 | Pattern match          | **op** =~ **op** ​            | **bool** ​ | L->R |
 +| 8 | Pattern doesn'​t match  | **op** !~ **op** ​            | **bool** ​ | L->R |
 +| 9 | Equal, ignore case     | **op** ​ %%==%% ​ **op** ​      | **bool** ​ | L->R |
 +| 9 | Not equal, ignore case | **op** ​ %%!=%% ​ **op** ​      | **bool** ​ | L->R |
 +| 9 | Equal                  | **op** ​ %%===%% ​ **op** ​     | **bool** ​ | L->R |
 +| 9 | Not equal              | **op** ​ %%!==%% ​ **op**  ​   | **bool** ​ | L->R |
 +|10 | Bitwise AND            | **int** & **int** ​           | **int** ​  | L->R |
 +|11 | Exclusive OR           | **int** ​ %%^%%  **int** ​     | **int** ​  | L->R |
 +|12 | Bitwise OR             | **int** ​ %%|%%  **int** ​     | **int** ​  | L->R |
 +|13 | Logical AND            | **bool** ​ %%&&​%% ​ **bool** ​  | **bool** ​ | L->R |
 +|14 | Logical XOR            | **bool** ​ %%^^%% ​ **bool** ​  | **bool** ​ | L->R |
 +|15 | Logical OR             | **bool** ​ %%||%% ​ **bool** ​  | **bool** ​ | L->R |
 +|16 | If-then-else ​          | **bool** ? **op** : **op** ​  | **op** ​   | R->L |
 +|17 | Assignment  ​    | **[[lval]]** = **op**  ​   | **op** ​   | R->L |
 +|17 | Addition-assign ​       | **[[lval]]** += **float** ​   | **float** | R->L |
 +|17 | Subtraction-assign ​    | **[[lval]]** -= **float** ​   | **float** | R->L |
 +|17 | Multiplication-assign ​ | **[[lval]]** *= **float** ​   | **float** | R->L |
 +|17 | Division-assign ​       | **[[lval]]** /= **float** ​   | **float** | R->L |
 +|17 | Modulus-assign ​        | **[[lval]]** %= **float** ​   | **float** | R->L |
 +|17 | Bitwise AND-assign ​    | **[[lval]]** &= **int** ​     | **int** ​  | R->L |
 +|17 | Exclusive OR-assign ​   | **[[lval]]** ​ %%^=%% **int**| **int** ​  | R->L |
 +|17 | Bitwise OR-assign ​     | **[[lval]]** ​ %%|=%% **int**| **int** ​  | R->L |
 +|17 | Bitshift left-assign ​  | **[[lval]]** ​ %%<<​=%% **int**| **int** ​ | R->L |
 +|17 | Bitshift right-assign ​ | **[[lval]]** ​ %%>>​=%% **int**| **int** ​ | R->L |
 +|17 | Logical AND-assig ​     | **[[lval]]** ​ %%&&​=%% **bool**| **bool**| R->L |
 +|17 | Logical OR-assign ​     | **[[lval]]** ​ %%||=%% **bool**| **bool**| R->L |
 +|17 | Logical XOR-assign ​    | **[[lval]]** ​ %%^^=%% **bool**| **bool**| R->L |
 +|17 | Exponent-assign ​       | **[[lval]]** ​ %%**=%% **float**|**float**| R->L |
 +|17 | strcat-assign ​         | **[[lval]]** ​ %%#​=%% ​ **op** ​ | **op** ​ | R->L |
 +|17 | String prefix-assign ​  | **[[lval]]** ​ %%#​~%% ​ **op** ​ | **op** ​ | R->L |
 +|17 | Swap values  ​    | **[[lval]]** %%<​=>​%% **[[lval]]** | **[[lval]]** ​ | R->L |
 +|17 | Last Value             | **op** ​ %%,%%  **op**  ​   | **op** ​   | L->R |
 +
 +[1] The operand must be an [[lval]]\\
 +[3] Short circuit operator.\\
 +[4] You do not have to give an explicit operand. ​ If you omit the operand, then [$*] is used as the operand.
 +
 +=====How operands are handled=====
 +There are four different kinds of operands
 +
 +=====Escapes to text mode=====
 +[...]
 +{...}
 +'​...'​
 +"​..."​
 +
 +=====Epic-only operators=====
 +
 +
 +=====Operators that behave different in epic=====
 +
 +=====How errors in expressions are handled=====
 +
 +The string concatenation operators, ##, #=, and #~, are a special case, as they
 +are not present in C or C++.  As their name indicates, they are used to join
 +two or more strings together, end to end.  For example:
 +
 +   @ foo  = [foo] ## [bar]              /* sets $foo to "​foobar"​ */
 +   @ foo #= [blah] ​                     /* sets $foo to "​foobarblah"​ */
 +   @ foo #~ [hmm]                       /* sets $foo to "​hmmfoobarblah"​ */
 +
 +Also like C/C++, parentheses may be used to force certain parts of the
 +expression to be evaluated first (mainly in the event that the user wishes
 +for it to evaluate in an order other than that of operator precedence).
 +Parentheses may be nested. ​ For example, if some variable $foo is set to 3:
 +
 +   foo * 4 + 5                          /* returns 17 */
 +   foo * (4 + 5)                        /* returns 27 */
 +   4 + ((foo + 9) / 3)                  /* returns 8 */
 +
 +All assignment operators always return the value assigned, which allows for
 +the assignment of multiple variables at once.  Keep in mind that expressions
 +are evaluated right to left.  For example, if $foo is 12 and $bar is 11:
 +
 +   @ foo += bar *= 2                    /* $bar is 22, $foo is 34 */
 +
 +Since the release of the EPIC4 pre-betas, the client has been growing ever
 +more perlish. Like perl, the =~ and !~ operators match with wildcards. =~ is
 +a direct opposite of !~, where it returns true if the patterns patch, while
 +!~ returns false. In this example, $bar is "​epic":​
 +
 +   @ foo = bar =~ [*pi*] ​              /* returns 1 */
 +   @ foo = bar !~ [*z*]                /* returns 1 */
 +
 +The various bitwise operators are of special interest also. Assuming $foo is 12
 +and $bar is 11:
 +
 +   foo & bar                            /* returns 8 */
 +   foo | bar                            /* returns 15 */
 +   foo ^ bar                            /* returns 7 */
 +
 +The exponential operator takes numbers to various powers. It is especially
 +useful, since many script writers create a $power() function for this purpose.
 +It supports negative and fractional exponents as long as the system'​s math
 +library (libm) does. Assuming $foo is 9:
 +
 +   foo ** 2                             /* returns 81 */
 +   foo ** 0.5                           /* returns 3 */
 +
 +The {pre,​post}fix {in,​de}crement operators are big timesavers that C and C++
 +users everywhere swear by.  They have also been known to swear at them, for
 +reasons you will soon see.  Assume $foo is 5, each column shows 3 ways of
 +doing the same thing, from least efficient to most efficient:
 +
 +   @ foo  = foo + 1                     @ foo  = foo - 1
 +   @ foo += 1                           @ foo -= 1
 +   @ foo++                              @ foo--
 +
 +However, these operators have pitfalls, which are mainly discovered by those
 +who do not understand how they work.  Both may either prefix or postfix a
 +variable; prefix causes it to evaluate before the operation, postfix causes
 +it to evaluate aster. ​ For the examples shown above, it makes no difference.
 +However, it does make a difference in this example:
 +
 +   while ( foo++ < 10 ) { ... }
 +
 +The expression is evaluated for whether $foo is less than 10, and then $foo
 +is incremented. ​ If the autoincrement operator was instead used in prefix
 +form, $foo would be incremented **before** the expression was evaluated, which
 +would cause the loop to have one less iteration.
 +
 +Another pitfall of the autoincrement and decrement operators is the
 +ambiguity introduced by insufficient whitespace when used in conjunction
 +with addition and subtraction operators. ​ Consider the following:
 +
 +   @ foo    = 4
 +   @ bar    = 8
 +   @ foobar = foo+++bar
 +
 +How should one interpret the last assignment? ​ Should it really look like
 +${foo++ + bar} or ${foo + ++bar}? ​ It's hard to tell.  The best solution is
 +to not write code that looks so silly and unreadable. ​ Add a couple spaces,
 +and there is no ambiguity. ​ (The answer is, the first one.)
 +
 +Another popular operator familiar to most C/C++ programmers is the tertiary
 +operator (sometimes referred to as the alternation operator). ​ It performs
 +a function similar to IF, except is much more compact and efficient. ​ We'll
 +let $foo be 5 again:
 +
 +   @ bar = foo > 3 ? 1 : 0              /* sets $bar to 1 */
 +   @ bar = foo > 8 ? 1 : 0              /* sets $bar to 0 */
 +
 +Functions (built-in and scripted) can also be used within expressions. ​ The
 +function will be evaluated, and its return value is used in the expression:
 +
 +   @ foo = pattern(b* foo bar blah)     /* sets $foo to "bar blah" */
 +
 +All functions implicitly use a special operator, ().  That is, the pair of
 +parentheses themselves compose an operator, though of course it is somewhat
 +different in nature from more traditional operators like '​+'​ or '<'​ or '&'​.
 +Functions (aliases with return values) require the () to function properly.
 +
 +A similar operator is [], which is used for alias and variable structures.
 +We've already seen that it can be used to explicitly switch the evaluation
 +context to text.  This can be extended to structure elements, such that
 +they can be expanded on the fly:
 +
 +   @ foo.1.1 = [foo]
 +   @ foo.1.2 = [bar]
 +   alias blah echo $foo[1][$0]
 +   /blah 2                              /* expands to $foo.1.2 -> "​bar"​ */
 +
 +The same can be applied to aliases and functions as well.  Because of the
 +nature of the [] operator, anything may be expanded inside it, variables and
 +functions alike.
  
math_operators.txt ยท Last modified: 2007/09/01 05:53 (external edit)