"""Abstract superclass of all expression nodes.
   
   Correct operator precedence and associativity is enforced by the parameter types
   of the various child classes. For example, consider the following simple expression:
   
       1 + 2 * 3
   
   Because multiplication has higher precedence than addition, the correct syntax tree
   for this expression is:
   ~~~
   SumOperation {
       leftOperand = IntegerLiteral("1");
       rightOperand = ProductOperation {
           leftOperand = IntegerLiteral("2");
           rightOperand = IntegerLiteral("3");
       };
   }
   ~~~
   A very simple, strictly left-associative parser that doesn’t respect operator
   precedence might instead try to produce:
   ~~~
   ProductOperation {
       leftFactor = SumOperation {
           leftSummand = IntegerLiteral("1");
           rightSummand = IntegerLiteral("2");
       };
       rightFactor = IntegerLiteral("3");
   }
   ~~~
   However, this is not well-typed (the parser would likely have an assertion failure
   at runtime), because the types of [[ProductOperation]]’s child nodes are crafted such
   that only nodes with correct precedence and associativity can be created.
   
   To ensure this, there is one type alias for each precedence level, specified as
   the union type of
   - the next higher level’s alias, and
   - all operator types on this level.
   
   For example, there is [[MultiplyingExpression]] for multiplicative expressions
   and [[AddingExpression]] for summative expressions.
   [[ProductOperation.leftFactor]] then has type [[MultiplyingExpression]],
   which does not include [[SumOperation]].
   [[ProductOperation.rightFactor]] has the next higher level’s type [[UnioningExpression]],
   reflecting the left-associativity of product operations:
   Instead of
   ~~~
   ProductOperation {
       leftFactor = IntegerLiteral("1");
       rightFactor = ProductOperation {
           leftFactor = IntegerLiteral("2");
           rightFactor = IntegerLiteral("3");
       };
   }
   ~~~
   you should have
   ~~~
   ProductOperation {
       leftFactor = ProductOperation {
           leftFactor = IntegerLiteral("1");
           rightFactor = IntegerLiteral("2");
       };
       rightFactor = IntegerLiteral("3");
   }
   ~~~
   
   These aliases are, from highest to lowest precedence:
   - [[PrePostfixingExpression]]
   - [[ExponentiatingExpression]]
   - [[InvertingExpression]]
   - [[IntersectingExpression]]
   - [[UnioningExpression]]
   - [[MultiplyingExpression]]
   - [[ScalingExpression]]
   - [[AddingExpression]]
   - [[SpanningExpression]]
   - [[ExistsNonemptyExpression]]
   - [[ComparingExpression]]
   - [[EquatingExpression]]
   - [[NegatingExpression]]
   - [[ConjoiningExpression]]
   - [[DisjoiningExpression]]
   - [[ThenElseExpression]]
   - [[AssigningExpression]]"""
shared abstract class Expression()
        of ValueExpression | FunctionExpression | LetExpression | ConditionalExpression
        extends Node() {
    shared actual formal Node[] children;
}