public LocalizedLibraryView GetOrImportLibrary(ParserContext parser, Token throwToken, string fullImportNameWithDots) { LocalizedLibraryView libView = this.GetOrImportLibraryImpl(parser, throwToken, fullImportNameWithDots); if (libView != null && libView.LibraryScope != parser.CurrentScope) { parser.CurrentScope.AddDependency(throwToken, libView); } return(libView); }
public void AddDependency(Token throwToken, LocalizedLibraryView libraryView) { if (this == libraryView.LibraryScope) { throw new System.Exception(); // This should not happen. } if (this.dependenciesAndViews.ContainsKey(libraryView.LibraryScope)) { if (this.dependenciesAndViews[libraryView.LibraryScope] != libraryView) { throw new ParserException(throwToken, "Cannot import the same library multiple times from different locales."); } } this.dependenciesAndViews[libraryView.LibraryScope] = libraryView; }
public void ParseInterpretedCode(string filename, string code) { FileScope fileScope = new FileScope(filename, this.CurrentScope); int fileId = this.GetNextFileId(); this.RegisterFileUsed(filename, code, fileId); Token[] tokenList = Tokenizer.Tokenize(filename, code, fileId, true); TokenStream tokens = new TokenStream(tokenList, filename); List <string> namespaceImportsBuilder = new List <string>(); // Implicitly import the Core library for the current locale. LocalizedLibraryView implicitCoreImport = this.LibraryManager.GetCoreLibrary(this); namespaceImportsBuilder.Add(implicitCoreImport.Name); fileScope.Imports.Add(new ImportStatement(null, implicitCoreImport.Name, this.CurrentLibrary, fileScope)); while (tokens.HasMore && tokens.IsNext(this.Keywords.IMPORT)) { ImportStatement importStatement = this.ExecutableParser.ParseTopLevel(tokens, null, fileScope) as ImportStatement; if (importStatement == null) { throw new Exception(); } namespaceImportsBuilder.Add(importStatement.ImportPath); LocalizedLibraryView localizedLibraryView = this.LibraryManager.GetOrImportLibrary(this, importStatement.FirstToken, importStatement.ImportPath); if (localizedLibraryView == null) { this.unresolvedImports.Add(importStatement); } } string[] namespaceImports = namespaceImportsBuilder.ToArray(); while (tokens.HasMore) { TopLevelConstruct executable = this.ExecutableParser.ParseTopLevel(tokens, null, fileScope); if (executable is ImportStatement) { throw this.GenerateParseError( ErrorMessages.ALL_IMPORTS_MUST_OCCUR_AT_BEGINNING_OF_FILE, executable.FirstToken); } this.CurrentScope.AddExecutable(executable); } }
public void AddDependency(Token throwToken, LocalizedLibraryView libraryView) { if (this == libraryView.LibraryScope) { throw new System.Exception(); // This should not happen. } if (this.dependenciesAndViews.ContainsKey(libraryView.LibraryScope)) { if (this.dependenciesAndViews[libraryView.LibraryScope] != libraryView) { throw ParserException.ThrowException( libraryView.Locale, ErrorMessages.CANNOT_IMPORT_SAME_LIBRARY_FROM_DIFFERENT_LOCALES, throwToken); } } this.dependenciesAndViews[libraryView.LibraryScope] = libraryView; }
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); }