예제 #1
0
        private static AccessorDeclarationSyntax GenerateGetter(CsField csElement,
                                                                PropertyValueGetTransform valueTransformation)
        {
            ExpressionSyntax valueExpression = ParseName(csElement.IntermediateMarshalName);

            return(AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
                   .WithExpressionBody(
                       ArrowExpressionClause(
                           valueTransformation != null
                               ? valueTransformation(GeneratorHelpers.WrapInParentheses(valueExpression))
                               : valueExpression
                           )
                       )
                   .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)));
        }
예제 #2
0
        private static PropertyValueSetTransform Compose(PropertyValueSetTransform second,
                                                         PropertyValueSetTransform first)
        {
            if (second == null)
            {
                return(first);
            }
            if (first == null)
            {
                return(second);
            }

            return((oldValue, x) =>
            {
                var value = first(oldValue, x);
                return second(oldValue, GeneratorHelpers.WrapInParentheses(value));
            });
        }
예제 #3
0
        public ExpressionSyntax GenerateCall(CsCallable callable, PlatformDetectionType platform,
                                             InteropMethodSignature interopSig)
        {
            var arguments = IterateNativeArguments(callable, interopSig).ToArray();

            ElementAccessExpressionSyntax vtblAccess = null;

            if (callable is CsMethod method)
            {
                var windowsOffsetExpression =
                    LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(method.WindowsOffset));
                var nonWindowsOffsetExpression =
                    LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(method.Offset));

                ExpressionSyntax vtableOffsetExpression;
                if ((platform & PlatformDetectionType.Any) == PlatformDetectionType.Any &&
                    method.Offset != method.WindowsOffset)
                {
                    vtableOffsetExpression = ConditionalExpression(
                        MemberAccessExpression(
                            SyntaxKind.SimpleMemberAccessExpression,
                            GlobalNamespace.GetTypeNameSyntax(WellKnownName.PlatformDetection),
                            IdentifierName("Is" + nameof(PlatformDetectionType.Windows))),
                        windowsOffsetExpression,
                        nonWindowsOffsetExpression);
                }
                else if ((platform & PlatformDetectionType.Windows) != 0)
                {
                    vtableOffsetExpression = windowsOffsetExpression;
                }
                else
                {
                    vtableOffsetExpression = nonWindowsOffsetExpression;
                }

                vtblAccess = ElementAccessExpression(
                    ThisExpression(),
                    BracketedArgumentList(
                        SingletonSeparatedList(
                            Argument(
                                method.CustomVtbl
                                    ? MemberAccessExpression(
                                    SyntaxKind.SimpleMemberAccessExpression,
                                    ThisExpression(),
                                    IdentifierName($"{callable.Name}__vtbl_index")
                                    )
                                    : vtableOffsetExpression
                                )
                            )
                        )
                    );
            }

            ExpressionSyntax FnPtrCall()
            {
                var fnptrParameters = arguments
                                      .Select(x => x.Type)
                                      .Append(ParseTypeName(interopSig.ReturnType.TypeName))
                                      .Select(FunctionPointerParameter);

                return(GeneratorHelpers.CastExpression(
                           FunctionPointerType(
                               FunctionPointerCallingConvention(
                                   Token(SyntaxKind.UnmanagedKeyword),
                                   FunctionPointerUnmanagedCallingConventionList(
                                       SingletonSeparatedList(
                                           FunctionPointerUnmanagedCallingConvention(
                                               Identifier(callable.CppCallingConvention.ToCallConvShortName())
                                               )
                                           )
                                       )
                                   ),
                               FunctionPointerParameterList(SeparatedList(fnptrParameters))
                               ),
                           vtblAccess
                           ));
            }

            var what = callable switch
            {
                CsFunction => IdentifierName(
                    callable.CppElementName + GeneratorHelpers.GetPlatformSpecificSuffix(platform)
                    ),
                CsMethod => GeneratorHelpers.WrapInParentheses(FnPtrCall()),
                _ => throw new ArgumentOutOfRangeException()
            };

            ExpressionSyntax call = InvocationExpression(
                what,
                ArgumentList(SeparatedList(arguments.Select(x => x.Argument)))
                );

            if (interopSig.CastToNativeLong)
            {
                call = CastExpression(GlobalNamespace.GetTypeNameSyntax(WellKnownName.NativeLong), call);
            }

            if (interopSig.CastToNativeULong)
            {
                call = CastExpression(GlobalNamespace.GetTypeNameSyntax(WellKnownName.NativeULong), call);
            }

            if (interopSig.ForcedReturnBufferSig || !callable.HasReturnType)
            {
                return(call);
            }

            return(AssignmentExpression(
                       SyntaxKind.SimpleAssignmentExpression,
                       GetMarshaller(callable.ReturnValue).GeneratesMarshalVariable(callable.ReturnValue)
                    ? MarshallerBase.GetMarshalStorageLocation(callable.ReturnValue)
                    : IdentifierName(callable.ReturnValue.Name),
                       call
                       ));
        }
예제 #4
0
        public override IEnumerable <MemberDeclarationSyntax> GenerateCode(CsField csElement)
        {
            if (csElement.IsBoolToInt && !csElement.IsArray)
            {
                yield return(GenerateBackingField(csElement, csElement.MarshalType));

                yield return(GenerateProperty(
                                 csElement, PredefinedType(Token(SyntaxKind.BoolKeyword)),
                                 GeneratorHelpers.GenerateIntToBoolConversion,
                                 (_, value) => GeneratorHelpers.CastExpression(
                                     ParseTypeName(csElement.MarshalType.QualifiedName),
                                     GeneratorHelpers.GenerateBoolToIntConversion(value)
                                     )
                                 ));
            }
            else if (csElement.IsArray && !csElement.IsString)
            {
                var elementType = ParseTypeName(csElement.PublicType.QualifiedName);

                yield return(GenerateBackingField(csElement, csElement.PublicType, isArray: true));

                yield return(GenerateProperty(
                                 csElement, ArrayType(elementType, SingletonList(ArrayRankSpecifier())),
                                 value => AssignmentExpression(
                                     SyntaxKind.CoalesceAssignmentExpression,
                                     value,
                                     ObjectCreationExpression(
                                         ArrayType(
                                             elementType,
                                             SingletonList(
                                                 ArrayRankSpecifier(
                                                     SingletonSeparatedList <ExpressionSyntax>(
                                                         LiteralExpression(
                                                             SyntaxKind.NumericLiteralExpression,
                                                             Literal(csElement.ArrayDimensionValue)
                                                             )
                                                         )
                                                     )
                                                 )
                                             )
                                         )
                                     ),
                                 null
                                 ));
            }
            else if (csElement.IsBitField)
            {
                PropertyValueGetTransform getterTransform;
                PropertyValueSetTransform setterTransform;
                TypeSyntax propertyType;

                if (csElement.IsBoolBitField)
                {
                    getterTransform = GeneratorHelpers.GenerateIntToBoolConversion;
                    setterTransform = (_, value) => GeneratorHelpers.GenerateBoolToIntConversion(value);
                    propertyType    = PredefinedType(Token(SyntaxKind.BoolKeyword));
                }
                else
                {
                    getterTransform = valueExpression => GeneratorHelpers.CastExpression(
                        ParseTypeName(csElement.PublicType.QualifiedName),
                        valueExpression
                        );
                    setterTransform = null;
                    propertyType    = ParseTypeName(csElement.PublicType.QualifiedName);
                }

                yield return(GenerateBackingField(csElement, csElement.PublicType));

                var bitMask   = LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(csElement.BitMask));
                var bitOffset = LiteralExpression(
                    SyntaxKind.NumericLiteralExpression, Literal(csElement.BitOffset)
                    );

                yield return(GenerateProperty(
                                 csElement, propertyType,
                                 Compose(
                                     getterTransform,
                                     value => BinaryExpression(
                                         SyntaxKind.BitwiseAndExpression,
                                         GeneratorHelpers.WrapInParentheses(
                                             BinaryExpression(SyntaxKind.RightShiftExpression, value, bitOffset)
                                             ),
                                         bitMask
                                         )
                                     ),
                                 Compose(
                                     (oldValue, value) => GeneratorHelpers.CastExpression(
                                         ParseTypeName(csElement.PublicType.QualifiedName),
                                         BinaryExpression(
                                             SyntaxKind.BitwiseOrExpression,
                                             GeneratorHelpers.WrapInParentheses(
                                                 BinaryExpression(
                                                     SyntaxKind.BitwiseAndExpression,
                                                     oldValue,
                                                     PrefixUnaryExpression(
                                                         SyntaxKind.BitwiseNotExpression,
                                                         GeneratorHelpers.WrapInParentheses(
                                                             BinaryExpression(SyntaxKind.LeftShiftExpression, bitMask, bitOffset)
                                                             )
                                                         )
                                                     )
                                                 ),
                                             GeneratorHelpers.WrapInParentheses(
                                                 BinaryExpression(
                                                     SyntaxKind.LeftShiftExpression,
                                                     GeneratorHelpers.WrapInParentheses(
                                                         BinaryExpression(SyntaxKind.BitwiseAndExpression, value, bitMask)
                                                         ),
                                                     bitOffset
                                                     )
                                                 )
                                             )
                                         ),
                                     setterTransform
                                     )
                                 ));
            }
            else
            {
                yield return(GenerateBackingField(
                                 csElement, csElement.PublicType, propertyBacking: false, document: true
                                 ));
            }
        }