Beispiel #1
0
        static AstInterfaceNode ParseInterface(AstAttributes interfaceAttrs, ref TokenParser parser)
        {
            var    interfaceName = parser.ParseIdentifier();
            string inheritsFrom  = null;

            if (parser.TryConsume(":"))
            {
                inheritsFrom = parser.ParseIdentifier();
            }

            EnsureOpenBracket(ref parser);
            var rv = new AstInterfaceNode
            {
                Name = interfaceName, Attributes = interfaceAttrs, Inherits = inheritsFrom
            };

            while (!parser.TryConsume('}') && !parser.Eof)
            {
                var memberAttrs = ParseLocalAttributes(ref parser);
                var returnType  = ParseType(ref parser);
                var name        = parser.ParseIdentifier();
                var member      = new AstInterfaceMemberNode
                {
                    Name = name, ReturnType = returnType, Attributes = memberAttrs
                };
                rv.Add(member);

                parser.Consume('(');
                while (true)
                {
                    if (parser.TryConsume(')'))
                    {
                        break;
                    }

                    var argumentAttrs = ParseLocalAttributes(ref parser);
                    var type          = ParseType(ref parser);
                    var argName       = parser.ParseIdentifier();
                    member.Add(new AstInterfaceMemberArgumentNode
                    {
                        Name = argName, Type = type, Attributes = argumentAttrs
                    });

                    if (parser.TryConsume(')'))
                    {
                        break;
                    }
                    if (parser.TryConsume(','))
                    {
                        continue;
                    }
                    throw new ParseException("Unexpected character", ref parser);
                }

                parser.Consume(';');
            }

            return(rv);
        }
        void GenerateInterface(ref NamespaceDeclarationSyntax ns, ref NamespaceDeclarationSyntax implNs,
                               AstInterfaceNode iface)
        {
            var guidString      = iface.GetAttribute("uuid");
            var inheritsUnknown = iface.Inherits == null || iface.Inherits == "IUnknown";

            var ifaceDec = InterfaceDeclaration(iface.Name)
                           .WithBaseType(inheritsUnknown ? "Avalonia.MicroCom.IUnknown" : iface.Inherits)
                           .AddModifiers(Token(_visibility), Token(SyntaxKind.UnsafeKeyword), Token(SyntaxKind.PartialKeyword));

            var proxyClassName = "__MicroCom" + iface.Name + "Proxy";
            var proxy          = ClassDeclaration(proxyClassName)
                                 .AddModifiers(Token(SyntaxKind.UnsafeKeyword), Token(_visibility), Token(SyntaxKind.PartialKeyword))
                                 .WithBaseType(inheritsUnknown ?
                                               "Avalonia.MicroCom.MicroComProxyBase" :
                                               ("__MicroCom" + iface.Inherits + "Proxy"))
                                 .AddBaseListTypes(SimpleBaseType(ParseTypeName(iface.Name)));


            // Generate vtable
            var vtbl = ClassDeclaration("__MicroCom" + iface.Name + "VTable")
                       .AddModifiers(Token(SyntaxKind.UnsafeKeyword));

            vtbl = vtbl.WithBaseType(inheritsUnknown ?
                                     "Avalonia.MicroCom.MicroComVtblBase" :
                                     "__MicroCom" + iface.Inherits + "VTable");

            var vtblCtor = new List <StatementSyntax>();

            for (var idx = 0; idx < iface.Count; idx++)
            {
                GenerateInterfaceMember(iface[idx], ref ifaceDec, ref proxy, ref vtbl, vtblCtor, idx);
            }

            vtbl = vtbl.AddMembers(
                ConstructorDeclaration(vtbl.Identifier.Text)
                .AddModifiers(Token(SyntaxKind.PublicKeyword))
                .WithBody(Block(vtblCtor))
                )
                   .AddMembers(MethodDeclaration(ParseTypeName("void"), "__MicroComModuleInit")
                               .AddModifiers(Token(SyntaxKind.StaticKeyword), Token(SyntaxKind.InternalKeyword))
                               .WithExpressionBody(ArrowExpressionClause(
                                                       ParseExpression("Avalonia.MicroCom.MicroComRuntime.RegisterVTable(typeof(" +
                                                                       iface.Name + "), new " + vtbl.Identifier.Text + "().CreateVTable())")))
                               .WithSemicolonToken(Semicolon()));


            // Finalize proxy code
            proxy = proxy.AddMembers(
                MethodDeclaration(ParseTypeName("void"), "__MicroComModuleInit")
                .AddModifiers(Token(SyntaxKind.StaticKeyword), Token(SyntaxKind.InternalKeyword))
                .WithBody(Block(
                              ParseStatement("Avalonia.MicroCom.MicroComRuntime.Register(typeof(" +
                                             iface.Name + "), new Guid(\"" + guidString + "\"), (p, owns) => new " +
                                             proxyClassName + "(p, owns));")
                              )))
                    .AddMembers(ParseMemberDeclaration("public " + proxyClassName +
                                                       "(IntPtr nativePointer, bool ownsHandle) : base(nativePointer, ownsHandle) {}"))
                    .AddMembers(ParseMemberDeclaration("protected override int VTableSize => base.VTableSize + " +
                                                       iface.Count + ";"));

            ns     = ns.AddMembers(RewriteMethodsToProperties(ifaceDec));
            implNs = implNs.AddMembers(RewriteMethodsToProperties(proxy), RewriteMethodsToProperties(vtbl));
        }