code: private ExpressionAndSubstitution convertIntoExpressionAndSubstitution(ImmutableExpression expression,
                                                                             ImmutableSet<Variable> leftVariables,
                                                                             ImmutableSet<Variable> rightVariables) {
  
          ImmutableSet<Variable> rightSpecificVariables = rightVariables.stream()
                  .filter(v -> !leftVariables.contains(v))
                  .collect(ImmutableCollectors.toSet());
  
  
          ImmutableSet<ImmutableExpression> expressions = expression.flattenAND();
          ImmutableSet<ImmutableExpression> downSubstitutionExpressions = expressions.stream()
                  .filter(e -> e.getFunctionSymbol().equals(EQ))
                  .filter(e -> {
                      ImmutableList<? extends ImmutableTerm> arguments = e.getTerms();
                      return arguments.stream().allMatch(t -> t instanceof NonFunctionalTerm)
                              && arguments.stream().anyMatch(rightVariables::contains);
                  })
                  .collect(ImmutableCollectors.toSet());
  
          ImmutableSubstitution<NonFunctionalTerm> downSubstitution =
                  substitutionFactory.getSubstitution(
                          downSubstitutionExpressions.stream()
                              .map(ImmutableFunctionalTerm::getTerms)
                              .map(args -> (args.get(0) instanceof Variable) ? args : args.reverse())
                              // Rename right-specific variables if possible
                              .map(args -> ((args.get(0) instanceof Variable) && rightSpecificVariables.contains(args.get(1)))
                                      ? args.reverse() : args)
                              .collect(ImmutableCollectors.toMap(
                                      args -> (Variable) args.get(0),
                                      args -> (NonFunctionalTerm) args.get(1))));
  
          Optional<ImmutableExpression> newExpression = getImmutabilityTools().foldBooleanExpressions(
                  expressions.stream()
                          .filter(e -> (!downSubstitutionExpressions.contains(e))
                                  || e.getTerms().stream().anyMatch(rightSpecificVariables::contains)))
                  .map(downSubstitution::applyToBooleanExpression);
  
          return new ExpressionAndSubstitution(newExpression, downSubstitution);
      }
docs: TODO: explain