Skip to content

Commit

Permalink
Overloads + miscellaneous binder fixes (#28)
Browse files Browse the repository at this point in the history
* PointerParameterOverloader

* PointerReturnValueOverloader

* ReturnTypeOverloader

* ArrayParameterOverloader

* StaticCountOverloader [NEW]

* Fix Overloader

* Commit updated specifications (fixed)

* Fix count signatures being misinterpreted and serialised incorrectly

* Duplicate signature checking for overloads

* Fix missing return keyword in PointerParameterOverloader

* Fix missing variable in ReturnTypeOverloader

* Iterate over newParameters instead of old parameters + more fixes in SCO

* Fix aftermath of b63cca

* Implement overloads.

* Give overloads an "antigen"/marker (in the form of a comment)

* Ok but let's not make the antigen bring down the system.

* Fix some yucky formatting

* Add a Flow attribute

* Relax some requirements for SCO

* Use attributes

* Fix package restore error

* FlowPointerOverloader [NEW]

* Fix a duplicate attribute bug

* Deeper typemapping where applicable

* in

* Update specifications

* Add homemade overloads to GL.cs

* Same, but for CoreGL and GLES
  • Loading branch information
Perksey authored and devvoid committed Jul 21, 2019
1 parent 0237ca5 commit 9107c96
Show file tree
Hide file tree
Showing 29 changed files with 63,084 additions and 30,110 deletions.
13,434 changes: 8,991 additions & 4,443 deletions build/binder_specifications/GLES.json

Large diffs are not rendered by default.

49,637 changes: 33,416 additions & 16,221 deletions build/binder_specifications/OpenGL (Compatibility Profile).json

Large diffs are not rendered by default.

28,299 changes: 18,949 additions & 9,350 deletions build/binder_specifications/OpenGL.json

Large diffs are not rendered by default.

112 changes: 112 additions & 0 deletions src/Core/BuildTools/Bind/Overloading/ArrayParameterOverloader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
// This file is part of Silk.NET.
//
// You may modify and distribute Silk.NET under the terms
// of the MIT license. See the LICENSE file for details.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Humanizer;
using MoreLinq.Extensions;
using Silk.NET.BuildTools.Common.Builders;
using Silk.NET.BuildTools.Common.Functions;

namespace Silk.NET.BuildTools.Bind.Overloading
{
public class ArrayParameterOverloader : IFunctionOverloader
{
/// <summary>
/// Determines whether or not the overloader is applicable for the given function.
/// </summary>
/// <param name="function">The function.</param>
/// <returns>true if the overloader is applicable; otherwise, false.</returns>
public static bool IsApplicable(Function function)
{
// function has exactly two parameters
var parameterCount = function.Parameters.Count;
if (parameterCount != 2)
{
return false;
}

// function's name starts with Get, Gen, or New
var hasCorrectPrefix = function.Name.StartsWith("Delete");
if (!hasCorrectPrefix)
{
return false;
}

var returnType = function.ReturnType;
if (!returnType.Name.Equals(typeof(void).Name, StringComparison.OrdinalIgnoreCase))
{
return false;
}

if (returnType.IsPointer)
{
return false;
}

var lastParameter = function.Parameters.Last();

if (!lastParameter.Type.IsPointer)
{
return false;
}

// the final parameter's flow is not out
if (lastParameter.Flow == FlowDirection.Out)
{
return false;
}

// the last parameter does not have a specific count set
if (!(lastParameter.Count is null) && lastParameter.Count.IsStatic)
{
if (lastParameter.Count.StaticCount > 1)
{
return false;
}
}

return true;
}

/// <inheritdoc/>
public IEnumerable<Overload> CreateOverloads(Function function)
{
if (!IsApplicable(function))
{
yield break;
}

var arrayParameter = function.Parameters.Last();
var arrayParameterType = arrayParameter.Type;

var newName = function.Name.Singularize(false);
var newParameters = SkipLastExtension.SkipLast(new List<Parameter>(function.Parameters), 2).ToList();

var newArrayParameterType = new TypeSignatureBuilder(arrayParameterType)
.WithArrayDimensions(0)
.WithIndirectionLevel(0)
.Build();

var newArrayParameter = new ParameterSignatureBuilder(arrayParameter)
.WithType(newArrayParameterType)
.Build();

newParameters.Add(newArrayParameter);

var sb = new StringBuilder();

sb.AppendLine("// ArrayParameterOverloader");
sb.AppendLine(function.Name + "(1, &" + newArrayParameter.Name + ");");

yield return new Overload(new FunctionSignatureBuilder(function)
.WithName(newName)
.WithParameters(newParameters)
.Build(), sb, true);
}
}
}
86 changes: 86 additions & 0 deletions src/Core/BuildTools/Bind/Overloading/FlowPointerOverloader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// This file is part of Silk.NET.
//
// You may modify and distribute Silk.NET under the terms
// of the MIT license. See the LICENSE file for details.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Silk.NET.BuildTools.Common;
using Silk.NET.BuildTools.Common.Builders;
using Silk.NET.BuildTools.Common.Functions;

namespace Silk.NET.BuildTools.Bind.Overloading
{
public class FlowPointerOverloader : IFunctionOverloader
{
public IEnumerable<Overload> CreateOverloads(Function function)
{
if (!function.Parameters.Any(x => x.Type.IsPointer && !x.Type.IsVoidPointer()))
{
yield break;
}

var sb = new StringBuilder();
var parameters = new List<string>();
var ind = string.Empty;
var sig = new FunctionSignatureBuilder(function);
var newParameters = new Parameter[function.Parameters.Count];
sb.AppendLine("// FlowPointerOverloader");

for (var i = 0; i < function.Parameters.Count; i++)
{
var param = function.Parameters[i];
if (param.Type.IsPointer && !param.Type.IsVoidPointer())
{
var newParameterType = new TypeSignatureBuilder(param.Type)
.WithIndirectionLevel(param.Type.IndirectionLevels - 1);
switch (param.Flow)
{
case FlowDirection.Undefined:
newParameterType = newParameterType.WithByRef(true);
break;
case FlowDirection.In:
newParameterType = newParameterType.WithIsIn(true);
break;
case FlowDirection.Out:
newParameterType = newParameterType.WithIsOut(true);
break;
default:
throw new ArgumentOutOfRangeException();
}

var newParameter = new ParameterSignatureBuilder(param).WithType(newParameterType.Build());
parameters.Add(param.Name + "Ptr");
var safeName = (Utilities.CSharpKeywords.Contains(param.Name) ? "@" : string.Empty) + param.Name;
sb.AppendLine(ind + $"fixed ({param.Type} {param.Name}Ptr = &{safeName})");
sb.AppendLine(ind + "{");
ind += " ";
newParameters[i] = newParameter.Build();
}
else
{
parameters.Add((Utilities.CSharpKeywords.Contains(param.Name) ? "@" : string.Empty) + param.Name);
newParameters[i] = param;
}
}

sb.Append(ind);
if (function.ReturnType.ToString() != "void")
{
sb.Append("return ");
}

sb.AppendLine(function.Name + "(" + string.Join(", ", parameters) + ");");

while (!string.IsNullOrEmpty(ind))
{
ind = ind.Remove(ind.Length - 4, 4);
sb.AppendLine(ind + "}");
}

yield return new Overload(sig.WithParameters(newParameters).Build(), sb, true);
}
}
}
46 changes: 43 additions & 3 deletions src/Core/BuildTools/Bind/Overloading/Overloader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,26 @@
// of the MIT license. See the LICENSE file for details.

using System.Collections.Generic;
using System.Linq;
using Silk.NET.BuildTools.Common;

namespace Silk.NET.BuildTools.Bind.Overloading
{
public static class Overloader
{
// TODO: Implement overloaders
public static readonly IFunctionOverloader[] Pipeline = new IFunctionOverloader[0];
public static readonly IFunctionOverloader[] Pipeline =
{
new ArrayParameterOverloader(),
new PointerParameterOverloader(),
new ReturnTypeOverloader(),
new PointerReturnValueOverloader(),
new StaticCountOverloader(),
new FlowPointerOverloader()
};

public static IEnumerable<Overload> GetOverloads(Project project)
{
var ret = new List<Overload>();
foreach (var @interface in project.Interfaces.Values)
{
foreach (var function in @interface.Functions)
Expand All @@ -23,11 +32,42 @@ public static IEnumerable<Overload> GetOverloads(Project project)
{
foreach (var overload in overloader.CreateOverloads(function))
{
yield return overload;
if (!@interface.Functions.Any(x => x.Equals(overload.Signature)))
{
if (!ret.Any(x => x.Signature.Equals(overload.Signature)))
{
ret.Add(overload);
}
}
}
}
}
}

return ret;
}

public static IEnumerable<Overload> GetOverloads(Interface @interface)
{
var ret = new List<Overload>();
foreach (var function in @interface.Functions)
{
foreach (var overloader in Pipeline)
{
foreach (var overload in overloader.CreateOverloads(function))
{
if (!@interface.Functions.Any(x => x.Equals(overload.Signature)))
{
if (!ret.Any(x => x.Signature.Equals(overload.Signature)))
{
ret.Add(overload);
}
}
}
}
}

return ret;
}
}
}
Loading

0 comments on commit 9107c96

Please sign in to comment.