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); } } }
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); }
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); }
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); }