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); }
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); }
public SourceNamedInterface( Interface_declarationContext context, SourceSymbolContext sourceSymbolContext, DiagnosticBag diagnostics) : base(diagnostics) { _anonymousSourceInterface = new SourceAnonymousInterface( context.anonymous_interface_declaration(), sourceSymbolContext.WithTypeParameters(() => TypeParameters), context.EXPORT() is { },
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()); }
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)); }
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); }
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); }
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); }
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) !); } }