private static void LibraryUsagePostOrderTraversal( LibraryCompilationScope libraryToUse, List <LibraryCompilationScope> libraryOrderOut, HashSet <LibraryCompilationScope> usedLibraries, HashSet <LibraryCompilationScope> cycleCheck, Stack <LibraryCompilationScope> breadcrumbs) { if (usedLibraries.Contains(libraryToUse)) { return; } breadcrumbs.Push(libraryToUse); if (cycleCheck.Contains(libraryToUse)) { StringBuilder message = new StringBuilder(); message.Append("There is a dependency cycle in your libraries: "); bool first = true; foreach (LibraryCompilationScope breadcrumb in breadcrumbs) { if (first) { first = false; } else { message.Append(" -> "); } message.Append(breadcrumb.Library.ID); } throw new InvalidOperationException(message.ToString()); } cycleCheck.Add(libraryToUse); foreach (LocalizedLibraryView dependency in libraryToUse.Dependencies) { LibraryUsagePostOrderTraversal(dependency.LibraryScope, libraryOrderOut, usedLibraries, cycleCheck, breadcrumbs); } cycleCheck.Remove(libraryToUse); breadcrumbs.Pop(); usedLibraries.Add(libraryToUse); libraryOrderOut.Add(libraryToUse); }
private LocalizedLibraryView GetOrImportLibraryImpl(ParserContext parser, Token throwToken, string fullImportNameWithDots) { // TODO: allow importing from a user-specified locale Locale fromLocale = parser.CurrentLocale; string name = fullImportNameWithDots.Contains('.') ? fullImportNameWithDots.Split('.')[0] : fullImportNameWithDots; string secondAttemptedKey = name; LibraryMetadata libraryMetadata = this.libraryFinder.GetLibraryMetadataFromAnyPossibleKey(fromLocale.ID + ":" + name); Locale effectiveLocale = fromLocale; if (libraryMetadata == null) { libraryMetadata = this.libraryFinder.GetLibraryMetadataFromAnyPossibleKey(name); if (libraryMetadata != null && libraryMetadata.SupportedLocales.Contains(fromLocale) && libraryMetadata.InternalLocale != fromLocale) { // Coincidental cross-language collision. return(null); } if (libraryMetadata == null) { // Simply no matches at all. return(null); } effectiveLocale = libraryMetadata.InternalLocale; } // Are there any restrictions on importing that library from this location? if (!libraryMetadata.IsAllowedImport(parser.CurrentLibrary)) { throw new ParserException(throwToken, "This library cannot be imported from here."); } // Ensure all secondary lookups for each locale is instantiated to make the upcoming code more readable. if (!this.importedLibrariesByLocalizedName.ContainsKey(effectiveLocale)) { this.importedLibrariesByLocalizedName[effectiveLocale] = new Dictionary <string, LocalizedLibraryView>(); } if (!this.importedLibrariesByLocalizedName.ContainsKey(libraryMetadata.InternalLocale)) { this.importedLibrariesByLocalizedName[libraryMetadata.InternalLocale] = new Dictionary <string, LocalizedLibraryView>(); } // Check to see if this library has been imported before. if (this.importedLibrariesById.ContainsKey(libraryMetadata.ID)) { // Is it imported by the same locale? if (this.importedLibrariesByLocalizedName[effectiveLocale].ContainsKey(name)) { // Then just return the previous instance as-is. return(this.importedLibrariesByLocalizedName[effectiveLocale][name]); } // Wrap the previous instance in the new locale. LocalizedLibraryView output = new LocalizedLibraryView(effectiveLocale, this.importedLibrariesById[libraryMetadata.ID]); this.importedLibrariesByLocalizedName[effectiveLocale][output.Name] = output; return(output); } // If the library exists but hasn't been imported before, instantiate it and // add it to all the lookups. This needs to happen before parsing the embedded // code to prevent infinite recursion. LibraryCompilationScope libraryScope = new LibraryCompilationScope(parser.BuildContext, libraryMetadata); this.librariesAlreadyImportedIndexByKey[libraryMetadata.CanonicalKey] = this.ImportedLibraries.Count; this.ImportedLibraries.Add(libraryScope); this.importedLibrariesById[libraryMetadata.ID] = libraryScope; LocalizedLibraryView localizedView = new LocalizedLibraryView(effectiveLocale, libraryScope); this.importedLibrariesByLocalizedName[effectiveLocale][name] = localizedView; // Parse the library. parser.PushScope(libraryScope); Dictionary <string, string> embeddedCode = libraryMetadata.GetEmbeddedCode(); foreach (string embeddedFile in embeddedCode.Keys.OrderBy(s => s.ToLower())) { string fakeName = "[" + embeddedFile + "]"; string code = embeddedCode[embeddedFile]; parser.ParseInterpretedCode(fakeName, code); } parser.PopScope(); return(localizedView); }
public LocalizedLibraryView(Locale locale, LibraryCompilationScope libraryScope) { this.Locale = locale; this.LibraryScope = libraryScope; this.FullyQualifiedEntityLookup = null; }