Beispiel #1
0
        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);
        }
Beispiel #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);
        }
        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);
        }