diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6846c123d1..e5f97e9b46 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -205,6 +205,7 @@ set(TINT_TEST_SRCS ast/cast_expression_test.cc ast/const_initializer_expression_test.cc ast/continue_statement_test.cc + ast/decorated_variable_test.cc ast/entry_point_test.cc ast/import_test.cc ast/int_literal_test.cc diff --git a/src/ast/binding_decoration.cc b/src/ast/binding_decoration.cc index 4278dd5c03..d9532fe4aa 100644 --- a/src/ast/binding_decoration.cc +++ b/src/ast/binding_decoration.cc @@ -22,7 +22,7 @@ BindingDecoration::BindingDecoration(size_t val) : value_(val) {} BindingDecoration::~BindingDecoration() = default; void BindingDecoration::to_str(std::ostream& out) const { - out << "binding " << value_; + out << "BindingDecoration{" << value_ << "}" << std::endl; } } // namespace ast diff --git a/src/ast/builtin_decoration.cc b/src/ast/builtin_decoration.cc index c0264afeac..89d116ef19 100644 --- a/src/ast/builtin_decoration.cc +++ b/src/ast/builtin_decoration.cc @@ -22,7 +22,7 @@ BuiltinDecoration::BuiltinDecoration(Builtin builtin) : builtin_(builtin) {} BuiltinDecoration::~BuiltinDecoration() = default; void BuiltinDecoration::to_str(std::ostream& out) const { - out << "builtin " << builtin_; + out << "BuiltinDecoration{" << builtin_ << "}" << std::endl; } } // namespace ast diff --git a/src/ast/decorated_variable.cc b/src/ast/decorated_variable.cc index 2a6b42e8b7..038aaed5f6 100644 --- a/src/ast/decorated_variable.cc +++ b/src/ast/decorated_variable.cc @@ -19,6 +19,9 @@ namespace ast { DecoratedVariable::DecoratedVariable() = default; +DecoratedVariable::DecoratedVariable(std::unique_ptr var) + : Variable(var->source(), var->name(), var->storage_class(), var->type()) {} + DecoratedVariable::DecoratedVariable(DecoratedVariable&&) = default; DecoratedVariable::~DecoratedVariable() = default; @@ -32,17 +35,17 @@ void DecoratedVariable::to_str(std::ostream& out, size_t indent) const { out << "DecoratedVariable{" << std::endl; make_indent(out, indent + 2); - out << "decorations{" << std::endl; + out << "Decorations{" << std::endl; for (const auto& deco : decorations_) { make_indent(out, indent + 4); deco->to_str(out); - out << std::endl; } make_indent(out, indent + 2); out << "}" << std::endl; info_to_str(out, indent + 2); + initializer_to_str(out, indent + 2); make_indent(out, indent); out << "}" << std::endl; } diff --git a/src/ast/decorated_variable.h b/src/ast/decorated_variable.h index d81de81351..4008a48b13 100644 --- a/src/ast/decorated_variable.h +++ b/src/ast/decorated_variable.h @@ -30,6 +30,9 @@ class DecoratedVariable : public Variable { public: /// Create a new empty decorated variable statement DecoratedVariable(); + /// Create a decorated variable from an existing variable + /// @param var the variable to initialize from + explicit DecoratedVariable(std::unique_ptr var); /// Move constructor DecoratedVariable(DecoratedVariable&&); diff --git a/src/ast/decorated_variable_test.cc b/src/ast/decorated_variable_test.cc new file mode 100644 index 0000000000..e2ed80010f --- /dev/null +++ b/src/ast/decorated_variable_test.cc @@ -0,0 +1,97 @@ +// 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/decorated_variable.h" + +#include "gtest/gtest.h" +#include "src/ast/binding_decoration.h" +#include "src/ast/identifier_expression.h" +#include "src/ast/set_decoration.h" +#include "src/ast/type/f32_type.h" +#include "src/ast/type/i32_type.h" +#include "src/ast/variable.h" +#include "src/ast/variable_decoration.h" + +namespace tint { +namespace ast { + +using DecoratedVariableTest = testing::Test; + +TEST_F(DecoratedVariableTest, Creation) { + type::I32Type t; + auto var = std::make_unique("my_var", StorageClass::kFunction, &t); + DecoratedVariable dv(std::move(var)); + + EXPECT_EQ(dv.name(), "my_var"); + EXPECT_EQ(dv.storage_class(), StorageClass::kFunction); + EXPECT_EQ(dv.type(), &t); + EXPECT_EQ(dv.line(), 0); + EXPECT_EQ(dv.column(), 0); +} + +TEST_F(DecoratedVariableTest, CreationWithSource) { + Source s{27, 4}; + type::F32Type t; + auto var = std::make_unique(s, "i", StorageClass::kPrivate, &t); + DecoratedVariable dv(std::move(var)); + + EXPECT_EQ(dv.name(), "i"); + EXPECT_EQ(dv.storage_class(), StorageClass::kPrivate); + EXPECT_EQ(dv.type(), &t); + EXPECT_EQ(dv.line(), 27); + EXPECT_EQ(dv.column(), 4); +} + +TEST_F(DecoratedVariableTest, IsValid) { + type::I32Type t; + auto var = std::make_unique("my_var", StorageClass::kNone, &t); + DecoratedVariable dv(std::move(var)); + EXPECT_TRUE(dv.IsValid()); +} + +TEST_F(DecoratedVariableTest, IsDecorated) { + DecoratedVariable dv; + EXPECT_TRUE(dv.IsDecorated()); +} + +TEST_F(DecoratedVariableTest, to_str) { + type::F32Type t; + auto var = std::make_unique("my_var", StorageClass::kFunction, &t); + DecoratedVariable dv(std::move(var)); + dv.set_initializer(std::make_unique("expr")); + + std::vector> decos; + decos.push_back(std::make_unique(2)); + decos.push_back(std::make_unique(1)); + + dv.set_decorations(std::move(decos)); + std::ostringstream out; + dv.to_str(out, 2); + EXPECT_EQ(out.str(), R"( DecoratedVariable{ + Decorations{ + BindingDecoration{2} + SetDecoration{1} + } + my_var + function + __f32 + { + Identifier{expr} + } + } +)"); +} + +} // namespace ast +} // namespace tint diff --git a/src/ast/location_decoration.cc b/src/ast/location_decoration.cc index 45bec565fe..9fb8d5f2ed 100644 --- a/src/ast/location_decoration.cc +++ b/src/ast/location_decoration.cc @@ -22,7 +22,7 @@ LocationDecoration::LocationDecoration(size_t val) : value_(val) {} LocationDecoration::~LocationDecoration() = default; void LocationDecoration::to_str(std::ostream& out) const { - out << "location " << value_; + out << "LocationDecoration{" << value_ << "}" << std::endl; } } // namespace ast diff --git a/src/ast/set_decoration.cc b/src/ast/set_decoration.cc index c27ee26863..7d54d98a6d 100644 --- a/src/ast/set_decoration.cc +++ b/src/ast/set_decoration.cc @@ -22,7 +22,7 @@ SetDecoration::SetDecoration(size_t val) : value_(val) {} SetDecoration::~SetDecoration() = default; void SetDecoration::to_str(std::ostream& out) const { - out << "set " << value_; + out << "SetDecoration{" << value_ << "}" << std::endl; } } // namespace ast diff --git a/src/ast/variable.cc b/src/ast/variable.cc index 1caa64b824..d9990b8b2c 100644 --- a/src/ast/variable.cc +++ b/src/ast/variable.cc @@ -56,18 +56,26 @@ void Variable::info_to_str(std::ostream& out, size_t indent) const { out << type_->type_name() << std::endl; } +void Variable::initializer_to_str(std::ostream& out, size_t indent) const { + if (initializer_ == nullptr) + return; + + make_indent(out, indent); + out << "{" << std::endl; + + initializer_->to_str(out, indent + 2); + + make_indent(out, indent); + out << "}" << std::endl; +} + void Variable::to_str(std::ostream& out, size_t indent) const { - info_to_str(out, indent); - - if (initializer_ != nullptr) { - make_indent(out, indent); - out << "{" << std::endl; - - initializer_->to_str(out, indent + 2); - - make_indent(out, indent); - out << "}" << std::endl; - } + make_indent(out, indent); + out << "Variable{" << std::endl; + info_to_str(out, indent + 2); + initializer_to_str(out, indent + 2); + make_indent(out, indent); + out << "}" << std::endl; } } // namespace ast diff --git a/src/ast/variable.h b/src/ast/variable.h index db27ed2bd5..3fec0d6777 100644 --- a/src/ast/variable.h +++ b/src/ast/variable.h @@ -105,6 +105,10 @@ class Variable : public Node { /// @param out the stream to write to /// @param indent number of spaces to indent the node when writing void info_to_str(std::ostream& out, size_t indent) const; + /// Output initializer for this variable. + /// @param out the stream to write to + /// @param indent number of spaces to indent the node when writing + void initializer_to_str(std::ostream& out, size_t indent) const; private: Variable(const Variable&) = delete; diff --git a/src/ast/variable_test.cc b/src/ast/variable_test.cc index 0f4f59b103..8156d239f7 100644 --- a/src/ast/variable_test.cc +++ b/src/ast/variable_test.cc @@ -89,10 +89,12 @@ TEST_F(VariableTest, to_str) { type::F32Type t; Variable v{"my_var", StorageClass::kFunction, &t}; std::ostringstream out; - v.to_str(out, 0); - EXPECT_EQ(out.str(), R"(my_var -function -__f32 + v.to_str(out, 2); + EXPECT_EQ(out.str(), R"( Variable{ + my_var + function + __f32 + } )"); } diff --git a/src/reader/wgsl/parser_impl.cc b/src/reader/wgsl/parser_impl.cc index 58d4bf27ad..59d461ba9f 100644 --- a/src/reader/wgsl/parser_impl.cc +++ b/src/reader/wgsl/parser_impl.cc @@ -329,11 +329,7 @@ std::unique_ptr ParserImpl::global_variable_decl() { } if (decos.size() > 0) { - auto dv = std::make_unique(); - dv->set_source(var->source()); - dv->set_name(var->name()); - dv->set_type(var->type()); - dv->set_storage_class(var->storage_class()); + auto dv = std::make_unique(std::move(var)); dv->set_decorations(std::move(decos)); var = std::move(dv);