/// <summary> /// Sequentially composes a unification with a dictionary, creating a new unification. /// </summary> /// <param name="dict"> /// The dictionary representing another unification to merge.</param> /// <returns> /// The composed unification (this; <paramref name="dict"/>). /// </returns> internal ImmutableTypeMap ComposeDict(SmallDictionary <TypeParameterSymbol, TypeWithModifiers> dict) { // TODO: efficiency var dictM = new ImmutableTypeMap(dict); var result = new ImmutableTypeMap(); // We want the resulting mapping to be dict(this(x)). // Thus: // 1) For all mappings in this (this(x) != x), take our mapping, substitute with dict, and store the resulting mapping; // 2) For all mappings in dict, add them back in if they are not already in the new mapping. foreach (var ourKey in Mapping.Keys) { result.Mapping.Add(ourKey, Mapping[ourKey].CustomModifiers.IsEmpty ? dictM.SubstituteType(Mapping[ourKey].AsTypeSymbolOnly()) : Mapping[ourKey]); } foreach (var theirKey in dict.Keys) { // This means the other mapping contained this, if (result.Mapping.ContainsKey(theirKey)) { continue; } result.Mapping.Add(theirKey, dict[theirKey]); } return(result); }
/// <summary> /// Sequentially composes a unification with a dictionary, creating a new unification. /// </summary> /// <param name="dict"> /// The dictionary representing another unification to merge.</param> /// <returns> /// The composed unification (this; <paramref name="dict"/>). /// </returns> internal ImmutableTypeMap ComposeDict(SmallDictionary <TypeParameterSymbol, TypeWithModifiers> dict) { Debug.Assert(IsNormalised, "map should be normalised before composition"); // TODO: efficiency var dictM = new ImmutableTypeMap(dict); var result = new ImmutableTypeMap(); // We want the resulting mapping to be dict(this(x)). // Thus: // 1) For all mappings in this (this(x) != x), take our mapping, substitute with dict, and store the resulting mapping; // 2) For all mappings in dict, add them back in if they are not already in the new mapping. foreach (var ourKey in Mapping.Keys) { result.Mapping.Add(ourKey, Mapping[ourKey].SubstituteType(dictM)); } foreach (var theirKey in dict.Keys) { if (!result.Mapping.ContainsKey(theirKey)) { result.Mapping.Add(theirKey, dict[theirKey]); } } Debug.Assert(IsNormalised, "map should be normalised after composition"); return(result); }
/// <summary> /// Sequentially composes this map with another one, then filters out /// the set of additions to the map using the given allowed set. /// </summary> /// <param name="other">The RHS of the sequential composition.</param> /// <param name="allowed">The array of allowed type parameters.</param> /// <returns> /// The composed map, with the present keys restricted to those either /// in this map or in <paramref name="allowed"/>. /// </returns> public ImmutableTypeMap RestrictedCompose(ImmutableTypeMap other, ImmutableArray <TypeParameterSymbol> allowed) { // Don't return 'other' if we're empty. // 'other' might need restricting. if (other.IsEmpty) { return(this); } // TODO(MattWindsor91): efficiency: we're creating and disposing // of a lot of intermediate data structures here. var unfiltered = Compose(other); var rdict = new SmallDictionary <TypeParameterSymbol, TypeWithModifiers>(); // De-duplicating this is important: SmallDictionary errors // on duplicate key insertion. var allAllowed = allowed.AddRange(Mapping.Keys).Distinct(); foreach (var a in allAllowed) { if (unfiltered.Mapping.ContainsKey(a)) { rdict.Add(a, unfiltered.Mapping[a]); } } return(new ImmutableTypeMap(rdict)); }
/// <summary> /// Sequentially composes two unifications, creating a new unification. /// </summary> /// <param name="other">The RHS of the sequential composition.</param> /// <returns> /// The composed unification (this; <paramref name="other"/>). /// </returns> internal ImmutableTypeMap Compose(ImmutableTypeMap other) { if (IsEmpty) { return(other); } if (other.IsEmpty) { return(this); } return(ComposeDict(other.Mapping)); }
/// <summary> /// Sequentially composes two unifications, creating a new unification. /// </summary> /// <param name="other"> /// The RHS of the sequential composition.</param> /// <returns> /// The composed unification (this; <paramref name="other"/>). /// </returns> internal ImmutableTypeMap Compose(ImmutableTypeMap other) => ComposeDict(other.Mapping);