/// <inheritdoc/>
        public IEnumerable <(FunctionSignature, StringBuilder)> CreateOverloads(FunctionSignature function)
        {
            if (!IsApplicable(function))
            {
                yield break;
            }

            var lastParameterType = function.Parameters.Last().Type;
            var newReturnType     = new TypeSignatureBuilder(lastParameterType)
                                    .WithIndirectionLevel(lastParameterType.IndirectionLevel - 1)
                                    .WithArrayDimensions(0)
                                    .Build();

            var newParameters = SkipLastExtension.SkipLast(function.Parameters, 1).ToList();
            var newName       = function.Name.Singularize(false);

            var functionBuilder = new FunctionSignatureBuilder(function)
                                  .WithName(newName)
                                  .WithReturnType(newReturnType);

            var sb        = new StringBuilder();
            var strParams = newParameters.Select(x => Utilities.CSharpKeywords.Contains(x.Name) ? "@" + x.Name : x.Name)
                            .Concat(new[] { "ret" });

            sb.AppendLine(lastParameterType + " ret = null;");
            sb.Append(function.Name + "(");
            sb.Append(string.Join(", ", strParams));
            sb.AppendLine(");");
            sb.AppendLine("return *ret;");

            if (!newParameters.Any())
            {
                yield return(functionBuilder
                             .WithParameters(newParameters)
                             .Build(), sb);

                yield break;
            }

            // TODO: check if this has anything to do with CLS compliance
            var sizeParameterType = newParameters.Last().Type;

            if (!sizeParameterType.Name.StartsWith("int", StringComparison.OrdinalIgnoreCase) || sizeParameterType.IsPointer)
            {
                yield return(functionBuilder
                             .WithParameters(newParameters)
                             .Build(), sb);

                yield break;
            }

            newParameters = SkipLastExtension.SkipLast(newParameters, 1).ToList();
            yield return
                (
                functionBuilder
                .WithParameters(newParameters)
                .Build(), sb
                );
        }
Exemplo n.º 2
0
 public IEnumerable <ImplementedFunction> CreateOverloads(Function function)
 {
     if (function.ReturnType.ToString() == "char*" || function.ReturnType.ToString() == "byte*")
     {
         var sb = new StringBuilder();
         sb.Append($"return Marshal.PtrToStringAnsi((IntPtr) {function.Name}(");
         sb.Append(string.Join(", ", function.Parameters.Select(Convert)));
         sb.AppendLine("));");
         var sig = new FunctionSignatureBuilder(function).WithReturnType(new Type {
             Name = "string"
         }).WithName(function.Name + "S").Build();
         yield return(new ImplementedFunction(sig, sb, true));
     }
 }
Exemplo n.º 3
0
        public static bool TryGetEarlyVariant(Function function, out Function finalVariant, Project core)
        {
            var parameters = new List <Parameter>();
            var returnType = function.ReturnType;

            parameters.AddRange(function.Parameters);
            var parametersVaried = false;
            var returnTypeVaried = false;

            for (var i = 0; i < parameters.Count; i++)
            {
                foreach (var earlyOverloader in Pipeline)
                {
                    parameters[i].Origin = function;
                    if (earlyOverloader.TryCreateVariant(parameters[i], out var variant, core))
                    {
                        parametersVaried = true;
                        parameters[i]    = variant;
                        break;
                    }

                    parameters[i].Origin = null;
                }
            }

            foreach (var earlyOverloader in Pipeline)
            {
                if (earlyOverloader.TryCreateVariant(returnType, out var variant, core))
                {
                    returnTypeVaried = true;
                    returnType       = variant;
                    break;
                }
            }

            if (returnTypeVaried || parametersVaried)
            {
                finalVariant = new FunctionSignatureBuilder(function)
                               .WithParameters(parameters)
                               .WithReturnType(returnType)
                               .WithName(returnTypeVaried && !parametersVaried ? function.Name + "S" : function.Name)
                               .Build();

                return(true);
            }

            finalVariant = null;
            return(false);
        }
Exemplo n.º 4
0
        private IEnumerable <FunctionSignature> MapGenericEnumFunctions
        (
            [NotNull] ApiProfile profile,
            [NotNull, ItemNotNull] IReadOnlyList <FunctionSignature> genericEnumFunctions
        )
        {
            var mappedGenericEnumFunctions = new List <FunctionSignature>();

            foreach (var functionWithGenericEnum in genericEnumFunctions)
            {
                var newParameters = new List <ParameterSignature>(functionWithGenericEnum.Parameters);
                for (var i = 0; i < newParameters.Count; ++i)
                {
                    var parameter     = newParameters[i];
                    var parameterType = parameter.Type;

                    if (parameterType.Name != "GLenum")
                    {
                        continue;
                    }

                    var newParameterType = MapGenericEnumerationType(profile, functionWithGenericEnum, parameterType);
                    var newParameter     = new ParameterSignatureBuilder(parameter).WithType(newParameterType).Build();

                    newParameters[i] = newParameter;
                }

                var newReturnType = functionWithGenericEnum.ReturnType;
                if (newReturnType.Name == "GLenum")
                {
                    newReturnType = MapGenericEnumerationType(profile, functionWithGenericEnum, newReturnType);
                }

                var newFunction = new FunctionSignatureBuilder(functionWithGenericEnum)
                                  .WithParameters(newParameters)
                                  .WithReturnType(newReturnType)
                                  .Build();

                mappedGenericEnumFunctions.Add(newFunction);

                Debug.WriteLine
                (
                    $"Mapped parameters in \"{functionWithGenericEnum.Name}\" to generic enum types. Consider adding" +
                    " an override to a more specialized enum."
                );
            }

            return(mappedGenericEnumFunctions);
        }
Exemplo n.º 5
0
        private bool TryCreateEnumVariant(Function function, out Function variant, Project core)
        {
            var  varied        = false;
            var  newParameters = new List <Parameter>();
            var  paramsMod     = false;
            Type newReturnType = function.ReturnType;

            foreach (var functionParameter in function.Parameters)
            {
                if (functionParameter.Type.OriginalGroup is null || core.Enums.All
                        (x => x.Name != functionParameter.Type.OriginalGroup))
                {
                    newParameters.Add(functionParameter);
                    continue;
                }

                paramsMod = true;
                varied    = true;
                var t =
                    new TypeSignatureBuilder(functionParameter.Type).WithName
                        (functionParameter.Type.OriginalGroup)
                    .Build();
                t.OriginalName = t.Name; // stop GLenum mapping
                newParameters.Add
                (
                    new ParameterSignatureBuilder(functionParameter).WithType
                    (
                        t
                    ).Build()
                );
            }

            if (!(function.ReturnType.OriginalGroup is null || core.Enums.All
                      (x => x.Name != function.ReturnType.OriginalGroup)))
            {
                varied        = true;
                newReturnType = new TypeSignatureBuilder(function.ReturnType).WithName
                                    (function.ReturnType.OriginalGroup)
                                .Build();
                newReturnType.OriginalName = newReturnType.Name;
            }

            variant = new FunctionSignatureBuilder(function).WithParameters(newParameters)
                      .WithName(paramsMod ? function.Name : function.Name + "G")
                      .WithReturnType(newReturnType)
                      .Build();
            return(varied);
        }
Exemplo n.º 6
0
        /// <inheritdoc/>
        public IEnumerable <FunctionSignature> CreateOverloads(FunctionSignature function)
        {
            var lastParameterType = function.Parameters.Last().Type;
            var newReturnType     = new TypeSignatureBuilder(lastParameterType)
                                    .WithIndirectionLevel(lastParameterType.IndirectionLevel - 1)
                                    .WithArrayDimensions(0)
                                    .Build();

            var newParameters = SkipLastExtension.SkipLast(function.Parameters, 1).ToList();
            var newName       = function.Name.Singularize(false);

            var functionBuilder = new FunctionSignatureBuilder(function)
                                  .WithName(newName)
                                  .WithReturnType(newReturnType);

            if (!newParameters.Any())
            {
                yield return(functionBuilder
                             .WithParameters(newParameters)
                             .Build());

                yield break;
            }

            // TODO: check if this has anything to do with CLS compliance
            var sizeParameterType = newParameters.Last().Type;

            if (!sizeParameterType.Name.StartsWith("int", StringComparison.OrdinalIgnoreCase) || sizeParameterType.IsPointer)
            {
                yield return(functionBuilder
                             .WithParameters(newParameters)
                             .Build());

                yield break;
            }

            newParameters = SkipLastExtension.SkipLast(newParameters, 1).ToList();
            yield return(functionBuilder
                         .WithParameters(newParameters)
                         .Build());
        }
Exemplo n.º 7
0
        /// <summary>
        /// Returns an enumerable containing the original function signature, as well as all overload variants
        /// generated by the overloaders.
        /// </summary>
        /// <param name="original">The original function signature.</param>
        /// <param name="core">The core project for this profile. May be used by some overloads.</param>
        /// <param name="overloaders">The overloaders to use in getting function overloads.</param>
        /// <returns>An enumerable containing the original function signature and all overloads.</returns>
        public static IEnumerable <Function> GetWithOverloads(Function original,
                                                              Project core,
                                                              params ISimpleReturnOverloader[] overloaders)
        {
            yield return(original);

            foreach (var overloader in overloaders)
            {
                if (overloader.TryGetReturnTypeVariant(original.ReturnType, out var varied, core))
                {
                    var ret = new FunctionSignatureBuilder(original)
                              .WithName(original.Name + ReturnOverloadSuffix)
                              .WithReturnType(varied)
                              .Build();
                    ret.Kind = SignatureKind.ReturnOverload;
                    yield return(ret);

                    break; // only overload the return type once
                }
            }
        }
Exemplo n.º 8
0
        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());
                    var ptrName      = (param.Name + "Ptr").Replace("@", "");

                    parameters.Add(ptrName);
                    sb.AppendLine(ind + $"fixed ({param.Type} {ptrName} = &{param.Name})");
                    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));
        }
Exemplo n.º 9
0
        public static void Implement(StringBuilder sb, Function function, Struct parent, int index, bool retDeref = false)
        {
            if (function.Attributes.IsBuildToolsIntrinsic(out var args) && args[0] == "$CPPRETFIXUP")
            {
                sb.AppendLine($"{function.ReturnType} silkDotNetReturnFixupResult;");
                sb.AppendLine("var pSilkDotNetReturnFixupResult = &silkDotNetReturnFixupResult;");
                var indIncremented = new TypeSignatureBuilder(function.ReturnType)
                                     .WithIndirectionLevel(function.ReturnType.IndirectionLevels + 1)
                                     .Build();
                var fixedUpFunction = new FunctionSignatureBuilder(function)
                                      .WithReturnType(indIncremented)
                                      .WithAttributes(Array.Empty <Attribute>())
                                      .WithParameters
                                      (
                    function.Parameters.Prepend
                    (
                        new Parameter
                {
                    Name = "pSilkDotNetReturnFixupResult",
                    Type = indIncremented
                }
                    ).ToArray()
                                      ).Build();
                Implement(sb, fixedUpFunction, parent, index, true);
                function.Attributes.RemoveAll(x => x.Name == "BuildToolsIntrinsic");
                return;
            }

            var ind = "";

            sb.AppendLine($"var @this = ({parent.Name}*) Unsafe.AsPointer(ref Unsafe.AsRef(in this));");

            var epilogue             = new List <Action>();
            var parameterInvocations = new List <(Type Type, string Parameter)>
            {
                (new Type {
                    Name = parent.Name, IndirectionLevels = 1
                }, "@this")
            };

            if (function.ReturnType.ToString() != "void")
            {
                sb.AppendLine($"{function.ReturnType} ret = default;");
            }

            for (var i = 0; i < function.Parameters.Count; i++)
            {
                var parameter = function.Parameters[i];
                if (parameter.Type.Name == "string")
                {
                    // assume ansi
                    if (parameter.Type.IsIn)
                    {
                        sb.AppendLine
                            ($"var {parameter.Name}PtrInit = (byte*) Marshal.StringToHGlobalAnsi({parameter.Name});");
                        sb.AppendLine($"var {parameter.Name}Ptr = &{parameter.Name}PtrInit;");
                        parameterInvocations.Add
                            ((new Type {
                            Name = "byte", IndirectionLevels = 2
                        }, $"{parameter.Name}Ptr"));
                        epilogue.Add(() => sb.AppendLine($"Marshal.FreeHGlobal((nint){parameter.Name}PtrInit);"));
                    }
                    else if (parameter.Type.IsByRef)
                    {
                        sb.AppendLine
                            ($"var {parameter.Name}PtrInit = (byte*) Marshal.StringToHGlobalAnsi({parameter.Name});");
                        sb.AppendLine($"var {parameter.Name}Ptr = &{parameter.Name}PtrInit;");
                        parameterInvocations.Add
                            ((new Type {
                            Name = "byte", IndirectionLevels = 2
                        }, $"{parameter.Name}Ptr"));
                        epilogue.Add
                        (
                            () =>
                        {
                            sb.AppendLine($"{parameter.Name} = Marshal.PtrToStringAnsi(*{parameter.Name}Ptr);");
                            sb.AppendLine($"Marshal.FreeHGlobal((nint){parameter.Name}PtrInit);");
                        }
                        );
                    }
                    else if (parameter.Type.IsOut)
                    {
                        throw new NotSupportedException
                              (
                                  "COM VTables don't support out strings due to lack of flow and count information."
                              );
                    }
                    else
                    {
                        sb.AppendLine
                            ($"var {parameter.Name}Ptr = (byte*) Marshal.StringToHGlobalAnsi({parameter.Name});");
                        parameterInvocations.Add
                            ((new Type {
                            Name = "byte", IndirectionLevels = 1
                        }, $"{parameter.Name}Ptr"));
                        epilogue.Add
                        (
                            () => { sb.AppendLine($"Marshal.FreeHGlobal((nint){parameter.Name}Ptr);"); }
                        );
                    }
                }
                else if (parameter.Type.IsIn || parameter.Type.IsOut || parameter.Type.IsByRef)
                {
                    var noRef = new TypeSignatureBuilder(parameter.Type)
                                .WithByRef(false)
                                .WithIsIn(false)
                                .WithIsOut(false)
                                .WithIndirectionLevel(parameter.Type.IndirectionLevels + 1)
                                .Build();
                    sb.AppendLine
                    (
                        ind + $"fixed ({noRef} {parameter.Name}Ptr = &{parameter.Name})"
                    );
                    sb.AppendLine(ind + "{");
                    parameterInvocations.Add((noRef, $"{parameter.Name}Ptr"));
                    ind += "    ";
                    epilogue.Add
                    (
                        () =>
                    {
                        ind = ind.Substring(0, ind.Length - 4);
                        sb.AppendLine(ind + "}");
                    }
                    );
                }
                else
                {
                    parameterInvocations.Add((parameter.Type, parameter.Name));
                }
            }

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

            var conv = function.Convention switch
            {
                CallingConvention.Winapi => throw new NotImplementedException(),
                      CallingConvention.Cdecl => "Cdecl",
                      CallingConvention.StdCall => "Stdcall",
                      CallingConvention.ThisCall => "Thiscall",
                      CallingConvention.FastCall => "Fastcall",
                      _ => "Cdecl"
            };

            var fnPtrSig = string.Join(", ", parameterInvocations.Select(x => x.Type.ToString()));

            if (!string.IsNullOrWhiteSpace(fnPtrSig))
            {
                fnPtrSig += ", ";
            }

            fnPtrSig += function.ReturnType;
            sb.Append($"((delegate* unmanaged[{conv}]<{fnPtrSig}>)");
            sb.Append($"LpVtbl[{index}])");
            sb.AppendLine("(" + string.Join(", ", parameterInvocations.Select(x => x.Parameter)) + ");");

            for (var i = epilogue.Count - 1; i >= 0; i--)
            {
                epilogue[i]();
            }

            if (retDeref)
            {
                sb.AppendLine("return *ret;");
            }
            else if (function.ReturnType.ToString() != "void")
            {
                sb.AppendLine("return ret;");
            }
        }
    }
Exemplo n.º 10
0
        /// <inheritdoc/>
        public IEnumerable <ImplementedFunction> CreateOverloads(Function function)
        {
            if (!IsApplicable(function))
            {
                yield break;
            }

            var lastParameterType = function.Parameters.Last().Type;
            var newReturnType     = new TypeSignatureBuilder(lastParameterType)
                                    .WithIndirectionLevel(lastParameterType.IndirectionLevels - 1)
                                    .WithArrayDimensions(0)
                                    .Build();

            var newParameters = SkipLastExtension.SkipLast(function.Parameters, 1).ToList();
            var newName       = function.Name.Singularize(false);

            var functionBuilder = new FunctionSignatureBuilder(function)
                                  .WithName(newName)
                                  .WithReturnType(newReturnType);

            var sb        = new StringBuilder();
            var strParams = newParameters.Select(Convert).Concat(new[] { "&ret" });

            sb.AppendLine("// ReturnTypeOverloader");
            sb.AppendLine($"{newReturnType} ret = default;");
            sb.Append($"{function.Name}(");
            sb.Append(string.Join(", ", strParams));
            sb.AppendLine(");");
            sb.AppendLine("return ret;");

            if (!newParameters.Any())
            {
                yield return(new ImplementedFunction(functionBuilder
                                                     .WithParameters(newParameters)
                                                     .Build(), sb, true));

                yield break;
            }

            var sizeParameterType = newParameters.Last().Type;

            if ((sizeParameterType.Name != "int" && sizeParameterType.Name != "uint") || sizeParameterType.IsPointer)
            {
                yield return(new ImplementedFunction(functionBuilder
                                                     .WithParameters(newParameters)
                                                     .Build(), sb, true));

                yield break;
            }

            var n = newParameters.Last().Name;

            sb.Insert(0,
                      $"const {(sizeParameterType.Name == "uint" ? "uint " : "int ")}{(Utilities.CSharpKeywords.Contains(n) ? "@" : "")}{n} = 1;\n"
                      );
            newParameters = SkipLastExtension.SkipLast(newParameters, 1).ToList();
            yield return(new ImplementedFunction
                         (
                             functionBuilder
                             .WithParameters(newParameters)
                             .Build(), sb, true
                         ));

            string Convert(Parameter x)
            {
                var pre = x.Type.IsOut ? "out " : string.Empty;

                return(pre + (Utilities.CSharpKeywords.Contains(x.Name) ? $"@{x.Name}" : x.Name));
            }
        }
Exemplo n.º 11
0
        public bool TryCreateVariant(Function function, out Function variant, Project core)
        {
            var varied     = false;
            var parameters = new List <Parameter>();

            parameters.AddRange(function.Parameters);
            var genericParams = new List <GenericTypeParameter>();

            for (var i = 0; i < parameters.Count; i++)
            {
                var param    = parameters[i];
                var typeName = param.Type.Name == "void" ? $"T{genericParams.Count}" : param.Type.Name;
                if (param.Type.Name == "void")
                {
                    genericParams.Add
                    (
                        new GenericTypeParameter
                    {
                        Name = $"T{genericParams.Count}", Constraints = new List <string> {
                            "unmanaged"
                        }
                    }
                    );
                }

                if (param.Type.IndirectionLevels == 1 && (param.Count?.IsMultiple ?? true))
                {
                    varied        = true;
                    parameters[i] = new ParameterSignatureBuilder(param).WithType
                                    (
                        new Type
                    {
                        GenericTypes = new List <Type>
                        {
                            new TypeSignatureBuilder(param.Type).WithName(typeName).WithIndirectionLevel(0).Build()
                        },
                        Name = "Span"
                    }
                                    )
                                    .Build();
                    continue;
                }

                if (param.Type.IsPointer && !(param.Count?.IsMultiple ?? true))
                {
                    varied        = true;
                    parameters[i] = new ParameterSignatureBuilder(param).WithType
                                    (
                        new TypeSignatureBuilder(param.Type)
                        .WithIndirectionLevel(param.Type.IndirectionLevels - 1)
                        .WithName(typeName)
                        .WithByRef(param.Flow != FlowDirection.Out)
                        .WithIsOut(param.Flow == FlowDirection.Out)
                        .Build()
                                    )
                                    .Build();
                }
            }

            if (varied)
            {
                variant = new FunctionSignatureBuilder(function).WithParameters
                              (parameters)
                          .WithGenericTypeParameters(genericParams)
                          .Build();
                return(true);
            }

            variant = null;
            return(false);
        }
Exemplo n.º 12
0
        public IEnumerable <ImplementedFunction> CreateOverloads(Function function)
        {
            var returnTypeChanged = false;
            var parameterChanged  = false;
            var sb = new StringBuilder();

            sb.AppendLine("// SpanOverloader");
            var parameters = function.Parameters.ToList();
            var fun        = new FunctionSignatureBuilder(function);
            // TODO we need a length for span returns, so I've disabled them for now
            //if (function.ReturnType.IndirectionLevels == 1 && function.ReturnType.Name != "void")
            //{
            //    fun.WithReturnType
            //    (
            //        new Type
            //        {
            //            Name = "Span", OriginalName = "Span",
            //            GenericTypes = new List<Type> {new Type {Name = function.ReturnType.Name}}
            //        }
            //    );
            //    returnTypeChanged = true;
            //}

            var ind = string.Empty;

            for (var i = 0; i < function.Parameters.Count; i++)
            {
                var param = function.Parameters[i];
                if (param.Type.IndirectionLevels == 1 && param.Type.Name != "void" && !param.Type.IsOut && !param.Type.IsIn && !param.Type.IsByRef)
                {
                    parameterChanged = true;
                    parameters[i]    = new ParameterSignatureBuilder(param).WithName($"{param.Name}Span")
                                       .WithType
                                       (
                        new Type
                    {
                        Name         = "Span", OriginalName = "Span",
                        GenericTypes = new List <Type>
                        {
                            new Type {
                                Name = param.Type.Name, OriginalName = param.Type.OriginalName
                            }
                        }
                    }
                                       )
                                       .Build();
                    sb.AppendLine($"{ind}fixed ({param.Type} {param.Name} = {param.Name}Span)");
                    sb.AppendLine($"{ind}{{");
                    ind += "    ";
                }
                else
                {
                    parameters[i] = param;
                }
            }

            if (returnTypeChanged)
            {
                sb.Append($"{ind}return (Span<{function.ReturnType.Name}>) ");
            }
            else if (function.ReturnType.ToString() != "void")
            {
                sb.Append($"{ind}return ");
            }
            else
            {
                sb.Append(ind);
            }

            sb.Append($"{function.Name}(");
            sb.Append(string.Join(", ", function.Parameters.Select(x => GetPrefix(x.Type) + Format(x.Name))));
            sb.AppendLine(");");

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

            fun.WithParameters(parameters);

            if (returnTypeChanged && !parameterChanged)
            {
                yield return(new ImplementedFunction(fun.WithName($"{function.Name}AsSpan").Build(), sb, true));
            }
            else if (parameterChanged)
            {
                yield return(new ImplementedFunction(fun.Build(), sb, true));
            }

            string GetPrefix(Type t)
            {
                return(t.IsOut ? "out " : t.IsByRef ? "ref " : string.Empty);
            }

            string Format(string n)
            {
                if (Utilities.CSharpKeywords.Contains(n))
                {
                    return($"@{n}");
                }

                return(n);
            }
        }
Exemplo n.º 13
0
        /// <summary>
        /// Returns an enumerable containing the original function signature, as well as all overload variants
        /// generated by the
        /// </summary>
        /// <param name="original">The original function signature.</param>
        /// <param name="core">The core project for this profile. May be used by some overloads.</param>
        /// <param name="overloaders">The overloaders to use in getting function overloads.</param>
        /// <returns>An enumerable containing the original function signature and all overloads.</returns>
        public static IEnumerable <Function> GetWithOverloads
        (
            Function original,
            Project core,
            params ISimpleParameterOverloader[] overloaders
        )
        {
            if (original.Parameters.Count == 0)
            {
                yield return(original);

                yield break;
            }

            var parameters = original.Parameters.Select(x => new List <Parameter> {
                x
            }).ToList();

            foreach (var parameter in parameters)
            {
                foreach (var overloader in overloaders)
                {
                    if (overloader.TryGetParameterVariant(parameter[0], out var variant, core))
                    {
                        parameter.Add(variant);
                    }
                }
            }

            foreach (var combination in Combinations(parameters))
            {
                var numGenericTypeParams = 0;
                var ret = new FunctionSignatureBuilder(original).WithParameters
                          (
                    combination.Select
                    (
                        x => !x.Type.IsGenericTypeParameterReference
                                    ? x
                                    : new ParameterSignatureBuilder(x).WithType
                        (
                            new TypeSignatureBuilder(x.Type).WithName("T" + numGenericTypeParams++)
                            .Build()
                        )
                        .Build()
                    )
                    .ToList()
                          )
                          .WithGenericTypeParameters
                          (
                    Enumerable.Range(0, numGenericTypeParams)
                    .Select
                    (
                        x => new GenericTypeParameter
                {
                    Name = "T" + x, Constraints = new List <string> {
                        "unmanaged"
                    }
                }
                    )
                    .ToList()
                          )
                          .Build();
                ret.Kind = original.Kind == SignatureKind.Normal ? ret.Parameters.SequenceEqual
                               (original.Parameters)
                    ? SignatureKind.Normal
                    : SignatureKind.SimpleOverload : original.Kind;
                yield return(ret);
            }
        }
Exemplo n.º 14
0
        /// <inheritdoc/>
        public IEnumerable <Overload> CreateOverloads(Function function)
        {
            if (!IsApplicable(function))
            {
                yield break;
            }

            var lastParameterType = function.Parameters.Last().Type;
            var newReturnType     = new TypeSignatureBuilder(lastParameterType)
                                    .WithIndirectionLevel(lastParameterType.IndirectionLevels - 1)
                                    .WithArrayDimensions(0)
                                    .Build();

            var newParameters = SkipLastExtension.SkipLast(function.Parameters, 1).ToList();
            var newName       = function.Name.Singularize(false);

            var functionBuilder = new FunctionSignatureBuilder(function)
                                  .WithName(newName)
                                  .WithReturnType(newReturnType);

            var sb        = new StringBuilder();
            var strParams = newParameters.Select(x => Utilities.CSharpKeywords.Contains(x.Name) ? "@" + x.Name : x.Name)
                            .Concat(new[] { "&ret" });

            sb.AppendLine("// ReturnTypeOverloader");
            sb.AppendLine(newReturnType + " ret = default;");
            sb.Append(function.Name + "(");
            sb.Append(string.Join(", ", strParams));
            sb.AppendLine(");");
            sb.AppendLine("return ret;");

            if (!newParameters.Any())
            {
                yield return(new Overload(functionBuilder
                                          .WithParameters(newParameters)
                                          .Build(), sb, true));

                yield break;
            }

            var sizeParameterType = newParameters.Last().Type;

            if ((sizeParameterType.Name != "int" && sizeParameterType.Name != "uint") || sizeParameterType.IsPointer)
            {
                yield return(new Overload(functionBuilder
                                          .WithParameters(newParameters)
                                          .Build(), sb, true));

                yield break;
            }

            var n = newParameters.Last().Name;

            sb.Insert(0, "const " + (sizeParameterType.Name == "uint" ? "uint " : "int ") +
                      (Utilities.CSharpKeywords.Contains(n) ? "@" : "") + n + " = 1;\n");
            newParameters = SkipLastExtension.SkipLast(newParameters, 1).ToList();
            yield return(new Overload
                         (
                             functionBuilder
                             .WithParameters(newParameters)
                             .Build(), sb, true
                         ));
        }
Exemplo n.º 15
0
        /// <summary>
        /// Returns an enumerable containing the original function signature, as well as all overload variants
        /// generated by the
        /// </summary>
        /// <param name="original">The original function signature.</param>
        /// <param name="core">The core project for this profile. May be used by some overloads.</param>
        /// <param name="overloaders">The overloaders to use in getting function overloads.</param>
        /// <returns>An enumerable containing the original function signature and all overloads.</returns>
        public static IEnumerable <Function> GetWithOverloads
        (
            Function original,
            Project core,
            IEnumerable <ISimpleParameterOverloader> overloaders
        )
        {
            if (original.Parameters.Count == 0)
            {
                yield return(original);

                yield break;
            }

            var parameters = original.Parameters.Select(x => new List <Parameter> {
                x
            }).ToList();

            foreach (var parameter in parameters)
            {
                foreach (var overloader in overloaders)
                {
                    if (overloader.TryGetParameterVariant(parameter[0], out var variant, core))
                    {
                        parameter.Add(variant);
                    }
                }
            }

            foreach (var combination in Combinations(parameters))
            {
                var numGenericTypeParams = 0;
                var ret = new FunctionSignatureBuilder(original).WithParameters
                          (
                    combination.Select
                    (
                        x => !x.Type.IsGenericTypeParameterReference
                                    ? x
                                    : new ParameterSignatureBuilder(x).WithType
                        (
                            new TypeSignatureBuilder(x.Type).WithName("T" + numGenericTypeParams++)
                            .Build()
                        )
                        .Build()
                    )
                    .ToList()
                          )
                          .WithGenericTypeParameters
                          (
                    Enumerable.Range(0, numGenericTypeParams)
                    .Select
                    (
                        x => new GenericTypeParameter
                {
                    Name = "T" + x, Constraints = new List <string> {
                        "unmanaged"
                    }
                }
                    )
                    .ToList()
                          )
                          .Build();
                ret.Kind = original.Kind == SignatureKind.Normal ? ret.Parameters.SequenceEqual
                               (original.Parameters)
                    ? SignatureKind.Normal
                    : SignatureKind.SimpleOverload : original.Kind;

                if (ret.NativeName.ConstitutesVulkanOutOverload() &&
                    (ret.Parameters.LastOrDefault()?.Type.IsOut ?? false))
                {
                    var last      = ret.Parameters.Last();
                    var outStruct = core.Structs.FirstOrDefault(x => x.Name == last.Type.Name);
                    var outSType  = outStruct?.Fields.FirstOrDefault();
                    if (outSType is not null && outSType.Name == "SType" && outSType.DefaultAssignment is not null)
                    {
                        ret.Attributes.Add
                        (
                            new()
                        {
                            Name      = "Inject",
                            Arguments = new()
                            {
                                "SilkTouchStage.Begin",
                                $"\"{last.Name} = new({outSType.DefaultAssignment});\""
                            }
                        }
                        );
                    }
                }

                yield return(ret);
            }
        }