void GenerateParameterList(DModule module, ParameterInfo[] parameters)
 {
     module.Write("(");
     {
         string prefix = "";
         foreach (ParameterInfo parameter in parameters)
         {
             module.Write("{0}{1} {2}", prefix, ToDEquivalentType(parameter.ParameterType), Util.ToDIdentifier(parameter.Name));
             prefix = ", ";
         }
     }
     module.Write(")");
 }
 void GenerateGenericParameters(DModule module, Type[] genericArgs, UInt16 inheritedGenericArgCount)
 {
     if (genericArgs != null && inheritedGenericArgCount < genericArgs.Length)
     {
         module.Write("(");
         string prefix = "";
         // we skip inherited generic args because they will be in the containing template
         for (Int32 i = inheritedGenericArgCount; i < genericArgs.Length; i++)
         {
             Type t = genericArgs[i];
             module.Write("{0}{1}", prefix, t.Name);
             prefix = ", ";
         }
         module.Write(")");
     }
 }
 // TODO: remove this?
 void GenerateGenericTypeSpecsExpression(DModule module, String linePrefix, Type[] genericArgs)
 {
     if (genericArgs.IsEmpty())
     {
         module.Write("null");
     }
     else
     {
         module.WriteLine("[");
         foreach (Type genericArg in genericArgs)
         {
             module.WriteLine("{0}    __d.clrbridge.GetTypeSpec!({1}),", linePrefix, ToDEquivalentType(genericArg));
         }
         module.Write("{0}]", linePrefix);
     }
 }
 void GenerateMetadata(DModule module, Type type, Type[] genericArgs)
 {
     module.WriteLine("    static struct __clrmetadata");
     module.WriteLine("    {");
     module.Write("        enum typeSpec = ");
     GenerateTypeSpecExpression(module, "            ", type, genericArgs);
     module.WriteLine(";");
     module.WriteLine("    }");
 }
 void GenerateDelegate(DModule module, Type type)
 {
     module.Write("/* .NET Delegate */ static struct {0}", Util.GetUnqualifiedTypeName(type));
     Type[] genericArgs = type.GetGenericArguments();
     GenerateGenericParameters(module, genericArgs, type.DeclaringType.GetGenericArgCount());
     module.WriteLine();
     module.WriteLine("{");
     module.WriteLine("    // TODO: generate delegate members");
     module.WriteLine("}");
 }
 void GenerateParameterTypeSpecExpression(DModule module, String linePrefix, ParameterInfo[] paramInfos)
 {
     if (paramInfos.IsEmpty())
     {
         module.Write("null");
     }
     else
     {
         module.WriteLine("[");
         String subTypePrefix = linePrefix + "        ";
         foreach (ParameterInfo paramInfo in paramInfos)
         {
             //module.WriteLine("{0}   {1},", linePrefix, TypeSpecReference(paramInfo.ParameterType));
             module.Write("{0}    /* param '{1}' */", linePrefix, paramInfo.Name);
             GenerateTypeSpecExpression(module, subTypePrefix, paramInfo.ParameterType);
             module.WriteLine(",");
         }
         module.Write("{0}]", linePrefix);
     }
 }
    void GenerateTypeSpecExpression(DModule module, String linePrefix, Type type, Type[] genericArgs)
    {
        if (type.IsGenericParameter)
        {
            Debug.Assert(genericArgs.IsEmpty(), "you can have a generic parameter type with generic args??");
            module.Write("__d.clrbridge.GetTypeSpec!({0})", ToDEquivalentType(type));
            return;
        }
        module.WriteLine("__d.clr.TypeSpec(");
        module.WriteLine("{0}\"{1}\",", linePrefix, type.Assembly.FullName);
        bool hasGenerics = !genericArgs.IsEmpty();

        module.Write("{0}\"{1}\"{2}", linePrefix, type.FullName, hasGenerics ? ", [" : ")", type.Name);
        if (hasGenerics)
        {
            module.WriteLine();
            foreach (Type genericArg in genericArgs)
            {
                module.WriteLine("{0}    __d.clrbridge.GetTypeSpec!({1}),", linePrefix, ToDEquivalentType(genericArg));
            }
            module.Write("{0}])", linePrefix);
        }
    }
 void GenerateClass(DModule module, Type type)
 {
     module.Write("/* .NET class */ static struct {0}", Util.GetUnqualifiedTypeName(type));
     Type[] genericArgs = type.GetGenericArguments();
     GenerateGenericParameters(module, genericArgs, type.DeclaringType.GetGenericArgCount());
     module.WriteLine();
     module.WriteLine("{");
     module.WriteLine("    // TODO: mixin the base class rather than DotNetObject");
     module.WriteLine("    mixin __d.clrbridge.DotNetObjectMixin!\"__d.clr.DotNetObject\";");
     // generate metadata, one reason for this is so that when this type is used as a template parameter, we can
     // get the .NET name for this type
     GenerateMetadata(module, type, genericArgs);
     GenerateFields(module, type);
     GenerateMethods(module, type);
     GenerateSubTypes(module, type);
     module.WriteLine("}");
 }
    void GenerateMethodBody(DModule module, Type type,
                            MethodBase method, Type returnType, ParameterInfo[] parameters)
    {
        // skip non-static methods for now, they just take too long right now
        if (!method.IsStatic && !method.IsConstructor)
        {
            if (returnType != typeof(void))
            {
                module.WriteLine("        return typeof(return).init;");
            }
            return;
        }
        // TODO: we may want to cache some of this stuff, but for now we'll just get it every time
        Type[] genericArgs = method.IsGenericMethod ? method.GetGenericArguments() : null;
        module.WriteLine("        enum __method_spec__ = __d.clrbridge.MethodSpec(__clrmetadata.typeSpec, \"{0}\",", method.Name);
        module.Write("            /* generic args */ ");
        GenerateGenericTypeSpecsExpression(module, "            ", genericArgs);
        module.Write(", /* parameter types */ ");
        GenerateParameterTypeSpecExpression(module, "            ", parameters);
        module.WriteLine(");");

        String methodTypeString = method.IsConstructor ? "Constructor" : "Method";

        // Get Assembly so we can get Type then Method (TODO: cache this somehow?)
        module.WriteLine("        const  __this_type__ = __d.globalClrBridge.getClosedType!(__clrmetadata.typeSpec);");
        module.WriteLine("        scope (exit) __this_type__.finalRelease(__d.globalClrBridge);");
        module.WriteLine("        assert(__method_spec__.genericTypes.length == 0, \"methods with generic args not implemented\");");
        // TODO: use getClosedMethod and getClosedConstructor
        module.WriteLine("        const __method__ = __d.globalClrBridge.get{0}(__this_type__.type,", methodTypeString);
        if (!method.IsConstructor)
        {
            module.WriteLine("            __d.CStringLiteral!\"{0}\",", method.Name);
        }
        module.WriteLine("            __d.globalClrBridge.getTypesArray!(__method_spec__.paramTypes)());");
        module.WriteLine("        scope (exit) { __d.globalClrBridge.release(__method__); }");

        //
        // Create parameters ObjectArray
        //
        {
            uint paramIndex = 0;
            foreach (ParameterInfo parameter in parameters)
            {
                if (parameter.ParameterType.IsArray ||
                    parameter.ParameterType.IsByRef ||
                    parameter.ParameterType.IsPointer)
                {
                    // skip complicated types for now
                }
                else
                {
                    String boxType = TryGetBoxType(parameter.ParameterType);
                    if (boxType != null)
                    {
                        module.WriteLine("        auto  __param{0}__ = __d.globalClrBridge.box!(__d.clr.PrimitiveType.{1})({2}); // actual type is {3}",
                                         paramIndex, boxType, Util.ToDIdentifier(parameter.Name), Util.GetQualifiedTypeName(parameter.ParameterType));
                        module.WriteLine("        scope (exit) __d.globalClrBridge.release(__param{0}__);", paramIndex);
                    }
                }
                paramIndex++;
            }
        }
        if (parameters.Length == 0)
        {
            module.WriteLine("        __d.ObjectArray __param_values__ = __d.ObjectArray.nullObject;");
        }
        else
        {
            module.WriteLine("        __d.ObjectArray __param_values__ = __d.globalClrBridge.makeObjectArray(");
            {
                uint   paramIndex = 0;
                string prefix     = " ";
                foreach (ParameterInfo parameter in parameters)
                {
                    if (TryGetBoxType(parameter.ParameterType) != null)
                    {
                        module.WriteLine("            {0}__param{1}__", prefix, paramIndex);
                    }
                    else
                    {
                        module.WriteLine("            {0}{1}", prefix, Util.ToDIdentifier(parameter.Name));
                    }
                    prefix = ",";
                    paramIndex++;
                }
            }
            module.WriteLine("        );");
            module.WriteLine("        scope (exit) { __d.globalClrBridge.release(__param_values__); }");
        }
        String returnValueAddrString;

        if (returnType == typeof(void))
        {
            returnValueAddrString = "null";
        }
        else
        {
            returnValueAddrString = "cast(void**)&__return_value__";
            if (returnType == typeof(Boolean))
            {
                module.WriteLine("        ushort __return_value__;");
            }
            else
            {
                module.WriteLine("        typeof(return) __return_value__;");
            }
        }

        if (method.IsConstructor)
        {
            module.WriteLine("        __return_value__ = cast(typeof(return))__d.globalClrBridge.callConstructor(__method__, __param_values__);");
        }
        else
        {
            module.WriteLine("        __d.globalClrBridge.funcs.CallGeneric(__method__, __d.clr.DotNetObject.nullObject, __param_values__, {0});", returnValueAddrString);
        }

        if (returnType == typeof(Boolean))
        {
            module.WriteLine("        return (__return_value__ == 0) ? false : true;");
        }
        else if (returnType != typeof(void))
        {
            module.WriteLine("        return __return_value__;");
        }
    }
    void GenerateMethods(DModule module, Type type)
    {
        foreach (ConstructorInfo constructor in type.GetConstructors())
        {
            if (type.IsValueType)
            {
                continue; // script structs for now
            }
            Debug.Assert(constructor.GetGenericArguments().IsEmpty(), "constructors can have generic arguments?");
            module.Write("    {0} static typeof(this) New", constructor.IsPrivate ? "private" : "public");
            ParameterInfo[] parameters = constructor.GetParameters();
            GenerateParameterList(module, parameters);
            module.WriteLine();
            module.WriteLine("    {");
            GenerateMethodBody(module, type, constructor, type, parameters);
            module.WriteLine("    }");
        }
        foreach (MethodInfo method in type.GetMethods())
        {
            //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
            // skip virtual methods for now so we don't get linker errors
            if (method.IsVirtual)
            {
                continue;
            }

            module.Write("    {0}", method.IsPrivate ? "private" : "public");
            if (method.IsStatic)
            {
                module.Write(" static");
            }
            else if (method.IsFinal)
            {
                module.Write(" final");
            }

            Type[] genericArguments = method.GetGenericArguments();
            Debug.Assert(method.ReturnType != null);
            if (method.ReturnType == typeof(void))
            {
                module.Write(" void");
            }
            else
            {
                module.Write(" {0}", ToDEquivalentType(method.ReturnType));
            }
            module.Write(" {0}", Util.ToDIdentifier(method.Name));
            ParameterInfo[] parameters = method.GetParameters();
            GenerateGenericParameters(module, genericArguments, type.GetGenericArgCount());
            GenerateParameterList(module, parameters);
            if (method.IsVirtual)
            {
                module.WriteLine(";");
                continue;
            }
            module.WriteLine();
            module.WriteLine("    {");
            GenerateMethodBody(module, type, method, method.ReturnType, parameters);
            module.WriteLine("    }");
        }
    }