Пример #1
0
        /// <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));
        }
Пример #2
0
        /// <summary>
        /// Returns a signature that represents an instantiation of the generic type represented
        /// by this signature.
        /// </summary>
        /// <param name="typeArguments">The type arguments of the instantiation.</param>
        /// <returns>A <see cref="TypeSignature"/> representing the instantiation of the generic
        /// type whose definition is represented by this signature and whose type arguments are
        /// given.</returns>
        /// <exception cref="ArgumentException"><paramref name="typeArguments"/> is empty.</exception>
        /// <exception cref="InvalidOperationException">This signature does not represent a class or value
        /// type.</exception>
        public TypeSignature makeGenericInstance(ReadOnlySpan <TypeSignature> typeArguments)
        {
            if (typeArguments.Length == 0)
            {
                throw new ArgumentException("Type arguments must not be empty.", nameof(typeArguments));
            }

            byte firstByte = getFirstByte();

            if (firstByte != (byte)SignatureTypeKind.Class && firstByte != (byte)SignatureTypeKind.ValueType)
            {
                throw new InvalidOperationException("Generic instantiation is only allowed for class and valuetype signatures.");
            }

            var builder = TypeSignatureBuilder.getInstance();

            try {
                builder.appendByte((byte)SignatureTypeCode.GenericTypeInstance);
                builder.appendSignature(this);

                builder.appendCompressedUnsignedInt(typeArguments.Length);
                for (int i = 0; i < typeArguments.Length; i++)
                {
                    builder.appendSignature(typeArguments[i]);
                }

                return(builder.makeSignature());
            }
            finally {
                builder.clear();
            }
        }
Пример #3
0
        private TypeSignature _addTypeCodePrefix(SignatureTypeCode code)
        {
            if (isByRef())
            {
                throw new InvalidOperationException("Cannot use a by-ref type as the element type of an array, pointer or by-ref type.");
            }

            int compactLength = (int)(m_compact >> 56);

            if (compactLength < 7)
            {
                return(new TypeSignature((long)(compactLength + 1) << 56 | m_compact << 8 | (byte)code));
            }

            var builder = TypeSignatureBuilder.getInstance();

            try {
                builder.appendByte((byte)code);
                builder.appendSignature(this);
                return(builder.makeSignature());
            }
            finally {
                builder.clear();
            }
        }
Пример #4
0
        /// <summary>
        /// Returns a signature that represents an instantiation of the generic type represented
        /// by this signature with its own type parameters as type arguments.
        /// </summary>
        /// <param name="typeParamCount">The number of type parameters in the generic type.</param>
        /// <returns>A <see cref="TypeSignature"/> representing the instantiation of the generic
        /// type whose definition is represented by this signature and whose type arguments are
        /// the generic type's own type parameters.</returns>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="typeParamCount"/> is zero or negative.</exception>
        /// <exception cref="InvalidOperationException">This signature does not represent a class or value
        /// type.</exception>
        public TypeSignature makeGenericSelfInstance(int typeParamCount)
        {
            if (typeParamCount <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(typeParamCount));
            }

            byte firstByte = getFirstByte();

            if (firstByte != (byte)SignatureTypeKind.Class && firstByte != (byte)SignatureTypeKind.ValueType)
            {
                throw new InvalidOperationException("Generic instantiation is only allowed for class or valuetype signatures.");
            }

            var builder = TypeSignatureBuilder.getInstance();

            try {
                builder.appendByte((byte)SignatureTypeCode.GenericTypeInstance);
                builder.appendSignature(this);

                builder.appendCompressedUnsignedInt(typeParamCount);
                for (int i = 0; i < typeParamCount; i++)
                {
                    builder.appendByte((byte)SignatureTypeCode.GenericTypeParameter);
                    builder.appendCompressedUnsignedInt(i);
                }

                return(builder.makeSignature());
            }
            finally {
                builder.clear();
            }
        }
Пример #5
0
        /// <inheritdoc/>
        public TypeSignature Map(TypeSignature input)
        {
            if (_typemap.TryGetValue(input, out var result))
            {
                return(result);
            }

            if (input.IsArray || input.IsPointer)
            {
                var baseType = new TypeSignatureBuilder(input)
                               .WithArrayDimensions(0)
                               .WithIndirectionLevel(0)
                               .Build();

                if (_typemap.TryGetValue(baseType, out var baseMappedType))
                {
                    var newMappedType = new TypeSignatureBuilder(baseMappedType)
                                        .WithArrayDimensions(baseMappedType.ArrayDimensions + input.ArrayDimensions)
                                        .WithIndirectionLevel(baseMappedType.IndirectionLevel + input.IndirectionLevel)
                                        .Build();

                    return(newMappedType);
                }
            }

            if (!_allowPassthrough)
            {
                throw new KeyNotFoundException("Could not find a valid mapping for the given type.");
            }

            return(input);
        }
Пример #6
0
        public bool TryGetParameterVariant(Parameter parameter, out Parameter variant, Project core)
        {
            if (parameter.Type.OriginalGroup is null || core.Enums.All
                    (x => x.Name != parameter.Type.OriginalGroup) /* || (parameter.Type.OriginalName != "GLenum" &&
                                                                   *   parameter.Type.OriginalName != "CLenum")*/)
            {
                variant = null;
                return(false);
            }

            var t =
                new TypeSignatureBuilder(parameter.Type).WithName
                    (parameter.Type.OriginalGroup)
                .Build();

            t.OriginalName = t.Name; // stop GLenum mapping
            variant        =
                new ParameterSignatureBuilder(parameter).WithType
                (
                    t
                )
                .Build()
            ;
            return(true);
        }
        /// <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
                );
        }
Пример #8
0
        /// <inheritdoc/>
        public IEnumerable <FunctionSignature> CreateOverloads(FunctionSignature function)
        {
            var newReturnType = new TypeSignatureBuilder(function.ReturnType)
                                .WithIndirectionLevel(0)
                                .WithName(nameof(IntPtr))
                                .Build();

            yield return(new FunctionSignatureBuilder(function)
                         .WithReturnType(newReturnType)
                         .Build());
        }
        /// <inheritdoc/>
        public IEnumerable <FunctionSignature> CreateOverloads(FunctionSignature function)
        {
            var baseParameters = function.Parameters;

            var staticCountPermutation = new List <ParameterSignature>(baseParameters);

            for (int i = 0; i < baseParameters.Count; ++i)
            {
                var baseParameter = baseParameters[i];
                var baseType      = baseParameter.Type;

                if (!HasStaticCount(baseParameter))
                {
                    continue;
                }

                // ReSharper disable once PossibleNullReferenceException
                var count = baseParameter.Count.Count;

                if (count > 1)
                {
                    // TODO: Support higher-ranked types
                    continue;
                }

                if (!baseType.IsPointer || baseType.IndirectionLevel > 1)
                {
                    continue;
                }

                var refTypeBuilder = new TypeSignatureBuilder(baseType)
                                     .WithIndirectionLevel(0)
                                     .WithByRef(true);

                if (baseParameter.Flow == FlowDirection.Out)
                {
                    refTypeBuilder = refTypeBuilder.WithIsOut(true);
                }

                var refType = refTypeBuilder.Build();

                var refParameter = new ParameterSignatureBuilder(baseParameter)
                                   .WithType(refType)
                                   .Build();

                staticCountPermutation[i] = refParameter;
            }

            yield return(new FunctionSignatureBuilder(function)
                         .WithParameters(staticCountPermutation)
                         .Build());
        }
Пример #10
0
        /// <inheritdoc/>
        public bool HasMapping(TypeSignature input)
        {
            if (!input.IsArray && !input.IsPointer)
            {
                return(_typemap.ContainsKey(input));
            }

            var baseType = new TypeSignatureBuilder(input)
                           .WithArrayDimensions(0)
                           .WithIndirectionLevel(0)
                           .Build();

            return(_typemap.TryGetValue(baseType, out _) || _typemap.ContainsKey(input));
        }
Пример #11
0
        public bool TryCreateVariant(Type returnType, out Type variant, Project core)
        {
            if (returnType.OriginalGroup is null || core.Enums.All
                    (x => x.Name != returnType.OriginalGroup) || returnType.OriginalName != "GLenum" ||
                returnType.OriginalName != "CLenum")
            {
                variant = null;
                return(false);
            }

            variant = new TypeSignatureBuilder(returnType).WithName
                          (returnType.OriginalGroup)
                      .Build();
            return(true);
        }
Пример #12
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);
        }
Пример #13
0
        public bool TryGetParameterVariant(Parameter parameter, out Parameter variant, Project core)
        {
            Struct s;

            if (parameter.Type.OriginalClass is null || (s = core.Structs.FirstOrDefault
                                                                 (x => x.NativeName == parameter.Type.OriginalClass)) is null)
            {
                variant = null;
                return(false);
            }

            var t = new TypeSignatureBuilder(parameter.Type).WithName(s.Name).Build();

            t.OriginalName = t.Name; // stop GLenum mapping
            variant        = new ParameterSignatureBuilder(parameter).WithType(t).Build();
            return(true);
        }
Пример #14
0
        private static TypeSignature _forClassOrValueType(EntityHandle handle, bool isValueType)
        {
            if (handle.IsNil)
            {
                throw new ArgumentException("Handle for a class or value type must not be null.", nameof(handle));
            }

            var builder = TypeSignatureBuilder.getInstance();

            try {
                builder.appendByte((byte)(isValueType ? SignatureTypeKind.ValueType : SignatureTypeKind.Class));
                builder.appendCompressedUnsignedInt(CodedIndex.TypeDefOrRefOrSpec(handle));
                return(builder.makeSignature());
            }
            finally {
                builder.clear();
            }
        }
Пример #15
0
        /// <summary>
        /// Returns a signature representing a general array type whose element type is represented
        /// by this signature.
        /// </summary>
        ///
        /// <param name="rank">The number of array dimensions.</param>
        /// <param name="lengths">A span containing the lengths for each dimension. The length of
        /// this argument must not be greater than <paramref name="rank"/>.</param>
        /// <param name="lowerBounds">A span containing the lower bounds for each dimension. The length of
        /// this argument must not be greater than <paramref name="rank"/>.</param>
        ///
        /// <returns>A <see cref="TypeSignature"/> representing the array type whose element type
        /// is represented by this signature and whose rank, lengths and lower bounds are given.</returns>
        ///
        /// <exception cref="InvalidOperationException">This signature represents a by-ref type.</exception>
        /// <exception cref="ArgumentOutOfRangeException">The rank is negative or zero, or the length
        /// of <paramref name="lengths"/> or <paramref name="lowerBounds"/> is greater than the rank.</exception>
        ///
        /// <remarks>
        /// This method creates a signature for a general array. To create a signature for a single-dimensional
        /// zero-based array, use <see cref="makeSZArray"/>. In particular, setting <paramref name="rank"/>
        /// to 1 and <paramref name="lengths"/> and <paramref name="lowerBounds"/> to empty spans does not
        /// create the same signature as <see cref="makeSZArray"/>.
        /// </remarks>
        public TypeSignature makeArray(
            int rank, ReadOnlySpan <int> lengths = default, ReadOnlySpan <int> lowerBounds = default)
        {
            if (rank <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(rank));
            }

            if (lengths.Length > rank || lowerBounds.Length > rank)
            {
                throw new ArgumentOutOfRangeException("Number of lengths or lower bounds is greater than the array rank.");
            }

            if (isByRef())
            {
                throw new InvalidOperationException("Cannot use a by-ref type as the element type of an array, pointer or by-ref type.");
            }

            var builder = TypeSignatureBuilder.getInstance();

            try {
                builder.appendByte((byte)SignatureTypeCode.Array);
                builder.appendSignature(this);

                builder.appendCompressedUnsignedInt(rank);

                builder.appendCompressedUnsignedInt(lengths.Length);
                for (int i = 0; i < lengths.Length; i++)
                {
                    builder.appendCompressedUnsignedInt(lengths[i]);
                }

                builder.appendCompressedUnsignedInt(lowerBounds.Length);
                for (int i = 0; i < lowerBounds.Length; i++)
                {
                    builder.appendCompressedSignedInt(lowerBounds[i]);
                }

                return(builder.makeSignature());
            }
            finally {
                builder.clear();
            }
        }
Пример #16
0
        /// <inheritdoc/>
        public ParameterSignature Map(ParameterSignature input)
        {
            var newType = _glTypeMapper.Map(input.Type);

            if (newType.Name.Equals("string", StringComparison.OrdinalIgnoreCase))
            {
                if (input.Flow == FlowDirection.Out)
                {
                    newType = new TypeSignatureBuilder(newType)
                              .WithByRef(true)
                              .WithIsOut(true)
                              .Build();
                }
            }

            return(new ParameterSignatureBuilder(input)
                   .WithType(newType)
                   .Build());
        }
Пример #17
0
        /// <inheritdoc/>
        public IEnumerable <ImplementedFunction> CreateOverloads(Function function)
        {
            if (!function.ReturnType.IsIntPtr())
            {
                yield break;
            }

            var newReturnType = new TypeSignatureBuilder(function.ReturnType)
                                .WithIndirectionLevel(1)
                                .WithName("void")
                                .Build();

            yield return(Cast(
                             new FunctionSignatureBuilder(function)
                             .WithReturnType(newReturnType)
                             .WithName($"{function.Name}AsPointer")
                             .Build(),
                             function));
        }
        /// <inheritdoc/>
        public IEnumerable <(FunctionSignature, StringBuilder)> CreateOverloads(FunctionSignature function)
        {
            if (!function.ReturnType.IsVoidPointer())
            {
                yield break;
            }

            var newReturnType = new TypeSignatureBuilder(function.ReturnType)
                                .WithIndirectionLevel(0)
                                .WithName(nameof(IntPtr))
                                .Build();

            yield return(Cast(
                             new FunctionSignatureBuilder(function)
                             .WithReturnType(newReturnType)
                             .WithName(function.Name + "Ptr")
                             .Build(),
                             function));
        }
Пример #19
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());
        }
        /// <inheritdoc/>
        public bool TryGetFunctionVariant(Function function, out ImplementedFunction overload, Project core)
        {
            if (!IsApplicable(function))
            {
                overload = null;
                return(false);
            }

            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});");

            overload = new ImplementedFunction(new FunctionSignatureBuilder(function)
                                               .WithName(newName)
                                               .WithParameters(newParameters)
                                               .Build(), sb, function, true);
            return(true);
        }
Пример #21
0
        /// <summary>
        /// Returns a signature representing the type parameter of a generic method at the
        /// given position.
        /// </summary>
        /// <param name="position">The zero-based position of the type parameter.</param>
        /// <returns>A <see cref="TypeSignature"/> representing the type parameter of a generic method at the
        /// given position.</returns>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="position"/> is zero or negative.</exception>
        public static TypeSignature forGenericMethodParam(int position)
        {
            if (position < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(position));
            }

            if (position < 127)
            {
                return(new TypeSignature(
                           (2L << 56) | (long)(position << 8) | (byte)SignatureTypeCode.GenericMethodParameter));
            }

            var builder = TypeSignatureBuilder.getInstance();

            try {
                builder.appendByte((byte)SignatureTypeCode.GenericMethodParameter);
                builder.appendCompressedUnsignedInt(position);
                return(builder.makeSignature());
            }
            finally {
                builder.clear();
            }
        }
Пример #22
0
        /// <inheritdoc/>
        public IEnumerable <FunctionSignature> CreateOverloads(FunctionSignature function)
        {
            var arrayParameter     = function.Parameters.Last();
            var arrayParameterType = arrayParameter.Type;

            var newName       = function.Name.Singularize(false);
            var newParameters = SkipLastExtension.SkipLast(new List <ParameterSignature>(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);

            yield return(new FunctionSignatureBuilder(function)
                         .WithName(newName)
                         .WithParameters(newParameters)
                         .Build());
        }
Пример #23
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));
        }
Пример #24
0
        /// <inheritdoc/>
        public IEnumerable <FunctionSignature> CreateOverloads(FunctionSignature function)
        {
            var baseParameters = function.Parameters;

            var newIntPtrParameters         = new List <ParameterSignature>(baseParameters);
            var newGenericArray1DParameters = new List <ParameterSignature>(baseParameters);
            var newGenericArray2DParameters = new List <ParameterSignature>(baseParameters);
            var newGenericArray3DParameters = new List <ParameterSignature>(baseParameters);
            var newGenericRefParameters     = new List <ParameterSignature>(baseParameters);

            var newGenericTypeParameters = new List <GenericTypeParameterSignature>();

            for (int i = 0; i < baseParameters.Count; ++i)
            {
                var parameter = baseParameters[i];
                if (!parameter.Type.IsVoidPointer())
                {
                    continue;
                }

                string genericTypeParameterName;
                if (baseParameters.Count(p => p.Type.IsVoidPointer()) > 1)
                {
                    genericTypeParameterName = $"T{newGenericTypeParameters.Count + 1}";
                }
                else
                {
                    genericTypeParameterName = "T";
                }

                var genericTypeParameter = new GenericTypeParameterSignature(genericTypeParameterName);

                newGenericTypeParameters.Add(genericTypeParameter);

                var newIntPtrParameterType = new TypeSignatureBuilder(parameter.Type)
                                             .WithIndirectionLevel(0)
                                             .WithName(nameof(IntPtr))
                                             .Build();

                // TODO: Simplify and generalize this
                var newGenericArray1DParameterType = new TypeSignatureBuilder(parameter.Type)
                                                     .WithIndirectionLevel(0)
                                                     .WithArrayDimensions(1)
                                                     .WithName(genericTypeParameterName)
                                                     .Build();

                var newGenericArray2DParameterType = new TypeSignatureBuilder(parameter.Type)
                                                     .WithIndirectionLevel(0)
                                                     .WithArrayDimensions(2)
                                                     .WithName(genericTypeParameterName)
                                                     .Build();

                var newGenericArray3DParameterType = new TypeSignatureBuilder(parameter.Type)
                                                     .WithIndirectionLevel(0)
                                                     .WithArrayDimensions(3)
                                                     .WithName(genericTypeParameterName)
                                                     .Build();

                var newGenericRefParameterType = new TypeSignatureBuilder(parameter.Type)
                                                 .WithIndirectionLevel(0)
                                                 .WithName(genericTypeParameterName)
                                                 .WithByRef(true)
                                                 .Build();

                newIntPtrParameters[i] = new ParameterSignatureBuilder(parameter)
                                         .WithType(newIntPtrParameterType)
                                         .Build();

                newGenericArray1DParameters[i] = new ParameterSignatureBuilder(parameter)
                                                 .WithType(newGenericArray1DParameterType)
                                                 .Build();

                newGenericArray2DParameters[i] = new ParameterSignatureBuilder(parameter)
                                                 .WithType(newGenericArray2DParameterType)
                                                 .Build();

                newGenericArray3DParameters[i] = new ParameterSignatureBuilder(parameter)
                                                 .WithType(newGenericArray3DParameterType)
                                                 .Build();

                newGenericRefParameters[i] = new ParameterSignatureBuilder(parameter)
                                             .WithType(newGenericRefParameterType)
                                             .Build();
            }

            yield return(new FunctionSignatureBuilder(function)
                         .WithParameters(newIntPtrParameters)
                         .Build());

            yield return(new FunctionSignatureBuilder(function)
                         .WithParameters(newGenericArray1DParameters)
                         .WithGenericTypeParameters(newGenericTypeParameters)
                         .Build());

            yield return(new FunctionSignatureBuilder(function)
                         .WithParameters(newGenericArray2DParameters)
                         .WithGenericTypeParameters(newGenericTypeParameters)
                         .Build());

            yield return(new FunctionSignatureBuilder(function)
                         .WithParameters(newGenericArray3DParameters)
                         .WithGenericTypeParameters(newGenericTypeParameters)
                         .Build());

            yield return(new FunctionSignatureBuilder(function)
                         .WithParameters(newGenericRefParameters)
                         .WithGenericTypeParameters(newGenericTypeParameters)
                         .Build());
        }
        /// <inheritdoc/>
        public IEnumerable <(FunctionSignature, StringBuilder)> CreateOverloads(FunctionSignature function)
        {
            if (!function.Parameters.Any(p => p.Type.IsVoidPointer()))
            {
                yield break;
            }

            var baseParameters = function.Parameters;

            var newIntPtrParameters         = new List <ParameterSignature>(baseParameters);
            var newGenericArray1DParameters = new List <ParameterSignature>(baseParameters);
            var newGenericArray2DParameters = new List <ParameterSignature>(baseParameters);
            var newGenericArray3DParameters = new List <ParameterSignature>(baseParameters);

            var newGenericTypeParameters = new List <GenericTypeParameterSignature>();

            for (var i = 0; i < baseParameters.Count; ++i)
            {
                var parameter = baseParameters[i];
                if (!parameter.Type.IsVoidPointer())
                {
                    continue;
                }

                var genericTypeParameterName = baseParameters.Count(p => p.Type.IsVoidPointer()) > 1
                    ? $"T{newGenericTypeParameters.Count + 1}" : "T";

                var genericTypeParameter = new GenericTypeParameterSignature(
                    genericTypeParameterName,
                    new[] { "unmanaged" });

                newGenericTypeParameters.Add(genericTypeParameter);

                var newIntPtrParameterType = new TypeSignatureBuilder(parameter.Type)
                                             .WithIndirectionLevel(0)
                                             .WithName(nameof(IntPtr))
                                             .Build();

                // TODO: Simplify and generalize this
                var newGenericArray1DParameterType = new TypeSignatureBuilder(parameter.Type)
                                                     .WithIndirectionLevel(0)
                                                     .WithArrayDimensions(1)
                                                     .WithName(genericTypeParameterName)
                                                     .Build();

                var newGenericArray2DParameterType = new TypeSignatureBuilder(parameter.Type)
                                                     .WithIndirectionLevel(0)
                                                     .WithArrayDimensions(2)
                                                     .WithName(genericTypeParameterName)
                                                     .Build();

                var newGenericArray3DParameterType = new TypeSignatureBuilder(parameter.Type)
                                                     .WithIndirectionLevel(0)
                                                     .WithArrayDimensions(3)
                                                     .WithName(genericTypeParameterName)
                                                     .Build();

                newIntPtrParameters[i] = new ParameterSignatureBuilder(parameter)
                                         .WithType(newIntPtrParameterType)
                                         .Build();

                newGenericArray1DParameters[i] = new ParameterSignatureBuilder(parameter)
                                                 .WithType(newGenericArray1DParameterType)
                                                 .Build();

                newGenericArray2DParameters[i] = new ParameterSignatureBuilder(parameter)
                                                 .WithType(newGenericArray2DParameterType)
                                                 .Build();

                newGenericArray3DParameters[i] = new ParameterSignatureBuilder(parameter)
                                                 .WithType(newGenericArray3DParameterType)
                                                 .Build();
            }

            yield return(ToPointer
                         (
                             new FunctionSignatureBuilder(function)
                             .WithParameters(newIntPtrParameters)
                             .Build(),
                             function
                         ));

            yield return(Fixed
                         (
                             new FunctionSignatureBuilder(function)
                             .WithParameters(newGenericArray1DParameters)
                             .WithGenericTypeParameters(newGenericTypeParameters)
                             .Build()
                         ));

            yield return(Fixed
                         (
                             new FunctionSignatureBuilder(function)
                             .WithParameters(newGenericArray2DParameters)
                             .WithGenericTypeParameters(newGenericTypeParameters)
                             .Build()
                         ));

            yield return(Fixed
                         (
                             new FunctionSignatureBuilder(function)
                             .WithParameters(newGenericArray3DParameters)
                             .WithGenericTypeParameters(newGenericTypeParameters)
                             .Build()
                         ));
        }
Пример #26
0
        /// <summary>
        /// Writes this struct to a file.
        /// </summary>
        /// <param name="struct">The enum to write.</param>
        /// <param name="file">The file to write to.</param>
        /// <param name="profile">The subsystem containing this enum.</param>
        /// <param name="project">The project containing this enum.</param>
        public static void WriteStruct(this Struct @struct, string file, Profile profile, Project project, BindState task)
        {
            if (@struct.Attributes.IsBuildToolsIntrinsic(out var args))
            {
                WriteBuildToolsIntrinsic(@struct, file, profile, project, task, args);
                return;
            }

            var sw = new StreamWriter(file);

            sw.WriteLine(task.LicenseText());
            sw.WriteLine();
            sw.WriteCoreUsings();
            sw.WriteLine();
            sw.WriteLine("#pragma warning disable 1591");
            sw.WriteLine();
            var ns = project.IsRoot ? task.Task.Namespace : task.Task.ExtensionsNamespace;

            sw.WriteLine($"namespace {ns}{project.Namespace}");
            sw.WriteLine("{");
            foreach (var attr in @struct.Attributes)
            {
                if (attr.Name == "BuildToolsIntrinsic")
                {
                    continue;
                }

                sw.WriteLine($"    {attr}");
            }

            sw.WriteLine($"    [NativeName(\"Name\", \"{@struct.NativeName}\")]");
            sw.WriteLine($"    public unsafe partial struct {@struct.Name}");
            sw.WriteLine("    {");
            foreach (var comBase in @struct.ComBases)
            {
                var asSuffix = comBase.Split('.').Last();
                asSuffix = (asSuffix.StartsWith('I') ? asSuffix.Substring(1) : comBase);
                asSuffix = asSuffix.StartsWith(task.Task.FunctionPrefix)
                    ? asSuffix.Substring(task.Task.FunctionPrefix.Length)
                    : asSuffix;
                var fromSuffix = @struct.Name.Split('.').Last();
                fromSuffix = (fromSuffix.StartsWith('I') ? fromSuffix.Substring(1) : comBase);
                fromSuffix = fromSuffix.StartsWith(task.Task.FunctionPrefix)
                    ? fromSuffix.Substring(task.Task.FunctionPrefix.Length)
                    : fromSuffix;
                sw.WriteLine($"        public static implicit operator {comBase}({@struct.Name} val)");
                sw.WriteLine($"            => Unsafe.As<{@struct.Name}, {comBase}>(ref val);");
                sw.WriteLine();
                if (@struct.Functions.Any(x => x.Signature.Name.Equals("QueryInterface")))
                {
                    sw.WriteLine($"        public static explicit operator {@struct.Name}({comBase} val)");
                    sw.WriteLine($"            => From{fromSuffix}(in val);");
                    sw.WriteLine();
                    sw.WriteLine($"        public readonly ref {comBase} As{asSuffix}()");
                    sw.WriteLine("        {");
                    // yes i know this is unsafe and that there's a good reason why struct members can't return themselves
                    // by reference, but this should work well enough.
                    sw.WriteLine("#if NETSTANDARD2_1 || NET5_0 || NETCOREAPP3_1");
                    sw.WriteLine($"            return ref Unsafe.As<{@struct.Name}, {comBase}>");
                    sw.WriteLine($"            (");
                    sw.WriteLine($"                ref MemoryMarshal.GetReference");
                    sw.WriteLine($"                (");
                    sw.WriteLine($"                    MemoryMarshal.CreateSpan");
                    sw.WriteLine($"                    (");
                    sw.WriteLine($"                        ref Unsafe.AsRef(in this),");
                    sw.WriteLine($"                        1");
                    sw.WriteLine($"                    )");
                    sw.WriteLine($"                )");
                    sw.WriteLine($"            );");
                    sw.WriteLine("#else");
                    sw.WriteLine($"            fixed ({@struct.Name}* @this = &this)");
                    sw.WriteLine($"            {{");
                    sw.WriteLine($"                return ref *({comBase}*) @this;");
                    sw.WriteLine($"            }}");
                    sw.WriteLine("#endif");
                    sw.WriteLine("        }");
                    sw.WriteLine();
                    sw.WriteLine($"        public static ref {@struct.Name} From{fromSuffix}(in {comBase} @this)");
                    sw.WriteLine("        {");
                    sw.WriteLine($"            {@struct.Name}* ret = default;");
                    sw.WriteLine($"            SilkMarshal.ThrowHResult");
                    sw.WriteLine($"            (");
                    sw.WriteLine($"                @this.QueryInterface");
                    sw.WriteLine($"                (");
                    sw.WriteLine($"                    ref SilkMarshal.GuidOf<{@struct.Name}>(),");
                    sw.WriteLine($"                    (void**) &ret");
                    sw.WriteLine($"                )");
                    sw.WriteLine($"            );");
                    sw.WriteLine();
                    sw.WriteLine($"            return ref *ret;");
                    sw.WriteLine("        }");
                    sw.WriteLine();
                }
            }

            if (@struct.Fields.Any(x => x.Count is null))
            {
                sw.WriteLine($"        public {@struct.Name}");
                sw.WriteLine("        (");
                var first = true;
                foreach (var field in @struct.Fields)
                {
                    if (!(field.Count is null))
                    {
                        continue; // I've chosen not to initialize multi-count fields from ctors.
                    }
                    var argName = field.Name[0].ToString().ToLower() + field.Name.Substring(1);
                    argName = Utilities.CSharpKeywords.Contains(argName) ? $"@{argName}" : argName;
                    if (!first)
                    {
                        sw.WriteLine(",");
                    }
                    else
                    {
                        first = false;
                    }

                    var nullable = field.Type.ToString().Contains('*') ? null : "?";
                    sw.Write($"            {field.Type}{nullable} {argName} = {field.DefaultAssignment ?? "null"}");
                }

                sw.WriteLine();
                sw.WriteLine("        ) : this()");
                sw.WriteLine("        {");
                first = true;
                foreach (var field in @struct.Fields)
                {
                    if (!(field.Count is null))
                    {
                        continue; // I've chosen not to initialize multi-count fields from ctors.
                    }
                    var argName = field.Name[0].ToString().ToLower() + field.Name.Substring(1);
                    argName = Utilities.CSharpKeywords.Contains(argName) ? $"@{argName}" : argName;
                    if (!first)
                    {
                        sw.WriteLine();
                    }
                    else
                    {
                        first = false;
                    }

                    sw.WriteLine($"            if ({argName} is not null)");
                    sw.WriteLine("            {");

                    var value = field.Type.ToString().Contains('*') ? null : ".Value";
                    sw.WriteLine($"                {field.Name} = {argName}{value};");
                    sw.WriteLine("            }");
                }

                sw.WriteLine("        }");
                sw.WriteLine();
            }

            foreach (var structField in @struct.Fields)
            {
                if (!(structField.Count is null))
                {
                    if (!Field.FixedCapableTypes.Contains(structField.Type.Name))
                    {
                        var count = structField.Count.IsConstant
                            ? int.Parse
                                    (
                            profile.Projects.SelectMany(x => x.Value.Classes.SelectMany(y => y.Constants))
                            .FirstOrDefault(x => x.NativeName == structField.Count.ConstantName)
                                    ?
                            .Value ?? throw new InvalidDataException("Couldn't find constant referenced")
                                    )
                                        : structField.Count.IsStatic
                                ? structField.Count.StaticCount
                                : 1;
                        var typeFixup09072020 = new TypeSignatureBuilder(structField.Type).WithIndirectionLevel
                                                    (structField.Type.IndirectionLevels - 1).Build();
                        sw.WriteLine($"        {structField.Doc}");
                        foreach (var attr in structField.Attributes)
                        {
                            sw.WriteLine($"        {attr}");
                        }

                        sw.WriteLine($"        [NativeName(\"Type\", \"{structField.NativeType}\")]");
                        sw.WriteLine($"        [NativeName(\"Type.Name\", \"{structField.Type.OriginalName}\")]");
                        sw.WriteLine($"        [NativeName(\"Name\", \"{structField.NativeName}\")]");
                        sw.WriteLine($"        public {structField.Name}Buffer {structField.Name};");
                        sw.WriteLine();
                        sw.WriteLine($"        public struct {structField.Name}Buffer");
                        sw.WriteLine("        {");
                        for (var i = 0; i < count; i++)
                        {
                            sw.WriteLine($"            public {typeFixup09072020} Element{i};");
                        }

                        sw.WriteLine($"            public ref {typeFixup09072020} this[int index]");
                        sw.WriteLine("            {");
                        sw.WriteLine("                get");
                        sw.WriteLine("                {");
                        sw.WriteLine($"                    if (index > {count - 1} || index < 0)");
                        sw.WriteLine("                    {");
                        sw.WriteLine("                        throw new ArgumentOutOfRangeException(nameof(index));");
                        sw.WriteLine("                    }");
                        sw.WriteLine();
                        sw.WriteLine($"                    fixed ({typeFixup09072020}* ptr = &Element0)");
                        sw.WriteLine("                    {");
                        sw.WriteLine("                        return ref ptr[index];");
                        sw.WriteLine("                    }");
                        sw.WriteLine("                }");
                        sw.WriteLine("            }");
                        if (!typeFixup09072020.IsPointer)
                        {
                            sw.WriteLine();
                            sw.WriteLine("#if NETSTANDARD2_1");
                            sw.WriteLine($"            public Span<{typeFixup09072020}> AsSpan()");
                            sw.WriteLine($"                => MemoryMarshal.CreateSpan(ref Element0, {count});");
                            sw.WriteLine("#endif");
                        }

                        sw.WriteLine("        }");
                        sw.WriteLine();
                    }
                    else
                    {
                        if (!string.IsNullOrEmpty(structField.Doc))
                        {
                            sw.WriteLine($"        {structField.Doc}");
                        }

                        var count = structField.Count.IsConstant
                            ? Utilities.ParseInt
                                    (
                            profile.Projects.SelectMany(x => x.Value.Classes.SelectMany(y => y.Constants))
                            .FirstOrDefault(x => x.NativeName == structField.Count.ConstantName)?
                            .Value ??
                            profile.Projects.SelectMany(x => x.Value.Enums.SelectMany(y => y.Tokens))
                            .FirstOrDefault(x => x.NativeName == structField.Count.ConstantName)?
                            .Value ?? throw new InvalidDataException("Couldn't find constant referenced")
                                    )
                                        : structField.Count.IsStatic
                                ? structField.Count.StaticCount
                                : 1;
                        var typeFixup09072020 = new TypeSignatureBuilder(structField.Type).WithIndirectionLevel
                                                //(structField.Type.IndirectionLevels - 1).Build();
                                                    (0).Build();

                        foreach (var attr in structField.Attributes)
                        {
                            sw.WriteLine($"        {attr}");
                        }

                        sw.WriteLine($"        [NativeName(\"Type\", \"{structField.NativeType}\")]");
                        sw.WriteLine($"        [NativeName(\"Type.Name\", \"{structField.Type.OriginalName}\")]");
                        sw.WriteLine($"        [NativeName(\"Name\", \"{structField.NativeName}\")]");
                        sw.WriteLine($"        public fixed {typeFixup09072020} {structField.Name}[{count}];");
                    }
                }
Пример #27
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;");
            }
        }
    }
Пример #28
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
                         ));
        }
Пример #29
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));
            }
        }
        /// <inheritdoc/>
        public IEnumerable <FunctionSignature> CreateOverloads(FunctionSignature function)
        {
            var baseParameters = function.Parameters;

            var refParameterPermutation   = new List <ParameterSignature>(baseParameters);
            var arrayParameterPermutation = new List <ParameterSignature>(baseParameters);

            for (int i = 0; i < baseParameters.Count; ++i)
            {
                var baseParameter = baseParameters[i];
                var baseType      = baseParameter.Type;

                if (!baseType.IsPointer || baseType.IndirectionLevel > 1)
                {
                    continue;
                }

                if (baseType.Name.Equals(typeof(void).Name, StringComparison.OrdinalIgnoreCase))
                {
                    // Skip void pointers
                    continue;
                }

                var refTypeBuilder = new TypeSignatureBuilder(baseType)
                                     .WithIndirectionLevel(0)
                                     .WithByRef(true);

                if (baseParameter.Flow == FlowDirection.Out)
                {
                    refTypeBuilder = refTypeBuilder.WithIsOut(true);
                }

                var refType = refTypeBuilder.Build();

                var refParameter = new ParameterSignatureBuilder(baseParameter)
                                   .WithType(refType)
                                   .Build();

                refParameterPermutation[i] = refParameter;

                if (!(baseParameter.Count is null) && baseParameter.Count.IsStatic && baseParameter.Count.Count == 1)
                {
                    // Single-element count pointers don't need array overloads
                    continue;
                }

                var arrayType = new TypeSignatureBuilder(baseType)
                                .WithIndirectionLevel(0)
                                .WithArrayDimensions(1)
                                .Build();

                var arrayParameter = new ParameterSignatureBuilder(baseParameter)
                                     .WithType(arrayType)
                                     .Build();

                arrayParameterPermutation[i] = arrayParameter;
            }

            yield return(new FunctionSignatureBuilder(function)
                         .WithParameters(refParameterPermutation)
                         .Build());

            yield return(new FunctionSignatureBuilder(function)
                         .WithParameters(arrayParameterPermutation)
                         .Build());
        }