Skip to content

Commit

Permalink
Primitive value type alias: Support returning arrays
Browse files Browse the repository at this point in the history
  • Loading branch information
badcel committed Sep 19, 2024
1 parent 2fd5504 commit a8f019d
Show file tree
Hide file tree
Showing 51 changed files with 468 additions and 192 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Generator.Renderer.Public;

namespace Generator.Renderer.Internal.ParameterToManagedExpressions;

Expand All @@ -21,15 +22,14 @@ public void Initialize(ParameterToManagedData parameterData, IEnumerable<Paramet
var signatureName = Model.Parameter.GetName(parameterData.Parameter);
var callName = signatureName + "Managed";

var parameterToNativeDatas = Public.ParameterToNativeExpression.Initialize(callback.Parameters);

var callableData = Public.CallableExpressions.Initialize(callback);
parameterData.SetSignatureName(() => 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);
}
Expand Down Expand Up @@ -67,7 +67,7 @@ private static string RenderContent(IEnumerable<Public.ParameterToNativeData> pa
.Join(Environment.NewLine);
}

private static string RenderCallStatement(string signatureName, GirModel.Callback callback, IReadOnlyList<Public.ParameterToNativeData> parameters, out string resultVariableName)
private static string RenderCallStatement(string signatureName, GirModel.Callback callback, IReadOnlyCollection<Public.ParameterToNativeData> parameters, out string resultVariableName)
{
resultVariableName = $"result{callback.Name}";
var call = new StringBuilder();
Expand All @@ -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<GirModel.Void>()
return data.ReturnType.AnyType.Is<GirModel.Void>()
? string.Empty
: $"return {Public.ReturnTypeToManagedExpression.Render(callback.ReturnType, returnVariable)};";
: $"return {data.GetExpression(returnVariable)};";
}
}
Original file line number Diff line number Diff line change
@@ -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<GirModel.PrimitiveValueType>();
}

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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using System.Collections.Generic;

namespace Generator.Renderer.Public;

public record CallableData(
ReturnTypeToManagedData ReturnTypeToManagedData,
IReadOnlyCollection<ParameterToNativeData> ParameterToNativeDatas
);
Original file line number Diff line number Diff line change
@@ -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);
}
}
21 changes: 11 additions & 10 deletions src/Generation/Generator/Renderer/Public/FunctionRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -89,7 +90,7 @@ private static string RenderParameters(IEnumerable<ParameterToNativeData> parame
return result.Join(", ");
}

private static string RenderCallStatement(GirModel.Function function, IReadOnlyList<ParameterToNativeData> parameters, out string resultVariableName)
private static string RenderCallStatement(GirModel.Function function, IEnumerable<ParameterToNativeData> parameters, out string resultVariableName)
{
resultVariableName = $"result{Function.GetName(function)}";
var call = new StringBuilder();
Expand All @@ -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<GirModel.Void>()
return data.ReturnType.AnyType.Is<GirModel.Void>()
? string.Empty
: $"return {ReturnTypeToManagedExpression.Render(function.ReturnType, returnVariable)};";
: $"return {data.GetExpression(returnVariable)};";
}

private static bool IsSupported(GirModel.Function function)
Expand Down
22 changes: 11 additions & 11 deletions src/Generation/Generator/Renderer/Public/MethodRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -96,7 +96,7 @@ private static string RenderParameters(IEnumerable<ParameterToNativeData> parame
return result.Join(", ");
}

private static string RenderCallStatement(GirModel.Method method, IReadOnlyList<ParameterToNativeData> parameters, out string resultVariableName)
private static string RenderCallStatement(GirModel.Method method, IReadOnlyCollection<ParameterToNativeData> parameters, out string resultVariableName)
{
resultVariableName = $"result{Method.GetPublicName(method)}";
var call = new StringBuilder();
Expand All @@ -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<GirModel.Void>()
return data.ReturnType.AnyType.Is<GirModel.Void>()
? string.Empty
: $"return {ReturnTypeToManagedExpression.Render(method.ReturnType, returnVariable)};";
: $"return {data.GetExpression(returnVariable)};";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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}");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace Generator.Renderer.Public;

public class ParameterToNativeData
public class ParameterToNativeData(GirModel.Parameter parameter)
{
private Func<string>? _getCallName;
private Func<string>? _getSignatureName;
Expand All @@ -14,19 +14,14 @@ 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; }
public bool IsArrayLengthParameter { get; internal set; }
public bool IsInOutArrayLengthParameter { get; internal set; }
public bool IsGLibErrorParameter { get; internal set; }

public ParameterToNativeData(GirModel.Parameter parameter)
{
Parameter = parameter;
}

public void SetExpression(Func<string> getExpression)
{
_getExpression = getExpression;
Expand Down
Original file line number Diff line number Diff line change
@@ -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<GirModel.PrimitiveValueType>();
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ namespace Generator.Renderer.Public;

internal static class ReturnTypeRenderer
{
private static readonly List<ReturnType.ReturnTypeConverter> converters = new()
{
private static readonly List<ReturnType.ReturnTypeConverter> converters =
[
new ReturnType.Bitfield(),
new ReturnType.Class(),
new ReturnType.Enumeration(),
Expand All @@ -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)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using GirModel;
using System.Collections.Generic;
using GirModel;

namespace Generator.Renderer.Public.ReturnTypeToManagedExpressions;

Expand All @@ -7,6 +8,6 @@ internal class Bitfield : ReturnTypeConverter
public bool Supports(AnyType type)
=> type.Is<GirModel.Bitfield>();

public string GetString(GirModel.ReturnType returnType, string fromVariableName)
=> fromVariableName;
public void Initialize(ReturnTypeToManagedData data, IEnumerable<ParameterToNativeData> _)
=> data.SetExpression(fromVariableName => fromVariableName);
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using Generator.Model;

namespace Generator.Renderer.Public.ReturnTypeToManagedExpressions;
Expand All @@ -8,15 +9,20 @@ internal class Class : ReturnTypeConverter
public bool Supports(GirModel.AnyType type)
=> type.Is<GirModel.Class>();

public string GetString(GirModel.ReturnType returnType, string fromVariableName)
public void Initialize(ReturnTypeToManagedData data, IEnumerable<ParameterToNativeData> _)
{
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)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using GirModel;
using System.Collections.Generic;
using GirModel;

namespace Generator.Renderer.Public.ReturnTypeToManagedExpressions;

Expand All @@ -7,6 +8,6 @@ internal class Enumeration : ReturnTypeConverter
public bool Supports(AnyType type)
=> type.Is<GirModel.Enumeration>();

public string GetString(GirModel.ReturnType returnType, string fromVariableName)
=> fromVariableName;
public void Initialize(ReturnTypeToManagedData data, IEnumerable<ParameterToNativeData> _)
=> data.SetExpression(fromVariableName => fromVariableName);
}
Original file line number Diff line number Diff line change
@@ -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<GirModel.Record>(out var record) && Model.Record.IsForeignTyped(record);

public string GetString(GirModel.ReturnType returnType, string fromVariableName)
public void Initialize(ReturnTypeToManagedData data, IEnumerable<ParameterToNativeData> _)
{
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;
});
}
}
Loading

0 comments on commit a8f019d

Please sign in to comment.