From 2fd55044c3ec24ef28571a97d288df6a86652230 Mon Sep 17 00:00:00 2001 From: badcel <1218031+badcel@users.noreply.github.com> Date: Sun, 8 Sep 2024 15:35:01 +0200 Subject: [PATCH 1/2] Primitive value type alias: Make "struct" a "record struct" Using a "record struct" instead of a regular "struct" allows to use a compiler generated equality check instead of the one implemented in the runtime which uses reflection. --- .../Generator/Renderer/Public/AliasPrimitiveValueType.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Generation/Generator/Renderer/Public/AliasPrimitiveValueType.cs b/src/Generation/Generator/Renderer/Public/AliasPrimitiveValueType.cs index ce8a0f4e3..8fbff5d7b 100644 --- a/src/Generation/Generator/Renderer/Public/AliasPrimitiveValueType.cs +++ b/src/Generation/Generator/Renderer/Public/AliasPrimitiveValueType.cs @@ -26,7 +26,7 @@ namespace {Namespace.GetPublicName(alias.Namespace)}; {PlatformSupportAttribute.Render(alias as GirModel.PlatformDependent)} [StructLayout(LayoutKind.Explicit)] -public readonly partial struct {alias.Name} +public readonly partial record struct {alias.Name} {{ [FieldOffset(0)] private readonly {type} _value; From a8f019d53ccee6a39c52db57f54afe053b00f778 Mon Sep 17 00:00:00 2001 From: badcel <1218031+badcel@users.noreply.github.com> Date: Sun, 8 Sep 2024 18:36:16 +0200 Subject: [PATCH 2/2] Primitive value type alias: Support returning arrays --- .../Converter/Callback.cs | 22 +++++----- .../Converter/PrimitiveValueTypeAliasArray.cs | 20 +++++++++ .../Internal/ReturnType/ReturnTypeRenderer.cs | 1 + .../CallableExpressions/CallableData.cs | 8 ++++ .../CallableExpressions.cs | 12 ++++++ .../Renderer/Public/FunctionRenderer.cs | 21 +++++----- .../Renderer/Public/MethodRenderer.cs | 22 +++++----- .../Converter/PrimitiveValueType.cs | 4 +- .../ParameterToNativeData.cs | 9 +--- .../Converter/PrimitiveValueTypeAliasArray.cs | 18 ++++++++ .../Public/ReturnType/ReturnTypeRenderer.cs | 9 ++-- .../Converter/Bitfield.cs | 7 ++-- .../Converter/Class.cs | 20 +++++---- .../Converter/Enumeration.cs | 7 ++-- .../Converter/ForeignTypedRecord.cs | 32 ++++++++------- .../Converter/Interface.cs | 20 +++++---- .../Converter/Long.cs | 12 ++++-- .../Converter/OpaqueTypedRecord.cs | 30 ++++++++------ .../Converter/OpaqueUntypedRecord.cs | 32 ++++++++------- .../Converter/PlatformString.cs | 7 ++-- .../Converter/PlatformStringArray.cs | 20 +++++---- .../Converter/Pointer.cs | 7 ++-- .../Converter/PointerAlias.cs | 7 ++-- .../Converter/PrimitiveValueType.cs | 7 ++-- .../Converter/PrimitiveValueTypeAlias.cs | 7 ++-- .../Converter/PrimitiveValueTypeAliasArray.cs | 41 +++++++++++++++++++ .../Converter/PrimitiveValueTypeArray.cs | 7 ++-- .../Converter/TypedRecord.cs | 29 +++++++------ .../Converter/UnsignedLong.cs | 11 +++-- .../Converter/UntypedRecord.cs | 29 +++++++------ .../Converter/Utf8String.cs | 7 ++-- .../Converter/Utf8StringArray.cs | 20 +++++---- .../Converter/Void.cs | 15 +++++++ .../ReturnTypeConverter.cs | 6 +-- .../ReturnTypeToManagedData.cs | 31 ++++++++++++++ .../ReturnTypeToManagedExpression.cs | 23 +++++++---- .../GirLoader/Output/Callback.GirModel.cs | 2 +- .../GirLoader/Output/Constructor.GirModel.cs | 2 +- .../GirLoader/Output/Function.GirModel.cs | 2 +- .../GirLoader/Output/Method.GirModel.cs | 2 +- .../Callbacks/Callback.GirModel.cs | 2 +- .../Functions/Function.GirModel.cs | 2 +- src/Generation/GirModel/Callable.cs | 1 + src/Generation/GirModel/Callback.cs | 1 - src/Generation/GirModel/Constructor.cs | 1 - src/Generation/GirModel/Function.cs | 1 - src/Generation/GirModel/Method.cs | 1 - src/Libs/GLib-2.0/Internal/StructArray.cs | 22 ++++++++++ src/Native/GirTestLib/girtest-alias-tester.c | 28 ++++++++++++- src/Native/GirTestLib/girtest-alias-tester.h | 3 ++ src/Tests/Libs/GirTest-0.1.Tests/AliasTest.cs | 10 +++++ 51 files changed, 468 insertions(+), 192 deletions(-) create mode 100644 src/Generation/Generator/Renderer/Internal/ReturnType/Converter/PrimitiveValueTypeAliasArray.cs create mode 100644 src/Generation/Generator/Renderer/Public/CallableExpressions/CallableData.cs create mode 100644 src/Generation/Generator/Renderer/Public/CallableExpressions/CallableExpressions.cs create mode 100644 src/Generation/Generator/Renderer/Public/ReturnType/Converter/PrimitiveValueTypeAliasArray.cs create mode 100644 src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/PrimitiveValueTypeAliasArray.cs create mode 100644 src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/Void.cs create mode 100644 src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/ReturnTypeToManagedData.cs create mode 100644 src/Libs/GLib-2.0/Internal/StructArray.cs diff --git a/src/Generation/Generator/Renderer/Internal/ParameterToManagedExpression/Converter/Callback.cs b/src/Generation/Generator/Renderer/Internal/ParameterToManagedExpression/Converter/Callback.cs index 4bf5ef020..6943be1dc 100644 --- a/src/Generation/Generator/Renderer/Internal/ParameterToManagedExpression/Converter/Callback.cs +++ b/src/Generation/Generator/Renderer/Internal/ParameterToManagedExpression/Converter/Callback.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using Generator.Renderer.Public; namespace Generator.Renderer.Internal.ParameterToManagedExpressions; @@ -21,15 +22,14 @@ public void Initialize(ParameterToManagedData parameterData, IEnumerable signatureName); - parameterData.SetExpression(() => @$"var {callName} = new {ns}.{type}(({GetManagedParameters(parameterToNativeDatas)}) => + parameterData.SetExpression(() => @$"var {callName} = new {ns}.{type}(({GetManagedParameters(callableData.ParameterToNativeDatas)}) => {{ - {RenderContent(parameterToNativeDatas)} - {RenderCallStatement(signatureName, callback, parameterToNativeDatas, out var resultVariableName)} - {RenderThrowOnError(callback, parameterToNativeDatas)} - {RenderReturnStatement(callback, resultVariableName)} + {RenderContent(callableData.ParameterToNativeDatas)} + {RenderCallStatement(signatureName, callback, callableData.ParameterToNativeDatas, out var resultVariableName)} + {RenderThrowOnError(callback, callableData.ParameterToNativeDatas)} + {RenderReturnStatement(callableData.ReturnTypeToManagedData, resultVariableName)} }});"); parameterData.SetCallName(() => callName); } @@ -67,7 +67,7 @@ private static string RenderContent(IEnumerable pa .Join(Environment.NewLine); } - private static string RenderCallStatement(string signatureName, GirModel.Callback callback, IReadOnlyList parameters, out string resultVariableName) + private static string RenderCallStatement(string signatureName, GirModel.Callback callback, IReadOnlyCollection parameters, out string resultVariableName) { resultVariableName = $"result{callback.Name}"; var call = new StringBuilder(); @@ -91,10 +91,10 @@ private static string RenderThrowOnError(GirModel.Callback callback, IEnumerable : string.Empty; } - private static string RenderReturnStatement(GirModel.Callback callback, string returnVariable) + private static string RenderReturnStatement(ReturnTypeToManagedData data, string returnVariable) { - return callback.ReturnType.AnyType.Is() + return data.ReturnType.AnyType.Is() ? string.Empty - : $"return {Public.ReturnTypeToManagedExpression.Render(callback.ReturnType, returnVariable)};"; + : $"return {data.GetExpression(returnVariable)};"; } } diff --git a/src/Generation/Generator/Renderer/Internal/ReturnType/Converter/PrimitiveValueTypeAliasArray.cs b/src/Generation/Generator/Renderer/Internal/ReturnType/Converter/PrimitiveValueTypeAliasArray.cs new file mode 100644 index 000000000..f89aa64fb --- /dev/null +++ b/src/Generation/Generator/Renderer/Internal/ReturnType/Converter/PrimitiveValueTypeAliasArray.cs @@ -0,0 +1,20 @@ +using System; +using Type = Generator.Model.Type; + +namespace Generator.Renderer.Internal.ReturnType; + +internal class PrimitiveValueTypeAliasArray : ReturnTypeConverter +{ + public bool Supports(GirModel.ReturnType returnType) + { + return returnType.AnyType.IsArrayAlias(); + } + + public RenderableReturnType Convert(GirModel.ReturnType returnType) + { + if (!returnType.IsPointer) + throw new NotImplementedException("Only primitive value types alias arrays which are pointer based are supported."); + + return new RenderableReturnType(Type.Pointer); + } +} diff --git a/src/Generation/Generator/Renderer/Internal/ReturnType/ReturnTypeRenderer.cs b/src/Generation/Generator/Renderer/Internal/ReturnType/ReturnTypeRenderer.cs index 6f16a6835..6c800edbe 100644 --- a/src/Generation/Generator/Renderer/Internal/ReturnType/ReturnTypeRenderer.cs +++ b/src/Generation/Generator/Renderer/Internal/ReturnType/ReturnTypeRenderer.cs @@ -23,6 +23,7 @@ internal static class ReturnTypeRenderer new ReturnType.UnsignedLong(), //Must be before primitive value type new ReturnType.PrimitiveValueType(), new ReturnType.PrimitiveValueTypeAlias(), + new ReturnType.PrimitiveValueTypeAliasArray(), new ReturnType.PrimitiveValueTypeArray(), new ReturnType.TypedRecord(), new ReturnType.TypedRecordArray(), diff --git a/src/Generation/Generator/Renderer/Public/CallableExpressions/CallableData.cs b/src/Generation/Generator/Renderer/Public/CallableExpressions/CallableData.cs new file mode 100644 index 000000000..34a9a7b19 --- /dev/null +++ b/src/Generation/Generator/Renderer/Public/CallableExpressions/CallableData.cs @@ -0,0 +1,8 @@ +using System.Collections.Generic; + +namespace Generator.Renderer.Public; + +public record CallableData( + ReturnTypeToManagedData ReturnTypeToManagedData, + IReadOnlyCollection ParameterToNativeDatas +); diff --git a/src/Generation/Generator/Renderer/Public/CallableExpressions/CallableExpressions.cs b/src/Generation/Generator/Renderer/Public/CallableExpressions/CallableExpressions.cs new file mode 100644 index 000000000..da7163e50 --- /dev/null +++ b/src/Generation/Generator/Renderer/Public/CallableExpressions/CallableExpressions.cs @@ -0,0 +1,12 @@ +namespace Generator.Renderer.Public; + +public class CallableExpressions +{ + public static CallableData Initialize(GirModel.Callable callable) + { + var parameters = ParameterToNativeExpression.Initialize(callable.Parameters); + var returnType = ReturnTypeToManagedExpression.Initialize(callable.ReturnType, parameters); + + return new CallableData(returnType, parameters); + } +} diff --git a/src/Generation/Generator/Renderer/Public/FunctionRenderer.cs b/src/Generation/Generator/Renderer/Public/FunctionRenderer.cs index ba4077eed..3b3c687f2 100644 --- a/src/Generation/Generator/Renderer/Public/FunctionRenderer.cs +++ b/src/Generation/Generator/Renderer/Public/FunctionRenderer.cs @@ -18,16 +18,17 @@ public static string Render(GirModel.Function? function) try { - var parameters = ParameterToNativeExpression.Initialize(function.Parameters); + var callableData = CallableExpressions.Initialize(function); var newModifier = Function.HidesFunction(function) ? "new " : string.Empty; return @$" {VersionAttribute.Render(function.Version)} -public static {newModifier}{ReturnTypeRenderer.Render(function.ReturnType)} {Function.GetName(function)}({RenderParameters(parameters)}) +public static {newModifier}{ReturnTypeRenderer.Render(function.ReturnType)} {Function.GetName(function)}({RenderParameters(callableData.ParameterToNativeDatas)}) {{ - {RenderFunctionContent(parameters)} - {RenderCallStatement(function, parameters, out var resultVariableName)} - {RenderPostCallContent(parameters)} - {RenderReturnStatement(function, resultVariableName)} + {RenderFunctionContent(callableData.ParameterToNativeDatas)} + {RenderCallStatement(function, callableData.ParameterToNativeDatas, out var resultVariableName)} + {RenderPostCallContent(callableData.ParameterToNativeDatas)} + {callableData.ReturnTypeToManagedData.GetPostReturnStatement(resultVariableName)} + {RenderReturnStatement(callableData.ReturnTypeToManagedData, resultVariableName)} }}"; } catch (Exception e) @@ -89,7 +90,7 @@ private static string RenderParameters(IEnumerable parame return result.Join(", "); } - private static string RenderCallStatement(GirModel.Function function, IReadOnlyList parameters, out string resultVariableName) + private static string RenderCallStatement(GirModel.Function function, IEnumerable parameters, out string resultVariableName) { resultVariableName = $"result{Function.GetName(function)}"; var call = new StringBuilder(); @@ -113,11 +114,11 @@ private static string RenderCallStatement(GirModel.Function function, IReadOnlyL return call.ToString(); } - private static string RenderReturnStatement(GirModel.Function function, string returnVariable) + private static string RenderReturnStatement(ReturnTypeToManagedData data, string returnVariable) { - return function.ReturnType.AnyType.Is() + return data.ReturnType.AnyType.Is() ? string.Empty - : $"return {ReturnTypeToManagedExpression.Render(function.ReturnType, returnVariable)};"; + : $"return {data.GetExpression(returnVariable)};"; } private static bool IsSupported(GirModel.Function function) diff --git a/src/Generation/Generator/Renderer/Public/MethodRenderer.cs b/src/Generation/Generator/Renderer/Public/MethodRenderer.cs index a212d78b9..924d09cf8 100644 --- a/src/Generation/Generator/Renderer/Public/MethodRenderer.cs +++ b/src/Generation/Generator/Renderer/Public/MethodRenderer.cs @@ -25,16 +25,16 @@ public static string Render(GirModel.Method method) explicitImplementation = $"{Namespace.GetPublicName(method.Parent.Namespace)}.{method.Parent.Name}."; } - var parameters = ParameterToNativeExpression.Initialize(method.Parameters); - + var callableData = CallableExpressions.Initialize(method); return @$" {VersionAttribute.Render(method.Version)} -{modifier}{ReturnTypeRenderer.Render(method.ReturnType)} {explicitImplementation}{Method.GetPublicName(method)}({RenderParameters(parameters)}) +{modifier}{ReturnTypeRenderer.Render(method.ReturnType)} {explicitImplementation}{Method.GetPublicName(method)}({RenderParameters(callableData.ParameterToNativeDatas)}) {{ - {RenderMethodContent(parameters)} - {RenderCallStatement(method, parameters, out var resultVariableName)} - {RenderPostCallContent(parameters)} - {RenderReturnStatement(method, resultVariableName)} + {RenderMethodContent(callableData.ParameterToNativeDatas)} + {RenderCallStatement(method, callableData.ParameterToNativeDatas, out var resultVariableName)} + {RenderPostCallContent(callableData.ParameterToNativeDatas)} + {callableData.ReturnTypeToManagedData.GetPostReturnStatement(resultVariableName)} + {RenderReturnStatement(callableData.ReturnTypeToManagedData, resultVariableName)} }}"; } catch (Exception e) @@ -96,7 +96,7 @@ private static string RenderParameters(IEnumerable parame return result.Join(", "); } - private static string RenderCallStatement(GirModel.Method method, IReadOnlyList parameters, out string resultVariableName) + private static string RenderCallStatement(GirModel.Method method, IReadOnlyCollection parameters, out string resultVariableName) { resultVariableName = $"result{Method.GetPublicName(method)}"; var call = new StringBuilder(); @@ -115,10 +115,10 @@ private static string RenderCallStatement(GirModel.Method method, IReadOnlyList< return call.ToString(); } - private static string RenderReturnStatement(GirModel.Method method, string returnVariable) + private static string RenderReturnStatement(ReturnTypeToManagedData data, string returnVariable) { - return method.ReturnType.AnyType.Is() + return data.ReturnType.AnyType.Is() ? string.Empty - : $"return {ReturnTypeToManagedExpression.Render(method.ReturnType, returnVariable)};"; + : $"return {data.GetExpression(returnVariable)};"; } } diff --git a/src/Generation/Generator/Renderer/Public/ParameterToNativeExpression/Converter/PrimitiveValueType.cs b/src/Generation/Generator/Renderer/Public/ParameterToNativeExpression/Converter/PrimitiveValueType.cs index 7b8548ca5..b0ce8a52c 100644 --- a/src/Generation/Generator/Renderer/Public/ParameterToNativeExpression/Converter/PrimitiveValueType.cs +++ b/src/Generation/Generator/Renderer/Public/ParameterToNativeExpression/Converter/PrimitiveValueType.cs @@ -51,6 +51,8 @@ private static void Out(ParameterToNativeData parameter) { var parameterName = Model.Parameter.GetName(parameter.Parameter); parameter.SetSignatureName(() => parameterName); - parameter.SetCallName(() => $"out {parameterName}"); + parameter.SetCallName(() => parameter.IsArrayLengthParameter + ? $"out var {parameterName}" + : $"out {parameterName}"); } } diff --git a/src/Generation/Generator/Renderer/Public/ParameterToNativeExpression/ParameterToNativeData.cs b/src/Generation/Generator/Renderer/Public/ParameterToNativeExpression/ParameterToNativeData.cs index 64c28d6ff..bc6b6657b 100644 --- a/src/Generation/Generator/Renderer/Public/ParameterToNativeExpression/ParameterToNativeData.cs +++ b/src/Generation/Generator/Renderer/Public/ParameterToNativeExpression/ParameterToNativeData.cs @@ -2,7 +2,7 @@ namespace Generator.Renderer.Public; -public class ParameterToNativeData +public class ParameterToNativeData(GirModel.Parameter parameter) { private Func? _getCallName; private Func? _getSignatureName; @@ -14,7 +14,7 @@ public class ParameterToNativeData private string? _expression; private string? _postCallExpression; - public GirModel.Parameter Parameter { get; } + public GirModel.Parameter Parameter { get; } = parameter; public bool IsCallbackUserData { get; internal set; } public bool IsDestroyNotify { get; internal set; } @@ -22,11 +22,6 @@ public class ParameterToNativeData public bool IsInOutArrayLengthParameter { get; internal set; } public bool IsGLibErrorParameter { get; internal set; } - public ParameterToNativeData(GirModel.Parameter parameter) - { - Parameter = parameter; - } - public void SetExpression(Func getExpression) { _getExpression = getExpression; diff --git a/src/Generation/Generator/Renderer/Public/ReturnType/Converter/PrimitiveValueTypeAliasArray.cs b/src/Generation/Generator/Renderer/Public/ReturnType/Converter/PrimitiveValueTypeAliasArray.cs new file mode 100644 index 000000000..f3983dad7 --- /dev/null +++ b/src/Generation/Generator/Renderer/Public/ReturnType/Converter/PrimitiveValueTypeAliasArray.cs @@ -0,0 +1,18 @@ +using System; + +namespace Generator.Renderer.Public.ReturnType; + +internal class PrimitiveValueTypeAliasArray : ReturnTypeConverter +{ + public RenderableReturnType Create(GirModel.ReturnType returnType) + { + if (!returnType.IsPointer) + throw new NotImplementedException("Only primitive value types alias arrays which are pointer based are supported."); + + var alias = (GirModel.Alias) returnType.AnyType.AsT1.AnyType.AsT0; + return new RenderableReturnType($"{Model.Namespace.GetPublicName(alias.Namespace)}.{Model.ArrayType.GetName(returnType.AnyType.AsT1)}"); + } + + public bool Supports(GirModel.ReturnType returnType) + => returnType.AnyType.IsArrayAlias(); +} diff --git a/src/Generation/Generator/Renderer/Public/ReturnType/ReturnTypeRenderer.cs b/src/Generation/Generator/Renderer/Public/ReturnType/ReturnTypeRenderer.cs index ec905a46a..9f3ed247c 100644 --- a/src/Generation/Generator/Renderer/Public/ReturnType/ReturnTypeRenderer.cs +++ b/src/Generation/Generator/Renderer/Public/ReturnType/ReturnTypeRenderer.cs @@ -5,8 +5,8 @@ namespace Generator.Renderer.Public; internal static class ReturnTypeRenderer { - private static readonly List converters = new() - { + private static readonly List converters = + [ new ReturnType.Bitfield(), new ReturnType.Class(), new ReturnType.Enumeration(), @@ -18,13 +18,14 @@ internal static class ReturnTypeRenderer new ReturnType.PointerAlias(), new ReturnType.PrimitiveValueType(), new ReturnType.PrimitiveValueTypeAlias(), + new ReturnType.PrimitiveValueTypeAliasArray(), new ReturnType.String(), new ReturnType.StringArray(), new ReturnType.TypedRecord(), new ReturnType.TypedRecordArray(), new ReturnType.UntypedRecord(), - new ReturnType.Void(), - }; + new ReturnType.Void() + ]; public static string Render(GirModel.ReturnType returnType) { diff --git a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/Bitfield.cs b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/Bitfield.cs index 9fe074a78..ba71e80bd 100644 --- a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/Bitfield.cs +++ b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/Bitfield.cs @@ -1,4 +1,5 @@ -using GirModel; +using System.Collections.Generic; +using GirModel; namespace Generator.Renderer.Public.ReturnTypeToManagedExpressions; @@ -7,6 +8,6 @@ internal class Bitfield : ReturnTypeConverter public bool Supports(AnyType type) => type.Is(); - public string GetString(GirModel.ReturnType returnType, string fromVariableName) - => fromVariableName; + public void Initialize(ReturnTypeToManagedData data, IEnumerable _) + => data.SetExpression(fromVariableName => fromVariableName); } diff --git a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/Class.cs b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/Class.cs index aeaf3a4df..b793509df 100644 --- a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/Class.cs +++ b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/Class.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using Generator.Model; namespace Generator.Renderer.Public.ReturnTypeToManagedExpressions; @@ -8,15 +9,20 @@ internal class Class : ReturnTypeConverter public bool Supports(GirModel.AnyType type) => type.Is(); - public string GetString(GirModel.ReturnType returnType, string fromVariableName) + public void Initialize(ReturnTypeToManagedData data, IEnumerable _) { - if (!returnType.IsPointer) - throw new NotImplementedException($"Can't convert {returnType} to managed as it is a pointer"); + data.SetExpression(fromVariableName => + { + var returnType = data.ReturnType; - var cls = (GirModel.Class) returnType.AnyType.AsT0; - return cls.Fundamental - ? Fundamental(cls, returnType, fromVariableName) - : Standard(cls, returnType, fromVariableName); + if (!returnType.IsPointer) + throw new NotImplementedException($"Can't convert {returnType} to managed as it is a pointer"); + + var cls = (GirModel.Class) returnType.AnyType.AsT0; + return cls.Fundamental + ? Fundamental(cls, returnType, fromVariableName) + : Standard(cls, returnType, fromVariableName); + }); } private static string Fundamental(GirModel.Class cls, GirModel.ReturnType returnType, string fromVariableName) diff --git a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/Enumeration.cs b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/Enumeration.cs index 9b44bb518..42b5c2aca 100644 --- a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/Enumeration.cs +++ b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/Enumeration.cs @@ -1,4 +1,5 @@ -using GirModel; +using System.Collections.Generic; +using GirModel; namespace Generator.Renderer.Public.ReturnTypeToManagedExpressions; @@ -7,6 +8,6 @@ internal class Enumeration : ReturnTypeConverter public bool Supports(AnyType type) => type.Is(); - public string GetString(GirModel.ReturnType returnType, string fromVariableName) - => fromVariableName; + public void Initialize(ReturnTypeToManagedData data, IEnumerable _) + => data.SetExpression(fromVariableName => fromVariableName); } diff --git a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/ForeignTypedRecord.cs b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/ForeignTypedRecord.cs index fc5b53c94..69c64fb5d 100644 --- a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/ForeignTypedRecord.cs +++ b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/ForeignTypedRecord.cs @@ -1,28 +1,32 @@ using System; -using GirModel; +using System.Collections.Generic; namespace Generator.Renderer.Public.ReturnTypeToManagedExpressions; internal class ForeignTypedRecord : ReturnTypeConverter { - public bool Supports(AnyType type) + public bool Supports(GirModel.AnyType type) => type.Is(out var record) && Model.Record.IsForeignTyped(record); - public string GetString(GirModel.ReturnType returnType, string fromVariableName) + public void Initialize(ReturnTypeToManagedData data, IEnumerable _) { - var record = (GirModel.Record) returnType.AnyType.AsT0; - - var handleExpression = returnType switch + data.SetExpression(fromVariableName => { - { Transfer: Transfer.Full } => fromVariableName, - { Transfer: Transfer.None } => $"{fromVariableName}.OwnedCopy()", - _ => throw new NotImplementedException("Unknown transfer type") - }; + var returnType = data.ReturnType; + var record = (GirModel.Record) returnType.AnyType.AsT0; + + var handleExpression = returnType switch + { + { Transfer: GirModel.Transfer.Full } => fromVariableName, + { Transfer: GirModel.Transfer.None } => $"{fromVariableName}.OwnedCopy()", + _ => throw new NotImplementedException("Unknown transfer type") + }; - var createNewInstance = $"new {Model.ComplexType.GetFullyQualified(record)}({handleExpression})"; + var createNewInstance = $"new {Model.ComplexType.GetFullyQualified(record)}({handleExpression})"; - return returnType.Nullable - ? $"{fromVariableName}.IsInvalid ? null : {createNewInstance}" - : createNewInstance; + return returnType.Nullable + ? $"{fromVariableName}.IsInvalid ? null : {createNewInstance}" + : createNewInstance; + }); } } diff --git a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/Interface.cs b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/Interface.cs index 37ec13da8..c02863c33 100644 --- a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/Interface.cs +++ b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/Interface.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using Generator.Model; namespace Generator.Renderer.Public.ReturnTypeToManagedExpressions; @@ -8,15 +9,20 @@ internal class Interface : ReturnTypeConverter public bool Supports(GirModel.AnyType type) => type.Is(); - public string GetString(GirModel.ReturnType returnType, string fromVariableName) + public void Initialize(ReturnTypeToManagedData data, IEnumerable _) { - if (!returnType.IsPointer) - throw new NotImplementedException($"Can't convert {returnType} to managed as it is a pointer"); + data.SetExpression(fromVariableName => + { + var returnType = data.ReturnType; - var @interface = (GirModel.Interface) returnType.AnyType.AsT0; + if (!returnType.IsPointer) + throw new NotImplementedException($"Can't convert {returnType} to managed as it is a pointer"); - return returnType.Nullable - ? $"GObject.Internal.ObjectWrapper.WrapNullableInterfaceHandle<{Model.Interface.GetFullyQualifiedImplementationName(@interface)}>({fromVariableName}, {Transfer.IsOwnedRef(returnType.Transfer).ToString().ToLower()})" - : $"GObject.Internal.ObjectWrapper.WrapInterfaceHandle<{Model.Interface.GetFullyQualifiedImplementationName(@interface)}>({fromVariableName}, {Transfer.IsOwnedRef(returnType.Transfer).ToString().ToLower()})"; + var @interface = (GirModel.Interface) returnType.AnyType.AsT0; + + return returnType.Nullable + ? $"GObject.Internal.ObjectWrapper.WrapNullableInterfaceHandle<{Model.Interface.GetFullyQualifiedImplementationName(@interface)}>({fromVariableName}, {Transfer.IsOwnedRef(returnType.Transfer).ToString().ToLower()})" + : $"GObject.Internal.ObjectWrapper.WrapInterfaceHandle<{Model.Interface.GetFullyQualifiedImplementationName(@interface)}>({fromVariableName}, {Transfer.IsOwnedRef(returnType.Transfer).ToString().ToLower()})"; + }); } } diff --git a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/Long.cs b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/Long.cs index e340e885e..ae2ce9c68 100644 --- a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/Long.cs +++ b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/Long.cs @@ -1,4 +1,5 @@ -using GirModel; +using System.Collections.Generic; +using GirModel; namespace Generator.Renderer.Public.ReturnTypeToManagedExpressions; @@ -7,8 +8,11 @@ internal class Long : ReturnTypeConverter public bool Supports(AnyType type) => type.Is(); - public string GetString(GirModel.ReturnType returnType, string fromVariableName) - => returnType.IsPointer + public void Initialize(ReturnTypeToManagedData data, IEnumerable _) + { + data.SetExpression(fromVariableName => data.ReturnType.IsPointer ? fromVariableName - : $"{fromVariableName}.Value"; + : $"{fromVariableName}.Value" + ); + } } diff --git a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/OpaqueTypedRecord.cs b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/OpaqueTypedRecord.cs index 5b9464b03..71d78f059 100644 --- a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/OpaqueTypedRecord.cs +++ b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/OpaqueTypedRecord.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using GirModel; namespace Generator.Renderer.Public.ReturnTypeToManagedExpressions; @@ -8,21 +9,26 @@ internal class OpaqueTypedRecord : ReturnTypeConverter public bool Supports(AnyType type) => type.Is(out var record) && Model.Record.IsOpaqueTyped(record); - public string GetString(GirModel.ReturnType returnType, string fromVariableName) + public void Initialize(ReturnTypeToManagedData data, IEnumerable _) { - var record = (GirModel.Record) returnType.AnyType.AsT0; - - var handleExpression = returnType switch + data.SetExpression(fromVariableName => { - { Transfer: Transfer.Full } => fromVariableName, - { Transfer: Transfer.None } => $"{fromVariableName}.OwnedCopy()", - _ => throw new NotImplementedException("Unknown transfer type") - }; + var returnType = data.ReturnType; + + var record = (GirModel.Record) returnType.AnyType.AsT0; + + var handleExpression = returnType switch + { + { Transfer: Transfer.Full } => fromVariableName, + { Transfer: Transfer.None } => $"{fromVariableName}.OwnedCopy()", + _ => throw new NotImplementedException("Unknown transfer type") + }; - var createNewInstance = $"new {Model.ComplexType.GetFullyQualified(record)}({handleExpression})"; + var createNewInstance = $"new {Model.ComplexType.GetFullyQualified(record)}({handleExpression})"; - return returnType.Nullable - ? $"{fromVariableName}.IsInvalid ? null : {createNewInstance}" - : createNewInstance; + return returnType.Nullable + ? $"{fromVariableName}.IsInvalid ? null : {createNewInstance}" + : createNewInstance; + }); } } diff --git a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/OpaqueUntypedRecord.cs b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/OpaqueUntypedRecord.cs index 7ab2caccf..cb9d27e94 100644 --- a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/OpaqueUntypedRecord.cs +++ b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/OpaqueUntypedRecord.cs @@ -1,28 +1,32 @@ using System; -using GirModel; +using System.Collections.Generic; namespace Generator.Renderer.Public.ReturnTypeToManagedExpressions; internal class OpaqueUntypedRecord : ReturnTypeConverter { - public bool Supports(AnyType type) + public bool Supports(GirModel.AnyType type) => type.Is(out var record) && Model.Record.IsOpaqueUntyped(record); - public string GetString(GirModel.ReturnType returnType, string fromVariableName) + public void Initialize(ReturnTypeToManagedData data, IEnumerable _) { - var record = (GirModel.Record) returnType.AnyType.AsT0; - - var handleExpression = returnType switch + data.SetExpression(fromVariableName => { - { Transfer: Transfer.Full } => fromVariableName, - { Transfer: Transfer.None } => $"{fromVariableName}.OwnedCopy()", - _ => throw new NotImplementedException("Unknown transfer type") - }; + var returnType = data.ReturnType; + var record = (GirModel.Record) returnType.AnyType.AsT0; + + var handleExpression = returnType switch + { + { Transfer: GirModel.Transfer.Full } => fromVariableName, + { Transfer: GirModel.Transfer.None } => $"{fromVariableName}.OwnedCopy()", + _ => throw new NotImplementedException("Unknown transfer type") + }; - var createNewInstance = $"new {Model.ComplexType.GetFullyQualified(record)}({handleExpression})"; + var createNewInstance = $"new {Model.ComplexType.GetFullyQualified(record)}({handleExpression})"; - return returnType.Nullable - ? $"{fromVariableName}.IsInvalid ? null : {createNewInstance}" - : createNewInstance; + return returnType.Nullable + ? $"{fromVariableName}.IsInvalid ? null : {createNewInstance}" + : createNewInstance; + }); } } diff --git a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/PlatformString.cs b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/PlatformString.cs index a1fdbae5f..fc7a8f6b0 100644 --- a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/PlatformString.cs +++ b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/PlatformString.cs @@ -1,4 +1,5 @@ -using GirModel; +using System.Collections.Generic; +using GirModel; namespace Generator.Renderer.Public.ReturnTypeToManagedExpressions; @@ -7,9 +8,9 @@ internal class PlatformString : ReturnTypeConverter public bool Supports(AnyType type) => type.Is(); - public string GetString(GirModel.ReturnType returnType, string fromVariableName) + public void Initialize(ReturnTypeToManagedData data, IEnumerable _) { // Convert the PlatformStringHandle return type to a string. - return $"{fromVariableName}.ConvertToString()"; + data.SetExpression(fromVariableName => $"{fromVariableName}.ConvertToString()"); } } diff --git a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/PlatformStringArray.cs b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/PlatformStringArray.cs index d1a1fbf16..b7bca6ad3 100644 --- a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/PlatformStringArray.cs +++ b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/PlatformStringArray.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; namespace Generator.Renderer.Public.ReturnTypeToManagedExpressions; @@ -7,16 +8,21 @@ internal class PlatformStringArray : ReturnTypeConverter public bool Supports(GirModel.AnyType type) => type.IsArray(); - public string GetString(GirModel.ReturnType returnType, string fromVariableName) + public void Initialize(ReturnTypeToManagedData data, IEnumerable _) { - var arrayType = returnType.AnyType.AsT1; - if (arrayType.IsZeroTerminated) - return NullTerminatedArray(returnType, fromVariableName); + data.SetExpression(fromVariableName => + { + var returnType = data.ReturnType; + var arrayType = returnType.AnyType.AsT1; - if (arrayType.Length is not null) - return SizeBasedArray(returnType, fromVariableName); + if (arrayType.IsZeroTerminated) + return NullTerminatedArray(returnType, fromVariableName); - throw new Exception("Unknown kind of array"); + if (arrayType.Length is not null) + return SizeBasedArray(returnType, fromVariableName); + + throw new Exception("Unknown kind of array"); + }); } private static string NullTerminatedArray(GirModel.ReturnType returnType, string fromVariableName) diff --git a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/Pointer.cs b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/Pointer.cs index 12496eeb3..1ff4dff79 100644 --- a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/Pointer.cs +++ b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/Pointer.cs @@ -1,4 +1,5 @@ -using GirModel; +using System.Collections.Generic; +using GirModel; namespace Generator.Renderer.Public.ReturnTypeToManagedExpressions; @@ -7,6 +8,6 @@ internal class Pointer : ReturnTypeConverter public bool Supports(AnyType type) => type.Is(); - public string GetString(GirModel.ReturnType returnType, string fromVariableName) - => fromVariableName; + public void Initialize(ReturnTypeToManagedData data, IEnumerable _) + => data.SetExpression(fromVariableName => fromVariableName); } diff --git a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/PointerAlias.cs b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/PointerAlias.cs index 2459f85a3..efc503fdf 100644 --- a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/PointerAlias.cs +++ b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/PointerAlias.cs @@ -1,4 +1,5 @@ -using GirModel; +using System.Collections.Generic; +using GirModel; namespace Generator.Renderer.Public.ReturnTypeToManagedExpressions; @@ -7,6 +8,6 @@ internal class PointerAlias : ReturnTypeConverter public bool Supports(AnyType type) => type.IsAlias(); - public string GetString(GirModel.ReturnType returnType, string fromVariableName) - => fromVariableName; + public void Initialize(ReturnTypeToManagedData data, IEnumerable _) + => data.SetExpression(fromVariableName => fromVariableName); } diff --git a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/PrimitiveValueType.cs b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/PrimitiveValueType.cs index a988b7f29..48880df34 100644 --- a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/PrimitiveValueType.cs +++ b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/PrimitiveValueType.cs @@ -1,4 +1,5 @@ -using GirModel; +using System.Collections.Generic; +using GirModel; namespace Generator.Renderer.Public.ReturnTypeToManagedExpressions; @@ -7,6 +8,6 @@ internal class PrimitiveValueType : ReturnTypeConverter public bool Supports(AnyType type) => type.Is(); - public string GetString(GirModel.ReturnType returnType, string fromVariableName) - => fromVariableName; //Valid for IsPointer = true && IsPointer = false + public void Initialize(ReturnTypeToManagedData data, IEnumerable _) + => data.SetExpression(fromVariableName => fromVariableName); //Valid for IsPointer = true && IsPointer = false } diff --git a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/PrimitiveValueTypeAlias.cs b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/PrimitiveValueTypeAlias.cs index e07e80082..a2cf6b049 100644 --- a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/PrimitiveValueTypeAlias.cs +++ b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/PrimitiveValueTypeAlias.cs @@ -1,4 +1,5 @@ -using GirModel; +using System.Collections.Generic; +using GirModel; namespace Generator.Renderer.Public.ReturnTypeToManagedExpressions; @@ -7,6 +8,6 @@ internal class PrimitiveValueTypeAlias : ReturnTypeConverter public bool Supports(AnyType type) => type.IsAlias(); - public string GetString(GirModel.ReturnType returnType, string fromVariableName) - => fromVariableName; //Valid for IsPointer = true && IsPointer = false + public void Initialize(ReturnTypeToManagedData data, IEnumerable _) + => data.SetExpression(fromVariableName => fromVariableName); //Valid for IsPointer = true && IsPointer = false } diff --git a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/PrimitiveValueTypeAliasArray.cs b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/PrimitiveValueTypeAliasArray.cs new file mode 100644 index 000000000..2a53c306d --- /dev/null +++ b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/PrimitiveValueTypeAliasArray.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using GirModel; + +namespace Generator.Renderer.Public.ReturnTypeToManagedExpressions; + +internal class PrimitiveValueTypeAliasArray : ReturnTypeConverter +{ + public bool Supports(AnyType type) + => type.IsArrayAlias(); + + public void Initialize(ReturnTypeToManagedData data, IEnumerable parameters) + { + if (data.ReturnType.AnyType.AsT1.IsZeroTerminated) + throw new NotImplementedException("Zero-terminated return type is not supported"); + + var lengthParameterIndex = data.ReturnType.AnyType.AsT1.Length ?? throw new Exception("Length Parameter not filled"); + var lengthParameter = parameters.ElementAt(lengthParameterIndex); + lengthParameter.IsArrayLengthParameter = true; + + data.SetPostReturnStatement(returnVariable => + { + var typeName = Model.Type.GetPublicNameFullyQuallified(data.ReturnType.AnyType.AsT1.AnyType.AsT0); + + return $$""" + var resultArray = GLib.Internal.StructArray.Copy<{{typeName}}>({{returnVariable}}, (uint) {{lengthParameter.GetSignatureName()}}); + {{RenderFreeStatement(data, returnVariable)}} + """; + }); + + data.SetExpression(returnVariable => "resultArray"); + } + + private static string RenderFreeStatement(ReturnTypeToManagedData data, string returnVariable) + { + return data.ReturnType.Transfer == Transfer.Full + ? $"GLib.Functions.Free({returnVariable});" + : string.Empty; + } +} diff --git a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/PrimitiveValueTypeArray.cs b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/PrimitiveValueTypeArray.cs index e8b8fdc39..d1c66fc4e 100644 --- a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/PrimitiveValueTypeArray.cs +++ b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/PrimitiveValueTypeArray.cs @@ -1,4 +1,5 @@ -using GirModel; +using System.Collections.Generic; +using GirModel; namespace Generator.Renderer.Public.ReturnTypeToManagedExpressions; @@ -7,6 +8,6 @@ internal class PrimitiveValueTypeArray : ReturnTypeConverter public bool Supports(AnyType type) => type.IsArray(); - public string GetString(GirModel.ReturnType returnType, string fromVariableName) - => fromVariableName; + public void Initialize(ReturnTypeToManagedData data, IEnumerable _) + => data.SetExpression(fromVariableName => fromVariableName); } diff --git a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/TypedRecord.cs b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/TypedRecord.cs index 78fd39b62..2bece50fb 100644 --- a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/TypedRecord.cs +++ b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/TypedRecord.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using GirModel; namespace Generator.Renderer.Public.ReturnTypeToManagedExpressions; @@ -8,21 +9,25 @@ internal class TypedRecord : ReturnTypeConverter public bool Supports(AnyType type) => type.Is(out var record) && Model.Record.IsTyped(record); - public string GetString(GirModel.ReturnType returnType, string fromVariableName) + public void Initialize(ReturnTypeToManagedData data, IEnumerable _) { - var record = (GirModel.Record) returnType.AnyType.AsT0; - - var handleExpression = returnType switch + data.SetExpression(fromVariableName => { - { Transfer: Transfer.Full } => fromVariableName, - { Transfer: Transfer.None } => $"{fromVariableName}.OwnedCopy()", - _ => throw new NotImplementedException("Unknown transfer type") - }; + var returnType = data.ReturnType; + var record = (GirModel.Record) returnType.AnyType.AsT0; + + var handleExpression = returnType switch + { + { Transfer: Transfer.Full } => fromVariableName, + { Transfer: Transfer.None } => $"{fromVariableName}.OwnedCopy()", + _ => throw new NotImplementedException("Unknown transfer type") + }; - var createNewInstance = $"new {Model.ComplexType.GetFullyQualified(record)}({handleExpression})"; + var createNewInstance = $"new {Model.ComplexType.GetFullyQualified(record)}({handleExpression})"; - return returnType.Nullable - ? $"{fromVariableName}.IsInvalid ? null : {createNewInstance}" - : createNewInstance; + return returnType.Nullable + ? $"{fromVariableName}.IsInvalid ? null : {createNewInstance}" + : createNewInstance; + }); } } diff --git a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/UnsignedLong.cs b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/UnsignedLong.cs index 73391bdc2..dd2f6bc37 100644 --- a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/UnsignedLong.cs +++ b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/UnsignedLong.cs @@ -1,4 +1,5 @@ -using GirModel; +using System.Collections.Generic; +using GirModel; namespace Generator.Renderer.Public.ReturnTypeToManagedExpressions; @@ -7,8 +8,10 @@ internal class UnsignedLong : ReturnTypeConverter public bool Supports(AnyType type) => type.Is(); - public string GetString(GirModel.ReturnType returnType, string fromVariableName) - => returnType.IsPointer + public void Initialize(ReturnTypeToManagedData data, IEnumerable _) + { + data.SetExpression(fromVariableName => data.ReturnType.IsPointer ? fromVariableName - : $"{fromVariableName}.Value"; + : $"{fromVariableName}.Value"); + } } diff --git a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/UntypedRecord.cs b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/UntypedRecord.cs index d59ae77ca..77d9cf1e3 100644 --- a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/UntypedRecord.cs +++ b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/UntypedRecord.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using GirModel; namespace Generator.Renderer.Public.ReturnTypeToManagedExpressions; @@ -8,21 +9,25 @@ internal class UntypedRecord : ReturnTypeConverter public bool Supports(AnyType type) => type.Is(out var record) && Model.Record.IsUntyped(record); - public string GetString(GirModel.ReturnType returnType, string fromVariableName) + public void Initialize(ReturnTypeToManagedData data, IEnumerable _) { - var record = (GirModel.Record) returnType.AnyType.AsT0; - - var handleExpression = returnType switch + data.SetExpression(fromVariableName => { - { Transfer: Transfer.Full } => fromVariableName, - { Transfer: Transfer.None } => $"{fromVariableName}.Copy()", - _ => throw new NotImplementedException($"Unsupported transfer type '{returnType.Transfer}' for untyped record {record.Name}") - }; + var returnType = data.ReturnType; + var record = (GirModel.Record) returnType.AnyType.AsT0; + + var handleExpression = returnType switch + { + { Transfer: Transfer.Full } => fromVariableName, + { Transfer: Transfer.None } => $"{fromVariableName}.Copy()", + _ => throw new NotImplementedException($"Unsupported transfer type '{returnType.Transfer}' for untyped record {record.Name}") + }; - var createNewInstance = $"new {Model.ComplexType.GetFullyQualified(record)}({handleExpression})"; + var createNewInstance = $"new {Model.ComplexType.GetFullyQualified(record)}({handleExpression})"; - return returnType.Nullable - ? $"{fromVariableName}.IsInvalid ? null : {createNewInstance}" - : createNewInstance; + return returnType.Nullable + ? $"{fromVariableName}.IsInvalid ? null : {createNewInstance}" + : createNewInstance; + }); } } diff --git a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/Utf8String.cs b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/Utf8String.cs index 9bb0a73de..0a53f195f 100644 --- a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/Utf8String.cs +++ b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/Utf8String.cs @@ -1,4 +1,5 @@ -using GirModel; +using System.Collections.Generic; +using GirModel; namespace Generator.Renderer.Public.ReturnTypeToManagedExpressions; @@ -7,9 +8,9 @@ internal class Utf8String : ReturnTypeConverter public bool Supports(AnyType type) => type.Is(); - public string GetString(GirModel.ReturnType returnType, string fromVariableName) + public void Initialize(ReturnTypeToManagedData data, IEnumerable _) { // Convert the Utf8StringHandle return type to a string. - return $"{fromVariableName}.ConvertToString()"; + data.SetExpression(fromVariableName => $"{fromVariableName}.ConvertToString()"); } } diff --git a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/Utf8StringArray.cs b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/Utf8StringArray.cs index 21087eac8..2a467efac 100644 --- a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/Utf8StringArray.cs +++ b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/Utf8StringArray.cs @@ -1,4 +1,6 @@ using System; +using System.Collections.Generic; +using System.Data.Common; namespace Generator.Renderer.Public.ReturnTypeToManagedExpressions; @@ -7,16 +9,20 @@ internal class Utf8StringArray : ReturnTypeConverter public bool Supports(GirModel.AnyType type) => type.IsArray(); - public string GetString(GirModel.ReturnType returnType, string fromVariableName) + public void Initialize(ReturnTypeToManagedData data, IEnumerable _) { - var arrayType = returnType.AnyType.AsT1; - if (arrayType.IsZeroTerminated) - return NullTerminatedArray(returnType, fromVariableName); + data.SetExpression(fromVariableName => + { + var returnType = data.ReturnType; + var arrayType = returnType.AnyType.AsT1; - if (arrayType.Length is not null) - return SizeBasedArray(returnType, fromVariableName); + if (arrayType.IsZeroTerminated) + return NullTerminatedArray(returnType, fromVariableName); + if (arrayType.Length is not null) + return SizeBasedArray(returnType, fromVariableName); - throw new Exception("Unknown kind of array"); + throw new Exception("Unknown kind of array"); + }); } private static string NullTerminatedArray(GirModel.ReturnType returnType, string fromVariableName) diff --git a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/Void.cs b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/Void.cs new file mode 100644 index 000000000..cec86321c --- /dev/null +++ b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/Converter/Void.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using GirModel; + +namespace Generator.Renderer.Public.ReturnTypeToManagedExpressions; + +internal class Void : ReturnTypeConverter +{ + public bool Supports(AnyType type) + => type.Is(); + + public void Initialize(ReturnTypeToManagedData data, IEnumerable _) + { + //Do nothing in case of void. There is no expression to create + } +} diff --git a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/ReturnTypeConverter.cs b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/ReturnTypeConverter.cs index 18818cf9d..f2ce489d4 100644 --- a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/ReturnTypeConverter.cs +++ b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/ReturnTypeConverter.cs @@ -1,9 +1,9 @@ -using GirModel; +using System.Collections.Generic; namespace Generator.Renderer.Public.ReturnTypeToManagedExpressions; internal interface ReturnTypeConverter { - bool Supports(AnyType type); - string GetString(GirModel.ReturnType returnType, string fromVariableName); + bool Supports(GirModel.AnyType type); + void Initialize(ReturnTypeToManagedData data, IEnumerable parameters); } diff --git a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/ReturnTypeToManagedData.cs b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/ReturnTypeToManagedData.cs new file mode 100644 index 000000000..d53766489 --- /dev/null +++ b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/ReturnTypeToManagedData.cs @@ -0,0 +1,31 @@ +using System; + +namespace Generator.Renderer.Public; + +public class ReturnTypeToManagedData(GirModel.ReturnType returnType) +{ + private Func? _expression; + private Func? _postReturnStatement; + + public GirModel.ReturnType ReturnType { get; } = returnType; + + public void SetPostReturnStatement(Func? expression) + { + _postReturnStatement = expression; + } + + public string? GetPostReturnStatement(string returnVariable) + { + return _postReturnStatement?.Invoke(returnVariable); + } + + public void SetExpression(Func expression) + { + _expression = expression; + } + + public string? GetExpression(string returnVariable) + { + return _expression?.Invoke(returnVariable); + } +} diff --git a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/ReturnTypeToManagedExpression.cs b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/ReturnTypeToManagedExpression.cs index 2c695666f..b4ab950db 100644 --- a/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/ReturnTypeToManagedExpression.cs +++ b/src/Generation/Generator/Renderer/Public/ReturnTypeToManagedExpression/ReturnTypeToManagedExpression.cs @@ -4,8 +4,8 @@ namespace Generator.Renderer.Public; internal static class ReturnTypeToManagedExpression { - private static readonly List Converter = new() - { + private static readonly List Converter = + [ new ReturnTypeToManagedExpressions.Bitfield(), new ReturnTypeToManagedExpressions.Class(), new ReturnTypeToManagedExpressions.Enumeration(), @@ -21,19 +21,28 @@ internal static class ReturnTypeToManagedExpression new ReturnTypeToManagedExpressions.UnsignedLong(), //Must be before primitive value type new ReturnTypeToManagedExpressions.PrimitiveValueType(), new ReturnTypeToManagedExpressions.PrimitiveValueTypeAlias(), + new ReturnTypeToManagedExpressions.PrimitiveValueTypeAliasArray(), new ReturnTypeToManagedExpressions.PrimitiveValueTypeArray(), new ReturnTypeToManagedExpressions.TypedRecord(), new ReturnTypeToManagedExpressions.UntypedRecord(), new ReturnTypeToManagedExpressions.Utf8String(), new ReturnTypeToManagedExpressions.Utf8StringArray(), - }; + new ReturnTypeToManagedExpressions.Void() + ]; - public static string Render(GirModel.ReturnType from, string fromVariableName) + public static ReturnTypeToManagedData Initialize(GirModel.ReturnType returnType, IEnumerable parameters) { + var data = new ReturnTypeToManagedData(returnType); + foreach (var converter in Converter) - if (converter.Supports(from.AnyType)) - return converter.GetString(from, fromVariableName); + { + if (!converter.Supports(returnType.AnyType)) + continue; + + converter.Initialize(data, parameters); + return data; + } - throw new System.NotImplementedException($"Missing converter to convert from internal return type {from} to public."); + throw new System.NotImplementedException($"Missing converter to convert from internal return type {returnType} to public."); } } diff --git a/src/Generation/GirLoader/Output/Callback.GirModel.cs b/src/Generation/GirLoader/Output/Callback.GirModel.cs index 1b9b2f2ee..c9108a47f 100644 --- a/src/Generation/GirLoader/Output/Callback.GirModel.cs +++ b/src/Generation/GirLoader/Output/Callback.GirModel.cs @@ -6,7 +6,7 @@ namespace GirLoader.Output; public partial class Callback : GirModel.Callback { - ReturnType GirModel.Callback.ReturnType => ReturnValue; + ReturnType GirModel.Callable.ReturnType => ReturnValue; bool GirModel.Callable.Throws => Throws; IEnumerable GirModel.Callable.Parameters => ParameterList.GetParameters().Cast(); GirModel.InstanceParameter? GirModel.Callable.InstanceParameter => null; diff --git a/src/Generation/GirLoader/Output/Constructor.GirModel.cs b/src/Generation/GirLoader/Output/Constructor.GirModel.cs index fc6a7c52f..c34cd6405 100644 --- a/src/Generation/GirLoader/Output/Constructor.GirModel.cs +++ b/src/Generation/GirLoader/Output/Constructor.GirModel.cs @@ -8,7 +8,7 @@ public partial class Constructor : GirModel.Constructor { GirModel.ComplexType GirModel.Constructor.Parent => _parent ?? throw new Exception($"{Identifier}: Unknown parent"); string GirModel.Callable.Name => Name; - GirModel.ReturnType GirModel.Constructor.ReturnType => ReturnValue; + GirModel.ReturnType GirModel.Callable.ReturnType => ReturnValue; string GirModel.Constructor.CIdentifier => Identifier; string? GirModel.Constructor.Version => Version; IEnumerable GirModel.Callable.Parameters => ParameterList.GetParameters().Cast(); diff --git a/src/Generation/GirLoader/Output/Function.GirModel.cs b/src/Generation/GirLoader/Output/Function.GirModel.cs index b8c9bdf3d..0c96f43bc 100644 --- a/src/Generation/GirLoader/Output/Function.GirModel.cs +++ b/src/Generation/GirLoader/Output/Function.GirModel.cs @@ -8,7 +8,7 @@ public partial class Function : GirModel.Function GirModel.Namespace GirModel.Function.Namespace => _repository.Namespace; GirModel.ComplexType? GirModel.Function.Parent => _parent; string GirModel.Callable.Name => Name; - GirModel.ReturnType GirModel.Function.ReturnType => ReturnValue; + GirModel.ReturnType GirModel.Callable.ReturnType => ReturnValue; string GirModel.Function.CIdentifier => Identifier; IEnumerable GirModel.Callable.Parameters => ParameterList.GetParameters().Cast(); GirModel.InstanceParameter? GirModel.Callable.InstanceParameter => null; diff --git a/src/Generation/GirLoader/Output/Method.GirModel.cs b/src/Generation/GirLoader/Output/Method.GirModel.cs index 3f25756e4..c4b058acf 100644 --- a/src/Generation/GirLoader/Output/Method.GirModel.cs +++ b/src/Generation/GirLoader/Output/Method.GirModel.cs @@ -7,7 +7,7 @@ public partial class Method : GirModel.Method { GirModel.ComplexType GirModel.Method.Parent => _parent ?? throw new Exception($"{Identifier}: Unknown parent"); string GirModel.Callable.Name => Name; - GirModel.ReturnType GirModel.Method.ReturnType => ReturnValue; + GirModel.ReturnType GirModel.Callable.ReturnType => ReturnValue; string GirModel.Method.CIdentifier => Identifier; GirModel.InstanceParameter GirModel.Method.InstanceParameter => ParameterList.InstanceParameter ?? throw new Exception("Instance parameter mis missing"); GirModel.InstanceParameter? GirModel.Callable.InstanceParameter => ParameterList.InstanceParameter; diff --git a/src/Generation/GirLoader/PlatformSupport/Callbacks/Callback.GirModel.cs b/src/Generation/GirLoader/PlatformSupport/Callbacks/Callback.GirModel.cs index e8847311f..24088e7d3 100644 --- a/src/Generation/GirLoader/PlatformSupport/Callbacks/Callback.GirModel.cs +++ b/src/Generation/GirLoader/PlatformSupport/Callbacks/Callback.GirModel.cs @@ -9,7 +9,7 @@ public partial class Callback : GirModel.Callback string GirModel.ComplexType.Name => _callback.Name; string GirModel.Callable.Name => _callback.Name; bool GirModel.Callable.Throws => _callback.Throws; - GirModel.ReturnType GirModel.Callback.ReturnType => _callback.ReturnType; + GirModel.ReturnType GirModel.Callable.ReturnType => _callback.ReturnType; IEnumerable GirModel.Callable.Parameters => _callback.Parameters; bool GirModel.Callback.Introspectable => _callback.Introspectable; GirModel.InstanceParameter? GirModel.Callable.InstanceParameter => null; diff --git a/src/Generation/GirLoader/PlatformSupport/Functions/Function.GirModel.cs b/src/Generation/GirLoader/PlatformSupport/Functions/Function.GirModel.cs index 652fddfe6..57f06b99c 100644 --- a/src/Generation/GirLoader/PlatformSupport/Functions/Function.GirModel.cs +++ b/src/Generation/GirLoader/PlatformSupport/Functions/Function.GirModel.cs @@ -7,7 +7,7 @@ public partial class Function : GirModel.Function GirModel.Namespace GirModel.Function.Namespace => _function.Namespace; GirModel.ComplexType? GirModel.Function.Parent => _function.Parent; string GirModel.Callable.Name => _function.Name; - GirModel.ReturnType GirModel.Function.ReturnType => _function.ReturnType; + GirModel.ReturnType GirModel.Callable.ReturnType => _function.ReturnType; string GirModel.Function.CIdentifier => _function.CIdentifier; IEnumerable GirModel.Callable.Parameters => _function.Parameters; GirModel.InstanceParameter? GirModel.Callable.InstanceParameter => _function.InstanceParameter; diff --git a/src/Generation/GirModel/Callable.cs b/src/Generation/GirModel/Callable.cs index 8da7ffb25..438881223 100644 --- a/src/Generation/GirModel/Callable.cs +++ b/src/Generation/GirModel/Callable.cs @@ -6,6 +6,7 @@ public interface Callable { string Name { get; } bool Throws { get; } + ReturnType ReturnType { get; } IEnumerable Parameters { get; } InstanceParameter? InstanceParameter { get; } Callable? Shadows { get; } diff --git a/src/Generation/GirModel/Callback.cs b/src/Generation/GirModel/Callback.cs index 5f3b237d7..b7b7d5e7d 100644 --- a/src/Generation/GirModel/Callback.cs +++ b/src/Generation/GirModel/Callback.cs @@ -3,6 +3,5 @@ public interface Callback : ComplexType, Callable { new string Name { get; } - ReturnType ReturnType { get; } bool Introspectable { get; } } diff --git a/src/Generation/GirModel/Constructor.cs b/src/Generation/GirModel/Constructor.cs index 7e39b1574..2ce54ad09 100644 --- a/src/Generation/GirModel/Constructor.cs +++ b/src/Generation/GirModel/Constructor.cs @@ -4,6 +4,5 @@ public interface Constructor : Callable { ComplexType Parent { get; } string CIdentifier { get; } - ReturnType ReturnType { get; } string? Version { get; } } diff --git a/src/Generation/GirModel/Function.cs b/src/Generation/GirModel/Function.cs index 86cae448b..0b4d4ffc2 100644 --- a/src/Generation/GirModel/Function.cs +++ b/src/Generation/GirModel/Function.cs @@ -9,7 +9,6 @@ public interface Function : Callable /// ComplexType? Parent { get; } string CIdentifier { get; } - public ReturnType ReturnType { get; } public bool Introspectable { get; } string? Version { get; } } diff --git a/src/Generation/GirModel/Method.cs b/src/Generation/GirModel/Method.cs index ca4e8fe2a..f822512bd 100644 --- a/src/Generation/GirModel/Method.cs +++ b/src/Generation/GirModel/Method.cs @@ -4,7 +4,6 @@ public interface Method : Callable { ComplexType Parent { get; } string CIdentifier { get; } - ReturnType ReturnType { get; } // Methods always have an instance parameter. new InstanceParameter InstanceParameter { get; } bool Introspectable { get; } diff --git a/src/Libs/GLib-2.0/Internal/StructArray.cs b/src/Libs/GLib-2.0/Internal/StructArray.cs new file mode 100644 index 000000000..a59ef8202 --- /dev/null +++ b/src/Libs/GLib-2.0/Internal/StructArray.cs @@ -0,0 +1,22 @@ +using System; + +namespace GLib.Internal; + +public static class StructArray +{ + public static T[] Copy(IntPtr p, uint length) where T : unmanaged + { + var resultArray = new T[length]; + unsafe + { + var ptr = (T*) p; + for (var i = 0; i < length; i++) + { + resultArray[i] = *ptr; + ptr++; + } + } + + return resultArray; + } +} diff --git a/src/Native/GirTestLib/girtest-alias-tester.c b/src/Native/GirTestLib/girtest-alias-tester.c index 4848834c3..a3f2cfb97 100644 --- a/src/Native/GirTestLib/girtest-alias-tester.c +++ b/src/Native/GirTestLib/girtest-alias-tester.c @@ -93,4 +93,30 @@ GirTestPointerAlias girtest_alias_tester_to_pointer_alias(gpointer pointer) { return (GirTestPointerAlias) pointer; -} \ No newline at end of file +} + +/** + * girtest_alias_tester_get_array_transfer_full: + * @n_elements: (out) (optional): location for the length of the array or %NULL + * + * Always returns 3 IntAlias values from 1 to 3; + * + * Returns: (array length=n_elements) (transfer full): The array + */ +GirTestIntAlias* +girtest_alias_tester_get_array_transfer_full (guint *n_elements) +{ + if(n_elements) + *n_elements = 3; + + GirTestIntAlias* array = g_new(GirTestIntAlias, 4); + + for(int i = 0; i <3; i++) + { + array[i] = i+1; + } + + array[3] = 0; + + return array; +} diff --git a/src/Native/GirTestLib/girtest-alias-tester.h b/src/Native/GirTestLib/girtest-alias-tester.h index 2efa3a6ea..45b4d8b9c 100644 --- a/src/Native/GirTestLib/girtest-alias-tester.h +++ b/src/Native/GirTestLib/girtest-alias-tester.h @@ -47,4 +47,7 @@ girtest_alias_tester_to_pointer(GirTestPointerAlias alias); GirTestPointerAlias girtest_alias_tester_to_pointer_alias(gpointer pointer); +GirTestIntAlias* +girtest_alias_tester_get_array_transfer_full (guint *n_elements); + G_END_DECLS diff --git a/src/Tests/Libs/GirTest-0.1.Tests/AliasTest.cs b/src/Tests/Libs/GirTest-0.1.Tests/AliasTest.cs index 4978e82ae..ceabb32c0 100644 --- a/src/Tests/Libs/GirTest-0.1.Tests/AliasTest.cs +++ b/src/Tests/Libs/GirTest-0.1.Tests/AliasTest.cs @@ -104,4 +104,14 @@ public void CanConvertPointerToPointerAlias() { AliasTester.ToPointerAlias((IntPtr) 42).Should().Be(new PointerAlias((IntPtr) 42)); } + + [TestMethod] + public void CanReadArrayTransferFull() + { + var array = AliasTester.GetArrayTransferFull(); + array.Length.Should().Be(3); + array[0].Should().Be(new IntAlias(1)); + array[1].Should().Be(new IntAlias(2)); + array[2].Should().Be(new IntAlias(3)); + } }