private IEnumerable <StatementSyntax> BuildDelegateBody(CppFunction cppFunction, TypeInfo returnTypeInfo)
        {
            yield return(SyntaxBuilder.DeclareLocals(false));

            var delegates = new Dictionary <string, string>();

            foreach (var cppParameter in cppFunction.Parameters)
            {
                if (!TypeMap.TryResolveType(cppParameter.Type, out var paramTypeInfo, false))
                {
                    throw new ArgumentException();
                }

                if (!paramTypeInfo.IsFunction)
                {
                    continue;
                }

                var managedParameterName = GetManagedName(cppParameter.Name);
                var variableName         = managedParameterName + "Ptr";
                delegates.Add(cppParameter.Name, variableName);
                yield return(SyntaxBuilder.DeclareDelegatePointerVariable(managedParameterName, variableName));
            }

            var call =
                InvocationExpression(IdentifierName(GetManagedName(cppFunction.Name) + "Private"))
                .AddArgumentListArguments(cppFunction.Parameters.Select(BuildArgument).ToArray());

            if (returnTypeInfo.IsVoid)
            {
                yield return(ExpressionStatement(call));
            }
            else
            {
                yield return(LocalDeclarationStatement(
                                 VariableDeclaration(returnTypeInfo.TypeSyntax)
                                 .AddVariables(VariableDeclarator("result").WithInitializer(
                                                   EqualsValueClause(call)))));
            }

            foreach (var cppParameter in cppFunction.Parameters.Reverse())
            {
                if (delegates.ContainsKey(cppParameter.Name))
                {
                    var managedParameterName = GetManagedName(cppParameter.Name);
                    yield return(SyntaxBuilder.CallKeepAlive(IdentifierName(managedParameterName)));
                }
            }

            if (!returnTypeInfo.IsVoid)
            {
                yield return(ReturnStatement(IdentifierName("result")));
            }

            ArgumentSyntax BuildArgument(CppParameter cppParameter)
            {
                var name = delegates.TryGetValue(cppParameter.Name, out string paramName)
                    ? paramName
                    : GetManagedName(cppParameter.Name);

                return(Argument(IdentifierName(name)));
            }
        }