public ICallable Instantiate(BindingContext context, IEnumerable <IBoundDecl> typeArgs, IBoundDecl argType) { bool canInfer; var genericContext = BuildContext(context, BaseType.Type.Parameter.Unbound, argType, ref typeArgs, out canInfer); // bail if we couldn't get the right number of type arguments if ((typeArgs == null) || (TypeParameters.Count != typeArgs.Count())) { return(null); } // create a new bound function type with the type arguments applied FuncType funcType = BaseType.Type.CloneFunc(); TypeBinder.Bind(genericContext, funcType); // make sure the concrete argument types of this instance match what we're actually given if (!DeclComparer.TypesMatch(funcType.Parameter.Bound, argType)) { return(null); } // create a new unbound function with the proper type Function instance = new Function(BaseType.Position, BaseType.BaseName, funcType, BaseType.ParamNames, BaseType.Body.Unbound, typeArgs, canInfer); instance.BindSearchSpace(BaseType.SearchSpace); // don't instantiate it multiple times // note that this must happen *before* the function is bound, in case the // newly instantiated generic function is recursive. context.Compiler.Functions.Add(instance); // bind it with the type arguments in context FunctionBinder.Bind(genericContext, instance); return(instance); }
public void BindAll() { // bind the types of the user functions and add them to the main table foreach (var unbound in mUnbound) { Bind(unbound); } // copy the functions to a queue because binding a function may cause generics // to be instantiated, adding to the collection. // (we don't need to worry about binding the newly added generics, because they // are bound as part of the instantiation process. binding is how the compiler // determines if a generic's type arguments are valid.) mToBind = new Queue <Function>(Functions); // bind the bodies of all of the functions while (mToBind.Count > 0) { var function = mToBind.Dequeue(); var context = new BindingContext(mCompiler, function.SearchSpace); FunctionBinder.Bind(context, function); } }