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))); }
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))); }
public LocalFuncExpr(Position position, IEnumerable <string> paramNames, FuncType type, IUnboundExpr body) { Position = position; ParamNames.AddRange(paramNames); Type = type; Body = body; }
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); } }
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))); }
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); }
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); }
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; }
public Function(Position position, string name, FuncType type, IEnumerable <string> paramNames, IUnboundExpr body) : this(position, name, type, paramNames, body, null, false) { }
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 }))); }
private Intrinsic(string name, FuncType type) { Name = name; FuncType = type; }
private Intrinsic(string name, OpCode opCode, FuncType type) : this(name, type) { OpCodes.Add(opCode); }
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."); }
public ForeignFunction(string name, int id, FuncType type) { Name = name; FuncType = type; ID = id; }