Esempio n. 1
0
        private static void ParseImpl(ProjectConfig config, string configContents, string originalPath)
        {
            string directory = System.IO.Path.GetFullPath(System.IO.Path.GetDirectoryName(originalPath));

            string[] lines = configContents.Split('\n');
            for (int i = 0; i < lines.Length; ++i)
            {
                string line = lines[i].Trim();
                if (line.Length == 0 || line[0] == '#')
                {
                    continue;
                }
                string[] parts = SplitOnColon(line);
                if (parts == null)
                {
                    throw new InvalidOperationException("Invalid syntax on line " + (i + 1) + " of " + originalPath + ":\n" + line);
                }

                string type = parts[0];
                string data = parts[1];
                switch (type)
                {
                case "IMPORT":
                    string importedConfig = CanonicalizeDirectory(directory, data);
                    if (!System.IO.File.Exists(importedConfig))
                    {
                        throw new InvalidOperationException("Config file does not exist: " + importedConfig);
                    }
                    string importedConfigContents = System.IO.File.ReadAllText(importedConfig);
                    ParseImpl(config, importedConfigContents, importedConfig);
                    break;

                case "LANGUAGE":
                    config.Language = LanguageUtil.ParseLanguage(data);
                    break;

                case "SOURCE":
                    config.Source = CanonicalizeDirectory(directory, data);
                    break;

                case "DEPENDENCY":
                    parts = SplitOnColon(data);
                    if (parts == null)
                    {
                        throw new InvalidOperationException("Dependency requires a namespace in " + originalPath + " on line " + (i + 1) + ":\n" + line);
                    }
                    string depNamespace = parts[0];
                    string path         = CanonicalizeDirectory(directory, parts[1]);
                    config.DependenciesByPrefix[depNamespace] = Parse(path);
                    break;

                case "FLAG":
                    parts = SplitOnColon(data);
                    if (parts.Length != 2)
                    {
                        throw new InvalidOperationException("Invalid flag definition: " + line);
                    }
                    config.Flags[parts[0]] = PastelUtil.StringToBool(parts[1]);
                    break;

                case "OUTPUT-STRUCTS":
                    config.OutputDirStructs = CanonicalizeDirectory(directory, data);
                    break;

                case "OUTPUT-FUNCTIONS":
                    config.OutputFileFunctions = CanonicalizeDirectory(directory, data);
                    break;

                // TODO: I have not found value in distinguishing these two aside from this is just how
                // I started things and have to maintain it. Merge the two namespaces and then change
                // these to just "NAMESPACE".
                case "NAMESPACE-FUNCTIONS":
                    config.NamespaceForFunctions = data;
                    break;

                case "NAMESPACE-STRUCTS":
                    config.NamespaceForStructs = data;
                    break;

                case "FUNCTION-WRAPPER-CLASS":
                    config.WrappingClassNameForFunctions = data;
                    break;

                case "EXT":
                    parts = SplitOnColon(data);
                    config.ExtensionPlatformValues[parts[0]] = parts[1];
                    config.ExtensionPlatformValuesDefinitionTokens[parts[0]] = new Token("", originalPath, i, 0, true);
                    break;

                case "EXT-TYPE":
                    config.ExtensionTypeDefinitions.Add(data);
                    break;

                case "CODE-IMPORT":
                    config.Imports.Add(data);
                    break;

                case "INCLUDE-PUBLIC-PASTEL-UTIL":
                    config.IncludePublicPastelUtil = PastelUtil.StringToBool(data);
                    break;

                case "PHP-FILE-INCLUDE":
                case "PHP-FILE-INCLUDE-OPTIONAL":
                    string phpFilePath = CanonicalizeDirectory(directory, data);
                    config.PhpFileIncludes.Add(phpFilePath);
                    config.PhpFileIncludeIsOptional.Add(phpFilePath);
                    break;

                default:
                    throw new InvalidOperationException("Unrecognized project config command '" + type + "' on line " + (i + 1) + " of " + originalPath + ":\n" + line);
                }
            }
        }
Esempio n. 2
0
        private static PastelContext GetContextForConfigImpl(
            ProjectConfig config,
            Dictionary <string, PastelContext> contexts,
            HashSet <string> recursionCheck)
        {
            if (contexts.ContainsKey(config.Path))
            {
                return(contexts[config.Path]);
            }
            if (recursionCheck.Contains(config.Path))
            {
                throw new InvalidOperationException("Project config dependencies have a cycle involving: " + config.Path);
            }

            recursionCheck.Add(config.Path);

            ProjectConfig[] requiredScopes = config.DependenciesByPrefix.Values.ToArray();
            for (int i = 0; i < requiredScopes.Length; ++i)
            {
                string path = requiredScopes[i].Path;
                if (!contexts.ContainsKey(path))
                {
                    throw new Exception(); // This shouldn't happen. These are run in dependency order.
                }
            }

            string        sourceRootDir = System.IO.Path.GetDirectoryName(config.Source);
            PastelContext context       = new PastelContext(sourceRootDir, config.Language, new CodeLoader(sourceRootDir));

            foreach (string prefix in config.DependenciesByPrefix.Keys)
            {
                ProjectConfig depConfig = config.DependenciesByPrefix[prefix];

                // TODO: make this a little more generic for other possible languages
                string funcNs       = depConfig.NamespaceForFunctions;
                string classWrapper = depConfig.WrappingClassNameForFunctions;
                string outputPrefix = "";
                if (funcNs != null)
                {
                    outputPrefix = funcNs + ".";
                }
                if (classWrapper != null)
                {
                    outputPrefix += classWrapper + ".";
                }

                context.AddDependency(contexts[depConfig.Path], prefix, outputPrefix);
            }
            context.MarkDependenciesAsFinalized();

            foreach (string constantName in config.Flags.Keys)
            {
                context.SetConstant(constantName, config.Flags[constantName]);
            }

            foreach (ExtensibleFunction exFn in config.GetExtensibleFunctions())
            {
                // TODO(pastel-split): Translation is already set on the extensible function in the
                // new codepath, so the 2nd parameter here ought to be removed.
                context.AddExtensibleFunction(exFn, exFn.Translation);
            }

            contexts[config.Path] = context;
            recursionCheck.Remove(config.Path);
            return(context);
        }
Esempio n. 3
0
        private static Dictionary <string, string> GenerateFiles(ProjectConfig config, PastelContext context)
        {
            Dictionary <string, string> output = new Dictionary <string, string>();

            if (context.UsesClassDefinitions)
            {
                Dictionary <string, string> classDefinitions = context.GetCodeForClasses();
                foreach (string className in classDefinitions.Keys.OrderBy(k => k))
                {
                    string classCode = classDefinitions[className];
                    if (context.ClassDefinitionsInSeparateFiles)
                    {
                        GenerateClassImplementation(config, className, classCode);
                    }
                    else
                    {
                        output["class_def:" + className] = classCode;
                    }
                }

                if (!context.ClassDefinitionsInSeparateFiles)
                {
                    System.Text.StringBuilder sb = new System.Text.StringBuilder();
                    foreach (string key in output.Keys.Where(k => k.StartsWith("class_def:")).OrderBy(k => k))
                    {
                        sb.Append(output[key]);
                        sb.Append("\n\n");
                    }
                    string code = sb.ToString().Trim();
                    if (code.Length > 0)
                    {
                        string classOutputDir = System.IO.Path.GetDirectoryName(config.OutputFileFunctions);
                        string path           = System.IO.Path.Combine(classOutputDir, "Classes" + LanguageUtil.GetFileExtension(config.Language));
                        System.IO.File.WriteAllText(path, code + "\n");
                    }
                }
            }

            if (context.UsesStructDefinitions)
            {
                Dictionary <string, string> structDefinitions = context.GetCodeForStructs();
                string[] structOrder = structDefinitions.Keys.OrderBy(k => k.ToLower()).ToArray();
                if (context.HasStructsInSeparateFiles)
                {
                    foreach (string structName in structOrder)
                    {
                        GenerateStructImplementation(config, structName, structDefinitions[structName]);
                    }
                }
                else
                {
                    GenerateStructBundleImplementation(config, structOrder, structDefinitions);
                }

                if (context.UsesStructDeclarations)
                {
                    Dictionary <string, string> structDeclarations = structOrder.ToDictionary(k => context.GetCodeForStructDeclaration(k));

                    foreach (string structName in structOrder)
                    {
                        output["struct_decl:" + structName] = structDeclarations[structName];
                    }
                }
            }

            if (context.UsesFunctionDeclarations)
            {
                string funcDeclarations = context.GetCodeForFunctionDeclarations();
                throw new NotImplementedException();
            }

            GenerateFunctionImplementation(config, context.GetCodeForFunctions());

            return(output);
        }
Esempio n. 4
0
 private static void GenerateFunctionImplementation(ProjectConfig config, string funcCode)
 {
     Transpilers.AbstractTranspiler transpiler = LanguageUtil.GetTranspiler(config.Language);
     funcCode = transpiler.WrapCodeForFunctions(config, funcCode);
     System.IO.File.WriteAllText(config.OutputFileFunctions, funcCode);
 }