public static void Validate(this AST.Struct x) { foreach (var m in x.Fields) { m.Validate(); } }
public void DefineStruct(AST.Struct type) { bool useabi = Strata == ApiStrata.ABI; Namespace(type.Namespace, useabi, () => { Spacer(); if (!useabi) { WriteXmlDocumentation(type.XmlDoc); } foreach (var attr in type.Attributes) { WriteAttribute(attr); } Line($"{(useabi ? "internal" : "public")} struct {type.Name}"); Block(() => { foreach (var field in type.Fields) { WriteXmlDocumentation(field.XmlDoc); Line($"public {TypeRef(field)} {field.Name};"); } Spacer(); if (useabi) { var tn = TypeRef(type, false); Line($"public static {type.Name} ToABI({tn} x)"); Block(() => { Line($"return new {type.Name}"); Block(() => { List(CodeListStyle.MultiLine, () => { foreach (var field in type.Fields) { if (field.IsArray) { if (field.Type.IsPrimitive || field.Type.IsString) { ListItem("{0} = MConv_.ToABI_{1}(x.{0})", field.Name, field.Type.Name); } else if (field.Type.IsObject) { ListItem("{0} = MConv_.ToABI_Object(x.{0} == null ? IntPtr.Zero : (({1})x.{0}).IPtr)", field.Name, TypeRef(field, false)); } else { ListItem("{0} = ABI.{1}.MConv.ToABI{2}(x.{0})", field.Name, type.Assembly.Name, field.Type.ShortId); } } else if (field.Type.IsString) { ListItem("{0} = MConv_.ToABI_string(x.{0})", field.Name); } else if (field.Type.IsObject) { ListItem("{0} = MConv_.ToABI_Object(x.{0} == null ? IntPtr.Zero : (({1})x.{0}).IPtr)", field.Name, TypeRef(field, false)); } else if (field.Type.IsStruct && CsRender.RequiresABITranslation(field.Type.ToVariable())) { ListItem("{0} = {1}.ToABI(x.{0})", field.Name, TypeRef(field, true)); } else if (field.Type.IsDelegate) { ListItem("{0} = ABI.{1}.D{2}.Unwrap(x.{0})", field.Name, type.Assembly.Name, field.Type.ShortId); } else { ListItem("{0} = x.{0}", field.Name); } } }); }, ";"); }); Line($"public static {tn} FromABI({type.Name} x)"); Block(() => { Action <string> fill = prefix => { List(CodeListStyle.MultiLine, () => { foreach (var field in type.Fields) { if (field.IsArray) { if (field.Type.IsPrimitive || field.Type.IsString) { ListItem(prefix + "MConv_.FromABI_{1}(x.{0}.Ptr, x.{0}.Count)", field.Name, field.Type.Name); } else if (field.Type.IsObject) { ListItem(prefix + "MConv_.FromABI_Object<{1}>(x.{0}.Ptr, x.{0}.Count)", TypeRef(field.Type, false), field.Name); } else { ListItem(prefix + "ABI.{1}.MConv.FromABI{2}(x.{0}.Ptr, x.{0}.Count)", field.Name, type.Assembly.Name, field.Type.ShortId); } } else if (field.Type.IsString) { ListItem(prefix + "MConv_.FromABI_string(x.{0})", field.Name); } else if (field.Type.IsObject) { ListItem(prefix + "GluonObject.Of<{1}>(x.{0})", field.Name, TypeRef(field.Type, false)); } else if (field.Type.IsStruct && CsRender.RequiresABITranslation(field.Type.ToVariable())) { ListItem(prefix + "{1}.FromABI(x.{0})", field.Name, TypeRef(field, true)); } else if (field.Type.IsDelegate) { ListItem(prefix + "ABI.{1}.D{2}.Wrap(x.{0}.Fn, x.{0}.Ctx)", field.Name, type.Assembly.Name, field.Type.ShortId); } else { ListItem(prefix + "x.{0}", field.Name); } } }); }; if (type.PredefinedFullConstructor) { Line($"return new {tn}("); Indent++; fill(""); Indent--; Line(");"); } else { Line($"return new {tn}"); Block(() => fill("{0} = "), ";"); } }); Line( @"public static {0}[] ToABI_Array({1}[] x) {{ if (x == null) return null; var r = new {0}[x.Length]; for (int i = 0; i < x.Length; i++) r[i] = ToABI(x[i]); return r; }} public static {1}[] FromABI_Array({0}[] x) {{ if (x == null) return null; var r = new {1}[x.Length]; for (int i = 0; i < x.Length; i++) r[i] = FromABI(x[i]); return r; }}", type.Name, tn); } else { Line("public {0}({1})", type.Name, DeclParameters(type.Fields.Select(f => f.Morph("_" + f.Name)))); Block(() => { foreach (var field in type.Fields) { Line("{0} = _{0};", field.Name); } }); } }); }); }
public void GenerateStruct(AST.Struct type, bool abi) { var strata = Strata; Guid id = (strata == ApiStrata.ABI ? type.Id : type.PrivateId); Namespace(type.Namespace, abi, () => { var localTranslations = CppRender.GetLocalTranslations(type); if (strata == ApiStrata.ABI) { localTranslations = null; } var fields = type.Fields; Spacer(); WriteXmlDocumentation(type.XmlDoc); Line("struct comid(\"{0}\") {1}", id, type.Name); Block(() => { if (strata == ApiStrata.Normal && CppRender.RequiresABITranslation(type.ToVariable())) { Line("typedef {0} ABIType;", TypeRef(type, true)); Spacer(); } if (localTranslations != null) { UseLocalTranslations = false; foreach (var kvp in localTranslations) { Line("using {0} = {1};", kvp.Value, TypeRef(kvp.Key, false)); } UseLocalTranslations = true; Spacer(); } LocalTranslationsBlock(localTranslations, () => { foreach (var field in fields) { WriteXmlDocumentation(field.XmlDoc); Line("{0} {1};", VariableType(field, AST.VariableContext.Member), field.Name); } Spacer(); // Default constructor Line("{0}() {{ }}", type.Name); // Full constructor var constructorArgs = fields.Select(f => f.Morph("_" + f.Name, AST.VariableContext.In)); if (strata == ApiStrata.ABI) { constructorArgs = constructorArgs.GetABIParametersCpp(); } Line("{0}({1}) : ", type.Name, DeclParameters(constructorArgs)); Indent++; List(() => { foreach (var field in fields) { if (strata == ApiStrata.ABI && field.IsArray) { ListItem("{0}(_{0}, _{0}_count)", field.Name); } else if (strata == ApiStrata.ABI && field.Type.IsDelegate) { ListItem("{0}(_{0}, _{0}_context)", field.Name); } else { ListItem("{0}(_{0})", field.Name); } } }); Indent--; Line(); Line("{ }"); }); }, ";"); }); var prefix = (abi ? "::ABI" : ""); if (type.Namespace.IsGlobal) { Line(@"IS_VALUETYPE({0}::{1}, ""{2}"");", prefix, type.Name, id); } else { Line(@"IS_VALUETYPE({0}::{1}::{2}, ""{3}"");", prefix, type.Namespace.FullName("::"), type.Name, id); } }
public Type Resolve(System.Type type) { if (type == null) { return(null); } if (type.IsByRef) { return(Resolve(type.GetElementType())); } if (type.IsArray) { return(Resolve(type.GetElementType())); } Type ret; if (_typeMap.TryGetValue(type, out ret)) { return(ret); } ret = BasicTypes.Of(type); if (ret != null) { _typeMap[type] = ret; return(ret); } switch (ConstructOf(type)) { case Construct.Void: ret = new Void(); break; case Construct.Primitive: ret = new Primitive(); break; case Construct.Enum: ret = new Enum(); break; case Construct.String: ret = new String(); break; case Construct.Delegate: ret = new Delegate(); break; case Construct.Task: ret = new Task(); break; case Construct.Struct: ret = new Struct(); break; case Construct.Object: ret = new Object(); break; default: Debug.Assert(false); return(null); } _typeMap[type] = ret; Product.AllTypes.Add(ret); ret.Name = type.Name; ret.Namespace = Resolve(type.Namespace); ret.Assembly = Resolve(type.Assembly); ret.XmlDoc = XmlDocReader.XMLFromType(type); ret.IsAttribute = typeof(System.Attribute).IsAssignableFrom(type); var nativeAttr = type.GetCustomAttribute <NativeAttribute>(); if (ret.IsDelegate && ((AST.Delegate)ret).IsGeneric || ret.IsTask) { ret.Origin = TypeOrigin.Mapped; } else if (!ret.Assembly.IsGluonDefinition) { if (ret.ConstructType == Construct.Object) { ret.IsPureReference = true; } ret.Origin = TypeOrigin.Managed; } else if (nativeAttr == null) { ret.Origin = TypeOrigin.Gluon; } else { if (ret.ConstructType == Construct.Object) { ret.IsPureReference = true; } ret.Origin = TypeOrigin.Native; ret.CppHeader = nativeAttr.Header; ret.CppLib = nativeAttr.StaticLibrary; } foreach (var attr in type.GetCustomAttributesData()) { ret.Attributes.Add(Resolve(attr)); } int isPublic = (type.GetCustomAttribute <PublicAttribute>() != null ? 1 : 0); int isProtected = (type.GetCustomAttribute <ProtectedAttribute>() != null ? 1 : 0); int isInternal = (type.GetCustomAttribute <InternalAttribute>() != null ? 1 : 0); int isPrivate = (type.GetCustomAttribute <PrivateAttribute>() != null ? 1 : 0); ret.Access = Access.Public; if (isPublic + isProtected + isInternal + isPrivate > 1) { Errors.Generic(type.FullName + " has multiple, conflicting access attributes"); } else if (isPublic == 1) { ret.Access = Access.Public; } else if (isProtected == 1) { ret.Access = Access.Protected; } else if (isInternal == 1) { ret.Access = Access.Internal; } else if (isPrivate == 1) { ret.Access = Access.Private; } if (!ret.IsPureReference) { Merge(ret, type); } return(ret); }