This notional machine represents a source code expression
in the form of a tree.
This makes the structure of the expression explicit,
and it allows visualizing the various steps of expression evaluation.
It also allows annotating the various subexpressions with their types.
An expression tree is essentially an abstract syntax tree (AST),
focused on just an expression.
Here is an example Java expression:
The corresponding expression tree
shows not only the expression’s structure
but also the types and values of all subexpressions:
A notional machine focuses on a subset of the syntax and semantics of a programming language. The following misconceptions are related to the language features expressible in this notional machine.
Addition has higher precedence than string concatenation
Parenthesis are used to access an element in an array
Arrays are created without the new keyword
The number of brackets in an array type or an array initializer corresponds to the length of the array
The type of a multi-dimensional array is written as T[] T[] T[]
To get the length of an array, one needs to call its length method
Array initializers list the elements in square brackets
Array rank and array length are the same thing
= compares two values
An assignment a=b is not an expression
One can invoke a method on primitive values
One needs a variable to invoke a method
Member accesses cannot be chained together
Method calls or field accesses cannot be chained to a constructor invocation
Chained methods are all called on the object at the beginning of the chain
Char is not a numeric type
To test whether an expression evaluates to true or false, one must compare it to a constant
To test whether an expression is True or False, one must compare it to True or to False
To test whether an expression is true or false, one must compare it to true or to false
Expressions that consist of multiple parts have no type
One can write the constructor name, without new, to instantiate a class
Evaluating an expression means outputting its result
An expression that reads a variable also updates its value after the evaluation
One has to evaluate an expression to determine its type
The expression tree of an expression involving a call inlines the call's computation of the returned value
The expression tree of an expression involving a variable inlines the variable's definition
Dividing two integers can produce a rational number
A literal is not an expression
When passing a literal string as argument to a method, no quotes are needed
To map a boolean expression to a boolean, a conditional operator is necessary
To map a boolean expression to a bool, a ternary conditional operator is necessary
A reference variable can point to multiple objects
A variable can contain more than one value
A multi-dimensional array is one thing
Expressions must consist of more than one piece
One cannot invoke methods on String literals
If a variable is at least as big (bit-width) as a value, then no cast is needed to a assign the value to the variable
An object contains only the fields declared in its class
There are no float literals
Smaller types are never automatically converted into bigger ones without an explicit cast
Multi-dimensional arrays have a rectangular shape
There are no long literals
Subclasses inherit fields but not methods
&& and || always evaluate both operands
and/or always evaluate both operands
& is only a bitwise AND
One cannot invoke toString() on a String
NullPointerExceptions are detected at compile time
Numeric types can be coerced to boolean
A variable is needed to instantiate an object
Only the elements of the innermost array of a multi-dimensional array are accessible
Out-of-bounds array elements are null
Nested function calls are invoked outside in
Nested method calls are invoked outside in
() are optional for method calls without arguments
() are optional for function calls without arguments
The type of a primitive variable depends on its value
Private members of a superclass are accessible from a subclass
Rational fractions are literals
Every reference type can be coerced to boolean
One can cast between references and ints
Chained accesses are invoked from right to left
The name self is not an expression
String literals can be in single quotes
One can know the length of a String object by accessing its length field
One needs to call the String constructor to get a String object from a literal
String concatenation stringifies non-String operand expressions
The multiplication operator can repeat a String a number of times
To call a method on a superclass, parentheses are needed after the keyword super
The type of a numerical expression depends on the type expected by the surrounding context
One can assign to this
this can be null
Instance method or constructor call nodes in expression trees have a child labeled "this"
In a constructor, this is null
The name this is not an expression
Invoking toString() prints something
= stores an expression in a variable