Skip to content

Commit

Permalink
Add support for untyped records
Browse files Browse the repository at this point in the history
  • Loading branch information
badcel committed Mar 12, 2024
1 parent 0594192 commit 530a053
Show file tree
Hide file tree
Showing 60 changed files with 1,764 additions and 43 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using GirModel;
using Method = Generator.Model.Method;

namespace Generator.Fixer.Record;

public class MethodWithInOutInstanceParameterFixer : Fixer<GirModel.Record>
{
public void Fixup(GirModel.Record record)
{
foreach (var method in record.Methods)
{
if (method.InstanceParameter.Direction == Direction.InOut)
{
Method.Disable(method);
Log.Warning($"Method {method.Name} has an instance parameter with direction inout which is not supported. Method is disabled.");
}
}
}
}
1 change: 1 addition & 0 deletions src/Generation/Generator/Fixer/Records.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ public static class Records
private static readonly List<Fixer<GirModel.Record>> Fixers = new()
{
new InternalMethodsNamedLikeRecordFixer(),
new MethodWithInOutInstanceParameterFixer(),
new PublicMethodsColldingWithFieldFixer()
};

Expand Down
29 changes: 29 additions & 0 deletions src/Generation/Generator/Generator/Internal/UntypedRecord.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using Generator.Model;

namespace Generator.Generator.Internal;

internal class UntypedRecord : Generator<GirModel.Record>
{
private readonly Publisher _publisher;

public UntypedRecord(Publisher publisher)
{
_publisher = publisher;
}

public void Generate(GirModel.Record obj)
{
if (!Record.IsUntyped(obj))
return;

var source = Renderer.Internal.UntypedRecord.Render(obj);
var codeUnit = new CodeUnit(
Project: Namespace.GetCanonicalName(obj.Namespace),
Name: obj.Name,
Source: source,
IsInternal: true
);

_publisher.Publish(codeUnit);
}
}
29 changes: 29 additions & 0 deletions src/Generation/Generator/Generator/Internal/UntypedRecordData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using Generator.Model;

namespace Generator.Generator.Internal;

internal class UntypedRecordData : Generator<GirModel.Record>
{
private readonly Publisher _publisher;

public UntypedRecordData(Publisher publisher)
{
_publisher = publisher;
}

public void Generate(GirModel.Record obj)
{
if (!Record.IsUntyped(obj))
return;

var source = Renderer.Internal.UntypedRecordData.Render(obj);
var codeUnit = new CodeUnit(
Project: Namespace.GetCanonicalName(obj.Namespace),
Name: Model.UntypedRecord.GetDataName(obj),
Source: source,
IsInternal: true
);

_publisher.Publish(codeUnit);
}
}
29 changes: 29 additions & 0 deletions src/Generation/Generator/Generator/Internal/UntypedRecordHandle.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using Generator.Model;

namespace Generator.Generator.Internal;

internal class UntypedRecordHandle : Generator<GirModel.Record>
{
private readonly Publisher _publisher;

public UntypedRecordHandle(Publisher publisher)
{
_publisher = publisher;
}

public void Generate(GirModel.Record obj)
{
if (!Record.IsUntyped(obj))
return;

var source = Renderer.Internal.UntypedRecordHandle.Render(obj);
var codeUnit = new CodeUnit(
Project: Namespace.GetCanonicalName(obj.Namespace),
Name: Model.UntypedRecord.GetInternalHandle(obj),
Source: source,
IsInternal: true
);

_publisher.Publish(codeUnit);
}
}
29 changes: 29 additions & 0 deletions src/Generation/Generator/Generator/Public/UntypedRecord.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using Generator.Model;

namespace Generator.Generator.Public;

internal class UntypedRecord : Generator<GirModel.Record>
{
private readonly Publisher _publisher;

public UntypedRecord(Publisher publisher)
{
_publisher = publisher;
}

public void Generate(GirModel.Record record)
{
if (!Record.IsUntyped(record))
return;

var source = Renderer.Public.UntypedRecord.Render(record);
var codeUnit = new CodeUnit(
Project: Namespace.GetCanonicalName(record.Namespace),
Name: Record.GetPublicClassName(record),
Source: source,
IsInternal: false
);

_publisher.Publish(codeUnit);
}
}
7 changes: 6 additions & 1 deletion src/Generation/Generator/Model/Record.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ internal static partial class Record
{
public static bool IsStandard(GirModel.Record record)
{
return !IsForeignTyped(record) && !IsOpaqueTyped(record) && !IsOpaqueUntyped(record) && !IsTyped(record);
return !IsForeignTyped(record) && !IsOpaqueTyped(record) && !IsOpaqueUntyped(record) && !IsTyped(record) && !IsUntyped(record);
}

public static bool IsForeignTyped(GirModel.Record record)
Expand Down Expand Up @@ -35,6 +35,11 @@ public static bool IsTyped(GirModel.Record record)
return record is { Foreign: false, Opaque: false, TypeFunction.CIdentifier: not "intern" };
}

public static bool IsUntyped(GirModel.Record record)
{
return record is { Foreign: false, Opaque: false, TypeFunction: null or { CIdentifier: "intern" } };
}

public static string GetFullyQualifiedInternalStructName(GirModel.Record record)
=> Namespace.GetInternalName(record.Namespace) + "." + GetInternalStructName(record);

Expand Down
86 changes: 86 additions & 0 deletions src/Generation/Generator/Model/UntypedRecord.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
using System.Linq;

namespace Generator.Model;

internal static class UntypedRecord
{
public static string GetPublicClassName(GirModel.Record record)
=> record.Name;

public static string GetFullyQualifiedPublicClassName(GirModel.Record record)
=> Namespace.GetPublicName(record.Namespace) + "." + GetPublicClassName(record);

public static string GetFullyQualifiedInternalClassName(GirModel.Record record)
=> Namespace.GetInternalName(record.Namespace) + "." + record.Name;

public static string GetInternalHandle(GirModel.Record record)
=> $"{Type.GetName(record)}Handle";

public static string GetInternalManagedHandle(GirModel.Record record)
=> $"{Type.GetName(record)}ManagedHandle";

public static string GetInternalOwnedHandle(GirModel.Record record)
=> $"{Type.GetName(record)}OwnedHandle";

public static string GetInternalUnownedHandle(GirModel.Record record)
=> $"{Type.GetName(record)}UnownedHandle";

public static string GetFullyQuallifiedHandle(GirModel.Record record)
=> $"{Namespace.GetInternalName(record.Namespace)}.{GetInternalHandle(record)}";

public static string GetFullyQuallifiedOwnedHandle(GirModel.Record record)
=> $"{Namespace.GetInternalName(record.Namespace)}.{GetInternalOwnedHandle(record)}";

public static string GetFullyQuallifiedUnownedHandle(GirModel.Record record)
=> $"{Namespace.GetInternalName(record.Namespace)}.{GetInternalUnownedHandle(record)}";

public static string GetFullyQuallifiedNullHandle(GirModel.Record record)
=> $"{Namespace.GetInternalName(record.Namespace)}.{GetInternalUnownedHandle(record)}.NullHandle";

public static string GetDataName(GirModel.Record record)
=> $"{Type.GetName(record)}Data";

public static string GetFullyQuallifiedDataName(GirModel.Record record)
=> $"{Namespace.GetInternalName(record.Namespace)}.{GetDataName(record)}";

public static string GetFullyQuallifiedManagedHandle(GirModel.Record record)
=> $"{Namespace.GetInternalName(record.Namespace)}.{GetInternalManagedHandle(record)}";

public static string GetInternalArrayHandle(GirModel.Record record)
{
var prefix = $"{Type.GetName(record)}Array";
if (record.Namespace.Records.Select(x => x.Name).Contains(prefix))
prefix += "2";

return $"{prefix}Handle";
}

public static string GetFullyQuallifiedArrayHandle(GirModel.Record record)
=> $"{Namespace.GetInternalName(record.Namespace)}.{GetInternalArrayHandle(record)}";

public static string GetInternalArrayOwnedHandle(GirModel.Record record)
{
var prefix = $"{Type.GetName(record)}Array";
if (record.Namespace.Records.Select(x => x.Name).Contains(prefix))
prefix += "2";

return $"{prefix}OwnedHandle";
}

public static string GetFullyQuallifiedArrayOwnedHandle(GirModel.Record record)
=> $"{Namespace.GetInternalName(record.Namespace)}.{GetInternalArrayOwnedHandle(record)}";

public static string GetInternalArrayUnownedHandle(GirModel.Record record)
{
var prefix = $"{Type.GetName(record)}Array";
if (record.Namespace.Records.Select(x => x.Name).Contains(prefix))
prefix += "2";
return $"{prefix}UnownedHandle";
}

public static string GetFullyQuallifiedArrayUnownedHandle(GirModel.Record record)
=> $"{Namespace.GetInternalName(record.Namespace)}.{GetInternalArrayUnownedHandle(record)}";

public static string GetFullyQuallifiedArrayNullHandle(GirModel.Record record)
=> $"{Namespace.GetInternalName(record.Namespace)}.{GetInternalArrayUnownedHandle(record)}.NullHandle";
}
6 changes: 6 additions & 0 deletions src/Generation/Generator/Records.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ public static void Generate(IEnumerable<GirModel.Record> records, string path)
var publisher = new Publisher(path);
var generators = new List<Generator<GirModel.Record>>()
{
//Untyped records
new Generator.Internal.UntypedRecord(publisher),
new Generator.Internal.UntypedRecordData(publisher),
new Generator.Internal.UntypedRecordHandle(publisher),
new Generator.Public.UntypedRecord(publisher),

//Foreign typed records
new Generator.Internal.ForeignTypedRecord(publisher),
new Generator.Internal.ForeignTypedRecordHandle(publisher),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,6 @@ private static string GetNullableTypeName(GirModel.Field field)
{
var arrayType = field.AnyTypeOrCallback.AsT0.AsT1;
var type = (GirModel.Record) arrayType.AnyType.AsT0;
return Model.Record.GetFullyQualifiedInternalStructName(type) + "[]";
return Model.TypedRecord.GetFullyQuallifiedDataName(type) + "[]";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using Generator.Model;

namespace Generator.Renderer.Internal.Field;

internal class UntypedRecord : FieldConverter
{
public bool Supports(GirModel.Field field)
{
return field.AnyTypeOrCallback.TryPickT0(out var anyType, out _) && anyType.Is<GirModel.Record>(out var record) && Model.Record.IsUntyped(record);
}

public RenderableField Convert(GirModel.Field field)
{
return new RenderableField(
Name: Model.Field.GetName(field),
Attribute: null,
NullableTypeName: GetNullableTypeName(field)
);
}

private static string GetNullableTypeName(GirModel.Field field)
{
var type = (GirModel.Record) field.AnyTypeOrCallback.AsT0.AsT0;
return field.IsPointer
? Type.Pointer
: Model.Record.GetFullyQualifiedInternalStructName(type);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
namespace Generator.Renderer.Internal.Field;

internal class UntypedRecordArray : FieldConverter
{
public bool Supports(GirModel.Field field)
{
return field.AnyTypeOrCallback.TryPickT0(out var anyType, out _) && anyType.IsArray<GirModel.Record>(out var record) && Model.Record.IsUntyped(record); ;
}

public RenderableField Convert(GirModel.Field field)
{
return new RenderableField(
Name: Model.Field.GetName(field),
Attribute: GetAttribute(field),
NullableTypeName: GetNullableTypeName(field)
);
}

private static string? GetAttribute(GirModel.Field field)
{
var arrayType = field.AnyTypeOrCallback.AsT0.AsT1;
return arrayType.FixedSize is not null
? MarshalAs.UnmanagedByValArray(sizeConst: arrayType.FixedSize.Value)
: null;
}

private static string GetNullableTypeName(GirModel.Field field)
{
var arrayType = field.AnyTypeOrCallback.AsT0.AsT1;
var type = (GirModel.Record) arrayType.AnyType.AsT0;
return Model.UntypedRecord.GetFullyQuallifiedDataName(type) + "[]";
}
}
2 changes: 2 additions & 0 deletions src/Generation/Generator/Renderer/Internal/Field/Fields.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ internal static class Fields
new Field.TypedRecordArray(),
new Field.Union(),
new Field.UnionArray(),
new Field.UntypedRecord(),
new Field.UntypedRecordArray()
};

public static string Render(IEnumerable<GirModel.Field> fields)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public class {unownedHandleTypeName} : {typeName}
protected override bool ReleaseHandle()
{{
throw new Exception(""UnownedHandle must not be freed"");
throw new System.Exception(""UnownedHandle must not be freed"");
}}
}}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using System;

namespace Generator.Renderer.Internal.InstanceParameter;

internal class UntypedRecord : InstanceParameterConverter
{
public bool Supports(GirModel.Type type)
{
return type is GirModel.Record r && Model.Record.IsUntyped(r);
}

public RenderableInstanceParameter Convert(GirModel.InstanceParameter instanceParameter)
{
return new RenderableInstanceParameter(
Name: Model.InstanceParameter.GetName(instanceParameter),
NullableTypeName: GetNullableTypeName(instanceParameter)
);
}

private static string GetNullableTypeName(GirModel.InstanceParameter instanceParameter)
{
var type = (GirModel.Record) instanceParameter.Type;
return instanceParameter switch
{
{ Direction: GirModel.Direction.In, Transfer: GirModel.Transfer.None } => Model.UntypedRecord.GetFullyQuallifiedHandle(type),
{ Direction: GirModel.Direction.In, Transfer: GirModel.Transfer.Full } => throw new Exception("Can't transfer ownership of untyped record"),
_ => throw new System.Exception($"Can't detect untyped record instance parameter type {instanceParameter.Name}: CallerAllocates={instanceParameter.CallerAllocates} Direction={instanceParameter.Direction} Transfer={instanceParameter.Transfer}")
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ internal static class InstanceParameters
new InstanceParameter.Pointer(),
new InstanceParameter.Record(),
new InstanceParameter.TypedRecord(),
new InstanceParameter.Union()
new InstanceParameter.Union(),
new InstanceParameter.UntypedRecord()
};

public static string Render(GirModel.InstanceParameter instanceParameter)
Expand Down
Loading

0 comments on commit 530a053

Please sign in to comment.