TupleTypeSpec ParseTuple()
        {
            TupleTypeSpec tuple = new TupleTypeSpec();

            ConsumeList(tuple.Elements, TypeTokenKind.RightParenthesis, "tuple");
            return(tuple);
        }
        protected override bool LLEquals(TypeSpec other, bool partialNameMatch)
        {
            TupleTypeSpec spec = other as TupleTypeSpec;

            if (spec == null)
            {
                return(false);
            }
            return(ListEqual(Elements, spec.Elements, partialNameMatch));
        }
        static bool ReplaceName(TupleTypeSpec tuple, string toFind, string replacement, ref TypeSpec result)
        {
            List <TypeSpec> resultTypes = new List <TypeSpec> (tuple.Elements.Count);

            if (ReplaceName(tuple.Elements, toFind, replacement, resultTypes))
            {
                result = new TupleTypeSpec(resultTypes);
                return(true);
            }
            result = tuple;
            return(false);
        }
 public TupleTypeSpec(TupleTypeSpec other)
     : base(TypeSpecKind.Tuple)
 {
     Elements = new List <TypeSpec> ();
     Elements.AddRange(other.Elements);
     if (other.HasAttributes)
     {
         Attributes.AddRange(other.Attributes);
     }
     if (other.ContainsGenericParameters)
     {
         GenericParameters.AddRange(other.GenericParameters);
     }
     IsInOut = other.IsInOut;
 }
        public bool IsBoundGeneric(BaseDeclaration context, TypeMapper mapper)
        {
            switch (this.Kind)
            {
            case TypeSpecKind.Named:
                NamedTypeSpec ns = (NamedTypeSpec)this;
                Entity        en = mapper.TryGetEntityForSwiftClassName(ns.Name);
                if (en == null)
                {
                    if (context.IsTypeSpecGeneric(ns))
                    {
                        return(false);                        // unbound
                    }
                }
                foreach (TypeSpec genParm in GenericParameters)
                {
                    if (genParm.IsUnboundGeneric(context, mapper))
                    {
                        return(false);                        // unbound
                    }
                }
                return(true);

            case TypeSpecKind.Closure:
                ClosureTypeSpec cs = (ClosureTypeSpec)this;
                return(cs.Arguments.IsBoundGeneric(context, mapper) && cs.ReturnType.IsBoundGeneric(context, mapper));

            case TypeSpecKind.Tuple:
                TupleTypeSpec ts = (TupleTypeSpec)this;
                foreach (TypeSpec elem in ts.Elements)
                {
                    if (elem.IsUnboundGeneric(context, mapper))
                    {
                        return(false);
                    }
                }
                return(true);

            default:
                throw new NotSupportedException("unknown TypeSpecKind " + this.Kind.ToString());
            }
        }
        public IEnumerable <TypeSpec> EachArgument()
        {
            if (!HasArguments())
            {
                yield break;
            }
            TupleTypeSpec argList = Arguments as TupleTypeSpec;

            if (argList != null)
            {
                foreach (TypeSpec arg in argList.Elements)
                {
                    yield return(arg);
                }
            }
            else
            {
                yield return(Arguments);
            }
        }
        public bool IsUnboundGeneric(BaseDeclaration context, TypeMapper mapper)
        {
            switch (Kind)
            {
            case TypeSpecKind.Named:
                NamedTypeSpec ns = (NamedTypeSpec)this;
                if (context.IsTypeSpecGeneric(ns.ToString()))
                {
                    return(true);
                }
                foreach (TypeSpec genparm in GenericParameters)
                {
                    if (genparm.IsUnboundGeneric(context, mapper))
                    {
                        return(true);
                    }
                }
                return(false);

            case TypeSpecKind.Closure:
                ClosureTypeSpec cs = (ClosureTypeSpec)this;
                return(cs.Arguments.IsUnboundGeneric(context, mapper) && cs.ReturnType.IsUnboundGeneric(context, mapper));

            case TypeSpecKind.Tuple:
                TupleTypeSpec ts = (TupleTypeSpec)this;
                foreach (TypeSpec elem in ts.Elements)
                {
                    if (elem.IsUnboundGeneric(context, mapper))
                    {
                        return(true);
                    }
                }
                return(false);

            case TypeSpecKind.ProtocolList:
                return(false);

            default:
                throw new NotSupportedException("unknown TypeSpecKind " + this.Kind.ToString());
            }
        }
        TypeSpec Parse()
        {
            TypeSpecToken            token = tokenizer.Peek();
            TypeSpec                 type  = null;
            List <TypeSpecAttribute> attrs = null;
            var    inout     = false;
            string typeLabel = null;

            // Prefix

            // parse any attributes
            if (token.Kind == TypeTokenKind.At)
            {
                attrs = ParseAttributes();
                token = tokenizer.Peek();
            }

            // looks like it's inout
            if (token.Kind == TypeTokenKind.TypeName && token.Value == "inout")
            {
                inout = true;
                tokenizer.Next();
                token = tokenizer.Peek();
            }

            if (token.Kind == TypeTokenKind.TypeLabel)
            {
                typeLabel = token.Value;
                tokenizer.Next();
                token = tokenizer.Peek();
            }


            // meat


            if (token.Kind == TypeTokenKind.LeftParenthesis)               // tuple
            {
                tokenizer.Next();
                TupleTypeSpec tuple = ParseTuple();
                type      = tuple.Elements.Count == 1 ? tuple.Elements [0] : tuple;
                typeLabel = type.TypeLabel;
            }
            else if (token.Kind == TypeTokenKind.TypeName)                 // name
            {
                tokenizer.Next();
                var tokenValue = token.Value.StartsWith("ObjectiveC.", StringComparison.Ordinal) ?
                                 "Foundation" + token.Value.Substring("ObjectiveC".Length) : token.Value;
                type = new NamedTypeSpec(tokenValue);
            }
            else if (token.Kind == TypeTokenKind.LeftBracket)                 // array
            {
                tokenizer.Next();
                type = ParseArray();
            }
            else                 // illegal
            {
                throw ErrorHelper.CreateError(ReflectorError.kTypeParseBase + 0, $"Unexpected token {token.Value}.");
            }

            // look-ahead for closure
            if (tokenizer.Peek().Kind == TypeTokenKind.TypeName && tokenizer.Peek().Value == "throws")
            {
                tokenizer.Next();
                if (tokenizer.Peek().Kind != TypeTokenKind.Arrow)
                {
                    throw ErrorHelper.CreateError(ReflectorError.kTypeParseBase + 1, $"Unexpected token {tokenizer.Peek ().Value} after a 'throws' in a closure.");
                }
                tokenizer.Next();
                type = ParseClosure(type, true);
            }

            if (tokenizer.Peek().Kind == TypeTokenKind.Arrow)
            {
                tokenizer.Next();
                type = ParseClosure(type, false);
            }
            else if (tokenizer.Peek().Kind == TypeTokenKind.LeftAngle)
            {
                tokenizer.Next();
                type = Genericize(type);
            }

            if (tokenizer.Peek().Kind == TypeTokenKind.Period)
            {
                tokenizer.Next();
                var currType = type as NamedTypeSpec;
                if (currType == null)
                {
                    throw ErrorHelper.CreateError(ReflectorError.kTypeParseBase + 2, $"In parsing an inner type (type.type), first element is a {type.Kind} instead of a NamedTypeSpec.");
                }
                var nextType = Parse() as NamedTypeSpec;
                if (nextType == null)
                {
                    throw ErrorHelper.CreateError(ReflectorError.kTypeParseBase + 3, $"In parsing an inner type (type.type), the second element is a {nextType.Kind} instead of a NamedTypeSpec");
                }
                currType.InnerType = nextType;
            }

            // Postfix

            if (tokenizer.Peek().Kind == TypeTokenKind.Ampersand)
            {
                type = ParseProtocolList(type as NamedTypeSpec);
            }

            while (tokenizer.Peek().Kind == TypeTokenKind.QuestionMark)
            {
                tokenizer.Next();
                type = WrapAsBoundGeneric(type, "Swift.Optional");
            }

            if (tokenizer.Peek().Kind == TypeTokenKind.ExclamationPoint)
            {
                tokenizer.Next();
                type = WrapAsBoundGeneric(type, "Swift.ImplicitlyUnwrappedOptional");
            }

            type.IsInOut   = inout;
            type.TypeLabel = typeLabel;

            if (type != null && attrs != null)
            {
                type.Attributes.AddRange(attrs);
            }

            return(type);
        }