public Library GetCoreLibrary(Parser parser) { if (this.coreLibrary == null) { this.coreLibrary = this.GetLibraryFromKey("en:Core"); // canonical key will work even if english locale not used. if (this.coreLibrary == null) { LibraryMetadata coreLibMetadata = this.GetLibraryMetadataFromAnyPossibleKey("en:Core"); TODO.GetCoreNameFromMetadataWithLocale(); string coreNameInLocale = coreLibMetadata.Name; this.coreLibrary = this.ImportLibrary(parser, null, coreNameInLocale); } } return(this.coreLibrary); }
private LibraryMetadata[] GetAvailableLibraryPathsByLibraryName( string nullableBuildFileCrayonPath, string nullableProjectDirectory) { string crayonHome = System.Environment.GetEnvironmentVariable("CRAYON_HOME"); #if RELEASE if (crayonHome == null) { throw new System.InvalidOperationException("Please set the CRAYON_HOME environment variable to the location of the directory containing both 'crayon.exe' and the 'lib' directory."); } #endif string placesWhereLibraryDirectoriesCanExist = ""; if (crayonHome != null) { placesWhereLibraryDirectoriesCanExist += ";" + System.IO.Path.Combine(crayonHome, "libs"); } if (nullableBuildFileCrayonPath != null) { placesWhereLibraryDirectoriesCanExist += ";" + nullableBuildFileCrayonPath; } placesWhereLibraryDirectoriesCanExist += ";" + (System.Environment.GetEnvironmentVariable("CRAYON_PATH") ?? ""); #if OSX placesWhereLibraryDirectoriesCanExist = placesWhereLibraryDirectoriesCanExist.Replace(':', ';'); #endif string[] paths = placesWhereLibraryDirectoriesCanExist.Split(new char[] { ';' }, System.StringSplitOptions.RemoveEmptyEntries); List <string> unverifiedLibraryDirectories = new List <string>(); foreach (string path in paths) { string absolutePath = FileUtil.IsAbsolutePath(path) ? path : System.IO.Path.Combine(nullableProjectDirectory, path); absolutePath = System.IO.Path.GetFullPath(absolutePath); if (System.IO.Directory.Exists(absolutePath)) { unverifiedLibraryDirectories.AddRange(System.IO.Directory.GetDirectories(absolutePath)); } } #if DEBUG // Presumably running from source. Walk up to the root directory and find the Libraries directory. // From there use the list of folders. string currentDirectory = System.IO.Path.GetFullPath("."); while (!string.IsNullOrEmpty(currentDirectory)) { string path = System.IO.Path.Combine(currentDirectory, "Libraries"); if (System.IO.Directory.Exists(path) && System.IO.File.Exists(System.IO.Path.Combine(currentDirectory, "Compiler", "CrayonWindows.sln"))) // quick sanity check { unverifiedLibraryDirectories.AddRange(System.IO.Directory.GetDirectories(path)); break; } currentDirectory = System.IO.Path.GetDirectoryName(currentDirectory); } #endif List <string> verifiedLibraryPaths = new List <string>(); foreach (string dir in unverifiedLibraryDirectories) { string manifestPath = System.IO.Path.Combine(dir, "manifest.txt"); if (System.IO.File.Exists(manifestPath)) { verifiedLibraryPaths.Add(dir); } } // Library name collisions will override any previous definition. // For example, a custom library referenced by a build file will override a built-in library. // An example use case of this would be to define a custom library called "Gamepad" for mobile that puts // buttons in the corners of the screen, but without having to change any code to be platform-aware. Dictionary <string, LibraryMetadata> uniqueLibraries = new Dictionary <string, LibraryMetadata>(); foreach (string path in verifiedLibraryPaths) { string defaultName = System.IO.Path.GetFileName(path); LibraryMetadata metadata = new LibraryMetadata(path, defaultName); // TODO: don't hardcode EN string uniqueKey = "en:" + metadata.Name; uniqueLibraries[uniqueKey] = metadata; } return(uniqueLibraries.Values .OrderBy(metadata => metadata.Name.ToLower()) .ToArray()); }
public Library ImportLibrary(Parser parser, Token throwToken, string name) { name = name.Split('.')[0]; string key = parser.CurrentLocale.ID + ":" + name; LibraryMetadata libraryMetadata = this.GetLibraryMetadataFromAnyPossibleKey(key); if (libraryMetadata == null) { // check for default locale libraryMetadata = this.GetLibraryMetadataFromAnyPossibleKey(name); if (libraryMetadata == null) { // No library found. Could just be a local namespace import. // If this is a bogus import, it'll throw in the Resolver. return(null); } if (libraryMetadata.SupportedLocales.Contains(parser.CurrentLocale)) { // If you import something by its default name from a supported locale, then it doesn't count. // Don't throw an error. A user should be able to define a namespace that happens to have the // same name as a library in some locale they aren't using. return(null); } } Library library = librariesAlreadyImportedIndexByKey.ContainsKey(libraryMetadata.CanonicalKey) ? librariesAlreadyImported[librariesAlreadyImportedIndexByKey[libraryMetadata.CanonicalKey]] : null; if (library == null) { string platformName = parser.BuildContext.Platform; Platform.AbstractPlatform platform = platformName == null || this.PlatformProvider == null ? null : this.PlatformProvider.GetPlatform(platformName); library = new Library(libraryMetadata, platform); CompilationScope scope = new CompilationScope(parser.BuildContext, library); library.Scope = scope; library.AddLocaleAccess(parser.CurrentLocale); this.librariesAlreadyImportedIndexByKey[libraryMetadata.CanonicalKey] = this.librariesAlreadyImported.Count; this.librariesAlreadyImported.Add(library); this.importedLibraries[name] = library; this.librariesByKey[name.ToLowerInvariant()] = library; parser.PushScope(scope); Dictionary <string, string> embeddedCode = library.GetEmbeddedCode(); foreach (string embeddedFile in embeddedCode.Keys) { string fakeName = "[" + embeddedFile + "]"; string code = embeddedCode[embeddedFile]; parser.ParseInterpretedCode(fakeName, code); } parser.PopScope(); } // Even if already imported, still must check to see if this import is allowed here. if (!library.IsAllowedImport(parser.CurrentLibrary)) { throw new ParserException(throwToken, "This library cannot be imported from here."); } return(library); }
public Library(LibraryMetadata metadata, Platform.AbstractPlatform nullablePlatform) { TODO.LibrariesNeedVersionNumber(); this.CanonicalKey = metadata.InternalLocale.ID + ":" + metadata.Name; this.Metadata = metadata; this.platformName = nullablePlatform == null ? null : nullablePlatform.Name; this.Resources = new LibraryResourceDatabase(this, nullablePlatform); this.Name = metadata.Name; this.RootDirectory = metadata.Directory; string[] manifest = metadata.Manifest.Split('\n'); Dictionary <string, string> values = new Dictionary <string, string>(); Dictionary <string, bool> flagValues = new Dictionary <string, bool>(); string platformPrefix = "[" + this.platformName + "]"; foreach (string line in manifest) { string trimmedLine = line.Trim(); if (trimmedLine.Length > 0 && line[0] != '#') { string[] parts = trimmedLine.Split(':'); if (parts.Length >= 2) { string key = parts[0].Trim(); string value = parts[1]; for (int i = 2; i < parts.Length; ++i) { value += ":" + parts[i]; } if (key.StartsWith("[")) { if (key.StartsWith(platformPrefix)) { key = key.Substring(platformPrefix.Length).Trim(); } else { continue; } } if (key == "BOOL_FLAG") { // TODO: parse bool flag value parts = value.Split(':'); if (parts.Length == 2) { key = parts[0].Trim(); bool boolValue = parts[1].Trim().ToLowerInvariant() == "true"; flagValues[key] = boolValue; } else { throw new ParserException(null, "Library '" + metadata.Name + "' has a syntax error in a boolean flag."); } } else { values[key] = value; } } else if (parts.Length == 1 && parts[0].Length != 0) { throw new ParserException(null, "Library '" + metadata.Name + "' has a syntax error in its manifest."); } } } this.CompileTimeConstants = new Dictionary <string, object>(); foreach (string key in flagValues.Keys) { this.CompileTimeConstants[key] = flagValues[key]; } foreach (string key in values.Keys) { this.CompileTimeConstants[key] = values[key]; } this.filepathsByFunctionName = new Dictionary <string, string>(); // Build a lookup dictionary of all file names that are simple function names e.g. "foo.cry" // Then go through and look up all the file names that contain . prefixes with the platform name and // overwrite the lookup value for that entry with the more specific path. // myFunction.cry // android.myFunction.cry // on Python, myFunction will be included for lib_foo_myFunction(), but on Android, android.myFunction.cry will be included instead. string[] files = new string[0]; if (FileUtil.DirectoryExists(this.RootDirectory + "/translate")) { files = System.IO.Directory.GetFiles(System.IO.Path.Combine(this.RootDirectory, "translate")); } Dictionary <string, string> moreSpecificFiles = new Dictionary <string, string>(); foreach (string fileWithDirectory in files) { string file = System.IO.Path.GetFileName(fileWithDirectory); if (file.EndsWith(".pst")) { string functionName = file.Substring(0, file.Length - ".pst".Length); if (functionName.Contains('.')) { // Add this file to the more specific lookup, but only if it contains the current platform. if (functionName.StartsWith(platformName + ".") || functionName.Contains("." + platformName + ".")) { string[] parts = functionName.Split('.'); moreSpecificFiles[parts[parts.Length - 1]] = file; } else { // just let it get filtered away. } } else { this.filepathsByFunctionName[functionName] = file; } } } foreach (string functionName in moreSpecificFiles.Keys) { this.filepathsByFunctionName[functionName] = moreSpecificFiles[functionName]; } if (values.ContainsKey("ONLY_ALLOW_IMPORT_FROM")) { this.onlyImportableFrom = new HashSet <string>(); foreach (string onlyImportFrom in values["ONLY_ALLOW_IMPORT_FROM"].Split(',')) { string libraryName = onlyImportFrom.Trim(); this.onlyImportableFrom.Add(this.Metadata.InternalLocale.ID + ":" + libraryName); } } }