Add semantic::MemberAccessorExpression, use it.

Pull the mutable 'is_swizzled' semantic field from ast::MemberAccessorExpression and into a new semantic::MemberAccessorExpression node.
Have the TypeDeterminer create these semantic::MemberAccessorExpression nodes.

Bug: tint:390
Change-Id: I8fc6e36dabb417190528536a94d027af54059222
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/40142
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: David Neto <dneto@google.com>
diff --git a/src/semantic/member_accessor_expression.h b/src/semantic/member_accessor_expression.h
new file mode 100644
index 0000000..7b21f97
--- /dev/null
+++ b/src/semantic/member_accessor_expression.h
@@ -0,0 +1,43 @@
+// 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_MEMBER_ACCESSOR_EXPRESSION_H_
+#define SRC_SEMANTIC_MEMBER_ACCESSOR_EXPRESSION_H_
+
+#include "src/semantic/expression.h"
+
+namespace tint {
+namespace semantic {
+
+/// MemberAccessorExpression holds the semantic information for a
+/// ast::MemberAccessorExpression node.
+class MemberAccessorExpression
+    : public Castable<MemberAccessorExpression, Expression> {
+ public:
+  /// Constructor
+  /// @param type the resolved type of the expression
+  /// @param is_swizzle true if this member access is for a vector swizzle
+  MemberAccessorExpression(type::Type* type, bool is_swizzle);
+
+  /// @return true if this member access is for a vector swizzle
+  bool IsSwizzle() const { return is_swizzle_; }
+
+ private:
+  bool const is_swizzle_;
+};
+
+}  // namespace semantic
+}  // namespace tint
+
+#endif  // SRC_SEMANTIC_MEMBER_ACCESSOR_EXPRESSION_H_
diff --git a/src/semantic/sem_member_accessor_expression.cc b/src/semantic/sem_member_accessor_expression.cc
new file mode 100644
index 0000000..1145a23
--- /dev/null
+++ b/src/semantic/sem_member_accessor_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/member_accessor_expression.h"
+
+TINT_INSTANTIATE_CLASS_ID(tint::semantic::MemberAccessorExpression);
+
+namespace tint {
+namespace semantic {
+
+MemberAccessorExpression::MemberAccessorExpression(type::Type* type,
+                                                   bool is_swizzle)
+    : Base(type), is_swizzle_(is_swizzle) {}
+
+}  // namespace semantic
+}  // namespace tint
diff --git a/src/semantic/type_mappings.h b/src/semantic/type_mappings.h
index 95c7fff..36ad538 100644
--- a/src/semantic/type_mappings.h
+++ b/src/semantic/type_mappings.h
@@ -25,6 +25,7 @@
 class CallExpression;
 class Expression;
 class Function;
+class MemberAccessorExpression;
 class Variable;
 
 }  // namespace ast
@@ -34,6 +35,7 @@
 class Call;
 class Expression;
 class Function;
+class MemberAccessorExpression;
 class Variable;
 
 /// TypeMappings is a struct that holds dummy `operator()` methods that's used
@@ -47,6 +49,8 @@
   semantic::Function* operator()(ast::Function*);
   semantic::Variable* operator()(ast::Variable*);
   semantic::Call* operator()(ast::CallExpression*);
+  semantic::MemberAccessorExpression* operator()(
+      ast::MemberAccessorExpression*);
   //! @endcond
 };