| //===--- TypeCheckRequest.h - Type Checking Request -------------*- C++ -*-===// |
| // |
| // This source file is part of the Swift.org open source project |
| // |
| // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors |
| // Licensed under Apache License v2.0 with Runtime Library Exception |
| // |
| // See https://swift.org/LICENSE.txt for license information |
| // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // This file defines the TypeCheckRequest type, which describes a request |
| // to the type checker to compute certain information. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef SWIFT_SEMA_TYPE_CHECK_REQUEST_H |
| #define SWIFT_SEMA_TYPE_CHECK_REQUEST_H |
| |
| #include "swift/AST/Identifier.h" |
| #include "swift/AST/Type.h" |
| #include "swift/Basic/SourceLoc.h" |
| #include "llvm/ADT/PointerUnion.h" |
| #include "llvm/ADT/STLExtras.h" |
| #include "llvm/Support/ErrorHandling.h" |
| #include <cassert> |
| #include <utility> |
| |
| namespace swift { |
| |
| class ClassDecl; |
| class DeclContext; |
| class EnumDecl; |
| class ExtensionDecl; |
| class ProtocolDecl; |
| class TypeDecl; |
| class TypeRepr; |
| |
| /// Describes the information needed to perform name lookup into a |
| /// declaration context. |
| struct DeclContextLookupInfo { |
| DeclContext *DC; |
| DeclName Name; |
| SourceLoc Loc; |
| |
| friend bool operator==(const DeclContextLookupInfo &x, |
| const DeclContextLookupInfo &y) { |
| return x.DC == y.DC && x.Name == y.Name; |
| } |
| |
| friend bool operator!=(const DeclContextLookupInfo &x, |
| const DeclContextLookupInfo &y) { |
| return !(x == y); |
| } |
| }; |
| |
| /// A request to the type checker to compute some particular kind of |
| /// information. |
| class TypeCheckRequest { |
| public: |
| /// Describes the kind of request. |
| enum Kind : uint8_t { |
| #define TYPE_CHECK_REQUEST(Request,Payload) \ |
| Request, |
| |
| #include "swift/Sema/TypeCheckRequestKinds.def" |
| } TheKind; |
| |
| private: |
| /// The payload of the request, which differs based on the request kind. |
| union PayloadType { |
| PayloadType() { } |
| |
| #define TYPE_CHECK_REQUEST_PAYLOAD(PayloadName,...) \ |
| __VA_ARGS__ PayloadName; |
| |
| #include "swift/Sema/TypeCheckRequestPayloads.def" |
| } Payload; |
| |
| /// Describes the kind of payload expected. |
| /// |
| /// The enumerators in this enumeration type are expected to map 1-1 to the |
| /// fields of the \c Payload union. |
| enum class PayloadKind { |
| #define TYPE_CHECK_REQUEST_PAYLOAD(PayloadName,...) \ |
| PayloadName, |
| |
| #include "swift/Sema/TypeCheckRequestPayloads.def" |
| }; |
| |
| /// Determine the payload kind for the given type check request kind. |
| static PayloadKind getPayloadKind(Kind kind) { |
| switch (kind) { |
| #define TYPE_CHECK_REQUEST(Request,PayloadName) \ |
| case Request: \ |
| return PayloadKind::PayloadName; |
| |
| #include "swift/Sema/TypeCheckRequestKinds.def" |
| } |
| |
| llvm_unreachable("Unhandled PayloadKind in switch."); |
| } |
| |
| public: |
| // The payload types. |
| #define TYPE_CHECK_REQUEST_PAYLOAD(PayloadName,...) \ |
| typedef __VA_ARGS__ PayloadName##PayloadType; |
| |
| #include "swift/Sema/TypeCheckRequestPayloads.def" |
| |
| // Constructors. |
| #define TYPE_CHECK_REQUEST_PAYLOAD(PayloadName,...) \ |
| TypeCheckRequest(Kind kind, __VA_ARGS__ payload) : TheKind(kind) { \ |
| assert(getPayloadKind(kind) == PayloadKind::PayloadName); \ |
| Payload.PayloadName = payload; \ |
| } |
| |
| #include "swift/Sema/TypeCheckRequestPayloads.def" |
| |
| TypeCheckRequest(const TypeCheckRequest &T) { *this = T; } |
| |
| TypeCheckRequest& operator=(const TypeCheckRequest &T) { |
| TheKind = T.getKind(); |
| switch (getPayloadKind(TheKind)) { |
| case PayloadKind::Class: |
| Payload.Class = T.Payload.Class; |
| break; |
| case PayloadKind::Enum: |
| Payload.Enum = T.Payload.Enum; |
| break; |
| case PayloadKind::InheritedClauseEntry: |
| new (&Payload.InheritedClauseEntry) |
| std::pair<llvm::PointerUnion<TypeDecl *, ExtensionDecl *>, unsigned>(); |
| Payload.InheritedClauseEntry = T.Payload.InheritedClauseEntry; |
| break; |
| case PayloadKind::Protocol: |
| Payload.Protocol = T.Payload.Protocol; |
| break; |
| case PayloadKind::DeclContextLookup: |
| new (&Payload.DeclContextLookup) DeclContextLookupInfo(); |
| Payload.DeclContextLookup = T.Payload.DeclContextLookup; |
| break; |
| case PayloadKind::TypeResolution: |
| new (&Payload.InheritedClauseEntry) |
| std::tuple<TypeRepr *, DeclContext *, unsigned>(); |
| Payload.TypeResolution = T.Payload.TypeResolution; |
| break; |
| case PayloadKind::TypeDeclResolution: |
| Payload.TypeDeclResolution = T.Payload.TypeDeclResolution; |
| break; |
| } |
| return *this; |
| } |
| |
| /// Determine the kind of type check request. |
| Kind getKind() const { return TheKind; } |
| |
| // Payload retrieval. |
| #define TYPE_CHECK_REQUEST_PAYLOAD(PayloadName,...) \ |
| __VA_ARGS__ get##PayloadName##Payload() const { \ |
| assert(getPayloadKind(TheKind) == PayloadKind::PayloadName); \ |
| return Payload.PayloadName; \ |
| } |
| |
| #include "swift/Sema/TypeCheckRequestPayloads.def" |
| |
| /// Retrieve the location at which this request was initiated. |
| SourceLoc getLoc() const; |
| |
| /// Retrieve the declaration to which this request was anchored. |
| /// |
| /// A request is anchored on a declaration if the request is |
| /// specifically about that declaration, e.g., the superclass of a |
| /// class or some inheritance clause entry of a type. |
| Decl *getAnchor() const; |
| |
| friend bool operator==(const TypeCheckRequest &x, const TypeCheckRequest &y); |
| }; |
| |
| /// A callback used to check whether a particular dependency of this |
| /// operation has been satisfied. If so, it returns \c false. If not, |
| /// the dependency will be recorded and this operation returns \c true. |
| typedef llvm::function_ref<bool(TypeCheckRequest)> UnsatisfiedDependency; |
| |
| // Create requestXXX functions to more easily form type check requests |
| // of the appropriate type. |
| #define TYPE_CHECK_REQUEST(Request,PayloadName) \ |
| inline TypeCheckRequest request##Request( \ |
| TypeCheckRequest::PayloadName##PayloadType payload) {\ |
| return TypeCheckRequest(TypeCheckRequest::Request, payload); \ |
| } |
| #include "swift/Sema/TypeCheckRequestKinds.def" |
| |
| /// Compare two type checking requests for equality. |
| bool operator==(const TypeCheckRequest &x, const TypeCheckRequest &y); |
| inline bool operator!=(const TypeCheckRequest &x, const TypeCheckRequest &y) { |
| return !(x == y); |
| } |
| |
| } |
| |
| #endif /* SWIFT_SEMA_TYPE_CHECK_REQUEST_H */ |