title: Refactoring advice for parser and calculator for logical expressions
body: <p>I have a code for parser and calculator of logical expressions. And I don't quite like how it looks.</p>
  <p>For the background.</p>
  <p>It supports following operations for operands</p>
  <p>bool: <strong>OR, And , Not</strong></p>
  <p>int: <strong>More than, less than</strong></p>
  <p>both bool and int: <strong>Equals</strong></p>
  <p>I've created general interface <code>IElement</code> for describing any element of expression. There are also other interfaces:</p>
  <ol>
  <li><code>IBinary : IOperation</code></li>
  <li><code>IValue : IElement</code></li>
  <li><code>IOperation : IElement</code></li>
  <li><code>IVariable&lt;T&gt; : IElement, IValue </code></li>
  <li><code>IBinaryOperation&lt;T&gt; : IOperation, IBinary</code></li>
  <li><code>IUnaryOperation : IOperation</code></li>
  </ol>
  <p>And those interfaces interfaces has following classes as implementations</p>
  <ol>
  <li><code>Variable&lt;T&gt; : IVariable&lt;T&gt;</code></li>
  <li><code>Not : IUnaryOperation</code></li>
  <li><code>And : IBinaryOperation&lt;bool&gt;</code></li>
  <li><code>Or : IBinaryOperation&lt;bool&gt;</code></li>
  <li><code>LessThen : IBinaryOperation&lt;int&gt;</code></li>
  <li><code>GreaterThen : IBinaryOperation&lt;int&gt;</code></li>
  <li><code>Eq : IBinaryOperation&lt;int&gt;, IBinaryOperation&lt;bool&gt;</code></li>
  </ol>
  <p>Units of the expression is represented as <code>List&lt;Element&gt;</code> in postfix notation .
  Here's my <code>Compute</code> method and couple methods used inside of it. I have a problem with both of inner methods.</p>
  
  <pre class="lang-c prettyprint-override"><code>public static bool Compute(List&lt;IElement&gt; element)
              {
                  Stack&lt;IElement&gt; stack = new Stack&lt;IElement&gt;();
                  foreach (IElement elem in element)
                  {
                      IElement tmp = elem;
                      switch (elem)
                      {
                          case IValue val:
                              {
                                  stack.Push(val);
                                  break;
                              }
                          case IBinary val:
                              {
                                  HandleBinary(val, ref stack);
                                  break;
                              }
                          case IUnaryOperation val:
                              {
                                  HandleUnary(val, ref stack);
                                  break;
                              }
                      }
                  }
                  return ((IVariable&lt;bool&gt;)stack.Pop()).getValue();
              }
  </code></pre>
  <pre class="lang-c prettyprint-override"><code>    private static void HandleBinary(IElement elem, ref Stack&lt;IElement&gt; stack)
                  {
      
                      switch (elem)
                      {
                          case And and:
                              {
                                  Tuple&lt;IVariable&lt;bool&gt;, IVariable&lt;bool&gt;&gt; operands = GetBoolOperands(ref stack);
                                  stack.Push(and.Execute(operands.Item2, operands.Item1));
                                  break;
                              }
                          case Or or:
                              {
                                  Tuple&lt;IVariable&lt;bool&gt;, IVariable&lt;bool&gt;&gt; operands = GetBoolOperands(ref stack);
                                  stack.Push(or.Execute(operands.Item2, operands.Item1));
                                  break;
                              }
                          case Eq eq:
                              {
                                  Type t = stack.Peek().GetType().GetGenericArguments()[0];
                                  switch (Type.GetTypeCode(t))
                                  {
                                      case TypeCode.Int32:
                                          {
                                              Tuple&lt;IVariable&lt;int&gt;, IVariable&lt;int&gt;&gt; operands = GetIntOperands(ref stack);
                                              stack.Push(eq.Execute(operands.Item2, operands.Item1));
                                              break;
                                          }
                                      case TypeCode.Boolean:
                                          {
                                              Tuple&lt;IVariable&lt;bool&gt;, IVariable&lt;bool&gt;&gt; operands = GetBoolOperands(ref stack);
                                              stack.Push(eq.Execute(operands.Item2, operands.Item1));
                                              break;
                                          }
                                  }
                                  break;
                              }
                          case GreaterThan gt:
                              {
                                  Tuple&lt;IVariable&lt;int&gt;, IVariable&lt;int&gt;&gt; operands = GetIntOperands(ref stack);
                                  stack.Push(gt.Execute(operands.Item2, operands.Item1));
                                  break;
                              }
                          case LowerThan lt:
                              {
                                  Tuple&lt;IVariable&lt;int&gt;, IVariable&lt;int&gt;&gt; operands = GetIntOperands(ref stack);
                                  stack.Push(lt.Execute(operands.Item2, operands.Item1));
                                  break;
                              }
                      }
                  }
  </code></pre>
  <pre class="lang-c prettyprint-override"><code>             private static Tuple&lt;IVariable&lt;int&gt;, IVariable&lt;int&gt;&gt; GetIntOperands(ref Stack&lt;IElement&gt; stack)
              {
                  return new Tuple&lt;IVariable&lt;int&gt;, IVariable&lt;int&gt;&gt;(
                      (IVariable&lt;int&gt;)stack.Pop(),
                      (IVariable&lt;int&gt;)stack.Pop());
  
              }
              private static Tuple&lt;IVariable&lt;bool&gt;, IVariable&lt;bool&gt;&gt; GetBoolOperands(ref Stack&lt;IElement&gt; stack)
              {
                  return new Tuple&lt;IVariable&lt;bool&gt;, IVariable&lt;bool&gt;&gt;(
                      (IVariable&lt;bool&gt;)stack.Pop(),
                      (IVariable&lt;bool&gt;)stack.Pop());
  
              }
  </code></pre>
  <p>As you can see this code has a lot of pattern matching and type casting, thit is expensive and that amount of casts worries.</p>
  <p>I feel like my attempt to utilize polymorphism is failed and whole preparation with those interfaces and implementations is wasted.</p>
  <p>I've tried to refactor this code but always ran into the problem of high amount of type casting and pattern matching.</p>
  <p>Can someone suggest another approach or point out an obvious but missed error.</p>