/// <summary> /// Compute comparability for a method's parameters based on the types of the parameters. Two parameters /// are considered comparable if one can be assigned to the other. /// </summary> /// <param name="parameters">the parameters</param> /// <seealso cref="TypeHelper.TypesAreAssignmentCompatible"/> /// <returns>comparability sets for the parameters</returns> public static HashSet <HashSet <string> > ParameterTypeComparability(IEnumerable <IParameterDefinition> parameters) { Contract.Requires(parameters != null); Contract.Ensures(Contract.Result <HashSet <HashSet <string> > >() != null); Dictionary <IParameterDefinition, int> ids = new Dictionary <IParameterDefinition, int>(); DisjointSets cmp = new DisjointSets(); foreach (var p in parameters) { ids.Add(p, cmp.AddElement()); } foreach (var lhs in parameters) { Contract.Assume(ids.ContainsKey(lhs), "Error tracking parameter " + lhs.Name); foreach (var rhs in parameters) { Contract.Assume(ids.ContainsKey(rhs), "Error tracking parameter " + rhs.Name); if (TypeHelper.TypesAreAssignmentCompatible(lhs.Type.ResolvedType, rhs.Type.ResolvedType, true)) { cmp.Union(cmp.FindSet(ids[lhs]), cmp.FindSet(ids[rhs])); } } } var result = new HashSet <HashSet <string> >(ids.Keys.GroupBy(p => cmp.FindSet(ids[p])).Select(g => new HashSet <string>(g.Select(p => p.Name.Value)))); return(result); }
private int GetId(string name) { Contract.Requires(!string.IsNullOrEmpty(name)); Contract.Ensures(ids.ContainsKey(name) && Contract.Result <int>() == ids[name]); Contract.Ensures(Contract.Result <int>() >= 0); if (!ids.ContainsKey(name)) { int id = comparability.AddElement(); ids.Add(name, id); return(id); } else { return(ids[name]); } }
public TypeSummary(string assemblyQualifiedName, NameBuilder names, IEnumerable <MethodVisitor> methods) { Contract.Requires(!string.IsNullOrEmpty(assemblyQualifiedName)); Contract.Requires(names != null); Contract.Requires(methods != null); Contract.Ensures(ids.Keys.SetEquals(names.ThisNames())); this.AssemblyQualifiedName = assemblyQualifiedName; // give a union-find id to each instance expression name foreach (var name in names.ThisNames()) { ids.Add(name, comparability.AddElement()); } // union the sets, according to each method's opinion foreach (var name in names.ThisNames()) { HashSet <string> indexOpinion = new HashSet <string>(); foreach (var method in methods) { var opinion = method.ComparabilitySet(name).Intersect(ids.Keys); string last = null; foreach (var other in opinion) { if (last != null) { comparability.Union(comparability.FindSet(ids[last]), comparability.FindSet(ids[name])); } last = other; } indexOpinion.UnionWith(method.IndexComparabilityOpinion(name).Intersect(names.ThisNames())); } if (indexOpinion.Count > 0) { arrayIndexes.Add(name, indexOpinion); } } }
public MethodVisitor(IMethodDefinition method, IMetadataHost host, NameBuilder names) { Contract.Requires(method != null); Contract.Requires(names != null); Contract.Requires(host != null); Contract.Ensures(Names == names); Contract.Ensures(Method == method); Contract.Ensures(Host == host); Names = names; Method = method; Host = host; ReferencedTypes = new Dictionary <IExpression, ITypeReference>(); ids.Add("return", comparability.AddElement()); foreach (var param in Method.Parameters) { ids.Add(param.Name.Value, comparability.AddElement()); } }