public override void Emit(FleeILGenerator ilg, IServiceProvider services) { MethodInfo overloadedMethod = this.GetOverloadedAndOrOperator(); if ((overloadedMethod != null)) { // Emit a call to an overloaded operator this.EmitOverloadedOperatorCall(overloadedMethod, ilg, services); } else { 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 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); } }
/// <summary> /// Emit elements into an array /// </summary> /// <param name="elements"></param> /// <param name="arrayElementType"></param> /// <param name="ilg"></param> /// <param name="services"></param> private static void EmitElementArrayLoad(ExpressionElement[] elements, Type arrayElementType, FleeILGenerator ilg, IServiceProvider services) { // Load the array length LiteralElement.EmitLoad(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.EmitLoad(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 ConditionalElement(BaseExpressionElement condition, BaseExpressionElement whenTrue, BaseExpressionElement whenFalse) { this.condition = condition; this.whenTrue = whenTrue; this.whenFalse = whenFalse; if (!ReferenceEquals(this.condition.ResultType, typeof(bool))) { throw CreateCompileException(CompileErrors.FirstArgNotBoolean, CompileExceptionReason.TypeMismatch); } // The result type is the type that is common to the true/false operands if (ImplicitConverter.EmitImplicitConvert(this.whenFalse.ResultType, this.whenTrue.ResultType, null)) { resultType = this.whenTrue.ResultType; } else if (ImplicitConverter.EmitImplicitConvert(this.whenTrue.ResultType, this.whenFalse.ResultType, null)) { resultType = this.whenFalse.ResultType; } else { throw CreateCompileException(CompileErrors.NeitherArgIsConvertibleToTheOther, CompileExceptionReason.TypeMismatch, this.whenTrue.ResultType.Name, this.whenFalse.ResultType.Name); } }
private void Validate() { if (ImplicitConverter.EmitImplicitConvert(_child.ResultType, _resultType, null) == false) { throw CreateCompileException(CompileErrors.CannotConvertTypeToExpressionResult, CompileExceptionReason.TypeMismatch, _child.ResultType.Name, _resultType.Name); } }
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"); }
/// <summary> /// Emit elements into an array /// </summary> private static void EmitElementArrayLoad(BaseExpressionElement[] elements, Type arrayElementType, YaleIlGenerator ilg, ExpressionContext context) { // Load the array length LiteralElement.EmitLoad(elements.Length, ilg); // Create the array ilg.Emit(OpCodes.Newarr, arrayElementType); // Store the new array in a unique local and remember the index var local = ilg.DeclareLocal(arrayElementType.MakeArrayType()); var arrayLocalIndex = local.LocalIndex; Utility.EmitStoreLocal(ilg, arrayLocalIndex); for (var i = 0; i <= elements.Length - 1; i++) { // Load the array Utility.EmitLoadLocal(ilg, arrayLocalIndex); // Load the index LiteralElement.EmitLoad(i, ilg); // Emit the element (with any required conversions) var element = elements[i]; element.Emit(ilg, context); ImplicitConverter.EmitImplicitConvert(element.ResultType, arrayElementType, ilg); // Store it into the array Utility.EmitArrayStore(ilg, arrayElementType); } // Load the array Utility.EmitLoadLocal(ilg, arrayLocalIndex); }
private void Validate() { if (ImplicitConverter.EmitImplicitConvert(_myChild.ResultType, _myResultType, null) == false) { base.ThrowCompileException(CompileErrorResourceKeys.CannotConvertTypeToExpressionResult, CompileExceptionReason.TypeMismatch, _myChild.ResultType.Name, _myResultType.Name); } }
private void EmitConditional(FleeILGenerator ilg, IServiceProvider services) { Label falseLabel = ilg.DefineLabel(); Label endLabel = ilg.DefineLabel(); // Emit the condition _myCondition.Emit(ilg, services); // On false go to the false operand ilg.EmitBranchFalse(falseLabel); // Emit the true operand _myWhenTrue.Emit(ilg, services); ImplicitConverter.EmitImplicitConvert(_myWhenTrue.ResultType, _myResultType, ilg); // Jump to end ilg.EmitBranch(endLabel); ilg.MarkLabel(falseLabel); // Emit the false operand _myWhenFalse.Emit(ilg, services); ImplicitConverter.EmitImplicitConvert(_myWhenFalse.ResultType, _myResultType, ilg); // Fall through to end ilg.MarkLabel(endLabel); }
/// <summary> /// Emit a string concatenation /// </summary> /// <param name="ilg"></param> /// <param name="services"></param> private void EmitStringConcat(FleeILGenerator ilg, IServiceProvider services) { Type argType = default(Type); System.Reflection.MethodInfo concatMethodInfo = default(System.Reflection.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(BaseExpressionElement child, Type resultType, YaleIlGenerator ilg, ExpressionContext context) { child.Emit(ilg, context); var converted = ImplicitConverter.EmitImplicitConvert(child.ResultType, resultType, ilg); Debug.Assert(converted, "convert failed"); }
private bool IsValidCast(Type sourceType, Type destType) { if (ReferenceEquals(sourceType, destType)) { // Identity cast always succeeds return(true); } if (destType.IsAssignableFrom(sourceType)) { // Cast is already implicitly valid return(true); } if (ImplicitConverter.EmitImplicitConvert(sourceType, destType, null)) { // Cast is already implicitly valid return(true); } if (IsCastableNumericType(sourceType) & IsCastableNumericType(destType)) { // Explicit cast of numeric types always succeeds return(true); } if (sourceType.IsEnum || destType.IsEnum) { return(IsValidExplicitEnumCast(sourceType, destType)); } if (GetExplictOverloadedOperator(sourceType, destType) != null) { // Overloaded explict cast exists return(true); } if (sourceType.IsValueType) { // 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); } if (destType.IsValueType) { // 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 var interfaces = destType.GetInterfaces(); return(IsBaseType(destType, sourceType) || Array.IndexOf(interfaces, sourceType) != -1); } // Reference type to reference type return(IsValidExplicitReferenceCast(sourceType, destType)); }
public override void Emit(YaleIlGenerator ilGenerator, ExpressionContext context) { var resultType = ResultType; LeftChild.Emit(ilGenerator, context); ImplicitConverter.EmitImplicitConvert(LeftChild.ResultType, resultType, ilGenerator); RightChild.Emit(ilGenerator, context); ImplicitConverter.EmitImplicitConvert(RightChild.ResultType, resultType, ilGenerator); ilGenerator.Emit(OpCodes.Xor); }
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 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 EmitConditional(YaleIlGenerator ilg, ExpressionContext context, BranchManager branchManager) { var falseLabel = branchManager.FindLabel("falseLabel"); var endLabel = branchManager.FindLabel("endLabel"); // Emit the condition condition.Emit(ilg, context); // On false go to the false operand if (ilg.IsTemp) { branchManager.AddBranch(ilg, falseLabel); ilg.Emit(OpCodes.Brfalse_S, falseLabel); } else if (branchManager.IsLongBranch(ilg, falseLabel) == false) { ilg.Emit(OpCodes.Brfalse_S, falseLabel); } else { ilg.Emit(OpCodes.Brfalse, falseLabel); } // Emit the true operand whenTrue.Emit(ilg, context); ImplicitConverter.EmitImplicitConvert(whenTrue.ResultType, resultType, ilg); // Jump to end if (ilg.IsTemp) { branchManager.AddBranch(ilg, endLabel); ilg.Emit(OpCodes.Br_S, endLabel); } else if (branchManager.IsLongBranch(ilg, endLabel) == false) { ilg.Emit(OpCodes.Br_S, endLabel); } else { ilg.Emit(OpCodes.Br, endLabel); } branchManager.MarkLabel(ilg, falseLabel); ilg.MarkLabel(falseLabel); // Emit the false operand whenFalse.Emit(ilg, context); ImplicitConverter.EmitImplicitConvert(whenFalse.ResultType, resultType, ilg); // Fall through to end branchManager.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(YaleIlGenerator ilg, Type sourceType, Type destType, ExpressionContext context) { var explicitOperator = GetExplictOverloadedOperator(sourceType, destType); if (ReferenceEquals(sourceType, destType)) { // Identity cast; do nothing return; } if (explicitOperator != null) { ilg.Emit(OpCodes.Call, explicitOperator); } else if (sourceType.IsEnum | destType.IsEnum) { EmitEnumCast(ilg, sourceType, destType, context); } else if (ImplicitConverter.EmitImplicitConvert(sourceType, destType, ilg)) { // Implicit numeric cast; do nothing return; } else if (IsCastableNumericType(sourceType) & IsCastableNumericType(destType)) { // Explicit numeric cast EmitExplicitNumericCast(ilg, sourceType, destType, context); } else if (sourceType.IsValueType) { Debug.Assert(destType.IsValueType == false, "expecting reference type"); ilg.Emit(OpCodes.Box, sourceType); } else { if (destType.IsValueType) { // 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); } } } }
/// <summary> /// Emit the arguments to a regular method call /// </summary> private void EmitRegularFunctionInternal(ParameterInfo[] parameters, BaseExpressionElement[] elements, YaleIlGenerator ilg, ExpressionContext context) { Debug.Assert(parameters.Length == elements.Length, "argument count mismatch"); // Emit each element and any required conversions to the actual parameter type for (var i = 0; i <= parameters.Length - 1; i++) { var element = elements[i]; var pi = parameters[i]; element.Emit(ilg, context); var success = ImplicitConverter.EmitImplicitConvert(element.ResultType, pi.ParameterType, ilg); Debug.Assert(success, "conversion failed"); } }
//Entry point of IL Creation public override void Emit(YaleIlGenerator ilGenerator, ExpressionContext context) { _child.Emit(ilGenerator, context); ImplicitConverter.EmitImplicitConvert(_child.ResultType, _resultType, ilGenerator); //Todo: Verify if this convert stuff works if ("isGeneric".Equals("false")) { ImplicitConverter.EmitImplicitConvert(_resultType, typeof(object), ilGenerator); } ilGenerator.Emit(OpCodes.Ret); }
/// <summary> /// Emit the arguments to a regular method call /// </summary> /// <param name="parameters"></param> /// <param name="elements"></param> /// <param name="ilg"></param> /// <param name="services"></param> 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"); } }
public override void Emit(FleeILGenerator ilg, IServiceProvider services) { _myChild.Emit(ilg, services); ImplicitConverter.EmitImplicitConvert(_myChild.ResultType, _myResultType, ilg); ExpressionOptions options = (ExpressionOptions)services.GetService(typeof(ExpressionOptions)); if (options.IsGeneric == false) { ImplicitConverter.EmitImplicitConvert(_myResultType, typeof(object), ilg); } ilg.Emit(OpCodes.Ret); }
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); } } } }
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); }
private void EmitCollectionIn(YaleIlGenerator ilg, ExpressionContext context) { // Get the contains method var methodInfo = GetCollectionContainsMethod(); var firstParameter = methodInfo.GetParameters()[0]; // Load the collection targetCollectionElement.Emit(ilg, context); // Load the argument operand.Emit(ilg, context); // Do an implicit convert if necessary ImplicitConverter.EmitImplicitConvert(operand.ResultType, firstParameter.ParameterType, ilg); // Call the contains method ilg.Emit(OpCodes.Callvirt, methodInfo); }
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(YaleIlGenerator ilGenerator, ExpressionContext context) { var resultType = ResultType; if (ReferenceEquals(resultType, typeof(bool))) { DoEmitLogical(ilGenerator, context); } else { LeftChild.Emit(ilGenerator, context); ImplicitConverter.EmitImplicitConvert(LeftChild.ResultType, resultType, ilGenerator); RightChild.Emit(ilGenerator, context); ImplicitConverter.EmitImplicitConvert(RightChild.ResultType, resultType, ilGenerator); EmitBitwiseOperation(ilGenerator, myOperation); } }
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); } }
private void EmitArrayLoad(YaleIlGenerator ilg, ExpressionContext context) { _indexerElement.Emit(ilg, context); ImplicitConverter.EmitImplicitConvert(_indexerElement.ResultType, typeof(Int32), ilg); var elementType = ResultType; if (elementType.IsValueType == false) { // Simple reference load ilg.Emit(OpCodes.Ldelem_Ref); } else { EmitValueTypeArrayLoad(ilg, elementType); } }
public override void Emit(YaleIlGenerator ilGenerator, ExpressionContext context) { var resultType = ResultType; MyChild.Emit(ilGenerator, context); ImplicitConverter.EmitImplicitConvert(MyChild.ResultType, resultType, ilGenerator); var methodInfo = Utility.GetSimpleOverloadedOperator(UnaryNegation, resultType, resultType); if (methodInfo == null) { ilGenerator.Emit(OpCodes.Neg); } else { ilGenerator.Emit(OpCodes.Call, methodInfo); } }