Site Tools


expressions

Differences

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

Link to this comparison view

expressions [2009/06/02 15:52] (current)
Line 1: Line 1:
 +======Expression Syntax in EPIC======
 +
 +=====About "​expression mode" and "text mode"​=====
 +EPIC has two "​modes"​ it executes your code in.  "Text mode" is the standard
 +mode that every command starts out in.
 +
 +^ Text mode  ​   ^Expression mode ^
 +| Everything is plain text  ​   | Everything is operator or operand|
 +| First word is command, rest is arg list   | Can escape to text mode with []s|
 +| $'s start "​expandos"​ (macro substitution) | $'s are not permitted before vars|
 +
 +"​Expression mode" occurs in all of the following text-mode commands:
 +(Technically,​ @ and parenthesis are not really commands, they just 
 +look like it)
 +
 + @ ... (return value is ignored -- see below)
 + (...) (return value is ignored -- see below)
 + ${...} (may be used anywhere in text mode)
 + IF (...)
 + UNLESS (...)
 + WHILE (...) 
 + UNTIL (...) 
 + DO {<​commands>​} WHILE (...)
 + FOR (<​command>,​ ... ,<​command>​)
 + REPEAT (...)
 +
 +When you are in an expression, you can escape to 'text mode' by using
 +the square brackets operator ([...]), the single quotes operator
 +('​...'​) or the double quotes operator ("​...."​).
 +
 +When you are in an expression, and you call a function, like so:
 + @foo = function(...)
 +the function parameters are always in 'text mode'.
 +
 +=====Operators and operands=====
 +When EPIC evaluates an expression, it breaks the entire expression into 
 +"​operators"​ and "​operands"​. ​ Operators are the mathematical actions that
 +you want to do (+, -, *, /, &&, ||, etc).  Operands are the "​arguments" ​
 +to the operators. ​ Some operators are unary (take only one operand) and
 +some operators are binary (take two operands), and one operator is 
 +tertiary (takes three operands)
 +
 +The process of evaluating an expression is performing each of the operations
 +one at a time until there is only one operand and no operators left.  The
 +operators have a //​precedence//,​ so all of the operators with precedence 1
 +go before any operator with precedence 2, and so on.  If there is more than
 +one operator with the same precedence, you have to know whether to do the
 +right one or the left one first. ​ This is the //​associativity//​. ​ L->R means
 +when there is more than one of the same operator in an expression, the left 
 +one is done first, and R->L means the right one is done first.
 +
 +Each operator "​reduces"​ the expression by removing itself and one or more 
 +operands and replacing it with a new operand. ​ When you have executed all of
 +the operators in an expression, you should have only one operand left, and
 +that is the //result// of the expression.
 +
 +=====Example:​=====
 +Let's solve the expression:
 + 3 - 4 * 5 - 7
 +Since * has precedence of 4 and + has precedence of 5 (see the table below), ​
 +the * goes first. ​ 4 * 5 is 20, so that reduces to
 + 3 - 20 - 7
 +Since there are two -'s, then we look at the associativity,​ and it is L->R
 +which means the left - is done first, which reduces to
 +<​code>​
 + -17 - 7
 +</​code>​
 +and performing the last operation yields
 +<​code>​
 + -24
 +</​code>​
 +as the result of the expression.
 +
 +=====List of operators and associativity=====
 +
 +^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.
  
expressions.txt ยท Last modified: 2009/06/02 15:52 (external edit)