예제 #1
0
        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);
        }