예제 #1
0
            public ICallable Instantiate(BindingContext context, IEnumerable <IBoundDecl> typeArgs,
                                         IBoundDecl argType)
            {
                // should have two args: an int and an array
                var argTuple = argType as BoundTupleType;

                if (argTuple == null)
                {
                    return(null);
                }

                if (argTuple.Fields[0] != Decl.Int)
                {
                    return(null);
                }

                var arrayType = argTuple.Fields[1] as BoundArrayType;

                if (arrayType == null)
                {
                    return(null);
                }

                // make the intrinsic
                return(new Intrinsic("__Call", OpCode.LoadArray, FuncType.Create(argTuple, arrayType.ElementType)));
            }
예제 #2
0
            public ICallable Instantiate(BindingContext context, IEnumerable <IBoundDecl> typeArgs,
                                         IBoundDecl argType)
            {
                // should have three args: an int, an array, and a value
                var argTuple = argType as BoundTupleType;

                if (argTuple == null)
                {
                    return(null);
                }

                // index
                if (argTuple.Fields[0] != Decl.Int)
                {
                    return(null);
                }

                // array
                var arrayType = argTuple.Fields[1] as BoundArrayType;

                if (arrayType == null)
                {
                    return(null);
                }

                // value
                if (!DeclComparer.TypesMatch(argTuple.Fields[2], arrayType.ElementType))
                {
                    return(null);
                }

                // make the intrinsic
                return(new Intrinsic("__Call<-", OpCode.StoreArray, FuncType.Create(argTuple, Decl.Unit)));
            }
예제 #3
0
 public LocalFuncExpr(Position position, IEnumerable <string> paramNames, FuncType type, IUnboundExpr body)
 {
     Position = position;
     ParamNames.AddRange(paramNames);
     Type = type;
     Body = body;
 }
예제 #4
0
 public static void Bind(BindingContext context, FuncType func)
 {
     // do nothing if already bound. some functions such as intrinsics or
     // auto-functions are created in bound form.
     if (!func.Parameter.IsBound)
     {
         var binder = MakeBinder(context);
         func.Parameter.Bind(binder);
         func.Return.Bind(binder);
     }
 }
예제 #5
0
            public ICallable Instantiate(BindingContext context, IEnumerable <IBoundDecl> typeArgs,
                                         IBoundDecl argType)
            {
                var arrayType = argType as BoundArrayType;

                if (arrayType == null)
                {
                    return(null);
                }

                // make the intrinsic
                return(new Intrinsic("Size", OpCode.SizeArray, FuncType.Create(arrayType, Decl.Int)));
            }
예제 #6
0
        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);
        }
예제 #7
0
        bool IBoundDeclVisitor <bool> .Visit(FuncType decl)
        {
            if (!TryInferParam(decl))
            {
                FuncType paramFunc = ParamType as FuncType;
                if (paramFunc == null)
                {
                    mFailed = true;
                    return(false);
                }

                mParamTypes.Push(paramFunc.Parameter.Unbound);
                decl.Parameter.Bound.Accept(this);
                mParamTypes.Pop();

                mParamTypes.Push(paramFunc.Return.Unbound);
                decl.Return.Bound.Accept(this);
                mParamTypes.Pop();
            }

            return(false);
        }
예제 #8
0
        public Function(Position position, string name, FuncType type, IEnumerable <string> paramNames, IUnboundExpr body,
                        IEnumerable <IBoundDecl> typeArgs, bool hasInferrableTypeArguments)
            : base(position, name, typeArgs)
        {
            if (position == null)
            {
                throw new ArgumentNullException("position");
            }
            if (type == null)
            {
                throw new ArgumentNullException("type");
            }

            if (paramNames != null)
            {
                ParamNames.AddRange(paramNames);
            }

            Body = new Expr(body);

            Type = type;
            HasInferrableTypeArguments = hasInferrableTypeArguments;
        }
예제 #9
0
 public Function(Position position, string name, FuncType type, IEnumerable <string> paramNames, IUnboundExpr body)
     : this(position, name, type, paramNames, body, null, false)
 {
 }
예제 #10
0
        public static IBoundExpr EqualInt(IBoundExpr left, IBoundExpr right)
        {
            var intrinsic = new Intrinsic("=", OpCode.EqualInt, FuncType.Create(Decl.Int, Decl.Int, Decl.Bool));

            return(intrinsic.CreateCall(new BoundTupleExpr(new IBoundExpr[] { left, right })));
        }
예제 #11
0
 private Intrinsic(string name, FuncType type)
 {
     Name     = name;
     FuncType = type;
 }
예제 #12
0
 private Intrinsic(string name, OpCode opCode, FuncType type)
     : this(name, type)
 {
     OpCodes.Add(opCode);
 }
예제 #13
0
        IBoundExpr IUnboundExprVisitor<IBoundExpr>.Visit(CallExpr expr)
        {
            var namedTarget = expr.Target as NameExpr;

            // see if it's a macro call before binding the arg
            if ((namedTarget != null) && (mContext.Compiler.MacroProcessor != null))
            {
                IUnboundExpr macroResult = mContext.Compiler.MacroProcessor.Process(namedTarget.Name, expr.Arg);

                // if it was a macro call, bind the result of it
                if (macroResult != null) return macroResult.Accept(this);
            }

            //### bob: handle array constructors. hack! should be intrinsic
            if ((namedTarget != null) && (namedTarget.Name == "ArrayOf"))
            {
                // handle ArrayOf[Int]
                if ((expr.Arg is UnitExpr) && (namedTarget.TypeArgs.Count == 1))
                {
                    return new ArrayExpr(namedTarget.Position, namedTarget.TypeArgs[0]).Accept(this);
                }

                // handle ArrayOf (1, 2, 3)
                var elements = (IEnumerable<IUnboundExpr>)(new IUnboundExpr[] { expr.Arg });
                if (expr.Arg is TupleExpr)
                {
                    elements = ((TupleExpr)expr.Arg).Fields;
                }

                return new ArrayExpr(namedTarget.Position, elements).Accept(this);
            }

            var boundArg = expr.Arg.Accept(this);

            // see if we're accessing a record field
            BoundRecordType recordType = boundArg.Type as BoundRecordType;
            if ((namedTarget != null) &&
                (recordType != null) &&
                recordType.Fields.ContainsKey(namedTarget.Name))
            {
                // find the index of the field
                //### bob: ToList() here is a gross hack.
                var index = recordType.Fields.Keys.ToList().IndexOf(namedTarget.Name);

                // bind it
                return new LoadExpr(boundArg, recordType.Fields[namedTarget.Name], index);
            }

            if (namedTarget != null)
            {
                return mContext.ResolveName(mFunction, Scope, namedTarget.Position,
                    namedTarget.Name, namedTarget.TypeArgs, boundArg);
            }

            IBoundExpr target = expr.Target.Accept(this);

            // see if we're calling a function
            FuncType funcType = target.Type as FuncType;
            if (funcType != null)
            {
                // check that args match
                if (!DeclComparer.TypesMatch(funcType.Parameter.Bound, boundArg.Type))
                {
                    throw new CompileException(expr.Position, "Argument types passed to evaluated function reference do not match function's parameter types.");
                }

                // simply apply the arg to the bound expression
                return new BoundCallExpr(target, boundArg);
            }

            // see if we're accessing a tuple field
            var tupleType = boundArg.Type as BoundTupleType;
            if ((tupleType != null) && (target.Type == Decl.Int))
            {
                var index = target as IntExpr;
                if (index == null) throw new CompileException(expr.Position, "Tuple fields can only be accessed using a literal index, not an int expression.");

                // make sure the field is in range
                if ((index.Value < 0) || (index.Value >= tupleType.Fields.Count))
                    throw new CompileException(expr.Position, String.Format("Cannot access field {0} because the tuple only has {1} fields.", index.Value, tupleType.Fields.Count));

                // bind it
                return new LoadExpr(boundArg, tupleType.Fields[index.Value], index.Value);
            }

            // not calling a function, so try to desugar to a __Call
            var callArg = new BoundTupleExpr(new IBoundExpr[] { target, boundArg });

            var call = mContext.ResolveFunction(mFunction, expr.Target.Position,
                "__Call", new IUnboundDecl[0], callArg);

            if (call != null) return call;

            throw new CompileException(expr.Position, "Target of call is not a function.");
        }
예제 #14
0
 public ForeignFunction(string name, int id, FuncType type)
 {
     Name     = name;
     FuncType = type;
     ID       = id;
 }