Beispiel #1
0
 public static void Validate(this AST.Struct x)
 {
     foreach (var m in x.Fields)
     {
         m.Validate();
     }
 }
Beispiel #2
0
        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);
                            }
                        });
                    }
                });
            });
        }
Beispiel #3
0
        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);
            }
        }
Beispiel #4
0
        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);
        }