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
