public Compiler(string name) { Assembly = new AssemblyDefinition(name, name + ".exe"); Context = new CompilerContext(this); Global = new GlobalNamespace(); AstRoot = new AstProject(name + ".exe"); }
public override StatementSyntax GenerateManagedToNative(CsMarshalBase csElement, bool singleStackFrame) => GenerateNullCheckIfNeeded( csElement, ExpressionStatement( InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, GlobalNamespace.GetTypeNameSyntax(WellKnownName.MarshallingHelpers), GenericName(Identifier("ConvertToPointerArray")) .WithTypeArgumentList( TypeArgumentList( SingletonSeparatedList <TypeSyntax>( IdentifierName(csElement.PublicType.QualifiedName) ) ) ) ), ArgumentList( SeparatedList( new[] { // Span<IntPtr> pointers, ReadOnlySpan<TCallback> interfaces Argument(GetMarshalStorageLocation(csElement)), Argument(IdentifierName(csElement.Name)) } ) ) ) ) );
public StatementSyntax GenerateManagedToNative(CsMarshalBase csElement, bool singleStackFrame) => ExpressionStatement( AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, GetMarshalStorageLocation(csElement), InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, GlobalNamespace.GetTypeNameSyntax(WellKnownName.MarshallingHelpers), GenericName(Identifier("ToCallbackPtr")) .WithTypeArgumentList( TypeArgumentList( SingletonSeparatedList <TypeSyntax>( IdentifierName(csElement.PublicType.QualifiedName) ) ) ) ), ArgumentList( SingletonSeparatedList( Argument(IdentifierName(csElement.Name)) ) ) ) ) );
public override void SetUp() { base.SetUp(); Context.References.Add(typeof(Boo.Lang.List).Assembly); Context.References.Add(typeof(Boo.Lang.Compiler.CompilerContext).Assembly); RunInCompilerContextEnvironment(() => _subject = My <GlobalNamespace> .Instance); }
public override void SetUp() { base.SetUp(); Context.References.Add(typeof(Boo.Lang.List).Assembly); Context.References.Add(typeof(Boo.Lang.Compiler.CompilerContext).Assembly); RunInCompilerContextEnvironment(() => _subject = My<GlobalNamespace>.Instance); }
private ExpressionSyntax GetMarshalFunctionPointerForDelegate(CsMethod method, PlatformDetectionType platform) => InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, GlobalNamespace.GetTypeNameSyntax(BuiltinType.Marshal), IdentifierName("GetFunctionPointerForDelegate") ), ArgumentList(SingletonSeparatedList(Argument(IdentifierName(GetMethodCacheName(method, platform))))) );
GlobalNamespace GetGlobalNamespace() { INamespace ns = _global; GlobalNamespace globals = ns as GlobalNamespace; while (globals == null && ns != null) { ns = ns.ParentNamespace; globals = ns as GlobalNamespace; } return(globals); }
public StatementSyntax GenerateManagedToNative(CsMarshalBase csElement, bool singleStackFrame) { var marshalStorage = GetMarshalStorageLocation(csElement); // TODO: Reverse-callback support? if (singleStackFrame) { return(GenerateNullCheckIfNeeded( csElement, EmitConvertToIntArray(marshalStorage) )); } else { return(GenerateNullCheckIfNeeded(csElement, FixedStatement( VariableDeclaration(GetMarshalTypeSyntax(csElement)) .WithVariables( SingletonSeparatedList( VariableDeclarator( Identifier("__ptr")) .WithInitializer( EqualsValueClause( PrefixUnaryExpression( SyntaxKind.AddressOfExpression, marshalStorage))))), EmitConvertToIntArray(IdentifierName("__ptr")) ))); } ExpressionStatementSyntax EmitConvertToIntArray(ExpressionSyntax destination) => ExpressionStatement( InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, GlobalNamespace.GetTypeNameSyntax(WellKnownName.BooleanHelpers), IdentifierName("ConvertToIntArray") ), ArgumentList( SeparatedList( new[] { Argument(IdentifierName(csElement.Name)), Argument(destination) } ) ) ) ); }
public StatementSyntax GenerateNativeCleanup(CsMarshalBase csElement, bool singleStackFrame) { if (!csElement.IsWideChar || !singleStackFrame) { return(ExpressionStatement( InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, GlobalNamespace.GetTypeNameSyntax(BuiltinType.Marshal), IdentifierName(nameof(Marshal.FreeHGlobal)) ), ArgumentList(SingletonSeparatedList(Argument(GetMarshalStorageLocation(csElement)))) ) )); } return(null); }
public StatementSyntax GenerateManagedToNative(CsMarshalBase csElement, bool singleStackFrame) { if (csElement.IsArray) // Fixed-length character array { if (!csElement.IsWideChar) { return(GenerateAnsiStringToArray(csElement)); } if (!singleStackFrame) { return(GenerateStringToArray(csElement)); } return(null); } // Variable-length string represented as a pointer. if (!csElement.IsWideChar || !singleStackFrame) { var argumentList = ArgumentList(SingletonSeparatedList(Argument(IdentifierName(csElement.Name)))); ExpressionSyntax value = csElement.StringMarshal switch { StringMarshalType.WindowsRuntimeString => ObjectCreationExpression( GlobalNamespace.GetTypeNameSyntax(WellKnownName.WinRTString), argumentList, default ), var type => InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, GlobalNamespace.GetTypeNameSyntax(BuiltinType.Marshal), IdentifierName( type switch { StringMarshalType.GlobalHeap when csElement.IsWideChar => nameof(Marshal.StringToHGlobalUni), StringMarshalType.GlobalHeap => nameof(Marshal.StringToHGlobalAnsi), StringMarshalType.ComTaskAllocator when csElement.IsWideChar => nameof(Marshal.StringToCoTaskMemUni), StringMarshalType.ComTaskAllocator => nameof(Marshal.StringToCoTaskMemAnsi), StringMarshalType.BinaryString => nameof(Marshal.StringToBSTR), _ => throw new ArgumentOutOfRangeException() }
public override MemberDeclarationSyntax GenerateCode(CsResultConstant csElement) => AddDocumentationTrivia( FieldDeclaration( VariableDeclaration( GlobalNamespace.GetTypeNameSyntax(WellKnownName.Result), SingletonSeparatedList( VariableDeclarator(Identifier(csElement.Name)) .WithInitializer( EqualsValueClause( ImplicitObjectCreationExpression() .AddArgumentListArguments(Argument(ParseExpression(csElement.Value))) ) ) ) ) ) .WithModifiers(csElement.VisibilityTokenList), csElement );
public StatementSyntax GenerateManagedToNative(CsMarshalBase csElement, bool singleStackFrame) { if (csElement.IsArray) // Fixed-length character array { if (!csElement.IsWideChar) { return(GenerateAnsiStringToArray(csElement)); } if (!singleStackFrame) { return(GenerateStringToArray(csElement)); } return(null); } // Variable-length string represented as a pointer. if (!csElement.IsWideChar || !singleStackFrame) { return(ExpressionStatement( AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, GetMarshalStorageLocation(csElement), InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, GlobalNamespace.GetTypeNameSyntax(BuiltinType.Marshal), IdentifierName( csElement.IsWideChar ? nameof(Marshal.StringToHGlobalUni) : nameof(Marshal.StringToHGlobalAnsi) ) ), ArgumentList(SingletonSeparatedList(Argument(IdentifierName(csElement.Name)))) ) ) )); } return(null); }
protected override ExpressionSyntax Generate(CsResultConstant csElement) { return(InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, GlobalNamespace.GetTypeNameSyntax(WellKnownName.Result), IdentifierName("Register") ), ArgumentList( SeparatedList( new[] { Argument(ParseExpression(csElement.Value)), LiteralArgument(csElement.Module), LiteralArgument(csElement.CppElementName), LiteralArgument(csElement.Name) } ) ) ));
public IEnumerable <StatementSyntax> GenerateManagedToNativeProlog(CsMarshalCallableBase csElement) { var identifier = GetMarshalStorageLocationIdentifier(csElement); var elementType = GetMarshalElementTypeSyntax(csElement); var spanTypeName = GlobalNamespace.GetGenericTypeNameSyntax( BuiltinType.Span, TypeArgumentList(SingletonSeparatedList(elementType)) ); ArrayTypeSyntax GetArrayType(ExpressionSyntax length) => ArrayType( elementType, SingletonList(ArrayRankSpecifier(SingletonSeparatedList(length))) ); yield return(LocalDeclarationStatement( VariableDeclaration( spanTypeName, SingletonSeparatedList( VariableDeclarator( identifier, default,
protected ExpressionStatementSyntax GenerateCopyMemoryInvocation( ExpressionSyntax destination, ExpressionSyntax source, ExpressionSyntax numBytesExpression ) => ExpressionStatement( InvocationExpression( MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, GlobalNamespace.GetTypeNameSyntax(WellKnownName.MemoryHelpers), IdentifierName("CopyMemory") ), ArgumentList( SeparatedList( new[] { Argument(destination), Argument(source), Argument(numBytesExpression) } ) ) ) );
public StatementSyntax GenerateNativeToManaged(CsMarshalBase csElement, bool singleStackFrame) { MemberAccessExpressionSyntax PtrToString(NameSyntax implName) => MemberAccessExpression( SyntaxKind.SimpleMemberAccessExpression, implName, IdentifierName( csElement.IsWideChar ? nameof(Marshal.PtrToStringUni) : nameof(Marshal.PtrToStringAnsi) ) ); if (csElement.IsArray) // Fixed-length character array { if (csElement.IsWideChar && singleStackFrame) { return(null); } const string ptrName = "__ptr"; return(FixedStatement( VariableDeclaration( VoidPtrType, SingletonSeparatedList( VariableDeclarator(ptrName) .WithInitializer( EqualsValueClause( PrefixUnaryExpression( SyntaxKind.AddressOfExpression, GetMarshalStorageLocation(csElement) ) ) ) ) ), ExpressionStatement( AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, IdentifierName(csElement.Name), InvocationExpression( PtrToString(GlobalNamespace.GetTypeNameSyntax(WellKnownName.StringHelpers)), ArgumentList( SeparatedList( new[] { Argument(CastExpression(IntPtrType, IdentifierName(ptrName))), Argument( LiteralExpression( SyntaxKind.NumericLiteralExpression, Literal(csElement.ArrayDimensionValue - 1) ) ) } ) ) ) ) ) )); } // Variable-length string represented as a pointer. return(ExpressionStatement( AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, IdentifierName(csElement.Name), InvocationExpression( PtrToString(GlobalNamespaceProvider.GetTypeNameSyntax(BuiltinType.Marshal)), ArgumentList(SingletonSeparatedList(Argument(GetMarshalStorageLocation(csElement)))) ) ) )); }
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 )); }
/// <summary> /// Iterate through all namespace data from top to bottom /// </summary> public IEnumerable <NamespaceData> GetAllNamespaceDatas(Func <NamespaceData, bool> predicate = null) { return(GlobalNamespace.GetSelfAndDescendantsNamespaceData(predicate)); }
private StatementSyntax GenerateStringToArray(CsMarshalBase marshallable) { var lengthIdentifier = LengthVariableName(marshallable); return(FixedStatement( VariableDeclaration( PointerType(PredefinedType(Token(SyntaxKind.CharKeyword))), SeparatedList( new[] { VariableDeclarator(FromIdentifier) .WithInitializer(EqualsValueClause(IdentifierName(marshallable.Name))), VariableDeclarator(ToIdentifier) .WithInitializer(EqualsValueClause( PrefixUnaryExpression(SyntaxKind.AddressOfExpression, GetMarshalStorageLocation(marshallable)))) }) ), Block( LocalDeclarationStatement( VariableDeclaration( TypeInt32, SingletonSeparatedList( VariableDeclarator(lengthIdentifier) .WithInitializer(EqualsValueClause( InvocationExpression(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, GlobalNamespace.GetTypeNameSyntax(BuiltinType.Math), IdentifierName(nameof(Math.Min))), ArgumentList( SeparatedList( new[] { Argument( BinaryExpression( SyntaxKind.MultiplyExpression, ParenthesizedExpression( GeneratorHelpers.OptionalLengthExpression(IdentifierName(marshallable.Name)) ), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(2)) )), Argument( BinaryExpression(SyntaxKind.MultiplyExpression, LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(marshallable.ArrayDimensionValue - 1)), LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(2)))) } ) ))))))), GenerateCopyMemoryInvocation(IdentifierName(lengthIdentifier), castTo: false, castFrom: false), ExpressionStatement( AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, ElementAccessExpression(IdentifierName(ToIdentifier), BracketedArgumentList( SingletonSeparatedList( Argument(IdentifierName(lengthIdentifier))))), LiteralExpression(SyntaxKind.CharacterLiteralExpression, Literal('\0'))))))); }
public MemberDeclarationSyntax GenerateCode(CsInterface csElement) { var vtblClassName = csElement.VtblName.Split('.').Last(); // Default: at least protected to enable inheritance. var vtblVisibility = csElement.VtblVisibility ?? Visibility.ProtectedInternal; StatementSyntax VtblMethodSelector(CsMethod method) { StatementSyntax MethodBuilder(PlatformDetectionType platform) { var arguments = new[] { Argument( ObjectCreationExpression(IdentifierName(GetMethodDelegateName(method, platform))) .WithArgumentList( ArgumentList( SingletonSeparatedList( Argument( IdentifierName( $"{method.Name}{GeneratorHelpers.GetPlatformSpecificSuffix(platform)}" ) ) ) ) ) ), Argument( LiteralExpression( SyntaxKind.NumericLiteralExpression, Literal((platform & PlatformDetectionType.Windows) != 0 ? method.WindowsOffset : method.Offset) ) ) }; return(ExpressionStatement( InvocationExpression(IdentifierName("AddMethod")) .WithArgumentList(ArgumentList(SeparatedList(arguments))) )); } return(GeneratorHelpers.GetPlatformSpecificStatements(GlobalNamespace, Generators.Config, method.InteropSignatures.Keys, MethodBuilder)); } List <MemberDeclarationSyntax> members = new() { ConstructorDeclaration(Identifier(vtblClassName)) .WithModifiers(TokenList(Token(SyntaxKind.PublicKeyword))) .WithParameterList( ParameterList( SingletonSeparatedList( Parameter(Identifier("numberOfCallbackMethods")) .WithType(PredefinedType(Token(SyntaxKind.IntKeyword))) ) ) ) .WithInitializer( ConstructorInitializer( SyntaxKind.BaseConstructorInitializer, ArgumentList( SingletonSeparatedList( Argument( BinaryExpression( SyntaxKind.AddExpression, IdentifierName("numberOfCallbackMethods"), LiteralExpression( SyntaxKind.NumericLiteralExpression, Literal(csElement.MethodList.Count) ) ) ) ) ) ) ) .WithBody( Block( csElement.Methods .OrderBy(method => method.Offset) .Select(VtblMethodSelector) ) ) }; members.AddRange(csElement.Methods.SelectMany(method => Generators.ShadowCallable.GenerateCode(method))); return(ClassDeclaration(vtblClassName) .WithModifiers( ModelUtilities.VisibilityToTokenList(vtblVisibility, SyntaxKind.UnsafeKeyword, SyntaxKind.PartialKeyword) ) .WithAttributeLists(DebuggerTypeProxyAttribute) .WithBaseList( BaseList( SingletonSeparatedList <BaseTypeSyntax>( SimpleBaseType( csElement.Base != null ? IdentifierName(csElement.Base.VtblName) : GlobalNamespace.GetTypeNameSyntax(WellKnownName.CppObjectVtbl) ) ) ) ) .WithMembers(List(members))); }
public MemberDeclarationSyntax GenerateCode(CsInterface csElement) { var shadowClassName = csElement.ShadowName.Split('.').Last(); var vtblName = IdentifierName(csElement.VtblName); var vtblConstructor = ArgumentList( SingletonSeparatedList( Argument( LiteralExpression( SyntaxKind.NumericLiteralExpression, Literal(0) ) ) ) ); var vtblProperty = PropertyDeclaration( GlobalNamespace.GetTypeNameSyntax(WellKnownName.CppObjectVtbl), Identifier("Vtbl") ) .WithModifiers( TokenList(Token(SyntaxKind.ProtectedKeyword), Token(SyntaxKind.OverrideKeyword)) ) .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)); List <MemberDeclarationSyntax> members = new(); if (csElement.AutoGenerateVtbl) { members.Add(Generators.Vtbl.GenerateCode(csElement)); } if (csElement.StaticShadowVtbl) { var vtblInstanceName = Identifier("VtblInstance"); members.Add( FieldDeclaration( VariableDeclaration(vtblName) .WithVariables( SingletonSeparatedList( VariableDeclarator(vtblInstanceName) .WithInitializer( EqualsValueClause( ImplicitObjectCreationExpression() .WithArgumentList( vtblConstructor ) ) ) ) ) ) .WithModifiers( TokenList(Token(SyntaxKind.PrivateKeyword), Token(SyntaxKind.StaticKeyword), Token(SyntaxKind.ReadOnlyKeyword)) ) ); vtblProperty = vtblProperty .WithExpressionBody( ArrowExpressionClause(IdentifierName(vtblInstanceName)) ); } else { vtblProperty = vtblProperty .WithAccessorList( AccessorList( SingletonList( AccessorDeclaration(SyntaxKind.GetAccessorDeclaration) .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)) ) ) ) .WithInitializer( EqualsValueClause( ObjectCreationExpression(vtblName) .WithArgumentList( vtblConstructor ) ) ); } members.Add(vtblProperty); return(ClassDeclaration(shadowClassName) .WithModifiers( ModelUtilities.VisibilityToTokenList(csElement.ShadowVisibility, SyntaxKind.PartialKeyword) ) .WithBaseList( BaseList( SingletonSeparatedList <BaseTypeSyntax>( SimpleBaseType( csElement.Base != null ? IdentifierName(csElement.Base.ShadowName) : GlobalNamespace.GetTypeNameSyntax(WellKnownName.CppObjectShadow) ) ) ) ) .WithMembers(new SyntaxList <MemberDeclarationSyntax>(members))); }