context: /*
   * GrGen: graph rewrite generator tool -- release GrGen.NET 4.4
   * Copyright (C) 2003-2015 Universitaet Karlsruhe, Institut fuer Programmstrukturen und Datenorganisation, LS Goos; and free programmers
   * licensed under LGPL v3 (see LICENSE.txt included in the packaging of this file)
   * www.grgen.net
   */
  
  // by Edgar Jakumeit, Moritz Kroll
  
  using System;
  using System.Collections.Generic;
  using System.Text;
  
  using de.unika.ipd.grGen.libGr;
  using System.Diagnostics;
  using de.unika.ipd.grGen.lgsp;
  
  namespace de.unika.ipd.grGen.expression
  {
      /// <summary>
      /// Base class of expressions and yieldings
      /// which allows to emit code and to iterate over the contained children
      /// </summary>
      public abstract class ExpressionOrYielding
      {
          /// <summary>
          /// emits c# code implementing the construct into the source builder
          /// to be implemented by concrete subclasses
          /// </summary>
          public abstract void Emit(SourceBuilder sourceCode);
  
          /// <summary>
          /// returns an enumerator over the contained children of this construct
          /// </summary>
          public virtual IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield break;
          }
  
          /// <summary>
          /// sets for the very node the parallelized flag (does not recurse)
          /// </summary>
          public virtual void SetNeedForParallelizedVersion(bool parallel)
          {
              // NOP, sufficient for most expressions and yieldings,
              // only the reachable-constructs and the user defined functions need to call a special version
              // that prevents issues due to the shared use of visited flags
              // and all version that support profiling, cause that must be different for the parallel version
          }
  
          /// <summary>
          /// sets for the very node the profiling flag (does not recurse)
          /// </summary>
          public virtual void SetNeedForProfiling(bool profiling)
          {
              // NOP, sufficient for most expressions and yieldings,
              // only the node/edge and the incident/adjacent/reachable-constructs need to call a special version
              // counting up the search steps with each visited element/graph element accessed (but not the implicit operations)
          }
      }
  
  
      /// <summary>
      /// Base class of expressions used in conditions to constrain the pattern
      /// </summary>
      public abstract class Expression : ExpressionOrYielding
      {
          /// <summary>
          /// copies the expression, renaming all variables with the given suffix
          /// </summary>
          public abstract Expression Copy(string renameSuffix);
      }
  
      /// <summary>
      /// Base class of operator expressions
      /// </summary>
      public abstract class Operator : Expression
      {
      }
  
      /// <summary>
      /// Class representing an binary infix operator.
      /// </summary>
      public abstract class BinInfixOperator : Operator
      {
          public BinInfixOperator(Expression left, Expression right)
          {
              Left = left;
              Right = right;
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("(");
              Left.Emit(sourceCode);
              sourceCode.Append(GetInfixOperator());
              Right.Emit(sourceCode);
              sourceCode.Append(")");
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return Left;
              yield return Right;
          }
  
          public abstract String GetInfixOperator();
  
          protected Expression Left;
          protected Expression Right;
      }
  
      /// <summary>
      /// Class representing an binary prefix operator in function notation.
      /// </summary>
      public abstract class BinFuncOperator : Operator
      {
          public BinFuncOperator(Expression left, Expression right)
          {
              Left = left;
              Right = right;
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append(GetFuncOperatorAndLParen());
              Left.Emit(sourceCode);
              sourceCode.Append(", ");
              Right.Emit(sourceCode);
              sourceCode.Append(")");
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return Left;
              yield return Right;
          }
  
          public abstract String GetFuncOperatorAndLParen();
  
          protected Expression Left;
          protected Expression Right;
      }
  
      /// <summary>
      /// Class representing a conditional operator (a ? b : c).
      /// </summary>
      public class COND : Operator
      {
          public COND(Expression condition, Expression left, Expression right)
          {
              Condition = condition;
              Left = left;
              Right = right;
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("(");
              Condition.Emit(sourceCode);
              sourceCode.Append(" ? ");
              Left.Emit(sourceCode);
              sourceCode.Append(" : ");
              Right.Emit(sourceCode);
              sourceCode.Append(")");
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new COND(Condition.Copy(renameSuffix), Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return Condition;
              yield return Left;
              yield return Right;
          }
  
          Expression Condition;
          Expression Left;
          Expression Right;
      }
  
      /// <summary>
      /// Class representing a logical or.
      /// </summary>
      public class LOG_OR : BinInfixOperator
      {
          public LOG_OR(Expression left, Expression right) : base(left, right) { }
  
          public override Expression Copy(string renameSuffix)
          {
              return new LOG_OR(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override string  GetInfixOperator()
          {
   	        return " || ";
          }
      }
  
      /// <summary>
      /// Class representing a logical and.
      /// </summary>
      public class LOG_AND : BinInfixOperator
      {
          public LOG_AND(Expression left, Expression right) : base(left, right) { }
  
          public override Expression Copy(string renameSuffix)
          {
              return new LOG_AND(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override string  GetInfixOperator()
          {
   	        return " && ";
          }
      }
  
      /// <summary>
      /// Class representing a bitwise or.
      /// </summary>
      public class BIT_OR : BinInfixOperator
      {
          public BIT_OR(Expression left, Expression right) : base(left, right) { }
  
          public override Expression Copy(string renameSuffix)
          {
              return new BIT_OR(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override string GetInfixOperator()
          {
              return " | ";
          }
      }
  
      /// <summary>
      /// Class representing the set/map union operator.
      /// </summary>
      public class DICT_BIT_OR : BinFuncOperator
      {
          public DICT_BIT_OR(Expression left, Expression right) : base(left, right) { }
  
          public override Expression Copy(string renameSuffix)
          {
              return new DICT_BIT_OR(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override string GetFuncOperatorAndLParen()
          {
              return "GRGEN_LIBGR.ContainerHelper.Union(";
          }
      }
  
      /// <summary>
      /// Class representing the set/map intersection operator.
      /// </summary>
      public class DICT_BIT_AND : BinFuncOperator
      {
          public DICT_BIT_AND(Expression left, Expression right) : base(left, right) { }
  
          public override Expression Copy(string renameSuffix)
          {
              return new DICT_BIT_AND(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override string GetFuncOperatorAndLParen()
          {
              return "GRGEN_LIBGR.ContainerHelper.Intersect(";
          }
      }
  
      /// <summary>
      /// Class representing the set/map except operator.
      /// </summary>
      public class DICT_EXCEPT : BinFuncOperator
      {
          public DICT_EXCEPT(Expression left, Expression right) : base(left, right) { }
  
          public override Expression Copy(string renameSuffix)
          {
              return new DICT_EXCEPT(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override string GetFuncOperatorAndLParen()
          {
              return "GRGEN_LIBGR.ContainerHelper.Except(";
          }
      }
  
      /// <summary>
      /// Class representing a bitwise xor.
      /// </summary>
      public class BIT_XOR : BinInfixOperator
      {
          public BIT_XOR(Expression left, Expression right) : base(left, right) { }
  
          public override Expression Copy(string renameSuffix)
          {
              return new BIT_XOR(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override string GetInfixOperator()
          {
              return " ^ ";
          }
      }
  
      /// <summary>
      /// Class representing a bitwise and.
      /// </summary>
      public class BIT_AND : BinInfixOperator
      {
          public BIT_AND(Expression left, Expression right) : base(left, right) { }
  
          public override Expression Copy(string renameSuffix)
          {
              return new BIT_AND(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override string GetInfixOperator()
          {
              return " & ";
          }
      }
  
      /// <summary>
      /// Class representing an equality comparison.
      /// </summary>
      public class EQ : BinInfixOperator
      {
          public EQ(Expression left, Expression right) : base(left, right) { }
  
          public override Expression Copy(string renameSuffix)
          {
              return new EQ(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override string GetInfixOperator()
          {
              return " == ";
          }
      }
  
      /// <summary>
      /// Class representing an inequality comparison.
      /// </summary>
      public class NE : BinInfixOperator
      {
          public NE(Expression left, Expression right) : base(left, right) { }
  
          public override Expression Copy(string renameSuffix)
          {
              return new NE(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override string GetInfixOperator()
          {
              return " != ";
          }
      }
  
      /// <summary>
      /// Class representing a less than comparison.
      /// </summary>
      public class LT : BinInfixOperator
      {
          public LT(Expression left, Expression right) : base(left, right) { }
  
          public override Expression Copy(string renameSuffix)
          {
              return new LT(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override string GetInfixOperator()
          {
              return " < ";
          }
      }
  
      /// <summary>
      /// Class representing a less than or equal comparison.
      /// </summary>
      public class LE : BinInfixOperator
      {
          public LE(Expression left, Expression right) : base(left, right) { }
  
          public override Expression Copy(string renameSuffix)
          {
              return new LE(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override string GetInfixOperator()
          {
              return " <= ";
          }
      }
  
      /// <summary>
      /// Class representing a greater than comparison.
      /// </summary>
      public class GT : BinInfixOperator
      {
          public GT(Expression left, Expression right) : base(left, right) { }
  
          public override Expression Copy(string renameSuffix)
          {
              return new GT(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override string GetInfixOperator()
          {
              return " > ";
          }
      }
  
      /// <summary>
      /// Class representing a greater than or equal comparison.
      /// </summary>
      public class GE : BinInfixOperator
      {
          public GE(Expression left, Expression right) : base(left, right) { }
  
          public override Expression Copy(string renameSuffix)
          {
              return new GE(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override string GetInfixOperator()
          {
              return " >= ";
          }
      }
  
      /// <summary>
      /// Class representing a less than comparison on strings.
      /// </summary>
      public class STRING_LT : Operator
      {
          public STRING_LT(Expression left, Expression right)
          {
              Left = left;
              Right = right;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new STRING_LT(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("(String.Compare(");
              Left.Emit(sourceCode);
              sourceCode.Append(", ");
              Right.Emit(sourceCode);
              sourceCode.Append(", StringComparison.InvariantCulture)");
              sourceCode.Append("<0)");
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return Left;
              yield return Right;
          }
  
          protected Expression Left;
          protected Expression Right;
      }
  
      /// <summary>
      /// Class representing a less than or equal comparison on strings.
      /// </summary>
      public class STRING_LE : Operator
      {
          public STRING_LE(Expression left, Expression right)
          {
              Left = left;
              Right = right;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new STRING_LE(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("(String.Compare(");
              Left.Emit(sourceCode);
              sourceCode.Append(", ");
              Right.Emit(sourceCode);
              sourceCode.Append(", StringComparison.InvariantCulture)");
              sourceCode.Append("<=0)");
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return Left;
              yield return Right;
          }
  
          protected Expression Left;
          protected Expression Right;
      }
  
      /// <summary>
      /// Class representing a greater than comparison on strings.
      /// </summary>
      public class STRING_GT : Operator
      {
          public STRING_GT(Expression left, Expression right) 
          {
              Left = left;
              Right = right;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new STRING_GT(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("(String.Compare(");
              Left.Emit(sourceCode);
              sourceCode.Append(", ");
              Right.Emit(sourceCode);
              sourceCode.Append(", StringComparison.InvariantCulture)");
              sourceCode.Append(">0)");
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return Left;
              yield return Right;
          }
  
          protected Expression Left;
          protected Expression Right;
      }
  
      /// <summary>
      /// Class representing a greater than or equal comparison on strings.
      /// </summary>
      public class STRING_GE : Operator
      {
          public STRING_GE(Expression left, Expression right)
          {
              Left = left;
              Right = right;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new STRING_GE(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("(String.Compare(");
              Left.Emit(sourceCode);
              sourceCode.Append(", ");
              Right.Emit(sourceCode);
              sourceCode.Append(", StringComparison.InvariantCulture)");
              sourceCode.Append(">=0)");
          }
          
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return Left;
              yield return Right;
          }
  
          protected Expression Left;
          protected Expression Right;
      }
  
      // external comparisons
  
      /// <summary>
      /// Class representing an equality comparison.
      /// </summary>
      public class EXTERNAL_EQ : BinFuncOperator
      {
          public EXTERNAL_EQ(Expression left, Expression right) : base(left, right) { }
  
          public override Expression Copy(string renameSuffix)
          {
              return new EXTERNAL_EQ(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override string GetFuncOperatorAndLParen()
          {
              return "GRGEN_MODEL.AttributeTypeObjectCopierComparer.IsEqual(";
          }
      }
  
      /// <summary>
      /// Class representing an inequality comparison.
      /// </summary>
      public class EXTERNAL_NE : BinFuncOperator
      {
          public EXTERNAL_NE(Expression left, Expression right) : base(left, right) { }
  
          public override Expression Copy(string renameSuffix)
          {
              return new EXTERNAL_NE(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override string GetFuncOperatorAndLParen()
          {
              return "!GRGEN_MODEL.AttributeTypeObjectCopierComparer.IsEqual(";
          }
      }
  
      /// <summary>
      /// Class representing a less than comparison.
      /// </summary>
      public class EXTERNAL_LT : BinFuncOperator
      {
          public EXTERNAL_LT(Expression left, Expression right) : base(left, right) { }
  
          public override Expression Copy(string renameSuffix)
          {
              return new EXTERNAL_LT(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override string GetFuncOperatorAndLParen()
          {
              return "GRGEN_MODEL.AttributeTypeObjectCopierComparer.IsLower(";
          }
      }
  
      /// <summary>
      /// Class representing a less than or equal comparison.
      /// </summary>
      public class EXTERNAL_LE : Operator
      {
          public EXTERNAL_LE(Expression left, Expression right)
          {
              Left = left;
              Right = right;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new EXTERNAL_LE(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("(GRGEN_MODEL.AttributeTypeObjectCopierComparer.IsLower(");
              Left.Emit(sourceCode);
              sourceCode.Append(", ");
              Right.Emit(sourceCode);
              sourceCode.Append(")");
              sourceCode.Append("|| GRGEN_MODEL.AttributeTypeObjectCopierComparer.IsEqual(");
              Left.Emit(sourceCode);
              sourceCode.Append(", ");
              Right.Emit(sourceCode);
              sourceCode.Append("))");
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return Left;
              yield return Right;
          }
  
          protected Expression Left;
          protected Expression Right;
      }
  
      /// <summary>
      /// Class representing a greater than comparison.
      /// </summary>
      public class EXTERNAL_GT : Operator
      {
          public EXTERNAL_GT(Expression left, Expression right)
          {
              Left = left;
              Right = right;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new EXTERNAL_GT(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("(!GRGEN_MODEL.AttributeTypeObjectCopierComparer.IsLower(");
              Left.Emit(sourceCode);
              sourceCode.Append(", ");
              Right.Emit(sourceCode);
              sourceCode.Append(")");
              sourceCode.Append("&& !GRGEN_MODEL.AttributeTypeObjectCopierComparer.IsEqual(");
              Left.Emit(sourceCode);
              sourceCode.Append(", ");
              Right.Emit(sourceCode);
              sourceCode.Append("))");
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return Left;
              yield return Right;
          }
  
          protected Expression Left;
          protected Expression Right;
      }
  
      /// <summary>
      /// Class representing a greater than or equal comparison.
      /// </summary>
      public class EXTERNAL_GE : BinFuncOperator
      {
          public EXTERNAL_GE(Expression left, Expression right) : base(left, right) { }
  
          public override Expression Copy(string renameSuffix)
          {
              return new EXTERNAL_GE(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override string GetFuncOperatorAndLParen()
          {
              return "!GRGEN_MODEL.AttributeTypeObjectCopierComparer.IsLower(";
          }
      }
  
      // TODO: a lot of the functions for the containers are mapping to the same code, 
      // helper functions with the same name resolved by the types in the generated code,
      // would make sense, safe code to not distinguish them
  
      /// <summary>
      /// Class representing set/map equality comparison.
      /// </summary>
      public class DICT_EQ : BinFuncOperator
      {
          public DICT_EQ(Expression left, Expression right) : base(left, right) { }
  
          public override Expression Copy(string renameSuffix)
          {
              return new DICT_EQ(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override string GetFuncOperatorAndLParen()
          {
              return "GRGEN_LIBGR.ContainerHelper.Equal(";
          }
      }
  
      /// <summary>
      /// Class representing set/map inequality comparison.
      /// </summary>
      public class DICT_NE : BinFuncOperator
      {
          public DICT_NE(Expression left, Expression right) : base(left, right) { }
  
          public override Expression Copy(string renameSuffix)
          {
              return new DICT_NE(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override string GetFuncOperatorAndLParen()
          {
              return "GRGEN_LIBGR.ContainerHelper.NotEqual(";
          }
      }
  
      /// <summary>
      /// Class representing proper subset/map comparison.
      /// </summary>
      public class DICT_LT : BinFuncOperator
      {
          public DICT_LT(Expression left, Expression right) : base(left, right) { }
  
          public override Expression Copy(string renameSuffix)
          {
              return new DICT_LT(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override string GetFuncOperatorAndLParen()
          {
              return "GRGEN_LIBGR.ContainerHelper.LessThan(";
          }
      }
  
      /// <summary>
      /// Class representing subset/map comparison.
      /// </summary>
      public class DICT_LE : BinFuncOperator
      {
          public DICT_LE(Expression left, Expression right) : base(left, right) { }
  
          public override Expression Copy(string renameSuffix)
          {
              return new DICT_LE(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override string GetFuncOperatorAndLParen()
          {
              return "GRGEN_LIBGR.ContainerHelper.LessOrEqual(";
          }
      }
  
      /// <summary>
      /// Class representing proper superset comparison.
      /// </summary>
      public class DICT_GT : BinFuncOperator
      {
          public DICT_GT(Expression left, Expression right) : base(left, right) { }
  
          public override Expression Copy(string renameSuffix)
          {
              return new DICT_GT(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override string GetFuncOperatorAndLParen()
          {
              return "GRGEN_LIBGR.ContainerHelper.GreaterThan(";
          }
      }
  
      /// <summary>
      /// Class representing superset comparison.
      /// </summary>
      public class DICT_GE : BinFuncOperator
      {
          public DICT_GE(Expression left, Expression right) : base(left, right) { }
  
          public override Expression Copy(string renameSuffix)
          {
              return new DICT_GE(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override string GetFuncOperatorAndLParen()
          {
              return "GRGEN_LIBGR.ContainerHelper.GreaterOrEqual(";
          }
      }
  
      /// <summary>
      /// Class representing array equality comparison.
      /// </summary>
      public class LIST_EQ : BinFuncOperator
      {
          public LIST_EQ(Expression left, Expression right) : base(left, right) { }
  
          public override Expression Copy(string renameSuffix)
          {
              return new LIST_EQ(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override string GetFuncOperatorAndLParen()
          {
              return "GRGEN_LIBGR.ContainerHelper.Equal(";
          }
      }
  
      /// <summary>
      /// Class representing array inequality comparison.
      /// </summary>
      public class LIST_NE : BinFuncOperator
      {
          public LIST_NE(Expression left, Expression right) : base(left, right) { }
  
          public override Expression Copy(string renameSuffix)
          {
              return new LIST_NE(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override string GetFuncOperatorAndLParen()
          {
              return "GRGEN_LIBGR.ContainerHelper.NotEqual(";
          }
      }
  
      /// <summary>
      /// Class representing proper subarray comparison.
      /// </summary>
      public class LIST_LT : BinFuncOperator
      {
          public LIST_LT(Expression left, Expression right) : base(left, right) { }
  
          public override Expression Copy(string renameSuffix)
          {
              return new LIST_LT(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override string GetFuncOperatorAndLParen()
          {
              return "GRGEN_LIBGR.ContainerHelper.LessThan(";
          }
      }
  
      /// <summary>
      /// Class representing subarray comparison.
      /// </summary>
      public class LIST_LE : BinFuncOperator
      {
          public LIST_LE(Expression left, Expression right) : base(left, right) { }
  
          public override Expression Copy(string renameSuffix)
          {
              return new LIST_LE(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override string GetFuncOperatorAndLParen()
          {
              return "GRGEN_LIBGR.ContainerHelper.LessOrEqual(";
          }
      }
  
      /// <summary>
      /// Class representing proper superarray comparison.
      /// </summary>
      public class LIST_GT : BinFuncOperator
      {
          public LIST_GT(Expression left, Expression right) : base(left, right) { }
  
          public override Expression Copy(string renameSuffix)
          {
              return new LIST_GT(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override string GetFuncOperatorAndLParen()
          {
              return "GRGEN_LIBGR.ContainerHelper.GreaterThan(";
          }
      }
  
      /// <summary>
      /// Class representing superarray comparison.
      /// </summary>
      public class LIST_GE : BinFuncOperator
      {
          public LIST_GE(Expression left, Expression right) : base(left, right) { }
  
          public override Expression Copy(string renameSuffix)
          {
              return new LIST_GE(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override string GetFuncOperatorAndLParen()
          {
              return "GRGEN_LIBGR.ContainerHelper.GreaterOrEqual(";
          }
      }
  
      /// <summary>
      /// Class representing deque equality comparison.
      /// </summary>
      public class DEQUE_EQ : BinFuncOperator
      {
          public DEQUE_EQ(Expression left, Expression right) : base(left, right) { }
  
          public override Expression Copy(string renameSuffix)
          {
              return new DEQUE_EQ(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override string GetFuncOperatorAndLParen()
          {
              return "GRGEN_LIBGR.ContainerHelper.Equal(";
          }
      }
  
      /// <summary>
      /// Class representing deque inequality comparison.
      /// </summary>
      public class DEQUE_NE : BinFuncOperator
      {
          public DEQUE_NE(Expression left, Expression right) : base(left, right) { }
  
          public override Expression Copy(string renameSuffix)
          {
              return new DEQUE_NE(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override string GetFuncOperatorAndLParen()
          {
              return "GRGEN_LIBGR.ContainerHelper.NotEqual(";
          }
      }
  
      /// <summary>
      /// Class representing proper subdeque comparison.
      /// </summary>
      public class DEQUE_LT : BinFuncOperator
      {
          public DEQUE_LT(Expression left, Expression right) : base(left, right) { }
  
          public override Expression Copy(string renameSuffix)
          {
              return new DEQUE_LT(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override string GetFuncOperatorAndLParen()
          {
              return "GRGEN_LIBGR.ContainerHelper.LessThan(";
          }
      }
  
      /// <summary>
      /// Class representing subdeque comparison.
      /// </summary>
      public class DEQUE_LE : BinFuncOperator
      {
          public DEQUE_LE(Expression left, Expression right) : base(left, right) { }
  
          public override Expression Copy(string renameSuffix)
          {
              return new DEQUE_LE(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override string GetFuncOperatorAndLParen()
          {
              return "GRGEN_LIBGR.ContainerHelper.LessOrEqual(";
          }
      }
  
      /// <summary>
      /// Class representing proper superdeque comparison.
      /// </summary>
      public class DEQUE_GT : BinFuncOperator
      {
          public DEQUE_GT(Expression left, Expression right) : base(left, right) { }
  
          public override Expression Copy(string renameSuffix)
          {
              return new DEQUE_GT(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override string GetFuncOperatorAndLParen()
          {
              return "GRGEN_LIBGR.ContainerHelper.GreaterThan(";
          }
      }
  
      /// <summary>
      /// Class representing superdeque comparison.
      /// </summary>
      public class DEQUE_GE : BinFuncOperator
      {
          public DEQUE_GE(Expression left, Expression right) : base(left, right) { }
  
          public override Expression Copy(string renameSuffix)
          {
              return new DEQUE_GE(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override string GetFuncOperatorAndLParen()
          {
              return "GRGEN_LIBGR.ContainerHelper.GreaterOrEqual(";
          }
      }
  
      /// <summary>
      /// Class representing a graph is-isomorph comparison.
      /// </summary>
      public class GRAPH_EQ : Operator
      {
          public GRAPH_EQ(Expression left, Expression right)
          {
              Left = left;
              Right = right;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new GRAPH_EQ(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("((GRGEN_LIBGR.IGraph)");
              Left.Emit(sourceCode);
              sourceCode.Append(").IsIsomorph((GRGEN_LIBGR.IGraph)");
              Right.Emit(sourceCode);
              sourceCode.Append(")");
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return Left;
              yield return Right;
          }
  
          protected Expression Left;
          protected Expression Right;
      }
  
      /// <summary>
      /// Class representing a graph is-not-isomorph comparison.
      /// </summary>
      public class GRAPH_NE : Operator
      {
          public GRAPH_NE(Expression left, Expression right)
          {
              Left = left;
              Right = right;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new GRAPH_NE(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("!((GRGEN_LIBGR.IGraph)");
              Left.Emit(sourceCode);
              sourceCode.Append(").IsIsomorph((GRGEN_LIBGR.IGraph)");
              Right.Emit(sourceCode);
              sourceCode.Append(")");
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return Left;
              yield return Right;
          }
  
          protected Expression Left;
          protected Expression Right;
      }
  
      /// <summary>
      /// Class representing a graph is-structural-equal (isomorph disregarding attributes) comparison.
      /// </summary>
      public class GRAPH_SE : Operator
      {
          public GRAPH_SE(Expression left, Expression right)
          {
              Left = left;
              Right = right;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new GRAPH_SE(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("((GRGEN_LIBGR.IGraph)");
              Left.Emit(sourceCode);
              sourceCode.Append(").HasSameStructure((GRGEN_LIBGR.IGraph)");
              Right.Emit(sourceCode);
              sourceCode.Append(")");
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return Left;
              yield return Right;
          }
  
          protected Expression Left;
          protected Expression Right;
      }
  
      /// <summary>
      /// Class representing a shift left expression.
      /// </summary>
      public class SHL : BinInfixOperator
      {
          public SHL(Expression left, Expression right) : base(left, right) { }
  
          public override Expression Copy(string renameSuffix)
          {
              return new SHL(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override string GetInfixOperator()
          {
              return " << ";
          }
      }
  
      /// <summary>
      /// Class representing an arithmetic shift right expression.
      /// </summary>
      public class SHR : BinInfixOperator
      {
          public SHR(Expression left, Expression right) : base(left, right) { }
  
          public override Expression Copy(string renameSuffix)
          {
              return new SHR(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override string GetInfixOperator()
          {
              return " >> ";
          }
      }
  
      /// <summary>
      /// Class representing a bit shift right expression, i.e. 0-extending, not sign-extending.
      /// </summary>
      public class BIT_SHR : BinInfixOperator
      {
          public BIT_SHR(Expression left, Expression right) : base(left, right) { }
  
          public override Expression Copy(string renameSuffix)
          {
              return new BIT_SHR(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("((int)(((uint)");
              Left.Emit(sourceCode);
              sourceCode.Append(")" + GetInfixOperator());
              Right.Emit(sourceCode);
              sourceCode.Append("))");
          }
  
          public override string GetInfixOperator()
          {
              return " >> ";
          }
      }
  
      /// <summary>
      /// Class representing an addition.
      /// </summary>
      public class ADD : BinInfixOperator
      {
          public ADD(Expression left, Expression right) : base(left, right) { }
  
          public override Expression Copy(string renameSuffix)
          {
              return new ADD(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override string GetInfixOperator()
          {
              return " + ";
          }
      }
  
      /// <summary>
      /// Class representing an array concatenation.
      /// </summary>
      public class LIST_ADD : BinFuncOperator
      {
          public LIST_ADD(Expression left, Expression right) : base(left, right) { }
  
          public override Expression Copy(string renameSuffix)
          {
              return new LIST_ADD(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override string GetFuncOperatorAndLParen()
          {
              return "GRGEN_LIBGR.ContainerHelper.Concatenate(";
          }
      }
  
      /// <summary>
      /// Class representing a Deque concatenation.
      /// </summary>
      public class DEQUE_ADD : BinFuncOperator
      {
          public DEQUE_ADD(Expression left, Expression right) : base(left, right) { }
  
          public override Expression Copy(string renameSuffix)
          {
              return new DEQUE_ADD(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override string GetFuncOperatorAndLParen()
          {
              return "GRGEN_LIBGR.ContainerHelper.Concatenate(";
          }
      }
  
      /// <summary>
      /// Class representing a subtraction.
      /// </summary>
      public class SUB : BinInfixOperator
      {
          public SUB(Expression left, Expression right) : base(left, right) { }
  
          public override Expression Copy(string renameSuffix)
          {
              return new SUB(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override string GetInfixOperator()
          {
              return " - ";
          }
      }
  
      /// <summary>
      /// Class representing a multiplication.
      /// </summary>
      public class MUL : BinInfixOperator
      {
          public MUL(Expression left, Expression right) : base(left, right) { }
  
          public override Expression Copy(string renameSuffix)
          {
              return new MUL(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override string GetInfixOperator()
          {
              return " * ";
          }
      }
  
      /// <summary>
      /// Class representing a division.
      /// </summary>
      public class DIV : BinInfixOperator
      {
          public DIV(Expression left, Expression right) : base(left, right) { }
  
          public override Expression Copy(string renameSuffix)
          {
              return new DIV(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override string GetInfixOperator()
          {
              return " / ";
          }
      }
  
  
      /// <summary>
      /// Class representing a modulo expression.
      /// </summary>
      public class MOD : BinInfixOperator
      {
          public MOD(Expression left, Expression right) : base(left, right) { }
  
          public override Expression Copy(string renameSuffix)
          {
              return new MOD(Left.Copy(renameSuffix), Right.Copy(renameSuffix));
          }
  
          public override string GetInfixOperator()
          {
              return " % ";
          }
      }
  
      /// <summary>
      /// Class representing a logical negation.
      /// </summary>
      public class LOG_NOT : Operator
      {
          public LOG_NOT(Expression nested)
          {
              Nested = nested;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new LOG_NOT(Nested.Copy(renameSuffix));
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("!");
              Nested.Emit(sourceCode);
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return Nested;
          }
  
          Expression Nested;
      }
  
      /// <summary>
      /// Class representing a bitwise negation.
      /// </summary>
      public class BIT_NOT : Operator
      {
          public BIT_NOT(Expression nested)
          {
              Nested = nested;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new BIT_NOT(Nested.Copy(renameSuffix));
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("~");
              Nested.Emit(sourceCode);
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return Nested;
          }
  
          Expression Nested;
      }
  
      /// <summary>
      /// Class representing an arithmetic negation.
      /// </summary>
      public class NEG : Operator
      {
          public NEG(Expression nested)
          {
              Nested = nested;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new NEG(Nested.Copy(renameSuffix));
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("-");
              Nested.Emit(sourceCode);
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return Nested;
          }
  
          Expression Nested;
      }
  
      /// <summary>
      /// Class representing a container or string inclusion query.
      /// </summary>
      public class IN : BinInfixOperator
      {
          // Switch operands as "right" is the dictionary
          public IN(Expression left, Expression right, bool isDictionary)
              : base(right, left)
          {
              IsDictionary = isDictionary;
          }
  
          // Switch operands as "right" is the dictionary
          public IN(Expression left, Expression right, String type, bool isDictionary)
              : base(right, left)
          {
              Type = type;
              IsDictionary = isDictionary;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              if(Type != null) // the constructor is reversing left and right so it fits for emit, reverse twice to keep order of already constructed object
                  return new IN(Right.Copy(renameSuffix), Left.Copy(renameSuffix), Type, IsDictionary);
              else
                  return new IN(Right.Copy(renameSuffix), Left.Copy(renameSuffix), IsDictionary);
          }
  
          public override string GetInfixOperator()
          {
              if(IsDictionary)
              {
                  if(Type != null)
                      return ").ContainsKey((" + Type + ")";
                  else
                      return ").ContainsKey(";
              }
              else
              {
                  if(Type != null)
                      return ").Contains((" + Type + ")";
                  else
                      return ").Contains(";
              }
          }
  
          String Type;
          bool IsDictionary;
      }
  
      /// <summary>
      /// Class representing cast expression
      /// </summary>
      public class Cast : Expression
      {
          public Cast(String typeName, Expression nested, bool isContainer)
          {
              TypeName = typeName;
              Nested = nested;
              IsContainer = isContainer;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new Cast(TypeName, Nested.Copy(renameSuffix), IsContainer);
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              if (TypeName == "string")
              {
                  if(IsContainer)
                  {
                      sourceCode.Append("GRGEN_LIBGR.EmitHelper.ToString(");
                      Nested.Emit(sourceCode);
                      sourceCode.Append(", graph)");
                  }
                  else
                  {
                      sourceCode.Append("GRGEN_LIBGR.EmitHelper.ToStringNonNull(");
                      Nested.Emit(sourceCode);
                      sourceCode.Append(", graph)");
                  }
              }
              else
              {
                  sourceCode.Append("(" + TypeName + ")");
                  Nested.Emit(sourceCode);
              }
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return Nested;
          }
  
          String TypeName;
          Expression Nested;
          bool IsContainer;
      }
  
      /// <summary>
      /// Class representing constant expression
      /// </summary>
      public class Constant : Expression
      {
          public Constant(string value)
          {
              Value = value;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new Constant(Value);
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append(Value);
          }
  
          String Value;
      }
  
      /// <summary>
      /// Class representing enum constant expression
      /// </summary>
      public class ConstantEnumExpression : Expression
      {
          public ConstantEnumExpression(string enumType, string enumItem)
          {
              EnumType = enumType;
              EnumItem = enumItem;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new ConstantEnumExpression(EnumType, EnumItem);
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("GRGEN_MODEL.ENUM_" + EnumType + ".@" + EnumItem);
          }
  
          string EnumType;
          string EnumItem;
      }
  
      /// <summary>
      /// Class representing graph entity expression
      /// </summary>
      public class GraphEntityExpression : Expression
      {
          public GraphEntityExpression(String entity)
          {
              Entity = entity;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new GraphEntityExpression(Entity + renameSuffix);
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append(NamesOfEntities.CandidateVariable(Entity));
          }
  
          public String Entity;
      }
  
      /// <summary>
      /// Class representing nameof expression
      /// </summary>
      public class Nameof : Expression
      {
          public Nameof(Expression entity)
          {
              Entity = entity;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              if(Entity != null)
                  return new Nameof(Entity.Copy(renameSuffix));
              else
                  return new Nameof(null);
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              if (Entity != null)
              {
                  sourceCode.Append("GRGEN_LIBGR.GraphHelper.Nameof(");
                  Entity.Emit(sourceCode);
                  sourceCode.Append(", graph)");
              }
              else
                  sourceCode.Append("GRGEN_LIBGR.GraphHelper.Nameof(null, graph)");
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              if(Entity != null)
                  yield return Entity;
          }
  
          Expression Entity;
      }
  
      /// <summary>
      /// Class representing unique id expression
      /// </summary>
      public class Uniqueof : Expression
      {
          public Uniqueof(Expression entity, bool isNode, bool isGraph)
          {
              Entity = entity;
              IsNode = isNode;
              IsGraph = isGraph;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              if(Entity != null)
                  return new Uniqueof(Entity.Copy(renameSuffix), IsNode, IsGraph);
              else
                  return new Uniqueof(null, IsNode, IsGraph);
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              if(Entity == null)
              {
                  sourceCode.Append("((GRGEN_LGSP.LGSPGraph)graph).GraphId");
              }
              else
              {
                  sourceCode.Append("(");
                  if(IsNode && !IsGraph)
                      sourceCode.Append("(GRGEN_LGSP.LGSPNode)");
                  else if(!IsNode && !IsGraph)
                      sourceCode.Append("(GRGEN_LGSP.LGSPEdge)");
                  else
                      sourceCode.Append("(GRGEN_LGSP.LGSPGraph)");
                  Entity.Emit(sourceCode);
                  if(IsGraph)
                      sourceCode.Append(").GraphId");
                  else
                      sourceCode.Append(").uniqueId");
              }
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              if(Entity != null)
                  yield return Entity;
          }
  
          Expression Entity;
          bool IsNode;
          bool IsGraph;
      }
  
      /// <summary>
      /// Class representing exists file expression
      /// </summary>
      public class ExistsFileExpression : Expression
      {
          public ExistsFileExpression(Expression path)
          {
              Path = path;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new ExistsFileExpression(Path.Copy(renameSuffix));
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("System.IO.File.Exists(");
              Path.Emit(sourceCode);
              sourceCode.Append(")");
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return Path;
          }
  
          Expression Path;
      }
  
      /// <summary>
      /// Class representing import expression
      /// </summary>
      public class ImportExpression : Expression
      {
          public ImportExpression(Expression path)
          {
              Path = path;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new ImportExpression(Path.Copy(renameSuffix));
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("GRGEN_LIBGR.GraphHelper.Import(");
              Path.Emit(sourceCode);
              sourceCode.Append(", graph)");
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return Path;
          }
  
          Expression Path;
      }
  
      /// <summary>
      /// Class representing copy expression
      /// </summary>
      public class CopyExpression : Expression
      {
          public CopyExpression(Expression graphOrContainer, String type)
          {
              GraphOrContainer = graphOrContainer;
              Type = type;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new CopyExpression(GraphOrContainer.Copy(renameSuffix), Type);
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              if(Type == null)
              {
                  sourceCode.Append("GRGEN_LIBGR.GraphHelper.Copy(");
                  GraphOrContainer.Emit(sourceCode);
                  sourceCode.Append(")");
              }
              else
              {
                  sourceCode.Append("new " + Type + "(");
                  GraphOrContainer.Emit(sourceCode);
                  sourceCode.Append(")");
              }
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return GraphOrContainer;
          }
  
          String Type; // if non-null, gives the container type to copy, if null it's a graph
          Expression GraphOrContainer;
      }
  
      /// <summary>
      /// Class representing count of instances of an iterated pattern expression
      /// </summary>
      public class Count : Expression
      {
          public Count(String iterated)
          {
              Iterated = iterated;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new Count(Iterated + renameSuffix);
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("match." + NamesOfEntities.MatchName(Iterated, BuildMatchObjectType.Iteration) + ".Count");
          }
  
          String Iterated;
      }
  
      /// <summary>
      /// Class representing qualification expression
      /// </summary>
      public class Qualification : Expression
      {
          public Qualification(String ownerType, String owner, String member)
          {
              OwnerType = ownerType;
              Owner = owner;
              Member = member;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new Qualification(OwnerType, Owner + renameSuffix, Member);
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("((" + OwnerType + ")"+ NamesOfEntities.CandidateVariable(Owner) + ").@" + Member);
          }
  
          String OwnerType;
          String Owner;
          String Member;
      }
  
      /// <summary>
      /// Class representing global variable qualification expression
      /// </summary>
      public class GlobalVariableQualification : Expression
      {
          public GlobalVariableQualification(String ownerType, String owner, String member)
          {
              OwnerType = ownerType;
              Owner = owner;
              Member = member;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new GlobalVariableQualification(OwnerType, Owner, Member);
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.AppendFormat("(({0})((GRGEN_LGSP.LGSPGraphProcessingEnvironment)actionEnv).GetVariableValue(\"{1}\")).@{2}", OwnerType, Owner, Member);
          }
  
          String OwnerType;
          String Owner;
          String Member;
      }
  
      /// <summary>
      /// Class representing qualification after cast expression
      /// </summary>
      public class CastQualification : Expression
      {
          public CastQualification(Expression owner, String member)
          {
              Owner = owner;
              Member = member;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new CastQualification(Owner.Copy(renameSuffix), Member);
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("(");
              Owner.Emit(sourceCode);
              sourceCode.Append(").@" + Member);
          }
  
          Expression Owner;
          String Member;
      }
  
      /// <summary>
      /// Class representing typeof expression
      /// </summary>
      public class Typeof : Expression
      {
          public Typeof(String entity)
          {
              Entity = entity;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new Typeof(Entity + renameSuffix);
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append(NamesOfEntities.CandidateVariable(Entity) + ".lgspType");
          }
  
          String Entity;
      }
  
      /// <summary>
      /// Class representing variable expression
      /// </summary>
      public class VariableExpression : Expression
      {
          public VariableExpression(String entity)
          {
              Entity = entity;
              MatchEntity = null;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              VariableExpression tmp = new VariableExpression(Entity + renameSuffix);
              if(MatchEntity != null)
                  tmp.MatchEntity = MatchEntity + renameSuffix;
              return tmp;
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              if(MatchEntity!=null)
                  sourceCode.Append(MatchEntity);
              else
                  sourceCode.Append(NamesOfEntities.Variable(Entity));
          }
  
          public String Entity;
          public String MatchEntity;
      }
  
      /// <summary>
      /// Class representing global variable expression
      /// </summary>
      public class GlobalVariableExpression : Expression
      {
          public GlobalVariableExpression(String name, String type)
          {
              GlobalVariableName = name;
              Type = type;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new GlobalVariableExpression(GlobalVariableName, Type);
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.AppendFormat("(({0})((GRGEN_LGSP.LGSPGraphProcessingEnvironment)actionEnv).GetVariableValue(\"{1}\"))", Type, GlobalVariableName);
          }
  
          public String GlobalVariableName;
          public String Type;
      }
  
      /// <summary>
      /// Class representing visited expression
      /// </summary>
      public class Visited : Expression
      {
          public Visited(Expression entity, Expression nested) // nested = expression computing visited-id
          {
              Entity = entity;
              Nested = nested;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new Visited(Entity.Copy(renameSuffix), Nested.Copy(renameSuffix));
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("graph.IsVisited(");
              Entity.Emit(sourceCode);
              sourceCode.Append(", ");
              Nested.Emit(sourceCode);
              sourceCode.Append(")");
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return Entity;
              yield return Nested;
          }
  
          Expression Entity;
          Expression Nested;
      }
  
      /// <summary>
      /// Class representing random expression
      /// </summary>
      public class Random : Expression
      {
          public Random(Expression nested) // nested = expression computing maximum value for int random
          {
              Nested = nested;
          }
  
          public Random() // double random
          {
              Nested = null;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              if(Nested != null)
                  return new Random(Nested.Copy(renameSuffix));
              else
                  return new Random();
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              if(Nested != null)
              {
                  sourceCode.Append("GRGEN_LIBGR.Sequence.randomGenerator.Next(");
                  Nested.Emit(sourceCode);
              }
              else
              {
                  sourceCode.Append("GRGEN_LIBGR.Sequence.randomGenerator.NextDouble(");
              }
              sourceCode.Append(")");
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              if(Nested != null)
                  yield return Nested;
              else
                  yield break;
          }
  
          Expression Nested;
      }
  
      /// <summary>
      /// Class representing this expression
      /// </summary>
      public class This : Expression
      {
          public This()
          {
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new This();
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("graph");
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield break;
          }
      }
  
      /// <summary>
      /// Class representing a string length expression.
      /// </summary>
      public class StringLength : Expression
      {
          public StringLength(Expression stringExpr)
          {
              StringExpr = stringExpr;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new StringLength(StringExpr.Copy(renameSuffix));
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("(");
              StringExpr.Emit(sourceCode);
              sourceCode.Append(").Length");
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return StringExpr;
          }
  
          Expression StringExpr;
      }
  
      /// <summary>
      /// Class representing a string to uppercase expression.
      /// </summary>
      public class StringToUpper : Expression
      {
          public StringToUpper(Expression stringExpr)
          {
              StringExpr = stringExpr;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new StringToUpper(StringExpr.Copy(renameSuffix));
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("(");
              StringExpr.Emit(sourceCode);
              sourceCode.Append(").ToUpperInvariant()");
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return StringExpr;
          }
  
          Expression StringExpr;
      }
  
      /// <summary>
      /// Class representing a string to lowercase expression.
      /// </summary>
      public class StringToLower : Expression
      {
          public StringToLower(Expression stringExpr)
          {
              StringExpr = stringExpr;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new StringToLower(StringExpr.Copy(renameSuffix));
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("(");
              StringExpr.Emit(sourceCode);
              sourceCode.Append(").ToLowerInvariant()");
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return StringExpr;
          }
  
          Expression StringExpr;
      }
  
      /// <summary>
      /// Class representing a substring expression.
      /// </summary>
      public class StringSubstring : Expression
      {
          public StringSubstring(Expression stringExpr, Expression startExpr, Expression lengthExpr)
          {
              StringExpr = stringExpr;
              StartExpr = startExpr;
              LengthExpr = lengthExpr;
          }
  
          public StringSubstring(Expression stringExpr, Expression startExpr)
          {
              StringExpr = stringExpr;
              StartExpr = startExpr;
              LengthExpr = null;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new StringSubstring(StringExpr.Copy(renameSuffix), 
                  StartExpr.Copy(renameSuffix), LengthExpr!=null ? LengthExpr.Copy(renameSuffix) : null);
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("(");
              StringExpr.Emit(sourceCode);
              sourceCode.Append(").Substring(");
              StartExpr.Emit(sourceCode);
              if(LengthExpr != null)
              {
                  sourceCode.Append(", ");
                  LengthExpr.Emit(sourceCode);
              }
              sourceCode.Append(")");
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return StringExpr;
              yield return StartExpr;
              if(LengthExpr != null)
                  yield return LengthExpr;
          }
  
          Expression StringExpr;
          Expression StartExpr;
          Expression LengthExpr;
      }
  
      /// <summary>
      /// Class representing a string indexOf expression.
      /// </summary>
      public class StringIndexOf : Expression
      {
          public StringIndexOf(Expression stringExpr, Expression stringToSearchForExpr)
          {
              StringExpr = stringExpr;
              StringToSearchForExpr = stringToSearchForExpr;
          }
  
          public StringIndexOf(Expression stringExpr, Expression stringToSearchForExpr, Expression startIndexExpr)
          {
              StringExpr = stringExpr;
              StringToSearchForExpr = stringToSearchForExpr;
              StartIndexExpr = startIndexExpr;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              if(StartIndexExpr!=null)
                  return new StringIndexOf(StringExpr.Copy(renameSuffix), StringToSearchForExpr.Copy(renameSuffix), StartIndexExpr.Copy(renameSuffix));
              else
                  return new StringIndexOf(StringExpr.Copy(renameSuffix), StringToSearchForExpr.Copy(renameSuffix));
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("(");
              StringExpr.Emit(sourceCode);
              sourceCode.Append(").IndexOf(");
              StringToSearchForExpr.Emit(sourceCode);
              if(StartIndexExpr != null)
              {
                  sourceCode.Append(", ");
                  StartIndexExpr.Emit(sourceCode);
              }
              sourceCode.Append(", StringComparison.InvariantCulture");
              sourceCode.Append(")");
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return StringExpr;
              yield return StringToSearchForExpr;
              if(StartIndexExpr != null)
                  yield return StartIndexExpr;
          }
  
          Expression StringExpr;
          Expression StringToSearchForExpr;
          Expression StartIndexExpr;
      }
  
      /// <summary>
      /// Class representing a string lastIndexOf expression.
      /// </summary>
      public class StringLastIndexOf : Expression
      {
          public StringLastIndexOf(Expression stringExpr, Expression stringToSearchForExpr)
          {
              StringExpr = stringExpr;
              StringToSearchForExpr = stringToSearchForExpr;
          }
  
          public StringLastIndexOf(Expression stringExpr, Expression stringToSearchForExpr, Expression startIndexExpr)
          {
              StringExpr = stringExpr;
              StringToSearchForExpr = stringToSearchForExpr;
              StartIndexExpr = startIndexExpr;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              if(StartIndexExpr != null)
                  return new StringLastIndexOf(StringExpr.Copy(renameSuffix), StringToSearchForExpr.Copy(renameSuffix), StartIndexExpr.Copy(renameSuffix));
              else
                  return new StringLastIndexOf(StringExpr.Copy(renameSuffix), StringToSearchForExpr.Copy(renameSuffix));
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("(");
              StringExpr.Emit(sourceCode);
              sourceCode.Append(").LastIndexOf(");
              StringToSearchForExpr.Emit(sourceCode);
              if(StartIndexExpr != null)
              {
                  sourceCode.Append(", ");
                  StartIndexExpr.Emit(sourceCode);
              }
              sourceCode.Append(", StringComparison.InvariantCulture");
              sourceCode.Append(")");
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return StringExpr;
              yield return StringToSearchForExpr;
              if(StartIndexExpr != null)
                  yield return StartIndexExpr;
          }
  
          Expression StringExpr;
          Expression StringToSearchForExpr;
          Expression StartIndexExpr;
      }
  
      /// <summary>
      /// Class representing a string starts with expression.
      /// </summary>
      public class StringStartsWith : Expression
      {
          public StringStartsWith(Expression stringExpr, Expression stringToSearchForExpr)
          {
              StringExpr = stringExpr;
              StringToSearchForExpr = stringToSearchForExpr;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new StringStartsWith(StringExpr.Copy(renameSuffix), StringToSearchForExpr.Copy(renameSuffix));
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("(");
              StringExpr.Emit(sourceCode);
              sourceCode.Append(").StartsWith(");
              StringToSearchForExpr.Emit(sourceCode);
              sourceCode.Append(", StringComparison.InvariantCulture");
              sourceCode.Append(")");
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return StringExpr;
              yield return StringToSearchForExpr;
          }
  
          Expression StringExpr;
          Expression StringToSearchForExpr;
      }
  
      /// <summary>
      /// Class representing a string ends with expression.
      /// </summary>
      public class StringEndsWith : Expression
      {
          public StringEndsWith(Expression stringExpr, Expression stringToSearchForExpr)
          {
              StringExpr = stringExpr;
              StringToSearchForExpr = stringToSearchForExpr;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new StringEndsWith(StringExpr.Copy(renameSuffix), StringToSearchForExpr.Copy(renameSuffix));
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("(");
              StringExpr.Emit(sourceCode);
              sourceCode.Append(").EndsWith(");
              StringToSearchForExpr.Emit(sourceCode);
              sourceCode.Append(", StringComparison.InvariantCulture");
              sourceCode.Append(")");
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return StringExpr;
              yield return StringToSearchForExpr;
          }
  
          Expression StringExpr;
          Expression StringToSearchForExpr;
      }
  
      /// <summary>
      /// Class representing a string replace expression.
      /// </summary>
      public class StringReplace : Expression
      {
          public StringReplace(Expression stringExpr, Expression startExpr, Expression lengthExpr, Expression replaceStrExpr)
          {
              StringExpr = stringExpr;
              StartExpr = startExpr;
              LengthExpr = lengthExpr;
              ReplaceStrExpr = replaceStrExpr;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new StringReplace(StringExpr.Copy(renameSuffix), StartExpr.Copy(renameSuffix),
                  LengthExpr.Copy(renameSuffix), ReplaceStrExpr.Copy(renameSuffix));
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("((");
              StringExpr.Emit(sourceCode);
              sourceCode.Append(").Substring(0, ");
              StartExpr.Emit(sourceCode);
              sourceCode.Append(") + ");
              ReplaceStrExpr.Emit(sourceCode);
              sourceCode.Append(" + (");
              StringExpr.Emit(sourceCode);
              sourceCode.Append(").Substring(");
              StartExpr.Emit(sourceCode);
              sourceCode.Append(" + ");
              LengthExpr.Emit(sourceCode);
              sourceCode.Append("))");
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return StringExpr;
              yield return StartExpr;
              yield return LengthExpr;
              yield return ReplaceStrExpr;
          }
  
          Expression StringExpr;
          Expression StartExpr;
          Expression LengthExpr;
          Expression ReplaceStrExpr;
      }
  
      /// <summary>
      /// Class representing a string as array expression.
      /// </summary>
      public class StringAsArray : Expression
      {
          public StringAsArray(Expression stringExpr, Expression stringToSplitAtExpr)
          {
              StringExpr = stringExpr;
              StringToSplitAtExpr = stringToSplitAtExpr;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new StringAsArray(StringExpr.Copy(renameSuffix), StringToSplitAtExpr.Copy(renameSuffix));
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("GRGEN_LIBGR.ContainerHelper.StringAsArray(");
              StringExpr.Emit(sourceCode);
              sourceCode.Append(", ");
              StringToSplitAtExpr.Emit(sourceCode);
              sourceCode.Append(")");
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return StringExpr;
              yield return StringToSplitAtExpr;
          }
  
          Expression StringExpr;
          Expression StringToSplitAtExpr;
      }
  
      /// <summary>
      /// Class representing a map access expression.
      /// </summary>
      public class MapAccess : Expression
      {
          public MapAccess(Expression target, Expression keyExpr)
          {
              Target = target;
              KeyExpr = keyExpr;
          }
  
          public MapAccess(Expression target, Expression keyExpr, String type)
          {
              Target = target;
              KeyExpr = keyExpr;
              Type = type;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new MapAccess(Target.Copy(renameSuffix), KeyExpr.Copy(renameSuffix), Type);
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("(");
              Target.Emit(sourceCode);
              sourceCode.Append("[");
              if(Type != null)
                  sourceCode.Append("(" + Type + ")");
              KeyExpr.Emit(sourceCode);
              sourceCode.Append("])");
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return Target;
              yield return KeyExpr;
          }
  
          Expression Target;
          Expression KeyExpr;
          String Type;
      }
  
      /// <summary>
      /// Class representing an array access expression.
      /// </summary>
      public class ArrayAccess : Expression
      {
          public ArrayAccess(Expression target, Expression keyExpr)
          {
              Target = target;
              KeyExpr = keyExpr;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new ArrayAccess(Target.Copy(renameSuffix), KeyExpr.Copy(renameSuffix));
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("(");
              Target.Emit(sourceCode);
              sourceCode.Append("[");
              KeyExpr.Emit(sourceCode);
              sourceCode.Append("])");
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return Target;
              yield return KeyExpr;
          }
  
          Expression Target;
          Expression KeyExpr;
      }
  
      /// <summary>
      /// Class representing a deque access expression.
      /// </summary>
      public class DequeAccess : Expression
      {
          public DequeAccess(Expression target, Expression keyExpr)
          {
              Target = target;
              KeyExpr = keyExpr;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new DequeAccess(Target.Copy(renameSuffix), KeyExpr.Copy(renameSuffix));
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("(");
              Target.Emit(sourceCode);
              sourceCode.Append("[");
              KeyExpr.Emit(sourceCode);
              sourceCode.Append("])");
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return Target;
              yield return KeyExpr;
          }
  
          Expression Target;
          Expression KeyExpr;
      }
  
      /// <summary>
      /// Class representing an incidence count index access expression.
      /// </summary>
      public class IncidenceCountIndexAccess : Expression
      {
          public IncidenceCountIndexAccess(String target, Expression keyExpr, String type)
          {
              Target = target;
              KeyExpr = keyExpr;
              Type = type;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new IncidenceCountIndexAccess(Target, KeyExpr.Copy(renameSuffix), Type);
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("((GRGEN_LIBGR.IIncidenceCountIndex)graph.Indices.GetIndex(\"" + Target + "\")).GetIncidenceCount(");
              sourceCode.Append("(" + Type + ")");
              KeyExpr.Emit(sourceCode);
              sourceCode.Append(")");
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return KeyExpr;
          }
  
          String Target;
          Expression KeyExpr;
          String Type;
      }
  
      /// <summary>
      /// Class representing a map size expression.
      /// </summary>
      public class MapSize : Expression
      {
          public MapSize(Expression target)
          {
              Target = target;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new MapSize(Target.Copy(renameSuffix));
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("(");
              Target.Emit(sourceCode);
              sourceCode.Append(").Count");
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return Target;
          }
  
          Expression Target;
      }
  
      /// <summary>
      /// Class representing a map empty expression.
      /// </summary>
      public class MapEmpty : Expression
      {
          public MapEmpty(Expression target)
          {
              Target = target;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new MapEmpty(Target.Copy(renameSuffix));
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("((");
              Target.Emit(sourceCode);
              sourceCode.Append(").Count==0)");
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return Target;
          }
  
          Expression Target;
      }
  
      /// <summary>
      /// Class representing a map peek expression.
      /// </summary>
      public class MapPeek : Expression
      {
          public MapPeek(Expression target, Expression number)
          {
              Target = target;
              Number = number;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new MapPeek(Target.Copy(renameSuffix), Number.Copy(renameSuffix));
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("GRGEN_LIBGR.ContainerHelper.Peek(");
              Target.Emit(sourceCode);
              sourceCode.Append(",");
              Number.Emit(sourceCode);
              sourceCode.Append(")");
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return Target;
              yield return Number;
          }
  
          Expression Target;
          Expression Number;
      }
  
      /// <summary>
      /// Class representing a map domain expression.
      /// </summary>
      public class MapDomain : Expression
      {
          public MapDomain(Expression target)
          {
              Target = target;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new MapDomain(Target.Copy(renameSuffix));
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("GRGEN_LIBGR.ContainerHelper.Domain(");
              Target.Emit(sourceCode);
              sourceCode.Append(")");
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return Target;
          }
  
          Expression Target;
      }
  
      /// <summary>
      /// Class representing a map range expression.
      /// </summary>
      public class MapRange : Expression
      {
          public MapRange(Expression target)
          {
              Target = target;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new MapRange(Target.Copy(renameSuffix));
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("GRGEN_LIBGR.ContainerHelper.Range(");
              Target.Emit(sourceCode);
              sourceCode.Append(")");
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return Target;
          }
  
          Expression Target;
      }
  
      /// <summary>
      /// Class representing a map as array expression.
      /// </summary>
      public class MapAsArray : Expression
      {
          public MapAsArray(Expression target)
          {
              Target = target;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new MapAsArray(Target.Copy(renameSuffix));
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("GRGEN_LIBGR.ContainerHelper.MapAsArray(");
              Target.Emit(sourceCode);
              sourceCode.Append(")");
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return Target;
          }
  
          Expression Target;
      }
  
      /// <summary>
      /// Class representing a set size expression.
      /// </summary>
      public class SetSize : Expression
      {
          public SetSize(Expression target)
          {
              Target = target;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new SetSize(Target.Copy(renameSuffix));
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("(");
              Target.Emit(sourceCode);
              sourceCode.Append(").Count");
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return Target;
          }
  
          Expression Target;
      }
  
      /// <summary>
      /// Class representing a set empty expression.
      /// </summary>
      public class SetEmpty: Expression
      {
          public SetEmpty(Expression target)
          {
              Target = target;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new SetEmpty(Target.Copy(renameSuffix));
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("((");
              Target.Emit(sourceCode);
              sourceCode.Append(").Count==0)");
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return Target;
          }
  
          Expression Target;
      }
  
      /// <summary>
      /// Class representing a set peek expression.
      /// </summary>
      public class SetPeek : Expression
      {
          public SetPeek(Expression target, Expression number)
          {
              Target = target;
              Number = number;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new SetPeek(Target.Copy(renameSuffix), Number.Copy(renameSuffix));
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("GRGEN_LIBGR.ContainerHelper.Peek(");
              Target.Emit(sourceCode);
              sourceCode.Append(",");
              Number.Emit(sourceCode);
              sourceCode.Append(")");
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return Target;
              yield return Number;
          }
  
          Expression Target;
          Expression Number;
      }
  
      /// <summary>
      /// Class representing a set as array expression.
      /// </summary>
      public class SetAsArray : Expression
      {
          public SetAsArray(Expression target)
          {
              Target = target;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new SetAsArray(Target.Copy(renameSuffix));
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("GRGEN_LIBGR.ContainerHelper.SetAsArray(");
              Target.Emit(sourceCode);
              sourceCode.Append(")");
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return Target;
          }
  
          Expression Target;
      }
  
      /// <summary>
      /// Class representing an array size expression.
      /// </summary>
      public class ArraySize : Expression
      {
          public ArraySize(Expression target)
          {
              Target = target;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new ArraySize(Target.Copy(renameSuffix));
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("(");
              Target.Emit(sourceCode);
              sourceCode.Append(").Count");
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return Target;
          }
  
          Expression Target;
      }
  
      /// <summary>
      /// Class representing an array empty expression.
      /// </summary>
      public class ArrayEmpty : Expression
      {
          public ArrayEmpty(Expression target)
          {
              Target = target;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new ArrayEmpty(Target.Copy(renameSuffix));
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              sourceCode.Append("((");
              Target.Emit(sourceCode);
              sourceCode.Append(").Count==0)");
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return Target;
          }
  
          Expression Target;
      }
  
      /// <summary>
      /// Class representing an array peek expression.
      /// </summary>
      public class ArrayPeek : Expression
      {
          public ArrayPeek(Expression target, Expression number)
          {
              Target = target;
              Number = number;
          }
  
          public ArrayPeek(Expression target)
          {
              Target = target;
          }
  
          public override Expression Copy(string renameSuffix)
          {
              return new ArrayPeek(Target.Copy(renameSuffix), Number!=null ? Number.Copy(renameSuffix) : null);
          }
  
          public override void Emit(SourceBuilder sourceCode)
          {
              Target.Emit(sourceCode);
              sourceCode.Append("[");
              if(Number != null)
                  Number.Emit(sourceCode);
              else
              {
                  sourceCode.Append("(");
                  Target.Emit(sourceCode);
                  sourceCode.Append(").Count-1");
              }
              sourceCode.Append("]");
          }
  
          public override IEnumerator<ExpressionOrYielding> GetEnumerator()
          {
              yield return Target;
  
gt:             if(Number!=null) yield return Number;