private TempComputeResult ComputeCustomConditionalLogic(Type type, string methodXName, string methodYName, object leftValue, object rightValue)
        {
            var methodX = DebugService.GetMethod(type, methodXName, BindingFlags.Public | BindingFlags.Static, methodInfo => CheckConditionalOperatorUnaryMethodParameters(type, methodInfo));

            if (methodX == null)
            {
                return(null);
            }
            var methodY = DebugService.GetMethod(type, methodYName, BindingFlags.Public | BindingFlags.Static, methodInfo => CheckConditionalOperatorBinaryMethodParameters(type, methodInfo));

            if (methodY == null)
            {
                return(null);
            }

            var condition = (bool)methodX.Invoke(null, new object[1] {
                leftValue
            });
            object obj = leftValue;

            if (!condition)
            {
                obj = methodY.Invoke(null, new object[2] {
                    leftValue, rightValue
                });
            }
            return(CreateComputeResult(obj, type));
        }
        public override TempComputeResult VisitBinaryExpression(BinaryExpressionSyntax node)
        {
            var left         = Visit(node.Left);
            var right        = Visit(node.Right);
            var operatorText = node.OperatorToken.Text;

            if (left.Type == null && right.Type == null)
            {
                if (operatorText == "==")
                {
                    return(CreateComputeResult(true, typeof(bool)));
                }
                else
                {
                    return(CreateComputeResult(null, null));
                }
            }

            var    leftType  = left.Type;
            var    rightType = right.Type;
            string methodName;

            if (dic_BinaryOperator_MethodName.TryGetValue(operatorText, out methodName))
            {
                var bindingFlags           = BindingFlags.Public | BindingFlags.Static;
                var overloadOperatorMethod = DebugService.GetMethod(leftType, methodName, bindingFlags, true, leftType, rightType);
                if (overloadOperatorMethod == null)
                {
                    overloadOperatorMethod = DebugService.GetMethod(rightType, methodName, bindingFlags, true, leftType, rightType);
                }
                if (overloadOperatorMethod != null) // 有运算符重载
                {
                    var result = overloadOperatorMethod.Invoke(null, new object[2] {
                        left.Value, right.Value
                    });
                    return(CreateComputeResult(result, overloadOperatorMethod.ReturnType));
                }
                else
                {
                    return(ComputeBinaryNative(leftType, rightType, left.Value, right.Value, operatorText, node));
                }
            }
            else
            {
                var result = ComputeCustomConditionalLogicOperator(leftType, rightType, left.Value, right.Value, operatorText); // 用户定义的条件逻辑运算符,规则为https://docs.microsoft.com/zh-cn/dotnet/csharp/language-reference/language-specification/expressions#conditional-logical-operators
                if (result != null)
                {
                    return(result);
                }
                return(ComputeBinaryNative(leftType, rightType, left.Value, right.Value, operatorText, node));
                //throw new NotSupportedException("Unknown Binary Operator:" + operatorText);
            }
        }
        public override TempComputeResult VisitConditionalExpression(ConditionalExpressionSyntax node)
        {
            var tuple = GetOrCreateVariableReference(node, "");

            tuple.Top.Type = VariableTypes.Value;

            bool conditionValue;
            var  conditionResult = Visit(node.Condition);

            if (conditionResult.Value is bool)
            {
                conditionValue = (bool)conditionResult.Value;
            }
            else
            {
                // true运算符重载
                var overloadTrueMethod = DebugService.GetMethod(conditionResult.Type, "op_True", BindingFlags.Public | BindingFlags.Static, methodInfo => CheckConditionalOperatorUnaryMethodParameters(conditionResult.Type, methodInfo));
                if (overloadTrueMethod != null)
                {
                    conditionValue = (bool)overloadTrueMethod.Invoke(null, new object[1] {
                        conditionResult.Value
                    });
                }
                else
                {
                    throw new InvalidOperationException(string.Format("\"{0}\" is not conditional expression", node.Condition.ToString()));
                }
            }

            TempComputeResult result;

            if (conditionValue)
            {
                result = Visit(node.WhenTrue);
            }
            else
            {
                result = Visit(node.WhenFalse);
            }

            tuple.Top.Value     = result.Value;
            tuple.Top.ValueType = result.Type;

            return(ResolveVariable(tuple.Bottom));
        }
        public TempComputeResult VisitUnaryExpression(ExpressionSyntax operand, string operatorText, bool isPrefix, string nodeText)
        {
            var operandResult = Visit(operand);

            if (operandResult.Type == null)
            {
                return(CreateComputeResult(null, null));
            }

            string methodName;

            if (dic_UnaryOperator_MethodName.TryGetValue(operatorText, out methodName))
            {
                var bindingFlags           = BindingFlags.Public | BindingFlags.Static;
                var overloadOperatorMethod = DebugService.GetMethod(operandResult.Type, methodName, bindingFlags, true, operandResult.Type);
                if (overloadOperatorMethod != null) // 有运算符重载
                {
                    var result = overloadOperatorMethod.Invoke(null, new object[1] {
                        operandResult.Value
                    });
                    return(CreateComputeResult(result, overloadOperatorMethod.ReturnType));
                }
            }

            try
            {
                var expressionText = isPrefix ? "{0}x" : "x{0}";
                var func           = new DynamicExpresso.Interpreter().Parse(string.Format(expressionText, operatorText), new DynamicExpresso.Parameter("x", operandResult.Type.UnWrapper()));
                var result         = func.Invoke(operandResult.Value);
                return(CreateComputeResult(result, result == null ? null : result.GetType()));
            }
            catch
            {
                throw new Exception(string.Format("Fail to calculate '{0}'", nodeText));
            }
        }