Vision Syntax

Order of Operations

In the expression:

  gm sales + ford sales
the 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 log
the 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 + 4
computes to 10 and:
  10 + 3 * 2
computes 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) * 2
computes to 26.

Vision extends the notions of precedence to include all messages. The precedence rules for expression evaluation are as follows:

  1. Parenthesized expressions are always evaluated first.
  2. Unary messages take precedence over binary and keyword messages.
  3. Unary messages are evaluated in the order they appear in the expression.
  4. 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 <-.
  5. Within an expression, binary messages at the same precedence level evaluate in the order in which they appear.
  6. The binary messages *, /, +, -, =, ==, >, <, <=, >=, !=, !==, &&, ||, and , take precedence over the keyword messages.
  7. 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:

Execution Order (1)

The actual steps performed are:

  1. Send the unary message sales to gm to produce an object representing GM's sales.
  2. Send the unary message sales to ford to produce an object representing Ford's sales.
  3. Send the unary message log to the object representing Ford's sales to produce an object representing the log of Ford's sales.
  4. 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) log
the expected result is achieved. The order of operations is:

Execution Order (2)

The actual steps performed are:

  1. Send the unary message sales to gm to produce an object representing GM's sales.
  2. Send the unary message sales to ford to produce an object representing Ford's sales.
  3. 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.
  4. 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) + 3
To 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 . + 3
and
  mylist union: yourlist . count
Note 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: autolist
or
  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) count
or
  (mylist union: yourlist . exclude: autolist) count
or
  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 \