// Typecheck an input for this function, and get the cursor type for an invocation with that input. // arg0 and arg0Type correspond to the input and its type. // The cursor type for aggregate functions is generally the type of a row in the input schema (table), // for example Table in an invocation Average(Table, valueFunction). // Returns true on success, false if the input or its type are invalid with respect to this function's declaration // (and populate the error container accordingly). public virtual bool CheckInput(TexlNode inputNode, DType inputSchema, IErrorContainer errors, out DType typeScope) { Contracts.AssertValue(inputNode); Contracts.Assert(inputSchema.IsValid); Contracts.AssertValue(errors); CallNode callNode = inputNode.Parent.CastList().Parent.CastCall(); Contracts.AssertValue(callNode); typeScope = inputSchema; bool fArgsValid = true; if (_function.ParamTypes.Length == 0) { switch (typeScope.Kind) { case DKind.Record: break; case DKind.Error: fArgsValid = false; errors.EnsureError(inputNode, TexlStrings.ErrBadType); break; default: fArgsValid = false; errors.Error(callNode, TexlStrings.ErrBadType); break; } } else if (_function.ParamTypes[0].IsTable) { if (!typeScope.IsTable) { errors.Error(callNode, TexlStrings.ErrNeedTable_Func, _function.Name); fArgsValid = false; } // This assumes that the lambdas operate on the individual records // of the table, not the entire table. bool fError = false; typeScope = typeScope.ToRecord(ref fError); fArgsValid &= !fError; } else { Contracts.Assert(_function.ParamTypes[0].IsRecord); if (!typeScope.IsRecord) { errors.Error(callNode, TexlStrings.ErrNeedRecord_Func, _function.Name); bool fError = false; typeScope = typeScope.ToRecord(ref fError); fArgsValid = false; } } return(fArgsValid); }
public override bool CheckInvocation(TexlBinding binding, TexlNode[] args, DType[] argTypes, IErrorContainer errors, out DType returnType, out Dictionary <TexlNode, DType> nodeToCoercedTypeMap) { Contracts.AssertValue(args); Contracts.AssertValue(argTypes); Contracts.Assert(args.Length == argTypes.Length); Contracts.AssertValue(errors); bool fArgsValid = base.CheckInvocation(args, argTypes, errors, out returnType, out nodeToCoercedTypeMap); DType arg0Type = argTypes[0]; if (arg0Type.IsTable) { returnType = arg0Type.ToRecord(); } else { returnType = arg0Type.IsRecord ? arg0Type : DType.Error; fArgsValid = false; } return(fArgsValid); }