Specifies the type of a lexical token.
示例#1
0
        /// <summary>
        /// Evalaute this node and return result.
        /// </summary>
        /// <param name="thisObject">Reference to object that is exposed as 'this'.</param>
        /// <returns>Result value and type of that result.</returns>
        public override EvalResult Evaluate(object thisObject)
        {
            EvalResult      target = this[0].Evaluate(thisObject);
            EvalNodeArgList args   = (EvalNodeArgList)this[1];

            if (target.Value == null)
            {
                throw new ApplicationException("Cannot access '" + Identifier + "' on a value of 'null'.");
            }

            // Evalute all the arguments
            EvalResult[] results = new EvalResult[args.Count];
            for (int i = 0; i < results.Length; i++)
            {
                results[i] = args[i].Evaluate(thisObject);
            }

            if (target.Value is Type)
            {
                return(EvaluateTypeMethod(target, results));
            }
            else
            {
                return(EvaluateObjectMethod(target, results));
            }
        }
示例#2
0
        private EvalResult EvaluateTypeMember(EvalResult target)
        {
            // Extract the type we are working against
            Type t = target.Value as Type;

            // Try and find the static field for our identifier
            FieldInfo fi = t.GetField(Identifier, BindingFlags.Static | BindingFlags.Public | BindingFlags.GetField);

            if (fi != null)
            {
                // Grab the value of the static field
                EvalResult ret = new EvalResult();
                ret.Value = fi.GetValue(null);
                return(DiscoverTypeCode(ret));
            }
            else
            {
                // Try and find the static property for our identifier
                PropertyInfo pi = t.GetProperty(Identifier, BindingFlags.Static | BindingFlags.Public | BindingFlags.GetProperty);

                if (pi == null)
                {
                    throw new ApplicationException("Cannot find static public field/property called '" + Identifier + "' for type '" + t.ToString() + "'.");
                }
                else
                {
                    // Grab the value of the static property
                    EvalResult ret = new EvalResult();
                    ret.Value = pi.GetValue(null, null);
                    return(DiscoverTypeCode(ret));
                }
            }
        }
示例#3
0
        private EvalResult EvaluatePlus(EvalResult ret)
        {
            // Unary plus means we do nothing as long as the type is valid
            switch (ret.Type)
            {
            case TypeCode.Char:
                if (_language == Language.VBNet)
                {
                    throw new ApplicationException("Operation '+' cannot be applied to operand of type '" + ret.Type.ToString() + "'.");
                }
                else
                {
                    break;
                }

            case TypeCode.Byte:
            case TypeCode.SByte:
            case TypeCode.Int16:
            case TypeCode.Int32:
            case TypeCode.Int64:
            case TypeCode.UInt16:
            case TypeCode.UInt32:
            case TypeCode.UInt64:
            case TypeCode.Single:
            case TypeCode.Double:
            case TypeCode.Decimal:
                break;

            default:
                throw new ApplicationException("Operation '+' cannot be applied to operand of type '" + ret.Type.ToString() + "'.");
            }

            return(ret);
        }
        private EvalResult EvaluateObjectArray(EvalResult target,
                                               EvalResult[] args,
                                               object thisObject)
        {
            // We know the value is an actual array instance
            Array array = (Array)target.Value;

            // Must have same number of arguments as the array rank
            if (array.Rank != args.Length)
            {
                throw new ApplicationException("Array expects '" + array.Rank.ToString() + "' indices but '" + args.Length.ToString() + "' have been specified.");
            }

            // Construct the set of indices for accessing array
            long[] indices = new long[args.Length];
            for (int i = 0; i < args.Length; i++)
            {
                indices[i] = ImplicitConverter.ConvertToInt64(args[i].Value, _language);
            }

            EvalResult ret = new EvalResult();

            ret.Value = array.GetValue(indices);
            return(DiscoverTypeCode(ret));
        }
        /// <summary>
        /// Evalaute this node and return result.
        /// </summary>
        /// <param name="thisObject">Reference to object that is exposed as 'this'.</param>
        /// <returns>Result value and type of that result.</returns>
        public override EvalResult Evaluate(object thisObject)
        {
            // Get the result from evaluating the left side of operand
            EvalResult left = this[0].Evaluate(thisObject);

            // We can only handle an object result
            if (left.Type != TypeCode.Object)
            {
                throw new ApplicationException("Null coalescing '??' requires a 'object' type for left operand.");
            }

            // If conditional is not null then return it
            if (left.Value != null)
            {
                return(left);
            }
            else
            {
                // Get the result from evaluating the right side operand
                EvalResult right = this[1].Evaluate(thisObject);

                // We can only handle an object result
                if (right.Type != TypeCode.Object)
                {
                    throw new ApplicationException("Null coalescing '??' requires a 'object' type for right operand.");
                }

                return(right);
            }
        }
        /// <summary>
        /// Converts source values to a value for the binding target.
        /// </summary>
        /// <param name="values">The array of values that the source bindings produces.</param>
        /// <param name="targetType">The type of the binding target property.</param>
        /// <param name="parameter">The converter parameter to use.</param>
        /// <param name="culture">The culture to use in the converter.</param>
        /// <returns>A converted value.</returns>
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            try
            {
                // First time around we parse the evaluation input
                if (_eval == null)
                {
                    _eval = new Eval(_language);
                    _eval.ResolveIdentifier += new EventHandler <ResolveIdentifierEventArgs>(OnResolveIdentifier);
                    _eval.Parse(_expression);
                }

                // Every time we evaluate we could throw an exception. This is because each time around the
                // bindings can provide values of different types. So first time round the binding has an
                // integer and so works correctly but next time it could provide a string and cause a type
                // error in the evaluation.
                EvalResult ret = _eval.Evaluate(values);

                // Null means we have no result to provide
                if (ret == null)
                {
                    return(DependencyProperty.UnsetValue);
                }
                else
                {
                    // If the return type is different to the target type
                    if (ret.Value.GetType() != targetType)
                    {
                        // If possible we perform an implicit conversion to the target
                        TypeCode targetTypeCode = Type.GetTypeCode(targetType);
                        if (ImplicitConverter.CanConvertTo(targetTypeCode, ret.Value, _language))
                        {
                            ret.Value = ImplicitConverter.ConvertTo(targetTypeCode, ret.Value, _language);
                        }
                        else
                        {
                            // Use type converters to attempt an explicit conversion
                            ret.Value = ConvertUsingConverter(ret, targetType);
                        }
                    }

                    return(ret.Value);
                }
            }
            catch (ParseException pe)
            {
                Console.WriteLine("EvalBinding Parsing Exception : {0} : Index '{1}'", pe.Message, pe.Index);
                return(DependencyProperty.UnsetValue);
            }
            catch (Exception e)
            {
                Console.WriteLine("EvalBinding Evaluation Exception : {0} : Eval '{1}'", e.Message, _eval.ToString());
                return(DependencyProperty.UnsetValue);
            }
        }
示例#7
0
        private EvalResult EvaluateComplement(EvalResult ret)
        {
            // Unary plus means we do nothing as long as the type is valid
            switch (ret.Type)
            {
            case TypeCode.Byte:
                ret.Value = ~(Byte)ret.Value;
                break;

            case TypeCode.SByte:
                ret.Value = ~(SByte)ret.Value;
                break;

            case TypeCode.Char:
                if (_language != Language.VBNet)
                {
                    ret.Value = ~(Char)ret.Value;
                }
                else
                {
                    throw new ApplicationException("Operation '~' cannot be applied to operand of type '" + ret.Type.ToString() + "'.");
                }
                break;

            case TypeCode.Int16:
                ret.Value = ~(Int16)ret.Value;
                break;

            case TypeCode.Int32:
                ret.Value = ~(Int32)ret.Value;
                break;

            case TypeCode.Int64:
                ret.Value = ~(Int64)ret.Value;
                break;

            case TypeCode.UInt16:
                ret.Value = ~(UInt16)ret.Value;
                break;

            case TypeCode.UInt32:
                ret.Value = ~(UInt32)ret.Value;
                break;

            case TypeCode.UInt64:
                ret.Value = ~(UInt64)ret.Value;
                break;

            default:
                throw new ApplicationException("Operation '~' cannot be applied to operand of type '" + ret.Type.ToString() + "'.");
            }

            return(ret);
        }
示例#8
0
        /// <summary>
        /// Evalaute this node and return result.
        /// </summary>
        /// <param name="thisObject">Reference to object that is exposed as 'this'.</param>
        /// <returns>Result value and type of that result.</returns>
        public override EvalResult Evaluate(object thisObject)
        {
            // Get the result from evaluating both children
            EvalResult left  = this[0].Evaluate(thisObject);
            EvalResult right = this[1].Evaluate(thisObject);

            // Convert both sides to a string if possible
            string leftString  = (left.Value != null ? left.Value.ToString() : string.Empty);
            string rightString = (right.Value != null ? right.Value.ToString() : string.Empty);

            return(new EvalResult(TypeCode.String, leftString + rightString));
        }
示例#9
0
        /// <summary>
        /// Update the TypeCode to reflect the contents of the Value fields.
        /// </summary>
        /// <param name="ret">Instance to update.</param>
        /// <returns>Instance that has been updated.</returns>
        protected EvalResult DiscoverTypeCode(EvalResult ret)
        {
            // Fill in the correct type code for the value
            if (ret.Value == null)
            {
                ret.Type = TypeCode.Object;
            }
            else
            {
                ret.Type = Type.GetTypeCode(ret.Value.GetType());
            }

            return(ret);
        }
示例#10
0
        private EvalResult EvaluateNot(EvalResult ret)
        {
            // Unary plus means we do nothing as long as the type is valid
            switch (ret.Type)
            {
            case TypeCode.Boolean:
                ret.Value = !(bool)ret.Value;
                break;

            default:
                throw new ApplicationException("Logical invert cannot be applied to operand of type '" + ret.Type.ToString() + "'.");
            }

            return(ret);
        }
示例#11
0
        /// <summary>
        /// Evalaute this node and return result.
        /// </summary>
        /// <param name="thisObject">Reference to object that is exposed as 'this'.</param>
        /// <returns>Result value and type of that result.</returns>
        public override EvalResult Evaluate(object thisObject)
        {
            EvalResult target = this[0].Evaluate(thisObject);

            if (target.Value == null)
            {
                throw new ApplicationException("Cannot access '" + Identifier + "' on a value of 'null'.");
            }
            else if (target.Value is Type)
            {
                return(EvaluateTypeMember(target));
            }
            else
            {
                return(EvaluateObjectMember(target));
            }
        }
        /// <summary>
        /// Evalaute this node and return result.
        /// </summary>
        /// <param name="thisObject">Reference to object that is exposed as 'this'.</param>
        /// <returns>Result value and type of that result.</returns>
        public override EvalResult Evaluate(object thisObject)
        {
            EvalResult target = this[0].Evaluate(thisObject);
            EvalNodeArgList args = (EvalNodeArgList)this[1];

            if (target.Value == null)
                throw new ApplicationException("Cannot access '" + Identifier + "' on a value of 'null'.");

            // Evalute all the arguments
            EvalResult[] results = new EvalResult[args.Count];
            for (int i = 0; i < results.Length; i++)
                results[i] = args[i].Evaluate(thisObject);

            if (target.Value is Type)
                return EvaluateTypeMethod(target, results);
            else
                return EvaluateObjectMethod(target, results);
        }
示例#13
0
        private EvalResult EvalShiftOp(UInt64 x, int count)
        {
            EvalResult ret = new EvalResult(TypeCode.UInt64, null);

            switch (Operation)
            {
            case ShiftOp.Left:
                ret.Value = x << count;
                break;

            case ShiftOp.Right:
                ret.Value = x >> count;
                break;

            default:
                throw new ApplicationException("Unrecognized 'UInt64' type shift operation '" + OperationString);
            }

            return(ret);
        }
示例#14
0
        /// <summary>
        /// Evalaute this node and return result.
        /// </summary>
        /// <param name="thisObject">Reference to object that is exposed as 'this'.</param>
        /// <returns>Result value and type of that result.</returns>
        public override EvalResult Evaluate(object thisObject)
        {
            // Get the result from evaluating the condition
            EvalResult cond = this[0].Evaluate(thisObject);

            // We can only handle a boolean result
            if (cond.Type != TypeCode.Boolean)
            {
                throw new ApplicationException("Conditional '?:' requires a 'bool' type for evaluating.");
            }

            // Decide which value to return based on boolean result
            if ((bool)cond.Value)
            {
                return(this[1].Evaluate(thisObject));
            }
            else
            {
                return(this[2].Evaluate(thisObject));
            }
        }
示例#15
0
        /// <summary>
        /// Evalaute this node and return result.
        /// </summary>
        /// <param name="thisObject">Reference to object that is exposed as 'this'.</param>
        /// <returns>Result value and type of that result.</returns>
        public override EvalResult Evaluate(object thisObject)
        {
            // Get the result from evaluating the single child
            EvalResult ret = this[0].Evaluate(thisObject);

            switch (Operation)
            {
            case UnaryOp.Plus:
                return(EvaluatePlus(ret));

            case UnaryOp.Minus:
                return(EvaluateMinus(ret));

            case UnaryOp.Not:
                return(EvaluateNot(ret));

            case UnaryOp.Complement:
                return(EvaluateComplement(ret));
            }

            return(ret);
        }
示例#16
0
        /// <summary>
        /// Evalaute this node and return result.
        /// </summary>
        /// <param name="thisObject">Reference to object that is exposed as 'this'.</param>
        /// <returns>Result value and type of that result.</returns>
        public override EvalResult Evaluate(object thisObject)
        {
            // Get the result from evaluating both children
            EvalResult left  = this[0].Evaluate(thisObject);
            EvalResult right = this[1].Evaluate(thisObject);

            // Both sides must be converted to doubles
            if (!ImplicitConverter.CanConvertToDouble(left.Value, _language))
            {
                throw new ApplicationException("Cannot convert '" + left.Type.ToString() + "' type to 'Double' for left side of exponent '^' operation.");
            }

            if (!ImplicitConverter.CanConvertToDouble(right.Value, _language))
            {
                throw new ApplicationException("Cannot convert '" + left.Type.ToString() + "' type to 'Double' for right side of exponent '^' operation.");
            }

            double leftDouble  = ImplicitConverter.ConvertToDouble(left.Value, _language);
            double rightDouble = ImplicitConverter.ConvertToDouble(right.Value, _language);

            return(new EvalResult(TypeCode.Double, Math.Pow(leftDouble, rightDouble)));
        }
        /// <summary>
        /// Evalaute this node and return result.
        /// </summary>
        /// <param name="thisObject">Reference to object that is exposed as 'this'.</param>
        /// <returns>Result value and type of that result.</returns>
        public override EvalResult Evaluate(object thisObject)
        {
            EvalResult target = this[0].Evaluate(thisObject);
            EvalNodeArgList args = (EvalNodeArgList)this[1];

            // We can only handle a target that is an object
            if (target.Type != TypeCode.Object)
                throw new ApplicationException("Array index cannot index a value of type '" + target.Type.ToString() + "'.");
            else if (target.Value == null)
                throw new ApplicationException("Array index cannot index a value of 'null'.");
            else if (target.Value is Type)
                throw new ApplicationException("Array index cannot index a 'type' object.");

            // Evalute all the arguments
            EvalResult[] results = new EvalResult[args.Count];
            for (int i = 0; i < results.Length; i++)
                results[i] = args[i].Evaluate(thisObject);

            // Is this an actual array of a type?
            if (target.Value.GetType().IsArray)
                return EvaluateObjectArray(target, results, thisObject);
            else
                return EvaluateObjectInstance(target, results, thisObject);
        }
示例#18
0
        /// <summary>
        /// Evalaute this node and return result.
        /// </summary>
        /// <param name="thisObject">Reference to object that is exposed as 'this'.</param>
        /// <returns>Result value and type of that result.</returns>
        public override EvalResult Evaluate(object thisObject)
        {
            EvalResult      target = this[0].Evaluate(thisObject);
            EvalNodeArgList args   = (EvalNodeArgList)this[1];

            // We can only handle a target that is an object
            if (target.Type != TypeCode.Object)
            {
                throw new ApplicationException("Array index cannot index a value of type '" + target.Type.ToString() + "'.");
            }
            else if (target.Value == null)
            {
                throw new ApplicationException("Array index cannot index a value of 'null'.");
            }
            else if (target.Value is Type)
            {
                throw new ApplicationException("Array index cannot index a 'type' object.");
            }

            // Evalute all the arguments
            EvalResult[] results = new EvalResult[args.Count];
            for (int i = 0; i < results.Length; i++)
            {
                results[i] = args[i].Evaluate(thisObject);
            }

            // Is this an actual array of a type?
            if (target.Value.GetType().IsArray)
            {
                return(EvaluateObjectArray(target, results, thisObject));
            }
            else
            {
                return(EvaluateObjectInstance(target, results, thisObject));
            }
        }
示例#19
0
 private EvalResult EvaluateTypeMethod(EvalResult target, EvalResult[] args)
 {
     // Get all the static methods that might of interest to us
     MethodInfo[] mis = ((Type)target.Value).GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod);
     return(EvaluateMethod(mis, null, args));
 }
示例#20
0
        private EvalResult EvaluateMinus(EvalResult ret)
        {
            // Processing depends on the type we are provided with
            switch (ret.Type)
            {
            case TypeCode.Byte:
                ret.Value = 0 - ((Byte)ret.Value);
                break;

            case TypeCode.SByte:
                ret.Value = 0 - ((SByte)ret.Value);
                break;

            case TypeCode.Char:
                if (_language != Language.VBNet)
                {
                    ret.Value = 0 - ((Char)ret.Value);
                    break;
                }
                else
                {
                    throw new ApplicationException("Operation '-' cannot be applied to operand of type '" + ret.Type.ToString() + "'.");
                }

            case TypeCode.Int16:
                ret.Value = 0 - ((Int16)ret.Value);
                break;

            case TypeCode.Int32:
                ret.Value = 0 - ((Int32)ret.Value);
                break;

            case TypeCode.Int64:
                ret.Value = 0 - ((Int64)ret.Value);
                break;

            case TypeCode.UInt16:
                // Convert to long and subtract from zero
                ret.Value = 0 - (Int64)((UInt16)ret.Value);
                ret.Type  = TypeCode.Int64;
                break;

            case TypeCode.UInt32:
                // Convert to long and subtract from zero
                ret.Value = 0 - (Int64)((UInt32)ret.Value);
                ret.Type  = TypeCode.Int64;
                break;

            case TypeCode.Single:
                ret.Value = 0 - ((Single)ret.Value);
                break;

            case TypeCode.Double:
                ret.Value = 0 - ((Double)ret.Value);
                break;

            case TypeCode.Decimal:
                ret.Value = 0 - ((Decimal)ret.Value);
                break;

            default:
                throw new ApplicationException("Operation '-' cannot be applied to operand of type '" + ret.Type.ToString() + "'.");
            }

            return(ret);
        }
示例#21
0
        private EvalResult EvaluateMethod(MethodInfo[] mis, object target, EvalResult[] args)
        {
            if (mis == null)
            {
                if (target == null)
                {
                    throw new ApplicationException("Cannot find static public method called '" + Identifier + "'.");
                }
                else
                {
                    throw new ApplicationException("Cannot find instance public method called '" + Identifier + "'.");
                }
            }

            MethodInfo callMi = null;

            object[] callParams = null;

            // Find methods that we could call
            foreach (MethodInfo mi in mis)
            {
                // Matching name?
                if (mi.Name == Identifier)
                {
                    ParameterInfo[] pis = mi.GetParameters();

                    // Is the last parameter an array of params?
                    bool paramArray = (pis.Length > 0 ? pis[pis.Length - 1].IsDefined(typeof(ParamArrayAttribute), false) : false);

                    // It must have the same number of parameters as we have arguments
                    if (!paramArray && (pis.Length == args.Length))
                    {
                        // Match parameter types?
                        int      i         = 0;
                        int      exact     = 0;
                        object[] pisParams = new object[args.Length];
                        for (i = 0; i < pis.Length; i++)
                        {
                            TypeCode methodTc = Type.GetTypeCode(pis[i].ParameterType);

                            // Note how many parameters are an exact match
                            if (methodTc == args[i].Type)
                            {
                                pisParams[i] = args[i].Value;
                                exact++;
                            }
                            else
                            {
                                // If cannot be implicitly converted, then fail to match at all
                                if (ImplicitConverter.CanConvertTo(methodTc, args[i].Value, _language))
                                {
                                    pisParams[i] = ImplicitConverter.ConvertTo(methodTc, args[i].Value, _language);
                                }
                                else
                                {
                                    break;
                                }
                            }
                        }

                        // If all parameters exactly match
                        if (exact == pis.Length)
                        {
                            // Use this method
                            callMi     = mi;
                            callParams = pisParams;
                            break;
                        }

                        // Remember the first compatible match we find
                        if ((i == pis.Length) && (callMi == null))
                        {
                            callMi     = mi;
                            callParams = pisParams;
                        }
                    }
                    else if (paramArray)
                    {
                        // We can only handle packaging up a param array as an object array
                        int lastIndex = pis.Length - 1;
                        if (pis[lastIndex].ParameterType == typeof(object[]))
                        {
                            // Package up the extra parameters into an object array
                            object[] pisParams  = new object[pis.Length];
                            object[] lastParams = new object[args.Length - lastIndex];
                            pisParams[lastIndex] = lastParams;
                            for (int j = 0; j < lastParams.Length; j++)
                            {
                                lastParams[j] = args[j + lastIndex].Value;
                            }

                            // Match parameter types for all but the last 'object[]' entry?
                            int i     = 0;
                            int exact = 0;
                            for (i = 0; i < lastIndex; i++)
                            {
                                TypeCode methodTc = Type.GetTypeCode(pis[i].ParameterType);

                                // Note how many parameters are an exact match
                                if (methodTc == args[i].Type)
                                {
                                    pisParams[i] = args[i].Value;
                                    exact++;
                                }
                                else
                                {
                                    // If cannot be implicitly converted, then fail to match at all
                                    if (ImplicitConverter.CanConvertTo(methodTc, args[i].Value, _language))
                                    {
                                        pisParams[i] = ImplicitConverter.ConvertTo(methodTc, args[i].Value, _language);
                                    }
                                    else
                                    {
                                        break;
                                    }
                                }
                            }

                            // If all parameters exactly match
                            if (exact == lastIndex)
                            {
                                // Use this method
                                callMi     = mi;
                                callParams = pisParams;
                                break;
                            }

                            // Remember the first compatible match we find
                            if ((i == lastIndex) && (callMi == null))
                            {
                                callMi     = mi;
                                callParams = pisParams;
                            }
                        }
                    }
                }
            }

            if (callMi == null)
            {
                if (target == null)
                {
                    throw new ApplicationException("Cannot find static public method called '" + Identifier + "' with matching parameters to those provided.");
                }
                else
                {
                    throw new ApplicationException("Cannot find instance public method called '" + Identifier + "' with matching parameters to those provided.");
                }
            }

            // Call the static method and return result
            EvalResult ret = new EvalResult();

            ret.Value = callMi.Invoke(target, callParams);
            return(DiscoverTypeCode(ret));
        }
示例#22
0
 private EvalResult EvaluateObjectMethod(EvalResult target, EvalResult[] args)
 {
     // Get all the instance methods that might of interest to us
     MethodInfo[] mis = target.Value.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.InvokeMethod);
     return(EvaluateMethod(mis, target.Value, args));
 }
        private EvalResult EvalShiftOp(UInt64 x, int count)
        {
            EvalResult ret = new EvalResult(TypeCode.UInt64, null);

            switch (Operation)
            {
                case ShiftOp.Left:
                    ret.Value = x << count;
                    break;
                case ShiftOp.Right:
                    ret.Value = x >> count;
                    break;
                default:
                    throw new ApplicationException("Unrecognized 'UInt64' type shift operation '" + OperationString);
            }

            return ret;
        }
        private EvalResult EvaluateObjectMember(EvalResult target)
        {
            // Extract the type we are working against
            Type t = target.Value.GetType();

            // Try and find the instance field for our identifier
            FieldInfo fi = t.GetField(Identifier, BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetField);

            if (fi != null)
            {
                // Grab the value of the static field
                EvalResult ret = new EvalResult();
                ret.Value = fi.GetValue(target.Value);
                return DiscoverTypeCode(ret);
            }
            else
            {
                // Try and find the instance property for our identifier
                PropertyInfo pi = t.GetProperty(Identifier, BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty);

                if (pi == null)
                    throw new ApplicationException("Cannot find instance public field/property called '" + Identifier + "' for type '" + t.ToString() + "'.");
                else
                {
                    // Grab the value of the instance property
                    EvalResult ret = new EvalResult();
                    ret.Value = pi.GetValue(target.Value, null);
                    return DiscoverTypeCode(ret);
                }
            }
        }
        private object ConvertUsingConverter(EvalResult ret, Type targetType)
        {
            // Try and get a converter from the target type
            TypeConverter converter = TypeDescriptor.GetConverter(targetType);
            if (converter != null)
            {
                // Ask the converter to convert using the source type when possible, if not possible
                // fallback to requesting a string version of the source be converted to the target
                switch (ret.Type)
                {
                    case TypeCode.Boolean:
                        if (converter.CanConvertFrom(typeof(Boolean)))
                            return converter.ConvertFrom((Boolean)ret.Value);
                        else if (converter.CanConvertFrom(typeof(String)))
                            return converter.ConvertFromString(ret.Value.ToString());
                        break;
                    case TypeCode.SByte:
                        if (converter.CanConvertFrom(typeof(SByte)))
                            return converter.ConvertFrom((SByte)ret.Value);
                        else if (converter.CanConvertFrom(typeof(String)))
                            return converter.ConvertFromString(ret.Value.ToString());
                        break;
                    case TypeCode.Byte:
                        if (converter.CanConvertFrom(typeof(Byte)))
                            return converter.ConvertFrom((Byte)ret.Value);
                        else if (converter.CanConvertFrom(typeof(String)))
                            return converter.ConvertFromString(ret.Value.ToString());
                        break;
                    case TypeCode.Char:
                        if (converter.CanConvertFrom(typeof(Char)))
                            return converter.ConvertFrom((Char)ret.Value);
                        else if (converter.CanConvertFrom(typeof(String)))
                            return converter.ConvertFromString(ret.Value.ToString());
                        break;
                    case TypeCode.Int16:
                        if (converter.CanConvertFrom(typeof(Int16)))
                            return converter.ConvertFrom((Int16)ret.Value);
                        else if (converter.CanConvertFrom(typeof(String)))
                            return converter.ConvertFromString(ret.Value.ToString());
                        break;
                    case TypeCode.Int32:
                        if (converter.CanConvertFrom(typeof(Int32)))
                            return converter.ConvertFrom((Int32)ret.Value);
                        else if (converter.CanConvertFrom(typeof(String)))
                            return converter.ConvertFromString(ret.Value.ToString());
                        break;
                    case TypeCode.Int64:
                        if (converter.CanConvertFrom(typeof(Int64)))
                            return converter.ConvertFrom((Int64)ret.Value);
                        else if (converter.CanConvertFrom(typeof(String)))
                            return converter.ConvertFromString(ret.Value.ToString());
                        break;
                    case TypeCode.UInt16:
                        if (converter.CanConvertFrom(typeof(UInt16)))
                            return converter.ConvertFrom((UInt16)ret.Value);
                        else if (converter.CanConvertFrom(typeof(String)))
                            return converter.ConvertFromString(ret.Value.ToString());
                        break;
                    case TypeCode.UInt32:
                        if (converter.CanConvertFrom(typeof(UInt32)))
                            return converter.ConvertFrom((UInt32)ret.Value);
                        else if (converter.CanConvertFrom(typeof(String)))
                            return converter.ConvertFromString(ret.Value.ToString());
                        break;
                    case TypeCode.UInt64:
                        if (converter.CanConvertFrom(typeof(UInt64)))
                            return converter.ConvertFrom((UInt64)ret.Value);
                        else if (converter.CanConvertFrom(typeof(String)))
                            return converter.ConvertFromString(ret.Value.ToString());
                        break;
                    case TypeCode.Single:
                        if (converter.CanConvertFrom(typeof(Single)))
                            return converter.ConvertFrom((Single)ret.Value);
                        else if (converter.CanConvertFrom(typeof(String)))
                            return converter.ConvertFromString(ret.Value.ToString());
                        break;
                    case TypeCode.Double:
                        if (converter.CanConvertFrom(typeof(Double)))
                            return converter.ConvertFrom((Double)ret.Value);
                        else if (converter.CanConvertFrom(typeof(String)))
                            return converter.ConvertFromString(ret.Value.ToString());
                        break;
                    case TypeCode.Decimal:
                        if (converter.CanConvertFrom(typeof(Decimal)))
                            return converter.ConvertFrom((Decimal)ret.Value);
                        else if (converter.CanConvertFrom(typeof(String)))
                            return converter.ConvertFromString(ret.Value.ToString());
                        break;
                    case TypeCode.String:
                        if (converter.CanConvertFrom(typeof(String)))
                            return converter.ConvertFrom((String)ret.Value);
                        else if (converter.CanConvertFrom(typeof(String)))
                            return converter.ConvertFromString(ret.Value.ToString());
                        break;
                    case TypeCode.DateTime:
                        if (converter.CanConvertFrom(typeof(DateTime)))
                            return converter.ConvertFrom((DateTime)ret.Value);
                        else if (converter.CanConvertFrom(typeof(String)))
                            return converter.ConvertFromString(ret.Value.ToString());
                        break;
                    case TypeCode.DBNull:
                        if (converter.CanConvertFrom(typeof(DBNull)))
                            return converter.ConvertFrom((DBNull)ret.Value);
                        else if (converter.CanConvertFrom(typeof(String)))
                            return converter.ConvertFromString(ret.Value.ToString());
                        break;
                    case TypeCode.Object:
                        if (converter.CanConvertFrom(typeof(Object)))
                            return converter.ConvertFrom((Object)ret.Value);
                        else if (converter.CanConvertFrom(typeof(String)))
                            return converter.ConvertFromString(ret.Value.ToString());
                        break;
                }
            }

            // Unable to convert the value
            return ret.Value;
        }
 private EvalResult EvaluateTypeMethod(EvalResult target, EvalResult[] args)
 {
     // Get all the static methods that might of interest to us
     MethodInfo[] mis = ((Type)target.Value).GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod);
     return EvaluateMethod(mis, null, args);
 }
        private EvalResult EvaluateObjectInstance(EvalResult target,
                                                  EvalResult[] args, 
                                                  object thisObject)
        {
            // Get the type definition of the target instance
            Type t = target.Value.GetType();

            // Get the list of all properties that might be of interest to us
            PropertyInfo[] pis = t.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty);

            PropertyInfo callPi = null;
            object[] callParams = null;

            // Find properties that we could call
            foreach (PropertyInfo pi in pis)
            {
                // Object indexers are compiled from 'this[...]' in C# to the fixed name 'Item'
                if (pi.Name == "Item")
                {
                    // Grab the list of parameters for this property accessor
                    ParameterInfo[] infos = pi.GetIndexParameters();

                    // Is the last parameter an array of params?
                    bool paramArray = (infos.Length > 0 ? infos[infos.Length - 1].IsDefined(typeof(ParamArrayAttribute), false) : false);

                    // It must have the same number of parameters as we have arguments
                    if (!paramArray && (infos.Length == args.Length))
                    {
                        // Match parameter types?
                        int i = 0;
                        int exact = 0;
                        object[] infoParams = new object[args.Length];
                        for (i = 0; i < infos.Length; i++)
                        {
                            TypeCode paramTc = Type.GetTypeCode(infos[i].ParameterType);

                            // Note how many parameters are an exact match
                            if (paramTc == args[i].Type)
                            {
                                infoParams[i] = args[i].Value;
                                exact++;
                            }
                            else
                            {
                                // If cannot be implicitly converted, then fail to match at all
                                if (ImplicitConverter.CanConvertTo(paramTc, args[i].Value, _language))
                                    infoParams[i] = ImplicitConverter.ConvertTo(paramTc, args[i].Value, _language);
                                else
                                    break;
                            }
                        }

                        // If all parameters exactly match
                        if (exact == infos.Length)
                        {
                            // Use this method
                            callPi = pi;
                            callParams = infoParams;
                            break;
                        }

                        // Remember the first compatible match we find
                        if ((i == infos.Length) && (callPi == null))
                        {
                            callPi = pi;
                            callParams = infoParams;
                        }
                    }
                    else if (paramArray)
                    {
                        // We can only handle packaging up a param array as an object array
                        int lastIndex = infos.Length - 1;
                        if (infos[lastIndex].ParameterType == typeof(object[]))
                        {
                            // Package up the extra parameters into an object array
                            object[] infoParams = new object[infos.Length];
                            object[] lastParams = new object[args.Length - lastIndex];
                            infoParams[lastIndex] = lastParams;
                            for (int j = 0; j < lastParams.Length; j++)
                                lastParams[j] = args[j + lastIndex].Value;

                            // Match parameter types for all but the last 'object[]' entry?
                            int i = 0;
                            int exact = 0;
                            for (i = 0; i < lastIndex; i++)
                            {
                                TypeCode paramTc = Type.GetTypeCode(infos[i].ParameterType);

                                // Note how many parameters are an exact match
                                if (paramTc == args[i].Type)
                                {
                                    infoParams[i] = args[i].Value;
                                    exact++;
                                }
                                else
                                {
                                    // If cannot be implicitly converted, then fail to match at all
                                    if (ImplicitConverter.CanConvertTo(paramTc, args[i].Value, _language))
                                        infoParams[i] = ImplicitConverter.ConvertTo(paramTc, args[i].Value, _language);
                                    else
                                        break;
                                }
                            }

                            // If all parameters exactly match
                            if (exact == lastIndex)
                            {
                                // Use this method
                                callPi = pi;
                                callParams = infoParams;
                                break;
                            }

                            // Remember the first compatible match we find
                            if ((i == lastIndex) && (callPi == null))
                            {
                                callPi = pi;
                                callParams = infoParams;
                            }
                        }
                    }
                }
            }

            if (callPi == null)
                throw new ApplicationException("Cannot find array acessor for type '" + target.Type.ToString() + "' with matching number and type of arguments.");

            // Call the static method and return result
            EvalResult ret = new EvalResult();
            ret.Value = callPi.GetValue(target.Value, callParams);
            return DiscoverTypeCode(ret);
        }
 private EvalResult EvaluateObjectMethod(EvalResult target, EvalResult[] args)
 {
     // Get all the instance methods that might of interest to us
     MethodInfo[] mis = target.Value.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.InvokeMethod);
     return EvaluateMethod(mis, target.Value, args);
 }
        private EvalResult EvaluateMinus(EvalResult ret)
        {
            // Processing depends on the type we are provided with
            switch (ret.Type)
            {
                case TypeCode.Byte:
                    ret.Value = 0 - ((Byte)ret.Value);
                    break;
                case TypeCode.SByte:
                    ret.Value = 0 - ((SByte)ret.Value);
                    break;
                case TypeCode.Char:
                    if (_language != Language.VBNet)
                    {
                        ret.Value = 0 - ((Char)ret.Value);
                        break;
                    }
                    else
                        throw new ApplicationException("Operation '-' cannot be applied to operand of type '" + ret.Type.ToString() + "'.");
                case TypeCode.Int16:
                    ret.Value = 0 - ((Int16)ret.Value);
                    break;
                case TypeCode.Int32:
                    ret.Value = 0 - ((Int32)ret.Value);
                    break;
                case TypeCode.Int64:
                    ret.Value = 0 - ((Int64)ret.Value);
                    break;
                case TypeCode.UInt16:
                    // Convert to long and subtract from zero
                    ret.Value = 0 - (Int64)((UInt16)ret.Value);
                    ret.Type = TypeCode.Int64;
                    break;
                case TypeCode.UInt32:
                    // Convert to long and subtract from zero
                    ret.Value = 0 - (Int64)((UInt32)ret.Value);
                    ret.Type = TypeCode.Int64;
                    break;
                case TypeCode.Single:
                    ret.Value = 0 - ((Single)ret.Value);
                    break;
                case TypeCode.Double:
                    ret.Value = 0 - ((Double)ret.Value);
                    break;
                case TypeCode.Decimal:
                    ret.Value = 0 - ((Decimal)ret.Value);
                    break;
                default:
                    throw new ApplicationException("Operation '-' cannot be applied to operand of type '" + ret.Type.ToString() + "'.");
            }

            return ret;
        }
示例#30
0
        /// <summary>
        /// Evalaute this node and return result.
        /// </summary>
        /// <param name="thisObject">Reference to object that is exposed as 'this'.</param>
        /// <returns>Result value and type of that result.</returns>
        public override EvalResult Evaluate(object thisObject)
        {
            // Get the result from evaluating both children
            EvalResult left  = this[0].Evaluate(thisObject);
            EvalResult right = this[1].Evaluate(thisObject);

            int count;

            if (_language == Language.CSharp)
            {
                // The shift count is always an Int32, so convert anything smaller to an Int32
                switch (right.Type)
                {
                case TypeCode.Char:
                    count = (Int32)(Char)right.Value;
                    break;

                case TypeCode.Byte:
                    count = (Int32)(Byte)right.Value;
                    break;

                case TypeCode.SByte:
                    count = (Int32)(SByte)right.Value;
                    break;

                case TypeCode.UInt16:
                    count = (Int32)(UInt16)right.Value;
                    break;

                case TypeCode.Int16:
                    count = (Int32)(Int16)right.Value;
                    break;

                case TypeCode.Int32:
                    count = (Int32)right.Value;
                    break;

                default:
                    throw new ApplicationException("Shift operation '" + OperationString + "' cannot convert the shift count from type '" + right.Type.ToString() + "' to 'Int32'.");
                }
            }
            else
            {
                if (ImplicitConverter.CanConvertToInt32(right.Value, Language.VBNet))
                {
                    count = ImplicitConverter.ConvertToInt32(right.Value, Language.VBNet);
                }
                else
                {
                    throw new ApplicationException("Shift operation '" + OperationString + "' cannot convert the shift count to a 'Int32' value.");
                }
            }

            // Perform the actual shift operation
            switch (left.Type)
            {
            case TypeCode.Byte:
                return(EvalShiftOp((Int32)(Byte)left.Value, count));

            case TypeCode.SByte:
                return(EvalShiftOp((Int32)(SByte)left.Value, count));

            case TypeCode.Char:
                if (_language == Language.CSharp)
                {
                    return(EvalShiftOp((Int32)(Char)left.Value, count));
                }
                break;

            case TypeCode.UInt16:
                return(EvalShiftOp((Int32)(UInt16)left.Value, count));

            case TypeCode.Int16:
                return(EvalShiftOp((Int32)(Int16)left.Value, count));

            case TypeCode.Int32:
                return(EvalShiftOp((Int32)(Int32)left.Value, count));

            case TypeCode.UInt32:
                return(EvalShiftOp((UInt32)left.Value, count));

            case TypeCode.Int64:
                return(EvalShiftOp((Int64)left.Value, count));

            case TypeCode.UInt64:
                return(EvalShiftOp((UInt64)left.Value, count));

            case TypeCode.Boolean:
                if (_language == Language.VBNet)
                {
                    return(EvalShiftOp((Int16)ImplicitConverter.ConvertToInt16(left.Value, Language.VBNet), count));
                }
                break;

            case TypeCode.Single:
                if (_language == Language.VBNet)
                {
                    return(EvalShiftOp((Int64)(Single)left.Value, count));
                }
                break;

            case TypeCode.Double:
                if (_language == Language.VBNet)
                {
                    return(EvalShiftOp((Int64)(Double)left.Value, count));
                }
                break;

            case TypeCode.Decimal:
                if (_language == Language.VBNet)
                {
                    return(EvalShiftOp((Int64)(Decimal)left.Value, count));
                }
                break;
            }

            throw new ApplicationException("Shift operation '" + OperationString + "' cannot shift type '" + left.Type.ToString() + "'.");
        }
        private EvalResult EvaluateObjectArray(EvalResult target, 
                                               EvalResult[] args, 
                                               object thisObject)
        {
            // We know the value is an actual array instance
            Array array = (Array)target.Value;

            // Must have same number of arguments as the array rank
            if (array.Rank != args.Length)
                throw new ApplicationException("Array expects '" + array.Rank.ToString() + "' indices but '" + args.Length.ToString() + "' have been specified.");

            // Construct the set of indices for accessing array
            long[] indices = new long[args.Length];
            for (int i = 0; i < args.Length; i++)
                indices[i] = ImplicitConverter.ConvertToInt64(args[i].Value, _language);

            EvalResult ret = new EvalResult();
            ret.Value = array.GetValue(indices);
            return DiscoverTypeCode(ret);
        }
        private EvalResult EvaluatePlus(EvalResult ret)
        {
            // Unary plus means we do nothing as long as the type is valid
            switch (ret.Type)
            {
                case TypeCode.Char:
                    if (_language == Language.VBNet)
                        throw new ApplicationException("Operation '+' cannot be applied to operand of type '" + ret.Type.ToString() + "'.");
                    else
                        break;
                case TypeCode.Byte:
                case TypeCode.SByte:
                case TypeCode.Int16:
                case TypeCode.Int32:
                case TypeCode.Int64:
                case TypeCode.UInt16:
                case TypeCode.UInt32:
                case TypeCode.UInt64:
                case TypeCode.Single:
                case TypeCode.Double:
                case TypeCode.Decimal:
                    break;
                default:
                    throw new ApplicationException("Operation '+' cannot be applied to operand of type '" + ret.Type.ToString() + "'.");
            }

            return ret;
        }
        private EvalResult EvaluateComplement(EvalResult ret)
        {
            // Unary plus means we do nothing as long as the type is valid
            switch (ret.Type)
            {
                case TypeCode.Byte:
                    ret.Value = ~(Byte)ret.Value;
                    break;
                case TypeCode.SByte:
                    ret.Value = ~(SByte)ret.Value;
                    break;
                case TypeCode.Char:
                    if (_language != Language.VBNet)
                        ret.Value = ~(Char)ret.Value;
                    else
                        throw new ApplicationException("Operation '~' cannot be applied to operand of type '" + ret.Type.ToString() + "'.");
                    break;
                case TypeCode.Int16:
                    ret.Value = ~(Int16)ret.Value;
                    break;
                case TypeCode.Int32:
                    ret.Value = ~(Int32)ret.Value;
                    break;
                case TypeCode.Int64:
                    ret.Value = ~(Int64)ret.Value;
                    break;
                case TypeCode.UInt16:
                    ret.Value = ~(UInt16)ret.Value;
                    break;
                case TypeCode.UInt32:
                    ret.Value = ~(UInt32)ret.Value;
                    break;
                case TypeCode.UInt64:
                    ret.Value = ~(UInt64)ret.Value;
                    break;
                default:
                    throw new ApplicationException("Operation '~' cannot be applied to operand of type '" + ret.Type.ToString() + "'.");
            }

            return ret;
        }
示例#34
0
        private EvalResult EvaluateObjectInstance(EvalResult target,
                                                  EvalResult[] args,
                                                  object thisObject)
        {
            // Get the type definition of the target instance
            Type t = target.Value.GetType();

            // Get the list of all properties that might be of interest to us
            PropertyInfo[] pis = t.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty);

            PropertyInfo callPi = null;

            object[] callParams = null;

            // Find properties that we could call
            foreach (PropertyInfo pi in pis)
            {
                // Object indexers are compiled from 'this[...]' in C# to the fixed name 'Item'
                if (pi.Name == "Item")
                {
                    // Grab the list of parameters for this property accessor
                    ParameterInfo[] infos = pi.GetIndexParameters();

                    // Is the last parameter an array of params?
                    bool paramArray = (infos.Length > 0 ? infos[infos.Length - 1].IsDefined(typeof(ParamArrayAttribute), false) : false);

                    // It must have the same number of parameters as we have arguments
                    if (!paramArray && (infos.Length == args.Length))
                    {
                        // Match parameter types?
                        int      i          = 0;
                        int      exact      = 0;
                        object[] infoParams = new object[args.Length];
                        for (i = 0; i < infos.Length; i++)
                        {
                            TypeCode paramTc = Type.GetTypeCode(infos[i].ParameterType);

                            // Note how many parameters are an exact match
                            if (paramTc == args[i].Type)
                            {
                                infoParams[i] = args[i].Value;
                                exact++;
                            }
                            else
                            {
                                // If cannot be implicitly converted, then fail to match at all
                                if (ImplicitConverter.CanConvertTo(paramTc, args[i].Value, _language))
                                {
                                    infoParams[i] = ImplicitConverter.ConvertTo(paramTc, args[i].Value, _language);
                                }
                                else
                                {
                                    break;
                                }
                            }
                        }

                        // If all parameters exactly match
                        if (exact == infos.Length)
                        {
                            // Use this method
                            callPi     = pi;
                            callParams = infoParams;
                            break;
                        }

                        // Remember the first compatible match we find
                        if ((i == infos.Length) && (callPi == null))
                        {
                            callPi     = pi;
                            callParams = infoParams;
                        }
                    }
                    else if (paramArray)
                    {
                        // We can only handle packaging up a param array as an object array
                        int lastIndex = infos.Length - 1;
                        if (infos[lastIndex].ParameterType == typeof(object[]))
                        {
                            // Package up the extra parameters into an object array
                            object[] infoParams = new object[infos.Length];
                            object[] lastParams = new object[args.Length - lastIndex];
                            infoParams[lastIndex] = lastParams;
                            for (int j = 0; j < lastParams.Length; j++)
                            {
                                lastParams[j] = args[j + lastIndex].Value;
                            }

                            // Match parameter types for all but the last 'object[]' entry?
                            int i     = 0;
                            int exact = 0;
                            for (i = 0; i < lastIndex; i++)
                            {
                                TypeCode paramTc = Type.GetTypeCode(infos[i].ParameterType);

                                // Note how many parameters are an exact match
                                if (paramTc == args[i].Type)
                                {
                                    infoParams[i] = args[i].Value;
                                    exact++;
                                }
                                else
                                {
                                    // If cannot be implicitly converted, then fail to match at all
                                    if (ImplicitConverter.CanConvertTo(paramTc, args[i].Value, _language))
                                    {
                                        infoParams[i] = ImplicitConverter.ConvertTo(paramTc, args[i].Value, _language);
                                    }
                                    else
                                    {
                                        break;
                                    }
                                }
                            }

                            // If all parameters exactly match
                            if (exact == lastIndex)
                            {
                                // Use this method
                                callPi     = pi;
                                callParams = infoParams;
                                break;
                            }

                            // Remember the first compatible match we find
                            if ((i == lastIndex) && (callPi == null))
                            {
                                callPi     = pi;
                                callParams = infoParams;
                            }
                        }
                    }
                }
            }

            if (callPi == null)
            {
                throw new ApplicationException("Cannot find array acessor for type '" + target.Type.ToString() + "' with matching number and type of arguments.");
            }

            // Call the static method and return result
            EvalResult ret = new EvalResult();

            ret.Value = callPi.GetValue(target.Value, callParams);
            return(DiscoverTypeCode(ret));
        }
        /// <summary>
        /// Evalaute this node and return result.
        /// </summary>
        /// <param name="thisObject">Reference to object that is exposed as 'this'.</param>
        /// <returns>Result value and type of that result.</returns>
        public override EvalResult Evaluate(object thisObject)
        {
            // Always evaluate the first child
            EvalResult left = this[0].Evaluate(thisObject);

            // We can only handle a boolean result
            if (left.Type != TypeCode.Boolean)
            {
                // Try and perform implicit conversion to a boolean
                if (ImplicitConverter.CanConvertToBoolean(left.Value, _language))
                {
                    left.Type  = TypeCode.Boolean;
                    left.Value = ImplicitConverter.ConvertToBoolean(left.Value, _language);
                }
                else
                {
                    throw new ApplicationException("Operator '" + OperationString + "' can only operate on 'bool' types.");
                }
            }

            switch (Operation)
            {
            case CompareOp.Or:
                // If 'true' then there is no need to evaluate the right side
                if ((bool)left.Value)
                {
                    return(left);
                }
                break;

            case CompareOp.And:
                // If 'false' then there is no need to evaluate the right side
                if (!(bool)left.Value)
                {
                    return(left);
                }
                break;

            default:
                throw new ApplicationException("Unimplemented conditional logical operator '" + Operation.ToString() + "'.");
            }

            // Need to evaluate the second child
            left = this[1].Evaluate(thisObject);

            // We can only handle a boolean result
            if (left.Type != TypeCode.Boolean)
            {
                // Try and perform implicit conversion to a boolean
                if (ImplicitConverter.CanConvertToBoolean(left.Value, _language))
                {
                    left.Type  = TypeCode.Boolean;
                    left.Value = ImplicitConverter.ConvertToBoolean(left.Value, _language);
                }
                else
                {
                    throw new ApplicationException("Operator '" + OperationString + "' can only operate on 'bool' types.");
                }
            }

            // Just return whatever the result is as the result of the conditional operation
            return(left);
        }
        private EvalResult EvaluateMethod(MethodInfo[] mis, object target, EvalResult[] args)
        {
            if (mis == null)
            {
                if (target == null)
                    throw new ApplicationException("Cannot find static public method called '" + Identifier + "'.");
                else
                    throw new ApplicationException("Cannot find instance public method called '" + Identifier + "'.");
            }

            MethodInfo callMi = null;
            object[] callParams = null;

            // Find methods that we could call
            foreach (MethodInfo mi in mis)
            {
                // Matching name?
                if (mi.Name == Identifier)
                {
                    ParameterInfo[] pis = mi.GetParameters();

                    // Is the last parameter an array of params?
                    bool paramArray = (pis.Length > 0 ? pis[pis.Length - 1].IsDefined(typeof(ParamArrayAttribute), false) : false);

                    // It must have the same number of parameters as we have arguments
                    if (!paramArray && (pis.Length == args.Length))
                    {
                        // Match parameter types?
                        int i = 0;
                        int exact = 0;
                        object[] pisParams = new object[args.Length];
                        for (i = 0; i < pis.Length; i++)
                        {
                            TypeCode methodTc = Type.GetTypeCode(pis[i].ParameterType);

                            // Note how many parameters are an exact match
                            if (methodTc == args[i].Type)
                            {
                                pisParams[i] = args[i].Value;
                                exact++;
                            }
                            else
                            {
                                // If cannot be implicitly converted, then fail to match at all
                                if (ImplicitConverter.CanConvertTo(methodTc, args[i].Value, _language))
                                    pisParams[i] = ImplicitConverter.ConvertTo(methodTc, args[i].Value, _language);
                                else
                                    break;
                            }
                        }

                        // If all parameters exactly match
                        if (exact == pis.Length)
                        {
                            // Use this method
                            callMi = mi;
                            callParams = pisParams;
                            break;
                        }

                        // Remember the first compatible match we find
                        if ((i == pis.Length) && (callMi == null))
                        {
                            callMi = mi;
                            callParams = pisParams;
                        }
                    }
                    else if (paramArray)
                    {
                        // We can only handle packaging up a param array as an object array
                        int lastIndex = pis.Length - 1;
                        if (pis[lastIndex].ParameterType == typeof(object[]))
                        {
                            // Package up the extra parameters into an object array
                            object[] pisParams = new object[pis.Length];
                            object[] lastParams = new object[args.Length - lastIndex];
                            pisParams[lastIndex] = lastParams;
                            for (int j = 0; j < lastParams.Length; j++)
                                lastParams[j] = args[j + lastIndex].Value;

                            // Match parameter types for all but the last 'object[]' entry?
                            int i = 0;
                            int exact = 0;
                            for (i = 0; i < lastIndex; i++)
                            {
                                TypeCode methodTc = Type.GetTypeCode(pis[i].ParameterType);

                                // Note how many parameters are an exact match
                                if (methodTc == args[i].Type)
                                {
                                    pisParams[i] = args[i].Value;
                                    exact++;
                                }
                                else
                                {
                                    // If cannot be implicitly converted, then fail to match at all
                                    if (ImplicitConverter.CanConvertTo(methodTc, args[i].Value, _language))
                                        pisParams[i] = ImplicitConverter.ConvertTo(methodTc, args[i].Value, _language);
                                    else
                                        break;
                                }
                            }

                            // If all parameters exactly match
                            if (exact == lastIndex)
                            {
                                // Use this method
                                callMi = mi;
                                callParams = pisParams;
                                break;
                            }

                            // Remember the first compatible match we find
                            if ((i == lastIndex) && (callMi == null))
                            {
                                callMi = mi;
                                callParams = pisParams;
                            }
                        }
                    }
                }
            }

            if (callMi == null)
            {
                if (target == null)
                    throw new ApplicationException("Cannot find static public method called '" + Identifier + "' with matching parameters to those provided.");
                else
                    throw new ApplicationException("Cannot find instance public method called '" + Identifier + "' with matching parameters to those provided.");
            }

            // Call the static method and return result
            EvalResult ret = new EvalResult();
            ret.Value = callMi.Invoke(target, callParams);
            return DiscoverTypeCode(ret);
        }
        private object ConvertUsingConverter(EvalResult ret, Type targetType)
        {
            // Try and get a converter from the target type
            TypeConverter converter = TypeDescriptor.GetConverter(targetType);

            if (converter != null)
            {
                // Ask the converter to convert using the source type when possible, if not possible
                // fallback to requesting a string version of the source be converted to the target
                switch (ret.Type)
                {
                case TypeCode.Boolean:
                    if (converter.CanConvertFrom(typeof(Boolean)))
                    {
                        return(converter.ConvertFrom((Boolean)ret.Value));
                    }
                    else if (converter.CanConvertFrom(typeof(String)))
                    {
                        return(converter.ConvertFromString(ret.Value.ToString()));
                    }
                    break;

                case TypeCode.SByte:
                    if (converter.CanConvertFrom(typeof(SByte)))
                    {
                        return(converter.ConvertFrom((SByte)ret.Value));
                    }
                    else if (converter.CanConvertFrom(typeof(String)))
                    {
                        return(converter.ConvertFromString(ret.Value.ToString()));
                    }
                    break;

                case TypeCode.Byte:
                    if (converter.CanConvertFrom(typeof(Byte)))
                    {
                        return(converter.ConvertFrom((Byte)ret.Value));
                    }
                    else if (converter.CanConvertFrom(typeof(String)))
                    {
                        return(converter.ConvertFromString(ret.Value.ToString()));
                    }
                    break;

                case TypeCode.Char:
                    if (converter.CanConvertFrom(typeof(Char)))
                    {
                        return(converter.ConvertFrom((Char)ret.Value));
                    }
                    else if (converter.CanConvertFrom(typeof(String)))
                    {
                        return(converter.ConvertFromString(ret.Value.ToString()));
                    }
                    break;

                case TypeCode.Int16:
                    if (converter.CanConvertFrom(typeof(Int16)))
                    {
                        return(converter.ConvertFrom((Int16)ret.Value));
                    }
                    else if (converter.CanConvertFrom(typeof(String)))
                    {
                        return(converter.ConvertFromString(ret.Value.ToString()));
                    }
                    break;

                case TypeCode.Int32:
                    if (converter.CanConvertFrom(typeof(Int32)))
                    {
                        return(converter.ConvertFrom((Int32)ret.Value));
                    }
                    else if (converter.CanConvertFrom(typeof(String)))
                    {
                        return(converter.ConvertFromString(ret.Value.ToString()));
                    }
                    break;

                case TypeCode.Int64:
                    if (converter.CanConvertFrom(typeof(Int64)))
                    {
                        return(converter.ConvertFrom((Int64)ret.Value));
                    }
                    else if (converter.CanConvertFrom(typeof(String)))
                    {
                        return(converter.ConvertFromString(ret.Value.ToString()));
                    }
                    break;

                case TypeCode.UInt16:
                    if (converter.CanConvertFrom(typeof(UInt16)))
                    {
                        return(converter.ConvertFrom((UInt16)ret.Value));
                    }
                    else if (converter.CanConvertFrom(typeof(String)))
                    {
                        return(converter.ConvertFromString(ret.Value.ToString()));
                    }
                    break;

                case TypeCode.UInt32:
                    if (converter.CanConvertFrom(typeof(UInt32)))
                    {
                        return(converter.ConvertFrom((UInt32)ret.Value));
                    }
                    else if (converter.CanConvertFrom(typeof(String)))
                    {
                        return(converter.ConvertFromString(ret.Value.ToString()));
                    }
                    break;

                case TypeCode.UInt64:
                    if (converter.CanConvertFrom(typeof(UInt64)))
                    {
                        return(converter.ConvertFrom((UInt64)ret.Value));
                    }
                    else if (converter.CanConvertFrom(typeof(String)))
                    {
                        return(converter.ConvertFromString(ret.Value.ToString()));
                    }
                    break;

                case TypeCode.Single:
                    if (converter.CanConvertFrom(typeof(Single)))
                    {
                        return(converter.ConvertFrom((Single)ret.Value));
                    }
                    else if (converter.CanConvertFrom(typeof(String)))
                    {
                        return(converter.ConvertFromString(ret.Value.ToString()));
                    }
                    break;

                case TypeCode.Double:
                    if (converter.CanConvertFrom(typeof(Double)))
                    {
                        return(converter.ConvertFrom((Double)ret.Value));
                    }
                    else if (converter.CanConvertFrom(typeof(String)))
                    {
                        return(converter.ConvertFromString(ret.Value.ToString()));
                    }
                    break;

                case TypeCode.Decimal:
                    if (converter.CanConvertFrom(typeof(Decimal)))
                    {
                        return(converter.ConvertFrom((Decimal)ret.Value));
                    }
                    else if (converter.CanConvertFrom(typeof(String)))
                    {
                        return(converter.ConvertFromString(ret.Value.ToString()));
                    }
                    break;

                case TypeCode.String:
                    if (converter.CanConvertFrom(typeof(String)))
                    {
                        return(converter.ConvertFrom((String)ret.Value));
                    }
                    else if (converter.CanConvertFrom(typeof(String)))
                    {
                        return(converter.ConvertFromString(ret.Value.ToString()));
                    }
                    break;

                case TypeCode.DateTime:
                    if (converter.CanConvertFrom(typeof(DateTime)))
                    {
                        return(converter.ConvertFrom((DateTime)ret.Value));
                    }
                    else if (converter.CanConvertFrom(typeof(String)))
                    {
                        return(converter.ConvertFromString(ret.Value.ToString()));
                    }
                    break;

                case TypeCode.DBNull:
                    if (converter.CanConvertFrom(typeof(DBNull)))
                    {
                        return(converter.ConvertFrom((DBNull)ret.Value));
                    }
                    else if (converter.CanConvertFrom(typeof(String)))
                    {
                        return(converter.ConvertFromString(ret.Value.ToString()));
                    }
                    break;

                case TypeCode.Object:
                    if (converter.CanConvertFrom(typeof(Object)))
                    {
                        return(converter.ConvertFrom((Object)ret.Value));
                    }
                    else if (converter.CanConvertFrom(typeof(String)))
                    {
                        return(converter.ConvertFromString(ret.Value.ToString()));
                    }
                    break;
                }
            }

            // Unable to convert the value
            return(ret.Value);
        }
        private EvalResult EvaluateNot(EvalResult ret)
        {
            // Unary plus means we do nothing as long as the type is valid
            switch (ret.Type)
            {
                case TypeCode.Boolean:
                    ret.Value = !(bool)ret.Value;
                    break;
                default:
                    throw new ApplicationException("Logical invert cannot be applied to operand of type '" + ret.Type.ToString() + "'.");
            }

            return ret;
        }