Add semantic::Expression, implement semantic::Info

semantic::Expression will hold the resolved expression type.
Migration to this will happen in the next change.

Bug: tint:390
Change-Id: I637eb6777d603ab0828c0e5e7126bd2ac1b0c4bc
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/39006
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
diff --git a/BUILD.gn b/BUILD.gn
index dc730a9..079bbd1 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -378,9 +378,13 @@
     "src/reader/reader.cc",
     "src/reader/reader.h",
     "src/scope_stack.h",
+    "src/semantic/expression.h",
     "src/semantic/info.h",
     "src/semantic/node.h",
+    "src/semantic/sem_expression.cc",
     "src/semantic/sem_info.cc",
+    "src/semantic/sem_node.cc",
+    "src/semantic/type_mappings.h",
     "src/source.cc",
     "src/source.h",
     "src/symbol.cc",
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index ba9685f..465e16f 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -192,9 +192,13 @@
   reader/reader.cc
   reader/reader.h
   scope_stack.h
+  semantic/expression.h
   semantic/info.h
   semantic/node.h
+  semantic/sem_expression.cc
   semantic/sem_info.cc
+  semantic/sem_node.cc
+  semantic/type_mappings.h
   source.cc
   source.h
   symbol.cc
@@ -451,7 +455,6 @@
     inspector/inspector_test.cc
     namer_test.cc
     program_test.cc
-    program_builder_test.cc
     scope_stack_test.cc
     symbol_table_test.cc
     symbol_test.cc
diff --git a/src/castable.h b/src/castable.h
index 1eb2cbc..afda1e0 100644
--- a/src/castable.h
+++ b/src/castable.h
@@ -62,6 +62,9 @@
 /// @see Castable
 class CastableBase {
  public:
+  /// Copy constructor
+  CastableBase(const CastableBase&) = default;
+
   /// Move constructor
   CastableBase(CastableBase&&) = default;
 
diff --git a/src/semantic/expression.h b/src/semantic/expression.h
new file mode 100644
index 0000000..40b15e4
--- /dev/null
+++ b/src/semantic/expression.h
@@ -0,0 +1,50 @@
+// 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_SEMANTIC_EXPRESSION_H_
+#define SRC_SEMANTIC_EXPRESSION_H_
+
+#include "src/semantic/node.h"
+
+#include "src/semantic/type_mappings.h"
+
+namespace tint {
+
+// Forward declarations
+namespace type {
+
+class Type;
+
+}  // namespace type
+
+namespace semantic {
+
+/// Expression holds the semantic information for expression nodes.
+class Expression : public Castable<Expression, Node> {
+ public:
+  /// Constructor
+  /// @param type the resolved type of the expression
+  explicit Expression(type::Type* type);
+
+  /// @return the resolved type of the expression
+  type::Type* Type() const { return type_; }
+
+ private:
+  type::Type* const type_;
+};
+
+}  // namespace semantic
+}  // namespace tint
+
+#endif  // SRC_SEMANTIC_EXPRESSION_H_
diff --git a/src/semantic/info.h b/src/semantic/info.h
index 4b36b2f..6e478ff 100644
--- a/src/semantic/info.h
+++ b/src/semantic/info.h
@@ -15,11 +15,23 @@
 #ifndef SRC_SEMANTIC_INFO_H_
 #define SRC_SEMANTIC_INFO_H_
 
+#include <assert.h>
+
+#include <unordered_map>
+
+#include "src/semantic/node.h"
+#include "src/semantic/type_mappings.h"
+
 namespace tint {
 
+// Forward declarations
+namespace ast {
+class Node;
+}  // namespace ast
+
 namespace semantic {
 
-/// Info will hold all the resolved semantic information for a Program.
+/// Info holds all the resolved semantic information for a Program.
 class Info {
  public:
   /// Constructor
@@ -36,6 +48,28 @@
   /// @return this Program
   Info& operator=(Info&& rhs);
 
+  /// Get looks up the semantic information for the AST node `ast_node`.
+  /// @param ast_node the AST node
+  /// @returns a pointer to the semantic node if found, otherwise nullptr
+  template <typename AST, typename SEM = SemanticNodeTypeFor<AST>>
+  const SEM* Get(const AST* ast_node) const {
+    auto it = ast_to_sem_.find(ast_node);
+    if (it == ast_to_sem_.end()) {
+      return nullptr;
+    }
+    return it->second->template As<SEM>();
+  }
+
+  /// Add registers the semantic node `sem_node` for the AST node `ast_node`.
+  /// @param ast_node the AST node
+  /// @param sem_node the semantic node
+  template <typename AST>
+  void Add(const AST* ast_node, const SemanticNodeTypeFor<AST>* sem_node) {
+    // Check there's no semantic info already existing for the node
+    assert(Get(ast_node) == nullptr);
+    ast_to_sem_.emplace(ast_node, sem_node);
+  }
+
   /// Wrap returns a new Info created with the contents of `inner`.
   /// The Info returned by Wrap is intended to temporarily extend the contents
   /// of an existing immutable Info.
@@ -44,9 +78,13 @@
   /// @param inner the immutable Info to extend
   /// @return the Info that wraps `inner`
   static Info Wrap(const Info& inner) {
-    (void)inner;
-    return Info();
+    Info out;
+    out.ast_to_sem_ = inner.ast_to_sem_;
+    return out;
   }
+
+ private:
+  std::unordered_map<const ast::Node*, const semantic::Node*> ast_to_sem_;
 };
 
 }  // namespace semantic
diff --git a/src/semantic/sem_expression.cc b/src/semantic/sem_expression.cc
new file mode 100644
index 0000000..52d13f7
--- /dev/null
+++ b/src/semantic/sem_expression.cc
@@ -0,0 +1,27 @@
+// 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/semantic/expression.h"
+
+#include "src/type/type.h"
+
+TINT_INSTANTIATE_CLASS_ID(tint::semantic::Expression);
+
+namespace tint {
+namespace semantic {
+
+Expression::Expression(type::Type* type) : type_(type->UnwrapIfNeeded()) {}
+
+}  // namespace semantic
+}  // namespace tint
diff --git a/src/semantic/sem_node.cc b/src/semantic/sem_node.cc
new file mode 100644
index 0000000..84be5ab
--- /dev/null
+++ b/src/semantic/sem_node.cc
@@ -0,0 +1,25 @@
+// 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/semantic/node.h"
+
+TINT_INSTANTIATE_CLASS_ID(tint::semantic::Node);
+
+namespace tint {
+namespace semantic {
+
+Node::~Node() = default;
+
+}  // namespace semantic
+}  // namespace tint
diff --git a/src/semantic/type_mappings.h b/src/semantic/type_mappings.h
new file mode 100644
index 0000000..4c59bd3
--- /dev/null
+++ b/src/semantic/type_mappings.h
@@ -0,0 +1,53 @@
+// 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_SEMANTIC_TYPE_MAPPINGS_H_
+#define SRC_SEMANTIC_TYPE_MAPPINGS_H_
+
+#include <type_traits>
+
+namespace tint {
+
+// Forward declarations
+namespace ast {
+
+class Expression;
+
+}  // namespace ast
+
+namespace semantic {
+
+class Expression;
+
+/// TypeMappings is a struct that holds dummy `operator()` methods that's used
+/// by SemanticNodeTypeFor to map AST node types to their corresponding semantic
+/// node types.
+/// The standard operator overload resolving rules will be used to infer the
+/// return type based on the argument type.
+struct TypeMappings {
+  //! @cond Doxygen_Suppress
+  semantic::Expression* operator()(ast::Expression*);
+  //! @endcond
+};
+
+/// SemanticNodeTypeFor resolves to the appropriate semantic::Node type for the
+/// AST node type `AST`.
+template <typename AST>
+using SemanticNodeTypeFor = typename std::remove_pointer<decltype(
+    TypeMappings()(std::declval<AST*>()))>::type;
+
+}  // namespace semantic
+}  // namespace tint
+
+#endif  // SRC_SEMANTIC_TYPE_MAPPINGS_H_