private IBoundExpression ResolveRecursiveDefaultMember(Declaration defaultMember, ExpressionClassification defaultMemberClassification, ArgumentList argumentList, ParserRuleContext expression, Declaration parent, int defaultMemberResolutionRecursionDepth, RecursiveDefaultMemberAccessExpression containedExpression) { var defaultMemberRecursionExpression = new RecursiveDefaultMemberAccessExpression(defaultMember, defaultMemberClassification, _lExpression.Context, defaultMemberResolutionRecursionDepth, containedExpression); var defaultMemberAsLExpression = new SimpleNameExpression(defaultMember, defaultMemberClassification, expression); return(Resolve(defaultMemberAsLExpression, argumentList, expression, parent, defaultMemberResolutionRecursionDepth, defaultMemberRecursionExpression)); }
public RecursiveDefaultMemberAccessExpression( Declaration referencedDeclaration, ExpressionClassification classification, ParserRuleContext context, int defaultMemberRecursionDepth = 0, RecursiveDefaultMemberAccessExpression containedDefaultMemberRecursionExpression = null) : base(referencedDeclaration, classification, context) { DefaultMemberRecursionDepth = defaultMemberRecursionDepth; ContainedDefaultMemberRecursionExpression = containedDefaultMemberRecursionExpression; }
public LetCoercionDefaultMemberAccessExpression( Declaration referencedDeclaration, ExpressionClassification classification, ParserRuleContext context, IBoundExpression wrappedExpression, int defaultMemberRecursionDepth = 0, RecursiveDefaultMemberAccessExpression containedDefaultMemberRecursionExpression = null) : base(referencedDeclaration, classification, context) { WrappedExpression = wrappedExpression; DefaultMemberRecursionDepth = defaultMemberRecursionDepth; ContainedDefaultMemberRecursionExpression = containedDefaultMemberRecursionExpression; }
private static IBoundExpression ResolveRecursiveDefaultMember(IBoundExpression wrappedExpression, Declaration defaultMember, ExpressionClassification defaultMemberClassification, ParserRuleContext expression, bool isAssignment, int recursionDepth, RecursiveDefaultMemberAccessExpression containedExpression) { var defaultMemberAsTypeName = defaultMember.AsTypeName; var defaultMemberAsTypeDeclaration = defaultMember.AsTypeDeclaration; var defaultMemberExpression = new RecursiveDefaultMemberAccessExpression(defaultMember, defaultMemberClassification, expression, recursionDepth, containedExpression); return(ResolveViaDefaultMember( wrappedExpression, defaultMemberAsTypeName, defaultMemberAsTypeDeclaration, expression, isAssignment, recursionDepth + 1, defaultMemberExpression)); }
public DictionaryAccessExpression( Declaration referencedDeclaration, ExpressionClassification classification, ParserRuleContext context, IBoundExpression lExpression, ArgumentList argumentList, ParserRuleContext defaultMemberContext, int defaultMemberRecursionDepth = 1, RecursiveDefaultMemberAccessExpression containedDefaultMemberRecursionExpression = null) : base(referencedDeclaration, classification, context) { LExpression = lExpression; ArgumentList = argumentList; DefaultMemberRecursionDepth = defaultMemberRecursionDepth; ContainedDefaultMemberRecursionExpression = containedDefaultMemberRecursionExpression; DefaultMemberContext = defaultMemberContext; }
private static IBoundExpression ResolveRecursiveDefaultMember(IBoundExpression lExpression, Declaration defaultMember, ExpressionClassification defaultMemberClassification, ArgumentList argumentList, ParserRuleContext expression, ParserRuleContext defaultMemberContext, int recursionDepth, RecursiveDefaultMemberAccessExpression containedExpression) { var defaultMemberAsTypeName = defaultMember.AsTypeName; var defaultMemberAsTypeDeclaration = defaultMember.AsTypeDeclaration; var defaultMemberExpression = new RecursiveDefaultMemberAccessExpression(defaultMember, defaultMemberClassification, defaultMemberContext, recursionDepth, containedExpression); return(ResolveViaDefaultMember( lExpression, defaultMemberAsTypeName, defaultMemberAsTypeDeclaration, argumentList, expression, defaultMemberContext, recursionDepth + 1, defaultMemberExpression)); }
public IndexExpression(Declaration referencedDeclaration, ExpressionClassification classification, ParserRuleContext context, IBoundExpression lExpression, ArgumentList argumentList, bool isArrayAccess = false, bool isDefaultMemberAccess = false, int defaultMemberRecursionDepth = 0, RecursiveDefaultMemberAccessExpression containedDefaultMemberRecursionExpression = null) : base(referencedDeclaration, classification, context) { LExpression = lExpression; ArgumentList = argumentList; IsArrayAccess = isArrayAccess; IsDefaultMemberAccess = isDefaultMemberAccess; DefaultMemberRecursionDepth = defaultMemberRecursionDepth; ContainedDefaultMemberRecursionExpression = containedDefaultMemberRecursionExpression; }
private IBoundExpression ResolveLExpressionDeclaredTypeIsArray(Declaration indexedDeclaration, ExpressionClassification originalExpressionClassification, ArgumentList argumentList, ParserRuleContext expression, int defaultMemberRecursionDepth, RecursiveDefaultMemberAccessExpression containedExpression) { if (indexedDeclaration == null || !indexedDeclaration.IsArray) { return(null); } /* * The declared type of <l-expression> is an array type, an empty argument list has not already * been specified for it, and one of the following is true: */ if (!argumentList.HasArguments) { /* * <argument-list> represents an empty argument list. In this case, the index expression * takes on the classification and declared type of <l-expression> and references the same * array. */ ResolveArgumentList(indexedDeclaration, argumentList); return(new IndexExpression(indexedDeclaration, originalExpressionClassification, expression, _lExpression, argumentList, defaultMemberRecursionDepth: defaultMemberRecursionDepth, containedDefaultMemberRecursionExpression: containedExpression)); } if (!argumentList.HasNamedArguments) { /* * <argument-list> represents an argument list with a number of positional arguments equal * to the rank of the array, and with no named arguments. In this case, the index expression * references an individual element of the array, is classified as a variable and has the * declared type of the array’s element type. * * TODO: Implement compatibility checking */ ResolveArgumentList(indexedDeclaration, argumentList, true); return(new IndexExpression(indexedDeclaration, ExpressionClassification.Variable, expression, _lExpression, argumentList, isArrayAccess: true, defaultMemberRecursionDepth: defaultMemberRecursionDepth, containedDefaultMemberRecursionExpression: containedExpression)); } return(null); }
private static IBoundExpression ResolveViaDefaultMember(IBoundExpression wrappedExpression, string asTypeName, Declaration asTypeDeclaration, ParserRuleContext expression, bool isAssignment, int recursionDepth = 1, RecursiveDefaultMemberAccessExpression containedExpression = null) { if (Tokens.Variant.Equals(asTypeName, StringComparison.InvariantCultureIgnoreCase) || Tokens.Object.Equals(asTypeName, StringComparison.InvariantCultureIgnoreCase)) { // We cannot know the the default member in this case, so return an unbound member call. return(new LetCoercionDefaultMemberAccessExpression(wrappedExpression.ReferencedDeclaration, ExpressionClassification.Unbound, expression, wrappedExpression, recursionDepth, containedExpression)); } var defaultMember = (asTypeDeclaration as ClassModuleDeclaration)?.DefaultMember; if (defaultMember == null || !IsPropertyGetLetFunctionProcedure(defaultMember) || !IsPublic(defaultMember)) { return(ExpressionForResolutionFailure(wrappedExpression, expression)); } var defaultMemberClassification = DefaultMemberClassification(defaultMember); var parameters = ((IParameterizedDeclaration)defaultMember).Parameters.ToList(); if (isAssignment && defaultMember.DeclarationType == DeclarationType.PropertyLet && IsCompatibleWithOneNonObjectParameter(parameters)) { //This is a Let assignment. So, finding a Property Let with one non object parameter means we are done. return(new LetCoercionDefaultMemberAccessExpression(defaultMember, defaultMemberClassification, expression, wrappedExpression, recursionDepth, containedExpression)); } if (parameters.All(parameter => parameter.IsOptional || parameter.IsParamArray)) { if (!defaultMember.IsObject) { //We found a property Get of Function default member returning a value type. //This might also be applicable in case of an assignment, because only the Get will be assigned as default member if both Get and Let exist. return(new LetCoercionDefaultMemberAccessExpression(defaultMember, defaultMemberClassification, expression, wrappedExpression, recursionDepth, containedExpression)); } if (DEFAULT_MEMBER_RECURSION_LIMIT >= recursionDepth) { //The default member returns an object type. So, we have to recurse. return(ResolveRecursiveDefaultMember(wrappedExpression, defaultMember, defaultMemberClassification, expression, isAssignment, recursionDepth, containedExpression)); } } return(ExpressionForResolutionFailure(wrappedExpression, expression)); }
private static IBoundExpression ResolveViaDefaultMember(IBoundExpression lExpression, string asTypeName, Declaration asTypeDeclaration, ArgumentList argumentList, ParserRuleContext expression, ParserRuleContext defaultMemberContext, int recursionDepth = 1, RecursiveDefaultMemberAccessExpression containedExpression = null) { if (Tokens.Variant.Equals(asTypeName, StringComparison.InvariantCultureIgnoreCase) || Tokens.Object.Equals(asTypeName, StringComparison.InvariantCultureIgnoreCase)) { /* * The declared type of <l-expression> is Object or Variant. * In this case, the dictionary access expression is classified as an unbound member with * a declared type of Variant, referencing <l-expression> with no member name. */ ResolveArgumentList(null, argumentList); return(new DictionaryAccessExpression(null, ExpressionClassification.Unbound, expression, lExpression, argumentList, defaultMemberContext, recursionDepth, containedExpression)); } /* * The declared type of <l-expression> is a specific class, which has a public default Property * Get, Property Let, function or subroutine. */ var defaultMember = (asTypeDeclaration as ClassModuleDeclaration)?.DefaultMember; if (defaultMember == null || !IsPropertyGetLetFunctionProcedure(defaultMember) || !IsPublic(defaultMember)) { ResolveArgumentList(null, argumentList); return(CreateFailedDefaultMemberAccessExpression(lExpression, argumentList, expression)); } var defaultMemberClassification = DefaultMemberClassification(defaultMember); var parameters = ((IParameterizedDeclaration)defaultMember).Parameters.ToList(); if (IsCompatibleWithOneStringArgument(parameters)) { /* * This default member’s parameter list is compatible with <argument-list>. In this case, the * dictionary access expression references this default member and takes on its classification and * declared type. */ ResolveArgumentList(defaultMember, argumentList); return(new DictionaryAccessExpression(defaultMember, ExpressionClassification.Variable, expression, lExpression, argumentList, defaultMemberContext, recursionDepth, containedExpression)); } if (parameters.All(param => param.IsOptional) && DEFAULT_MEMBER_RECURSION_LIMIT >= recursionDepth) { /* * This default member cannot accept any parameters. In this case, the static analysis restarts * recursively, as if this default member was specified instead for <l-expression> with the * same <argument-list>. */ return(ResolveRecursiveDefaultMember(lExpression, defaultMember, defaultMemberClassification, argumentList, expression, defaultMemberContext, recursionDepth, containedExpression)); } ResolveArgumentList(null, argumentList); return(CreateFailedDefaultMemberAccessExpression(lExpression, argumentList, expression)); }
private IBoundExpression Resolve(IBoundExpression lExpression, ArgumentList argumentList, ParserRuleContext expression, Declaration parent, int defaultMemberResolutionRecursionDepth = 0, RecursiveDefaultMemberAccessExpression containedExpression = null) { if (lExpression.Classification == ExpressionClassification.ResolutionFailed) { ResolveArgumentList(null, argumentList); var argumentExpressions = argumentList.Arguments.Select(arg => arg.Expression); return(lExpression.JoinAsFailedResolution(expression, argumentExpressions)); } if (lExpression.Classification == ExpressionClassification.Unbound) { return(ResolveLExpressionIsUnbound(lExpression, argumentList, expression, defaultMemberResolutionRecursionDepth, containedExpression)); } if (lExpression.ReferencedDeclaration != null) { if (argumentList.HasArguments) { switch (lExpression) { case IndexExpression indexExpression: var doubleIndexExpression = ResolveLExpressionIsIndexExpression(indexExpression, argumentList, expression, parent, defaultMemberResolutionRecursionDepth, containedExpression); if (doubleIndexExpression != null) { return(doubleIndexExpression); } break; case DictionaryAccessExpression dictionaryAccessExpression: var indexOnBangExpression = ResolveLExpressionIsDictionaryAccessExpression(dictionaryAccessExpression, argumentList, expression, parent, defaultMemberResolutionRecursionDepth, containedExpression); if (indexOnBangExpression != null) { return(indexOnBangExpression); } break; } if (IsVariablePropertyFunctionWithoutParameters(lExpression) && !(lExpression.Classification == ExpressionClassification.Variable && parent.Equals(lExpression.ReferencedDeclaration))) { var parameterlessLExpressionAccess = ResolveLExpressionIsVariablePropertyFunctionNoParameters(lExpression, argumentList, expression, parent, defaultMemberResolutionRecursionDepth, containedExpression); if (parameterlessLExpressionAccess != null) { return(parameterlessLExpressionAccess); } } } } if (lExpression.Classification == ExpressionClassification.Property || lExpression.Classification == ExpressionClassification.Function || lExpression.Classification == ExpressionClassification.Subroutine || lExpression.Classification == ExpressionClassification.Variable && parent.Equals(lExpression.ReferencedDeclaration)) { var procedureDeclaration = lExpression.ReferencedDeclaration as IParameterizedDeclaration; var parameters = procedureDeclaration?.Parameters?.ToList(); if (parameters != null && ArgumentListIsCompatible(parameters, argumentList)) { return(ResolveLExpressionIsPropertyFunctionSubroutine(lExpression, argumentList, expression, defaultMemberResolutionRecursionDepth, containedExpression)); } } ResolveArgumentList(null, argumentList); return(CreateFailedExpression(lExpression, argumentList, expression, parent, defaultMemberResolutionRecursionDepth > 0)); }
private IBoundExpression ResolveLExpressionIsUnbound(IBoundExpression lExpression, ArgumentList argumentList, ParserRuleContext expression, int defaultMemberResolutionRecursionDepth, RecursiveDefaultMemberAccessExpression containedExpression) { /* * <l-expression> is classified as an unbound member. In this case, the index expression references * <l-expression>, is classified as an unbound member and its declared type is Variant. */ ResolveArgumentList(lExpression.ReferencedDeclaration, argumentList); return(new IndexExpression(lExpression.ReferencedDeclaration, ExpressionClassification.Unbound, expression, _lExpression, argumentList, defaultMemberRecursionDepth: defaultMemberResolutionRecursionDepth, containedDefaultMemberRecursionExpression: containedExpression)); }
private IBoundExpression ResolveLExpressionIsPropertyFunctionSubroutine(IBoundExpression lExpression, ArgumentList argumentList, ParserRuleContext expression, int defaultMemberRecursionDepth, RecursiveDefaultMemberAccessExpression containedExpression) { /* * <l-expression> is classified as a property or function and its parameter list is compatible with * <argument-list>. In this case, the index expression references <l-expression> and takes on its * classification and declared type. * * <l-expression> is classified as a subroutine and its parameter list is compatible with <argument- * list>. In this case, the index expression references <l-expression> and takes on its classification * and declared type. * * Note: Apart from a check of the number of arguments provided, we assume compatibility through enforcement by the VBE. */ ResolveArgumentList(lExpression.ReferencedDeclaration, argumentList); return(new IndexExpression(lExpression.ReferencedDeclaration, ExpressionClassification.Variable, expression, _lExpression, argumentList, defaultMemberRecursionDepth: defaultMemberRecursionDepth, containedDefaultMemberRecursionExpression: containedExpression)); }
private IBoundExpression ResolveDefaultMember(string asTypeName, Declaration asTypeDeclaration, ArgumentList argumentList, ParserRuleContext expression, Declaration parent, int defaultMemberResolutionRecursionDepth, RecursiveDefaultMemberAccessExpression containedExpression) { /* * The declared type of 'l-expression' is Object or Variant, and 'argument-list' contains no * named arguments. In this case, the index expression is classified as an unbound member with * a declared type of Variant, referencing 'l-expression' with no member name. */ if (Tokens.Variant.Equals(asTypeName, StringComparison.InvariantCultureIgnoreCase) && !argumentList.HasNamedArguments) { ResolveArgumentList(null, argumentList); //We do not treat unbound accesses on variables of type Variant as default member accesses because they could be array accesses as well. return(new IndexExpression(null, ExpressionClassification.Unbound, expression, _lExpression, argumentList, isDefaultMemberAccess: false, defaultMemberRecursionDepth: defaultMemberResolutionRecursionDepth, containedDefaultMemberRecursionExpression: containedExpression)); } if (Tokens.Object.Equals(asTypeName, StringComparison.InvariantCultureIgnoreCase) && !argumentList.HasNamedArguments) { ResolveArgumentList(null, argumentList); return(new IndexExpression(null, ExpressionClassification.Unbound, expression, _lExpression, argumentList, isDefaultMemberAccess: true, defaultMemberRecursionDepth: defaultMemberResolutionRecursionDepth, containedDefaultMemberRecursionExpression: containedExpression)); } /* * The declared type of 'l-expression' is a specific class, which has a public default Property * Get, Property Let, function or subroutine, and one of the following is true: */ if (asTypeDeclaration is ClassModuleDeclaration classModule && classModule.DefaultMember is Declaration defaultMember && IsPropertyGetLetFunctionProcedure(defaultMember) && IsPublic(defaultMember)) { var defaultMemberClassification = DefaultMemberExpressionClassification(defaultMember); /* * This default member’s parameter list is compatible with 'argument-list'. In this case, the * index expression references this default member and takes on its classification and * declared type. * * TODO: Improve argument compatibility check by checking the argument types. */ var parameters = ((IParameterizedDeclaration)defaultMember).Parameters.ToList(); if (ArgumentListIsCompatible(parameters, argumentList)) { ResolveArgumentList(defaultMember, argumentList); return(new IndexExpression(defaultMember, ExpressionClassification.Variable, expression, _lExpression, argumentList, isDefaultMemberAccess: true, defaultMemberRecursionDepth: defaultMemberResolutionRecursionDepth, containedDefaultMemberRecursionExpression: containedExpression)); } /** * This default member can accept no parameters. In this case, the static analysis restarts * recursively, as if this default member was specified instead for 'l-expression' with the * same 'argument-list'. */ if (parameters.All(parameter => parameter.IsOptional) && DEFAULT_MEMBER_RECURSION_LIMIT >= defaultMemberResolutionRecursionDepth) { return(ResolveRecursiveDefaultMember(defaultMember, defaultMemberClassification, argumentList, expression, parent, defaultMemberResolutionRecursionDepth, containedExpression)); } } return(null); }
private IBoundExpression ResolveLExpressionIsDictionaryAccessExpression(DictionaryAccessExpression dictionaryAccessExpression, ArgumentList argumentList, ParserRuleContext expression, Declaration parent, int defaultMemberResolutionRecursionDepth, RecursiveDefaultMemberAccessExpression containedExpression) { //This is equivalent to the case in which the lExpression is an IndexExpression with the difference that it cannot be an array access. var indexedDeclaration = dictionaryAccessExpression.ReferencedDeclaration; if (indexedDeclaration == null) { return(null); } if (indexedDeclaration.IsArray) { return(ResolveLExpressionDeclaredTypeIsArray(indexedDeclaration, dictionaryAccessExpression.Classification, argumentList, expression, defaultMemberResolutionRecursionDepth, containedExpression)); } var asTypeName = indexedDeclaration.AsTypeName; var asTypeDeclaration = indexedDeclaration.AsTypeDeclaration; return(ResolveDefaultMember(asTypeName, asTypeDeclaration, argumentList, expression, parent, defaultMemberResolutionRecursionDepth + 1, containedExpression)); }
private IBoundExpression ResolveLExpressionIsIndexExpression(IndexExpression indexExpression, ArgumentList argumentList, ParserRuleContext expression, Declaration parent, int defaultMemberResolutionRecursionDepth, RecursiveDefaultMemberAccessExpression containedExpression) { /* * <l-expression> is classified as an index expression and the argument list is not empty. * Thus, me must be dealing with a default member access or an array access. */ var indexedDeclaration = indexExpression.ReferencedDeclaration; if (indexedDeclaration == null) { return(null); } //The result of an array access is never an array. Any double array access requires either a default member access in between //or an array assigned to a Variant, the access to which is counted as an unbound member access and, thus, is resolved correctly //via the default member path. if (indexedDeclaration.IsArray && !indexExpression.IsArrayAccess) { return(ResolveLExpressionDeclaredTypeIsArray(indexedDeclaration, indexExpression.Classification, argumentList, expression, defaultMemberResolutionRecursionDepth, containedExpression)); } var asTypeName = indexedDeclaration.AsTypeName; var asTypeDeclaration = indexedDeclaration.AsTypeDeclaration; return(ResolveDefaultMember(asTypeName, asTypeDeclaration, argumentList, expression, parent, defaultMemberResolutionRecursionDepth + 1, containedExpression)); }
private IBoundExpression ResolveLExpressionIsVariablePropertyFunctionNoParameters(IBoundExpression lExpression, ArgumentList argumentList, ParserRuleContext expression, Declaration parent, int defaultMemberResolutionRecursionDepth, RecursiveDefaultMemberAccessExpression containedExpression) { /* * <l-expression> is classified as a variable, or <l-expression> is classified as a property or function * with a parameter list that cannot accept any parameters and an <argument-list> that is not * empty, and one of the following is true (see below): * * There are no parameters to the lExpression. So, this is either an array access or a default member call. */ var indexedDeclaration = lExpression.ReferencedDeclaration; if (indexedDeclaration == null) { return(null); } if (indexedDeclaration.IsArray && !(lExpression is IndexExpression indexExpression && indexExpression.IsArrayAccess)) { return(ResolveLExpressionDeclaredTypeIsArray(lExpression.ReferencedDeclaration, lExpression.Classification, argumentList, expression, defaultMemberResolutionRecursionDepth, containedExpression)); } var asTypeName = indexedDeclaration.AsTypeName; var asTypeDeclaration = indexedDeclaration.AsTypeDeclaration; return(ResolveDefaultMember(asTypeName, asTypeDeclaration, argumentList, expression, parent, defaultMemberResolutionRecursionDepth + 1, containedExpression)); }