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