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