Vision Syntax
Order of Operations
In the expression:
gm sales + ford salesthe following interpretations could be possible:
- Add ford to gm sales and send the resultant object the message sales.
- Add ford to the message sales and send this message to gm. Then send the message sales to the resultant object.
- Evaluate the expressions gm sales and ford sales and then add one to the other.
In this example, the last interpretation is clearly the only meaningful one. However, in the example:
gm sales + ford sales logthe following interpretations could be possible:
- Add the log of Ford's sales to GM's sales.
- Add GM's and Ford's sales, then take the log of the result.
Although the second interpretation is likely to be the one intended, Vision would actually use the first approach.
Clearly the order of executing the various messages can make a difference, so Vision needs unambiguous rules for choosing what to do first. Vision does this by assigning a precedence level to each type of message.
You are probably familiar with the precedence rules used for basic arithmetic. Arithmetic rules state that multiplication and division have a higher precedence than addition and subtraction, so they are performed first. If an expression contains two operations of the same precedence, they are executed in the order in which they occur. For example:
3 * 2 + 4computes to 10 and:
10 + 3 * 2computes to 16.
Parentheses can be used to change the order of evaluation. In the above examples:
3 * (2 + 4)computes to 18 and:
(10 + 3) * 2computes to 26.
Vision extends the notions of precedence to include all messages. The precedence rules for expression evaluation are as follows:
- Parenthesized expressions are always evaluated first.
- Unary messages take precedence over binary and keyword messages.
- Unary messages are evaluated in the order they appear in the expression.
- The precedence order for binary messages is * and / first, followed by + and -, followed by =, ==, >, <, <=, >=, and !=, !==, followed by && followed by || followed by ,, followed by ->, followed by <-.
- Within an expression, binary messages at the same precedence level evaluate in the order in which they appear.
- The binary messages *, /, +, -, =, ==, >, <, <=, >=, !=, !==, &&, ||, and , take precedence over the keyword messages.
- Keyword messages take precedence over the binary messages -> and <-.
When Vision finds parenthesized expressions they are always evaluated first. If more than one parenthesized expression exists, they are evaluated in the order in which they appear. Parenthesized expressions may contain parenthesized expressions. Within each expression, these same precedence rules apply.
For example the order of operations for the example described above is illustrated below:
The actual steps performed are:
- Send the unary message sales to gm to produce an object representing GM's sales.
- Send the unary message sales to ford to produce an object representing Ford's sales.
- Send the unary message log to the object representing Ford's sales to produce an object representing the log of Ford's sales.
- Send the binary message + to the object representing GM's sales with the object representing the log of Ford's sales as its argument.
As the preceding example illustrates, expressions are actually decomposed into a series of expressions that get executed based on precedence order. An expression within parentheses is evaluated before any expression outside the parentheses. If the previous example were written as:
(gm sales + ford sales) logthe expected result is achieved. The order of operations is:
The actual steps performed are:
- Send the unary message sales to gm to produce an object representing GM's sales.
- Send the unary message sales to ford to produce an object representing Ford's sales.
- Send the binary message + to the object representing GM's sales with the object representing Ford's sales as its argument to produce an object representing the value of their combined sales.
- Send the unary message log to the combined sales value to produce an object representing the log of the combined sales figure.
Sample Usage
The following examples further illustrate precedence rules. To add 3 to the value of the May estimate, the expression:
:estimate asOf: 9305 + 3 (incorrect)produces incorrect results. Because the binary message + is evaluated before keyword messages, Vision will first add 3 to 9305 to produce the parameter for the asOf: message. The correct expression is:
(:estimate asOf: 9305) + 3To print the sum of 2 and 7, the expression:
2 + 7 print ; (incorrect)produces incorrect results. Because unary messages are evaluated before binary messages, Vision will print the value 7 prior to performing the addition operation. The correct expression is:
( 2 + 7 ) print ;Alternatively, you could have used one of the keyword versions of the print message. For example, the expression:
2 + 7 print: 12 ;also produces the correct result. Because the keyword message print: has a lower precedence than the binary message +, the expression 2 + 7 is evaluated first and the message print: 12 is applied to the result. In this case the value 9 is printed, right justified in 12 columns.
To count the number of elements in the union of two lists, the expression:
mylist union: yourlist count (incorrect)produces incorrect results. Because unary messages are evaluated before keyword messages, Vision will compute the number of elements in yourlist first and will use this result as the argument for the union: message. The correct expression is:
(mylist union: yourlist) count
The . (Dot) Operator
Because keyword messages have lower precedence than unary and most binary messages, it is often necessary to enclose the entire keyword message expression (i.e., recipient, selectors, and parameters) within parentheses. This can become cumbersome, especially when an expression contains many multiple keyword expressions within it. For this situation, Vision provides an alternative to the parentheses. You can place a '.' (period) in your expression to indicate that you have completed a keyword message. This Dot Operator plays the role of a closing parenthesis, where the opening parenthesis is assumed to be at the start of the current expression.
Using the dot operator, the previous expressions could have been written as:
:estimate asOf: 9305 . + 3and
mylist union: yourlist . countNote that the '.' can only be used as a terminator for a keyword message. It is meaningless with unary and binary messages and will produce a syntax error in these cases.
One final piece of information is needed to complete this discussion on order of operations. Whenever multiple keywords appear in an unparenthesized expression, Vision assumes they form a single message. Therefore the expression:
mylist union: yourlist exclude: autolist (incorrect)would be viewed as sending the keyword message union:exclude: to the object mylist and providing two parameters, yourlist and autolist. To tell Vision to view this expression as two successive keyword messages (i.e., union: and exclude: ) either of the following formats is valid:
(mylist union: yourlist) exclude: autolistor
mylist union: yourlist . exclude: autolist
Any of the following formats can be used to find the number of elements in the final list produced:
( (mylist union: yourlist) exclude: autolist) countor
(mylist union: yourlist . exclude: autolist) countor
mylist union: yourlist . exclude: autolist . count
Syntax Summary
For you grammar buffs, here is the Vision language syntax presented in a BNF format:
VisionProgram : ExpressionList ExpressionList : ExpressionListTerm | ExpressionList ';' ExpressionListTerm ExpressionListTerm : | Expression Expression : KeywordExpression | BinaryExpression | UnaryExpression KeywordExpression : Expression KeywordExpressionTerms KeywordExpressionTerms : KeywordExpressionTerm | KeywordExpressionTerm KeywordExpressionTerms KeywordExpressionTerm : Keyword Expression | ':' Keyword Expression BinaryExpression : Expression BinaryOperator Expression | Expression ':' BinaryOperator Expression BinaryOperator : '*' | '/' | '+' | '-' | '=' | '==' | '!=' | '!==' | '<' | '<=' | '>=' | '>' | '&&' | '||' | ',' | '<-' | '->' UnaryExpression : Primary | UnaryOperator | UnaryExpression UnaryOperator UnaryOperator : Identifier | ':' Identifier Primary : '!' Identifier | '^' Identifier | Block | Selector | String | Number | '(' Expression ')' | KeywordExpression '.' Block : '[' ExpressionList ']' | '[' | BlockHeader '|' ExpressionList ']' BlockHeader : ParameterList | MethodTemplate ParameterList : ':' Identifier | ':' Identifier ParameterList MethodTemplate : Identifier | BinaryOperator Identifier | KeywordMethodTemplate KeywordMethodTemplate : Keyword Identifier | Keyword Identifier KeywordMethodTemplate Selector : ''' Identifier ''' | ''' BinaryOperator ''' | ''' KeywordSelector ''' KeywordSelector : Keyword | Keyword KeywordSelector Keyword : Identifier':' ... no whitespace allowed before the : Identifier : Alpha | Alpha AlphaNumerics Alpha : [a-zA-Z_] | '\'. ... any character preceded by a \ AlphaNumerics : AlphaNumeric AlphaNumerics AlphaNumeric : Alpha | Digit Number : Sign UnsignedNumber Sign : | '+' | '-' UnsignedNumber : Mantissa Exponent | '0x'HexDigits ... no whitespace allowed after the 0x Mantissa : Digits | Digits '.' | '.' Digits | Digits '.' Digits Exponent : | ExponentTag Sign Digits ExponentTag : [Ee] Digits : Digit | Digit Digits Digit : [0-9] HexDigits : HexDigit | HexDigit HexDigits HexDigit : [0-9a-fA-F] String : '"' StringBody '"' StringBody : | StringBodyCharacter StringBody StringBodyCharacter : . | '\'. ... any character preceded by a \