Exemple #1
0
        public override void VisitInstanceFunctionCallSyntax(InstanceFunctionCallSyntax syntax)
        {
            FunctionFlags currentFlags = allowedFlags;

            this.Visit(syntax.BaseExpression);
            this.Visit(syntax.Dot);
            this.Visit(syntax.Name);
            this.Visit(syntax.OpenParen);
            allowedFlags = allowedFlags.HasDecoratorFlag() ? FunctionFlags.Default : allowedFlags;
            this.VisitNodes(syntax.Arguments);
            this.Visit(syntax.CloseParen);
            allowedFlags = currentFlags;

            if (!syntax.Name.IsValid)
            {
                // the parser produced an instance function calls with an invalid name
                // all instance function calls must be bound to a symbol, so let's
                // bind to a symbol without any errors (there's already a parse error)
                this.bindings.Add(syntax, new ErrorSymbol());
                return;
            }

            if (bindings.TryGetValue(syntax.BaseExpression, out var baseSymbol) && baseSymbol is NamespaceSymbol namespaceSymbol)
            {
                var functionSymbol = allowedFlags.HasDecoratorFlag()
                                     // Decorator functions are only valid when HasDecoratorFlag() is true which means
                                     // the instance function call is the top level expression of a DecoratorSyntax node.
                    ? namespaceSymbol.Type.MethodResolver.TryGetSymbol(syntax.Name) ?? namespaceSymbol.Type.DecoratorResolver.TryGetSymbol(syntax.Name)
                    : namespaceSymbol.Type.MethodResolver.TryGetSymbol(syntax.Name);

                var foundSymbol = SymbolValidator.ResolveNamespaceQualifiedFunction(allowedFlags, functionSymbol, syntax.Name, namespaceSymbol);

                this.bindings.Add(syntax, foundSymbol);
            }
        }
Exemple #2
0
        private Symbol LookupGlobalSymbolByName(IdentifierSyntax identifierSyntax, bool isFunctionCall)
        {
            // attempt to find name in the built in namespaces. imported namespaces will be present in the declarations list as they create declared symbols.
            if (this.namespaceResolver.BuiltIns.TryGetValue(identifierSyntax.IdentifierName) is { } namespaceSymbol)
            {
                // namespace symbol found
                return(namespaceSymbol);
            }

            // declarations must not have a namespace value, namespaces are used to fully qualify a function access.
            // There might be instances where a variable declaration for example uses the same name as one of the imported
            // functions, in this case to differentiate a variable declaration vs a function access we check the namespace value,
            // the former case must have an empty namespace value whereas the latter will have a namespace value.
            if (this.declarations.TryGetValue(identifierSyntax.IdentifierName, out var globalSymbol))
            {
                // we found the symbol in the global namespace
                return(globalSymbol);
            }

            // attempt to find function in all imported namespaces
            var foundSymbols = namespaceResolver.ResolveUnqualifiedFunction(identifierSyntax, includeDecorators: allowedFlags.HasAnyDecoratorFlag());

            if (foundSymbols.Count() > 1)
            {
                // ambiguous symbol
                return(new ErrorSymbol(DiagnosticBuilder.ForPosition(identifierSyntax).AmbiguousSymbolReference(identifierSyntax.IdentifierName, namespaceResolver.GetNamespaceNames().ToImmutableSortedSet(StringComparer.Ordinal))));
            }

            var foundSymbol = foundSymbols.FirstOrDefault();

            return(isFunctionCall ?
                   SymbolValidator.ResolveUnqualifiedFunction(allowedFlags, foundSymbol, identifierSyntax, namespaceResolver) :
                   SymbolValidator.ResolveUnqualifiedSymbol(foundSymbol, identifierSyntax, namespaceResolver, declarations.Keys));
        }
Exemple #3
0
        private Symbol LookupSymbolByName(IdentifierSyntax identifierSyntax, bool isFunctionCall)
        {
            // attempt to find name in the imported namespaces
            if (this.namespaces.TryGetValue(identifierSyntax.IdentifierName, out var namespaceSymbol))
            {
                // namespace symbol found
                return(namespaceSymbol);
            }

            // declarations must not have a namespace value, namespaces are used to fully qualify a function access.
            // There might be instances where a variable declaration for example uses the same name as one of the imported
            // functions, in this case to differentiate a variable declaration vs a function access we check the namespace value,
            // the former case must have an empty namespace value whereas the latter will have a namespace value.
            if (this.declarations.TryGetValue(identifierSyntax.IdentifierName, out var localSymbol))
            {
                // we found the symbol in the local namespace
                return(localSymbol);
            }

            // attempt to find function in all imported namespaces
            var foundSymbols = this.namespaces
                               .Select(kvp => allowedFlags.HasDecoratorFlag()
                    ? kvp.Value.Type.MethodResolver.TryGetSymbol(identifierSyntax) ?? kvp.Value.Type.DecoratorResolver.TryGetSymbol(identifierSyntax)
                    : kvp.Value.Type.MethodResolver.TryGetSymbol(identifierSyntax))
                               .Where(symbol => symbol != null)
                               .ToList();

            if (foundSymbols.Count > 1)
            {
                // ambiguous symbol
                return(new ErrorSymbol(DiagnosticBuilder.ForPosition(identifierSyntax).AmbiguousSymbolReference(identifierSyntax.IdentifierName, this.namespaces.Keys)));
            }

            var foundSymbol = foundSymbols.FirstOrDefault();

            return(isFunctionCall ?
                   SymbolValidator.ResolveUnqualifiedFunction(allowedFlags, foundSymbol, identifierSyntax, namespaces.Values) :
                   SymbolValidator.ResolveUnqualifiedSymbol(foundSymbol, identifierSyntax, namespaces.Values, declarations.Keys));
        }
Exemple #4
0
        public override void VisitInstanceFunctionCallSyntax(InstanceFunctionCallSyntax syntax)
        {
            base.VisitInstanceFunctionCallSyntax(syntax);

            if (!syntax.Name.IsValid)
            {
                // the parser produced an instance function calls with an invalid name
                // all instance function calls must be bound to a symbol, so let's
                // bind to a symbol without any errors (there's already a parse error)
                this.bindings.Add(syntax, new ErrorSymbol());
                return;
            }

            if (bindings.TryGetValue(syntax.BaseExpression, out var baseSymbol) && baseSymbol is NamespaceSymbol namespaceSymbol)
            {
                var functionSymbol = namespaceSymbol.Type.MethodResolver.TryGetSymbol(syntax.Name);

                var foundSymbol = SymbolValidator.ResolveNamespaceQualifiedFunction(allowedFlags, functionSymbol, syntax.Name, namespaceSymbol);

                this.bindings.Add(syntax, foundSymbol);
            }
        }