private RppMethodInfo FindGenericConstructor(RType targetType, out RType inferredType) { inferredType = null; IReadOnlyList<RppMethodInfo> constructors = targetType.Constructors; foreach (RppMethodInfo constructor in constructors) { if (NeedToInferGenericArguments(targetType)) { var genericParameters = targetType.GenericParameters; List<RType> argTypes = ArgsTypes.ToList(); var inferredTypeArguments = InferGenericArguments(genericParameters, argTypes, constructor.Parameters.Select(p => p.Type)); if (inferredTypeArguments.Any(t => t.IsUndefined())) { continue; } RType inflatedType = targetType.MakeGenericType(inferredTypeArguments); var matchingConstructors = FindConstructors(inflatedType); if (matchingConstructors.Count > 1) { throw SemanticExceptionFactory.AmbiguousReferenceToOverloadedDefinition(Token, matchingConstructors, argTypes); } if (matchingConstructors.Count == 1) { inferredType = inflatedType; return matchingConstructors.First(); } } } throw SemanticExceptionFactory.SomethingWentWrong(Token); }
public void TestSpecializedGenericTypesEquality() { // class Foo[T](val id: T) // class SecondFoo[A](id: Int, val name: A) extends Foo[Int](id) RType fooTy = new RType("Foo"); fooTy.DefineGenericParameters("T"); RType intFooTy = fooTy.MakeGenericType(IntTy); RType secondTy = new RType("SecondFoo"); secondTy.DefineGenericParameters("A"); secondTy.BaseType = intFooTy; Assert.IsTrue(secondTy.IsGenericType); Assert.IsTrue(secondTy.IsGenericTypeDefinition); Assert.IsTrue(intFooTy.IsAssignable(secondTy)); }
public void TestOneGenericContainerWith2DistinctClasses() { // class List[A] // class Apple // class Orange // listOfApples = new List[Apple]() // listOfOranges = new List[Orange]() RType listTy = new RType("List"); listTy.DefineGenericParameters("A"); RType appleTy = new RType("Apple"); RType listOfApplesTy = listTy.MakeGenericType(appleTy); RType orangeTy = new RType("Orange"); RType listOfOrangesTy = listTy.MakeGenericType(orangeTy); Assert.IsFalse(listOfOrangesTy.IsAssignable(listOfApplesTy)); Assert.IsFalse(listOfApplesTy.IsAssignable(listOfOrangesTy)); Assert.IsTrue(listOfOrangesTy.IsAssignable(listOfOrangesTy)); }
public void TestAssigningNothing() { RType optionTy = new RType("Option"); RppGenericParameter[] genericParameters = optionTy.DefineGenericParameters("A"); genericParameters[0].Variance = RppGenericParameterVariance.Covariant; RType nothingOptionTy = optionTy.MakeGenericType(NothingTy); RType stringOptionTy = optionTy.MakeGenericType(StringTy); Assert.IsTrue(stringOptionTy.IsAssignable(nothingOptionTy)); }
public void ExtendingSpecializedGenericAndDefineOneMoreGenericParameter() { // class Foo[T] // class SecondFoo[A] extends Foo[Int] // Foo[Int] = SecondFoo[String] RType fooTy = new RType("Foo"); fooTy.DefineGenericParameters("T"); RType intFooTy = fooTy.MakeGenericType(IntTy); RType secondFooTy = new RType("SecondFoo", RTypeAttributes.Class, intFooTy); Assert.IsTrue(intFooTy.IsAssignable(secondFooTy)); }
/// <summary> /// Creates 2 types, List[Fruit] and List[Apple], where: /// <code> /// class List[A] /// class Fruit /// class Apple extends Fruit /// </code> /// </summary> /// <param name="variance">variance type for type argument <code>'A'</code></param> /// <param name="listOfFruits"></param> /// <param name="listOfApples"></param> private static void CreateTypes(RppGenericParameterVariance variance, out RType listOfFruits, out RType listOfApples) { RType listTy = new RType("List"); RppGenericParameter[] genericParameters = listTy.DefineGenericParameters("A"); genericParameters[0].Variance = variance; RType fruitTy = new RType("Fruit"); RType listOfFruitsTy = listTy.MakeGenericType(fruitTy); RType appleTy = new RType("Apple", RTypeAttributes.Class, fruitTy); listOfApples = listTy.MakeGenericType(appleTy); listOfFruits = listOfFruitsTy; }
public void InflateSimpleGeneric() { /* class Foo[A,B]{ def get(x: A, y: B): B } */ RType fooTy = new RType("Foo"); RppGenericParameter[] gp = fooTy.DefineGenericParameters("A", "B"); fooTy.DefineMethod("get", RMethodAttributes.Public, gp[0].Type, new[] {new RppParameterInfo(gp[0].Type), new RppParameterInfo(gp[1].Type)}); // Foo[Int, Float] RType specializedFooTy = fooTy.MakeGenericType(IntTy, FloatTy); // get(x: Int) : Float RppMethodInfo getMethod = specializedFooTy.Methods[0]; Assert.AreEqual(IntTy, getMethod.ReturnType); Assert.AreEqual(IntTy, getMethod.Parameters[0].Type); Assert.AreEqual(FloatTy, getMethod.Parameters[1].Type); }
public void InflateClassWithGenericBaseType() { /* class Foo[A, B] { def get(x: A) : B } class Bar[A, B, C] extends Foo[A, B] { def map(x: A, y: B) : C } */ RType fooTy = new RType("Foo"); { RppGenericParameter[] gp = fooTy.DefineGenericParameters("X", "Y"); fooTy.DefineMethod("get", RMethodAttributes.Public, gp[1].Type, new[] {new RppParameterInfo(gp[0].Type)}); } RType barTy = new RType("Bar"); RppGenericParameter[] barGp = barTy.DefineGenericParameters("A", "B", "C"); barTy.DefineMethod("map", RMethodAttributes.Public, barGp[2].Type, new[] { new RppParameterInfo(barGp[0].Type), new RppParameterInfo(barGp[1].Type) }); barTy.BaseType = fooTy.MakeGenericType(barGp[0].Type, barGp[1].Type); RType specilizedBarTy = barTy.MakeGenericType(IntTy, FloatTy, StringTy); Assert.IsNotNull(specilizedBarTy.BaseType); IReadOnlyCollection<RType> barGenericArguments = specilizedBarTy.GenericArguments; CollectionAssert.AreEqual(new[] {IntTy, FloatTy, StringTy}, barGenericArguments.ToList()); var fooGenericArguments = specilizedBarTy.BaseType.GenericArguments; CollectionAssert.AreEqual(new[] {IntTy, FloatTy}, fooGenericArguments.ToList()); RppMethodInfo getMethod = specilizedBarTy.BaseType.Methods[0]; Assert.AreEqual(FloatTy, getMethod.ReturnType); Assert.AreEqual(IntTy, getMethod.Parameters[0].Type); }
private RType SubstitutedType(RType type) { if (type.IsGenericParameter) { return GetGenericArgument(type); } if (type.IsGenericType) { RType[] mappedGenericArguments; // Generictype definition is an RType which contains generic params // Inflated type doesn't contain generic params but contains generic arguments // So for RType we should use GenericParameters and for RInflatedType - GenericArguments if (type.IsGenericTypeDefinition) { mappedGenericArguments = type.GenericParameters.Select(ga => _genericArguments[ga.Position]).ToArray(); } else { mappedGenericArguments = type.GenericArguments.Select(ga => _genericArguments[ga.GenericParameterPosition]).ToArray(); } var substitutedType = type.MakeGenericType(mappedGenericArguments); return substitutedType; } return type; }