Exemplo n.º 1
0
 protected internal virtual CapnpBoundGenericType VisitClosedType(CapnpBoundGenericType closed)
 {
     closed.OpenType = (CapnpNamedType)Visit(closed.OpenType);
     if (closed.ParentScope != null)
     {
         closed.ParentScope = VisitClosedType(closed.ParentScope);
     }
     return(closed);
 }
Exemplo n.º 2
0
        /// <summary>
        /// Given the generic and its generic parameter bindings, bind for as much as possible any generic parameters in the current
        /// partially open type.
        /// </summary>
        public CapnpBoundGenericType CloseWith(CapnpBoundGenericType generic)
        {
            Debug.Assert(!IsFullyClosed);

            var typeParams = this.TypeParameters.Select(param => param is CapnpGenericParameter ? generic.ResolveGenericParameter((CapnpGenericParameter)param) ?? param
                                                                                             : param).ToArray();

            return(new CapnpBoundGenericType
            {
                OpenType = this.OpenType,
                ParentScope = this.ParentScope == null ? null : this.ParentScope.CloseWith(generic),
                TypeParameters = typeParams
            });
        }
Exemplo n.º 3
0
        private CapnpType _ResolveName(NamePart part, CapnpComposite nameScope, CapnpBoundGenericType genericScope = null)
        {
            var result = _ResolveName(part.Name);

            if (result == null)
            {
                // Todo: this is somewhat "bolted" on, can we unify with generics?
                if (part.Name == "List" && part.TypeParameters.Length == 1)
                {
                    var param = nameScope.ResolveFullName(part.TypeParameters[0]);
                    if (param == null)
                    {
                        return(null);
                    }
                    return(new CapnpList
                    {
                        Parameter = param
                    });
                }
            }

            // E.g. an unresolved Using.
            if (result is CapnpReference)
            {
                return(result);
            }

            if (result is CapnpGenericType)
            {
                // Resolve generic parameters given our generic state.
                // Note that the name could refer to a generic parameter creating a *partially closed* type.
                var generic = (CapnpGenericType)result;

                // We don't allow *partial* closing of a generic type (there's no syntax for it).
                if (generic.TypeParameters.Length != part.TypeParameters.Length && part.TypeParameters.Length > 0)
                {
                    return(null);
                }

                // Nothing to parameterize.
                if (generic.TypeParameters.Length == 0 && part.TypeParameters.Length > 0)
                {
                    return(null);
                }

                // If the type does not actually have generic parameters, and we're not a nested type of a generic type, we're done.
                if (!generic.IsGeneric && genericScope == null)
                {
                    return(result);
                }

                Debug.Assert(generic.TypeParameters.Length == part.TypeParameters.Length || part.TypeParameters.Length == 0);

                var resolvedParams = part.TypeParameters.Length == 0 ? generic.TypeParameters : // the type is fully open
                                     part.TypeParameters.Select(p => nameScope.ResolveFullName(p)).ToArray();

                // If any of the type parameters are unresolved, we have to wait.
                if (resolvedParams.Any(p => p == null || p is CapnpReference))
                {
                    return(null);
                }

                // The generic scope is the scope in which generic parameters our bound.
                // If none are defined the parent scope is closed using just the generic parameters.
                var parentScope = genericScope ?? generic.Scope.MakeOpenGenericType();

                return(new CapnpBoundGenericType
                {
                    OpenType = generic,
                    ParentScope = parentScope,
                    TypeParameters = resolvedParams
                });
            }
            else if (result is CapnpBoundGenericType)
            {
                var closed = (CapnpBoundGenericType)result;

                if (part.TypeParameters.Length > 0 && closed.TypeParameters.Length != part.TypeParameters.Length)
                {
                    return(null);
                }

                var resolvedParams = closed.TypeParameters;

                if (part.TypeParameters.Length > 0)
                {
                    // Cannot be partially closed and it makes no sense to close an already fully closed generic type
                    Debug.Assert(closed.TypeParameters.All(p => (p is CapnpGenericParameter)));

                    resolvedParams = part.TypeParameters.Select(p => nameScope.ResolveFullName(p)).ToArray();
                    if (resolvedParams.Any(p => p == null || p is CapnpReference))
                    {
                        return(null);
                    }
                }

                // Return a new closed generic whose scope is the current genericScope if defined.
                // Note that in the case both genericScope and clode.ParentScope exist, genericScope is "more closed" but point
                // to the same open type.
                Debug.Assert(genericScope == null || closed.ParentScope == null || genericScope.OpenType == closed.ParentScope.OpenType);

                return(new CapnpBoundGenericType
                {
                    OpenType = closed.OpenType,
                    ParentScope = genericScope ?? closed.ParentScope,
                    TypeParameters = resolvedParams
                });
            }
            else if (part.TypeParameters.Length > 0)
            {
                // The name defines generic parameters but the type is not generic.
                return(null);
            }
            else if (result is CapnpGenericParameter)
            {
                return(result);
            }
            else if (genericScope != null)
            {
                // An annotation or enumeration or whatever contained within a generic struct is itself generic.
                return(new CapnpBoundGenericType
                {
                    OpenType = (CapnpNamedType)result,
                    ParentScope = genericScope,
                    TypeParameters = Empty <CapnpType> .Array
                });
            }
            else
            {
                return(result);
            }
        }