expressions
                no way to compare when less than two revisions
Differences
This shows you the differences between two versions of the page.
| — | expressions [2009/06/02 15:52] (current) – created - external edit 127.0.0.1 | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| + | ======Expression Syntax in EPIC====== | ||
| + | |||
| + | =====About " | ||
| + | EPIC has two " | ||
| + | mode that every command starts out in. | ||
| + | |||
| + | ^ Text mode				  | ||
| + | | Everything is plain text		  | ||
| + | | First word is command, rest is arg list | Can escape to text mode with []s| | ||
| + | | $'s start " | ||
| + | |||
| + | " | ||
| + | (Technically, | ||
| + | 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 {< | ||
| + | 	FOR (< | ||
| + | REPEAT (...) | ||
| + | |||
| + | When you are in an expression, you can escape to 'text mode' by using | ||
| + | the square brackets operator ([...]), the single 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 | ||
| + | " | ||
| + | you want to do (+, -, *, /, &&, ||, etc).  Operands are the " | ||
| + | to the operators.  | ||
| + | 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 // | ||
| + | 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.  | ||
| + | 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 " | ||
| + | operands and replacing it with a new operand.  | ||
| + | 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.  | ||
| + | 3 - 20 - 7 | ||
| + | Since there are two -'s, then we look at the associativity, | ||
| + | which means the left - is done first, which reduces to | ||
| + | < | ||
| + | -17 - 7 | ||
| + | </ | ||
| + | and performing the last operation yields | ||
| + | < | ||
| + | -24 | ||
| + | </ | ||
| + | as the result of the expression. | ||
| + | |||
| + | =====List of operators and associativity===== | ||
| + | |||
| + | ^PRECEDENCE ^OPERATOR  | ||
| + | | 1 | Sub-expression  | ||
| + | | 2 | Logical NOT	     | ! **bool**  | ||
| + | | 2 | Bitwise NOT	     | ~ **int**  | ||
| + | | 2 | Prefix Decrement	  | ||
| + | | 2 | Prefix Increment	  | ||
| + | | 2 | Suffix Decrement  | ||
| + | | 2 | Suffix Increment  | ||
| + | | 2 | Unary Plus	     | + **float**  | ||
| + | | 2 | Unary Minus	  | ||
| + | | 2 | String length	  | ||
| + | | 2 | Word Count	  | ||
| + | | 2 | Variable Dereference  | ||
| + | | 2 | Variable Dereference  | ||
| + | | 2 | Double Expansion  | ||
| + | | 3 | Exponent		  | ||
| + | | 4 | Multiplication	  | ||
| + | | 4 | Division		  | ||
| + | | 4 | Modulus		  | ||
| + | | 5 | Addition  | ||
| + | | 5 | Subtraction  | ||
| + | | 5 | String Catenation  | ||
| + | | 6 | Bitwise shift left     | **int**  | ||
| + | | 6 | Bitwise shift right    | **int**  | ||
| + | | 7 | Less Than              | **op**  | ||
| + | | 7 | Less than or equal to  | **op**  | ||
| + | | 7 | Greater than           | **op**  | ||
| + | | 7 | Greater than or equal to | **op**  | ||
| + | | 8 | Pattern match          | **op** =~ **op**  | ||
| + | | 8 | Pattern doesn' | ||
| + | | 9 | Equal, ignore case     | **op**  | ||
| + | | 9 | Not equal, ignore case | **op**  | ||
| + | | 9 | Equal                  | **op**  | ||
| + | | 9 | Not equal              | **op**  | ||
| + | |10 | Bitwise AND            | **int** & **int**  | ||
| + | |11 | Exclusive OR           | **int**  | ||
| + | |12 | Bitwise OR             | **int**  | ||
| + | |13 | Logical AND            | **bool**  | ||
| + | |14 | Logical XOR            | **bool**  | ||
| + | |15 | Logical OR             | **bool**  | ||
| + | |16 | If-then-else  | ||
| + | |17 | Assignment	  | ||
| + | |17 | Addition-assign  | ||
| + | |17 | Subtraction-assign  | ||
| + | |17 | Multiplication-assign  | ||
| + | |17 | Division-assign  | ||
| + | |17 | Modulus-assign  | ||
| + | |17 | Bitwise AND-assign  | ||
| + | |17 | Exclusive OR-assign  | ||
| + | |17 | Bitwise OR-assign  | ||
| + | |17 | Bitshift left-assign  | ||
| + | |17 | Bitshift right-assign  | ||
| + | |17 | Logical AND-assig  | ||
| + | |17 | Logical OR-assign  | ||
| + | |17 | Logical XOR-assign  | ||
| + | |17 | Exponent-assign  | ||
| + | |17 | strcat-assign  | ||
| + | |17 | String prefix-assign  | ||
| + | |17 | Swap values	  | ||
| + | |17 | Last Value             | **op**  | ||
| + | |||
| + | [1] The operand must be an [[lval]]\\ | ||
| + | [3] Short circuit operator.\\ | ||
| + | [4] You do not have to give an explicit 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 " | ||
| + |    @ foo #= [blah]  | ||
| + |    @ foo #~ [hmm]                       /* sets $foo to " | ||
| + | |||
| + | 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.  | ||
| + | |||
| + | 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 " | ||
| + | |||
| + |    @ foo = bar =~ [*pi*]  | ||
| + | @ 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' | ||
| + | library (libm) does. Assuming $foo is 9: | ||
| + | |||
| + | foo ** 2 /* returns 81 */ | ||
| + | foo ** 0.5 /* returns 3 */ | ||
| + | |||
| + | The {pre, | ||
| + | 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.  | ||
| + | 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.  | ||
| + | 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.  | ||
| + | |||
| + | @ foo = 4 | ||
| + | @ bar = 8 | ||
| + | @ foobar = foo+++bar | ||
| + | |||
| + | How should one interpret the last assignment?  | ||
| + | ${foo++ + bar} or ${foo + ++bar}?  | ||
| + | to not write code that looks so silly and unreadable.  | ||
| + | and there is no ambiguity.  | ||
| + | |||
| + | Another popular operator familiar to most C/C++ programmers is the tertiary | ||
| + | operator (sometimes referred to as the alternation operator).  | ||
| + | a function similar to IF, except is much more compact and efficient.  | ||
| + | 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.  | ||
| + | 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 ' | ||
| + | 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 -> " | ||
| + | |||
| + | 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 by 127.0.0.1
                
                