| // 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. | 
 |  | 
 | #include "src/program.h" | 
 |  | 
 | #include <utility> | 
 |  | 
 | #include "src/demangler.h" | 
 | #include "src/resolver/resolver.h" | 
 | #include "src/semantic/expression.h" | 
 |  | 
 | namespace tint { | 
 |  | 
 | Program::Program() = default; | 
 |  | 
 | Program::Program(Program&& program) | 
 |     : types_(std::move(program.types_)), | 
 |       ast_nodes_(std::move(program.ast_nodes_)), | 
 |       sem_nodes_(std::move(program.sem_nodes_)), | 
 |       ast_(std::move(program.ast_)), | 
 |       sem_(std::move(program.sem_)), | 
 |       symbols_(std::move(program.symbols_)), | 
 |       diagnostics_(std::move(program.diagnostics_)), | 
 |       is_valid_(program.is_valid_) { | 
 |   program.AssertNotMoved(); | 
 |   program.moved_ = true; | 
 | } | 
 |  | 
 | Program::Program(ProgramBuilder&& builder) { | 
 |   is_valid_ = builder.IsValid(); | 
 |   if (builder.ResolveOnBuild() && builder.IsValid()) { | 
 |     resolver::Resolver resolver(&builder); | 
 |     if (!resolver.Resolve()) { | 
 |       diagnostics_.add_error(resolver.error()); | 
 |       is_valid_ = false; | 
 |     } | 
 |   } | 
 |  | 
 |   // The above must be called *before* the calls to std::move() below | 
 |  | 
 |   types_ = std::move(builder.Types()); | 
 |   ast_nodes_ = std::move(builder.ASTNodes()); | 
 |   sem_nodes_ = std::move(builder.SemNodes()); | 
 |   ast_ = ast_nodes_.Create<ast::Module>( | 
 |       Source{}, std::move(builder.AST().GlobalDeclarations())); | 
 |   sem_ = std::move(builder.Sem()); | 
 |   symbols_ = std::move(builder.Symbols()); | 
 |   diagnostics_.add(std::move(builder.Diagnostics())); | 
 |   builder.MarkAsMoved(); | 
 |  | 
 |   if (!is_valid_ && !diagnostics_.contains_errors()) { | 
 |     // If the builder claims to be invalid, then we really should have an error | 
 |     // message generated. If we find a situation where the program is not valid | 
 |     // and there are no errors reported, add one here. | 
 |     diagnostics_.add_error("invalid program generated"); | 
 |   } | 
 | } | 
 |  | 
 | Program::~Program() = default; | 
 |  | 
 | Program& Program::operator=(Program&& program) { | 
 |   program.AssertNotMoved(); | 
 |   program.moved_ = true; | 
 |   types_ = std::move(program.types_); | 
 |   ast_nodes_ = std::move(program.ast_nodes_); | 
 |   sem_nodes_ = std::move(program.sem_nodes_); | 
 |   ast_ = std::move(program.ast_); | 
 |   sem_ = std::move(program.sem_); | 
 |   symbols_ = std::move(program.symbols_); | 
 |   diagnostics_ = std::move(program.diagnostics_); | 
 |   is_valid_ = program.is_valid_; | 
 |   return *this; | 
 | } | 
 |  | 
 | Program Program::Clone() const { | 
 |   AssertNotMoved(); | 
 |   return Program(CloneAsBuilder()); | 
 | } | 
 |  | 
 | ProgramBuilder Program::CloneAsBuilder() const { | 
 |   AssertNotMoved(); | 
 |   ProgramBuilder out; | 
 |   CloneContext(&out, this).Clone(); | 
 |   return out; | 
 | } | 
 |  | 
 | bool Program::IsValid() const { | 
 |   AssertNotMoved(); | 
 |   return is_valid_; | 
 | } | 
 |  | 
 | type::Type* Program::TypeOf(const ast::Expression* expr) const { | 
 |   auto* sem = Sem().Get(expr); | 
 |   return sem ? sem->Type() : nullptr; | 
 | } | 
 |  | 
 | std::string Program::to_str(bool demangle) const { | 
 |   AssertNotMoved(); | 
 |   auto str = ast_->to_str(Sem()); | 
 |   if (demangle) { | 
 |     str = Demangler().Demangle(Symbols(), str); | 
 |   } | 
 |   return str; | 
 | } | 
 |  | 
 | std::string Program::str(const ast::Node* node) const { | 
 |   return Demangler().Demangle(Symbols(), node->str(Sem())); | 
 | } | 
 |  | 
 | void Program::AssertNotMoved() const { | 
 |   assert(!moved_); | 
 | } | 
 |  | 
 | }  // namespace tint |