diff --git a/src/ast/module.cc b/src/ast/module.cc index 0de64bbd81..e39e0487c2 100644 --- a/src/ast/module.cc +++ b/src/ast/module.cc @@ -1,4 +1,4 @@ -// Copyright 2020 The Tint Authors. +// 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. @@ -14,10 +14,104 @@ #include "src/ast/module.h" +#include +#include +#include + +#include "src/clone_context.h" +#include "src/program.h" +#include "src/type/alias_type.h" +#include "src/type/struct_type.h" + +TINT_INSTANTIATE_CLASS_ID(tint::ast::Module); + namespace tint { namespace ast { -// Placeholder +Module::Module() : Base(Source{}) {} + +Module::Module(std::vector constructed_types, + FunctionList functions, + VariableList global_variables) + : Base(Source{}), + constructed_types_(std::move(constructed_types)), + functions_(std::move(functions)), + global_variables_(std::move(global_variables)) {} + +Module::~Module() = default; + +bool Module::IsValid() const { + for (auto* var : global_variables_) { + if (var == nullptr || !var->IsValid()) { + return false; + } + } + for (auto* const ty : constructed_types_) { + if (ty == nullptr) { + return false; + } + if (auto* alias = ty->As()) { + if (alias->type() == nullptr) { + return false; + } + if (auto* str = alias->type()->As()) { + if (!str->symbol().IsValid()) { + return false; + } + } + } else if (auto* str = ty->As()) { + if (!str->symbol().IsValid()) { + return false; + } + } else { + return false; + } + } + for (auto* func : functions_) { + if (func == nullptr || !func->IsValid()) { + return false; + } + } + return true; +} + +Module* Module::Clone(CloneContext* ctx) const { + return ctx->dst->create(ctx->Clone(constructed_types_), + ctx->Clone(functions_), + ctx->Clone(global_variables_)); +} + +void Module::to_str(std::ostream& out, size_t indent) const { + make_indent(out, indent); + out << "Module{" << std::endl; + indent += 2; + for (auto* const ty : constructed_types_) { + make_indent(out, indent); + if (auto* alias = ty->As()) { + out << alias->symbol().to_str() << " -> " << alias->type()->type_name() + << std::endl; + if (auto* str = alias->type()->As()) { + str->impl()->to_str(out, indent); + } + } else if (auto* str = ty->As()) { + out << str->symbol().to_str() << " "; + str->impl()->to_str(out, indent); + } + } + for (auto* var : global_variables_) { + var->to_str(out, indent); + } + for (auto* func : functions_) { + func->to_str(out, indent); + } + out << "}" << std::endl; +} + +std::string Module::to_str() const { + std::ostringstream out; + to_str(out, 0); + return out.str(); +} } // namespace ast } // namespace tint diff --git a/src/ast/module.h b/src/ast/module.h index 3e2beebfd8..7227131fb6 100644 --- a/src/ast/module.h +++ b/src/ast/module.h @@ -1,4 +1,4 @@ -// Copyright 2020 The Tint Authors. +// 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. @@ -15,10 +15,89 @@ #ifndef SRC_AST_MODULE_H_ #define SRC_AST_MODULE_H_ +#include +#include + +#include "src/ast/function.h" +#include "src/ast/node.h" +#include "src/ast/variable.h" +#include "src/type/type.h" + namespace tint { namespace ast { -// Placeholder +/// Module holds the top-level AST types, functions and global variables used by +/// a Program. +class Module : public Castable { + public: + /// Constructor + Module(); + + /// Constructor + /// @param constructed_types the list of types explicitly declared in the AST + /// @param functions the list of program functions + /// @param global_variables the list of global variables + Module(std::vector constructed_types, + FunctionList functions, + VariableList global_variables); + + /// Destructor + ~Module() override; + + /// Add a global variable to the Builder + /// @param var the variable to add + void AddGlobalVariable(ast::Variable* var) { + global_variables_.push_back(var); + } + + /// @returns the global variables for the translation unit + const VariableList& GlobalVariables() const { return global_variables_; } + + /// @returns the global variables for the translation unit + VariableList& GlobalVariables() { return global_variables_; } + + /// Adds a constructed type to the Builder. + /// The type must be an alias or a struct. + /// @param type the constructed type to add + void AddConstructedType(type::Type* type) { + constructed_types_.push_back(type); + } + + /// @returns the constructed types in the translation unit + const std::vector& ConstructedTypes() const { + return constructed_types_; + } + + /// @returns the functions declared in the translation unit + const FunctionList& Functions() const { return functions_; } + + /// @returns the functions declared in the translation unit + FunctionList& Functions() { return functions_; } + + /// @returns true if all required fields in the AST are present. + bool IsValid() const override; + + /// Clones this node and all transitive child nodes using the `CloneContext` + /// `ctx`. + /// @note Semantic information such as resolved expression type and intrinsic + /// information is not cloned. + /// @param ctx the clone context + /// @return the newly cloned node + Module* Clone(CloneContext* ctx) const override; + + /// Writes a representation of the node to the output stream + /// @param out the stream to write to + /// @param indent number of spaces to indent the node when writing + void to_str(std::ostream& out, size_t indent) const override; + + /// @returns a string representation of the Builder + std::string to_str() const; + + private: + std::vector constructed_types_; + FunctionList functions_; + VariableList global_variables_; +}; } // namespace ast } // namespace tint diff --git a/src/clone_context.cc b/src/clone_context.cc index 5eb1a86cf7..f9862443cc 100644 --- a/src/clone_context.cc +++ b/src/clone_context.cc @@ -30,4 +30,13 @@ void CloneContext::Clone() { src->Clone(this); } +ast::FunctionList CloneContext::Clone(const ast::FunctionList& v) { + ast::FunctionList out; + out.reserve(v.size()); + for (ast::Function* el : v) { + out.Add(Clone(el)); + } + return out; +} + } // namespace tint diff --git a/src/clone_context.h b/src/clone_context.h index 1f742b931b..fc391b015b 100644 --- a/src/clone_context.h +++ b/src/clone_context.h @@ -19,6 +19,7 @@ #include #include +#include "src/ast/function.h" #include "src/castable.h" #include "src/source.h" #include "src/symbol.h" @@ -106,6 +107,14 @@ class CloneContext { return out; } + /// Clones each of the elements of the vector `v` into the Program #dst. + /// + /// All the elements of the vector `v` must be owned by the Program #src. + /// + /// @param v the vector to clone + /// @return the cloned vector + ast::FunctionList Clone(const ast::FunctionList& v); + /// ReplaceAll() registers `replacer` to be called whenever the Clone() method /// is called with a type that matches (or derives from) the type of the /// second parameter of `replacer`. diff --git a/src/program.cc b/src/program.cc index 5ae2e26621..07fa1d51aa 100644 --- a/src/program.cc +++ b/src/program.cc @@ -21,9 +21,9 @@ namespace tint { -Program::Program() = default; +Program::Program() : ast_(nodes_.Create()) {} -Program::Program(Program&&) = default; +Program::Program(Program&& rhs) = default; Program& Program::operator=(Program&& rhs) = default; @@ -36,93 +36,35 @@ Program Program::Clone() const { } void Program::Clone(CloneContext* ctx) const { - for (auto* ty : constructed_types_) { - ctx->dst->constructed_types_.emplace_back(ctx->Clone(ty)); + for (auto* ty : AST().ConstructedTypes()) { + ctx->dst->AST().AddConstructedType(ctx->Clone(ty)); } - for (auto* var : global_variables_) { - ctx->dst->global_variables_.emplace_back(ctx->Clone(var)); + for (auto* var : AST().GlobalVariables()) { + ctx->dst->AST().AddGlobalVariable(ctx->Clone(var)); } - for (auto* func : functions_) { - ctx->dst->functions_.emplace_back(ctx->Clone(func)); + for (auto* func : AST().Functions()) { + ctx->dst->AST().Functions().Add(ctx->Clone(func)); } } Symbol Program::RegisterSymbol(const std::string& name) { - return symbol_table_.Register(name); + return symbols_.Register(name); } Symbol Program::GetSymbol(const std::string& name) const { - return symbol_table_.Get(name); + return symbols_.Get(name); } std::string Program::SymbolToName(const Symbol sym) const { - return symbol_table_.NameFor(sym); + return symbols_.NameFor(sym); } bool Program::IsValid() const { - for (auto* var : global_variables_) { - if (var == nullptr || !var->IsValid()) { - return false; - } - } - for (auto* const ty : constructed_types_) { - if (ty == nullptr) { - return false; - } - if (auto* alias = ty->As()) { - if (alias->type() == nullptr) { - return false; - } - if (auto* str = alias->type()->As()) { - if (!str->symbol().IsValid()) { - return false; - } - } - } else if (auto* str = ty->As()) { - if (!str->symbol().IsValid()) { - return false; - } - } else { - return false; - } - } - for (auto* func : functions_) { - if (func == nullptr || !func->IsValid()) { - return false; - } - } - return true; + return ast_->IsValid(); } std::string Program::to_str() const { - std::ostringstream out; - - out << "Module{" << std::endl; - const auto indent = 2; - for (auto* const ty : constructed_types_) { - for (size_t i = 0; i < indent; ++i) { - out << " "; - } - if (auto* alias = ty->As()) { - out << alias->symbol().to_str() << " -> " << alias->type()->type_name() - << std::endl; - if (auto* str = alias->type()->As()) { - str->impl()->to_str(out, indent); - } - } else if (auto* str = ty->As()) { - out << str->symbol().to_str() << " "; - str->impl()->to_str(out, indent); - } - } - for (auto* var : global_variables_) { - var->to_str(out, indent); - } - for (auto* func : functions_) { - func->to_str(out, indent); - } - out << "}" << std::endl; - - return out.str(); + return ast_->to_str(); } } // namespace tint diff --git a/src/program.h b/src/program.h index e232c3b11d..5ba6dfeb4a 100644 --- a/src/program.h +++ b/src/program.h @@ -24,6 +24,7 @@ #include #include "src/ast/function.h" +#include "src/ast/module.h" #include "src/ast/variable.h" #include "src/block_allocator.h" #include "src/symbol_table.h" @@ -36,11 +37,15 @@ namespace tint { /// Represents all the source in a given program. class Program { public: + /// ASTNodes is an alias to BlockAllocator + using ASTNodes = BlockAllocator; + /// Constructor Program(); /// Move constructor - Program(Program&&); + /// @param rhs the Program to move + Program(Program&& rhs); /// Move assignment operator /// @param rhs the Program to move @@ -50,10 +55,28 @@ class Program { /// Destructor ~Program(); + /// @returns a reference to the program's types + const type::Manager& Types() const { return types_; } + + /// @returns a reference to the program's AST nodes storage + const ASTNodes& Nodes() const { return nodes_; } + + /// @returns a reference to the program's AST root Module + const ast::Module& AST() const { return *ast_; } + + /// @returns a reference to the program's AST root Module + ast::Module& AST() { return *ast_; } + + /// @returns a reference to the program's SymbolTable + const SymbolTable& Symbols() const { return symbols_; } + + /// @returns a reference to the program's SymbolTable + SymbolTable& Symbols() { return symbols_; } + /// @return a deep copy of this program Program Clone() const; - /// Clone this program into `ctx->mod` using the provided CloneContext + /// Clone this program into `ctx->dst` using the provided CloneContext /// The program will be cloned in this order: /// * Constructed types /// * Global variables @@ -61,36 +84,6 @@ class Program { /// @param ctx the clone context void Clone(CloneContext* ctx) const; - /// Add a global variable to the program - /// @param var the variable to add - void AddGlobalVariable(ast::Variable* var) { - global_variables_.push_back(var); - } - /// @returns the global variables for the program - const ast::VariableList& global_variables() const { - return global_variables_; - } - - /// @returns the global variables for the program - ast::VariableList& global_variables() { return global_variables_; } - - /// Adds a constructed type to the program. - /// The type must be an alias or a struct. - /// @param type the constructed type to add - void AddConstructedType(type::Type* type) { - constructed_types_.push_back(type); - } - /// @returns the constructed types in the program - const std::vector& constructed_types() const { - return constructed_types_; - } - - /// @returns the functions declared in the translation unit - const ast::FunctionList& Functions() const { return functions_; } - - /// @returns the functions declared in the translation unit - ast::FunctionList& Functions() { return functions_; } - /// @returns true if all required fields in the AST are present. bool IsValid() const; @@ -103,7 +96,7 @@ class Program { /// @returns the node pointer template traits::EnableIfIsType* create(ARGS&&... args) { - return ast_nodes_.Create(std::forward(args)...); + return nodes_.Create(std::forward(args)...); } /// Creates a new type::Type owned by the Program. @@ -122,44 +115,83 @@ class Program { traits::EnableIfIsType* create(ARGS&&... args) { static_assert(std::is_base_of::value, "T does not derive from type::Type"); - return type_mgr_.Get(std::forward(args)...); + return types_.Get(std::forward(args)...); } + /// Add a global variable to the program + /// [DEPRECATED]: Use AST().AddGlobalVariable(var) + /// @param var the variable to add + void AddGlobalVariable(ast::Variable* var) { AST().AddGlobalVariable(var); } + + /// [DEPRECATED]: Use AST().GlobalVariables() + /// @returns the global variables for the program + const ast::VariableList& global_variables() const { + return AST().GlobalVariables(); + } + + /// [DEPRECATED]: Use AST().GlobalVariables() + /// @returns the global variables for the program + ast::VariableList& global_variables() { return AST().GlobalVariables(); } + + /// Adds a constructed type to the program. + /// The type must be an alias or a struct. + /// [DEPRECATED]: Use AST().AddConstructedType(type) + /// @param type the constructed type to add + void AddConstructedType(type::Type* type) { AST().AddConstructedType(type); } + + /// @returns the constructed types in the program + /// [DEPRECATED]: Use AST().ConstructedTypes() + const std::vector& constructed_types() const { + return AST().ConstructedTypes(); + } + + /// @returns the functions declared in the translation unit + /// [DEPRECATED]: Use AST().Functions() + const ast::FunctionList& Functions() const { return AST().Functions(); } + + /// @returns the functions declared in the translation unit + /// [DEPRECATED]: Use AST().Functions() + ast::FunctionList& Functions() { return AST().Functions(); } + /// Returns all the declared types in the program + /// [DEPRECATED]: Use AST().Types().types() /// @returns the mapping from name string to type. const std::unordered_map& types() { - return type_mgr_.types(); + return types_.types(); } /// @returns all the declared nodes in the program - BlockAllocator::View nodes() { return ast_nodes_.Objects(); } + /// [DEPRECATED]: Use Nodes().Objects() + BlockAllocator::ConstView nodes() const { + return Nodes().Objects(); + } /// Registers `name` as a symbol /// @param name the name to register /// @returns the symbol for the `name`. If `name` is already registered the /// previously generated symbol will be returned. + /// [DEPRECATED]: Use Symbols().Register() Symbol RegisterSymbol(const std::string& name); /// Returns the symbol for `name` /// @param name the name to lookup /// @returns the symbol for name or symbol::kInvalid + /// [DEPRECATED]: Use Symbols().Get() Symbol GetSymbol(const std::string& name) const; /// Returns the `name` for `sym` /// @param sym the symbol to retrieve the name for /// @returns the use provided `name` for the symbol or "" if not found + /// [DEPRECATED]: Use Symbols().NameFor() std::string SymbolToName(const Symbol sym) const; private: Program(const Program&) = delete; - SymbolTable symbol_table_; - ast::VariableList global_variables_; - // The constructed types are owned by the type manager - std::vector constructed_types_; - ast::FunctionList functions_; - BlockAllocator ast_nodes_; - type::Manager type_mgr_; + type::Manager types_; + ASTNodes nodes_; + ast::Module* ast_; + SymbolTable symbols_; }; } // namespace tint