diff --git a/src/Generator/Generators/CLI/CLIMarshal.cs b/src/Generator/Generators/CLI/CLIMarshal.cs index 6603b52a..6009ea87 100644 --- a/src/Generator/Generators/CLI/CLIMarshal.cs +++ b/src/Generator/Generators/CLI/CLIMarshal.cs @@ -4,70 +4,91 @@ using Cxxi.Types; namespace Cxxi.Generators.CLI { - public interface IMarshalPrinter : ITypeVisitor, IDeclVisitor + public abstract class MarshalPrinter : ITypeVisitor, IDeclVisitor { - + public MarshalContext Context { get; private set; } + + protected MarshalPrinter(MarshalContext ctx) + { + Context = ctx; + } + + public abstract bool VisitTagType(TagType tag, TypeQualifiers quals); + public abstract bool VisitArrayType(ArrayType array, TypeQualifiers quals); + public abstract bool VisitFunctionType(FunctionType function, TypeQualifiers quals); + public abstract bool VisitPointerType(PointerType pointer, TypeQualifiers quals); + public abstract bool VisitMemberPointerType(MemberPointerType member, TypeQualifiers quals); + public abstract bool VisitBuiltinType(BuiltinType builtin, TypeQualifiers quals); + public abstract bool VisitTypedefType(TypedefType typedef, TypeQualifiers quals); + public abstract bool VisitTemplateSpecializationType(TemplateSpecializationType template, TypeQualifiers quals); + public abstract bool VisitPrimitiveType(PrimitiveType type, TypeQualifiers quals); + public abstract bool VisitDeclaration(Declaration decl, TypeQualifiers quals); + public abstract bool VisitTemplateParameterType(TemplateParameterType param, TypeQualifiers quals); + public abstract bool VisitDeclaration(Declaration decl); + public abstract bool VisitClassDecl(Class @class); + public abstract bool VisitFieldDecl(Field field); + public abstract bool VisitFunctionDecl(Function function); + public abstract bool VisitMethodDecl(Method method); + public abstract bool VisitParameterDecl(Parameter parameter); + public abstract bool VisitTypedefDecl(TypedefDecl typedef); + public abstract bool VisitEnumDecl(Enumeration @enum); + public abstract bool VisitVariableDecl(Variable variable); + public abstract bool VisitClassTemplateDecl(ClassTemplate template); + public abstract bool VisitFunctionTemplateDecl(FunctionTemplate template); + public abstract bool VisitMacroDefinition(MacroDefinition macro); + public abstract bool VisitNamespace(Namespace @namespace); + public abstract bool VisitEvent(Event @event); } - public class CLIMarshalNativeToManagedPrinter : IMarshalPrinter + public class CLIMarshalNativeToManagedPrinter : MarshalPrinter { - public TextGenerator Return; - - Driver Driver { get; set; } - ITypeMapDatabase TypeMapDatabase { get; set; } - MarshalContext Context { get; set; } - public CLIMarshalNativeToManagedPrinter(Driver driver, MarshalContext marshalContext) + public CLIMarshalNativeToManagedPrinter(MarshalContext marshalContext) + : base(marshalContext) { - Driver = driver; - TypeMapDatabase = driver.TypeDatabase; - Context = marshalContext; - - Return = new TextGenerator(); - Context.Return = Return; Context.MarshalToManaged = this; } - public bool VisitTagType(TagType tag, TypeQualifiers quals) + public override bool VisitTagType(TagType tag, TypeQualifiers quals) { var decl = tag.Declaration; return decl.Visit(this); } - public bool VisitArrayType(ArrayType array, TypeQualifiers quals) + public override bool VisitArrayType(ArrayType array, TypeQualifiers quals) { switch (array.SizeType) { case ArrayType.ArraySize.Constant: - Return.Write("nullptr"); + Context.Return.Write("nullptr"); break; case ArrayType.ArraySize.Variable: - Return.Write("nullptr"); + Context.Return.Write("nullptr"); break; } return true; } - public bool VisitFunctionType(FunctionType function, TypeQualifiers quals) + public override bool VisitFunctionType(FunctionType function, TypeQualifiers quals) { var returnType = function.ReturnType; return returnType.Visit(this, quals); } - public bool VisitPointerType(PointerType pointer, TypeQualifiers quals) + public override bool VisitPointerType(PointerType pointer, TypeQualifiers quals) { var pointee = pointer.Pointee; if (pointee.IsPrimitiveType(PrimitiveType.Void, walkTypedefs: true)) { - Return.Write("IntPtr({0})", Context.ReturnVarName); + Context.Return.Write("IntPtr({0})", Context.ReturnVarName); return true; } if (pointee.IsPrimitiveType(PrimitiveType.Char)) { - Return.Write("clix::marshalString({0})", + Context.Return.Write("clix::marshalString({0})", Context.ReturnVarName); return true; } @@ -75,7 +96,7 @@ namespace Cxxi.Generators.CLI PrimitiveType primitive; if (pointee.IsPrimitiveType(out primitive, walkTypedefs: true)) { - Return.Write("IntPtr({0})", Context.ReturnVarName); + Context.Return.Write("IntPtr({0})", Context.ReturnVarName); return true; } @@ -85,13 +106,13 @@ namespace Cxxi.Generators.CLI return true; } - public bool VisitMemberPointerType(MemberPointerType member, + public override bool VisitMemberPointerType(MemberPointerType member, TypeQualifiers quals) { return false; } - public bool VisitBuiltinType(BuiltinType builtin, TypeQualifiers quals) + public override bool VisitBuiltinType(BuiltinType builtin, TypeQualifiers quals) { return VisitPrimitiveType(builtin.Type); } @@ -113,7 +134,7 @@ namespace Cxxi.Generators.CLI case PrimitiveType.UInt64: case PrimitiveType.Float: case PrimitiveType.Double: - Return.Write(Context.ReturnVarName); + Context.Return.Write(Context.ReturnVarName); return true; case PrimitiveType.WideChar: return false; @@ -122,12 +143,12 @@ namespace Cxxi.Generators.CLI return false; } - public bool VisitTypedefType(TypedefType typedef, TypeQualifiers quals) + public override bool VisitTypedefType(TypedefType typedef, TypeQualifiers quals) { var decl = typedef.Declaration; TypeMap typeMap = null; - if (TypeMapDatabase.FindTypeMap(decl, out typeMap)) + if (Context.Driver.TypeDatabase.FindTypeMap(decl, out typeMap)) { typeMap.Type = typedef; typeMap.CLIMarshalToManaged(Context); @@ -137,10 +158,10 @@ namespace Cxxi.Generators.CLI FunctionType function; if (decl.Type.IsPointerTo(out function)) { - Return.Write("safe_cast<{0}>(", typedef); - Return.Write("System::Runtime::InteropServices::Marshal::"); - Return.Write("GetDelegateForFunctionPointer("); - Return.Write("IntPtr({0}), {1}::typeid))",Context.ReturnVarName, + Context.Return.Write("safe_cast<{0}>(", typedef); + Context.Return.Write("System::Runtime::InteropServices::Marshal::"); + Context.Return.Write("GetDelegateForFunctionPointer("); + Context.Return.Write("IntPtr({0}), {1}::typeid))",Context.ReturnVarName, typedef.ToString().TrimEnd('^')); return true; } @@ -148,11 +169,11 @@ namespace Cxxi.Generators.CLI return decl.Type.Visit(this); } - public bool VisitTemplateSpecializationType(TemplateSpecializationType template, + public override bool VisitTemplateSpecializationType(TemplateSpecializationType template, TypeQualifiers quals) { TypeMap typeMap; - if (TypeMapDatabase.FindTypeMap(template, out typeMap)) + if (Context.Driver.TypeDatabase.FindTypeMap(template, out typeMap)) { typeMap.Type = template; typeMap.CLIMarshalToManaged(Context); @@ -162,27 +183,27 @@ namespace Cxxi.Generators.CLI return template.Template.Visit(this); } - public bool VisitTemplateParameterType(TemplateParameterType param, TypeQualifiers quals) + public override bool VisitTemplateParameterType(TemplateParameterType param, TypeQualifiers quals) { throw new NotImplementedException(); } - public bool VisitPrimitiveType(PrimitiveType type, TypeQualifiers quals) + public override bool VisitPrimitiveType(PrimitiveType type, TypeQualifiers quals) { throw new NotImplementedException(); } - public bool VisitDeclaration(Declaration decl, TypeQualifiers quals) + public override bool VisitDeclaration(Declaration decl, TypeQualifiers quals) { throw new NotImplementedException(); } - public bool VisitDeclaration(Declaration decl) + public override bool VisitDeclaration(Declaration decl) { throw new NotImplementedException(); } - public bool VisitClassDecl(Class @class) + public override bool VisitClassDecl(Class @class) { var instance = string.Empty; @@ -197,8 +218,8 @@ namespace Cxxi.Generators.CLI public string QualifiedIdentifier(Declaration decl) { - if (Driver.Options.GenerateLibraryNamespace) - return string.Format("{0}::{1}", Driver.Options.OutputNamespace, + if (Context.Driver.Options.GenerateLibraryNamespace) + return string.Format("{0}::{1}", Context.Driver.Options.OutputNamespace, decl.QualifiedName); return string.Format("{0}", decl.QualifiedName); } @@ -206,77 +227,77 @@ namespace Cxxi.Generators.CLI public void WriteClassInstance(Class @class, string instance) { if (@class.IsRefType) - Return.Write("gcnew "); + Context.Return.Write("gcnew "); - Return.Write("{0}(", QualifiedIdentifier(@class)); - Return.Write("(::{0}*)", @class.QualifiedOriginalName); - Return.Write("{0})", instance); + Context.Return.Write("{0}(", QualifiedIdentifier(@class)); + Context.Return.Write("(::{0}*)", @class.QualifiedOriginalName); + Context.Return.Write("{0})", instance); } - public bool VisitFieldDecl(Field field) + public override bool VisitFieldDecl(Field field) { return field.Type.Visit(this); } - public bool VisitFunctionDecl(Function function) + public override bool VisitFunctionDecl(Function function) { throw new NotImplementedException(); } - public bool VisitMethodDecl(Method method) + public override bool VisitMethodDecl(Method method) { throw new NotImplementedException(); } - public bool VisitParameterDecl(Parameter parameter) + public override bool VisitParameterDecl(Parameter parameter) { return parameter.Type.Visit(this, parameter.QualifiedType.Qualifiers); } - public bool VisitTypedefDecl(TypedefDecl typedef) + public override bool VisitTypedefDecl(TypedefDecl typedef) { throw new NotImplementedException(); } - public bool VisitEnumDecl(Enumeration @enum) + public override bool VisitEnumDecl(Enumeration @enum) { - Return.Write("({0}){1}", ToCLITypeName(@enum), + Context.Return.Write("({0}){1}", ToCLITypeName(@enum), Context.ReturnVarName); return true; } - public bool VisitVariableDecl(Variable variable) + public override bool VisitVariableDecl(Variable variable) { throw new NotImplementedException(); } private string ToCLITypeName(Declaration decl) { - var typePrinter = new CLITypePrinter(Driver); + var typePrinter = new CLITypePrinter(Context.Driver); return typePrinter.VisitDeclaration(decl); } - public bool VisitClassTemplateDecl(ClassTemplate template) + public override bool VisitClassTemplateDecl(ClassTemplate template) { return template.TemplatedClass.Visit(this); } - public bool VisitFunctionTemplateDecl(FunctionTemplate template) + public override bool VisitFunctionTemplateDecl(FunctionTemplate template) { throw new NotImplementedException(); } - public bool VisitMacroDefinition(MacroDefinition macro) + public override bool VisitMacroDefinition(MacroDefinition macro) { throw new NotImplementedException(); } - public bool VisitNamespace(Namespace @namespace) + public override bool VisitNamespace(Namespace @namespace) { throw new NotImplementedException(); } - public bool VisitEvent(Event @event) + public override bool VisitEvent(Event @event) { throw new NotImplementedException(); } @@ -287,46 +308,32 @@ namespace Cxxi.Generators.CLI } } - public class CLIMarshalManagedToNativePrinter : ITypeVisitor, - IDeclVisitor + public class CLIMarshalManagedToNativePrinter : MarshalPrinter { - public TextGenerator SupportBefore; - public TextGenerator SupportAfter; - public TextGenerator Return; - public TextGenerator VarPrefix; - public TextGenerator ArgumentPrefix; + public readonly TextGenerator VarPrefix; + public readonly TextGenerator ArgumentPrefix; - ITypeMapDatabase TypeMapDatabase { get; set; } - MarshalContext Context { get; set; } - - public CLIMarshalManagedToNativePrinter(ITypeMapDatabase typeMap, - MarshalContext ctx) + public CLIMarshalManagedToNativePrinter(MarshalContext ctx) + : base(ctx) { - TypeMapDatabase = typeMap; - Context = ctx; - - SupportBefore = new TextGenerator(); - SupportAfter = new TextGenerator(); - Return = new TextGenerator(); VarPrefix = new TextGenerator(); ArgumentPrefix = new TextGenerator(); - Context.Return = Return; Context.MarshalToNative = this; } - public bool VisitTagType(TagType tag, TypeQualifiers quals) + public override bool VisitTagType(TagType tag, TypeQualifiers quals) { var decl = tag.Declaration; return decl.Visit(this); } - public bool VisitArrayType(ArrayType array, TypeQualifiers quals) + public override bool VisitArrayType(ArrayType array, TypeQualifiers quals) { return false; } - public bool VisitFunctionType(FunctionType function, TypeQualifiers quals) + public override bool VisitFunctionType(FunctionType function, TypeQualifiers quals) { var returnType = function.ReturnType; return returnType.Visit(this, quals); @@ -346,12 +353,12 @@ namespace Cxxi.Generators.CLI sb.Append("System::Runtime::InteropServices::Marshal::"); sb.Append("GetFunctionPointerForDelegate("); sb.AppendFormat("{0}).ToPointer())", Context.Parameter.Name); - Return.Write(sb.ToString()); + Context.Return.Write(sb.ToString()); return true; } - public bool VisitPointerType(PointerType pointer, TypeQualifiers quals) + public override bool VisitPointerType(PointerType pointer, TypeQualifiers quals) { var pointee = pointer.Pointee; @@ -364,18 +371,18 @@ namespace Cxxi.Generators.CLI if (isVoidPtr || isUInt8Ptr) { if (isUInt8Ptr) - Return.Write("({0})", "uint8*"); - Return.Write("{0}.ToPointer()", Context.Parameter.Name); + Context.Return.Write("({0})", "uint8*"); + Context.Return.Write("{0}.ToPointer()", Context.Parameter.Name); return true; } if (pointee.IsPrimitiveType(PrimitiveType.Char)) { - SupportBefore.Write( + Context.SupportBefore.WriteLine( "auto _{0} = clix::marshalString({1});", Context.ArgName, Context.Parameter.Name); - Return.Write("_{0}.c_str()", Context.ArgName); + Context.Return.Write("_{0}.c_str()", Context.ArgName); return true; } @@ -389,13 +396,13 @@ namespace Cxxi.Generators.CLI return pointee.Visit(this, quals); } - public bool VisitMemberPointerType(MemberPointerType member, + public override bool VisitMemberPointerType(MemberPointerType member, TypeQualifiers quals) { return false; } - public bool VisitBuiltinType(BuiltinType builtin, TypeQualifiers quals) + public override bool VisitBuiltinType(BuiltinType builtin, TypeQualifiers quals) { return VisitPrimitiveType(builtin.Type); } @@ -417,7 +424,7 @@ namespace Cxxi.Generators.CLI case PrimitiveType.UInt64: case PrimitiveType.Float: case PrimitiveType.Double: - Return.Write(Context.Parameter.Name); + Context.Return.Write(Context.Parameter.Name); return true; case PrimitiveType.WideChar: return false; @@ -426,12 +433,12 @@ namespace Cxxi.Generators.CLI return false; } - public bool VisitTypedefType(TypedefType typedef, TypeQualifiers quals) + public override bool VisitTypedefType(TypedefType typedef, TypeQualifiers quals) { var decl = typedef.Declaration; TypeMap typeMap = null; - if (TypeMapDatabase.FindTypeMap(decl, out typeMap)) + if (Context.Driver.TypeDatabase.FindTypeMap(decl, out typeMap)) { typeMap.CLIMarshalToNative(Context); return typeMap.IsValueType; @@ -447,17 +454,17 @@ namespace Cxxi.Generators.CLI PrimitiveType primitive; if (decl.Type.IsPrimitiveType(out primitive, walkTypedefs: true)) { - Return.Write("({0})", typedef.Declaration.Name); + Context.Return.Write("({0})", typedef.Declaration.Name); } return decl.Type.Visit(this); } - public bool VisitTemplateSpecializationType(TemplateSpecializationType template, + public override bool VisitTemplateSpecializationType(TemplateSpecializationType template, TypeQualifiers quals) { TypeMap typeMap = null; - if (TypeMapDatabase.FindTypeMap(template, out typeMap)) + if (Context.Driver.TypeDatabase.FindTypeMap(template, out typeMap)) { typeMap.Type = template; typeMap.CLIMarshalToNative(Context); @@ -467,27 +474,27 @@ namespace Cxxi.Generators.CLI return template.Template.Visit(this); } - public bool VisitTemplateParameterType(TemplateParameterType param, TypeQualifiers quals) + public override bool VisitTemplateParameterType(TemplateParameterType param, TypeQualifiers quals) { throw new NotImplementedException(); } - public bool VisitPrimitiveType(PrimitiveType type, TypeQualifiers quals) + public override bool VisitPrimitiveType(PrimitiveType type, TypeQualifiers quals) { throw new NotImplementedException(); } - public bool VisitDeclaration(Declaration decl, TypeQualifiers quals) + public override bool VisitDeclaration(Declaration decl, TypeQualifiers quals) { throw new NotImplementedException(); } - public bool VisitDeclaration(Declaration decl) + public override bool VisitDeclaration(Declaration decl) { throw new NotImplementedException(); } - public bool VisitClassDecl(Class @class) + public override bool VisitClassDecl(Class @class) { if (@class.IsValueType) { @@ -504,7 +511,7 @@ namespace Cxxi.Generators.CLI private void MarshalRefClass(Class @class) { TypeMap typeMap = null; - if (TypeMapDatabase.FindTypeMap(@class, out typeMap)) + if (Context.Driver.TypeDatabase.FindTypeMap(@class, out typeMap)) { typeMap.CLIMarshalToNative(Context); return; @@ -512,7 +519,7 @@ namespace Cxxi.Generators.CLI if (!Context.Parameter.Type.IsPointer()) { - Return.Write("*"); + Context.Return.Write("*"); if (Context.Parameter.Type.IsReference()) VarPrefix.Write("&"); @@ -523,13 +530,13 @@ namespace Cxxi.Generators.CLI && method.Conversion == MethodConversionKind.FunctionToInstanceMethod && Context.ParameterIndex == 0) { - Return.Write("(::{0}*)", @class.QualifiedOriginalName); - Return.Write("NativePtr"); + Context.Return.Write("(::{0}*)", @class.QualifiedOriginalName); + Context.Return.Write("NativePtr"); return; } - Return.Write("(::{0}*)", @class.QualifiedOriginalName); - Return.Write("{0}->NativePtr", Context.Parameter.Name); + Context.Return.Write("(::{0}*)", @class.QualifiedOriginalName); + Context.Return.Write("{0}->NativePtr", Context.Parameter.Name); } private void MarshalValueClass(Class @class) @@ -537,13 +544,12 @@ namespace Cxxi.Generators.CLI var marshalVar = "_marshal" + Context.ParameterIndex++; - SupportBefore.WriteLine("auto {0} = ::{1}();", marshalVar, + Context.SupportBefore.WriteLine("auto {0} = ::{1}();", marshalVar, @class.QualifiedOriginalName); - SupportBefore.PushIndent(); MarshalValueClassFields(@class, marshalVar); - Return.Write(marshalVar); + Context.Return.Write(marshalVar); if (Context.Parameter.Type.IsPointer()) ArgumentPrefix.Write("&"); @@ -577,20 +583,28 @@ namespace Cxxi.Generators.CLI ParameterIndex = Context.ParameterIndex++ }; - var marshal = new CLIMarshalManagedToNativePrinter(TypeMapDatabase, - marshalCtx); + var marshal = new CLIMarshalManagedToNativePrinter(marshalCtx); field.Visit(marshal); Context.ParameterIndex = marshalCtx.ParameterIndex; - if (!string.IsNullOrWhiteSpace(marshal.SupportBefore)) - SupportBefore.WriteLine(marshal.SupportBefore); + if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore)) + Context.SupportBefore.Write(marshal.Context.SupportBefore); + + if(field.Type.IsPointer()) + { + Context.SupportBefore.WriteLine("if ({0} != nullptr)", fieldRef); + Context.SupportBefore.PushIndent(); + } + + Context.SupportBefore.WriteLine("{0}.{1} = {2};", marshalVar, field.OriginalName, + marshal.Context.Return); - SupportBefore.WriteLine("{0}.{1} = {2};", marshalVar, field.OriginalName, - marshal.Return); + if(field.Type.IsPointer()) + Context.SupportBefore.PopIndent(); } - public bool VisitFieldDecl(Field field) + public override bool VisitFieldDecl(Field field) { Context.Parameter = new Parameter { @@ -601,59 +615,59 @@ namespace Cxxi.Generators.CLI return field.Type.Visit(this); } - public bool VisitFunctionDecl(Function function) + public override bool VisitFunctionDecl(Function function) { throw new NotImplementedException(); } - public bool VisitMethodDecl(Method method) + public override bool VisitMethodDecl(Method method) { throw new NotImplementedException(); } - public bool VisitParameterDecl(Parameter parameter) + public override bool VisitParameterDecl(Parameter parameter) { return parameter.Type.Visit(this); } - public bool VisitTypedefDecl(TypedefDecl typedef) + public override bool VisitTypedefDecl(TypedefDecl typedef) { throw new NotImplementedException(); } - public bool VisitEnumDecl(Enumeration @enum) + public override bool VisitEnumDecl(Enumeration @enum) { - Return.Write("(::{0}){1}", @enum.QualifiedOriginalName, + Context.Return.Write("(::{0}){1}", @enum.QualifiedOriginalName, Context.Parameter.Name); return true; } - public bool VisitVariableDecl(Variable variable) + public override bool VisitVariableDecl(Variable variable) { throw new NotImplementedException(); } - public bool VisitClassTemplateDecl(ClassTemplate template) + public override bool VisitClassTemplateDecl(ClassTemplate template) { return template.TemplatedClass.Visit(this); } - public bool VisitFunctionTemplateDecl(FunctionTemplate template) + public override bool VisitFunctionTemplateDecl(FunctionTemplate template) { throw new NotImplementedException(); } - public bool VisitMacroDefinition(MacroDefinition macro) + public override bool VisitMacroDefinition(MacroDefinition macro) { throw new NotImplementedException(); } - public bool VisitNamespace(Namespace @namespace) + public override bool VisitNamespace(Namespace @namespace) { throw new NotImplementedException(); } - public bool VisitEvent(Event @event) + public override bool VisitEvent(Event @event) { throw new NotImplementedException(); } diff --git a/src/Generator/Generators/CLI/CLISourcesTemplate.cs b/src/Generator/Generators/CLI/CLISourcesTemplate.cs index 5dcf0ec9..d416251e 100644 --- a/src/Generator/Generators/CLI/CLISourcesTemplate.cs +++ b/src/Generator/Generators/CLI/CLISourcesTemplate.cs @@ -186,20 +186,19 @@ namespace Cxxi.Generators.CLI ArgName = param.Name, }; - var marshal = new CLIMarshalManagedToNativePrinter(Driver.TypeDatabase, - ctx); + var marshal = new CLIMarshalManagedToNativePrinter(ctx); param.Visit(marshal); var variable = string.Format("((::{0}*)NativePtr)->{1}", @class.QualifiedOriginalName, field.OriginalName); - if (!string.IsNullOrWhiteSpace(marshal.SupportBefore)) - WriteLine(marshal.SupportBefore); + if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore)) + Write(marshal.Context.SupportBefore); - WriteLine("{0} = {1};", variable, marshal.Return); + WriteLine("{0} = {1};", variable, marshal.Context.Return); - if (!string.IsNullOrWhiteSpace(marshal.SupportAfter)) - WriteLine(marshal.SupportAfter); + if (!string.IsNullOrWhiteSpace(marshal.Context.SupportAfter)) + Write(marshal.Context.SupportAfter); WriteCloseBraceIndent(); NewLine(); @@ -220,10 +219,10 @@ namespace Cxxi.Generators.CLI ReturnType = field.Type }; - var marshal = new CLIMarshalNativeToManagedPrinter(Driver, ctx); + var marshal = new CLIMarshalNativeToManagedPrinter(ctx); field.Visit(marshal); - WriteLine("return {0};", marshal.Return); + WriteLine("return {0};", marshal.Context.Return); WriteCloseBraceIndent(); NewLine(); @@ -328,10 +327,10 @@ namespace Cxxi.Generators.CLI ReturnType = param.Type }; - var marshal = new CLIMarshalNativeToManagedPrinter(Driver, ctx); + var marshal = new CLIMarshalNativeToManagedPrinter(ctx); param.Visit(marshal); - returns.Add(marshal.Return); + returns.Add(marshal.Context.Return); } Write("{0}::raise(", @event.Name); @@ -411,10 +410,16 @@ namespace Cxxi.Generators.CLI ReturnType = field.Type }; - var marshal = new CLIMarshalNativeToManagedPrinter(Driver, ctx); + var marshal = new CLIMarshalNativeToManagedPrinter(ctx); field.Visit(marshal); - WriteLine("{0} = {1};", field.Name, marshal.Return); + if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore)) + Write(marshal.Context.SupportBefore); + + WriteLine("{0} = {1};", field.Name, marshal.Context.Return); + + if (!string.IsNullOrWhiteSpace(marshal.Context.SupportAfter)) + Write(marshal.Context.SupportAfter); } } @@ -498,14 +503,13 @@ namespace Cxxi.Generators.CLI ArgName = param.Name, }; - var marshal = new CLIMarshalManagedToNativePrinter(Driver.TypeDatabase, - ctx); + var marshal = new CLIMarshalManagedToNativePrinter(ctx); param.Visit(marshal); - if (!string.IsNullOrWhiteSpace(marshal.SupportBefore)) - WriteLine(marshal.SupportBefore); + if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore)) + Write(marshal.Context.SupportBefore); - names.Add(marshal.Return); + names.Add(marshal.Context.Return); } WriteLine("auto _native = ::{0}({1});", @class.QualifiedOriginalName, @@ -537,10 +541,10 @@ namespace Cxxi.Generators.CLI ReturnType = field.Type }; - var marshal = new CLIMarshalNativeToManagedPrinter(Driver, ctx); + var marshal = new CLIMarshalNativeToManagedPrinter(ctx); field.Visit(marshal); - WriteLine("this->{0} = {1};", field.Name, marshal.Return); + WriteLine("this->{0} = {1};", field.Name, marshal.Context.Return); } } @@ -621,10 +625,10 @@ namespace Cxxi.Generators.CLI ReturnType = retType }; - var marshal = new CLIMarshalNativeToManagedPrinter(Driver, ctx); + var marshal = new CLIMarshalNativeToManagedPrinter(ctx); function.ReturnType.Visit(marshal); - WriteLine("{0};", marshal.Return); + WriteLine("{0};", marshal.Context.Return); } } @@ -677,21 +681,20 @@ namespace Cxxi.Generators.CLI Function = function }; - var marshal = new CLIMarshalManagedToNativePrinter(Driver.TypeDatabase, - ctx); + var marshal = new CLIMarshalManagedToNativePrinter(ctx); param.Visit(marshal); - if (string.IsNullOrEmpty(marshal.Return)) + if (string.IsNullOrEmpty(marshal.Context.Return)) throw new Exception("Cannot marshal argument of function"); - if (!string.IsNullOrWhiteSpace(marshal.SupportBefore)) - WriteLine(marshal.SupportBefore); + if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore)) + Write(marshal.Context.SupportBefore); - WriteLine("auto {0}{1} = {2};", marshal.VarPrefix, argName, marshal.Return); + WriteLine("auto {0}{1} = {2};", marshal.VarPrefix, argName, marshal.Context.Return); - if (!string.IsNullOrWhiteSpace(marshal.SupportAfter)) - WriteLine(marshal.SupportAfter); + if (!string.IsNullOrWhiteSpace(marshal.Context.SupportAfter)) + Write(marshal.Context.SupportAfter); var argText = marshal.ArgumentPrefix + argName; return new ParamMarshal {Name = argText, Param = param}; diff --git a/src/Generator/Types/TypeMap.cs b/src/Generator/Types/TypeMap.cs index afab810e..0ff19047 100644 --- a/src/Generator/Types/TypeMap.cs +++ b/src/Generator/Types/TypeMap.cs @@ -9,15 +9,21 @@ namespace Cxxi.Types { public MarshalContext(Driver driver) { - + Driver = driver; + SupportBefore = new TextGenerator(); + SupportAfter = new TextGenerator(); + Return = new TextGenerator(); } - public Driver Driver { get; set; } + public Driver Driver { get; private set; } public CLIMarshalNativeToManagedPrinter MarshalToManaged; public CLIMarshalManagedToNativePrinter MarshalToNative; - public TextGenerator Return; + public TextGenerator SupportBefore { get; private set; } + public TextGenerator SupportAfter { get; private set; } + public TextGenerator Return { get; private set; } + public string ReturnVarName { get; set; } public Type ReturnType { get; set; } diff --git a/src/Generator/Utils/TextGenerator.cs b/src/Generator/Utils/TextGenerator.cs index a3abba17..e14a3905 100644 --- a/src/Generator/Utils/TextGenerator.cs +++ b/src/Generator/Utils/TextGenerator.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; using System.Text; @@ -24,16 +25,19 @@ namespace Cxxi public void Write(string msg, params object[] args) { - if (isStartOfLine) - sb.Append(new string(' ', (int)CurrentIndent.Sum(u => u))); - if (args.Length > 0) msg = string.Format(msg, args); - if (msg.Length > 0) - isStartOfLine = false; + foreach(var line in msg.SplitAndKeep(Environment.NewLine)) + { + if (isStartOfLine && !string.IsNullOrWhiteSpace(line)) + sb.Append(new string(' ', (int) CurrentIndent.Sum(u => u))); + + if (line.Length > 0) + isStartOfLine = line.EndsWith(Environment.NewLine); - sb.Append(msg); + sb.Append(line); + } } public void WriteLine(string msg, params object[] args) diff --git a/src/Generator/Utils/Utils.cs b/src/Generator/Utils/Utils.cs index 0d6c8c6e..3485a3d2 100644 --- a/src/Generator/Utils/Utils.cs +++ b/src/Generator/Utils/Utils.cs @@ -164,6 +164,17 @@ namespace Cxxi var str = Regex.Replace(input, "([A-Z])", " $1", RegexOptions.Compiled); return str.Trim().Split(); } + + public static IEnumerable SplitAndKeep(this string s, string seperator) + { + string[] obj = s.Split(new string[] { seperator }, StringSplitOptions.None); + + for (int i = 0; i < obj.Length; i++) + { + string result = i == obj.Length - 1 ? obj[i] : obj[i] + seperator; + yield return result; + } + } } public static class AssemblyHelpers