docs: public static String print(Expression expression) {
          return expression.match(new Expression.MatchBlock<String>() {
  
              @Override
              public String _case(LiteralExpression x) {
                  return print(x.literal);
              }
  
              @Override
              public String _case(VariableExpression x) {
                  return x.selector.match(new Optional.MatchBlock<Expression, String>() {
                      @Override
                      public String _case(Some<Expression> x) {
                          return print(x.value) + ".";
                      }
  
                      @Override
                      public String _case(None<Expression> x) {
                          return "";
                      }
                  }) + x.identifier;
              }
  
              @Override
              public String _case(NestedExpression x) {
                  return "( " + print(x.expression) + " )";
              }
  
              @Override
              public String _case(ClassReference x) {
                  return print(x.type) + ".class";
              }
  
              @Override
              public String _case(TernaryExpression x) {
                  return print(x.cond) + " ? " + print(x.trueExpression) + " : " + print (x.falseExpression);
              }
  
              @Override
              public String _case(BinaryExpression x) {
                  return print(x.left) + " " + print(x.op) + " " +  print(x.right);
              }
          });
      }