| // Copyright 2021 The Tint Authors. | 
 | // | 
 | // Licensed under the Apache License, Version 2.0 (the "License"); | 
 | // you may not use this file except in compliance with the License. | 
 | // You may obtain a copy of the License at | 
 | // | 
 | //     http://www.apache.org/licenses/LICENSE-2.0 | 
 | // | 
 | // Unless required by applicable law or agreed to in writing, software | 
 | // distributed under the License is distributed on an "AS IS" BASIS, | 
 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | // See the License for the specific language governing permissions and | 
 | // limitations under the License. | 
 |  | 
 | #ifndef SRC_PROGRAM_H_ | 
 | #define SRC_PROGRAM_H_ | 
 |  | 
 | #include <string> | 
 | #include <unordered_set> | 
 |  | 
 | #include "src/ast/function.h" | 
 | #include "src/program_id.h" | 
 | #include "src/sem/info.h" | 
 | #include "src/sem/type_manager.h" | 
 | #include "src/symbol_table.h" | 
 |  | 
 | namespace tint { | 
 |  | 
 | // Forward declarations | 
 | class CloneContext; | 
 |  | 
 | namespace ast { | 
 |  | 
 | class Module; | 
 |  | 
 | }  // namespace ast | 
 |  | 
 | /// Program holds the AST, Type information and SymbolTable for a tint program. | 
 | class Program { | 
 |  public: | 
 |   /// ASTNodeAllocator is an alias to BlockAllocator<ast::Node> | 
 |   using ASTNodeAllocator = BlockAllocator<ast::Node>; | 
 |  | 
 |   /// SemNodeAllocator is an alias to BlockAllocator<sem::Node> | 
 |   using SemNodeAllocator = BlockAllocator<sem::Node>; | 
 |  | 
 |   /// Constructor | 
 |   Program(); | 
 |  | 
 |   /// Move constructor | 
 |   /// @param rhs the Program to move | 
 |   Program(Program&& rhs); | 
 |  | 
 |   /// Move constructor from builder | 
 |   /// @param builder the builder used to construct the program | 
 |   explicit Program(ProgramBuilder&& builder); | 
 |  | 
 |   /// Destructor | 
 |   ~Program(); | 
 |  | 
 |   /// Move assignment operator | 
 |   /// @param rhs the Program to move | 
 |   /// @return this Program | 
 |   Program& operator=(Program&& rhs); | 
 |  | 
 |   /// @returns the unique identifier for this program | 
 |   ProgramID ID() const { return id_; } | 
 |  | 
 |   /// @returns a reference to the program's types | 
 |   const sem::Manager& Types() const { | 
 |     AssertNotMoved(); | 
 |     return types_; | 
 |   } | 
 |  | 
 |   /// @returns a reference to the program's AST nodes storage | 
 |   const ASTNodeAllocator& ASTNodes() const { | 
 |     AssertNotMoved(); | 
 |     return ast_nodes_; | 
 |   } | 
 |  | 
 |   /// @returns a reference to the program's semantic nodes storage | 
 |   const SemNodeAllocator& SemNodes() const { | 
 |     AssertNotMoved(); | 
 |     return sem_nodes_; | 
 |   } | 
 |  | 
 |   /// @returns a reference to the program's AST root Module | 
 |   const ast::Module& AST() const { | 
 |     AssertNotMoved(); | 
 |     return *ast_; | 
 |   } | 
 |  | 
 |   /// @returns a reference to the program's semantic info | 
 |   const sem::Info& Sem() const { | 
 |     AssertNotMoved(); | 
 |     return sem_; | 
 |   } | 
 |  | 
 |   /// @returns a reference to the program's SymbolTable | 
 |   const SymbolTable& Symbols() const { | 
 |     AssertNotMoved(); | 
 |     return symbols_; | 
 |   } | 
 |  | 
 |   /// @returns a reference to the program's diagnostics | 
 |   const diag::List& Diagnostics() const { | 
 |     AssertNotMoved(); | 
 |     return diagnostics_; | 
 |   } | 
 |  | 
 |   /// Performs a deep clone of this program. | 
 |   /// The returned Program will contain no pointers to objects owned by this | 
 |   /// Program, and so after calling, this Program can be safely destructed. | 
 |   /// @return a new Program copied from this Program | 
 |   Program Clone() const; | 
 |  | 
 |   /// Performs a deep clone of this Program's AST nodes, types and symbols into | 
 |   /// a new ProgramBuilder. Semantic nodes are not cloned, as these will be | 
 |   /// rebuilt when the ProgramBuilder builds its Program. | 
 |   /// The returned ProgramBuilder will contain no pointers to objects owned by | 
 |   /// this Program, and so after calling, this Program can be safely destructed. | 
 |   /// @return a new ProgramBuilder copied from this Program | 
 |   ProgramBuilder CloneAsBuilder() const; | 
 |  | 
 |   /// @returns true if the program has no error diagnostics and is not missing | 
 |   /// information | 
 |   bool IsValid() const; | 
 |  | 
 |   /// @return the TypeInfo pointers of all transforms that have been applied to | 
 |   /// this program. | 
 |   std::unordered_set<const TypeInfo*> TransformsApplied() const { | 
 |     return transforms_applied_; | 
 |   } | 
 |  | 
 |   /// @param transform the TypeInfo of the transform | 
 |   /// @returns true if the transform with the given TypeInfo was applied to the | 
 |   /// Program | 
 |   bool HasTransformApplied(const TypeInfo* transform) const { | 
 |     return transforms_applied_.count(transform); | 
 |   } | 
 |  | 
 |   /// @returns true if the transform of type `T` was applied. | 
 |   template <typename T> | 
 |   bool HasTransformApplied() const { | 
 |     return HasTransformApplied(&TypeInfo::Of<T>()); | 
 |   } | 
 |  | 
 |   /// Helper for returning the resolved semantic type of the expression `expr`. | 
 |   /// @param expr the AST expression | 
 |   /// @return the resolved semantic type for the expression, or nullptr if the | 
 |   /// expression has no resolved type. | 
 |   const sem::Type* TypeOf(const ast::Expression* expr) const; | 
 |  | 
 |   /// Helper for returning the resolved semantic type of the AST type `type`. | 
 |   /// @param type the AST type | 
 |   /// @return the resolved semantic type for the type, or nullptr if the type | 
 |   /// has no resolved type. | 
 |   const sem::Type* TypeOf(const ast::Type* type) const; | 
 |  | 
 |   /// Helper for returning the resolved semantic type of the AST type | 
 |   /// declaration `type_decl`. | 
 |   /// @param type_decl the AST type declaration | 
 |   /// @return the resolved semantic type for the type declaration, or nullptr if | 
 |   /// the type declaration has no resolved type. | 
 |   const sem::Type* TypeOf(const ast::TypeDecl* type_decl) const; | 
 |  | 
 |   /// A function that can be used to print a program | 
 |   using Printer = std::string (*)(const Program*); | 
 |  | 
 |   /// The Program printer used for testing and debugging. | 
 |   static Printer printer; | 
 |  | 
 |  private: | 
 |   Program(const Program&) = delete; | 
 |  | 
 |   /// Asserts that the program has not been moved. | 
 |   void AssertNotMoved() const; | 
 |  | 
 |   ProgramID id_; | 
 |   sem::Manager types_; | 
 |   ASTNodeAllocator ast_nodes_; | 
 |   SemNodeAllocator sem_nodes_; | 
 |   ast::Module* ast_ = nullptr; | 
 |   sem::Info sem_; | 
 |   SymbolTable symbols_{id_}; | 
 |   diag::List diagnostics_; | 
 |   std::unordered_set<const TypeInfo*> transforms_applied_; | 
 |   bool is_valid_ = false;  // Not valid until it is built | 
 |   bool moved_ = false; | 
 | }; | 
 |  | 
 | /// @param program the Program | 
 | /// @returns the ProgramID of the Program | 
 | inline ProgramID ProgramIDOf(const Program* program) { | 
 |   return program->ID(); | 
 | } | 
 |  | 
 | }  // namespace tint | 
 |  | 
 | #endif  // SRC_PROGRAM_H_ |