void PreResolveWorker(ModuleDefinition m) { Contract.Requires(m != null); if (m.RefinementBase == null) return; if (moduleUnderConstruction != null) { postTasks.Clear(); } moduleUnderConstruction = m; refinementCloner = new RefinementCloner(moduleUnderConstruction); var prev = m.RefinementBase; // Create a simple name-to-decl dictionary. Ignore any duplicates at this time. var declaredNames = new Dictionary<string, int>(); for (int i = 0; i < m.TopLevelDecls.Count; i++) { var d = m.TopLevelDecls[i]; if (!declaredNames.ContainsKey(d.Name)) { declaredNames.Add(d.Name, i); } } // Merge the declarations of prev into the declarations of m List<string> processedDecl = new List<string>(); foreach (var d in prev.TopLevelDecls) { int index; processedDecl.Add(d.Name); if (!declaredNames.TryGetValue(d.Name, out index)) { m.TopLevelDecls.Add(refinementCloner.CloneDeclaration(d, m)); } else { var nw = m.TopLevelDecls[index]; MergeTopLevelDecls(m, nw, d, index); } } // Merge the imports of prev var prevTopLevelDecls = RefinedSig.TopLevels.Values; foreach (var d in prevTopLevelDecls) { int index; if (!processedDecl.Contains(d.Name) && (declaredNames.TryGetValue(d.Name, out index))) { // if it is redefined, we need to merge them. var nw = m.TopLevelDecls[index]; MergeTopLevelDecls(m, nw, d, index); } } m.RefinementBaseSig = RefinedSig; Contract.Assert(moduleUnderConstruction == m); // this should be as it was set earlier in this method }
void PreResolveWorker(ModuleDefinition m) { Contract.Requires(m != null); if (m.RefinementBase == null) return; if (moduleUnderConstruction != null) { postTasks.Clear(); } moduleUnderConstruction = m; refinementCloner = new RefinementCloner(moduleUnderConstruction); var prev = m.RefinementBase; //copy the signature, including its opened imports refinedSigOpened = Resolver.MergeSignature(new ModuleSignature(), RefinedSig); Resolver.ResolveOpenedImports(refinedSigOpened, m.RefinementBase, false, null); // Create a simple name-to-decl dictionary. Ignore any duplicates at this time. var declaredNames = new Dictionary<string, int>(); for (int i = 0; i < m.TopLevelDecls.Count; i++) { var d = m.TopLevelDecls[i]; if (!declaredNames.ContainsKey(d.Name)) { declaredNames.Add(d.Name, i); } // TODO: This is more restrictive than is necessary, // it would be possible to disambiguate these, but it seems like // a lot of work for not much gain if (refinedSigOpened.TopLevels.ContainsKey(d.Name) && !RefinedSig.TopLevels.ContainsKey(d.Name)) { var decl = Resolver.AmbiguousTopLevelDecl.Create(m, d, refinedSigOpened.TopLevels[d.Name]); if (decl is Resolver.AmbiguousTopLevelDecl) { reporter.Error(MessageSource.RefinementTransformer, d.tok, "Base module {0} imports {1} from an opened import, so it cannot be overridden. Give this declaration a unique name to disambiguate.", prev.Name, d.Name); } } } // Merge the declarations of prev into the declarations of m List<string> processedDecl = new List<string>(); foreach (var d in prev.TopLevelDecls) { int index; processedDecl.Add(d.Name); if (!declaredNames.TryGetValue(d.Name, out index)) { m.TopLevelDecls.Add(refinementCloner.CloneDeclaration(d, m)); } else { var nw = m.TopLevelDecls[index]; MergeTopLevelDecls(m, nw, d, index); } } // Merge the imports of prev var prevTopLevelDecls = RefinedSig.TopLevels.Values; foreach (var d in prevTopLevelDecls) { int index; if (!processedDecl.Contains(d.Name) && (declaredNames.TryGetValue(d.Name, out index))) { // if it is redefined, we need to merge them. var nw = m.TopLevelDecls[index]; MergeTopLevelDecls(m, nw, d, index); } } m.RefinementBaseSig = RefinedSig; Contract.Assert(moduleUnderConstruction == m); // this should be as it was set earlier in this method }
void PreResolveWorker(ModuleDefinition m) { Contract.Requires(m != null); if (m.RefinementBase == null) return; if (moduleUnderConstruction != null) { postTasks.Clear(); } moduleUnderConstruction = m; refinementCloner = new RefinementCloner(moduleUnderConstruction); var prev = m.RefinementBase; // Create a simple name-to-decl dictionary. Ignore any duplicates at this time. var declaredNames = new Dictionary<string, int>(); for (int i = 0; i < m.TopLevelDecls.Count; i++) { var d = m.TopLevelDecls[i]; if (!declaredNames.ContainsKey(d.Name)) { declaredNames.Add(d.Name, i); } } // Merge the declarations of prev into the declarations of m foreach (var d in prev.TopLevelDecls) { int index; if (!declaredNames.TryGetValue(d.Name, out index)) { m.TopLevelDecls.Add(refinementCloner.CloneDeclaration(d, m)); } else { var nw = m.TopLevelDecls[index]; if (d is ModuleDecl) { if (!(nw is ModuleDecl)) { reporter.Error(MessageSource.RefinementTransformer, nw, "a module ({0}) must refine another module", nw.Name); } else if (!(d is ModuleFacadeDecl)) { reporter.Error(MessageSource.RefinementTransformer, nw, "a module ({0}) can only refine a module facade", nw.Name); } else { ModuleSignature original = ((ModuleFacadeDecl)d).OriginalSignature; ModuleSignature derived = null; if (nw is AliasModuleDecl) { derived = ((AliasModuleDecl)nw).Signature; } else if (nw is ModuleFacadeDecl) { derived = ((ModuleFacadeDecl)nw).Signature; } else { reporter.Error(MessageSource.RefinementTransformer, nw, "a module ({0}) can only be refined by an alias module or a module facade", d.Name); } if (derived != null) { // check that the new module refines the previous declaration if (!CheckIsRefinement(derived, original)) reporter.Error(MessageSource.RefinementTransformer, nw.tok, "a module ({0}) can only be replaced by a refinement of the original module", d.Name); } } } else if (d is OpaqueTypeDecl) { if (nw is ModuleDecl) { reporter.Error(MessageSource.RefinementTransformer, nw, "a module ({0}) must refine another module", nw.Name); } else { bool dDemandsEqualitySupport = ((OpaqueTypeDecl)d).MustSupportEquality; if (nw is OpaqueTypeDecl) { if (dDemandsEqualitySupport != ((OpaqueTypeDecl)nw).MustSupportEquality) { reporter.Error(MessageSource.RefinementTransformer, nw, "type declaration '{0}' is not allowed to change the requirement of supporting equality", nw.Name); } if (nw.TypeArgs.Count != d.TypeArgs.Count) { reporter.Error(MessageSource.RefinementTransformer, nw, "type '{0}' is not allowed to change its number of type parameters (got {1}, expected {2})", nw.Name, nw.TypeArgs.Count, d.TypeArgs.Count); } } else if (dDemandsEqualitySupport) { if (nw is ClassDecl) { // fine, as long as "nw" takes the right number of type parameters if (nw.TypeArgs.Count != d.TypeArgs.Count) { reporter.Error(MessageSource.RefinementTransformer, nw, "opaque type '{0}' is not allowed to be replaced by a class that takes a different number of type parameters (got {1}, expected {2})", nw.Name, nw.TypeArgs.Count, d.TypeArgs.Count); } } else if (nw is NewtypeDecl) { // fine, as long as "nw" does not take any type parameters if (nw.TypeArgs.Count != 0) { reporter.Error(MessageSource.RefinementTransformer, nw, "opaque type '{0}', which has {1} type argument{2}, is not allowed to be replaced by a newtype, which takes none", nw.Name, d.TypeArgs.Count, d.TypeArgs.Count == 1 ? "" : "s"); } } else if (nw is CoDatatypeDecl) { reporter.Error(MessageSource.RefinementTransformer, nw, "a type declaration that requires equality support cannot be replaced by a codatatype"); } else { Contract.Assert(nw is IndDatatypeDecl || nw is TypeSynonymDecl); if (nw.TypeArgs.Count != d.TypeArgs.Count) { reporter.Error(MessageSource.RefinementTransformer, nw, "opaque type '{0}' is not allowed to be replaced by a type that takes a different number of type parameters (got {1}, expected {2})", nw.Name, nw.TypeArgs.Count, d.TypeArgs.Count); } else { // Here, we need to figure out if the new type supports equality. But we won't know about that until resolution has // taken place, so we defer it until the PostResolve phase. var udt = UserDefinedType.FromTopLevelDecl(nw.tok, nw); postTasks.Enqueue(() => { if (!udt.SupportsEquality) { reporter.Error(MessageSource.RefinementTransformer, udt.tok, "type '{0}' is used to refine an opaque type with equality support, but '{0}' does not support equality", udt.Name); } }); } } } else if (d.TypeArgs.Count != nw.TypeArgs.Count) { reporter.Error(MessageSource.RefinementTransformer, nw, "opaque type '{0}' is not allowed to be replaced by a type that takes a different number of type parameters (got {1}, expected {2})", nw.Name, nw.TypeArgs.Count, d.TypeArgs.Count); } } } else if (nw is OpaqueTypeDecl) { reporter.Error(MessageSource.RefinementTransformer, nw, "an opaque type declaration ({0}) in a refining module cannot replace a more specific type declaration in the refinement base", nw.Name); } else if (nw is DatatypeDecl) { reporter.Error(MessageSource.RefinementTransformer, nw, "a datatype declaration ({0}) in a refinement module can only replace an opaque type declaration", nw.Name); } else if (nw is IteratorDecl) { if (d is IteratorDecl) { m.TopLevelDecls[index] = MergeIterator((IteratorDecl)nw, (IteratorDecl)d); } else { reporter.Error(MessageSource.RefinementTransformer, nw, "an iterator declaration ({0}) is a refining module cannot replace a different kind of declaration in the refinement base", nw.Name); } } else { Contract.Assert(nw is ClassDecl); if (d is DatatypeDecl) { reporter.Error(MessageSource.RefinementTransformer, nw, "a class declaration ({0}) in a refining module cannot replace a different kind of declaration in the refinement base", nw.Name); } else { m.TopLevelDecls[index] = MergeClass((ClassDecl)nw, (ClassDecl)d); } } } } Contract.Assert(moduleUnderConstruction == m); // this should be as it was set earlier in this method }