Add SamplerType to AST.

This CL adds the sampler type into the AST.

Bug: tint:141
Change-Id: Id2f7678a2df677cb7dae47f05543c1e0a1999eed
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/26080
Reviewed-by: David Neto <dneto@google.com>
diff --git a/BUILD.gn b/BUILD.gn
index 8789413..2a25855 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -331,6 +331,8 @@
     "src/ast/type/matrix_type.h",
     "src/ast/type/pointer_type.cc",
     "src/ast/type/pointer_type.h",
+    "src/ast/type/sampler_type.cc",
+    "src/ast/type/sampler_type.h",
     "src/ast/type/struct_type.cc",
     "src/ast/type/struct_type.h",
     "src/ast/type/type.cc",
@@ -714,6 +716,7 @@
     "src/ast/type/i32_type_test.cc",
     "src/ast/type/matrix_type_test.cc",
     "src/ast/type/pointer_type_test.cc",
+    "src/ast/type/sampler_type_test.cc",
     "src/ast/type/struct_type_test.cc",
     "src/ast/type/u32_type_test.cc",
     "src/ast/type/vector_type_test.cc",
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 5a70f60..3a9e778 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -152,6 +152,8 @@
   ast/type/matrix_type.h
   ast/type/pointer_type.cc
   ast/type/pointer_type.h
+  ast/type/sampler_type.cc
+  ast/type/sampler_type.h
   ast/type/struct_type.cc
   ast/type/struct_type.h
   ast/type/type.cc
@@ -322,6 +324,7 @@
   ast/type/i32_type_test.cc
   ast/type/matrix_type_test.cc
   ast/type/pointer_type_test.cc
+  ast/type/sampler_type_test.cc
   ast/type/struct_type_test.cc
   ast/type/u32_type_test.cc
   ast/type/vector_type_test.cc
diff --git a/src/ast/type/alias_type_test.cc b/src/ast/type/alias_type_test.cc
index 35b85f8..285873d 100644
--- a/src/ast/type/alias_type_test.cc
+++ b/src/ast/type/alias_type_test.cc
@@ -45,6 +45,7 @@
   EXPECT_FALSE(at.IsI32());
   EXPECT_FALSE(at.IsMatrix());
   EXPECT_FALSE(at.IsPointer());
+  EXPECT_FALSE(at.IsSampler());
   EXPECT_FALSE(at.IsStruct());
   EXPECT_FALSE(at.IsU32());
   EXPECT_FALSE(at.IsVector());
diff --git a/src/ast/type/array_type_test.cc b/src/ast/type/array_type_test.cc
index 678fee5..d6e63e5 100644
--- a/src/ast/type/array_type_test.cc
+++ b/src/ast/type/array_type_test.cc
@@ -54,6 +54,7 @@
   EXPECT_FALSE(arr.IsI32());
   EXPECT_FALSE(arr.IsMatrix());
   EXPECT_FALSE(arr.IsPointer());
+  EXPECT_FALSE(arr.IsSampler());
   EXPECT_FALSE(arr.IsStruct());
   EXPECT_FALSE(arr.IsU32());
   EXPECT_FALSE(arr.IsVector());
diff --git a/src/ast/type/bool_type_test.cc b/src/ast/type/bool_type_test.cc
index 55e406d..e526c48 100644
--- a/src/ast/type/bool_type_test.cc
+++ b/src/ast/type/bool_type_test.cc
@@ -32,6 +32,7 @@
   EXPECT_FALSE(b.IsI32());
   EXPECT_FALSE(b.IsMatrix());
   EXPECT_FALSE(b.IsPointer());
+  EXPECT_FALSE(b.IsSampler());
   EXPECT_FALSE(b.IsStruct());
   EXPECT_FALSE(b.IsU32());
   EXPECT_FALSE(b.IsVector());
diff --git a/src/ast/type/f32_type_test.cc b/src/ast/type/f32_type_test.cc
index 1717956..30a8d04 100644
--- a/src/ast/type/f32_type_test.cc
+++ b/src/ast/type/f32_type_test.cc
@@ -32,6 +32,7 @@
   EXPECT_FALSE(f.IsI32());
   EXPECT_FALSE(f.IsMatrix());
   EXPECT_FALSE(f.IsPointer());
+  EXPECT_FALSE(f.IsSampler());
   EXPECT_FALSE(f.IsStruct());
   EXPECT_FALSE(f.IsU32());
   EXPECT_FALSE(f.IsVector());
diff --git a/src/ast/type/i32_type_test.cc b/src/ast/type/i32_type_test.cc
index 7697fc7..8408ca9 100644
--- a/src/ast/type/i32_type_test.cc
+++ b/src/ast/type/i32_type_test.cc
@@ -32,6 +32,7 @@
   EXPECT_TRUE(i.IsI32());
   EXPECT_FALSE(i.IsMatrix());
   EXPECT_FALSE(i.IsPointer());
+  EXPECT_FALSE(i.IsSampler());
   EXPECT_FALSE(i.IsStruct());
   EXPECT_FALSE(i.IsU32());
   EXPECT_FALSE(i.IsVector());
diff --git a/src/ast/type/matrix_type_test.cc b/src/ast/type/matrix_type_test.cc
index 4fcd024..888d27f 100644
--- a/src/ast/type/matrix_type_test.cc
+++ b/src/ast/type/matrix_type_test.cc
@@ -42,6 +42,7 @@
   EXPECT_FALSE(m.IsI32());
   EXPECT_TRUE(m.IsMatrix());
   EXPECT_FALSE(m.IsPointer());
+  EXPECT_FALSE(m.IsSampler());
   EXPECT_FALSE(m.IsStruct());
   EXPECT_FALSE(m.IsU32());
   EXPECT_FALSE(m.IsVector());
diff --git a/src/ast/type/pointer_type_test.cc b/src/ast/type/pointer_type_test.cc
index 8889cb8..4e09c95 100644
--- a/src/ast/type/pointer_type_test.cc
+++ b/src/ast/type/pointer_type_test.cc
@@ -41,6 +41,7 @@
   EXPECT_FALSE(p.IsI32());
   EXPECT_FALSE(p.IsMatrix());
   EXPECT_TRUE(p.IsPointer());
+  EXPECT_FALSE(p.IsSampler());
   EXPECT_FALSE(p.IsStruct());
   EXPECT_FALSE(p.IsU32());
   EXPECT_FALSE(p.IsVector());
diff --git a/src/ast/type/sampler_type.cc b/src/ast/type/sampler_type.cc
new file mode 100644
index 0000000..ccbd3fa
--- /dev/null
+++ b/src/ast/type/sampler_type.cc
@@ -0,0 +1,50 @@
+// Copyright 2020 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/ast/type/sampler_type.h"
+
+namespace tint {
+namespace ast {
+namespace type {
+
+std::ostream& operator<<(std::ostream& out, SamplerKind kind) {
+  switch (kind) {
+    case SamplerKind::kSampler:
+      out << "sampler";
+      break;
+    case SamplerKind::kComparisonSampler:
+      out << "comparison_sampler";
+      break;
+  }
+  return out;
+}
+
+SamplerType::SamplerType(SamplerKind kind) : kind_(kind) {}
+
+SamplerType::SamplerType(SamplerType&&) = default;
+
+SamplerType::~SamplerType() = default;
+
+bool SamplerType::IsSampler() const {
+  return true;
+}
+
+std::string SamplerType::type_name() const {
+  return std::string("__sampler_") +
+         (kind_ == SamplerKind::kSampler ? "sampler" : "comparison");
+}
+
+}  // namespace type
+}  // namespace ast
+}  // namespace tint
diff --git a/src/ast/type/sampler_type.h b/src/ast/type/sampler_type.h
new file mode 100644
index 0000000..74e0443
--- /dev/null
+++ b/src/ast/type/sampler_type.h
@@ -0,0 +1,66 @@
+// Copyright 2020 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_AST_TYPE_SAMPLER_TYPE_H_
+#define SRC_AST_TYPE_SAMPLER_TYPE_H_
+
+#include <ostream>
+#include <string>
+
+#include "src/ast/type/type.h"
+
+namespace tint {
+namespace ast {
+namespace type {
+
+/// The different kinds of samplers
+enum class SamplerKind {
+  /// A regular sampler
+  kSampler,
+  /// A comparison sampler
+  kComparisonSampler
+};
+std::ostream& operator<<(std::ostream& out, SamplerKind kind);
+
+/// A sampler type.
+class SamplerType : public Type {
+ public:
+  /// Constructor
+  /// @param kind the kind of sampler
+  explicit SamplerType(SamplerKind kind);
+  /// Move constructor
+  SamplerType(SamplerType&&);
+  ~SamplerType() override;
+
+  /// @returns true if the type is a sampler type
+  bool IsSampler() const override;
+
+  /// @returns the sampler type
+  SamplerKind kind() const { return kind_; }
+
+  /// @returns true if this is a comparison sampler
+  bool IsComparison() const { return kind_ == SamplerKind::kComparisonSampler; }
+
+  /// @returns the name for this type
+  std::string type_name() const override;
+
+ private:
+  SamplerKind kind_ = SamplerKind::kSampler;
+};
+
+}  // namespace type
+}  // namespace ast
+}  // namespace tint
+
+#endif  // SRC_AST_TYPE_SAMPLER_TYPE_H_
diff --git a/src/ast/type/sampler_type_test.cc b/src/ast/type/sampler_type_test.cc
new file mode 100644
index 0000000..bcbd5f6
--- /dev/null
+++ b/src/ast/type/sampler_type_test.cc
@@ -0,0 +1,65 @@
+// Copyright 2020 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/ast/type/sampler_type.h"
+
+#include "gtest/gtest.h"
+
+namespace tint {
+namespace ast {
+namespace type {
+namespace {
+
+using SamplerTypeTest = testing::Test;
+
+TEST_F(SamplerTypeTest, Creation) {
+  SamplerType s{SamplerKind::kSampler};
+  EXPECT_EQ(s.kind(), SamplerKind::kSampler);
+}
+
+TEST_F(SamplerTypeTest, Creation_ComparisonSampler) {
+  SamplerType s{SamplerKind::kComparisonSampler};
+  EXPECT_EQ(s.kind(), SamplerKind::kComparisonSampler);
+  EXPECT_TRUE(s.IsComparison());
+}
+
+TEST_F(SamplerTypeTest, Is) {
+  SamplerType s{SamplerKind::kSampler};
+  EXPECT_FALSE(s.IsAlias());
+  EXPECT_FALSE(s.IsArray());
+  EXPECT_FALSE(s.IsBool());
+  EXPECT_FALSE(s.IsF32());
+  EXPECT_FALSE(s.IsI32());
+  EXPECT_FALSE(s.IsMatrix());
+  EXPECT_FALSE(s.IsPointer());
+  EXPECT_TRUE(s.IsSampler());
+  EXPECT_FALSE(s.IsStruct());
+  EXPECT_FALSE(s.IsU32());
+  EXPECT_FALSE(s.IsVector());
+}
+
+TEST_F(SamplerTypeTest, TypeName_Sampler) {
+  SamplerType s{SamplerKind::kSampler};
+  EXPECT_EQ(s.type_name(), "__sampler_sampler");
+}
+
+TEST_F(SamplerTypeTest, TypeName_Comparison) {
+  SamplerType s{SamplerKind::kComparisonSampler};
+  EXPECT_EQ(s.type_name(), "__sampler_comparison");
+}
+
+}  // namespace
+}  // namespace type
+}  // namespace ast
+}  // namespace tint
diff --git a/src/ast/type/struct_type_test.cc b/src/ast/type/struct_type_test.cc
index 5c3c65e..9df6e7d 100644
--- a/src/ast/type/struct_type_test.cc
+++ b/src/ast/type/struct_type_test.cc
@@ -43,6 +43,7 @@
   EXPECT_FALSE(s.IsI32());
   EXPECT_FALSE(s.IsMatrix());
   EXPECT_FALSE(s.IsPointer());
+  EXPECT_FALSE(s.IsSampler());
   EXPECT_TRUE(s.IsStruct());
   EXPECT_FALSE(s.IsU32());
   EXPECT_FALSE(s.IsVector());
diff --git a/src/ast/type/type.cc b/src/ast/type/type.cc
index 8475e9a..fb7d277 100644
--- a/src/ast/type/type.cc
+++ b/src/ast/type/type.cc
@@ -23,6 +23,7 @@
 #include "src/ast/type/i32_type.h"
 #include "src/ast/type/matrix_type.h"
 #include "src/ast/type/pointer_type.h"
+#include "src/ast/type/sampler_type.h"
 #include "src/ast/type/struct_type.h"
 #include "src/ast/type/u32_type.h"
 #include "src/ast/type/vector_type.h"
@@ -83,6 +84,10 @@
   return false;
 }
 
+bool Type::IsSampler() const {
+  return false;
+}
+
 bool Type::IsStruct() const {
   return false;
 }
@@ -174,6 +179,11 @@
   return static_cast<const PointerType*>(this);
 }
 
+const SamplerType* Type::AsSampler() const {
+  assert(IsSampler());
+  return static_cast<const SamplerType*>(this);
+}
+
 const StructType* Type::AsStruct() const {
   assert(IsStruct());
   return static_cast<const StructType*>(this);
@@ -229,6 +239,11 @@
   return static_cast<PointerType*>(this);
 }
 
+SamplerType* Type::AsSampler() {
+  assert(IsSampler());
+  return static_cast<SamplerType*>(this);
+}
+
 StructType* Type::AsStruct() {
   assert(IsStruct());
   return static_cast<StructType*>(this);
diff --git a/src/ast/type/type.h b/src/ast/type/type.h
index b7086aa..fc30c9d 100644
--- a/src/ast/type/type.h
+++ b/src/ast/type/type.h
@@ -28,6 +28,7 @@
 class I32Type;
 class MatrixType;
 class PointerType;
+class SamplerType;
 class StructType;
 class U32Type;
 class VectorType;
@@ -54,6 +55,8 @@
   virtual bool IsMatrix() const;
   /// @returns true if the type is a ptr type
   virtual bool IsPointer() const;
+  /// @returns true if the type is a sampler
+  virtual bool IsSampler() const;
   /// @returns true if the type is a struct type
   virtual bool IsStruct() const;
   /// @returns true if the type is a u32 type
@@ -119,6 +122,8 @@
   const MatrixType* AsMatrix() const;
   /// @returns the type as a pointer type
   const PointerType* AsPointer() const;
+  /// @returns the type as a sampler type
+  const SamplerType* AsSampler() const;
   /// @returns the type as a struct type
   const StructType* AsStruct() const;
   /// @returns the type as a u32 type
@@ -142,6 +147,8 @@
   MatrixType* AsMatrix();
   /// @returns the type as a pointer type
   PointerType* AsPointer();
+  /// @returns the type as a sampler type
+  SamplerType* AsSampler();
   /// @returns the type as a struct type
   StructType* AsStruct();
   /// @returns the type as a u32 type
diff --git a/src/ast/type/u32_type_test.cc b/src/ast/type/u32_type_test.cc
index eb875b4..6342ce6 100644
--- a/src/ast/type/u32_type_test.cc
+++ b/src/ast/type/u32_type_test.cc
@@ -32,6 +32,7 @@
   EXPECT_FALSE(u.IsI32());
   EXPECT_FALSE(u.IsMatrix());
   EXPECT_FALSE(u.IsPointer());
+  EXPECT_FALSE(u.IsSampler());
   EXPECT_FALSE(u.IsStruct());
   EXPECT_TRUE(u.IsU32());
   EXPECT_FALSE(u.IsVector());
diff --git a/src/ast/type/vector_type_test.cc b/src/ast/type/vector_type_test.cc
index b4fd515..b6108c6 100644
--- a/src/ast/type/vector_type_test.cc
+++ b/src/ast/type/vector_type_test.cc
@@ -41,6 +41,7 @@
   EXPECT_FALSE(v.IsI32());
   EXPECT_FALSE(v.IsMatrix());
   EXPECT_FALSE(v.IsPointer());
+  EXPECT_FALSE(v.IsSampler());
   EXPECT_FALSE(v.IsStruct());
   EXPECT_FALSE(v.IsU32());
   EXPECT_TRUE(v.IsVector());