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.Assert(args.Length >= 2); Contracts.AssertValue(errors); nodeToCoercedTypeMap = null; int count = args.Length; bool hasTableArg = false; bool fArgsValid = true; // Type check the args // If any one input argument is of table type, then the returnType will be table type. for (int i = 0; i < count; i++) { bool isTable; fArgsValid &= CheckParamIsTypeOrSingleColumnTable(DType.String, args[i], argTypes[i], errors, out isTable, ref nodeToCoercedTypeMap); hasTableArg |= isTable; } returnType = hasTableArg ? DType.CreateTable(new TypedName(DType.String, OneColumnTableResultName)) : DType.String; 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.AssertAllValues(args); Contracts.AssertValue(argTypes); Contracts.Assert(args.Length == argTypes.Length); Contracts.AssertValue(errors); bool fArgsValid = base.CheckInvocation(args, argTypes, errors, out returnType, out nodeToCoercedTypeMap); if (argTypes[1].IsRecord) { returnType = argTypes[1].ToTable(); } else if (argTypes[1].IsPrimitive || argTypes[1].IsTable) { returnType = DType.CreateTable(new TypedName(argTypes[1], ColumnName_Value)); } else { returnType = DType.Error; 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.AssertAllValues(args); Contracts.AssertValue(argTypes); Contracts.Assert(args.Length == argTypes.Length); Contracts.AssertValue(errors); Contracts.Assert(MinArity <= args.Length && args.Length <= MaxArity); bool fValid = base.CheckInvocation(args, argTypes, errors, out returnType, out nodeToCoercedTypeMap); DType type0 = argTypes[0]; DType type1 = argTypes[1]; DType otherType = DType.Invalid; TexlNode otherArg = null; // At least one of the arguments has to be a table. if (type0.IsTable) { // Ensure we have a one-column table of colors. fValid &= CheckColorColumnType(type0, args[0], errors, ref nodeToCoercedTypeMap); // Borrow the return type from the 1st arg. returnType = type0; // Check arg1 below. otherArg = args[1]; otherType = type1; fValid &= CheckOtherType(otherType, otherArg, DType.Number, errors, ref nodeToCoercedTypeMap); Contracts.Assert(returnType.IsTable); Contracts.Assert(!fValid || returnType.IsColumn); } else if (type1.IsTable) { // Ensure we have a one-column table of numerics. fValid &= CheckNumericColumnType(type1, args[1], errors, ref nodeToCoercedTypeMap); // Since the 1st arg is not a table, make a new table return type *[Result:c] returnType = DType.CreateTable(new TypedName(DType.Color, OneColumnTableResultName)); // Check arg0 below. otherArg = args[0]; otherType = type0; fValid &= CheckOtherType(otherType, otherArg, DType.Color, errors, ref nodeToCoercedTypeMap); Contracts.Assert(returnType.IsTable); Contracts.Assert(!fValid || returnType.IsColumn); } else { Contracts.Assert(returnType.IsTable); errors.EnsureError(DocumentErrorSeverity.Severe, args[0], TexlStrings.ErrTypeError_Ex1_Ex2_Found, TableKindString, DType.Color.GetKindString(), type0.GetKindString()); errors.EnsureError(DocumentErrorSeverity.Severe, args[1], TexlStrings.ErrTypeError_Ex1_Ex2_Found, TableKindString, DType.Number.GetKindString(), type1.GetKindString()); // Both args are invalid. No need to continue. return(false); } return(fValid); }
public override bool CheckInvocation(TexlBinding binding, TexlNode[] args, DType[] argTypes, IErrorContainer errors, out DType returnType, out Dictionary <TexlNode, DType> nodeToCoercedTypeMap) { Contracts.AssertValue(args); Contracts.AssertAllValues(args); Contracts.AssertValue(argTypes); Contracts.Assert(args.Length == argTypes.Length); Contracts.Assert(args.Length == 2); Contracts.AssertValue(errors); bool fValid = base.CheckInvocation(args, argTypes, errors, out returnType, out nodeToCoercedTypeMap); Contracts.Assert(returnType.IsTable); returnType = DType.CreateTable(new TypedName(DType.String, OneColumnTableResultName)); return(fValid); }
public override bool CheckInvocation(TexlBinding binding, TexlNode[] args, DType[] argTypes, IErrorContainer errors, out DType returnType, out Dictionary <TexlNode, DType> nodeToCoercedTypeMap) { Contracts.AssertValue(args); Contracts.AssertAllValues(args); Contracts.AssertValue(argTypes); Contracts.Assert(args.Length == argTypes.Length); Contracts.AssertValue(errors); Contracts.Assert(MinArity <= args.Length && args.Length <= MaxArity); bool fValid = base.CheckInvocation(args, argTypes, errors, out returnType, out nodeToCoercedTypeMap); Contracts.Assert(returnType.IsTable); // Typecheck the input table fValid &= CheckStringColumnType(argTypes[0], args[0], errors, ref nodeToCoercedTypeMap); // Synthesize a new return type returnType = DType.CreateTable(new TypedName(DType.Number, OneColumnTableResultName)); return(fValid); }
internal static void AddSuggestionsForNamesInType(DType type, IntellisenseData.IntellisenseData data, bool createTableSuggestion) { Contracts.AssertValid(type); Contracts.AssertValue(data); foreach (var field in type.GetNames(DPath.Root)) { var usedName = field.Name; string maybeDisplayName; if (DType.TryGetDisplayNameForColumn(type, usedName, out maybeDisplayName)) { usedName = new DName(maybeDisplayName); } DType suggestionType = field.Type; if (createTableSuggestion) { suggestionType = DType.CreateTable(new TypedName(type, usedName)); } AddSuggestion(data, usedName.Value, SuggestionKind.Field, SuggestionIconKind.Other, suggestionType, requiresSuggestionEscaping: true); } }
public override bool CheckInvocation(TexlNode[] args, DType[] argTypes, IErrorContainer errors, out DType returnType, out Dictionary <TexlNode, DType> nodeToCoercedTypeMap) { Contracts.AssertValue(args); Contracts.AssertAllValues(args); Contracts.AssertValue(argTypes); Contracts.Assert(args.Length == argTypes.Length); Contracts.Assert(args.Length == 1); Contracts.AssertValue(errors); var reifiedError = ErrorType.ReifiedError(); var acceptedFields = reifiedError.GetNames(DPath.Root); var requiredKindField = acceptedFields.Where(tn => tn.Name == "Kind").First(); Contracts.Assert(requiredKindField.Type.IsEnum); var optionalFields = acceptedFields.Where(tn => tn.Name != "Kind"); returnType = DType.ObjNull; nodeToCoercedTypeMap = null; var argument = args[0]; var argumentType = argTypes[0]; if (argumentType.Kind != DKind.Record && argumentType.Kind != DKind.Table) { errors.EnsureError(argument, TexlStrings.ErrBadType); return(false); } // We cache the whole name list regardless of path. var names = argumentType.GetNames(DPath.Root).ToArray(); // First handle required fields (currently only 'Kind') if (!names.Any(field => field.Name == requiredKindField.Name)) { // Kind is required, point it out to the maker, and specify the enumeration type. errors.EnsureError( argument, TexlStrings.ErrBadSchema_ExpectedType, reifiedError.GetKindString()); errors.Error( argument, TexlStrings.ErrColumnMissing_ColName_ExpectedType, requiredKindField.Name.Value, "ErrorKind"); return(false); } var argumentKindType = names.First(tn => tn.Name == requiredKindField.Name).Type; if (!argumentKindType.CoercesTo(requiredKindField.Type)) { errors.EnsureError( argument, TexlStrings.ErrBadSchema_ExpectedType, reifiedError.GetKindString()); errors.Error( argument, TexlStrings.ErrBadRecordFieldType_FieldName_ExpectedType, requiredKindField.Name.Value, "ErrorKind"); return(false); } bool valid = true; var record = argument.AsRecord(); foreach (var name in names) { if (!acceptedFields.Any(field => field.Name == name.Name)) { // If they have a record literal, we can position the errors for rejected fields. if (record != null) { errors.EnsureError(record.Children.Where((_, i) => record.Ids[i].Name == name.Name).FirstOrDefault() ?? record, TexlStrings.ErrErrorIrrelevantField); } else { errors.EnsureError(argument, TexlStrings.ErrErrorIrrelevantField); } valid = false; } } bool matchedWithCoercion; bool typeValid; if (argumentType.Kind == DKind.Record) { // A record with the proper types for the fields that are specified. var expectedOptionalFieldsRecord = DType.CreateRecord( acceptedFields.Where(field => // Kind has already been handled before field.Name != "Kind" && names.Any(name => name.Name == field.Name))); typeValid = CheckType(argument, argumentType, expectedOptionalFieldsRecord, errors, true, out matchedWithCoercion); } else { // A table with the proper types for the fields that are specified. var expectedOptionalFieldsTable = DType.CreateTable( acceptedFields.Where(field => // Kind has already been handled before field.Name != "Kind" && names.Any(name => name.Name == field.Name))); typeValid = CheckType(argument, argumentType, expectedOptionalFieldsTable, errors, true, out matchedWithCoercion); } if (!typeValid) { errors.EnsureError(DocumentErrorSeverity.Severe, argument, TexlStrings.ErrTypeError); valid = false; } else if (matchedWithCoercion && valid) { var recordOrTableSchema = acceptedFields.Where(field => names.Any(name => name.Name == field.Name)); var expectedRecordOrTable = argumentType.Kind == DKind.Record ? DType.CreateRecord(recordOrTableSchema) : DType.CreateTable(recordOrTableSchema); CollectionUtils.Add(ref nodeToCoercedTypeMap, argument, expectedRecordOrTable); } return(valid); }
public SequenceFunction() : base("Sequence", TexlStrings.AboutSequence, FunctionCategories.MathAndStat, DType.CreateTable(new TypedName(DType.Number, new DName("Value"))), 0, 1, 3, DType.Number, DType.Number, DType.Number) { }
public override bool CheckInvocation(TexlBinding binding, TexlNode[] args, DType[] argTypes, IErrorContainer errors, out DType returnType, out Dictionary <TexlNode, DType> nodeToCoercedTypeMap) { Contracts.AssertValue(args); Contracts.AssertAllValues(args); Contracts.AssertValue(argTypes); Contracts.Assert(args.Length == argTypes.Length); Contracts.AssertValue(errors); Contracts.Assert(MinArity <= args.Length && args.Length <= MaxArity); bool fValid = base.CheckInvocation(args, argTypes, errors, out returnType, out nodeToCoercedTypeMap); DType type0 = argTypes[0]; DType type1 = argTypes[1]; DType type2 = argTypes[2]; // Arg0 should be either a string or a column of strings. // Its type dictates the function return type. if (type0.IsTable) { // Ensure we have a one-column table of strings fValid &= CheckStringColumnType(type0, args[0], errors, ref nodeToCoercedTypeMap); // Borrow the return type from the 1st arg returnType = type0; } else { returnType = DType.CreateTable(new TypedName(DType.String, OneColumnTableResultName)); if (!DType.String.Accepts(type0)) { if (type0.CoercesTo(DType.String)) { CollectionUtils.Add(ref nodeToCoercedTypeMap, args[0], DType.String); } else { fValid = false; errors.EnsureError(DocumentErrorSeverity.Severe, args[0], TexlStrings.ErrStringExpected); } } } // Arg1 should be either a string or a column of strings. if (type1.IsTable) { fValid &= CheckStringColumnType(type1, args[1], errors, ref nodeToCoercedTypeMap); } else if (!DType.String.Accepts(type1)) { if (type1.CoercesTo(DType.String)) { CollectionUtils.Add(ref nodeToCoercedTypeMap, args[1], DType.String); } else { fValid = false; errors.EnsureError(DocumentErrorSeverity.Severe, args[1], TexlStrings.ErrStringExpected); } } // Arg2 should be either a string or a column of strings. if (type2.IsTable) { fValid &= CheckStringColumnType(type2, args[2], errors, ref nodeToCoercedTypeMap); } else if (!DType.String.Accepts(type2)) { if (type2.CoercesTo(DType.String)) { CollectionUtils.Add(ref nodeToCoercedTypeMap, args[2], DType.String); } else { fValid = false; errors.EnsureError(DocumentErrorSeverity.Severe, args[2], TexlStrings.ErrStringExpected); } } bool hasCount = args.Length == 4; if (hasCount) { DType type3 = argTypes[3]; // Arg3 should be either a number or a column of numbers. if (type3.IsTable) { fValid &= CheckNumericColumnType(type3, args[3], errors, ref nodeToCoercedTypeMap); } else if (!DType.Number.Accepts(type3)) { if (type3.CoercesTo(DType.Number)) { CollectionUtils.Add(ref nodeToCoercedTypeMap, args[3], DType.Number); } else { fValid = false; errors.EnsureError(DocumentErrorSeverity.Severe, args[3], TexlStrings.ErrNumberExpected); } } } // At least one arg has to be a table. if (!(type0.IsTable || type1.IsTable || type2.IsTable) && (!hasCount || !argTypes[3].IsTable)) { fValid = false; errors.EnsureError(DocumentErrorSeverity.Severe, args[0], TexlStrings.ErrTypeError); errors.EnsureError(DocumentErrorSeverity.Severe, args[1], TexlStrings.ErrTypeError); errors.EnsureError(DocumentErrorSeverity.Severe, args[2], TexlStrings.ErrTypeError); if (hasCount) { errors.EnsureError(DocumentErrorSeverity.Severe, args[3], TexlStrings.ErrTypeError); } } return(fValid); }
/// <returns> /// The <see cref="DType"/> of a collection of error values /// </returns> public static DType ReifiedErrorTable() => DType.CreateTable(ReifiedErrorSchema);
public override bool CheckInvocation(TexlBinding binding, TexlNode[] args, DType[] argTypes, IErrorContainer errors, out DType returnType, out Dictionary <TexlNode, DType> nodeToCoercedTypeMap) { Contracts.AssertValue(args); Contracts.AssertAllValues(args); Contracts.AssertValue(argTypes); Contracts.Assert(args.Length == argTypes.Length); Contracts.AssertValue(errors); Contracts.Assert(MinArity <= args.Length && args.Length <= MaxArity); bool fValid = base.CheckInvocation(args, argTypes, errors, out returnType, out nodeToCoercedTypeMap); DType type0 = argTypes[0]; DType type1 = argTypes[1]; returnType = DType.CreateTable(new TypedName(DType.Number, OneColumnTableResultName)); // Arg0 should be either a date or a column of dates. if (type0.IsTable) { // Ensure we have a one-column table of dates fValid &= CheckDateColumnType(type0, args[0], errors, ref nodeToCoercedTypeMap); } else if (!DType.DateTime.Accepts(type0)) { if (type0.CoercesTo(DType.DateTime)) { CollectionUtils.Add(ref nodeToCoercedTypeMap, args[0], DType.DateTime); } else { fValid = false; errors.EnsureError(DocumentErrorSeverity.Severe, args[0], TexlStrings.ErrDateExpected); } } // Arg1 should be either a a date or a column of dates. if (type1.IsTable) { // Ensure we have a one-column table of dates fValid &= CheckDateColumnType(type1, args[1], errors, ref nodeToCoercedTypeMap); } else if (!DType.DateTime.Accepts(type1)) { if (type1.CoercesTo(DType.DateTime)) { CollectionUtils.Add(ref nodeToCoercedTypeMap, args[1], DType.DateTime); } else { fValid = false; errors.EnsureError(DocumentErrorSeverity.Severe, args[1], TexlStrings.ErrDateExpected); } } bool hasUnits = args.Length == 3; if (hasUnits && !DType.String.Accepts(argTypes[2])) { // Arg2 should be a string fValid = false; errors.EnsureError(DocumentErrorSeverity.Severe, args[2], TexlStrings.ErrStringExpected); } // At least one arg has to be a table. if (!(type0.IsTable || type1.IsTable)) { fValid = false; errors.EnsureError(DocumentErrorSeverity.Severe, args[0], TexlStrings.ErrTypeError); errors.EnsureError(DocumentErrorSeverity.Severe, args[1], TexlStrings.ErrTypeError); } return(fValid); }
public ClockFunction(string functionInvariantName, TexlStrings.StringGetter functionDescription) : base(new DPath().Append(new DName(LanguageConstants.InvariantClockNamespace)), functionInvariantName, functionDescription, FunctionCategories.DateTime, DType.CreateTable(new TypedName(DType.String, new DName("Value"))), 0, 0, 0) { }
public override bool CheckInvocation(TexlNode[] args, DType[] argTypes, IErrorContainer errors, out DType returnType, out Dictionary <TexlNode, DType> nodeToCoercedTypeMap) { Contracts.AssertValue(args); Contracts.AssertAllValues(args); Contracts.AssertValue(argTypes); Contracts.Assert(args.Length == argTypes.Length); Contracts.AssertValue(errors); Contracts.Assert(MinArity <= args.Length && args.Length <= MaxArity); bool fValid = base.CheckInvocation(args, argTypes, errors, out returnType, out nodeToCoercedTypeMap); DType type0 = argTypes[0]; DType type1 = argTypes[1]; TexlNode arg0 = args[0]; TexlNode arg1 = args[1]; // Arg0 should be either a number or a column of number (coercion is ok). bool matchedWithCoercion; if (type0.IsTable) { // Ensure we have a one-column table of numbers. fValid &= CheckNumericColumnType(type0, arg0, errors, ref nodeToCoercedTypeMap); } else if (CheckType(arg0, type0, DType.Number, DefaultErrorContainer, out matchedWithCoercion)) { if (matchedWithCoercion) { CollectionUtils.Add(ref nodeToCoercedTypeMap, arg0, DType.Number); } } else { fValid = false; errors.EnsureError(DocumentErrorSeverity.Severe, arg0, TexlStrings.ErrNumberExpected); } // Arg1 should be either a number or a column of number (coercion is ok). if (type1.IsTable) { fValid &= CheckNumericColumnType(type1, arg1, errors, ref nodeToCoercedTypeMap); } else if (CheckType(arg1, type1, DType.Number, DefaultErrorContainer, out matchedWithCoercion)) { if (matchedWithCoercion) { CollectionUtils.Add(ref nodeToCoercedTypeMap, arg1, DType.Number); } } else { fValid = false; errors.EnsureError(DocumentErrorSeverity.Severe, arg1, TexlStrings.ErrNumberExpected); } returnType = DType.CreateTable(new TypedName(DType.Number, OneColumnTableResultName)); // At least one arg has to be a table. if (!(type0.IsTable || type1.IsTable)) { fValid = false; } if (!fValid) { nodeToCoercedTypeMap = null; } return(fValid); }
public static AllowedValuesMetadata CreateForValue(DType valueType) { Contracts.Assert(valueType.IsValid); return(new AllowedValuesMetadata(DType.CreateTable(new TypedName(valueType, ValueColumnName)))); }