Reintroduce ast::Module as the root AST structure

Holds the global variables, constructed types and functions.

Deprecate the functions on program that forward on to the module.
These will be fixed up in another change.

Bug: tint:390
Change-Id: I47b6921a7d84be18113dec830c8435d4e0d4182d
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/38544
Reviewed-by: dan sinclair <dsinclair@chromium.org>
diff --git a/src/ast/module.cc b/src/ast/module.cc
index 0de64bb..e39e048 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 <sstream>
+#include <string>
+#include <utility>
+
+#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<type::Type*> 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<type::Alias>()) {
+      if (alias->type() == nullptr) {
+        return false;
+      }
+      if (auto* str = alias->type()->As<type::Struct>()) {
+        if (!str->symbol().IsValid()) {
+          return false;
+        }
+      }
+    } else if (auto* str = ty->As<type::Struct>()) {
+      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<Module>(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<type::Alias>()) {
+      out << alias->symbol().to_str() << " -> " << alias->type()->type_name()
+          << std::endl;
+      if (auto* str = alias->type()->As<type::Struct>()) {
+        str->impl()->to_str(out, indent);
+      }
+    } else if (auto* str = ty->As<type::Struct>()) {
+      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