Beispiel #1
0
        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);
        }
Beispiel #2
0
        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);
        }
Beispiel #3
0
        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);
        }
Beispiel #4
0
        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);
        }
Beispiel #5
0
        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);
        }
Beispiel #6
0
        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);
            }
        }
Beispiel #7
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.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);
        }
Beispiel #8
0
 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)
 {
 }
Beispiel #9
0
        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);
        }
Beispiel #10
0
 /// <returns>
 /// The <see cref="DType"/> of a collection of error values
 /// </returns>
 public static DType ReifiedErrorTable() => DType.CreateTable(ReifiedErrorSchema);
Beispiel #11
0
        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);
        }
Beispiel #12
0
 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)
 {
 }
Beispiel #13
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);
        }
Beispiel #14
0
        public static AllowedValuesMetadata CreateForValue(DType valueType)
        {
            Contracts.Assert(valueType.IsValid);

            return(new AllowedValuesMetadata(DType.CreateTable(new TypedName(valueType, ValueColumnName))));
        }