public static IType GetTypeOrError(
            this SourceSymbolContext context,
            QualifiedName name,
            ImmutableArray <IType> typeArguments,
            out Func <Location, Diagnostic>?diagnostic)
        {
            diagnostic = default;
            var possibleTypes = context.GetPossibleTypes(name, typeArguments);

            if (possibleTypes.Count == 0)
            {
                diagnostic = l => new Diagnostic(l, ErrorCode.TypeNotFound, ImmutableArray.Create <object?>(name));
                return(ErrorInterface.Instance);
            }

            if (possibleTypes.Count > 1)
            {
                diagnostic = l => new Diagnostic(l, ErrorCode.AmbigiousInterfaceReference, ImmutableArray.Create <object?>(possibleTypes.Cast <object?>().Prepend(name).ToImmutableArray()));
                return(ErrorInterface.Instance);
            }

            var type = possibleTypes[0];

            if (typeArguments.Length > 0)
            {
                Release.Assert(type is IInterface);
                var @interface     = (IInterface)type;
                var typeParameters = @interface.TypeParameters;
                HasValidTypeArguments(typeArguments, typeParameters, out diagnostic);
                type = @interface.Construct(typeArguments);
            }

            return(type);
        }
示例#2
0
        public static IType BindType(this TypeContext context, SourceSymbolContext sourceSymbolContext, bool isExported, DiagnosticBag diagnostics)
        {
            if (context.primitive_type() is { } primitive)
            {
                return(primitive.BindPrimitive());
            }
            if (context.named_type_reference() is { } namedTypeReference)
            {
                return(namedTypeReference.BindNamedTypeReference(sourceSymbolContext, isExported, diagnostics));
            }
            if (context.anonymous_interface_declaration() is { } interfaceContext)
            {
                return(new SourceAnonymousInterface(
                           interfaceContext,
                           sourceSymbolContext,
                           isExported: isExported,
                           diagnostics));
            }
            if (context.union() is { } union)
            {
                return(new SourceUnion(union, sourceSymbolContext, isExported, diagnostics));
            }

            diagnostics.Add(new Diagnostic(new Location(context), ErrorCode.InvalidParseTree, ImmutableArray.Create <object?>(context)));
            return(ErrorType.Instance);
        }
示例#3
0
 public SourceNamedInterface(
     Interface_declarationContext context,
     SourceSymbolContext sourceSymbolContext,
     DiagnosticBag diagnostics) : base(diagnostics)
 {
     _anonymousSourceInterface = new SourceAnonymousInterface(
         context.anonymous_interface_declaration(),
         sourceSymbolContext.WithTypeParameters(() => TypeParameters),
         context.EXPORT() is { },
示例#4
0
 public static ImmutableArray <IType> BindTypeArgumentList(
     this Type_argument_listContext context,
     SourceSymbolContext sourceSymbolContext,
     DiagnosticBag diagnostics)
 {
     return
         (context
          .type()
          .Select(x => x.BindType(sourceSymbolContext, false, diagnostics))
          .ToImmutableArray());
 }
示例#5
0
 public SourceParameter(
     ParameterContext context,
     SourceSymbolContext sourceSymbolContext,
     bool isExported,
     DiagnosticBag diagnostics) : base(diagnostics)
 {
     _context             = context;
     _sourceSymbolContext = sourceSymbolContext;
     Name  = _context.LOWERCASE_IDENTIFIER().Symbol.Text;
     _type = new Lazy <IType>(() => _context.type_declaration().type().BindType(_sourceSymbolContext, isExported, _diagnostics));
 }
 public static IReadOnlyList <IMethod> GetPossibleMethods(this SourceSymbolContext context, QualifiedName name, ImmutableArray <IType> typeArguments)
 {
     return(GetPossibleTs(
                context,
                name,
                typeArguments,
                (IAssembly x, QualifiedName n, out IMethod? i) => x.TryGetMethod(n, out i),
                x => x.LocalMethods,
                x => x.FullyQualifiedName,
                x => x.TypeParameters));
 }
示例#7
0
 public SourceUnion(
     UnionContext context,
     SourceSymbolContext sourceSymbolContext,
     bool isExported,
     DiagnosticBag diagnostics) : base(diagnostics)
 {
     _context             = context;
     _sourceSymbolContext = sourceSymbolContext;
     _isExported          = isExported;
     _options             = new Lazy <ImmutableArray <IType> >(BindOptions);
 }
        public SourceAnonymousInterface(
            Anonymous_interface_declarationContext context,
            SourceSymbolContext sourceSymbolContext,
            bool isExported,
            DiagnosticBag diagnostics) : base(diagnostics)
        {
            _context             = context;
            _sourceSymbolContext = sourceSymbolContext;
            IsExported           = isExported;

            _methods = new Lazy <ImmutableArray <IInterfaceMethod> >(GenerateMethods);
        }
示例#9
0
 public SourceTypeParameter(
     Type_parameterContext context,
     SourceSymbolContext sourceSymbolContext,
     bool isExported,
     DiagnosticBag diagnostics) : base(diagnostics)
 {
     _context             = context;
     _sourceSymbolContext = sourceSymbolContext;
     _isExported          = isExported;
     Name           = _context.UPPERCASE_IDENTIFIER().Symbol.Text;
     _constrainedTo = new Lazy <IType?>(BindConstrainedTo);
 }
示例#10
0
        public SourceInterfaceMethod(
            Method_signatureContext context,
            SourceSymbolContext sourceSymbolContext,
            bool isExported,
            DiagnosticBag diagnostics) : base(diagnostics)
        {
            _context             = context;
            _sourceSymbolContext = sourceSymbolContext;
            _isExported          = isExported;
            Name = context.UPPERCASE_IDENTIFIER().Symbol.Text;

            _returnType = new Lazy <IType>(BindReturnType);
            _parameters = new Lazy <ImmutableArray <IParameter> >(BindParameters);
        }
        public static IReadOnlyList <IType> GetPossibleTypes(
            this SourceSymbolContext context,
            QualifiedName name,
            ImmutableArray <IType> typeArguments)
        {
            if (name.Parent is null && typeArguments.Length == 0)
            {
                if (context.GetTypeParameter(name.Name) is { } typeParameter)
                {
                    return(new[] { typeParameter });
                }
            }

            return(GetPossibleTs(
                       context,
                       name,
                       typeArguments,
                       (IAssembly x, QualifiedName n, out IInterface? i) => x.TryGetInterface(n, out i),
                       x => x.LocalInterfaces,
                       x => x.FullyQualifiedName,
                       x => x.TypeParameters));
        }
        public static IType?GetTypeParameter(this SourceSymbolContext context, string name)
        {
            {
                if (context.CurrentLevelTypeParameters().FirstOrDefault(x => x.Name == name) is { } typeParameter)
                {
                    return(typeParameter);
                }
            }

            var scope = context.Scope;

            while (scope != null)
            {
                if (scope.TypeParameters.FirstOrDefault(x => x.Name == name) is { } typeParameter)
                {
                    return(typeParameter);
                }
                scope = scope.DeclaringMethod;
            }

            return(null);
        }
示例#13
0
        private static IType BindNamedTypeReference(
            this Named_type_referenceContext context,
            SourceSymbolContext sourceSymbolContext,
            bool isExported,
            DiagnosticBag diagnostics)
        {
            var qualifiedName = context.qualified_name();
            var typeArguments =
                context
                .type_argument_list()
                .BindTypeArgumentList(sourceSymbolContext, diagnostics);

            var type = sourceSymbolContext.GetTypeOrError(
                qualifiedName.GetQualifiedName(),
                typeArguments,
                out var diagnostic);

            if (diagnostic != null)
            {
                diagnostics.Add(diagnostic(new Location(qualifiedName)));
            }
            if (diagnostic is null && isExported && type is IInterface {
                IsExported : false
            })
        public static IMethod GetMethodOrError(
            this SourceSymbolContext context,
            QualifiedName name,
            ImmutableArray <IType> typeArguments,
            out Func <Location, Diagnostic>?diagnostic)
        {
            diagnostic = null;
            var possibleMethods = context.GetPossibleMethods(name, typeArguments);

            if (possibleMethods.Count == 0)
            {
                diagnostic = l => new Diagnostic(l, ErrorCode.MethodNotFound, ImmutableArray.Create <object?>(name));
                return(ErrorMethod.Instance);
            }


            if (possibleMethods.Count > 1)
            {
                diagnostic = l => new Diagnostic(
                    l,
                    ErrorCode.AmbigiousMethodReference,
                    ImmutableArray.Create <object?>(possibleMethods.Cast <object?>().Prepend(name).ToImmutableArray()));
                return(ErrorMethod.Instance);
            }

            var method = possibleMethods[0];

            if (typeArguments.Length > 0)
            {
                var typeParameters = method.TypeParameters;
                HasValidTypeArguments(typeArguments, typeParameters, out diagnostic);
                method = method.Substitute(CreateTypeMap(typeArguments, typeParameters), new Dictionary <IType, IType>());
            }

            return(method);
        }
        private static IReadOnlyList <T> GetPossibleTs <T>(
            SourceSymbolContext context,
            QualifiedName name,
            ImmutableArray <IType> typeArguments,
            TryGetT <T> tryGetT,
            GetLocalTs <T> getLocalTs,
            GetFullyQualifiedName <T> getFullyQualifiedName,
            GetTypeParameters <T> getTypeParameters) where T : class
        {
            List <T> possibleTs;

            if (name.Parent is null)
            {
                // local ts have priority over top level ts,
                // and an inner local t hides an outer local t

                // local ts can only have simple names, so we can skip this check if the name is not simple

                var scope = context.Scope;
                while (scope != null)
                {
                    possibleTs = getLocalTs(scope)
                                 .Where(
                        x => getFullyQualifiedName(x) == name &&
                        getTypeParameters(x).Length == typeArguments.Length)
                                 .ToList();
                    if (possibleTs.Count > 0)
                    {
                        return(possibleTs);
                    }

                    scope = scope.DeclaringMethod;
                }
            }

            var assemblies = context.Assembly.ReferencedAssembliesAndSelf;

            // types in the innermost namespace have priority over types in its parent namespace,
            // which have priority over types in its parent etc.
            var @namespace = context.NameSpace;

            while (@namespace != null)
            {
                var possibleName = name.Prepend(@namespace);

                possibleTs = LookupPossibleName(possibleName).ToList();

                if (possibleTs.Count > 0)
                {
                    return(possibleTs);
                }

                @namespace = @namespace?.Parent;
            }

            // Types in the global namespace have priority over types defined in imports
            possibleTs = LookupPossibleName(name).ToList();

            if (possibleTs.Count > 0)
            {
                return(possibleTs);
            }

            // look for types in imports
            if (name.Parent is null)
            {
                // imports only bring the top level types into scope, so they are only relevant if the name is simple;

                var possibleNames = context.Imports.Select(x => x.Append(name)).ToList();

                return
                    (possibleNames
                     .SelectMany(LookupPossibleName)
                     .ToList());
            }

            return(Array.Empty <T>());

            IEnumerable <T> LookupPossibleName(QualifiedName possibleName)
            {
                return(assemblies.Select(x =>
                {
                    tryGetT(x, possibleName, out var t);
                    return t;
                }).Where(x => x != null && getTypeParameters(x).Length == typeArguments.Length) !);
            }
        }