Browse Source

Refactor file writing into the driver instead of duplicating it each generator.

pull/3/head
triton 12 years ago
parent
commit
70f76588aa
  1. 199
      src/Generator/Driver.cs
  2. 36
      src/Generator/Generators/CLI/CLIGenerator.cs
  3. 2
      src/Generator/Generators/CLI/CLITypePrinter.cs
  4. 20
      src/Generator/Generators/CSharp/CSharpGenerator.cs
  5. 50
      src/Generator/Generators/Generator.cs

199
src/Generator/Driver.cs

@ -12,118 +12,76 @@ namespace CppSharp @@ -12,118 +12,76 @@ namespace CppSharp
public class Driver
{
public DriverOptions Options { get; private set; }
public ILibrary Transform { get; private set; }
public IDiagnosticConsumer Diagnostics { get; private set; }
public Parser Parser { get; private set; }
public TypeMapDatabase TypeDatabase { get; private set; }
public ILibrary Transform { get; private set; }
public Generator Generator { get; private set; }
public Library Library { get; private set; }
public Library LibrarySymbols { get; private set; }
public Generator Generator { get; private set; }
public Driver(DriverOptions options, ILibrary transform)
public Driver(DriverOptions options, IDiagnosticConsumer diagnostics,
ILibrary transform)
{
Options = options;
Transform = transform;
Diagnostics = new TextDiagnosticPrinter();
Diagnostics = diagnostics;
Parser = new Parser(Options);
TypeDatabase = new TypeMapDatabase();
Transform = transform;
}
public void Setup()
{
if (Transform != null)
Transform.Setup(Options);
ValidateOptions();
Generator = CreateGenerator();
}
private void ValidateOptions()
static void ValidateOptions(DriverOptions options)
{
if (string.IsNullOrWhiteSpace(Options.LibraryName))
if (string.IsNullOrWhiteSpace(options.LibraryName))
throw new InvalidDataException();
if (Options.OutputDir == null)
Options.OutputDir = Directory.GetCurrentDirectory();
if (options.OutputDir == null)
options.OutputDir = Directory.GetCurrentDirectory();
for (var i = 0; i < Options.IncludeDirs.Count; i++)
for (var i = 0; i < options.IncludeDirs.Count; i++)
{
Options.IncludeDirs[i] = Path.GetFullPath(Options.IncludeDirs[i]);
options.IncludeDirs[i] = Path.GetFullPath(options.IncludeDirs[i]);
}
for (var i = 0; i < Options.LibraryDirs.Count; i++)
for (var i = 0; i < options.LibraryDirs.Count; i++)
{
Options.LibraryDirs[i] = Path.GetFullPath(Options.LibraryDirs[i]);
options.LibraryDirs[i] = Path.GetFullPath(options.LibraryDirs[i]);
}
if (string.IsNullOrWhiteSpace(Options.OutputNamespace))
Options.OutputNamespace = Options.LibraryName;
if (string.IsNullOrWhiteSpace(options.OutputNamespace))
options.OutputNamespace = options.LibraryName;
}
Generator CreateGenerator()
public void Setup()
{
switch (Options.GeneratorKind)
{
case LanguageGeneratorKind.CSharp:
return new CSharpGenerator(this);
case LanguageGeneratorKind.CPlusPlusCLI:
return new CLIGenerator(this);
default:
throw new NotImplementedException("Unknown language generator kind");
}
}
ValidateOptions(Options);
private void OnFileParsed(string file, ParserResult result)
{
switch (result.Kind)
{
case ParserResultKind.Success:
Console.WriteLine(" Parsed '{0}'", file);
break;
case ParserResultKind.Error:
Console.WriteLine(" Error parsing '{0}'", file);
break;
case ParserResultKind.FileNotFound:
Console.WriteLine(" File '{0}' was not found", file);
break;
}
if (!Directory.Exists(Options.OutputDir))
Directory.CreateDirectory(Options.OutputDir);
foreach (var diag in result.Diagnostics)
{
Console.WriteLine(string.Format("{0}({1},{2}): {3}: {4}",
diag.FileName, diag.LineNumber, diag.ColumnNumber,
diag.Level.ToString().ToLower(), diag.Message));
}
if (!Generators.ContainsKey(Options.GeneratorKind))
throw new NotImplementedException("Unknown generator kind");
Generator = Generators[Options.GeneratorKind](this);
}
public bool ParseCode()
{
Console.WriteLine("Parsing code...");
var parser = new Parser(Options);
parser.OnHeaderParsed += OnFileParsed;
if( !parser.ParseHeaders(Options.Headers) )
if (!Parser.ParseHeaders(Options.Headers))
return false;
Library = parser.Library;
Library = Parser.Library;
return true;
}
public bool ParseLibraries()
{
Console.WriteLine("Parsing libraries...");
var parser = new Parser(Options);
parser.OnLibraryParsed += OnFileParsed;
if (!parser.ParseLibraries(Options.Libraries))
if (!Parser.ParseLibraries(Options.Libraries))
return false;
LibrarySymbols = parser.Library;
Console.WriteLine("Indexing library symbols...");
LibrarySymbols.IndexSymbols();
LibrarySymbols = Parser.Library;
return true;
}
@ -133,7 +91,7 @@ namespace CppSharp @@ -133,7 +91,7 @@ namespace CppSharp
TypeDatabase.SetupTypeMaps();
if (Transform != null)
Transform.Preprocess(Library);
Transform.Preprocess(this, Library);
var passes = new PassBuilder(this);
passes.CleanUnit(Options);
@ -150,11 +108,7 @@ namespace CppSharp @@ -150,11 +108,7 @@ namespace CppSharp
passes.CheckFlagEnums();
passes.CheckAmbiguousOverloads();
if (Options.GeneratorKind == LanguageGeneratorKind.CSharp)
{
passes.CheckAbiParameters(Options);
passes.CheckOperatorOverloads();
}
Generator.SetupPasses(passes);
passes.RunPasses();
@ -167,12 +121,6 @@ namespace CppSharp @@ -167,12 +121,6 @@ namespace CppSharp
if (Library.TranslationUnits.Count <= 0)
return;
Console.WriteLine("Generating wrapper code...");
if (!Directory.Exists(Options.OutputDir))
Directory.CreateDirectory(Options.OutputDir);
// Process everything in the global namespace for now.
foreach (var unit in Library.TranslationUnits)
{
if (unit.Ignore || !unit.HasDeclarations)
@ -181,22 +129,18 @@ namespace CppSharp @@ -181,22 +129,18 @@ namespace CppSharp
if (unit.IsSystemHeader)
continue;
// Generate the target code.
Generator.Generate(unit);
}
}
var outputs = new List<GeneratorOutput>();
if (!Generator.Generate(unit, outputs))
continue;
public static void Run(ILibrary library)
{
var options = new DriverOptions();
foreach (var output in outputs)
{
Diagnostics.EmitMessage(DiagnosticId.FileGenerated,
"Generated '{0}'", Path.GetFileName(output.OutputPath));
var driver = new Driver(options, library);
driver.Setup();
if (driver.ParseLibraries() && driver.ParseCode())
{
driver.ProcessCode();
driver.GenerateCode();
var text = output.Template.ToString();
File.WriteAllText(output.OutputPath, text);
}
}
}
}
@ -263,4 +207,61 @@ namespace CppSharp @@ -263,4 +207,61 @@ namespace CppSharp
public bool WriteOnlyWhenChanged;
public Func<TranslationUnit, string> GenerateName;
}
public static class ConsoleDriver
{
static void OnFileParsed(string file, ParserResult result)
{
switch (result.Kind)
{
case ParserResultKind.Success:
Console.WriteLine(" Parsed '{0}'", file);
break;
case ParserResultKind.Error:
Console.WriteLine(" Error parsing '{0}'", file);
break;
case ParserResultKind.FileNotFound:
Console.WriteLine(" File '{0}' was not found", file);
break;
}
foreach (var diag in result.Diagnostics)
{
Console.WriteLine(string.Format("{0}({1},{2}): {3}: {4}",
diag.FileName, diag.LineNumber, diag.ColumnNumber,
diag.Level.ToString().ToLower(), diag.Message));
}
}
public static void Run(ILibrary library)
{
Console.BufferHeight = 1999;
var options = new DriverOptions();
var driver = new Driver(options, new TextDiagnosticPrinter(),
library);
library.Setup(driver);
driver.Setup();
driver.Parser.OnHeaderParsed += OnFileParsed;
driver.Parser.OnLibraryParsed += OnFileParsed;
Console.WriteLine("Parsing libraries...");
if (!driver.ParseLibraries())
return;
Console.WriteLine("Indexing library symbols...");
driver.LibrarySymbols.IndexSymbols();
Console.WriteLine("Parsing code...");
if (!driver.ParseCode())
return;
Console.WriteLine("Processing code...");
driver.ProcessCode();
Console.WriteLine("Generating code...");
driver.GenerateCode();
}
}
}

36
src/Generator/Generators/CLI/CLIGenerator.cs

@ -1,47 +1,33 @@ @@ -1,47 +1,33 @@
using System.IO;
using System.Collections.Generic;
using System.IO;
using CppSharp.Types.Std;
namespace CppSharp.Generators.CLI
{
public class CLIGenerator : Generator
{
private readonly CLITypePrinter typePrinter;
private readonly FileHashes fileHashes;
public CLIGenerator(Driver driver) : base(driver)
{
typePrinter = new CLITypePrinter(driver);
Type.TypePrinterDelegate += type => type.Visit(typePrinter);
fileHashes = FileHashes.Load("hashes.ser");
}
void WriteTemplate(TextTemplate template)
public override bool Generate(TranslationUnit unit,
List<GeneratorOutput> outputs)
{
var path = GetOutputPath(template.TranslationUnit)
+ "." + template.FileExtension;
template.Generate();
var text = template.ToString();
var header = new CLIHeadersTemplate(Driver, unit);
outputs.Add(GenerateTemplateOutput(header));
if(Driver.Options.WriteOnlyWhenChanged)
{
var updated = fileHashes.UpdateHash(path, text.GetHashCode());
if (File.Exists(path) && !updated)
return;
}
var source = new CLISourcesTemplate(Driver, unit);
outputs.Add(GenerateTemplateOutput(source));
Driver.Diagnostics.EmitMessage(DiagnosticId.FileGenerated,
" Generated '{0}'.", Path.GetFileName(path));
File.WriteAllText(path, text);
return true;
}
public override bool Generate(TranslationUnit unit)
public override bool SetupPasses(PassBuilder builder)
{
var header = new CLIHeadersTemplate(Driver, unit);
WriteTemplate(header);
var source = new CLISourcesTemplate(Driver, unit);
WriteTemplate(source);
return true;
}
}

2
src/Generator/Generators/CLI/CLITypePrinter.cs

@ -248,7 +248,7 @@ namespace CppSharp.Generators.CLI @@ -248,7 +248,7 @@ namespace CppSharp.Generators.CLI
var names = new List<string>();
if (Options.GenerateLibraryNamespace)
names.Add(Driver.Library.Name);
names.Add(Driver.Options.OutputNamespace);
if (!string.IsNullOrEmpty(decl.Namespace.QualifiedName))
names.Add(decl.Namespace.QualifiedName);

20
src/Generator/Generators/CSharp/CSharpGenerator.cs

@ -1,5 +1,6 @@ @@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using CppSharp.Passes;
namespace CppSharp.Generators.CSharp
{
@ -13,22 +14,11 @@ namespace CppSharp.Generators.CSharp @@ -13,22 +14,11 @@ namespace CppSharp.Generators.CSharp
Type.TypePrinterDelegate += type => type.Visit(typePrinter).Type;
}
void WriteTemplate(TextTemplate template)
{
var path = GetOutputPath(template.TranslationUnit)
+ "." + template.FileExtension;
template.Generate();
File.WriteAllText(path, template.ToString());
Driver.Diagnostics.EmitMessage(DiagnosticId.FileGenerated,
" Generated '{0}'.", Path.GetFileName(path));
}
public override bool Generate(TranslationUnit unit)
public override bool Generate(TranslationUnit unit,
List<GeneratorOutput> outputs)
{
var template = new CSharpTextTemplate(Driver, unit, typePrinter);
WriteTemplate(template);
outputs.Add(GenerateTemplateOutput(template));
return true;
}

50
src/Generator/Generators/Generator.cs

@ -1,19 +1,36 @@ @@ -1,19 +1,36 @@
using System.IO;
using System.Collections.Generic;
using System.IO;
namespace CppSharp.Generators
{
public enum LanguageGeneratorKind
{
CPlusPlusCLI,
CSharp
CSharp,
}
public interface IGenerator
/// <summary>
/// Output generated by each backend generator.
/// </summary>
public struct GeneratorOutput
{
bool Generate(TranslationUnit unit);
/// <summary>
/// Translation unit associated with output.
/// </summary>
public TranslationUnit TranslationUnit;
/// <summary>
/// Text template with generated output.
/// </summary>
public TextTemplate Template;
/// <summary>
/// Output path of the generated output.
/// </summary>
public string OutputPath;
}
public abstract class Generator : IGenerator
public abstract class Generator
{
public Driver Driver { get; private set; }
@ -22,9 +39,11 @@ namespace CppSharp.Generators @@ -22,9 +39,11 @@ namespace CppSharp.Generators
Driver = driver;
}
public abstract bool Generate(TranslationUnit unit);
public abstract bool Generate(TranslationUnit unit,
List<GeneratorOutput> outputs);
public string GetOutputPath(TranslationUnit unit)
protected string GetOutputPath(TranslationUnit unit)
{
var file = unit.FileNameWithoutExtension;
@ -34,5 +53,22 @@ namespace CppSharp.Generators @@ -34,5 +53,22 @@ namespace CppSharp.Generators
var path = Path.Combine(Driver.Options.OutputDir, file);
return Path.GetFullPath(path);
}
protected GeneratorOutput GenerateTemplateOutput(TextTemplate template)
{
var path = GetOutputPath(template.TranslationUnit)
+ "." + template.FileExtension;
template.Generate();
var output = new GeneratorOutput()
{
OutputPath = path,
Template = template,
TranslationUnit = template.TranslationUnit
};
return output;
}
}
}
Loading…
Cancel
Save