示例#1
0
文件: RppNew.cs 项目: dubik/csharprpp
        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);
        }
示例#2
0
        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));
        }
示例#3
0
        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));
        }
示例#4
0
        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));
        }
示例#5
0
        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));
        }
示例#6
0
        /// <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;
        }
示例#7
0
        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);
        }
示例#8
0
        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);
        }
示例#9
0
        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;
        }