public static ATypeInference CreateInstance (ArrayList arguments)
{
- if (RootContext.Version == LanguageVersion.ISO_2)
- return new TypeInferenceV2 (arguments);
-
return new TypeInferenceV3 (arguments);
}
public abstract Type[] InferDelegateArguments (MethodBase method);
}
- //
- // Implements C# 2.0 type inference
- //
- class TypeInferenceV2 : ATypeInference
- {
- public TypeInferenceV2 (ArrayList arguments)
- : base (arguments)
- {
- }
-
- public override Type[] InferDelegateArguments (MethodBase method)
- {
- AParametersCollection pd = TypeManager.GetParameterData (method);
- if (arg_count != pd.Count)
- return null;
-
- Type[] method_args = method.GetGenericArguments ();
- Type[] inferred_types = new Type[method_args.Length];
-
- Type[] param_types = new Type[pd.Count];
- Type[] arg_types = (Type[])arguments.ToArray (typeof (Type));
-
- for (int i = 0; i < arg_count; i++) {
- param_types[i] = pd.Types [i];
- }
-
- if (!InferTypeArguments (param_types, arg_types, inferred_types))
- return null;
-
- return inferred_types;
- }
-
- public override Type[] InferMethodArguments (EmitContext ec, MethodBase method)
- {
- AParametersCollection pd = TypeManager.GetParameterData (method);
- Type[] method_generic_args = method.GetGenericArguments ();
- Type [] inferred_types = new Type [method_generic_args.Length];
- Type[] arg_types = new Type [pd.Count];
-
- int a_count = arg_types.Length;
- if (pd.HasParams)
- --a_count;
-
- for (int i = 0; i < a_count; i++) {
- Argument a = (Argument) arguments[i];
- if (a.Expr is NullLiteral || a.Expr is MethodGroupExpr || a.Expr is AnonymousMethodExpression)
- continue;
-
- if (!TypeInferenceV2.UnifyType (pd.Types [i], a.Type, inferred_types))
- return null;
- }
-
- if (pd.HasParams) {
- Type element_type = TypeManager.GetElementType (pd.Types [a_count]);
- for (int i = a_count; i < arg_count; i++) {
- Argument a = (Argument) arguments [i];
- if (a.Expr is NullLiteral || a.Expr is MethodGroupExpr || a.Expr is AnonymousMethodExpression)
- continue;
-
- if (!TypeInferenceV2.UnifyType (element_type, a.Type, inferred_types))
- return null;
- }
- }
-
- for (int i = 0; i < inferred_types.Length; i++)
- if (inferred_types [i] == null)
- return null;
-
- return inferred_types;
- }
-
- static bool InferTypeArguments (Type[] param_types, Type[] arg_types,
- Type[] inferred_types)
- {
- for (int i = 0; i < arg_types.Length; i++) {
- if (arg_types[i] == null)
- continue;
-
- if (!UnifyType (param_types[i], arg_types[i], inferred_types))
- return false;
- }
-
- for (int i = 0; i < inferred_types.Length; ++i)
- if (inferred_types[i] == null)
- return false;
-
- return true;
- }
-
- public static bool UnifyType (Type pt, Type at, Type[] inferred)
- {
- if (pt.IsGenericParameter) {
- if (pt.DeclaringMethod == null)
- return pt == at;
-
- int pos = pt.GenericParameterPosition;
-
- if (inferred [pos] == null)
- inferred [pos] = at;
-
- return inferred [pos] == at;
- }
-
- if (!pt.ContainsGenericParameters) {
- if (at.ContainsGenericParameters)
- return UnifyType (at, pt, inferred);
- else
- return true;
- }
-
- if (at.IsArray) {
- if (pt.IsArray) {
- if (at.GetArrayRank () != pt.GetArrayRank ())
- return false;
-
- return UnifyType (TypeManager.GetElementType (pt), TypeManager.GetElementType (at), inferred);
- }
-
- if (!pt.IsGenericType)
- return false;
-
- Type gt = pt.GetGenericTypeDefinition ();
- if ((gt != TypeManager.generic_ilist_type) && (gt != TypeManager.generic_icollection_type) &&
- (gt != TypeManager.generic_ienumerable_type))
- return false;
-
- Type[] args = TypeManager.GetTypeArguments (pt);
- return UnifyType (args[0], at.GetElementType (), inferred);
- }
-
- if (pt.IsArray) {
- if (!at.IsArray ||
- (pt.GetArrayRank () != at.GetArrayRank ()))
- return false;
-
- return UnifyType (pt.GetElementType (), at.GetElementType (), inferred);
- }
-
- if (pt.IsByRef && at.IsByRef)
- return UnifyType (pt.GetElementType (), at.GetElementType (), inferred);
- ArrayList list = new ArrayList ();
- if (at.IsGenericType)
- list.Add (at);
- for (Type bt = at.BaseType; bt != null; bt = bt.BaseType)
- list.Add (bt);
-
- list.AddRange (TypeManager.GetInterfaces (at));
-
- foreach (Type type in list) {
- if (!type.IsGenericType)
- continue;
-
- if (TypeManager.DropGenericTypeArguments (pt) != TypeManager.DropGenericTypeArguments (type))
- continue;
-
- if (!UnifyTypes (pt.GetGenericArguments (), type.GetGenericArguments (), inferred))
- return false;
- }
-
- return true;
- }
-
- static bool UnifyTypes (Type[] pts, Type[] ats, Type[] inferred)
- {
- for (int i = 0; i < ats.Length; i++) {
- if (!UnifyType (pts [i], ats [i], inferred))
- return false;
- }
- return true;
- }
- }
-
//
// Implements C# 3.0 type inference
//