Пример #1
0
 public void GenerateValueTypesABI(CsTreeWriter file)
 {
     foreach (var type in AllGeneratedStructs.Where(t => CsRender.RequiresABITranslation(t.ToVariable())))
     {
         file.DefineStruct(type);
     }
 }
Пример #2
0
        private void Render(PascalTreeWriter treeWriter, string path)
        {
            var writer = new CsRender();

            treeWriter.InsertUsings();
            treeWriter.Tree.Resolve(writer);
            writer.Write(path);
            OutputFiles.Add(path);
        }
Пример #3
0
        public static string GenerateConverter(AST.IVariable v, VariableContext ctx, bool isCallback)
        {
            var requiresTranslation = CsRender.RequiresABITranslation(v);
            var channels            = GetChannels(v);

            if (v.IsArray)
            {
                return(null);
            }
            if (v.IsRef && v.Type.IsObject)
            {
                return(null);
            }

            if (!requiresTranslation)
            {
                return(NoTranslation[TranslationIndex(ctx, isCallback)]);
            }
            else
            {
                if (channels == null)
                {
                    return(_Replacer.Replace(BasicTranslation[TranslationIndex(ctx, isCallback)],
                                             m =>
                    {
                        var label = m.Groups["Label"];
                        var format = m.Groups["Format"];

                        if (!label.Success)
                        {
                            return m.Value;
                        }
                        if (label.Value == "ToABI")
                        {
                            string fmt = format.Success ? format.Value.Replace("$", "{0}") : "{0}";
                            return ToABI[v.Type.ConstructType].Replace("{0}", fmt);
                        }
                        else if (label.Value == "FromABI")
                        {
                            string fmt = format.Success ? format.Value.Replace("$", "{0}") : "{0}";
                            return FromABI[v.Type.ConstructType].Replace("{0}", fmt);
                        }
                        else
                        {
                            return m.Value;
                        }
                    }));
                }
            }

            return(null);
        }
Пример #4
0
        public static VarConversion Get(IVariable v, PascalTreeWriter writer, bool unwrap)
        {
            string conv;

            if (v == null)
            {
                return(null);
            }
            if (v.IsVoid)
            {
                return(null);
            }

            conv = GenerateConverter(v, v.Context, unwrap);

            if (conv == null)
            {
                if (unwrap)
                {
                    if (v.IsArray)
                    {
                        if (v.Type.IsPrimitive || v.Type.IsString)
                        {
                            conv = PrimitiveArrayCBConverters[(int)v.Context];
                        }
                        else if (v.Type.IsStruct)
                        {
                            if (CsRender.RequiresABITranslation(v))
                            {
                                conv = StructArrayCBConverters[(int)v.Context];
                            }
                            else
                            {
                                conv = BlittableStructArrayCBConverters[(int)v.Context];
                            }
                        }
                        else if (v.Type.IsObject)
                        {
                            conv = ObjectArrayCBConverters[(int)v.Context];
                        }
                        else if (v.Type.IsDelegate)
                        {
                            conv = DelegateArrayCBConverters[(int)v.Context];
                        }
                        else
                        {
                            return(null);
                        }
                    }
                    else if (!CsRender.RequiresABITranslation(v))
                    {
                        conv = PrimitiveCBConverters[(int)v.Context];
                    }
                    else if (v.Type.IsStruct)
                    {
                        conv = StructCBConverters[(int)v.Context];
                    }
                    else if (v.Type.IsObject)
                    {
                        conv = ObjectCBConverters[(int)v.Context];
                    }
                    else if (v.Type.IsString)
                    {
                        conv = StringCBConverters[(int)v.Context];
                    }
                    else if (v.Type.IsDelegate)
                    {
                        conv = DelegateCBConverters[(int)v.Context];
                    }
                    else
                    {
                        return(null);
                    }
                }
                else
                {
                    if (v.IsArray)
                    {
                        if (v.Type.IsPrimitive || v.Type.IsString)
                        {
                            conv = PrimitiveArrayConverters[(int)v.Context];
                        }
                        else if (v.Type.IsStruct)
                        {
                            if (CsRender.RequiresABITranslation(v))
                            {
                                conv = StructArrayConverters[(int)v.Context];
                            }
                            else
                            {
                                conv = BlittableStructArrayConverters[(int)v.Context];
                            }
                        }
                        else if (v.Type.IsObject)
                        {
                            conv = ObjectArrayConverters[(int)v.Context];
                        }
                        else if (v.Type.IsDelegate)
                        {
                            conv = DelegateArrayConverters[(int)v.Context];
                        }
                        else
                        {
                            return(null);
                        }
                    }
                    else if (!CsRender.RequiresABITranslation(v))
                    {
                        conv = PrimitiveConverters[(int)v.Context];
                    }
                    else if (v.Type.IsStruct)
                    {
                        conv = StructConverters[(int)v.Context];
                    }
                    else if (v.Type.IsObject)
                    {
                        conv = ObjectConverters[(int)v.Context];
                    }
                    else if (v.Type.IsString)
                    {
                        conv = StringConverters[(int)v.Context];
                    }
                    else if (v.Type.IsDelegate)
                    {
                        conv = DelegateConverters[(int)v.Context];
                    }
                    else
                    {
                        return(null);
                    }
                }
            }

            return(new VarConversion(conv,
                                     v.Name,
                                     writer.TypeRef(v.Morph(null, null, null, false), false),
                                     writer.TypeRef(v.Morph(null, null, null, false), true),
                                     v.Type.ShortId));
        }
Пример #5
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);
                            }
                        });
                    }
                });
            });
        }
Пример #6
0
        public void WriteArrayMemberConverter(AST.Type type)
        {
            var tn    = TypeRef(type, false);
            var tnabi = TypeRef(type, true);

            if (type.IsDelegate)
            {
                tnabi = "DelegateBlob";
            }

            Line("public static {0}[] FromABI{1}(IntPtr data, int count)", tn, type.ShortId);
            Block(() =>
            {
                Line("if(data == IntPtr.Zero) return null;");
                Line("var sz = Marshal.SizeOf<{0}>();", tnabi);
                Line("var r = new {0}[count];", tn);
                Line("for(int i = 0;i < count;i++)");
                Block(() =>
                {
                    if (type.IsStruct)
                    {
                        if (CsRender.RequiresABITranslation(type.ToVariable()))
                        {
                            Line("r[i] = {0}.FromABI(Marshal.PtrToStructure<{0}>((IntPtr)((long)data + i * sz)));", tnabi);
                        }
                        else
                        {
                            Line("r[i] = Marshal.PtrToStructure<{0}>((IntPtr)((long)data + i * sz));", tnabi);
                        }
                    }
                    else if (type.IsDelegate)
                    {
                        Line("var blob = Marshal.PtrToStructure<{0}>((IntPtr)((long)data + i * sz));", tnabi);
                        Line("r[i] = D{0}.Wrap(blob.Fn, blob.Ctx);", type.ShortId);
                    }
                    else if (type.IsObject)
                    {
                        Line("r[i] = GluonObject.Of<{0}>(Marshal.ReadIntPtr((IntPtr)((long)data + i * sz)));", tn);
                    }
                    else
                    {
                        throw new InvalidOperationException("This writer only designed to write for structs, delegates, and classes");
                    }
                });
                Line("Marshal.FreeCoTaskMem(data);");
                Line("return r;");
            });

            Line("public static ArrayBlob ToABI{1}({0}[] arr)", tn, type.ShortId);
            Block(() =>
            {
                Line("if(arr == null) return new ArrayBlob();");
                Line("var sz = Marshal.SizeOf<{0}>();", tnabi);
                Line("var r = new ArrayBlob(Marshal.AllocCoTaskMem(sz * arr.Length), arr.Length);");
                Line("for(int i = 0;i < arr.Length;i++)");
                Block(() =>
                {
                    if (type.IsStruct)
                    {
                        if (CsRender.RequiresABITranslation(type.ToVariable()))
                        {
                            Line("Marshal.StructureToPtr({0}.ToABI(arr[i]), r.Ptr + sz * i, false);", tnabi);
                        }
                        else
                        {
                            Line("Marshal.StructureToPtr(arr[i], r.Ptr + sz * i, false);", tnabi);
                        }
                    }
                    else if (type.IsDelegate)
                    {
                        Line("var blob = D{0}.Unwrap(arr[i]);", type.ShortId);
                        Line("Marshal.StructureToPtr(blob, (IntPtr)((long)r.Ptr + sz * i), false);");
                    }
                    else if (type.IsObject)
                    {
                        Line("var item = arr[i];");
                        Line("Marshal.WriteIntPtr((IntPtr)((long)r.Ptr + sz * i), item == null ? IntPtr.Zero : item.IPtr);");
                    }
                });
                Line("return r;");
            });

            Line("public static void FreeABI{0}(IntPtr data, int count)", type.ShortId);
            Block(() =>
            {
                Line("Marshal.FreeCoTaskMem(data);");
            });
        }
Пример #7
0
        public override string TypeName(AST.Type t, bool?abi = null)
        {
            var useabi = RequiresABITranslation(t.ToVariable()) && (abi ?? Strata == ApiStrata.ABI);

            if (t.IsVoid)
            {
                return("void");
            }

            if (t == BasicTypes.IUnknown)
            {
                t = BasicTypes.IntPtr;
            }

            if (useabi && (/*v.IsArray ||*/ t.IsObject))
            {
                return("IntPtr");
            }

            var qn = t.Name;

            if (t.IsDelegate)
            {
                var d = (AST.Delegate)t;

                if (useabi)
                {
                    return("IntPtr");
                }
                else if (d.IsGeneric)
                {
                    CsRender writer = new CsRender();

                    if (!d.Return.IsVoid)
                    {
                        writer.Code("Func<");
                        writer.BeginList(CodeListStyle.Compact);
                        foreach (var arg in d.Parameters)
                        {
                            writer.ListItem(TypeName(arg, false));
                        }
                        writer.ListItem(TypeName(d.Return));
                        writer.EndList();
                        writer.Code(">");
                    }
                    else if (d.Parameters.Count == 0)
                    {
                        return("Action");
                    }
                    else
                    {
                        writer.Code("Action<");
                        writer.BeginList(CodeListStyle.Compact);
                        foreach (var arg in d.Parameters)
                        {
                            writer.ListItem(TypeName(arg, false));
                        }
                        writer.EndList();
                        writer.Code(">");
                    }

                    return(writer.ToString());
                }
            }

            if ((t.IsObject || t.IsDelegate || t.IsStruct) && (WorkingABINamespace != useabi || WorkingNamespace != t.Namespace))
            {
                if (useabi)
                {
                    if (t.IsObject || t.IsDelegate)
                    {
                        return("IntPtr");
                    }
                    else
                    {
                        return("ABI." + t.FullName("."));
                    }
                }
                else
                {
                    return("global::" + t.FullName("."));
                }
            }

            if (t.IsEnum && WorkingABINamespace)
            {
                return("global::" + t.FullName("."));
            }

            return(ScopeTo(t.Namespace) + qn);
        }