public ConditionalElement(ExpressionElement condition, ExpressionElement whenTrue, ExpressionElement whenFalse) { MyCondition = condition; MyWhenTrue = whenTrue; MyWhenFalse = whenFalse; if ((!object.ReferenceEquals(MyCondition.ResultType, typeof(bool)))) { base.ThrowCompileException(CompileErrorResourceKeys.FirstArgNotBoolean, CompileExceptionReason.TypeMismatch); } // The result type is the type that is common to the true/false operands if (ImplicitConverter.EmitImplicitConvert(MyWhenFalse.ResultType, MyWhenTrue.ResultType, null) == true) { MyResultType = MyWhenTrue.ResultType; } else if (ImplicitConverter.EmitImplicitConvert(MyWhenTrue.ResultType, MyWhenFalse.ResultType, null) == true) { MyResultType = MyWhenFalse.ResultType; } else { base.ThrowCompileException(CompileErrorResourceKeys.NeitherArgIsConvertibleToTheOther, CompileExceptionReason.TypeMismatch, MyWhenTrue.ResultType.Name, MyWhenFalse.ResultType.Name); } }
private void Validate() { if (ImplicitConverter.EmitImplicitConvert(MyChild.ResultType, MyResultType, null) == false) { base.ThrowCompileException(CompileErrorResourceKeys.CannotConvertTypeToExpressionResult, CompileExceptionReason.TypeMismatch, MyChild.ResultType.Name, MyResultType.Name); } }
// Emit a string concatenation private void EmitStringConcat(FleeILGenerator ilg, IServiceProvider services) { Type argType = default(Type); MethodInfo concatMethodInfo = default(MethodInfo); // Pick the most specific concat method if (this.AreBothChildrenOfType(typeof(string)) == true) { concatMethodInfo = OurStringConcatMethodInfo; argType = typeof(string); } else { Debug.Assert(this.IsEitherChildOfType(typeof(string)), "one child must be a string"); concatMethodInfo = OurObjectConcatMethodInfo; argType = typeof(object); } // Emit the operands and call the function MyLeftChild.Emit(ilg, services); ImplicitConverter.EmitImplicitConvert(MyLeftChild.ResultType, argType, ilg); MyRightChild.Emit(ilg, services); ImplicitConverter.EmitImplicitConvert(MyRightChild.ResultType, argType, ilg); ilg.Emit(OpCodes.Call, concatMethodInfo); }
protected static void EmitChildWithConvert(ExpressionElement child, Type resultType, FleeILGenerator ilg, IServiceProvider services) { child.Emit(ilg, services); bool converted = ImplicitConverter.EmitImplicitConvert(child.ResultType, resultType, ilg); Debug.Assert(converted, "convert failed"); }
// Emit elements into an array private static void EmitElementArrayLoad(ExpressionElement[] elements, Type arrayElementType, FleeILGenerator ilg, IServiceProvider services) { // Load the array length LiteralElement.EmitInt32Load(elements.Length, ilg); // Create the array ilg.Emit(OpCodes.Newarr, arrayElementType); // Store the new array in a unique local and remember the index LocalBuilder local = ilg.DeclareLocal(arrayElementType.MakeArrayType()); int arrayLocalIndex = local.LocalIndex; Utility.EmitStoreLocal(ilg, arrayLocalIndex); for (int i = 0; i <= elements.Length - 1; i++) { // Load the array Utility.EmitLoadLocal(ilg, arrayLocalIndex); // Load the index LiteralElement.EmitInt32Load(i, ilg); // Emit the element (with any required conversions) ExpressionElement element = elements[i]; element.Emit(ilg, services); ImplicitConverter.EmitImplicitConvert(element.ResultType, arrayElementType, ilg); // Store it into the array Utility.EmitArrayStore(ilg, arrayElementType); } // Load the array Utility.EmitLoadLocal(ilg, arrayLocalIndex); }
public override void Emit(FleeILGenerator ilg, IServiceProvider services) { Type resultType = this.ResultType; MyLeftChild.Emit(ilg, services); ImplicitConverter.EmitImplicitConvert(MyLeftChild.ResultType, resultType, ilg); MyRightChild.Emit(ilg, services); ImplicitConverter.EmitImplicitConvert(MyRightChild.ResultType, resultType, ilg); ilg.Emit(OpCodes.Xor); }
private bool IsValidCast(Type sourceType, Type destType) { if (object.ReferenceEquals(sourceType, destType)) { // Identity cast always succeeds return(true); } else if (destType.IsAssignableFrom(sourceType) == true) { // Cast is already implicitly valid return(true); } else if (ImplicitConverter.EmitImplicitConvert(sourceType, destType, null) == true) { // Cast is already implicitly valid return(true); } else if (IsCastableNumericType(sourceType) & IsCastableNumericType(destType)) { // Explicit cast of numeric types always succeeds return(true); } else if (sourceType.IsEnum == true | destType.IsEnum == true) { return(this.IsValidExplicitEnumCast(sourceType, destType)); } else if ((this.GetExplictOverloadedOperator(sourceType, destType) != null)) { // Overloaded explict cast exists return(true); } if (sourceType.IsValueType == true) { // If we get here then the cast always fails since we are either casting one value type to another // or a value type to an invalid reference type return(false); } else { if (destType.IsValueType == true) { // Reference type to value type // Can only succeed if the reference type is a base of the value type or // it is one of the interfaces the value type implements Type[] interfaces = destType.GetInterfaces(); return(IsBaseType(destType, sourceType) == true | System.Array.IndexOf(interfaces, sourceType) != -1); } else { // Reference type to reference type return(this.IsValidExplicitReferenceCast(sourceType, destType)); } } }
private void EmitConditional(FleeILGenerator ilg, IServiceProvider services, BranchManager bm) { Label falseLabel = bm.FindLabel("falseLabel"); Label endLabel = bm.FindLabel("endLabel"); // Emit the condition MyCondition.Emit(ilg, services); // On false go to the false operand if (ilg.IsTemp == true) { bm.AddBranch(ilg, falseLabel); ilg.Emit(OpCodes.Brfalse_S, falseLabel); } else if (bm.IsLongBranch(ilg, falseLabel) == false) { ilg.Emit(OpCodes.Brfalse_S, falseLabel); } else { ilg.Emit(OpCodes.Brfalse, falseLabel); } // Emit the true operand MyWhenTrue.Emit(ilg, services); ImplicitConverter.EmitImplicitConvert(MyWhenTrue.ResultType, MyResultType, ilg); // Jump to end if (ilg.IsTemp == true) { bm.AddBranch(ilg, endLabel); ilg.Emit(OpCodes.Br_S, endLabel); } else if (bm.IsLongBranch(ilg, endLabel) == false) { ilg.Emit(OpCodes.Br_S, endLabel); } else { ilg.Emit(OpCodes.Br, endLabel); } bm.MarkLabel(ilg, falseLabel); ilg.MarkLabel(falseLabel); // Emit the false operand MyWhenFalse.Emit(ilg, services); ImplicitConverter.EmitImplicitConvert(MyWhenFalse.ResultType, MyResultType, ilg); // Fall through to end bm.MarkLabel(ilg, endLabel); ilg.MarkLabel(endLabel); }
private void SetupArrayIndexer() { MyIndexerElement = MyIndexerElements[0]; if (MyIndexerElements.Count > 1) { base.ThrowCompileException(CompileErrorResourceKeys.MultiArrayIndexNotSupported, CompileExceptionReason.TypeMismatch); } else if (ImplicitConverter.EmitImplicitConvert(MyIndexerElement.ResultType, typeof(Int32), null) == false) { base.ThrowCompileException(CompileErrorResourceKeys.ArrayIndexersMustBeOfType, CompileExceptionReason.TypeMismatch, typeof(Int32).Name); } }
private void EmitCast(FleeILGenerator ilg, Type sourceType, Type destType, IServiceProvider services) { MethodInfo explicitOperator = this.GetExplictOverloadedOperator(sourceType, destType); if (object.ReferenceEquals(sourceType, destType)) { // Identity cast; do nothing return; } else if ((explicitOperator != null)) { ilg.Emit(OpCodes.Call, explicitOperator); } else if (sourceType.IsEnum == true | destType.IsEnum == true) { this.EmitEnumCast(ilg, sourceType, destType, services); } else if (ImplicitConverter.EmitImplicitConvert(sourceType, destType, ilg) == true) { // Implicit numeric cast; do nothing return; } else if (IsCastableNumericType(sourceType) & IsCastableNumericType(destType)) { // Explicit numeric cast EmitExplicitNumericCast(ilg, sourceType, destType, services); } else if (sourceType.IsValueType == true) { Debug.Assert(destType.IsValueType == false, "expecting reference type"); ilg.Emit(OpCodes.Box, sourceType); } else { if (destType.IsValueType == true) { // Reference type to value type ilg.Emit(OpCodes.Unbox_Any, destType); } else { // Reference type to reference type if (destType.IsAssignableFrom(sourceType) == false) { // Only emit cast if it is an explicit cast ilg.Emit(OpCodes.Castclass, destType); } } } }
public override void Emit(FleeILGenerator ilg, IServiceProvider services) { MyChild.Emit(ilg, services); ImplicitConverter.EmitImplicitConvert(MyChild.ResultType, MyResultType, ilg); ExpressionOptions options = services.GetService(typeof(ExpressionOptions)) as ExpressionOptions; if (options.IsGeneric == false) { ImplicitConverter.EmitImplicitConvert(MyResultType, typeof(object), ilg); } ilg.Emit(OpCodes.Ret); }
// Emit the arguments to a regular method call private void EmitRegularFunctionInternal(ParameterInfo[] parameters, ExpressionElement[] elements, FleeILGenerator ilg, IServiceProvider services) { Debug.Assert(parameters.Length == elements.Length, "argument count mismatch"); // Emit each element and any required conversions to the actual parameter type for (int i = 0; i <= parameters.Length - 1; i++) { ExpressionElement element = elements[i]; ParameterInfo pi = parameters[i]; element.Emit(ilg, services); bool success = ImplicitConverter.EmitImplicitConvert(element.ResultType, pi.ParameterType, ilg); Debug.Assert(success, "conversion failed"); } }
private static bool AreValidArgumentsForParameters(Type[] argTypes, ParameterInfo[] parameters) { Debug.Assert(argTypes.Length == parameters.Length); // Match if every given argument is implicitly convertible to the method's corresponding parameter for (int i = 0; i <= argTypes.Length - 1; i++) { if (ImplicitConverter.EmitImplicitConvert(argTypes[i], parameters[i].ParameterType, null) == false) { return(false); } } return(true); }
private void EmitCollectionIn(FleeILGenerator ilg, IServiceProvider services) { // Get the contains method MethodInfo mi = this.GetCollectionContainsMethod(); ParameterInfo p1 = mi.GetParameters()[0]; // Load the collection MyTargetCollectionElement.Emit(ilg, services); // Load the argument MyOperand.Emit(ilg, services); // Do an implicit convert if necessary ImplicitConverter.EmitImplicitConvert(MyOperand.ResultType, p1.ParameterType, ilg); // Call the contains method ilg.Emit(OpCodes.Callvirt, mi); }
public override MethodBase SelectMethod(BindingFlags bindingAttr, MethodBase[] match, System.Type[] types, ParameterModifier[] modifiers) { foreach (MethodInfo mi in match) { ParameterInfo[] parameters = mi.GetParameters(); bool leftValid = ImplicitConverter.EmitImplicitConvert(MyLeftType, parameters[0].ParameterType, null); bool rightValid = ImplicitConverter.EmitImplicitConvert(MyRightType, parameters[1].ParameterType, null); if (leftValid == true & rightValid == true) { return(mi); } } return(null); }
private void EmitArrayLoad(FleeILGenerator ilg, IServiceProvider services) { MyIndexerElement.Emit(ilg, services); ImplicitConverter.EmitImplicitConvert(MyIndexerElement.ResultType, typeof(Int32), ilg); Type elementType = this.ResultType; if (elementType.IsValueType == false) { // Simple reference load ilg.Emit(OpCodes.Ldelem_Ref); } else { this.EmitValueTypeArrayLoad(ilg, elementType); } }
public override void Emit(FleeILGenerator ilg, IServiceProvider services) { Type resultType = this.ResultType; if (object.ReferenceEquals(resultType, typeof(bool))) { this.DoEmitLogical(ilg, services); } else { MyLeftChild.Emit(ilg, services); ImplicitConverter.EmitImplicitConvert(MyLeftChild.ResultType, resultType, ilg); MyRightChild.Emit(ilg, services); ImplicitConverter.EmitImplicitConvert(MyRightChild.ResultType, resultType, ilg); EmitBitwiseOperation(ilg, MyOperation); } }
public override void Emit(FleeILGenerator ilg, IServiceProvider services) { Type resultType = this.ResultType; MyChild.Emit(ilg, services); ImplicitConverter.EmitImplicitConvert(MyChild.ResultType, resultType, ilg); MethodInfo mi = Utility.GetSimpleOverloadedOperator("UnaryNegation", resultType, resultType); if (mi == null) { ilg.Emit(OpCodes.Neg); } else { ilg.Emit(OpCodes.Call, mi); } }
private void ResolveForCollectionSearch() { // Try to find a collection type MyTargetCollectionType = this.GetTargetCollectionType(); if (MyTargetCollectionType == null) { base.ThrowCompileException(CompileErrorResourceKeys.SearchArgIsNotKnownCollectionType, CompileExceptionReason.TypeMismatch, MyTargetCollectionElement.ResultType.Name); } // Validate that the operand type is compatible with the collection MethodInfo mi = this.GetCollectionContainsMethod(); ParameterInfo p1 = mi.GetParameters()[0]; if (ImplicitConverter.EmitImplicitConvert(MyOperand.ResultType, p1.ParameterType, null) == false) { base.ThrowCompileException(CompileErrorResourceKeys.OperandNotConvertibleToCollectionType, CompileExceptionReason.TypeMismatch, MyOperand.ResultType.Name, p1.ParameterType.Name); } }
private bool IsParamArrayMatch(Type[] argTypes, ParameterInfo[] parameters, ParameterInfo paramArrayParameter) { // Get the count of arguments before the paramArray parameter int fixedParameterCount = paramArrayParameter.Position; Type[] fixedArgTypes = new Type[fixedParameterCount]; ParameterInfo[] fixedParameters = new ParameterInfo[fixedParameterCount]; // Get the argument types and parameters before the paramArray System.Array.Copy(argTypes, fixedArgTypes, fixedParameterCount); System.Array.Copy(parameters, fixedParameters, fixedParameterCount); // If the fixed arguments don't match, we are not a match if (AreValidArgumentsForParameters(fixedArgTypes, fixedParameters) == false) { return(false); } // Get the type of the paramArray ParamArrayElementType = paramArrayParameter.ParameterType.GetElementType(); // Get the types of the arguments passed to the paramArray Type[] paramArrayArgTypes = new Type[argTypes.Length - fixedParameterCount]; System.Array.Copy(argTypes, fixedParameterCount, paramArrayArgTypes, 0, paramArrayArgTypes.Length); // Check each argument foreach (Type argType in paramArrayArgTypes) { if (ImplicitConverter.EmitImplicitConvert(argType, ParamArrayElementType, null) == false) { return(false); } } MyFixedArgTypes = fixedArgTypes; MyParamArrayArgTypes = paramArrayArgTypes; // They all match, so we are a match return(true); }
// Load a PropertyDescriptor based property private void EmitVirtualPropertyLoad(FleeILGenerator ilg) { // The previous value is already on the top of the stack but we need it at the bottom // Get a temporary local index int index = ilg.GetTempLocalIndex(MyPrevious.ResultType); // Store the previous value there Utility.EmitStoreLocal(ilg, index); // Load the variable collection EmitLoadVariables(ilg); // Load the property name ilg.Emit(OpCodes.Ldstr, MyName); // Load the previous value and convert it to object Utility.EmitLoadLocal(ilg, index); ImplicitConverter.EmitImplicitConvert(MyPrevious.ResultType, typeof(object), ilg); // Call the method to get the actual value MethodInfo mi = VariableCollection.GetVirtualPropertyLoadMethod(this.ResultType); this.EmitMethodCall(mi, ilg); }