public void GenerateClassDeclaration(AST.Object type, bool fullIntellisense = false, Action additionalDeclarations = null) { // Set up generator state, figure out the class ID, other vars Strata = ApiStrata.Normal; // Class Signature Line($"class comid(\"{type.PrivateId}\")"); Code("{0} : public ComObject<{0}, {1}, {2}", type.Name, type.BaseType != null ? TypeRef(type.BaseType) : "Object", TypeRef(type, true)); foreach (var iface in type.Interfaces) { Code($", {TypeRef(iface, true)}"); } Line(">"); Line("{"); GenerateClassHeaderMembers(type, fullIntellisense); if (additionalDeclarations != null) { Spacer(); additionalDeclarations(); } Code("};"); }
public void GenerateMethodDeclaration(AST.Object type, AST.Method method) { bool isOverride = type.IsMethodOverride(method); if (method.IsAbstract || (method.IsVirtual && !isOverride)) { Code("virtual "); } Code("{0} {1}({2})", VariableType(method.Return), method.Name, DeclParameters(true, method.Parameters)); if (method.IsConst) { Code(" const"); } if (isOverride) { Line(" override;"); } else if (method.IsAbstract) { Line(" = 0;"); } else { Line(";"); } }
public void EventABIImplementation(AST.Event ev, AST.Object owner) { Debug.Assert(Strata == ApiStrata.ABI); Line("HRESULT {0}::_Add{1}Handler({2} handler, IObject* context)", TypeRef(owner, false), ev.Name, TypeRef(ev.HandlerType)); Block(() => { Code("try "); Block(() => { Line("{0} += ABIUtil<{1}>::FromABI(handler, context);", ev.Name, TypeRef(ev.HandlerType, false)); Line("return S_OK;"); }, " TRANSLATE_EXCEPTIONS"); }); Line("HRESULT {0}::_Remove{1}Handler({2} handler, IObject* context)", TypeRef(owner, false), ev.Name, TypeRef(ev.HandlerType)); Block(() => { Code("try "); Block(() => { Line("{0} -= ABIUtil<{1}>::FromABI(handler, context);", ev.Name, TypeRef(ev.HandlerType, false)); Line("return S_OK;"); }, " TRANSLATE_EXCEPTIONS"); }); }
private void WriteInterfaceMembersUsingComImport(AST.Object type) { foreach (var m in type.Methods) { if (type.IsMethodOverride(m)) { continue; } WriteInterfaceMemberUsingComImport(m); } foreach (var p in type.Properties) { var getter = p.CreateGetter(); if (!type.IsMethodOverride(getter)) { WriteInterfaceMemberUsingVTableWrapper(getter); } if (!p.IsReadOnly) { var setter = p.CreateSetter(); if (!type.IsMethodOverride(setter)) { WriteInterfaceMemberUsingVTableWrapper(p.CreateSetter()); } } } foreach (var e in type.Events) { WriteInterfaceMemberUsingComImport(e.CreateAdder()); WriteInterfaceMemberUsingComImport(e.CreateRemover()); } }
public void GenerateInterface(AST.Object type, bool fullIntellisense = false) { Strata = ApiStrata.ABI; Line($"cominterface comid(\"{type.Id}\") {type.Name} : public IUnknown"); Block(() => { GenerateInterfaceMembers(type, true, fullIntellisense); }, ";"); }
public void DeclareABIConstructors(AST.Object type) { Strata = ApiStrata.ABI; if (!type.IsAbstract) { foreach (var constructor in type.Constructors) { Line($"ABI_CONSTRUCTOR {constructor.GetABIConstructorName(type)}({DeclParameters(constructor.GetABIParametersCpp(), $"{TypeRef(type, true)}** outInstance")});"); } } }
public void WrapperConstructorImplementation(AST.Constructor c, AST.Object owner) { Line($"{TypeRef(owner)} {owner.Namespace.FullName("::")}::Create{owner.Name}({DeclParameters(c.Parameters)})"); Block(() => { Line($"{TypeRef(owner, true)}* instance;"); CallToABIMethodBody(c.Rename(c.GetABIConstructorName(owner))); Line($"return ::ABI::Wrap<{TypeRef(owner)}>(instance);"); }); }
public Dictionary <AST.Type, string> GenerateLocalTranslations(AST.Object type) { var localTranslations = CppRender.GetLocalTranslations(type); UseLocalTranslations = false; foreach (var kvp in localTranslations) { Line("using {0} = {1};", kvp.Value, TypeRef(kvp.Key, false)); } UseLocalTranslations = true; return(localTranslations); }
public void GenerateInterfaceMembers(AST.Object type, bool pure, bool fullIntellisense = false) { var suffix = pure ? " = 0" : ""; if (!fullIntellisense) { Directive("#ifndef __INTELLISENSE__"); } Region(() => { Action <AST.Method> declare = m => { if (type.IsMethodOverride(m)) { return; } Line($"METHOD _{m.GetComCompatibleName()}({DeclParameters(m.GetABIParametersCpp())}){suffix};"); }; foreach (var method in type.Methods) { declare(method); } Spacer(); foreach (var prop in type.Properties) { declare(prop.CreateGetter()); if (!prop.IsReadOnly) { declare(prop.CreateSetter()); } } Spacer(); foreach (var ev in type.Events) { declare(ev.CreateAdder()); declare(ev.CreateRemover()); } }); if (!fullIntellisense) { Directive("#endif"); } }
private void DefineWrapperClass(AST.Object type) { var abiName = TypeRef(type, true); WriteXmlDocumentation(type.XmlDoc); Line($"[Guid(\"{type.PrivateId}\")]"); Line($"[GluonGenerated(abi: typeof(global::ABI.{type.FullName(".")}))]"); foreach (var attr in type.Attributes) { WriteAttribute(attr); } Line("{0} {3} class {1} : {2}", type.Access.ToString().ToLower(), type.Name, type.BaseType != null ? TypeRef(type.BaseType) : "GluonObject", type.IsAbstract ? "abstract partial" : "partial"); Block(() => { Line( $@"static partial void StaticInit(); partial void Init(); partial void PartialDispose(bool finalizing); static {type.Name}() {{ ABI.{type.Assembly.Name}.Native.RegisterTypes(); StaticInit(); }}"); Spacer(); foreach (var c in type.Constructors) { WriteXmlDocumentation(c.XmlDoc); if (c.Parameters.Count == 0) { LineStyle = CodeLineStyle.SingleLine; } Line( $@"{c.Access.ToString().ToLower()} {type.Name}({DeclParameters(c.Parameters)}) : this(new AbiPtr(Make({List(c.Parameters, arg => { var adorn = arg.IsRef ? "ref " : arg.IsOut ? "out " : ""; return $"{adorn}{arg.Name}"; })}))) {{ {ForEach(type.Events, e => Line( $"_{e.Name}_abi = D{e.HandlerType.ShortId}.Unwrap(_Call_{e.Name});"))} Init(); }}"); Spacer(); LineStyle = CodeLineStyle.Standard; }
public void DefineClass(AST.Object type) { bool useabi = Strata == ApiStrata.ABI; Namespace(type.Namespace, useabi, () => { if (!useabi) { DefineWrapperClass(type); } else { DefineInterfaceUsingVTableWrapper(type); } }); }
public static void Validate(this AST.Object x) { foreach (var p in x.Properties) { p.Validate(); } foreach (var c in x.Constructors) { c.Validate(); } foreach (var m in x.Methods) { m.Validate(); } }
private void DefineInterfaceUsingVTableWrapper(AST.Object type) { Strata = ApiStrata.ABI; foreach (var attr in type.Attributes) { WriteAttribute(attr); } Line("[Guid(\"{0}\")]", type.Id); Line("[StructLayout(LayoutKind.Sequential)]"); Line("internal struct {0}", type.Name); Block(() => { Line("public readonly VTUnknown Unknown;"); Spacer(); WriteInterfaceMembersUsingVTableWrapper(type); }); if (!type.IsAbstract) { Line("internal static partial class Factory", type.Name); Block(() => { if (type.Constructors.Count == 0) { Line("[DllImport(Native.DllPath)]"); Line("public static extern int Create_{0}(out IntPtr newInstance);", type.FullName("_")); Spacer(); } int index = 1; foreach (var c in type.Constructors) { Line("[DllImport(Native.DllPath)]"); Line("public static extern int Create_{0}_{1}({2});", type.FullName("_"), index, DeclParameters(c.GetABIParametersCs(), "out IntPtr newInstance")); Spacer(); index++; } }); } }
public void GenerateWrapperImplementation(AST.Object type) { var localTranslations = CppRender.GetLocalTranslations(type); LocalTranslationsBlock(localTranslations, () => { foreach (var ctor in type.Constructors.Where(c => c.Access == AST.Access.Public)) { WrapperConstructorImplementation(ctor, type); } Spacer(); foreach (var member in type.Members.OrderBy(m => m.ConstructType)) { switch (member) { case AST.Constructor ctor: break; case AST.Property prop: MethodImplementation(prop.CreateGetter().AsConst(), type); if (!prop.IsReadOnly) { MethodImplementation(prop.CreateSetter().AsConst(), type); } break; case AST.Event ev: MethodImplementation(ev.CreateAdder().AsConst(), type); MethodImplementation(ev.CreateRemover().AsConst(), type); break; case AST.Method method: MethodImplementation(method.AsConst(), type); break; default: throw new Exception("Oops, unhandled member type: " + member.ConstructType.ToString()); } } }); }
private void DefineInterfaceUsingComImport(AST.Object type) { Strata = ApiStrata.ABI; foreach (var attr in type.Attributes) { WriteAttribute(attr); } Line("[ComImport, Guid(\"{0}\")]", type.Id); Line("[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]"); Code("internal interface {0}", type.Name); Block(() => { WriteInterfaceMembersUsingComImport(type); }); if (!type.IsAbstract) { Line("internal static partial class Factory", type.Name); Block(() => { if (type.Constructors.Count == 0) { Line("[DllImport(Native.DllPath)]"); Line("public static extern int Create_{0}(out {1} newInstance);", type.FullName("_"), type.Name); Spacer(); } int index = 1; foreach (var c in type.Constructors) { Line("[DllImport(Native.DllPath)]"); Line("public static extern int Create_{0}_{1}({2});", type.FullName("_"), index, DeclParameters(c.GetABIParametersCs(), "out " + type.Name + " newInstance")); Spacer(); index++; } }); } }
public void GenerateWrapperDeclaration(AST.Object type, Action additionalDeclarations = null) { Strata = ApiStrata.Normal; foreach (var ctor in type.Constructors.Where(c => c.Access == AST.Access.Public)) { WriteXmlDocumentation(ctor.XmlDoc); Line($"{type.Name} Create{type.Name}({DeclParameters(ctor.Parameters)});"); } Spacer(); WriteXmlDocumentation(type.XmlDoc); Line($"class {type.Name} : public {(type.BaseType != null ? TypeRef(type.BaseType) : "ABI::Wrapper")}"); Line("{"); GenerateWrapperHeaderMembers(type); if (additionalDeclarations != null) { Spacer(); additionalDeclarations(); } Code("};"); }
public static string GetABIConstructorName(this AST.Constructor ctor, AST.Object owner) { int index = owner.Constructors.IndexOf(ctor) + 1; return($"Create_{owner.FullName("_")}_{index}"); }
public void ConstructorImplementation(AST.Constructor c, AST.Object owner, Action implementation = null, IEnumerable <string> initializers = null) { if (Strata == ApiStrata.Normal) { Code("{0}::{1}({2})", TypeRef(owner), owner.Name, DeclParameters(c.Parameters)); if (owner.BaseType != null && owner.BaseType.Constructors.Count != 0 && owner.BaseType.Constructors[0].Parameters.Count != 0) { Code(" : "); List(() => { if (Settings.Mode == CppMode.PimplWrapper) { Line($"{owner.BaseType.Name}(nullptr)"); } else { Code("Base("); List(() => { var bc = owner.BaseType.Constructors[0]; foreach (var bcarg in bc.Parameters) { ListItem("DEFAULT_({0})", TypeRef(bcarg)); } }); Line(")"); NextListItem(); if (initializers != null) { foreach (var str in initializers) { ListItem(str); } } } }); } else { Line(); } if (implementation == null) { Block(() => Line("Not_Implemented_Warning")); } else { Block(() => implementation()); } } else { Line($"ABI_CONSTRUCTOR {c.GetABIConstructorName(owner)}({DeclParameters(c.GetABIParametersCpp(), $"{TypeRef(owner, true)}** outInstance")})"); Block(() => { if (implementation != null) { implementation(); return; } Code("try "); Block(() => { ABIWrapperParameterValidation(c); Line("if(!outInstance) return E_POINTER;"); Line($"*outInstance = new {TypeRef(owner, false)}("); List(CodeListStyle.MultiLine, () => { Indent++; foreach (var arg in c.Parameters) { string extra = ""; if (arg.IsArray) { extra = ", " + arg.Name + "_count"; } else if (arg.Type.IsDelegate) { extra = ", " + arg.Name + "_context"; } ListItem($"ABIUtil<{TypeRef(arg, false)}>::{(arg.IsWriteable() ? "Ref" : "FromABI")}({arg.Name}{extra})"); } Indent--; }); Line(");"); Line("return S_OK;"); }, " TRANSLATE_EXCEPTIONS"); }); } }
public void GenerateWrapperHeaderMembers(AST.Object type) { Line("#pragma region Gluon Maintained"); Line("// clang-format off"); Line($" typedef {(type.BaseType == null ? "ABI::Wrapper" : TypeRef(type.BaseType))} Base;"); Line($" WRAPPER_CORE({type.Name}, ::ABI::{type.FullName("::")})"); AST.Construct currentConstruct = AST.Construct.Constructor; Indent++; Region(() => { var localTranslations = GenerateLocalTranslations(type); UseLocalTranslations = true; LocalTranslationsBlock(localTranslations, () => { //Spacer(); //Line($"{type.Name}();"); //Line($"{type.Name}(std::nullptr_t);"); //Line($"{type.Name}(const {type.Name}& copy);"); //Line($"{type.Name}({type.Name}&& move);"); var currentAccess = AST.Access.Private; foreach (var member in type.Members /*.Where(m => m.Access == AST.Access.Public)*/.OrderBy(m => m.ConstructType).OrderBy(m => m.Access)) { if (member is AST.Constructor) { continue; } if (member.ConstructType != currentConstruct) { Spacer(); currentConstruct = member.ConstructType; } if (member.Access != currentAccess) { Spacer(); Indent--; Line($"{member.Access.ToString().ToLower()}:"); Indent++; currentAccess = member.Access; } WriteXmlDocumentation(member.XmlDoc); switch (member) { case AST.Constructor constructor: //Line("{0}({1});", type.Name, DeclParameters(true, constructor.Parameters)); break; case AST.Event ev: Line($"VirtualEvent<{Signature(ev)}, {type.Name}> {ev.Name}"); Line(" {{ this, &{0}::Add{1}Handler, &{0}::Remove{1}Handler }};", type.Name, ev.Name); break; case AST.Property prop: Line("PROPERTY{0}({1}, {2});", prop.IsReadOnly ? "_READONLY" : "", VariableType(prop, (prop.Type.IsStruct || prop.Type.IsDelegate || (prop.Type.IsObject && prop.IsFactory)) ? AST.VariableContext.Return : AST.VariableContext.In), prop.Name); GenerateMethodDeclaration(type, prop.CreateGetter().AsConst()); if (!prop.IsReadOnly) { GenerateMethodDeclaration(type, prop.CreateSetter().AsConst()); } break; case AST.Method method: GenerateMethodDeclaration(type, method.AsConst()); break; default: throw new Exception("Oops, unhandled member type: " + member.ConstructType.ToString()); } } var allEvents = type.Members.Where(m => m.Access == AST.Access.Public).OfType <AST.Event>().ToArray(); if (allEvents != null && allEvents.Length > 0) { Spacer(); Indent--; Line("private:"); Indent++; Spacer(); foreach (var ev in allEvents) { GenerateMethodDeclaration(type, ev.CreateAdder().AsConst()); GenerateMethodDeclaration(type, ev.CreateRemover().AsConst()); } } }); }); Indent--; Spacer(); Line("// clang-format on"); Line("#pragma endregion"); }
public void GenerateClass(CsTreeWriter file, AST.Object type) { file.DefineClass(type); }
public void GenerateClassHeaderMembers(AST.Object type, bool fullIntellisense = false) { if (type.Origin != TypeOrigin.MappedIntermediary) { Line("#pragma region Gluon Maintained"); Line("// clang-format off"); } Region(() => { Indent++; var localTranslations = GenerateLocalTranslations(type); Indent--; Spacer(); LocalTranslationsBlock(localTranslations, () => { Line("public:"); Indent++; // ABI type declaration Line("typedef {0} ABIType;", TypeRef(type, true)); Spacer(); AST.Access currentAccess = AST.Access.Public; AST.Construct currentConstruct = AST.Construct.Void; foreach (var member in type.Members.OrderBy(m => m.Access)) { var access = member.Access; if (access == AST.Access.Internal) { access = AST.Access.Public; } if (access != currentAccess) { currentAccess = access; Indent--; Spacer(); Line(access.ToString().ToLower() + ":"); Indent++; } var construct = member.ConstructType; if (construct != currentConstruct) { Spacer(); currentConstruct = construct; } switch (construct) { case AST.Construct.Constructor: { var constructor = (AST.Constructor)member; Line("{0}({1});", type.Name, DeclParameters(true, constructor.Parameters)); } break; case AST.Construct.Event: { var ev = (AST.Event)member; if (ev.IsAbstract || ev.IsVirtual) { Line("VirtualEvent<{0}, {1}> {2}", Signature(ev), type.Name, ev.Name); Line(" {{ this, &{0}::Add{1}Handler, &{0}::Remove{1}Handler }};", type.Name, ev.Name); } else { Line("Event<{0}> {1} {{_{1}}};", Signature(ev), ev.Name); } } break; case AST.Construct.Property: { var prop = (AST.Property)member; Spacer(); Line("PROPERTY{0}({1}, {2});", prop.IsReadOnly ? "_READONLY" : "", VariableType(prop, (prop.Type.IsStruct || prop.Type.IsDelegate || (prop.Type.IsObject && prop.IsFactory)) ? AST.VariableContext.Return : AST.VariableContext.In), prop.Name); GenerateMethodDeclaration(type, prop.CreateGetter()); if (!prop.IsReadOnly) { GenerateMethodDeclaration(type, prop.CreateSetter()); } } break; case AST.Construct.Method: { var method = (AST.Method)member; GenerateMethodDeclaration(type, method); } break; default: throw new Exception("Oops, unhandled member type: " + construct.ToString()); } } Spacer(); if (currentAccess != AST.Access.Public) { Indent--; Line("public:"); Indent++; currentAccess = AST.Access.Public; } // Wrapped Interface Implementation foreach (var iface in type.Interfaces) { if (iface.Origin == TypeOrigin.Native) { continue; } BlockComment(() => Code(iface.Name)); foreach (var method in iface.Methods) { GenerateMethodDeclaration(type, method); } Spacer(); } Spacer(); foreach (var ev in type.Events) { if (currentAccess != AST.Access.Private) { Indent--; Line("private:"); Indent++; currentAccess = AST.Access.Private; } if (ev.IsAbstract || ev.IsVirtual) { Line("virtual void Add{0}Handler(const Delegate<{1}>& handler){2};", ev.Name, Signature(ev), ev.IsAbstract ? " = 0" : ""); Line("virtual void Remove{0}Handler(const Delegate<{1}>& handler){2};", ev.Name, Signature(ev), ev.IsAbstract ? " = 0" : ""); } else { Line("EventTrigger<{0}> _{1};", Signature(ev), ev.Name); } } Spacer(); Strata = ApiStrata.ABI; if (currentAccess != AST.Access.Private) { Indent--; Line("private:"); Indent++; currentAccess = AST.Access.Private; } // ABI interface members GenerateInterfaceMembers(type, false, fullIntellisense); Spacer(); foreach (var iface in type.Interfaces) { if (iface.Origin == TypeOrigin.Native) { continue; } GenerateInterfaceMembers(iface, false, fullIntellisense); Spacer(); } Strata = ApiStrata.Normal; }); }); Indent--; if (type.Origin != TypeOrigin.MappedIntermediary) { Line("// clang-format on"); Line("#pragma endregion"); } }