Exemple #1
0
        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);
        }
Exemple #2
0
        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());
        }
Exemple #3
0
        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);
        }
Exemple #4
0
        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);
                }
            }
        }