/// <summary> /// Checks the validity of an assignment of a source to a destination, with arguments. /// </summary> /// <param name="parameterTableList">The list of expected parameters.</param> /// <param name="resultTableList">The list of results.</param> /// <param name="argumentList">The list of actual arguments.</param> /// <param name="sourceExpression">Expression in the assignment.</param> /// <param name="destinationType">The expected type for the expression.</param> /// <param name="errorList">The list of errors found.</param> /// <param name="source">The source to use when reporting errors.</param> /// <param name="featureCall">Details of the feature call.</param> public static bool CheckAssignmentConformance(IList <ISealableList <IParameter> > parameterTableList, IList <ISealableList <IParameter> > resultTableList, IList <IArgument> argumentList, IExpression sourceExpression, ICompiledType destinationType, IErrorList errorList, ISource source, out IFeatureCall featureCall) { featureCall = null; IResultType SourceResult = sourceExpression.ResolvedResult.Item; List <IExpressionType> MergedArgumentList = new List <IExpressionType>(); if (!Argument.Validate(argumentList, MergedArgumentList, out TypeArgumentStyles TypeArgumentStyle, errorList)) { return(false); } if (!Argument.ArgumentsConformToParameters(parameterTableList, MergedArgumentList, TypeArgumentStyle, errorList, source, out int SelectedIndex)) { return(false); } if (SourceResult.Count != 1) { errorList.AddError(new ErrorInvalidExpression(sourceExpression)); return(false); } ISealableList <IParameter> SelectedParameterList = parameterTableList[SelectedIndex]; ISealableList <IParameter> SelectedResultList = resultTableList[SelectedIndex]; ICompiledType SourceType = SourceResult.At(0).ValueType; if (!ObjectType.TypeConformToBase(SourceType, destinationType, errorList, sourceExpression, isConversionAllowed: true)) { errorList.AddError(new ErrorInvalidExpression(sourceExpression)); return(false); } featureCall = new FeatureCall(SelectedParameterList, SelectedResultList, argumentList, MergedArgumentList, TypeArgumentStyle); return(true); }
/// <summary> /// Finds the matching nodes of a <see cref="IBinaryOperatorExpression"/>. /// </summary> /// <param name="node">The agent expression to check.</param> /// <param name="errorList">The list of errors found.</param> /// <param name="resolvedResult">The expression result types upon return.</param> /// <param name="resolvedException">Exceptions the expression can throw upon return.</param> /// <param name="constantSourceList">Sources of the constant expression upon return, if any.</param> /// <param name="expressionConstant">The constant value upon return, if any.</param> /// <param name="selectedFeature">The matching feature upon return.</param> /// <param name="selectedOverload">The matching overload in <paramref name="selectedFeature"/> upon return.</param> /// <param name="featureCall">Details of the feature call.</param> public static bool ResolveCompilerReferences(IBinaryOperatorExpression node, IErrorList errorList, out IResultType resolvedResult, out IResultException resolvedException, out ISealableList <IExpression> constantSourceList, out ILanguageConstant expressionConstant, out IFunctionFeature selectedFeature, out IQueryOverload selectedOverload, out IFeatureCall featureCall) { resolvedResult = null; resolvedException = null; constantSourceList = new SealableList <IExpression>(); expressionConstant = NeutralLanguageConstant.NotConstant; selectedFeature = null; selectedOverload = null; featureCall = null; IExpression LeftExpression = (IExpression)node.LeftExpression; IIdentifier Operator = (IIdentifier)node.Operator; IExpression RightExpression = (IExpression)node.RightExpression; IResultType LeftResult = LeftExpression.ResolvedResult.Item; if (LeftResult.TryGetResult(out ICompiledType LeftExpressionType)) { if (LeftExpressionType is IClassType AsClassType) { string OperatorName = Operator.ValidText.Item; ISealableDictionary <IFeatureName, IFeatureInstance> LeftFeatureTable = AsClassType.FeatureTable; if (!FeatureName.TableContain(LeftFeatureTable, OperatorName, out IFeatureName Key, out IFeatureInstance Value)) { errorList.AddError(new ErrorUnknownIdentifier(Operator, OperatorName)); return(false); } Debug.Assert(Value.Feature != null); ICompiledFeature OperatorFeature = Value.Feature; ICompiledType OperatorType = OperatorFeature.ResolvedAgentType.Item; if (OperatorFeature is IFunctionFeature AsFunctionFeature && OperatorType is FunctionType AsFunctionType) { IList <ISealableList <IParameter> > ParameterTableList = new List <ISealableList <IParameter> >(); foreach (IQueryOverloadType Overload in AsFunctionType.OverloadList) { ParameterTableList.Add(Overload.ParameterTable); } IResultType RightResult = RightExpression.ResolvedResult.Item; if (!Argument.ArgumentsConformToParameters(ParameterTableList, RightResult.ToList(), TypeArgumentStyles.Positional, errorList, Operator, out int SelectedIndex)) { return(false); } IQueryOverloadType SelectedOverloadType = AsFunctionType.OverloadList[SelectedIndex]; resolvedResult = new ResultType(SelectedOverloadType.ResultTypeList); selectedFeature = AsFunctionFeature; selectedOverload = AsFunctionFeature.OverloadList[SelectedIndex]; IArgument FirstArgument = new PositionalArgument(RightExpression); IList <IArgument> ArgumentList = new List <IArgument>() { FirstArgument }; List <IExpressionType> MergedArgumentList = new List <IExpressionType>(); bool IsArgumentValid = Argument.Validate(ArgumentList, MergedArgumentList, out TypeArgumentStyles TypeArgumentStyle, errorList); Debug.Assert(IsArgumentValid); featureCall = new FeatureCall(SelectedOverloadType.ParameterTable, SelectedOverloadType.ResultTable, ArgumentList, MergedArgumentList, TypeArgumentStyle); resolvedException = new ResultException(SelectedOverloadType.ExceptionIdentifierList); constantSourceList.Add(LeftExpression); constantSourceList.Add(RightExpression); } else { errorList.AddError(new ErrorInvalidOperator(Operator, OperatorName)); return(false); } } else { errorList.AddError(new ErrorInvalidExpression(LeftExpression)); return(false); } }