@Override
  public ITree filterProduction(ITree tree, Object environment) {
    String cons = TreeAdapter.getConstructorName(tree);

    if (cons != null) {
      Environment env = (Environment) environment;
      Result<IValue> var = env.getFrameVariable(cons);

      if (var != null && var instanceof ICallableValue) {
        ICallableValue function = (ICallableValue) var;

        try {
          Result<IValue> result = null;
          if (TreeAdapter.isContextFree(tree)) {
            // For context free trees, try it without layout and literal arguments first.
            result = call(function, TreeAdapter.getASTArgs(tree));
          }

          if (result == null) {
            result = call(function, TreeAdapter.getArgs(tree));
          }

          if (result == null) {
            return tree;
          }

          if (result.getType().isBottom()) {
            return tree;
          }

          if (!(result.getType() instanceof NonTerminalType
              && SymbolAdapter.isEqual(
                  ((NonTerminalType) result.getType()).getSymbol(), TreeAdapter.getType(tree)))) {
            // do not call the function if it does not return the right type
            return tree;
          }

          return (ITree) result.getValue();
        } catch (Filtered f) {
          return null;
        }
      }
    }

    return tree;
  }
  @Override
  protected Result<IBool> equalToConcreteSyntax(ConcreteSyntaxResult that) {
    IConstructor left = this.getValue();
    IConstructor right = that.getValue();

    if (TreeAdapter.isLayout(left) && TreeAdapter.isLayout(right)) {
      return bool(true, ctx);
    }

    if (TreeAdapter.isAppl(left) && TreeAdapter.isAppl(right)) {
      IConstructor p1 = TreeAdapter.getProduction(left);
      IConstructor p2 = TreeAdapter.getProduction(right);

      if (!p1.isEqual(p2)) {
        return bool(false, ctx);
      }

      IList l1 = TreeAdapter.getArgs(left);
      IList l2 = TreeAdapter.getArgs(right);

      if (l1.length() != l2.length()) {
        return bool(false, ctx);
      }
      for (int i = 0; i < l1.length(); i++) {
        IValue kid1 = l1.get(i);
        IValue kid2 = l2.get(i);
        // Recurse here on kids to reuse layout handling etc.
        Result<IBool> result =
            makeResult(kid1.getType(), kid1, ctx).equals(makeResult(kid2.getType(), kid2, ctx));
        if (!result.getValue().getValue()) {
          return bool(false, ctx);
        }
        if (TreeAdapter.isContextFree(left)) {
          i++; // skip layout
        }
      }
      return bool(true, ctx);
    }

    if (TreeAdapter.isChar(left) && TreeAdapter.isChar(right)) {
      return bool((TreeAdapter.getCharacter(left) == TreeAdapter.getCharacter(right)), ctx);
    }

    if (TreeAdapter.isAmb(left) && TreeAdapter.isAmb(right)) {
      ISet alts1 = TreeAdapter.getAlternatives(left);
      ISet alts2 = TreeAdapter.getAlternatives(right);

      if (alts1.size() != alts2.size()) {
        return bool(false, ctx);
      }

      // TODO: this is very inefficient
      again:
      for (IValue alt1 : alts1) {
        for (IValue alt2 : alts2) {
          Result<IBool> result =
              makeResult(alt1.getType(), alt1, ctx).equals(makeResult(alt2.getType(), alt2, ctx));
          if (result.getValue().getValue()) {
            // As soon an alt1 is equal to an alt2
            // continue the outer loop.
            continue again;
          }
        }
        // If an alt1 is not equal to any of the the alt2's return false;
        return bool(false, ctx);
      }
      return bool(true, ctx);
    }

    return bool(false, ctx);
  }