public override bool CheckInvocation(TexlBinding binding, TexlNode[] args, DType[] argTypes, IErrorContainer errors, out DType returnType, out Dictionary <TexlNode, DType> nodeToCoercedTypeMap) { Contracts.AssertValue(binding); 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); int count = args.Length; nodeToCoercedTypeMap = null; // Check the predicates. bool fArgsValid = true; DType type = ReturnType; bool isBehavior = binding.IsBehavior; Contracts.Assert(type == DType.Unknown); for (int i = 0; i < count;) { TexlNode nodeArg = args[i]; DType typeArg = argTypes[i]; if (typeArg.IsError) { errors.EnsureError(args[i], TexlStrings.ErrTypeError); } DType typeSuper = DType.Supertype(type, typeArg); if (!typeSuper.IsError) { type = typeSuper; } else if (type.Kind == DKind.Unknown) { // One of the args is also of unknown type, so we can't resolve the type of IfError type = typeSuper; fArgsValid = false; } else if (!type.IsError) { // Types don't resolve normally, coercion needed if (typeArg.CoercesTo(type)) { CollectionUtils.Add(ref nodeToCoercedTypeMap, nodeArg, type); } else if (!isBehavior || !IsArgTypeInconsequential(nodeArg)) { errors.EnsureError(DocumentErrorSeverity.Severe, nodeArg, TexlStrings.ErrBadType_ExpectedType_ProvidedType, type.GetKindString(), typeArg.GetKindString()); fArgsValid = false; } } else if (typeArg.Kind != DKind.Unknown) { type = typeArg; fArgsValid = false; } // If there are an odd number of args, the last arg also participates. i += 2; if (i == count) { i--; } } returnType = type; return(fArgsValid); }
public override bool CheckInvocation(TexlBinding binding, TexlNode[] args, DType[] argTypes, IErrorContainer errors, out DType returnType, out Dictionary <TexlNode, DType> nodeToCoercedTypeMap) { Contracts.AssertValue(binding); 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); int count = args.Length; nodeToCoercedTypeMap = null; // Check the predicates. bool fArgsValid = true; for (int i = 0; i < (count & ~1); i += 2) { bool withCoercion; fArgsValid &= CheckType(args[i], argTypes[i], DType.Boolean, errors, true, out withCoercion); if (withCoercion) { CollectionUtils.Add(ref nodeToCoercedTypeMap, args[i], DType.Boolean); } } DType type = ReturnType; // Are we on a behavior property? bool isBehavior = binding.IsBehavior; // Compute the result type by joining the types of all non-predicate args. Contracts.Assert(type == DType.Unknown); for (int i = 1; i < count;) { TexlNode nodeArg = args[i]; DType typeArg = argTypes[i]; if (typeArg.IsError) { errors.EnsureError(args[i], TexlStrings.ErrTypeError); } DType typeSuper = DType.Supertype(type, typeArg); if (!typeSuper.IsError) { type = typeSuper; } else if (type.Kind == DKind.Unknown) { type = typeSuper; fArgsValid = false; } else if (!type.IsError) { if (typeArg.CoercesTo(type)) { CollectionUtils.Add(ref nodeToCoercedTypeMap, nodeArg, type); } else if (!isBehavior || !IsArgTypeInconsequential(nodeArg)) { errors.EnsureError(DocumentErrorSeverity.Severe, nodeArg, TexlStrings.ErrBadType_ExpectedType_ProvidedType, type.GetKindString(), typeArg.GetKindString()); fArgsValid = false; } } else if (typeArg.Kind != DKind.Unknown) { type = typeArg; fArgsValid = false; } // If there are an odd number of args, the last arg also participates. i += 2; if (i == count) { i--; } } // Update the return type based on the specified invocation args. returnType = type; 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.Assert(args.Length >= 1); Contracts.AssertValue(errors); nodeToCoercedTypeMap = null; int count = args.Length; bool fArgsValid = true; bool fArgsNonNull = false; DType type = ReturnType; for (int i = 0; i < count; i++) { TexlNode nodeArg = args[i]; DType typeArg = argTypes[i]; if (typeArg.Kind == DKind.ObjNull) { continue; } fArgsNonNull = true; if (typeArg.IsError) { errors.EnsureError(args[i], TexlStrings.ErrTypeError); } DType typeSuper = DType.Supertype(type, typeArg); if (!typeSuper.IsError) { type = typeSuper; } else if (type.Kind == DKind.Unknown) { // One of the args is also of unknown type, so we can't resolve the type of IfError type = typeSuper; fArgsValid = false; } else if (!type.IsError) { // Types don't resolve normally, coercion needed if (typeArg.CoercesTo(type)) { CollectionUtils.Add(ref nodeToCoercedTypeMap, nodeArg, type); } else { errors.EnsureError(DocumentErrorSeverity.Severe, nodeArg, TexlStrings.ErrBadType_ExpectedType_ProvidedType, type.GetKindString(), typeArg.GetKindString()); fArgsValid = false; } } else if (typeArg.Kind != DKind.Unknown) { type = typeArg; fArgsValid = false; } } if (!fArgsNonNull) { type = DType.ObjNull; } returnType = type; return(fArgsValid); }