public void GenerateValueTypesABI(CsTreeWriter file) { foreach (var type in AllGeneratedStructs.Where(t => CsRender.RequiresABITranslation(t.ToVariable()))) { file.DefineStruct(type); } }
private void Render(PascalTreeWriter treeWriter, string path) { var writer = new CsRender(); treeWriter.InsertUsings(); treeWriter.Tree.Resolve(writer); writer.Write(path); OutputFiles.Add(path); }
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); }
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)); }
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 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);"); }); }
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); }