using System; using System.Collections.Generic; using System.Linq; using CppSharp.AST; namespace CppSharp.Generators { /// /// Kinds of language generators. /// public enum GeneratorKind { CLI = 1, CSharp = 2, C, CPlusPlus, ObjectiveC, Java, Swift, QuickJS, NAPI, TypeScript } /// /// Output generated by each backend generator. /// public class GeneratorOutput { /// /// Translation unit associated with output. /// public TranslationUnit TranslationUnit; /// /// Code generators with generated output. /// public List Outputs; } /// /// Generators are the base class for each language backend. /// public abstract class Generator : IDisposable { public BindingContext Context { get; } protected Generator(BindingContext context) { Context = context; CppSharp.AST.Type.TypePrinterDelegate += TypePrinterDelegate; } /// /// Called when a translation unit is generated. /// public Action OnUnitGenerated = delegate { }; /// /// Setup any generator-specific passes here. /// public abstract bool SetupPasses(); /// /// Setup any generator-specific processing here. /// public virtual void Process() { } /// /// Generates the outputs for the given translation units. /// /// The units to generate outputs for. public abstract List Generate(IEnumerable units); /// /// Generates the outputs. /// public virtual List Generate() { var outputMode = Context.Options.GenerationOutputMode; // TODO: Remove this once file per module works for C++ backend if (!Context.Options.IsCSharpGenerator) outputMode = GenerationOutputMode.FilePerUnit; var outputs = new List(); if (outputMode == GenerationOutputMode.FilePerModule) { foreach (var module in Context.Options.Modules) { var output = GenerateModule(module); if (output != null) { OnUnitGenerated(output); outputs.Add(output); } } } else { var units = Context.ASTContext.TranslationUnits.GetGenerated() .Where(u => !u.IsSystemHeader).ToList(); foreach (var unit in units) { var output = GenerateUnit(unit); if (output != null) { outputs.Add(output); OnUnitGenerated(output); } } var generateSystemModule = Context.Options.SystemModule != null && Context.Options.GeneratorKind == GeneratorKind.CSharp; if (generateSystemModule) { var output = GenerateModule(Context.Options.SystemModule); if (output != null) { OnUnitGenerated(output); outputs.Add(output); } } } return outputs; } public virtual GeneratorOutput GenerateUnit(TranslationUnit unit) { var codeGenerators = Generate(new[] { unit }); if (codeGenerators.Count == 0) return null; foreach (var codeGen in codeGenerators) { codeGen.Process(); } var output = new GeneratorOutput { TranslationUnit = unit, Outputs = codeGenerators }; return output; } public virtual GeneratorOutput GenerateModule(Module module) { var generatedUnits = module.Units.GetGenerated().ToList(); if (generatedUnits.Count == 0) return null; var output = new GeneratorOutput { TranslationUnit = new TranslationUnit { FilePath = $"{module.LibraryName}.h", Module = module }, Outputs = Generate(generatedUnits) }; output.Outputs[0].Process(); return output; } protected abstract string TypePrinterDelegate(CppSharp.AST.Type type); public static string GeneratedIdentifier(string id) => $"__{(id.StartsWith("@") ? id.Substring(1) : id)}"; public void Dispose() { CppSharp.AST.Type.TypePrinterDelegate -= TypePrinterDelegate; } } }