public void BindAll() { // copy the types to a queue because binding a type may cause // other generic types to be instantiated, adding to the type // table. mToBind = new Queue <INamedType>(mTypes.Values.Where(type => (type is Struct) || (type is Union))); while (mToBind.Count > 0) { INamedType type = mToBind.Dequeue(); //### bob: call the appropriate bind function. this is gross. // should use an overridden method or something. Struct structure = type as Struct; if (structure != null) { TypeBinder.Bind(mCompiler, structure); } else { TypeBinder.Bind(mCompiler, (Union)type); } } mToBind = null; }
private void Bind(Function unbound) { var context = new BindingContext(mCompiler, unbound.SearchSpace); TypeBinder.Bind(context, unbound.Type); Add(unbound); }
//### 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); }
IBoundExpr IUnboundExprVisitor<IBoundExpr>.Visit(FuncRefExpr expr) { IBoundDecl paramType = null; if (expr.ParamType != null) { paramType = TypeBinder.Bind(mContext, expr.ParamType); } var callable = mContext.Compiler.Functions.Find(mContext, expr.Name.Name, expr.Name.TypeArgs, paramType); var function = callable as Function; //### bob: to support intrinsics, we'll need to basically create wrapper functions // that have the same type signature as the intrinsic and that do nothing but // call the intrinsic and return. then, we can get a reference to that wrapper. // // to support foreign functions, we can either do the same thing, or change the // way function references work. if a function reference can be distinguished // between being a regular function, a foreign one (or later a closure), then // we can get rid of ForeignFuncCallExpr and just use CallExpr for foreign calls // too. if (function == null) throw new NotImplementedException("Can only get references to user-defined functions. Intrinsics, auto-generated, and foreign function references aren't supported yet."); return new BoundFuncRefExpr(function); }
private ICallable LookUpFunction(BindingContext context, string fullName, IList <IUnboundDecl> typeArgs, IBoundDecl argType) { // with this line uncommented, the "InferredGenericUsesExplicitType" test // passes, but the self-hosting compiler doesn't compile. the line after // the next will get the compiler to break at a different point (earlier? // later?), but breaks the test // the first line is newer and (i think) correct. the old line is what it was // doing before. var boundTypeArgs = TypeBinder.Bind(context, typeArgs); //var boundTypeArgs = TypeBinder.Bind(new BindingContext(context.Compiler, context.SearchSpace), typeArgs); string uniqueName = Callable.UniqueName(fullName, boundTypeArgs, argType); // try the already bound functions ICallable callable; if (TryFind(fullName, boundTypeArgs, argType, out callable)) { return(callable); } // try to instantiate a generic foreach (var generic in mGenerics) { // names must match if (generic.Name != fullName) { continue; } ICallable instance = generic.Instantiate(context, boundTypeArgs, argType); //### bob: there's a bug here. it doesn't check that the *unique* names of the two functions // match, just the base names. i think this means it could incorrectly collide: // List'Int () // List'Bool () // but i'm not positive if (instance != null) { return(instance); } } // couldn't find it return(null); }
IBoundExpr IUnboundExprVisitor<IBoundExpr>.Visit(ArrayExpr expr) { var elementType = (IBoundDecl)null; if (expr.ElementType != null) { elementType = TypeBinder.Bind(mContext, expr.ElementType); } var elements = expr.Elements.Accept(this); // infer the type from the elements if (elementType == null) { var index = 0; foreach (var element in elements) { if (elementType == null) { // take the type of the first elementType = element.Type; } else { // make sure the others match if (!DeclComparer.TypesMatch(elementType, element.Type)) throw new CompileException(expr.Position, String.Format("Array elements must all be the same type. Array is type {0}, but element {1} is type {2}.", elementType, index, element.Type)); } index++; } } // build a structure for the array var fields = new List<IBoundExpr>(); fields.Add(new IntExpr(expr.Elements.Count)); fields.AddRange(elements); return new BoundTupleExpr(fields, new BoundArrayType(elementType)); }
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 Struct Instantiate(Compiler compiler, IEnumerable <IBoundDecl> typeArgs) { // look for a previously instantiated one var structure = compiler.Types.FindStruct(BaseType.Name, typeArgs); if (structure == null) { // instantiate the structure structure = 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(structure, typeArgs); // immediately bind it with the type arguments BindingContext context = new BindingContext(compiler, structure.SearchSpace, TypeParameters, typeArgs); TypeBinder.Bind(context, structure); } return(structure); }