private ProgramState HandleReferenceEqualsCall(InvocationExpressionSyntax invocation, ProgramState programState)
        {
            SymbolicValue arg1;
            SymbolicValue arg2;

            var newProgramState = programState
                                  .PopValue(out arg1)
                                  .PopValue(out arg2)
                                  .PopValue();

            var refEquals = new ReferenceEqualsSymbolicValue(arg1, arg2);

            newProgramState = newProgramState.PushValue(refEquals);
            return(SetConstraintOnReferenceEquals(refEquals, invocation, arg1, arg2, newProgramState));
        }
        private ProgramState SetConstraintOnReferenceEquals(ReferenceEqualsSymbolicValue refEquals, InvocationExpressionSyntax invocation,
                                                            SymbolicValue arg1, SymbolicValue arg2, ProgramState programState)
        {
            if (AreBothArgumentsNull(arg1, arg2, programState))
            {
                return(refEquals.SetConstraint(BoolConstraint.True, programState));
            }

            if (IsAnyArgumentNonNullValueType(invocation, arg1, arg2, programState) ||
                ArgumentsHaveDifferentNullability(arg1, arg2, programState))
            {
                return(refEquals.SetConstraint(BoolConstraint.False, programState));
            }

            if (arg1 == arg2)
            {
                return(refEquals.SetConstraint(BoolConstraint.True, programState));
            }

            return(programState);
        }
        private ProgramState HandleReferenceEqualsCall(InvocationExpressionSyntax invocation, ProgramState programState)
        {
            SymbolicValue arg1;
            SymbolicValue arg2;

            var newProgramState = programState
                .PopValue(out arg1)
                .PopValue(out arg2)
                .PopValue();

            var refEquals = new ReferenceEqualsSymbolicValue(arg1, arg2);
            newProgramState = newProgramState.PushValue(refEquals);
            return SetConstraintOnReferenceEquals(refEquals, invocation, arg1, arg2, newProgramState);
        }
        private ProgramState SetConstraintOnReferenceEquals(ReferenceEqualsSymbolicValue refEquals, InvocationExpressionSyntax invocation,
            SymbolicValue arg1, SymbolicValue arg2, ProgramState programState)
        {
            if (AreBothArgumentsNull(arg1, arg2, programState))
            {
                return refEquals.SetConstraint(BoolConstraint.True, programState);
            }

            if (IsAnyArgumentNonNullValueType(invocation, arg1, arg2, programState) ||
                ArgumentsHaveDifferentNullability(arg1, arg2, programState))
            {
                return refEquals.SetConstraint(BoolConstraint.False, programState);
            }

            if (arg1 == arg2)
            {
                return refEquals.SetConstraint(BoolConstraint.True, programState);
            }

            return programState;
        }