tint: Add sem::Expression

A new base class for sem::ValueExpression, which other types of
expression can derive from.

Example: sem::TypeExpression - an expression that resolves to a type.

Bug: tint:1810
Change-Id: I90dfb66b265b67d9fdf0c04eb3dce2442c7e18ea
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/118404
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: James Price <jrprice@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
diff --git a/src/tint/sem/expression.cc b/src/tint/sem/expression.cc
new file mode 100644
index 0000000..f491ab4
--- /dev/null
+++ b/src/tint/sem/expression.cc
@@ -0,0 +1,26 @@
+// Copyright 2023 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/tint/sem/expression.h"
+
+TINT_INSTANTIATE_TYPEINFO(tint::sem::Expression);
+
+namespace tint::sem {
+
+Expression::Expression(const ast::Expression* declaration, const Statement* statement)
+    : declaration_(declaration), statement_(statement) {}
+
+Expression::~Expression() = default;
+
+}  // namespace tint::sem
diff --git a/src/tint/sem/expression.h b/src/tint/sem/expression.h
new file mode 100644
index 0000000..884ff4d
--- /dev/null
+++ b/src/tint/sem/expression.h
@@ -0,0 +1,55 @@
+// Copyright 2023 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_TINT_SEM_EXPRESSION_H_
+#define SRC_TINT_SEM_EXPRESSION_H_
+
+#include "src/tint/ast/expression.h"
+#include "src/tint/sem/node.h"
+
+// Forward declarations
+namespace tint::sem {
+class Statement;
+}  // namespace tint::sem
+
+namespace tint::sem {
+
+/// Expression holds the semantic information for expression nodes.
+class Expression : public Castable<Expression, Node> {
+  public:
+    /// Constructor
+    /// @param declaration the AST node
+    /// @param statement the statement that owns this expression
+    Expression(const ast::Expression* declaration, const Statement* statement);
+
+    /// Destructor
+    ~Expression() override;
+
+    /// @returns the AST node
+    const ast::Expression* Declaration() const { return declaration_; }
+
+    /// @return the statement that owns this expression
+    const Statement* Stmt() const { return statement_; }
+
+  protected:
+    /// The AST expression node for this semantic expression
+    const ast::Expression* const declaration_;
+
+  private:
+    const Statement* const statement_;
+};
+
+}  // namespace tint::sem
+
+#endif  // SRC_TINT_SEM_EXPRESSION_H_
diff --git a/src/tint/sem/info.h b/src/tint/sem/info.h
index 43a158e..2ce46f5 100644
--- a/src/tint/sem/info.h
+++ b/src/tint/sem/info.h
@@ -30,6 +30,7 @@
 // Forward declarations
 namespace tint::sem {
 class Module;
+class ValueExpression;
 }  // namespace tint::sem
 namespace tint::type {
 class Node;
@@ -88,6 +89,14 @@
         return nullptr;
     }
 
+    /// Convenience function that's an alias for Get<ValueExpression>()
+    /// @param ast_node the AST node
+    /// @returns a pointer to the semantic node if found, otherwise nullptr
+    template <typename AST>
+    const sem::ValueExpression* GetVal(const AST* ast_node) const {
+        return Get<ValueExpression>(ast_node);
+    }
+
     /// 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
diff --git a/src/tint/sem/type_mappings.h b/src/tint/sem/type_mappings.h
index 40e287c..419a9c2 100644
--- a/src/tint/sem/type_mappings.h
+++ b/src/tint/sem/type_mappings.h
@@ -22,13 +22,19 @@
 class CastableBase;
 }  // namespace tint
 namespace tint::ast {
+class AccessorExpression;
 class Array;
+class BinaryExpression;
+class BitcastExpression;
+class CallExpression;
 class Expression;
 class ForLoopStatement;
 class Function;
 class IfStatement;
+class LiteralExpression;
 class Node;
 class Override;
+class PhonyExpression;
 class Statement;
 class Struct;
 class StructMember;
@@ -37,8 +43,10 @@
 class TypeDecl;
 class Variable;
 class WhileStatement;
+class UnaryOpExpression;
 }  // namespace tint::ast
 namespace tint::sem {
+class Expression;
 class ForLoopStatement;
 class Function;
 class GlobalVariable;
@@ -77,17 +85,24 @@
     SwitchStatement* operator()(ast::SwitchStatement*);
     type::Type* operator()(ast::Type*);
     type::Type* operator()(ast::TypeDecl*);
-    ValueExpression* operator()(ast::Expression*);
+    Expression* operator()(ast::Expression*);
+    ValueExpression* operator()(ast::AccessorExpression*);
+    ValueExpression* operator()(ast::CallExpression*);
+    ValueExpression* operator()(ast::BinaryExpression*);
+    ValueExpression* operator()(ast::BitcastExpression*);
+    ValueExpression* operator()(ast::LiteralExpression*);
+    ValueExpression* operator()(ast::PhonyExpression*);
+    ValueExpression* operator()(ast::UnaryOpExpression*);
     Variable* operator()(ast::Variable*);
     WhileStatement* operator()(ast::WhileStatement*);
     //! @endcond
 };
 
 /// SemanticNodeTypeFor resolves to the appropriate sem::Node type for the
-/// AST or type node `AST_OR_TYPE`.
-template <typename AST_OR_TYPE>
+/// AST node `AST`.
+template <typename AST>
 using SemanticNodeTypeFor =
-    typename std::remove_pointer<decltype(TypeMappings()(std::declval<AST_OR_TYPE*>()))>::type;
+    typename std::remove_pointer<decltype(TypeMappings()(std::declval<AST*>()))>::type;
 
 }  // namespace tint::sem
 
diff --git a/src/tint/sem/value_expression.cc b/src/tint/sem/value_expression.cc
index de3c4cf..9fe4615 100644
--- a/src/tint/sem/value_expression.cc
+++ b/src/tint/sem/value_expression.cc
@@ -30,11 +30,10 @@
                                  const constant::Value* constant,
                                  bool has_side_effects,
                                  const Variable* root_ident /* = nullptr */)
-    : declaration_(declaration),
+    : Base(declaration, statement),
       root_identifier_(root_ident),
       type_(type),
       stage_(stage),
-      statement_(statement),
       constant_(std::move(constant)),
       has_side_effects_(has_side_effects) {
     TINT_ASSERT(Semantic, type_);
diff --git a/src/tint/sem/value_expression.h b/src/tint/sem/value_expression.h
index 9840c11..a6fb624 100644
--- a/src/tint/sem/value_expression.h
+++ b/src/tint/sem/value_expression.h
@@ -15,11 +15,10 @@
 #ifndef SRC_TINT_SEM_VALUE_EXPRESSION_H_
 #define SRC_TINT_SEM_VALUE_EXPRESSION_H_
 
-#include "src/tint/ast/expression.h"
 #include "src/tint/constant/value.h"
 #include "src/tint/sem/behavior.h"
 #include "src/tint/sem/evaluation_stage.h"
-#include "src/tint/sem/node.h"
+#include "src/tint/sem/expression.h"
 
 // Forward declarations
 namespace tint::sem {
@@ -30,7 +29,7 @@
 namespace tint::sem {
 
 /// ValueExpression holds the semantic information for expression nodes.
-class ValueExpression : public Castable<ValueExpression, Node> {
+class ValueExpression : public Castable<ValueExpression, Expression> {
   public:
     /// Constructor
     /// @param declaration the AST node
@@ -51,18 +50,12 @@
     /// Destructor
     ~ValueExpression() override;
 
-    /// @returns the AST node
-    const ast::Expression* Declaration() const { return declaration_; }
-
     /// @return the resolved type of the expression
     const type::Type* Type() const { return type_; }
 
     /// @return the earliest evaluation stage for the expression
     EvaluationStage Stage() const { return stage_; }
 
-    /// @return the statement that owns this expression
-    const Statement* Stmt() const { return statement_; }
-
     /// @return the constant value of this expression
     const constant::Value* ConstantValue() const { return constant_; }
 
@@ -92,15 +85,12 @@
     const ValueExpression* Unwrap() const;
 
   protected:
-    /// The AST expression node for this semantic expression
-    const ast::Expression* const declaration_;
     /// The root identifier for this semantic expression, or nullptr
     const Variable* root_identifier_;
 
   private:
     const type::Type* const type_;
     const EvaluationStage stage_;
-    const Statement* const statement_;
     const constant::Value* const constant_;
     sem::Behaviors behaviors_{sem::Behavior::kNext};
     const bool has_side_effects_;