/// <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)); } }
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)); } } }
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); } }
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); }
/// <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)); }
/// <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); }
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); }
/// <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); }
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); }
/// <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)); } }
/// <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); }
/// <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); }
/// <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)); } }
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 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); }
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 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; }
/// <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; }
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; }