Exemplo n.º 1
0
        void GatherGenerics(TypeMapper typeMapper, FunctionDeclaration func, SLImportModules modules, TypeSpec type,
                            SLGenericTypeDeclarationCollection genericDecl, Dictionary <string, List <BaseConstraint> > redundantConstraints)
        {
            if (!func.IsTypeSpecGeneric(type))
            {
                return;
            }

            if (type.ContainsGenericParameters)
            {
                var entity = typeMapper.GetEntityForTypeSpec(type);
                if (entity != null)
                {
                    for (int i = 0; i < entity.Type.Generics.Count; i++)
                    {
                        var genDecl             = entity.Type.Generics [i];
                        var originalGenTypeSpec = type.GenericParameters [i];
                        if (originalGenTypeSpec is NamedTypeSpec named)
                        {
                            var depthIndex = func.GetGenericDepthAndIndex(originalGenTypeSpec);
                            if (depthIndex.Item1 < 0 || depthIndex.Item2 < 0)
                            {
                                continue;
                            }
                            var genRef     = new SLGenericReferenceType(depthIndex.Item1, depthIndex.Item2);
                            var genRefName = genRef.Name;
                            List <BaseConstraint> constList = null;
                            if (!redundantConstraints.TryGetValue(genRefName, out constList))
                            {
                                constList = new List <BaseConstraint> ();
                                redundantConstraints.Add(genRefName, constList);
                            }
                            constList.AddRange(genDecl.Constraints);
                        }
                        else if (originalGenTypeSpec is ClosureTypeSpec closure)
                        {
                            GatherGenerics(typeMapper, func, modules, closure.Arguments, genericDecl, redundantConstraints);
                            GatherGenerics(typeMapper, func, modules, closure.ReturnType, genericDecl, redundantConstraints);
                        }
                        else if (originalGenTypeSpec is TupleTypeSpec tuple)
                        {
                            foreach (var tupleSpec in tuple.Elements)
                            {
                                GatherGenerics(typeMapper, func, modules, tupleSpec, genericDecl, redundantConstraints);
                            }
                        }
                    }
                }
                foreach (var subType in type.GenericParameters)
                {
                    GatherGenerics(typeMapper, func, modules, subType, genericDecl, redundantConstraints);
                }
            }
            else
            {
                if (type is NamedTypeSpec named)
                {
                    var depthIndex = func.GetGenericDepthAndIndex(type);
                    var gd         = func.GetGeneric(depthIndex.Item1, depthIndex.Item2);
                    var genRef     = new SLGenericReferenceType(depthIndex.Item1, depthIndex.Item2);
                    var sldecl     = new SLGenericTypeDeclaration(new SLIdentifier(genRef.Name));
#if SWIFT4
                    if (depthIndex.Item1 >= func.GetMaxDepth())
                    {
                        sldecl.Constraints.AddRange(gd.Constraints.Select(baseConstraint =>
                                                                          MethodWrapping.ToSLGenericConstraint(func, baseConstraint, genRef.ToString())
                                                                          ));
                    }
#else
                    sldecl.Constraints.AddRange(gd.Constraints.Select(bc => {
                        InheritanceConstraint inh = bc as InheritanceConstraint;
                        if (inh == null)
                        {
                            throw new CompilerException("Equality constraints not supported (yet)");
                        }
                        return(new SLGenericConstraint(true, new SLSimpleType(genRef.Name), parent.TypeSpecMapper.MapType(func, modules, inh.InheritsTypeSpec)));
                    }));
#endif
                    genericDecl.Add(sldecl);
                }
                else if (type is ClosureTypeSpec closure)
                {
                    GatherGenerics(typeMapper, func, modules, closure.Arguments, genericDecl, redundantConstraints);
                    GatherGenerics(typeMapper, func, modules, closure.ReturnType, genericDecl, redundantConstraints);
                }
                else if (type is TupleTypeSpec tuple)
                {
                    foreach (var tupleSpec in tuple.Elements)
                    {
                        GatherGenerics(typeMapper, func, modules, tupleSpec, genericDecl, redundantConstraints);
                    }
                }
            }
        }