Site Tools


math_operators
no way to compare when less than two revisions

Differences

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


math_operators [2007/09/01 05:53] (current) – created - external edit 127.0.0.1
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 by 127.0.0.1