diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e8c005ce9d..a14cebbfaf 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -417,6 +417,7 @@ if(${TINT_BUILD_WGSL_WRITER}) writer/wgsl/generator_impl_relational_test.cc writer/wgsl/generator_impl_type_test.cc writer/wgsl/generator_impl_unary_derivative_test.cc + writer/wgsl/generator_impl_unary_method_test.cc writer/wgsl/generator_impl_variable_test.cc ) endif() diff --git a/src/writer/wgsl/generator_impl.cc b/src/writer/wgsl/generator_impl.cc index 9e6a1be386..b6942c065a 100644 --- a/src/writer/wgsl/generator_impl.cc +++ b/src/writer/wgsl/generator_impl.cc @@ -45,6 +45,7 @@ #include "src/ast/type_initializer_expression.h" #include "src/ast/uint_literal.h" #include "src/ast/unary_derivative_expression.h" +#include "src/ast/unary_method_expression.h" namespace tint { namespace writer { @@ -148,6 +149,9 @@ bool GeneratorImpl::EmitExpression(ast::Expression* expr) { if (expr->IsUnaryDerivative()) { return EmitUnaryDerivative(expr->AsUnaryDerivative()); } + if (expr->IsUnaryMethod()) { + return EmitUnaryMethod(expr->AsUnaryMethod()); + } error_ = "unknown expression type"; return false; @@ -566,6 +570,51 @@ bool GeneratorImpl::EmitUnaryDerivative(ast::UnaryDerivativeExpression* expr) { return true; } +bool GeneratorImpl::EmitUnaryMethod(ast::UnaryMethodExpression* expr) { + switch (expr->op()) { + case ast::UnaryMethod::kAny: + out_ << "any"; + break; + case ast::UnaryMethod::kAll: + out_ << "all"; + break; + case ast::UnaryMethod::kIsNan: + out_ << "is_nan"; + break; + case ast::UnaryMethod::kIsInf: + out_ << "is_inf"; + break; + case ast::UnaryMethod::kIsFinite: + out_ << "is_finite"; + break; + case ast::UnaryMethod::kIsNormal: + out_ << "is_normal"; + break; + case ast::UnaryMethod::kDot: + out_ << "dot"; + break; + case ast::UnaryMethod::kOuterProduct: + out_ << "outer_product"; + break; + } + out_ << "("; + + bool first = true; + for (const auto& param : expr->params()) { + if (!first) { + out_ << ", "; + } + first = false; + + if (!EmitExpression(param.get())) { + return false; + } + } + out_ << ")"; + + return true; +} + } // namespace wgsl } // namespace writer } // namespace tint diff --git a/src/writer/wgsl/generator_impl.h b/src/writer/wgsl/generator_impl.h index c2836a23b9..a550dcb2e5 100644 --- a/src/writer/wgsl/generator_impl.h +++ b/src/writer/wgsl/generator_impl.h @@ -128,8 +128,12 @@ class GeneratorImpl { bool EmitTypeInitializer(ast::TypeInitializerExpression* expr); /// Handles a unary derivative expression /// @param expr the expression to emit - /// @returns true if the expressionw as emitted + /// @returns true if the expression was emitted bool EmitUnaryDerivative(ast::UnaryDerivativeExpression* expr); + /// Handles a unary method expression + /// @param expr the expression to emit + /// @returns true if the expression was emitted + bool EmitUnaryMethod(ast::UnaryMethodExpression* expr); /// Handles generating a variable /// @param var the variable to generate /// @returns true if the variable was emitted diff --git a/src/writer/wgsl/generator_impl_unary_method_test.cc b/src/writer/wgsl/generator_impl_unary_method_test.cc new file mode 100644 index 0000000000..32455bfc91 --- /dev/null +++ b/src/writer/wgsl/generator_impl_unary_method_test.cc @@ -0,0 +1,85 @@ +// 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 +#include + +#include "gtest/gtest.h" +#include "src/ast/identifier_expression.h" +#include "src/ast/unary_method_expression.h" +#include "src/writer/wgsl/generator_impl.h" + +namespace tint { +namespace writer { +namespace wgsl { +namespace { + +struct UnaryMethodData { + const char* name; + ast::UnaryMethod method; +}; +inline std::ostream& operator<<(std::ostream& out, UnaryMethodData data) { + out << data.method; + return out; +} +using UnaryMethodTest = testing::TestWithParam; +TEST_P(UnaryMethodTest, Emit) { + auto params = GetParam(); + + auto expr = std::make_unique("expr"); + std::vector> ops; + ops.push_back(std::move(expr)); + + ast::UnaryMethodExpression method(params.method, std::move(ops)); + + GeneratorImpl g; + ASSERT_TRUE(g.EmitExpression(&method)) << g.error(); + EXPECT_EQ(g.result(), std::string(params.name) + "(expr)"); +} +INSTANTIATE_TEST_SUITE_P( + GeneratorImplTest, + UnaryMethodTest, + testing::Values(UnaryMethodData{"any", ast::UnaryMethod::kAny}, + UnaryMethodData{"all", ast::UnaryMethod::kAll}, + UnaryMethodData{"is_nan", ast::UnaryMethod::kIsNan}, + UnaryMethodData{"is_finite", ast::UnaryMethod::kIsFinite}, + UnaryMethodData{"is_normal", ast::UnaryMethod::kIsNormal})); + +using UnaryMethodTest_MultiParam = testing::TestWithParam; +TEST_P(UnaryMethodTest_MultiParam, Emit) { + auto params = GetParam(); + + auto expr1 = std::make_unique("expr1"); + auto expr2 = std::make_unique("expr2"); + std::vector> ops; + ops.push_back(std::move(expr1)); + ops.push_back(std::move(expr2)); + + ast::UnaryMethodExpression method(params.method, std::move(ops)); + + GeneratorImpl g; + ASSERT_TRUE(g.EmitExpression(&method)) << g.error(); + EXPECT_EQ(g.result(), std::string(params.name) + "(expr1, expr2)"); +} +INSTANTIATE_TEST_SUITE_P( + GeneratorImplTest, + UnaryMethodTest_MultiParam, + testing::Values(UnaryMethodData{"dot", ast::UnaryMethod::kDot}, + UnaryMethodData{"outer_product", + ast::UnaryMethod::kOuterProduct})); + +} // namespace +} // namespace wgsl +} // namespace writer +} // namespace tint