private ClassHierarchyNode FindGreatestCommonDescendant(ICollection <ClassHierarchyNode> typeNodes) { V_0 = null; V_1 = 0x7fffffff; V_2 = typeNodes.GetEnumerator(); try { while (V_2.MoveNext()) { V_3 = V_2.get_Current(); V_4 = ExpressionTypeInferer.GetTypeIndex(V_3.get_NodeType()); if (V_4 >= V_1) { continue; } V_1 = V_4; V_0 = V_3; } } finally { if (V_2 != null) { V_2.Dispose(); } } return(V_0); }
protected override ClassHierarchyNode FindLowestCommonAncestor(ICollection <ClassHierarchyNode> typeNodes) { V_0 = null; V_1 = -2147483648; V_2 = typeNodes.GetEnumerator(); try { while (V_2.MoveNext()) { V_3 = V_2.get_Current(); V_4 = ExpressionTypeInferer.GetTypeIndex(V_3.get_NodeType()); if (V_4 <= V_1) { continue; } V_1 = V_4; V_0 = V_3; } } finally { if (V_2 != null) { V_2.Dispose(); } } return(V_0); }
private bool IsAssignable(TypeReference toAssign, TypeReference recipient) { if (!toAssign.get_IsPrimitive() || !recipient.get_IsPrimitive()) { return(true); } stackVariable6 = ExpressionTypeInferer.GetTypeIndex(toAssign); return(stackVariable6 + 1 == ExpressionTypeInferer.GetTypeIndex(recipient)); }
/// <summary> /// Checks if one primitive type is Directly smaller than the other. /// </summary> /// <param name="toAssign">The supposed smaller type.</param> /// <param name="recipient">The supposed bigger type.</param> /// <returns></returns> private bool IsAssignable(TypeReference toAssign, TypeReference recipient) { ///This method handles assignability between primitive types only. if (!toAssign.IsPrimitive || !recipient.IsPrimitive) { return(true); } int index = ExpressionTypeInferer.GetTypeIndex(toAssign); int index2 = ExpressionTypeInferer.GetTypeIndex(recipient); return(index + 1 == index2); }
/// <summary> /// As integer values can be ordered depending on their size, the graph algorithm used in TypeInferer isn't needed here. /// Instead, we might use the indexes to determine which is the smallest type big enough to contain every type provided in /// <paramref name="typeNodes"/>. /// </summary> /// <param name="typeNodes">The list of types.</param> /// <returns>The common parent node.</returns> protected override ClassHierarchyNode FindLowestCommonAncestor(ICollection <ClassHierarchyNode> typeNodes) { ClassHierarchyNode result = null; int maxIndex = Int32.MinValue; foreach (ClassHierarchyNode node in typeNodes) { int currentIndex = ExpressionTypeInferer.GetTypeIndex(node.NodeType); if (currentIndex > maxIndex) { maxIndex = currentIndex; result = node; } } return(result); }
internal static TypeReference GetContainingType(TypeDefinition leftType, TypeDefinition rightType) { if ((object)leftType == (object)rightType) { return(rightType); } if (leftType == null) { return(rightType); } if (rightType == null) { return(leftType); } if (ExpressionTypeInferer.GetTypeIndex(leftType) > ExpressionTypeInferer.GetTypeIndex(rightType)) { return(leftType); } return(rightType); }
/// <summary> /// Determines if the use of <paramref name="variable"/> in <paramref name="useExpression"/> requires a cast. /// </summary> /// <param name="useExpression">The expression being checked.</param> /// <param name="variable">The variable that might need to be casted.</param> private void AddCastIfNeeded(Expression useExpression, VariableReference variable) { switch (useExpression.CodeNodeType) { case CodeNodeType.MethodInvocationExpression: MethodInvocationExpression miEx = useExpression as MethodInvocationExpression; Expression argument = miEx.Arguments.FirstOrDefault(x => x.CodeNodeType == CodeNodeType.VariableReferenceExpression && (x as VariableReferenceExpression).Variable == variable); if (argument != null) { ///The variable is passed as argument to the method. int argumentIndex = miEx.Arguments.IndexOf(argument); TypeReference argumentType = miEx.MethodExpression.Method.Parameters[argumentIndex].ResolveParameterType(miEx.MethodExpression.Method); if (!IsSubtype(argumentType, variable.VariableType)) { if (argumentType.IsPrimitive && variable.VariableType.IsPrimitive) { ///Integer values are not in inheritance relations. Some of them, however, can be expanded to bigger types ///automatically, without the addition of a cast, i.e. Byte variable can be passed as int parameter without the ///need to include a cast. TypeReference containingType = ExpressionTypeInferer.GetContainingType(argumentType.Resolve(), variable.VariableType.Resolve()); if (containingType.FullName == argumentType.FullName) { ///Then the type of the argument contains the type of the variable, thus no cast is needed. return; } } ///Then a cast is needed. miEx.Arguments[argumentIndex] = new CastExpression(argument, argumentType, null); ///This should be enough to update the expression everywhere it is seen. } } else { /// Then the variable is the object from which the method is called /// variable.SomeMethod(...); Expression target = miEx.MethodExpression.Target; if (target.CodeNodeType == CodeNodeType.VariableReferenceExpression && (target as VariableReferenceExpression).Variable == variable) { TypeReference targetType = miEx.MethodExpression.Method.DeclaringType; if (!IsSubtype(targetType, variable.VariableType)) { miEx.MethodExpression.Target = new CastExpression(target, targetType, null); } } else { ///This should not be reachable, but anyway. AddCastIfNeeded(target, variable); } } break; case CodeNodeType.BinaryExpression: BinaryExpression binEx = useExpression as BinaryExpression; if (binEx.Operator == BinaryOperator.Assign) { if (binEx.Right.CodeNodeType == CodeNodeType.VariableReferenceExpression && (binEx.Right as VariableReferenceExpression).Variable == variable) { TypeReference assignedAs = binEx.Left.ExpressionType; ///binex.Right should be VariableReferenceExpression to 'variable'. if (!IsSubtype(assignedAs, variable.VariableType)) { binEx.Right = new CastExpression(binEx.Right, assignedAs, null); } } } break; //default: //throw new NotSupportedException("Not supported cast expression."); } }
/// <summary> /// Finds the smallest type from the given types. /// </summary> /// <param name="typeNodes">The list of type nodes.</param> /// <returns>Returns the smallest type.</returns> private ClassHierarchyNode FindGreatestCommonDescendant(ICollection <ClassHierarchyNode> typeNodes) { ClassHierarchyNode result = null; int minIndex = Int32.MaxValue; foreach (ClassHierarchyNode node in typeNodes) { int currentIndex = ExpressionTypeInferer.GetTypeIndex(node.NodeType); if (currentIndex < minIndex) { minIndex = currentIndex; result = node; } } return(result); //Stack<ClassHierarchyNode> possibleGcdOrdered = new Stack<ClassHierarchyNode>(); //HashSet<ClassHierarchyNode> possibleGcdSearchable = new HashSet<ClassHierarchyNode>(); //foreach (ClassHierarchyNode node in typeNodes) //{ // if (possibleGcdOrdered.Count == 0) //first pass // { // ClassHierarchyNode currentSubtype = node; // while (currentSubtype != null) // { // possibleGcdOrdered.Push(currentSubtype); // possibleGcdSearchable.Add(currentSubtype); // ClassHierarchyNode nextSubtype = null; // foreach (ClassHierarchyNode x in currentSubtype.SubTypes) // { // if (x.IsHardNode) // { // nextSubtype = x; // break; // } // } // currentSubtype = nextSubtype; // } // } // else // { // ClassHierarchyNode firstSubtype = node; // while (!possibleGcdSearchable.Contains(firstSubtype)) // { // //should not reach null, as Int32 is the ultimate GCD // ClassHierarchyNode nextSubtype = null; // foreach (ClassHierarchyNode x in firstSubtype.SubTypes) // { // if (x.IsHardNode) // { // nextSubtype = x; // break; // } // } // firstSubtype = nextSubtype; // } // while (possibleGcdOrdered.Peek() != firstSubtype) // { // ClassHierarchyNode removed = possibleGcdOrdered.Pop(); // possibleGcdSearchable.Remove(removed); // } // } //} //return possibleGcdOrdered.Peek(); }
private void AddCastIfNeeded(Expression useExpression, VariableReference variable) { V_0 = new TypeInferer.u003cu003ec__DisplayClass8_0(); V_0.variable = variable; V_4 = useExpression.get_CodeNodeType(); if (V_4 == 19) { V_1 = useExpression as MethodInvocationExpression; V_2 = V_1.get_Arguments().FirstOrDefault <Expression>(new Func <Expression, bool>(V_0.u003cAddCastIfNeededu003eb__0)); if (V_2 == null) { V_7 = V_1.get_MethodExpression().get_Target(); if (V_7.get_CodeNodeType() != 26 || (object)(V_7 as VariableReferenceExpression).get_Variable() != (object)V_0.variable) { this.AddCastIfNeeded(V_7, V_0.variable); return; } V_8 = V_1.get_MethodExpression().get_Method().get_DeclaringType(); if (!this.IsSubtype(V_8, V_0.variable.get_VariableType())) { V_1.get_MethodExpression().set_Target(new ExplicitCastExpression(V_7, V_8, null)); return; } } else { V_5 = V_1.get_Arguments().IndexOf(V_2); V_6 = V_1.get_MethodExpression().get_Method().get_Parameters().get_Item(V_5).ResolveParameterType(V_1.get_MethodExpression().get_Method()); if (!this.IsSubtype(V_6, V_0.variable.get_VariableType())) { if (V_6.get_IsPrimitive() && V_0.variable.get_VariableType().get_IsPrimitive() && String.op_Equality(ExpressionTypeInferer.GetContainingType(V_6.Resolve(), V_0.variable.get_VariableType().Resolve()).get_FullName(), V_6.get_FullName())) { return; } V_1.get_Arguments().set_Item(V_5, new ExplicitCastExpression(V_2, V_6, null)); return; } } } else { if (V_4 != 24) { return; } V_3 = useExpression as BinaryExpression; if (V_3.get_Operator() == 26 && V_3.get_Right().get_CodeNodeType() == 26 && (object)(V_3.get_Right() as VariableReferenceExpression).get_Variable() == (object)V_0.variable) { V_9 = V_3.get_Left().get_ExpressionType(); if (!this.IsSubtype(V_9, V_0.variable.get_VariableType())) { V_3.set_Right(new ExplicitCastExpression(V_3.get_Right(), V_9, null)); } } } return; }