// 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 #include #include "src/ast/module.h" #include "src/clone_context.h" #include "src/program_builder.h" #include "src/type_determiner.h" namespace tint { Program::Program() = default; Program::Program(Program&& program) : types_(std::move(program.types_)), nodes_(std::move(program.nodes_)), ast_(std::move(program.ast_)), 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()) { TypeDeterminer td(&builder); if (!td.Determine()) { diagnostics_.add_error(td.error()); } } // The above must be called *before* the calls to std::move() below types_ = std::move(builder.Types()); nodes_ = std::move(builder.Nodes()); ast_ = nodes_.Create(Source{}, builder.AST().ConstructedTypes(), builder.AST().Functions(), builder.AST().GlobalVariables()); symbols_ = std::move(builder.Symbols()); diagnostics_ = 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_); nodes_ = std::move(program.nodes_); ast_ = std::move(program.ast_); symbols_ = std::move(program.symbols_); 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_; } std::string Program::to_str() const { AssertNotMoved(); return ast_->to_str(); } void Program::AssertNotMoved() const { assert(!moved_); } } // namespace tint