/// <summary>
        /// Infers the types of the given collection of named type arguments from the given collection
        /// of parameters.
        /// </summary>
        /// <param name="typeArgNames">The names of the type parameters.</param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public static IList <IBoundDecl> Infer(IEnumerable <string> typeParameters,
                                               IUnboundDecl parameterType,
                                               IBoundDecl argType)
        {
            var inferrer = new TypeArgInferrer(typeParameters);

            inferrer.mParamTypes.Push(parameterType);
            bool dummy = argType.Accept(inferrer);

            inferrer.mParamTypes.Pop();

            // if the inference failed (like from a type collision) then fail
            if (inferrer.mFailed)
            {
                return(null);
            }

            // if any type argument is left unfilled then fail
            if (inferrer.mTypeArguments.Contains(null))
            {
                return(null);
            }

            return(inferrer.mTypeArguments);
        }
Example #2
0
        public BindingContext BuildContext(BindingContext callingContext,
                                           IUnboundDecl parameterType, IBoundDecl argType,
                                           ref IEnumerable <IBoundDecl> typeArgs, out bool canInferArgs)
        {
            // try to infer the args if not passed in
            IList <IBoundDecl> inferredTypeArgs = TypeArgInferrer.Infer(TypeParameters,
                                                                        parameterType, argType);

            canInferArgs = inferredTypeArgs != null;

            if (canInferArgs)
            {
                typeArgs = inferredTypeArgs;
            }

            if (typeArgs.IsEmpty())
            {
                typeArgs = null;
            }

            // include the open namespaces of the calling context. this was the instantiated
            // generic has access to everything that the instantiation call site has access
            // to
            var searchSpace = new NameSearchSpace(BaseType.SearchSpace, callingContext.SearchSpace);

            return(new BindingContext(callingContext.Compiler, searchSpace, TypeParameters, typeArgs));
        }
Example #3
0
        //### bob: this is basically a copy from Struct :(
        public Union Instantiate(Compiler compiler, IEnumerable <IBoundDecl> typeArgs)
        {
            // look for a previously instantiated one
            var union = compiler.Types.FindUnion(BaseType.Name, typeArgs);

            if (union == null)
            {
                // instantiate the structure
                union = BaseType.Clone(typeArgs);

                // add it to the list of known types. this must happen before
                // the subsequent binding in case the type is recursive.
                compiler.Types.Add(union, typeArgs);

                // immediately bind it with the type arguments
                BindingContext context = new BindingContext(compiler, union.SearchSpace, TypeParameters, typeArgs);
                TypeBinder.Bind(context, union);

                // figure out which of the cases can infer type arguments. this
                // needs to be done now while we still know the type parameters
                // and the unbound uses of them in the cases.
                for (int i = 0; i < union.Cases.Count; i++)
                {
                    var inferredTypeArgs = TypeArgInferrer.Infer(TypeParameters,
                                                                 BaseType.Cases[i].ValueType.Unbound,
                                                                 union.Cases[i].ValueType.Bound);

                    union.Cases[i].HasInferrableTypeArguments = inferredTypeArgs != null;
                }
            }

            return(union);
        }