Update intrinsics in the grammar.
The intrinsic methods were removed from the WGSL grammar and are treated as builtin functions. This Cl updates Tint to match. Bug: tint:41 Change-Id: I3f9ff6c17f1ca57ad159d883fd5a966657caeb4f Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/22301 Reviewed-by: David Neto <dneto@google.com>
This commit is contained in:
parent
1d2ad81eb9
commit
46e959da39
14
BUILD.gn
14
BUILD.gn
|
@ -230,8 +230,6 @@ source_set("libtint_core_src") {
|
|||
"src/ast/continue_statement.h",
|
||||
"src/ast/decorated_variable.cc",
|
||||
"src/ast/decorated_variable.h",
|
||||
"src/ast/derivative_modifier.cc",
|
||||
"src/ast/derivative_modifier.h",
|
||||
"src/ast/else_statement.cc",
|
||||
"src/ast/else_statement.h",
|
||||
"src/ast/entry_point.cc",
|
||||
|
@ -322,14 +320,6 @@ source_set("libtint_core_src") {
|
|||
"src/ast/type_constructor_expression.h",
|
||||
"src/ast/uint_literal.cc",
|
||||
"src/ast/uint_literal.h",
|
||||
"src/ast/unary_derivative.cc",
|
||||
"src/ast/unary_derivative.h",
|
||||
"src/ast/unary_derivative_expression.cc",
|
||||
"src/ast/unary_derivative_expression.h",
|
||||
"src/ast/unary_method.cc",
|
||||
"src/ast/unary_method.h",
|
||||
"src/ast/unary_method_expression.cc",
|
||||
"src/ast/unary_method_expression.h",
|
||||
"src/ast/unary_op.cc",
|
||||
"src/ast/unary_op.h",
|
||||
"src/ast/unary_op_expression.cc",
|
||||
|
@ -623,8 +613,6 @@ source_set("tint_unittests_core_src") {
|
|||
"src/ast/type/vector_type_test.cc",
|
||||
"src/ast/type_constructor_expression_test.cc",
|
||||
"src/ast/uint_literal_test.cc",
|
||||
"src/ast/unary_derivative_expression_test.cc",
|
||||
"src/ast/unary_method_expression_test.cc",
|
||||
"src/ast/unary_op_expression_test.cc",
|
||||
"src/ast/unless_statement_test.cc",
|
||||
"src/ast/variable_decl_statement_test.cc",
|
||||
|
@ -737,7 +725,6 @@ source_set("tint_unittests_wgsl_reader_src") {
|
|||
"src/reader/wgsl/parser_impl_const_literal_test.cc",
|
||||
"src/reader/wgsl/parser_impl_continue_stmt_test.cc",
|
||||
"src/reader/wgsl/parser_impl_continuing_stmt_test.cc",
|
||||
"src/reader/wgsl/parser_impl_derivative_modifier_test.cc",
|
||||
"src/reader/wgsl/parser_impl_else_stmt_test.cc",
|
||||
"src/reader/wgsl/parser_impl_elseif_stmt_test.cc",
|
||||
"src/reader/wgsl/parser_impl_entry_point_decl_test.cc",
|
||||
|
@ -830,7 +817,6 @@ source_set("tint_unittests_wgsl_writer_src") {
|
|||
"src/writer/wgsl/generator_impl_switch_test.cc",
|
||||
"src/writer/wgsl/generator_impl_test.cc",
|
||||
"src/writer/wgsl/generator_impl_type_test.cc",
|
||||
"src/writer/wgsl/generator_impl_unary_derivative_test.cc",
|
||||
"src/writer/wgsl/generator_impl_unary_method_test.cc",
|
||||
"src/writer/wgsl/generator_impl_unary_op_test.cc",
|
||||
"src/writer/wgsl/generator_impl_unless_test.cc",
|
||||
|
|
|
@ -67,8 +67,6 @@ set(TINT_LIB_SRCS
|
|||
ast/continue_statement.h
|
||||
ast/decorated_variable.cc
|
||||
ast/decorated_variable.h
|
||||
ast/derivative_modifier.cc
|
||||
ast/derivative_modifier.h
|
||||
ast/else_statement.cc
|
||||
ast/else_statement.h
|
||||
ast/entry_point.cc
|
||||
|
@ -159,14 +157,6 @@ set(TINT_LIB_SRCS
|
|||
ast/type/void_type.h
|
||||
ast/uint_literal.cc
|
||||
ast/uint_literal.h
|
||||
ast/unary_derivative.cc
|
||||
ast/unary_derivative.h
|
||||
ast/unary_derivative_expression.cc
|
||||
ast/unary_derivative_expression.h
|
||||
ast/unary_method.cc
|
||||
ast/unary_method.h
|
||||
ast/unary_method_expression.cc
|
||||
ast/unary_method_expression.h
|
||||
ast/unary_op.cc
|
||||
ast/unary_op.h
|
||||
ast/unary_op_expression.cc
|
||||
|
@ -303,8 +293,6 @@ set(TINT_TEST_SRCS
|
|||
ast/type/vector_type_test.cc
|
||||
ast/type_constructor_expression_test.cc
|
||||
ast/uint_literal_test.cc
|
||||
ast/unary_derivative_expression_test.cc
|
||||
ast/unary_method_expression_test.cc
|
||||
ast/unary_op_expression_test.cc
|
||||
ast/unless_statement_test.cc
|
||||
ast/variable_decl_statement_test.cc
|
||||
|
@ -368,7 +356,6 @@ if(${TINT_BUILD_WGSL_READER})
|
|||
reader/wgsl/parser_impl_const_literal_test.cc
|
||||
reader/wgsl/parser_impl_continue_stmt_test.cc
|
||||
reader/wgsl/parser_impl_continuing_stmt_test.cc
|
||||
reader/wgsl/parser_impl_derivative_modifier_test.cc
|
||||
reader/wgsl/parser_impl_else_stmt_test.cc
|
||||
reader/wgsl/parser_impl_elseif_stmt_test.cc
|
||||
reader/wgsl/parser_impl_entry_point_decl_test.cc
|
||||
|
@ -478,8 +465,6 @@ if(${TINT_BUILD_WGSL_WRITER})
|
|||
writer/wgsl/generator_impl_return_test.cc
|
||||
writer/wgsl/generator_impl_switch_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_unary_op_test.cc
|
||||
writer/wgsl/generator_impl_unless_test.cc
|
||||
writer/wgsl/generator_impl_variable_decl_statement_test.cc
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
// 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/derivative_modifier.h"
|
||||
|
||||
namespace tint {
|
||||
namespace ast {
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, DerivativeModifier mod) {
|
||||
switch (mod) {
|
||||
case DerivativeModifier::kNone: {
|
||||
out << "none";
|
||||
break;
|
||||
}
|
||||
case DerivativeModifier::kFine: {
|
||||
out << "fine";
|
||||
break;
|
||||
}
|
||||
case DerivativeModifier::kCoarse: {
|
||||
out << "coarse";
|
||||
break;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
} // namespace ast
|
||||
} // namespace tint
|
|
@ -1,31 +0,0 @@
|
|||
// 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_DERIVATIVE_MODIFIER_H_
|
||||
#define SRC_AST_DERIVATIVE_MODIFIER_H_
|
||||
|
||||
#include <ostream>
|
||||
|
||||
namespace tint {
|
||||
namespace ast {
|
||||
|
||||
/// The derivative modifier
|
||||
enum class DerivativeModifier { kNone = -1, kFine, kCoarse };
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, DerivativeModifier mod);
|
||||
|
||||
} // namespace ast
|
||||
} // namespace tint
|
||||
|
||||
#endif // SRC_AST_DERIVATIVE_MODIFIER_H_
|
|
@ -25,8 +25,6 @@
|
|||
#include "src/ast/identifier_expression.h"
|
||||
#include "src/ast/member_accessor_expression.h"
|
||||
#include "src/ast/type/alias_type.h"
|
||||
#include "src/ast/unary_derivative_expression.h"
|
||||
#include "src/ast/unary_method_expression.h"
|
||||
#include "src/ast/unary_op_expression.h"
|
||||
|
||||
namespace tint {
|
||||
|
@ -78,14 +76,6 @@ bool Expression::IsBinary() const {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Expression::IsUnaryDerivative() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Expression::IsUnaryMethod() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Expression::IsUnaryOp() const {
|
||||
return false;
|
||||
}
|
||||
|
@ -129,16 +119,6 @@ const MemberAccessorExpression* Expression::AsMemberAccessor() const {
|
|||
return static_cast<const MemberAccessorExpression*>(this);
|
||||
}
|
||||
|
||||
const UnaryDerivativeExpression* Expression::AsUnaryDerivative() const {
|
||||
assert(IsUnaryDerivative());
|
||||
return static_cast<const UnaryDerivativeExpression*>(this);
|
||||
}
|
||||
|
||||
const UnaryMethodExpression* Expression::AsUnaryMethod() const {
|
||||
assert(IsUnaryMethod());
|
||||
return static_cast<const UnaryMethodExpression*>(this);
|
||||
}
|
||||
|
||||
const UnaryOpExpression* Expression::AsUnaryOp() const {
|
||||
assert(IsUnaryOp());
|
||||
return static_cast<const UnaryOpExpression*>(this);
|
||||
|
@ -184,16 +164,6 @@ MemberAccessorExpression* Expression::AsMemberAccessor() {
|
|||
return static_cast<MemberAccessorExpression*>(this);
|
||||
}
|
||||
|
||||
UnaryDerivativeExpression* Expression::AsUnaryDerivative() {
|
||||
assert(IsUnaryDerivative());
|
||||
return static_cast<UnaryDerivativeExpression*>(this);
|
||||
}
|
||||
|
||||
UnaryMethodExpression* Expression::AsUnaryMethod() {
|
||||
assert(IsUnaryMethod());
|
||||
return static_cast<UnaryMethodExpression*>(this);
|
||||
}
|
||||
|
||||
UnaryOpExpression* Expression::AsUnaryOp() {
|
||||
assert(IsUnaryOp());
|
||||
return static_cast<UnaryOpExpression*>(this);
|
||||
|
|
|
@ -32,8 +32,6 @@ class CastExpression;
|
|||
class IdentifierExpression;
|
||||
class ConstructorExpression;
|
||||
class MemberAccessorExpression;
|
||||
class UnaryDerivativeExpression;
|
||||
class UnaryMethodExpression;
|
||||
class UnaryOpExpression;
|
||||
|
||||
/// Base expression class
|
||||
|
@ -63,10 +61,6 @@ class Expression : public Node {
|
|||
virtual bool IsMemberAccessor() const;
|
||||
/// @returns true if this is a binary expression
|
||||
virtual bool IsBinary() const;
|
||||
/// @returns true if this is a unary derivative expression
|
||||
virtual bool IsUnaryDerivative() const;
|
||||
/// @returns true if this is a unary method expression
|
||||
virtual bool IsUnaryMethod() const;
|
||||
/// @returns true if this is a unary op expression
|
||||
virtual bool IsUnaryOp() const;
|
||||
|
||||
|
@ -86,10 +80,6 @@ class Expression : public Node {
|
|||
const MemberAccessorExpression* AsMemberAccessor() const;
|
||||
/// @returns the expression as a binary expression
|
||||
const BinaryExpression* AsBinary() const;
|
||||
/// @returns the expression as a unary derivative expression
|
||||
const UnaryDerivativeExpression* AsUnaryDerivative() const;
|
||||
/// @returns the expression as a unary method expression
|
||||
const UnaryMethodExpression* AsUnaryMethod() const;
|
||||
/// @returns the expression as a unary op expression
|
||||
const UnaryOpExpression* AsUnaryOp() const;
|
||||
|
||||
|
@ -109,10 +99,6 @@ class Expression : public Node {
|
|||
MemberAccessorExpression* AsMemberAccessor();
|
||||
/// @returns the expression as a binary expression
|
||||
BinaryExpression* AsBinary();
|
||||
/// @returns the expression as a unary derivative expression
|
||||
UnaryDerivativeExpression* AsUnaryDerivative();
|
||||
/// @returns the expression as a unary method expression
|
||||
UnaryMethodExpression* AsUnaryMethod();
|
||||
/// @returns the expression as a unary op expression
|
||||
UnaryOpExpression* AsUnaryOp();
|
||||
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
// 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/unary_derivative.h"
|
||||
|
||||
namespace tint {
|
||||
namespace ast {
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, UnaryDerivative mod) {
|
||||
switch (mod) {
|
||||
case UnaryDerivative::kDpdx: {
|
||||
out << "dpdx";
|
||||
break;
|
||||
}
|
||||
case UnaryDerivative::kDpdy: {
|
||||
out << "dpdy";
|
||||
break;
|
||||
}
|
||||
case UnaryDerivative::kFwidth: {
|
||||
out << "fwidth";
|
||||
break;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
} // namespace ast
|
||||
} // namespace tint
|
|
@ -1,31 +0,0 @@
|
|||
// 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_UNARY_DERIVATIVE_H_
|
||||
#define SRC_AST_UNARY_DERIVATIVE_H_
|
||||
|
||||
#include <ostream>
|
||||
|
||||
namespace tint {
|
||||
namespace ast {
|
||||
|
||||
/// The unary derivative
|
||||
enum class UnaryDerivative { kDpdx = 0, kDpdy, kFwidth };
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, UnaryDerivative mod);
|
||||
|
||||
} // namespace ast
|
||||
} // namespace tint
|
||||
|
||||
#endif // SRC_AST_UNARY_DERIVATIVE_H_
|
|
@ -1,64 +0,0 @@
|
|||
// 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/unary_derivative_expression.h"
|
||||
|
||||
namespace tint {
|
||||
namespace ast {
|
||||
|
||||
UnaryDerivativeExpression::UnaryDerivativeExpression() : Expression() {}
|
||||
|
||||
UnaryDerivativeExpression::UnaryDerivativeExpression(
|
||||
UnaryDerivative op,
|
||||
DerivativeModifier mod,
|
||||
std::unique_ptr<Expression> param)
|
||||
: Expression(), op_(op), modifier_(mod), param_(std::move(param)) {}
|
||||
|
||||
UnaryDerivativeExpression::UnaryDerivativeExpression(
|
||||
const Source& source,
|
||||
UnaryDerivative op,
|
||||
DerivativeModifier mod,
|
||||
std::unique_ptr<Expression> param)
|
||||
: Expression(source), op_(op), modifier_(mod), param_(std::move(param)) {}
|
||||
|
||||
UnaryDerivativeExpression::UnaryDerivativeExpression(
|
||||
UnaryDerivativeExpression&&) = default;
|
||||
|
||||
UnaryDerivativeExpression::~UnaryDerivativeExpression() = default;
|
||||
|
||||
bool UnaryDerivativeExpression::IsUnaryDerivative() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UnaryDerivativeExpression::IsValid() const {
|
||||
if (param_ == nullptr || !param_->IsValid()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void UnaryDerivativeExpression::to_str(std::ostream& out, size_t indent) const {
|
||||
make_indent(out, indent);
|
||||
out << "UnaryDerivative{" << std::endl;
|
||||
make_indent(out, indent + 2);
|
||||
out << op_ << std::endl;
|
||||
make_indent(out, indent + 2);
|
||||
out << modifier_ << std::endl;
|
||||
param_->to_str(out, indent + 2);
|
||||
make_indent(out, indent);
|
||||
out << "}" << std::endl;
|
||||
}
|
||||
|
||||
} // namespace ast
|
||||
} // namespace tint
|
|
@ -1,96 +0,0 @@
|
|||
// 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_UNARY_DERIVATIVE_EXPRESSION_H_
|
||||
#define SRC_AST_UNARY_DERIVATIVE_EXPRESSION_H_
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "src/ast/derivative_modifier.h"
|
||||
#include "src/ast/expression.h"
|
||||
#include "src/ast/literal.h"
|
||||
#include "src/ast/unary_derivative.h"
|
||||
|
||||
namespace tint {
|
||||
namespace ast {
|
||||
|
||||
/// A unary derivative expression
|
||||
class UnaryDerivativeExpression : public Expression {
|
||||
public:
|
||||
/// Constructor
|
||||
UnaryDerivativeExpression();
|
||||
/// Constructor
|
||||
/// @param op the op
|
||||
/// @param mod the derivative modifier
|
||||
/// @param param the param
|
||||
UnaryDerivativeExpression(UnaryDerivative op,
|
||||
DerivativeModifier mod,
|
||||
std::unique_ptr<Expression> param);
|
||||
/// Constructor
|
||||
/// @param source the unary derivative expression source
|
||||
/// @param op the op
|
||||
/// @param mod the derivative modifier
|
||||
/// @param param the param
|
||||
UnaryDerivativeExpression(const Source& source,
|
||||
UnaryDerivative op,
|
||||
DerivativeModifier mod,
|
||||
std::unique_ptr<Expression> param);
|
||||
/// Move constructor
|
||||
UnaryDerivativeExpression(UnaryDerivativeExpression&&);
|
||||
~UnaryDerivativeExpression() override;
|
||||
|
||||
/// Sets the op
|
||||
/// @param op the op
|
||||
void set_op(UnaryDerivative op) { op_ = op; }
|
||||
/// @returns the op
|
||||
UnaryDerivative op() const { return op_; }
|
||||
|
||||
/// Sets the derivative modifier
|
||||
/// @param mod the modifier
|
||||
void set_modifier(DerivativeModifier mod) { modifier_ = mod; }
|
||||
/// @returns the derivative modifier
|
||||
DerivativeModifier modifier() const { return modifier_; }
|
||||
|
||||
/// Sets the param
|
||||
/// @param param the param
|
||||
void set_param(std::unique_ptr<Expression> param) {
|
||||
param_ = std::move(param);
|
||||
}
|
||||
/// @returns the param
|
||||
Expression* param() const { return param_.get(); }
|
||||
|
||||
/// @returns true if this is an as expression
|
||||
bool IsUnaryDerivative() const override;
|
||||
|
||||
/// @returns true if the node is valid
|
||||
bool IsValid() const override;
|
||||
|
||||
/// Writes a representation of the node to the output stream
|
||||
/// @param out the stream to write to
|
||||
/// @param indent number of spaces to indent the node when writing
|
||||
void to_str(std::ostream& out, size_t indent) const override;
|
||||
|
||||
private:
|
||||
UnaryDerivativeExpression(const UnaryDerivativeExpression&) = delete;
|
||||
|
||||
UnaryDerivative op_ = UnaryDerivative::kDpdx;
|
||||
DerivativeModifier modifier_ = DerivativeModifier::kNone;
|
||||
std::unique_ptr<Expression> param_;
|
||||
};
|
||||
|
||||
} // namespace ast
|
||||
} // namespace tint
|
||||
|
||||
#endif // SRC_AST_UNARY_DERIVATIVE_EXPRESSION_H_
|
|
@ -1,90 +0,0 @@
|
|||
// 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/unary_derivative_expression.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "src/ast/identifier_expression.h"
|
||||
|
||||
namespace tint {
|
||||
namespace ast {
|
||||
namespace {
|
||||
|
||||
using UnaryDerivativeExpressionTest = testing::Test;
|
||||
|
||||
TEST_F(UnaryDerivativeExpressionTest, Creation) {
|
||||
auto ident = std::make_unique<IdentifierExpression>("ident");
|
||||
auto* ident_ptr = ident.get();
|
||||
|
||||
UnaryDerivativeExpression d(UnaryDerivative::kDpdy,
|
||||
DerivativeModifier::kCoarse, std::move(ident));
|
||||
EXPECT_EQ(d.param(), ident_ptr);
|
||||
EXPECT_EQ(d.modifier(), DerivativeModifier::kCoarse);
|
||||
EXPECT_EQ(d.op(), UnaryDerivative::kDpdy);
|
||||
}
|
||||
|
||||
TEST_F(UnaryDerivativeExpressionTest, Creation_WithSource) {
|
||||
auto ident = std::make_unique<IdentifierExpression>("ident");
|
||||
|
||||
UnaryDerivativeExpression d(Source{20, 2}, UnaryDerivative::kDpdy,
|
||||
DerivativeModifier::kCoarse, std::move(ident));
|
||||
auto src = d.source();
|
||||
EXPECT_EQ(src.line, 20u);
|
||||
EXPECT_EQ(src.column, 2u);
|
||||
}
|
||||
|
||||
TEST_F(UnaryDerivativeExpressionTest, IsUnaryDerivative) {
|
||||
UnaryDerivativeExpression d;
|
||||
EXPECT_TRUE(d.IsUnaryDerivative());
|
||||
}
|
||||
|
||||
TEST_F(UnaryDerivativeExpressionTest, IsValid) {
|
||||
auto ident = std::make_unique<IdentifierExpression>("ident");
|
||||
UnaryDerivativeExpression d(UnaryDerivative::kDpdy,
|
||||
DerivativeModifier::kCoarse, std::move(ident));
|
||||
EXPECT_TRUE(d.IsValid());
|
||||
}
|
||||
|
||||
TEST_F(UnaryDerivativeExpressionTest, IsValid_NullParam) {
|
||||
UnaryDerivativeExpression d(UnaryDerivative::kDpdy,
|
||||
DerivativeModifier::kCoarse, nullptr);
|
||||
EXPECT_FALSE(d.IsValid());
|
||||
}
|
||||
|
||||
TEST_F(UnaryDerivativeExpressionTest, IsValid_InvalidParam) {
|
||||
auto ident = std::make_unique<IdentifierExpression>("");
|
||||
UnaryDerivativeExpression d(UnaryDerivative::kDpdy,
|
||||
DerivativeModifier::kCoarse, std::move(ident));
|
||||
EXPECT_FALSE(d.IsValid());
|
||||
}
|
||||
|
||||
TEST_F(UnaryDerivativeExpressionTest, ToStr) {
|
||||
auto ident = std::make_unique<IdentifierExpression>("ident");
|
||||
UnaryDerivativeExpression d(UnaryDerivative::kDpdy,
|
||||
DerivativeModifier::kCoarse, std::move(ident));
|
||||
std::ostringstream out;
|
||||
d.to_str(out, 2);
|
||||
EXPECT_EQ(out.str(), R"( UnaryDerivative{
|
||||
dpdy
|
||||
coarse
|
||||
Identifier{ident}
|
||||
}
|
||||
)");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace ast
|
||||
} // namespace tint
|
|
@ -1,59 +0,0 @@
|
|||
// 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/unary_method.h"
|
||||
|
||||
namespace tint {
|
||||
namespace ast {
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, UnaryMethod mod) {
|
||||
switch (mod) {
|
||||
case UnaryMethod::kAny: {
|
||||
out << "any";
|
||||
break;
|
||||
}
|
||||
case UnaryMethod::kAll: {
|
||||
out << "all";
|
||||
break;
|
||||
}
|
||||
case UnaryMethod::kIsNan: {
|
||||
out << "is_nan";
|
||||
break;
|
||||
}
|
||||
case UnaryMethod::kIsInf: {
|
||||
out << "is_inf";
|
||||
break;
|
||||
}
|
||||
case UnaryMethod::kIsFinite: {
|
||||
out << "is_finite";
|
||||
break;
|
||||
}
|
||||
case UnaryMethod::kIsNormal: {
|
||||
out << "is_normal";
|
||||
break;
|
||||
}
|
||||
case UnaryMethod::kDot: {
|
||||
out << "dot";
|
||||
break;
|
||||
}
|
||||
case UnaryMethod::kOuterProduct: {
|
||||
out << "outer_product";
|
||||
break;
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
} // namespace ast
|
||||
} // namespace tint
|
|
@ -1,40 +0,0 @@
|
|||
// 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_UNARY_METHOD_H_
|
||||
#define SRC_AST_UNARY_METHOD_H_
|
||||
|
||||
#include <ostream>
|
||||
|
||||
namespace tint {
|
||||
namespace ast {
|
||||
|
||||
/// The unary methods
|
||||
enum class UnaryMethod {
|
||||
kAny = 0,
|
||||
kAll,
|
||||
kIsNan,
|
||||
kIsInf,
|
||||
kIsFinite,
|
||||
kIsNormal,
|
||||
kDot,
|
||||
kOuterProduct
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, UnaryMethod mod);
|
||||
|
||||
} // namespace ast
|
||||
} // namespace tint
|
||||
|
||||
#endif // SRC_AST_UNARY_METHOD_H_
|
|
@ -1,65 +0,0 @@
|
|||
// 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/unary_method_expression.h"
|
||||
|
||||
namespace tint {
|
||||
namespace ast {
|
||||
|
||||
UnaryMethodExpression::UnaryMethodExpression() : Expression() {}
|
||||
|
||||
UnaryMethodExpression::UnaryMethodExpression(UnaryMethod op,
|
||||
ExpressionList params)
|
||||
: Expression(), op_(op), params_(std::move(params)) {}
|
||||
|
||||
UnaryMethodExpression::UnaryMethodExpression(const Source& source,
|
||||
UnaryMethod op,
|
||||
ExpressionList params)
|
||||
: Expression(source), op_(op), params_(std::move(params)) {}
|
||||
|
||||
UnaryMethodExpression::UnaryMethodExpression(UnaryMethodExpression&&) = default;
|
||||
|
||||
UnaryMethodExpression::~UnaryMethodExpression() = default;
|
||||
|
||||
bool UnaryMethodExpression::IsUnaryMethod() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UnaryMethodExpression::IsValid() const {
|
||||
if (params_.empty()) {
|
||||
return false;
|
||||
}
|
||||
for (const auto& p : params_) {
|
||||
if (p == nullptr || !p->IsValid()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void UnaryMethodExpression::to_str(std::ostream& out, size_t indent) const {
|
||||
make_indent(out, indent);
|
||||
|
||||
out << "UnaryMethod{" << std::endl;
|
||||
make_indent(out, indent + 2);
|
||||
out << op_ << std::endl;
|
||||
for (const auto& param : params_) {
|
||||
param->to_str(out, indent + 2);
|
||||
}
|
||||
make_indent(out, indent);
|
||||
out << "}" << std::endl;
|
||||
}
|
||||
|
||||
} // namespace ast
|
||||
} // namespace tint
|
|
@ -1,80 +0,0 @@
|
|||
// 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_UNARY_METHOD_EXPRESSION_H_
|
||||
#define SRC_AST_UNARY_METHOD_EXPRESSION_H_
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "src/ast/expression.h"
|
||||
#include "src/ast/literal.h"
|
||||
#include "src/ast/unary_method.h"
|
||||
|
||||
namespace tint {
|
||||
namespace ast {
|
||||
|
||||
/// A unary method expression
|
||||
class UnaryMethodExpression : public Expression {
|
||||
public:
|
||||
/// Constructor
|
||||
UnaryMethodExpression();
|
||||
/// Constructor
|
||||
/// @param op the op
|
||||
/// @param params the params
|
||||
UnaryMethodExpression(UnaryMethod op, ExpressionList params);
|
||||
/// Constructor
|
||||
/// @param source the unary method source
|
||||
/// @param op the op
|
||||
/// @param params the params
|
||||
UnaryMethodExpression(const Source& source,
|
||||
UnaryMethod op,
|
||||
ExpressionList params);
|
||||
/// Move constructor
|
||||
UnaryMethodExpression(UnaryMethodExpression&&);
|
||||
~UnaryMethodExpression() override;
|
||||
|
||||
/// Sets the op
|
||||
/// @param op the op
|
||||
void set_op(UnaryMethod op) { op_ = op; }
|
||||
/// @returns the op
|
||||
UnaryMethod op() const { return op_; }
|
||||
|
||||
/// Sets the params
|
||||
/// @param params the parameters
|
||||
void set_params(ExpressionList params) { params_ = std::move(params); }
|
||||
/// @returns the params
|
||||
const ExpressionList& params() const { return params_; }
|
||||
|
||||
/// @returns true if this is an as expression
|
||||
bool IsUnaryMethod() const override;
|
||||
|
||||
/// @returns true if the node is valid
|
||||
bool IsValid() const override;
|
||||
|
||||
/// Writes a representation of the node to the output stream
|
||||
/// @param out the stream to write to
|
||||
/// @param indent number of spaces to indent the node when writing
|
||||
void to_str(std::ostream& out, size_t indent) const override;
|
||||
|
||||
private:
|
||||
UnaryMethodExpression(const UnaryMethodExpression&) = delete;
|
||||
|
||||
UnaryMethod op_ = UnaryMethod::kAny;
|
||||
ExpressionList params_;
|
||||
};
|
||||
|
||||
} // namespace ast
|
||||
} // namespace tint
|
||||
|
||||
#endif // SRC_AST_UNARY_METHOD_EXPRESSION_H_
|
|
@ -1,103 +0,0 @@
|
|||
// 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/unary_method_expression.h"
|
||||
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "src/ast/identifier_expression.h"
|
||||
|
||||
namespace tint {
|
||||
namespace ast {
|
||||
namespace {
|
||||
|
||||
using UnaryMethodExpressionTest = testing::Test;
|
||||
|
||||
TEST_F(UnaryMethodExpressionTest, Creation) {
|
||||
ExpressionList params;
|
||||
params.push_back(std::make_unique<IdentifierExpression>("ident"));
|
||||
|
||||
auto* ident_ptr = params[0].get();
|
||||
|
||||
UnaryMethodExpression u(UnaryMethod::kAll, std::move(params));
|
||||
EXPECT_EQ(u.op(), UnaryMethod::kAll);
|
||||
ASSERT_EQ(u.params().size(), 1u);
|
||||
EXPECT_EQ(u.params()[0].get(), ident_ptr);
|
||||
}
|
||||
|
||||
TEST_F(UnaryMethodExpressionTest, Creation_WithSource) {
|
||||
ExpressionList params;
|
||||
params.push_back(std::make_unique<IdentifierExpression>("ident"));
|
||||
|
||||
UnaryMethodExpression u(Source{20, 2}, UnaryMethod::kAll, std::move(params));
|
||||
auto src = u.source();
|
||||
EXPECT_EQ(src.line, 20u);
|
||||
EXPECT_EQ(src.column, 2u);
|
||||
}
|
||||
|
||||
TEST_F(UnaryMethodExpressionTest, IsUnaryMethod) {
|
||||
UnaryMethodExpression u;
|
||||
EXPECT_TRUE(u.IsUnaryMethod());
|
||||
}
|
||||
|
||||
TEST_F(UnaryMethodExpressionTest, IsValid) {
|
||||
ExpressionList params;
|
||||
params.push_back(std::make_unique<IdentifierExpression>("ident"));
|
||||
|
||||
UnaryMethodExpression u(UnaryMethod::kAll, std::move(params));
|
||||
EXPECT_TRUE(u.IsValid());
|
||||
}
|
||||
|
||||
TEST_F(UnaryMethodExpressionTest, IsValid_NullParam) {
|
||||
ExpressionList params;
|
||||
params.push_back(std::make_unique<IdentifierExpression>("ident"));
|
||||
params.push_back(nullptr);
|
||||
|
||||
UnaryMethodExpression u(UnaryMethod::kAll, std::move(params));
|
||||
EXPECT_FALSE(u.IsValid());
|
||||
}
|
||||
|
||||
TEST_F(UnaryMethodExpressionTest, IsValid_InvalidParam) {
|
||||
ExpressionList params;
|
||||
params.push_back(std::make_unique<IdentifierExpression>(""));
|
||||
|
||||
UnaryMethodExpression u(UnaryMethod::kAll, std::move(params));
|
||||
EXPECT_FALSE(u.IsValid());
|
||||
}
|
||||
|
||||
TEST_F(UnaryMethodExpressionTest, IsValid_EmptyParams) {
|
||||
UnaryMethodExpression u;
|
||||
u.set_op(UnaryMethod::kAll);
|
||||
EXPECT_FALSE(u.IsValid());
|
||||
}
|
||||
|
||||
TEST_F(UnaryMethodExpressionTest, ToStr) {
|
||||
ExpressionList params;
|
||||
params.push_back(std::make_unique<IdentifierExpression>("ident"));
|
||||
|
||||
UnaryMethodExpression u(UnaryMethod::kAll, std::move(params));
|
||||
std::ostringstream out;
|
||||
u.to_str(out, 2);
|
||||
EXPECT_EQ(out.str(), R"( UnaryMethod{
|
||||
all
|
||||
Identifier{ident}
|
||||
}
|
||||
)");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace ast
|
||||
} // namespace tint
|
|
@ -468,10 +468,6 @@ Token Lexer::try_punctuation() {
|
|||
}
|
||||
|
||||
Token Lexer::check_keyword(const Source& source, const std::string& str) {
|
||||
if (str == "all")
|
||||
return {Token::Type::kAll, source, "all"};
|
||||
if (str == "any")
|
||||
return {Token::Type::kAny, source, "any"};
|
||||
if (str == "array")
|
||||
return {Token::Type::kArray, source, "array"};
|
||||
if (str == "as")
|
||||
|
@ -498,16 +494,8 @@ Token Lexer::check_keyword(const Source& source, const std::string& str) {
|
|||
return {Token::Type::kContinue, source, "continue"};
|
||||
if (str == "continuing")
|
||||
return {Token::Type::kContinuing, source, "continuing"};
|
||||
if (str == "coarse")
|
||||
return {Token::Type::kCoarse, source, "coarse"};
|
||||
if (str == "default")
|
||||
return {Token::Type::kDefault, source, "default"};
|
||||
if (str == "dot")
|
||||
return {Token::Type::kDot, source, "dot"};
|
||||
if (str == "dpdx")
|
||||
return {Token::Type::kDpdx, source, "dpdx"};
|
||||
if (str == "dpdy")
|
||||
return {Token::Type::kDpdy, source, "dpdy"};
|
||||
if (str == "else")
|
||||
return {Token::Type::kElse, source, "else"};
|
||||
if (str == "elseif")
|
||||
|
@ -520,16 +508,12 @@ Token Lexer::check_keyword(const Source& source, const std::string& str) {
|
|||
return {Token::Type::kFallthrough, source, "fallthrough"};
|
||||
if (str == "false")
|
||||
return {Token::Type::kFalse, source, "false"};
|
||||
if (str == "fine")
|
||||
return {Token::Type::kFine, source, "fine"};
|
||||
if (str == "fn")
|
||||
return {Token::Type::kFn, source, "fn"};
|
||||
if (str == "fragment")
|
||||
return {Token::Type::kFragment, source, "fragment"};
|
||||
if (str == "function")
|
||||
return {Token::Type::kFunction, source, "function"};
|
||||
if (str == "fwidth")
|
||||
return {Token::Type::kFwidth, source, "fwidth"};
|
||||
if (str == "i32")
|
||||
return {Token::Type::kI32, source, "i32"};
|
||||
if (str == "if")
|
||||
|
@ -540,14 +524,6 @@ Token Lexer::check_keyword(const Source& source, const std::string& str) {
|
|||
return {Token::Type::kImport, source, "import"};
|
||||
if (str == "in")
|
||||
return {Token::Type::kIn, source, "in"};
|
||||
if (str == "is_nan")
|
||||
return {Token::Type::kIsNan, source, "is_nan"};
|
||||
if (str == "is_inf")
|
||||
return {Token::Type::kIsInf, source, "is_inf"};
|
||||
if (str == "is_finite")
|
||||
return {Token::Type::kIsFinite, source, "is_finite"};
|
||||
if (str == "is_normal")
|
||||
return {Token::Type::kIsNormal, source, "is_normal"};
|
||||
if (str == "kill")
|
||||
return {Token::Type::kKill, source, "kill"};
|
||||
if (str == "location")
|
||||
|
@ -576,8 +552,6 @@ Token Lexer::check_keyword(const Source& source, const std::string& str) {
|
|||
return {Token::Type::kOffset, source, "offset"};
|
||||
if (str == "out")
|
||||
return {Token::Type::kOut, source, "out"};
|
||||
if (str == "outer_product")
|
||||
return {Token::Type::kOuterProduct, source, "outer_product"};
|
||||
if (str == "private")
|
||||
return {Token::Type::kPrivate, source, "private"};
|
||||
if (str == "ptr")
|
||||
|
|
|
@ -408,82 +408,69 @@ TEST_P(KeywordTest, Parses) {
|
|||
INSTANTIATE_TEST_SUITE_P(
|
||||
LexerTest,
|
||||
KeywordTest,
|
||||
testing::Values(
|
||||
TokenData{"all", Token::Type::kAll},
|
||||
TokenData{"any", Token::Type::kAny},
|
||||
TokenData{"array", Token::Type::kArray},
|
||||
TokenData{"as", Token::Type::kAs},
|
||||
TokenData{"binding", Token::Type::kBinding},
|
||||
TokenData{"block", Token::Type::kBlock},
|
||||
TokenData{"bool", Token::Type::kBool},
|
||||
TokenData{"break", Token::Type::kBreak},
|
||||
TokenData{"builtin", Token::Type::kBuiltin},
|
||||
TokenData{"case", Token::Type::kCase},
|
||||
TokenData{"cast", Token::Type::kCast},
|
||||
TokenData{"compute", Token::Type::kCompute},
|
||||
TokenData{"const", Token::Type::kConst},
|
||||
TokenData{"continue", Token::Type::kContinue},
|
||||
TokenData{"continuing", Token::Type::kContinuing},
|
||||
TokenData{"coarse", Token::Type::kCoarse},
|
||||
TokenData{"default", Token::Type::kDefault},
|
||||
TokenData{"dot", Token::Type::kDot},
|
||||
TokenData{"dpdx", Token::Type::kDpdx},
|
||||
TokenData{"dpdy", Token::Type::kDpdy},
|
||||
TokenData{"else", Token::Type::kElse},
|
||||
TokenData{"elseif", Token::Type::kElseIf},
|
||||
TokenData{"entry_point", Token::Type::kEntryPoint},
|
||||
TokenData{"f32", Token::Type::kF32},
|
||||
TokenData{"fallthrough", Token::Type::kFallthrough},
|
||||
TokenData{"false", Token::Type::kFalse},
|
||||
TokenData{"fine", Token::Type::kFine},
|
||||
TokenData{"fn", Token::Type::kFn},
|
||||
TokenData{"fragment", Token::Type::kFragment},
|
||||
TokenData{"function", Token::Type::kFunction},
|
||||
TokenData{"fwidth", Token::Type::kFwidth},
|
||||
TokenData{"i32", Token::Type::kI32},
|
||||
TokenData{"if", Token::Type::kIf},
|
||||
TokenData{"image", Token::Type::kImage},
|
||||
TokenData{"import", Token::Type::kImport},
|
||||
TokenData{"in", Token::Type::kIn},
|
||||
TokenData{"is_nan", Token::Type::kIsNan},
|
||||
TokenData{"is_inf", Token::Type::kIsInf},
|
||||
TokenData{"is_finite", Token::Type::kIsFinite},
|
||||
TokenData{"is_normal", Token::Type::kIsNormal},
|
||||
TokenData{"kill", Token::Type::kKill},
|
||||
TokenData{"location", Token::Type::kLocation},
|
||||
TokenData{"loop", Token::Type::kLoop},
|
||||
TokenData{"mat2x2", Token::Type::kMat2x2},
|
||||
TokenData{"mat2x3", Token::Type::kMat2x3},
|
||||
TokenData{"mat2x4", Token::Type::kMat2x4},
|
||||
TokenData{"mat3x2", Token::Type::kMat3x2},
|
||||
TokenData{"mat3x3", Token::Type::kMat3x3},
|
||||
TokenData{"mat3x4", Token::Type::kMat3x4},
|
||||
TokenData{"mat4x2", Token::Type::kMat4x2},
|
||||
TokenData{"mat4x3", Token::Type::kMat4x3},
|
||||
TokenData{"mat4x4", Token::Type::kMat4x4},
|
||||
TokenData{"offset", Token::Type::kOffset},
|
||||
TokenData{"out", Token::Type::kOut},
|
||||
TokenData{"outer_product", Token::Type::kOuterProduct},
|
||||
TokenData{"private", Token::Type::kPrivate},
|
||||
TokenData{"ptr", Token::Type::kPtr},
|
||||
TokenData{"return", Token::Type::kReturn},
|
||||
TokenData{"set", Token::Type::kSet},
|
||||
TokenData{"storage_buffer", Token::Type::kStorageBuffer},
|
||||
TokenData{"struct", Token::Type::kStruct},
|
||||
TokenData{"switch", Token::Type::kSwitch},
|
||||
TokenData{"true", Token::Type::kTrue},
|
||||
TokenData{"type", Token::Type::kType},
|
||||
TokenData{"u32", Token::Type::kU32},
|
||||
TokenData{"uniform", Token::Type::kUniform},
|
||||
TokenData{"uniform_constant", Token::Type::kUniformConstant},
|
||||
TokenData{"unless", Token::Type::kUnless},
|
||||
TokenData{"var", Token::Type::kVar},
|
||||
TokenData{"vec2", Token::Type::kVec2},
|
||||
TokenData{"vec3", Token::Type::kVec3},
|
||||
TokenData{"vec4", Token::Type::kVec4},
|
||||
TokenData{"vertex", Token::Type::kVertex},
|
||||
TokenData{"void", Token::Type::kVoid},
|
||||
TokenData{"workgroup", Token::Type::kWorkgroup}));
|
||||
testing::Values(TokenData{"array", Token::Type::kArray},
|
||||
TokenData{"as", Token::Type::kAs},
|
||||
TokenData{"binding", Token::Type::kBinding},
|
||||
TokenData{"block", Token::Type::kBlock},
|
||||
TokenData{"bool", Token::Type::kBool},
|
||||
TokenData{"break", Token::Type::kBreak},
|
||||
TokenData{"builtin", Token::Type::kBuiltin},
|
||||
TokenData{"case", Token::Type::kCase},
|
||||
TokenData{"cast", Token::Type::kCast},
|
||||
TokenData{"compute", Token::Type::kCompute},
|
||||
TokenData{"const", Token::Type::kConst},
|
||||
TokenData{"continue", Token::Type::kContinue},
|
||||
TokenData{"continuing", Token::Type::kContinuing},
|
||||
TokenData{"default", Token::Type::kDefault},
|
||||
TokenData{"else", Token::Type::kElse},
|
||||
TokenData{"elseif", Token::Type::kElseIf},
|
||||
TokenData{"entry_point", Token::Type::kEntryPoint},
|
||||
TokenData{"f32", Token::Type::kF32},
|
||||
TokenData{"fallthrough", Token::Type::kFallthrough},
|
||||
TokenData{"false", Token::Type::kFalse},
|
||||
TokenData{"fn", Token::Type::kFn},
|
||||
TokenData{"fragment", Token::Type::kFragment},
|
||||
TokenData{"function", Token::Type::kFunction},
|
||||
TokenData{"i32", Token::Type::kI32},
|
||||
TokenData{"if", Token::Type::kIf},
|
||||
TokenData{"image", Token::Type::kImage},
|
||||
TokenData{"import", Token::Type::kImport},
|
||||
TokenData{"in", Token::Type::kIn},
|
||||
TokenData{"kill", Token::Type::kKill},
|
||||
TokenData{"location", Token::Type::kLocation},
|
||||
TokenData{"loop", Token::Type::kLoop},
|
||||
TokenData{"mat2x2", Token::Type::kMat2x2},
|
||||
TokenData{"mat2x3", Token::Type::kMat2x3},
|
||||
TokenData{"mat2x4", Token::Type::kMat2x4},
|
||||
TokenData{"mat3x2", Token::Type::kMat3x2},
|
||||
TokenData{"mat3x3", Token::Type::kMat3x3},
|
||||
TokenData{"mat3x4", Token::Type::kMat3x4},
|
||||
TokenData{"mat4x2", Token::Type::kMat4x2},
|
||||
TokenData{"mat4x3", Token::Type::kMat4x3},
|
||||
TokenData{"mat4x4", Token::Type::kMat4x4},
|
||||
TokenData{"offset", Token::Type::kOffset},
|
||||
TokenData{"out", Token::Type::kOut},
|
||||
TokenData{"private", Token::Type::kPrivate},
|
||||
TokenData{"ptr", Token::Type::kPtr},
|
||||
TokenData{"return", Token::Type::kReturn},
|
||||
TokenData{"set", Token::Type::kSet},
|
||||
TokenData{"storage_buffer", Token::Type::kStorageBuffer},
|
||||
TokenData{"struct", Token::Type::kStruct},
|
||||
TokenData{"switch", Token::Type::kSwitch},
|
||||
TokenData{"true", Token::Type::kTrue},
|
||||
TokenData{"type", Token::Type::kType},
|
||||
TokenData{"u32", Token::Type::kU32},
|
||||
TokenData{"uniform", Token::Type::kUniform},
|
||||
TokenData{"uniform_constant",
|
||||
Token::Type::kUniformConstant},
|
||||
TokenData{"unless", Token::Type::kUnless},
|
||||
TokenData{"var", Token::Type::kVar},
|
||||
TokenData{"vec2", Token::Type::kVec2},
|
||||
TokenData{"vec3", Token::Type::kVec3},
|
||||
TokenData{"vec4", Token::Type::kVec4},
|
||||
TokenData{"vertex", Token::Type::kVertex},
|
||||
TokenData{"void", Token::Type::kVoid},
|
||||
TokenData{"workgroup", Token::Type::kWorkgroup}));
|
||||
|
||||
using KeywordTest_Reserved = testing::TestWithParam<const char*>;
|
||||
TEST_P(KeywordTest_Reserved, Parses) {
|
||||
|
|
|
@ -57,10 +57,6 @@
|
|||
#include "src/ast/type/void_type.h"
|
||||
#include "src/ast/type_constructor_expression.h"
|
||||
#include "src/ast/uint_literal.h"
|
||||
#include "src/ast/unary_derivative.h"
|
||||
#include "src/ast/unary_derivative_expression.h"
|
||||
#include "src/ast/unary_method.h"
|
||||
#include "src/ast/unary_method_expression.h"
|
||||
#include "src/ast/unary_op.h"
|
||||
#include "src/ast/unary_op_expression.h"
|
||||
#include "src/ast/variable_decl_statement.h"
|
||||
|
@ -2338,30 +2334,6 @@ std::unique_ptr<ast::Expression> ParserImpl::postfix_expression() {
|
|||
// : postfix_expression
|
||||
// | MINUS unary_expression
|
||||
// | BANG unary_expression
|
||||
// | ANY PAREN_LEFT IDENT PAREN_RIGHT
|
||||
// | ALL PAREN_LEFT IDENT PAREN_RIGHT
|
||||
// | IS_NAN PAREN_LEFT IDENT PAREN_RIGHT
|
||||
// | IS_INF PAREN_LEFT IDENT PAREN_RIGHT
|
||||
// | IS_FINITE PAREN_LEFT IDENT PAREN_RIGHT
|
||||
// | IS_NORMAL PAREN_LEFT IDENT PAREN_RIGHT
|
||||
// | DOT PAREN_LEFT IDENT COMMA IDENT PAREN_RIGHT
|
||||
// | OUTER_PRODUCT PAREN_LEFT IDENT COMMA IDENT PAREN_RIGHT
|
||||
// | DPDX (LESS_THAN derivative_modifier GREATER_THAN)?
|
||||
// PAREN_LEFT IDENT PAREN_RIGHT
|
||||
// | DPDY (LESS_THAN derivative_modifier GREATER_THAN)?
|
||||
// PAREN_LEFT IDENT PAREN_RIGHT
|
||||
// | FWIDTH (LESS_THAN derivative_modifier GREATER_THAN)?
|
||||
// PAREN_LEFT IDENT PAREN_RIGHT
|
||||
// # | unord_greater_than_equal(a, b)
|
||||
// # | unord_greater_than(a, b)
|
||||
// # | unord_less_than_equal(a, b)
|
||||
// # | unord_less_than(a, b)
|
||||
// # | unord_not_equal(a, b)
|
||||
// # | unord_equal(a, b)
|
||||
// # | signed_greater_than_equal(a, b)
|
||||
// # | signed_greater_than(a, b)
|
||||
// # | signed_less_than_equal(a, b)
|
||||
// # | signed_less_than(a, b)
|
||||
std::unique_ptr<ast::Expression> ParserImpl::unary_expression() {
|
||||
auto t = peek();
|
||||
auto source = t.source();
|
||||
|
@ -2385,158 +2357,9 @@ std::unique_ptr<ast::Expression> ParserImpl::unary_expression() {
|
|||
return std::make_unique<ast::UnaryOpExpression>(source, op,
|
||||
std::move(expr));
|
||||
}
|
||||
if (t.IsAny() || t.IsAll() || t.IsIsNan() || t.IsIsInf() || t.IsIsFinite() ||
|
||||
t.IsIsNormal()) {
|
||||
next(); // Consume the peek
|
||||
|
||||
auto op = ast::UnaryMethod::kAny;
|
||||
if (t.IsAll())
|
||||
op = ast::UnaryMethod::kAll;
|
||||
else if (t.IsIsNan())
|
||||
op = ast::UnaryMethod::kIsNan;
|
||||
else if (t.IsIsInf())
|
||||
op = ast::UnaryMethod::kIsInf;
|
||||
else if (t.IsIsFinite())
|
||||
op = ast::UnaryMethod::kIsFinite;
|
||||
else if (t.IsIsNormal())
|
||||
op = ast::UnaryMethod::kIsNormal;
|
||||
|
||||
t = next();
|
||||
if (!t.IsParenLeft()) {
|
||||
set_error(t, "missing ( for method call");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
t = next();
|
||||
if (!t.IsIdentifier()) {
|
||||
set_error(t, "missing identifier for method call");
|
||||
return nullptr;
|
||||
}
|
||||
ast::ExpressionList ident;
|
||||
ident.push_back(
|
||||
std::make_unique<ast::IdentifierExpression>(source, t.to_str()));
|
||||
|
||||
t = next();
|
||||
if (!t.IsParenRight()) {
|
||||
set_error(t, "missing ) for method call");
|
||||
return nullptr;
|
||||
}
|
||||
return std::make_unique<ast::UnaryMethodExpression>(source, op,
|
||||
std::move(ident));
|
||||
}
|
||||
if (t.IsDot() || t.IsOuterProduct()) {
|
||||
next(); // Consume the peek
|
||||
|
||||
auto op = ast::UnaryMethod::kDot;
|
||||
if (t.IsOuterProduct())
|
||||
op = ast::UnaryMethod::kOuterProduct;
|
||||
|
||||
t = next();
|
||||
if (!t.IsParenLeft()) {
|
||||
set_error(t, "missing ( for method call");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
t = next();
|
||||
if (!t.IsIdentifier()) {
|
||||
set_error(t, "missing identifier for method call");
|
||||
return nullptr;
|
||||
}
|
||||
ast::ExpressionList ident;
|
||||
ident.push_back(
|
||||
std::make_unique<ast::IdentifierExpression>(source, t.to_str()));
|
||||
|
||||
t = next();
|
||||
if (!t.IsComma()) {
|
||||
set_error(t, "missing , for method call");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
t = next();
|
||||
if (!t.IsIdentifier()) {
|
||||
set_error(t, "missing identifier for method call");
|
||||
return nullptr;
|
||||
}
|
||||
ident.push_back(
|
||||
std::make_unique<ast::IdentifierExpression>(source, t.to_str()));
|
||||
|
||||
t = next();
|
||||
if (!t.IsParenRight()) {
|
||||
set_error(t, "missing ) for method call");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return std::make_unique<ast::UnaryMethodExpression>(source, op,
|
||||
std::move(ident));
|
||||
}
|
||||
if (t.IsDpdx() || t.IsDpdy() || t.IsFwidth()) {
|
||||
next(); // Consume the peek
|
||||
|
||||
auto op = ast::UnaryDerivative::kDpdx;
|
||||
if (t.IsDpdy())
|
||||
op = ast::UnaryDerivative::kDpdy;
|
||||
else if (t.IsFwidth())
|
||||
op = ast::UnaryDerivative::kFwidth;
|
||||
|
||||
t = next();
|
||||
auto mod = ast::DerivativeModifier::kNone;
|
||||
if (t.IsLessThan()) {
|
||||
mod = derivative_modifier();
|
||||
if (has_error())
|
||||
return nullptr;
|
||||
if (mod == ast::DerivativeModifier::kNone) {
|
||||
set_error(peek(), "unable to parse derivative modifier");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
t = next();
|
||||
if (!t.IsGreaterThan()) {
|
||||
set_error(t, "missing > for derivative modifier");
|
||||
return nullptr;
|
||||
}
|
||||
t = next();
|
||||
}
|
||||
if (!t.IsParenLeft()) {
|
||||
set_error(t, "missing ( for derivative method");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
t = next();
|
||||
if (!t.IsIdentifier()) {
|
||||
set_error(t, "missing identifier for derivative method");
|
||||
return nullptr;
|
||||
}
|
||||
auto ident =
|
||||
std::make_unique<ast::IdentifierExpression>(source, t.to_str());
|
||||
|
||||
t = next();
|
||||
if (!t.IsParenRight()) {
|
||||
set_error(t, "missing ) for derivative method");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return std::make_unique<ast::UnaryDerivativeExpression>(source, op, mod,
|
||||
std::move(ident));
|
||||
}
|
||||
return postfix_expression();
|
||||
}
|
||||
|
||||
// derivative_modifier
|
||||
// : FINE
|
||||
// | COARSE
|
||||
ast::DerivativeModifier ParserImpl::derivative_modifier() {
|
||||
auto t = peek();
|
||||
if (t.IsFine()) {
|
||||
next(); // Consume the peek
|
||||
return ast::DerivativeModifier::kFine;
|
||||
}
|
||||
if (t.IsCoarse()) {
|
||||
next(); // Consume the peek
|
||||
return ast::DerivativeModifier::kCoarse;
|
||||
}
|
||||
return ast::DerivativeModifier::kNone;
|
||||
}
|
||||
|
||||
// multiplicative_expr
|
||||
// :
|
||||
// | STAR unary_expression multiplicative_expr
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include "src/ast/assignment_statement.h"
|
||||
#include "src/ast/builtin.h"
|
||||
#include "src/ast/constructor_expression.h"
|
||||
#include "src/ast/derivative_modifier.h"
|
||||
#include "src/ast/else_statement.h"
|
||||
#include "src/ast/entry_point.h"
|
||||
#include "src/ast/function.h"
|
||||
|
@ -246,9 +245,6 @@ class ParserImpl {
|
|||
/// Parses a `unary_expression` grammar element
|
||||
/// @returns the parsed expression or nullptr
|
||||
std::unique_ptr<ast::Expression> unary_expression();
|
||||
/// Parses a `derivative_modifier` grammar element
|
||||
/// @returns the modifier or DerivativeModifier::kNone if none matched
|
||||
ast::DerivativeModifier derivative_modifier();
|
||||
/// Parses the recursive part of the `multiplicative_expression`
|
||||
/// @param lhs the left side of the expression
|
||||
/// @returns the parsed expression or nullptr
|
||||
|
|
|
@ -17,8 +17,6 @@
|
|||
#include "src/ast/identifier_expression.h"
|
||||
#include "src/ast/int_literal.h"
|
||||
#include "src/ast/scalar_constructor_expression.h"
|
||||
#include "src/ast/unary_derivative_expression.h"
|
||||
#include "src/ast/unary_method_expression.h"
|
||||
#include "src/ast/unary_op_expression.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
|
|
@ -1,86 +0,0 @@
|
|||
// 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 "gtest/gtest.h"
|
||||
#include "src/ast/derivative_modifier.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace wgsl {
|
||||
namespace {
|
||||
|
||||
struct DerivativeModifierData {
|
||||
const char* input;
|
||||
ast::DerivativeModifier result;
|
||||
};
|
||||
inline std::ostream& operator<<(std::ostream& out,
|
||||
DerivativeModifierData data) {
|
||||
out << std::string(data.input);
|
||||
return out;
|
||||
}
|
||||
|
||||
class DerivativeModifierTest
|
||||
: public testing::TestWithParam<DerivativeModifierData> {
|
||||
public:
|
||||
DerivativeModifierTest() = default;
|
||||
~DerivativeModifierTest() override = default;
|
||||
|
||||
void SetUp() override { ctx_.Reset(); }
|
||||
|
||||
void TearDown() override { impl_ = nullptr; }
|
||||
|
||||
ParserImpl* parser(const std::string& str) {
|
||||
impl_ = std::make_unique<ParserImpl>(&ctx_, str);
|
||||
return impl_.get();
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<ParserImpl> impl_;
|
||||
Context ctx_;
|
||||
};
|
||||
|
||||
TEST_P(DerivativeModifierTest, Parses) {
|
||||
auto params = GetParam();
|
||||
auto* p = parser(params.input);
|
||||
|
||||
auto mod = p->derivative_modifier();
|
||||
ASSERT_FALSE(p->has_error());
|
||||
EXPECT_EQ(mod, params.result);
|
||||
|
||||
auto t = p->next();
|
||||
EXPECT_TRUE(t.IsEof());
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
ParserImplTest,
|
||||
DerivativeModifierTest,
|
||||
testing::Values(
|
||||
DerivativeModifierData{"fine", ast::DerivativeModifier::kFine},
|
||||
DerivativeModifierData{"coarse", ast::DerivativeModifier::kCoarse}));
|
||||
|
||||
TEST_F(ParserImplTest, DerivativeModifier_NoMatch) {
|
||||
auto* p = parser("not-a-modifier");
|
||||
auto stage = p->derivative_modifier();
|
||||
ASSERT_EQ(stage, ast::DerivativeModifier::kNone);
|
||||
|
||||
auto t = p->next();
|
||||
EXPECT_TRUE(t.IsIdentifier());
|
||||
EXPECT_EQ(t.to_str(), "not");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace wgsl
|
||||
} // namespace reader
|
||||
} // namespace tint
|
|
@ -19,8 +19,6 @@
|
|||
#include "src/ast/int_literal.h"
|
||||
#include "src/ast/member_accessor_expression.h"
|
||||
#include "src/ast/scalar_constructor_expression.h"
|
||||
#include "src/ast/unary_derivative_expression.h"
|
||||
#include "src/ast/unary_method_expression.h"
|
||||
#include "src/ast/unary_op_expression.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
|
|
@ -23,8 +23,6 @@
|
|||
#include "src/ast/type/f32_type.h"
|
||||
#include "src/ast/type/i32_type.h"
|
||||
#include "src/ast/type_constructor_expression.h"
|
||||
#include "src/ast/unary_derivative_expression.h"
|
||||
#include "src/ast/unary_method_expression.h"
|
||||
#include "src/ast/unary_op_expression.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
|
|
@ -17,8 +17,6 @@
|
|||
#include "src/ast/identifier_expression.h"
|
||||
#include "src/ast/int_literal.h"
|
||||
#include "src/ast/scalar_constructor_expression.h"
|
||||
#include "src/ast/unary_derivative_expression.h"
|
||||
#include "src/ast/unary_method_expression.h"
|
||||
#include "src/ast/unary_op_expression.h"
|
||||
#include "src/reader/wgsl/parser_impl.h"
|
||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||
|
@ -99,732 +97,6 @@ TEST_F(ParserImplTest, UnaryExpression_Bang_InvalidRHS) {
|
|||
EXPECT_EQ(p->error(), "1:2: unable to parse right side of ! expression");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Any) {
|
||||
auto* p = parser("any(a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsUnaryMethod());
|
||||
|
||||
auto* u = e->AsUnaryMethod();
|
||||
ASSERT_EQ(u->op(), ast::UnaryMethod::kAny);
|
||||
ASSERT_EQ(u->params().size(), 1u);
|
||||
ASSERT_TRUE(u->params()[0]->IsIdentifier());
|
||||
auto* ident = u->params()[0]->AsIdentifier();
|
||||
EXPECT_EQ(ident->name(), "a");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Any_MissingParenLeft) {
|
||||
auto* p = parser("any a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:5: missing ( for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Any_MissingParenRight) {
|
||||
auto* p = parser("any(a");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:6: missing ) for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Any_MissingIdentifier) {
|
||||
auto* p = parser("any()");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:5: missing identifier for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Any_InvalidIdentifier) {
|
||||
auto* p = parser("any(123)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:5: missing identifier for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_All) {
|
||||
auto* p = parser("all(a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsUnaryMethod());
|
||||
|
||||
auto* u = e->AsUnaryMethod();
|
||||
ASSERT_EQ(u->op(), ast::UnaryMethod::kAll);
|
||||
ASSERT_EQ(u->params().size(), 1u);
|
||||
ASSERT_TRUE(u->params()[0]->IsIdentifier());
|
||||
auto* ident = u->params()[0]->AsIdentifier();
|
||||
EXPECT_EQ(ident->name(), "a");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_All_MissingParenLeft) {
|
||||
auto* p = parser("all a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:5: missing ( for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_All_MissingParenRight) {
|
||||
auto* p = parser("all(a");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:6: missing ) for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_All_MissingIdentifier) {
|
||||
auto* p = parser("all()");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:5: missing identifier for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_All_InvalidIdentifier) {
|
||||
auto* p = parser("all(123)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:5: missing identifier for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_IsNan) {
|
||||
auto* p = parser("is_nan(a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsUnaryMethod());
|
||||
|
||||
auto* u = e->AsUnaryMethod();
|
||||
ASSERT_EQ(u->op(), ast::UnaryMethod::kIsNan);
|
||||
ASSERT_EQ(u->params().size(), 1u);
|
||||
ASSERT_TRUE(u->params()[0]->IsIdentifier());
|
||||
auto* ident = u->params()[0]->AsIdentifier();
|
||||
EXPECT_EQ(ident->name(), "a");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_IsNan_MissingParenLeft) {
|
||||
auto* p = parser("is_nan a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:8: missing ( for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_IsNan_MissingParenRight) {
|
||||
auto* p = parser("is_nan(a");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:9: missing ) for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_IsNan_MissingIdentifier) {
|
||||
auto* p = parser("is_nan()");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:8: missing identifier for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_IsNan_InvalidIdentifier) {
|
||||
auto* p = parser("is_nan(123)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:8: missing identifier for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_IsInf) {
|
||||
auto* p = parser("is_inf(a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsUnaryMethod());
|
||||
|
||||
auto* u = e->AsUnaryMethod();
|
||||
ASSERT_EQ(u->op(), ast::UnaryMethod::kIsInf);
|
||||
ASSERT_EQ(u->params().size(), 1u);
|
||||
ASSERT_TRUE(u->params()[0]->IsIdentifier());
|
||||
auto* ident = u->params()[0]->AsIdentifier();
|
||||
EXPECT_EQ(ident->name(), "a");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_IsInf_MissingParenLeft) {
|
||||
auto* p = parser("is_inf a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:8: missing ( for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_IsInf_MissingParenRight) {
|
||||
auto* p = parser("is_inf(a");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:9: missing ) for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_IsInf_MissingIdentifier) {
|
||||
auto* p = parser("is_inf()");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:8: missing identifier for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_IsInf_InvalidIdentifier) {
|
||||
auto* p = parser("is_inf(123)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:8: missing identifier for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_IsFinite) {
|
||||
auto* p = parser("is_finite(a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsUnaryMethod());
|
||||
|
||||
auto* u = e->AsUnaryMethod();
|
||||
ASSERT_EQ(u->op(), ast::UnaryMethod::kIsFinite);
|
||||
ASSERT_EQ(u->params().size(), 1u);
|
||||
ASSERT_TRUE(u->params()[0]->IsIdentifier());
|
||||
auto* ident = u->params()[0]->AsIdentifier();
|
||||
EXPECT_EQ(ident->name(), "a");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_IsFinite_MissingParenLeft) {
|
||||
auto* p = parser("is_finite a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:11: missing ( for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_IsFinite_MissingParenRight) {
|
||||
auto* p = parser("is_finite(a");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:12: missing ) for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_IsFinite_MissingIdentifier) {
|
||||
auto* p = parser("is_finite()");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:11: missing identifier for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_IsFinite_InvalidIdentifier) {
|
||||
auto* p = parser("is_finite(123)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:11: missing identifier for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_IsNormal) {
|
||||
auto* p = parser("is_normal(a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsUnaryMethod());
|
||||
|
||||
auto* u = e->AsUnaryMethod();
|
||||
ASSERT_EQ(u->op(), ast::UnaryMethod::kIsNormal);
|
||||
ASSERT_EQ(u->params().size(), 1u);
|
||||
ASSERT_TRUE(u->params()[0]->IsIdentifier());
|
||||
auto* ident = u->params()[0]->AsIdentifier();
|
||||
EXPECT_EQ(ident->name(), "a");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_IsNormal_MissingParenLeft) {
|
||||
auto* p = parser("is_normal a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:11: missing ( for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_IsNormal_MissingParenRight) {
|
||||
auto* p = parser("is_normal(a");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:12: missing ) for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_IsNormal_MissingIdentifier) {
|
||||
auto* p = parser("is_normal()");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:11: missing identifier for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_IsNormal_InvalidIdentifier) {
|
||||
auto* p = parser("is_normal(123)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:11: missing identifier for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dot) {
|
||||
auto* p = parser("dot(a, b)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsUnaryMethod());
|
||||
|
||||
auto* u = e->AsUnaryMethod();
|
||||
ASSERT_EQ(u->op(), ast::UnaryMethod::kDot);
|
||||
ASSERT_EQ(u->params().size(), 2u);
|
||||
ASSERT_TRUE(u->params()[0]->IsIdentifier());
|
||||
auto* ident = u->params()[0]->AsIdentifier();
|
||||
EXPECT_EQ(ident->name(), "a");
|
||||
|
||||
ASSERT_TRUE(u->params()[1]->IsIdentifier());
|
||||
ident = u->params()[1]->AsIdentifier();
|
||||
EXPECT_EQ(ident->name(), "b");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dot_MissingParenLeft) {
|
||||
auto* p = parser("dot a, b)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:5: missing ( for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dot_MissingParenRight) {
|
||||
auto* p = parser("dot(a, b");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:9: missing ) for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dot_MissingFirstIdentifier) {
|
||||
auto* p = parser("dot(, a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:5: missing identifier for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dot_MissingSecondIdentifier) {
|
||||
auto* p = parser("dot(a, )");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:8: missing identifier for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dot_MissingComma) {
|
||||
auto* p = parser("dot(a b)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:7: missing , for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dot_InvalidFirstIdentifier) {
|
||||
auto* p = parser("dot(123, b)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:5: missing identifier for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dot_InvalidSecondIdentifier) {
|
||||
auto* p = parser("dot(a, 123)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:8: missing identifier for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_OuterProduct) {
|
||||
auto* p = parser("outer_product(a, b)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsUnaryMethod());
|
||||
|
||||
auto* u = e->AsUnaryMethod();
|
||||
ASSERT_EQ(u->op(), ast::UnaryMethod::kOuterProduct);
|
||||
ASSERT_EQ(u->params().size(), 2u);
|
||||
ASSERT_TRUE(u->params()[0]->IsIdentifier());
|
||||
auto* ident = u->params()[0]->AsIdentifier();
|
||||
EXPECT_EQ(ident->name(), "a");
|
||||
|
||||
ASSERT_TRUE(u->params()[1]->IsIdentifier());
|
||||
ident = u->params()[1]->AsIdentifier();
|
||||
EXPECT_EQ(ident->name(), "b");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_OuterProduct_MissingParenLeft) {
|
||||
auto* p = parser("outer_product a, b)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:15: missing ( for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_OuterProduct_MissingParenRight) {
|
||||
auto* p = parser("outer_product(a, b");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:19: missing ) for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_OuterProduct_MissingFirstIdentifier) {
|
||||
auto* p = parser("outer_product(, b)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:15: missing identifier for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_OuterProduct_MissingSecondIdentifier) {
|
||||
auto* p = parser("outer_product(a, )");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:18: missing identifier for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_OuterProduct_MissingComma) {
|
||||
auto* p = parser("outer_product(a b)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:17: missing , for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_OuterProduct_InvalidFirstIdentifier) {
|
||||
auto* p = parser("outer_product(123, b)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:15: missing identifier for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_OuterProduct_InvalidSecondIdentifier) {
|
||||
auto* p = parser("outer_product(a, 123)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:18: missing identifier for method call");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dpdx_NoModifier) {
|
||||
auto* p = parser("dpdx(a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsUnaryDerivative());
|
||||
|
||||
auto* deriv = e->AsUnaryDerivative();
|
||||
EXPECT_EQ(deriv->op(), ast::UnaryDerivative::kDpdx);
|
||||
EXPECT_EQ(deriv->modifier(), ast::DerivativeModifier::kNone);
|
||||
|
||||
ASSERT_NE(deriv->param(), nullptr);
|
||||
ASSERT_TRUE(deriv->param()->IsIdentifier());
|
||||
auto* ident = deriv->param()->AsIdentifier();
|
||||
EXPECT_EQ(ident->name(), "a");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dpdx_WithModifier) {
|
||||
auto* p = parser("dpdx<coarse>(a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsUnaryDerivative());
|
||||
|
||||
auto* deriv = e->AsUnaryDerivative();
|
||||
EXPECT_EQ(deriv->op(), ast::UnaryDerivative::kDpdx);
|
||||
EXPECT_EQ(deriv->modifier(), ast::DerivativeModifier::kCoarse);
|
||||
|
||||
ASSERT_NE(deriv->param(), nullptr);
|
||||
ASSERT_TRUE(deriv->param()->IsIdentifier());
|
||||
auto* ident = deriv->param()->AsIdentifier();
|
||||
EXPECT_EQ(ident->name(), "a");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dpdx_MissingLessThan) {
|
||||
auto* p = parser("dpdx coarse>(a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:6: missing ( for derivative method");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dpdx_InvalidModifier) {
|
||||
auto* p = parser("dpdx<invalid>(a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:6: unable to parse derivative modifier");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dpdx_EmptyModifer) {
|
||||
auto* p = parser("dpdx coarse>(a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:6: missing ( for derivative method");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dpdx_MissingGreaterThan) {
|
||||
auto* p = parser("dpdx<coarse (a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:13: missing > for derivative modifier");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dpdx_MisisngLeftParen) {
|
||||
auto* p = parser("dpdx<coarse>a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:13: missing ( for derivative method");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dpdx_MissingRightParen) {
|
||||
auto* p = parser("dpdx<coarse>(a");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:15: missing ) for derivative method");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dpdx_MissingIdentifier) {
|
||||
auto* p = parser("dpdx<coarse>()");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:14: missing identifier for derivative method");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dpdx_InvalidIdentifeir) {
|
||||
auto* p = parser("dpdx<coarse>(12345)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:14: missing identifier for derivative method");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dpdy_NoModifier) {
|
||||
auto* p = parser("dpdy(a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsUnaryDerivative());
|
||||
|
||||
auto* deriv = e->AsUnaryDerivative();
|
||||
EXPECT_EQ(deriv->op(), ast::UnaryDerivative::kDpdy);
|
||||
EXPECT_EQ(deriv->modifier(), ast::DerivativeModifier::kNone);
|
||||
|
||||
ASSERT_NE(deriv->param(), nullptr);
|
||||
ASSERT_TRUE(deriv->param()->IsIdentifier());
|
||||
auto* ident = deriv->param()->AsIdentifier();
|
||||
EXPECT_EQ(ident->name(), "a");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dpdy_WithModifier) {
|
||||
auto* p = parser("dpdy<fine>(a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsUnaryDerivative());
|
||||
|
||||
auto* deriv = e->AsUnaryDerivative();
|
||||
EXPECT_EQ(deriv->op(), ast::UnaryDerivative::kDpdy);
|
||||
EXPECT_EQ(deriv->modifier(), ast::DerivativeModifier::kFine);
|
||||
|
||||
ASSERT_NE(deriv->param(), nullptr);
|
||||
ASSERT_TRUE(deriv->param()->IsIdentifier());
|
||||
auto* ident = deriv->param()->AsIdentifier();
|
||||
EXPECT_EQ(ident->name(), "a");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dpdy_MissingLessThan) {
|
||||
auto* p = parser("dpdy coarse>(a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:6: missing ( for derivative method");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dpdy_InvalidModifier) {
|
||||
auto* p = parser("dpdy<invalid>(a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:6: unable to parse derivative modifier");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dpdy_EmptyModifer) {
|
||||
auto* p = parser("dpdy coarse>(a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:6: missing ( for derivative method");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dpdy_MissingGreaterThan) {
|
||||
auto* p = parser("dpdy<coarse (a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:13: missing > for derivative modifier");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dpdy_MisisngLeftParen) {
|
||||
auto* p = parser("dpdy<coarse>a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:13: missing ( for derivative method");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dpdy_MissingRightParen) {
|
||||
auto* p = parser("dpdy<coarse>(a");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:15: missing ) for derivative method");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dpdy_MissingIdentifier) {
|
||||
auto* p = parser("dpdy<coarse>()");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:14: missing identifier for derivative method");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Dpdy_InvalidIdentifeir) {
|
||||
auto* p = parser("dpdy<coarse>(12345)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:14: missing identifier for derivative method");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Fwidth_NoModifier) {
|
||||
auto* p = parser("fwidth(a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsUnaryDerivative());
|
||||
|
||||
auto* deriv = e->AsUnaryDerivative();
|
||||
EXPECT_EQ(deriv->op(), ast::UnaryDerivative::kFwidth);
|
||||
EXPECT_EQ(deriv->modifier(), ast::DerivativeModifier::kNone);
|
||||
|
||||
ASSERT_NE(deriv->param(), nullptr);
|
||||
ASSERT_TRUE(deriv->param()->IsIdentifier());
|
||||
auto* ident = deriv->param()->AsIdentifier();
|
||||
EXPECT_EQ(ident->name(), "a");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Fwidth_WithModifier) {
|
||||
auto* p = parser("fwidth<coarse>(a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_FALSE(p->has_error()) << p->error();
|
||||
ASSERT_NE(e, nullptr);
|
||||
ASSERT_TRUE(e->IsUnaryDerivative());
|
||||
|
||||
auto* deriv = e->AsUnaryDerivative();
|
||||
EXPECT_EQ(deriv->op(), ast::UnaryDerivative::kFwidth);
|
||||
EXPECT_EQ(deriv->modifier(), ast::DerivativeModifier::kCoarse);
|
||||
|
||||
ASSERT_NE(deriv->param(), nullptr);
|
||||
ASSERT_TRUE(deriv->param()->IsIdentifier());
|
||||
auto* ident = deriv->param()->AsIdentifier();
|
||||
EXPECT_EQ(ident->name(), "a");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Fwidth_MissingLessThan) {
|
||||
auto* p = parser("fwidth coarse>(a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:8: missing ( for derivative method");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Fwidth_InvalidModifier) {
|
||||
auto* p = parser("fwidth<invalid>(a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:8: unable to parse derivative modifier");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Fwidth_EmptyModifer) {
|
||||
auto* p = parser("fwidth coarse>(a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:8: missing ( for derivative method");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Fwidth_MissingGreaterThan) {
|
||||
auto* p = parser("fwidth<coarse (a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:15: missing > for derivative modifier");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Fwidth_MisisngLeftParen) {
|
||||
auto* p = parser("fwidth<coarse>a)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:15: missing ( for derivative method");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Fwidth_MissingRightParen) {
|
||||
auto* p = parser("fwidth<coarse>(a");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:17: missing ) for derivative method");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Fwidth_MissingIdentifier) {
|
||||
auto* p = parser("fwidth<coarse>()");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:16: missing identifier for derivative method");
|
||||
}
|
||||
|
||||
TEST_F(ParserImplTest, UnaryExpression_Fwidht_InvalidIdentifeir) {
|
||||
auto* p = parser("fwidth<coarse>(12345)");
|
||||
auto e = p->unary_expression();
|
||||
ASSERT_TRUE(p->has_error());
|
||||
ASSERT_EQ(e, nullptr);
|
||||
EXPECT_EQ(p->error(), "1:16: missing identifier for derivative method");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace wgsl
|
||||
} // namespace reader
|
||||
|
|
|
@ -116,7 +116,6 @@ TEST_F(ParserImplTest, VariableDecoration_Builtin_MissingValue) {
|
|||
EXPECT_EQ(p->error(), "1:8: expected identifier for builtin");
|
||||
}
|
||||
|
||||
|
||||
TEST_F(ParserImplTest, VariableDecoration_Builtin_InvalidValue) {
|
||||
auto* p = parser("builtin other_thingy");
|
||||
auto deco = p->variable_decoration();
|
||||
|
|
|
@ -105,10 +105,6 @@ std::string Token::TypeToName(Type type) {
|
|||
case Token::Type::kXor:
|
||||
return "^";
|
||||
|
||||
case Token::Type::kAll:
|
||||
return "all";
|
||||
case Token::Type::kAny:
|
||||
return "any";
|
||||
case Token::Type::kArray:
|
||||
return "array";
|
||||
case Token::Type::kAs:
|
||||
|
@ -135,16 +131,8 @@ std::string Token::TypeToName(Type type) {
|
|||
return "continue";
|
||||
case Token::Type::kContinuing:
|
||||
return "continuing";
|
||||
case Token::Type::kCoarse:
|
||||
return "coarse";
|
||||
case Token::Type::kDefault:
|
||||
return "default";
|
||||
case Token::Type::kDot:
|
||||
return "dot";
|
||||
case Token::Type::kDpdx:
|
||||
return "dpdx";
|
||||
case Token::Type::kDpdy:
|
||||
return "dpdy";
|
||||
case Token::Type::kElse:
|
||||
return "else";
|
||||
case Token::Type::kElseIf:
|
||||
|
@ -157,16 +145,12 @@ std::string Token::TypeToName(Type type) {
|
|||
return "fallthrough";
|
||||
case Token::Type::kFalse:
|
||||
return "false";
|
||||
case Token::Type::kFine:
|
||||
return "fine";
|
||||
case Token::Type::kFn:
|
||||
return "fn";
|
||||
case Token::Type::kFragment:
|
||||
return "fragment";
|
||||
case Token::Type::kFunction:
|
||||
return "function";
|
||||
case Token::Type::kFwidth:
|
||||
return "fwidth";
|
||||
case Token::Type::kI32:
|
||||
return "i32";
|
||||
case Token::Type::kIf:
|
||||
|
@ -177,14 +161,6 @@ std::string Token::TypeToName(Type type) {
|
|||
return "import";
|
||||
case Token::Type::kIn:
|
||||
return "in";
|
||||
case Token::Type::kIsNan:
|
||||
return "is_nan";
|
||||
case Token::Type::kIsInf:
|
||||
return "is_inf";
|
||||
case Token::Type::kIsFinite:
|
||||
return "is_finite";
|
||||
case Token::Type::kIsNormal:
|
||||
return "is_normal";
|
||||
case Token::Type::kKill:
|
||||
return "kill";
|
||||
case Token::Type::kLocation:
|
||||
|
@ -213,8 +189,6 @@ std::string Token::TypeToName(Type type) {
|
|||
return "offset";
|
||||
case Token::Type::kOut:
|
||||
return "out";
|
||||
case Token::Type::kOuterProduct:
|
||||
return "outer_product";
|
||||
case Token::Type::kPremerge:
|
||||
return "premerge";
|
||||
case Token::Type::kPrivate:
|
||||
|
|
|
@ -116,10 +116,6 @@ class Token {
|
|||
/// A '^'
|
||||
kXor,
|
||||
|
||||
/// A 'all'
|
||||
kAll,
|
||||
/// A 'any'
|
||||
kAny,
|
||||
/// A 'array'
|
||||
kArray,
|
||||
/// A 'as'
|
||||
|
@ -146,16 +142,8 @@ class Token {
|
|||
kContinue,
|
||||
/// A 'continuing'
|
||||
kContinuing,
|
||||
/// A 'coarse'
|
||||
kCoarse,
|
||||
/// A 'default'
|
||||
kDefault,
|
||||
/// A 'dot'
|
||||
kDot,
|
||||
/// A 'dpdx'
|
||||
kDpdx,
|
||||
/// A 'dpdy'
|
||||
kDpdy,
|
||||
/// A 'else'
|
||||
kElse,
|
||||
/// A 'elseif'
|
||||
|
@ -168,16 +156,12 @@ class Token {
|
|||
kFallthrough,
|
||||
/// A 'false'
|
||||
kFalse,
|
||||
/// A 'fine'
|
||||
kFine,
|
||||
/// A 'fn'
|
||||
kFn,
|
||||
/// A 'fragment'
|
||||
kFragment,
|
||||
/// A 'function'
|
||||
kFunction,
|
||||
/// A 'fwidth'
|
||||
kFwidth,
|
||||
/// A 'i32'
|
||||
kI32,
|
||||
/// A 'if'
|
||||
|
@ -188,14 +172,6 @@ class Token {
|
|||
kImport,
|
||||
/// A 'in'
|
||||
kIn,
|
||||
/// A 'is_nan'
|
||||
kIsNan,
|
||||
/// A 'is_inf'
|
||||
kIsInf,
|
||||
/// A 'is_finite'
|
||||
kIsFinite,
|
||||
/// A 'is_normal'
|
||||
kIsNormal,
|
||||
/// A 'kill'
|
||||
kKill,
|
||||
/// A 'location'
|
||||
|
@ -224,8 +200,6 @@ class Token {
|
|||
kOffset,
|
||||
/// A 'out'
|
||||
kOut,
|
||||
/// A 'outer_product'
|
||||
kOuterProduct,
|
||||
/// A 'premerge'
|
||||
kPremerge,
|
||||
/// A 'private'
|
||||
|
@ -401,10 +375,6 @@ class Token {
|
|||
/// @returns true if token is a '^'
|
||||
bool IsXor() const { return type_ == Type::kXor; }
|
||||
|
||||
/// @returns true if token is a 'all'
|
||||
bool IsAll() const { return type_ == Type::kAll; }
|
||||
/// @returns true if token is a 'any'
|
||||
bool IsAny() const { return type_ == Type::kAny; }
|
||||
/// @returns true if token is a 'array'
|
||||
bool IsArray() const { return type_ == Type::kArray; }
|
||||
/// @returns true if token is a 'as'
|
||||
|
@ -423,8 +393,6 @@ class Token {
|
|||
bool IsCase() const { return type_ == Type::kCase; }
|
||||
/// @returns true if token is a 'cast'
|
||||
bool IsCast() const { return type_ == Type::kCast; }
|
||||
/// @returns true if token is 'coarse'
|
||||
bool IsCoarse() const { return type_ == Type::kCoarse; }
|
||||
/// @returns true if token is a 'compute'
|
||||
bool IsCompute() const { return type_ == Type::kCompute; }
|
||||
/// @returns true if token is a 'const'
|
||||
|
@ -435,12 +403,6 @@ class Token {
|
|||
bool IsContinuing() const { return type_ == Type::kContinuing; }
|
||||
/// @returns true if token is a 'default'
|
||||
bool IsDefault() const { return type_ == Type::kDefault; }
|
||||
/// @returns true if token is a 'dot'
|
||||
bool IsDot() const { return type_ == Type::kDot; }
|
||||
/// @returns true if token is a 'dpdx'
|
||||
bool IsDpdx() const { return type_ == Type::kDpdx; }
|
||||
/// @returns true if token is a 'dpdy'
|
||||
bool IsDpdy() const { return type_ == Type::kDpdy; }
|
||||
/// @returns true if token is a 'else'
|
||||
bool IsElse() const { return type_ == Type::kElse; }
|
||||
/// @returns true if token is a 'elseif'
|
||||
|
@ -453,16 +415,12 @@ class Token {
|
|||
bool IsFallthrough() const { return type_ == Type::kFallthrough; }
|
||||
/// @returns true if token is a 'false'
|
||||
bool IsFalse() const { return type_ == Type::kFalse; }
|
||||
/// @returns true if token is a 'fine'
|
||||
bool IsFine() const { return type_ == Type::kFine; }
|
||||
/// @returns true if token is a 'fn'
|
||||
bool IsFn() const { return type_ == Type::kFn; }
|
||||
/// @returns true if token is a 'fragment'
|
||||
bool IsFragment() const { return type_ == Type::kFragment; }
|
||||
/// @returns true if token is a 'function'
|
||||
bool IsFunction() const { return type_ == Type::kFunction; }
|
||||
/// @returns true if token is a 'fwidth'
|
||||
bool IsFwidth() const { return type_ == Type::kFwidth; }
|
||||
/// @returns true if token is a 'i32'
|
||||
bool IsI32() const { return type_ == Type::kI32; }
|
||||
/// @returns true if token is a 'if'
|
||||
|
@ -473,14 +431,6 @@ class Token {
|
|||
bool IsImport() const { return type_ == Type::kImport; }
|
||||
/// @returns true if token is a 'in'
|
||||
bool IsIn() const { return type_ == Type::kIn; }
|
||||
/// @returns true if token is a 'is_nan'
|
||||
bool IsIsNan() const { return type_ == Type::kIsNan; }
|
||||
/// @returns true if token is a 'is_inf'
|
||||
bool IsIsInf() const { return type_ == Type::kIsInf; }
|
||||
/// @returns true if token is a 'is_finite'
|
||||
bool IsIsFinite() const { return type_ == Type::kIsFinite; }
|
||||
/// @returns true if token is a 'is_normal'
|
||||
bool IsIsNormal() const { return type_ == Type::kIsNormal; }
|
||||
/// @returns true if token is a 'kill'
|
||||
bool IsKill() const { return type_ == Type::kKill; }
|
||||
/// @returns true if token is a 'location'
|
||||
|
@ -509,8 +459,6 @@ class Token {
|
|||
bool IsOffset() const { return type_ == Type::kOffset; }
|
||||
/// @returns true if token is a 'out'
|
||||
bool IsOut() const { return type_ == Type::kOut; }
|
||||
/// @returns true if token is a 'outer_product'
|
||||
bool IsOuterProduct() const { return type_ == Type::kOuterProduct; }
|
||||
/// @returns true if token is a 'private'
|
||||
bool IsPrivate() const { return type_ == Type::kPrivate; }
|
||||
/// @returns true if token is a 'ptr'
|
||||
|
|
|
@ -42,13 +42,30 @@
|
|||
#include "src/ast/type/struct_type.h"
|
||||
#include "src/ast/type/vector_type.h"
|
||||
#include "src/ast/type_constructor_expression.h"
|
||||
#include "src/ast/unary_derivative_expression.h"
|
||||
#include "src/ast/unary_method_expression.h"
|
||||
#include "src/ast/unary_op_expression.h"
|
||||
#include "src/ast/unless_statement.h"
|
||||
#include "src/ast/variable_decl_statement.h"
|
||||
|
||||
namespace tint {
|
||||
namespace {
|
||||
|
||||
bool IsDerivative(const std::string& name) {
|
||||
return name == "dpdx" || name == "dpdx_fine" || name == "dpdx_coarse" ||
|
||||
name == "dpdy" || name == "dpdy_fine" || name == "dpdy_coarse" ||
|
||||
name == "fwidth" || name == "fwidth_fine" || name == "fwidth_coarse";
|
||||
}
|
||||
|
||||
bool IsFloatIntrinsic(const std::string& name) {
|
||||
return name == "is_finite" || name == "is_inf" || name == "is_nan" ||
|
||||
name == "is_normal";
|
||||
}
|
||||
|
||||
bool IsIntrinsic(const std::string& name) {
|
||||
return IsDerivative(name) || name == "all" || name == "any" ||
|
||||
IsFloatIntrinsic(name) || name == "dot" || name == "outer_product";
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TypeDeterminer::TypeDeterminer(Context* ctx, ast::Module* mod)
|
||||
: ctx_(*ctx), mod_(mod) {}
|
||||
|
@ -253,12 +270,6 @@ bool TypeDeterminer::DetermineResultType(ast::Expression* expr) {
|
|||
if (expr->IsMemberAccessor()) {
|
||||
return DetermineMemberAccessor(expr->AsMemberAccessor());
|
||||
}
|
||||
if (expr->IsUnaryDerivative()) {
|
||||
return DetermineUnaryDerivative(expr->AsUnaryDerivative());
|
||||
}
|
||||
if (expr->IsUnaryMethod()) {
|
||||
return DetermineUnaryMethod(expr->AsUnaryMethod());
|
||||
}
|
||||
if (expr->IsUnaryOp()) {
|
||||
return DetermineUnaryOp(expr->AsUnaryOp());
|
||||
}
|
||||
|
@ -318,7 +329,11 @@ bool TypeDeterminer::DetermineCall(ast::CallExpression* expr) {
|
|||
if (expr->func()->IsIdentifier()) {
|
||||
auto* ident = expr->func()->AsIdentifier();
|
||||
|
||||
if (ident->has_path()) {
|
||||
if (IsIntrinsic(ident->name())) {
|
||||
if (!DetermineIntrinsic(ident->name(), expr))
|
||||
return false;
|
||||
|
||||
} else if (ident->has_path()) {
|
||||
auto* imp = mod_->FindImportByName(ident->path());
|
||||
if (imp == nullptr) {
|
||||
set_error(expr->source(), "Unable to find import for " + ident->name());
|
||||
|
@ -355,6 +370,75 @@ bool TypeDeterminer::DetermineCall(ast::CallExpression* expr) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool TypeDeterminer::DetermineIntrinsic(const std::string& name,
|
||||
ast::CallExpression* expr) {
|
||||
if (IsDerivative(name)) {
|
||||
if (expr->params().size() != 1) {
|
||||
set_error(expr->source(), "incorrect number of parameters for " + name);
|
||||
return false;
|
||||
}
|
||||
|
||||
// The result type must be the same as the type of the parameter.
|
||||
auto& param = expr->params()[0];
|
||||
if (!DetermineResultType(param.get())) {
|
||||
return false;
|
||||
}
|
||||
expr->func()->set_result_type(param->result_type()->UnwrapPtrIfNeeded());
|
||||
return true;
|
||||
}
|
||||
if (name == "any" || name == "all") {
|
||||
expr->func()->set_result_type(
|
||||
ctx_.type_mgr().Get(std::make_unique<ast::type::BoolType>()));
|
||||
return true;
|
||||
}
|
||||
if (IsFloatIntrinsic(name)) {
|
||||
if (expr->params().size() != 1) {
|
||||
set_error(expr->source(), "incorrect number of parameters for " + name);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto* bool_type =
|
||||
ctx_.type_mgr().Get(std::make_unique<ast::type::BoolType>());
|
||||
|
||||
auto* param_type = expr->params()[0]->result_type()->UnwrapPtrIfNeeded();
|
||||
if (param_type->IsVector()) {
|
||||
expr->func()->set_result_type(
|
||||
ctx_.type_mgr().Get(std::make_unique<ast::type::VectorType>(
|
||||
bool_type, param_type->AsVector()->size())));
|
||||
} else {
|
||||
expr->func()->set_result_type(bool_type);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (name == "dot") {
|
||||
expr->func()->set_result_type(
|
||||
ctx_.type_mgr().Get(std::make_unique<ast::type::F32Type>()));
|
||||
return true;
|
||||
}
|
||||
if (name == "outer_product") {
|
||||
if (expr->params().size() != 2) {
|
||||
set_error(expr->source(),
|
||||
"incorrect number of parameters for outer_product");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto* param0_type = expr->params()[0]->result_type()->UnwrapPtrIfNeeded();
|
||||
auto* param1_type = expr->params()[1]->result_type()->UnwrapPtrIfNeeded();
|
||||
if (!param0_type->IsVector() || !param1_type->IsVector()) {
|
||||
set_error(expr->source(), "invalid parameter type for outer_product");
|
||||
return false;
|
||||
}
|
||||
|
||||
expr->func()->set_result_type(
|
||||
ctx_.type_mgr().Get(std::make_unique<ast::type::MatrixType>(
|
||||
ctx_.type_mgr().Get(std::make_unique<ast::type::F32Type>()),
|
||||
param0_type->AsVector()->size(), param1_type->AsVector()->size())));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TypeDeterminer::DetermineCast(ast::CastExpression* expr) {
|
||||
if (!DetermineResultType(expr->expr())) {
|
||||
return false;
|
||||
|
@ -550,77 +634,6 @@ bool TypeDeterminer::DetermineBinary(ast::BinaryExpression* expr) {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool TypeDeterminer::DetermineUnaryDerivative(
|
||||
ast::UnaryDerivativeExpression* expr) {
|
||||
// The result type must be the same as the type of the parameter.
|
||||
if (!DetermineResultType(expr->param())) {
|
||||
return false;
|
||||
}
|
||||
expr->set_result_type(expr->param()->result_type()->UnwrapPtrIfNeeded());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TypeDeterminer::DetermineUnaryMethod(ast::UnaryMethodExpression* expr) {
|
||||
if (!DetermineResultType(expr->params())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (expr->op()) {
|
||||
case ast::UnaryMethod::kAny:
|
||||
case ast::UnaryMethod::kAll: {
|
||||
expr->set_result_type(
|
||||
ctx_.type_mgr().Get(std::make_unique<ast::type::BoolType>()));
|
||||
break;
|
||||
}
|
||||
case ast::UnaryMethod::kIsNan:
|
||||
case ast::UnaryMethod::kIsInf:
|
||||
case ast::UnaryMethod::kIsFinite:
|
||||
case ast::UnaryMethod::kIsNormal: {
|
||||
if (expr->params().empty()) {
|
||||
set_error(expr->source(), "incorrect number of parameters");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto* bool_type =
|
||||
ctx_.type_mgr().Get(std::make_unique<ast::type::BoolType>());
|
||||
auto* param_type = expr->params()[0]->result_type()->UnwrapPtrIfNeeded();
|
||||
if (param_type->IsVector()) {
|
||||
expr->set_result_type(
|
||||
ctx_.type_mgr().Get(std::make_unique<ast::type::VectorType>(
|
||||
bool_type, param_type->AsVector()->size())));
|
||||
} else {
|
||||
expr->set_result_type(bool_type);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ast::UnaryMethod::kDot: {
|
||||
expr->set_result_type(
|
||||
ctx_.type_mgr().Get(std::make_unique<ast::type::F32Type>()));
|
||||
break;
|
||||
}
|
||||
case ast::UnaryMethod::kOuterProduct: {
|
||||
if (expr->params().size() != 2) {
|
||||
set_error(expr->source(),
|
||||
"incorrect number of parameters for outer product");
|
||||
return false;
|
||||
}
|
||||
auto* param0_type = expr->params()[0]->result_type()->UnwrapPtrIfNeeded();
|
||||
auto* param1_type = expr->params()[1]->result_type()->UnwrapPtrIfNeeded();
|
||||
if (!param0_type->IsVector() || !param1_type->IsVector()) {
|
||||
set_error(expr->source(), "invalid parameter type for outer product");
|
||||
return false;
|
||||
}
|
||||
expr->set_result_type(
|
||||
ctx_.type_mgr().Get(std::make_unique<ast::type::MatrixType>(
|
||||
ctx_.type_mgr().Get(std::make_unique<ast::type::F32Type>()),
|
||||
param0_type->AsVector()->size(),
|
||||
param1_type->AsVector()->size())));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TypeDeterminer::DetermineUnaryOp(ast::UnaryOpExpression* expr) {
|
||||
// Result type matches the parameter type.
|
||||
if (!DetermineResultType(expr->expr())) {
|
||||
|
|
|
@ -34,8 +34,6 @@ class ConstructorExpression;
|
|||
class Function;
|
||||
class IdentifierExpression;
|
||||
class MemberAccessorExpression;
|
||||
class UnaryDerivativeExpression;
|
||||
class UnaryMethodExpression;
|
||||
class UnaryOpExpression;
|
||||
class Variable;
|
||||
|
||||
|
@ -114,9 +112,8 @@ class TypeDeterminer {
|
|||
bool DetermineCast(ast::CastExpression* expr);
|
||||
bool DetermineConstructor(ast::ConstructorExpression* expr);
|
||||
bool DetermineIdentifier(ast::IdentifierExpression* expr);
|
||||
bool DetermineIntrinsic(const std::string& name, ast::CallExpression* expr);
|
||||
bool DetermineMemberAccessor(ast::MemberAccessorExpression* expr);
|
||||
bool DetermineUnaryDerivative(ast::UnaryDerivativeExpression* expr);
|
||||
bool DetermineUnaryMethod(ast::UnaryMethodExpression* expr);
|
||||
bool DetermineUnaryOp(ast::UnaryOpExpression* expr);
|
||||
|
||||
Context& ctx_;
|
||||
|
|
|
@ -51,8 +51,6 @@
|
|||
#include "src/ast/type/struct_type.h"
|
||||
#include "src/ast/type/vector_type.h"
|
||||
#include "src/ast/type_constructor_expression.h"
|
||||
#include "src/ast/unary_derivative_expression.h"
|
||||
#include "src/ast/unary_method_expression.h"
|
||||
#include "src/ast/unary_op_expression.h"
|
||||
#include "src/ast/unless_statement.h"
|
||||
#include "src/ast/variable_decl_statement.h"
|
||||
|
@ -1369,13 +1367,34 @@ TEST_F(TypeDeterminerTest, Expr_Binary_Multiply_Matrix_Matrix) {
|
|||
EXPECT_EQ(mat->columns(), 4u);
|
||||
}
|
||||
|
||||
using UnaryDerivativeExpressionTest =
|
||||
TypeDeterminerTestWithParam<ast::UnaryDerivative>;
|
||||
TEST_P(UnaryDerivativeExpressionTest, Expr_UnaryDerivative) {
|
||||
auto derivative = GetParam();
|
||||
using IntrinsicDerivativeTest = TypeDeterminerTestWithParam<std::string>;
|
||||
TEST_P(IntrinsicDerivativeTest, Scalar) {
|
||||
auto name = GetParam();
|
||||
|
||||
ast::type::F32Type f32;
|
||||
|
||||
auto var =
|
||||
std::make_unique<ast::Variable>("ident", ast::StorageClass::kNone, &f32);
|
||||
mod()->AddGlobalVariable(std::move(var));
|
||||
|
||||
// Register the global
|
||||
EXPECT_TRUE(td()->Determine());
|
||||
|
||||
ast::ExpressionList call_params;
|
||||
call_params.push_back(std::make_unique<ast::IdentifierExpression>("ident"));
|
||||
|
||||
ast::CallExpression expr(std::make_unique<ast::IdentifierExpression>(name),
|
||||
std::move(call_params));
|
||||
EXPECT_TRUE(td()->DetermineResultType(&expr));
|
||||
|
||||
ASSERT_NE(expr.result_type(), nullptr);
|
||||
ASSERT_TRUE(expr.result_type()->IsF32());
|
||||
}
|
||||
|
||||
TEST_P(IntrinsicDerivativeTest, Vector) {
|
||||
auto name = GetParam();
|
||||
|
||||
ast::type::F32Type f32;
|
||||
ast::type::VectorType vec4(&f32, 4);
|
||||
|
||||
auto var =
|
||||
|
@ -1385,25 +1404,75 @@ TEST_P(UnaryDerivativeExpressionTest, Expr_UnaryDerivative) {
|
|||
// Register the global
|
||||
EXPECT_TRUE(td()->Determine());
|
||||
|
||||
ast::UnaryDerivativeExpression der(
|
||||
derivative, ast::DerivativeModifier::kNone,
|
||||
std::make_unique<ast::IdentifierExpression>("ident"));
|
||||
EXPECT_TRUE(td()->DetermineResultType(&der));
|
||||
ASSERT_NE(der.result_type(), nullptr);
|
||||
ASSERT_TRUE(der.result_type()->IsVector());
|
||||
EXPECT_TRUE(der.result_type()->AsVector()->type()->IsF32());
|
||||
EXPECT_EQ(der.result_type()->AsVector()->size(), 4u);
|
||||
ast::ExpressionList call_params;
|
||||
call_params.push_back(std::make_unique<ast::IdentifierExpression>("ident"));
|
||||
|
||||
ast::CallExpression expr(std::make_unique<ast::IdentifierExpression>(name),
|
||||
std::move(call_params));
|
||||
EXPECT_TRUE(td()->DetermineResultType(&expr));
|
||||
|
||||
ASSERT_NE(expr.result_type(), nullptr);
|
||||
ASSERT_TRUE(expr.result_type()->IsVector());
|
||||
EXPECT_TRUE(expr.result_type()->AsVector()->type()->IsF32());
|
||||
EXPECT_EQ(expr.result_type()->AsVector()->size(), 4u);
|
||||
}
|
||||
|
||||
TEST_P(IntrinsicDerivativeTest, MissingParam) {
|
||||
auto name = GetParam();
|
||||
|
||||
ast::type::F32Type f32;
|
||||
ast::type::VectorType vec4(&f32, 4);
|
||||
|
||||
// Register the global
|
||||
EXPECT_TRUE(td()->Determine());
|
||||
|
||||
ast::ExpressionList call_params;
|
||||
ast::CallExpression expr(std::make_unique<ast::IdentifierExpression>(name),
|
||||
std::move(call_params));
|
||||
EXPECT_FALSE(td()->DetermineResultType(&expr));
|
||||
EXPECT_EQ(td()->error(), "incorrect number of parameters for " + name);
|
||||
}
|
||||
|
||||
TEST_P(IntrinsicDerivativeTest, ToomManyParams) {
|
||||
auto name = GetParam();
|
||||
|
||||
ast::type::F32Type f32;
|
||||
ast::type::VectorType vec4(&f32, 4);
|
||||
|
||||
auto var1 = std::make_unique<ast::Variable>("ident1",
|
||||
ast::StorageClass::kNone, &vec4);
|
||||
auto var2 = std::make_unique<ast::Variable>("ident2",
|
||||
ast::StorageClass::kNone, &vec4);
|
||||
mod()->AddGlobalVariable(std::move(var1));
|
||||
mod()->AddGlobalVariable(std::move(var2));
|
||||
|
||||
// Register the global
|
||||
EXPECT_TRUE(td()->Determine());
|
||||
|
||||
ast::ExpressionList call_params;
|
||||
call_params.push_back(std::make_unique<ast::IdentifierExpression>("ident1"));
|
||||
call_params.push_back(std::make_unique<ast::IdentifierExpression>("ident2"));
|
||||
|
||||
ast::CallExpression expr(std::make_unique<ast::IdentifierExpression>(name),
|
||||
std::move(call_params));
|
||||
EXPECT_FALSE(td()->DetermineResultType(&expr));
|
||||
EXPECT_EQ(td()->error(), "incorrect number of parameters for " + name);
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(TypeDeterminerTest,
|
||||
UnaryDerivativeExpressionTest,
|
||||
testing::Values(ast::UnaryDerivative::kDpdx,
|
||||
ast::UnaryDerivative::kDpdy,
|
||||
ast::UnaryDerivative::kFwidth));
|
||||
IntrinsicDerivativeTest,
|
||||
testing::Values("dpdx",
|
||||
"dpdx_coarse",
|
||||
"dpdx_fine",
|
||||
"dpdy",
|
||||
"dpdy_coarse",
|
||||
"dpdy_fine",
|
||||
"fwidth",
|
||||
"fwidth_coarse",
|
||||
"fwidth_fine"));
|
||||
|
||||
using UnaryMethodExpressionBoolTest =
|
||||
TypeDeterminerTestWithParam<ast::UnaryMethod>;
|
||||
TEST_P(UnaryMethodExpressionBoolTest, Expr_UnaryMethod_Any) {
|
||||
auto op = GetParam();
|
||||
using Intrinsic = TypeDeterminerTestWithParam<std::string>;
|
||||
TEST_P(Intrinsic, Test) {
|
||||
auto name = GetParam();
|
||||
|
||||
ast::type::BoolType bool_type;
|
||||
ast::type::VectorType vec3(&bool_type, 3);
|
||||
|
@ -1412,27 +1481,26 @@ TEST_P(UnaryMethodExpressionBoolTest, Expr_UnaryMethod_Any) {
|
|||
&vec3);
|
||||
mod()->AddGlobalVariable(std::move(var));
|
||||
|
||||
ast::ExpressionList params;
|
||||
params.push_back(std::make_unique<ast::IdentifierExpression>("my_var"));
|
||||
ast::ExpressionList call_params;
|
||||
call_params.push_back(std::make_unique<ast::IdentifierExpression>("my_var"));
|
||||
|
||||
ast::UnaryMethodExpression exp(op, std::move(params));
|
||||
ast::CallExpression expr(std::make_unique<ast::IdentifierExpression>(name),
|
||||
std::move(call_params));
|
||||
|
||||
// Register the variable
|
||||
EXPECT_TRUE(td()->Determine());
|
||||
|
||||
EXPECT_TRUE(td()->DetermineResultType(&exp));
|
||||
ASSERT_NE(exp.result_type(), nullptr);
|
||||
EXPECT_TRUE(exp.result_type()->IsBool());
|
||||
EXPECT_TRUE(td()->DetermineResultType(&expr));
|
||||
ASSERT_NE(expr.result_type(), nullptr);
|
||||
EXPECT_TRUE(expr.result_type()->IsBool());
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(TypeDeterminerTest,
|
||||
UnaryMethodExpressionBoolTest,
|
||||
testing::Values(ast::UnaryMethod::kAny,
|
||||
ast::UnaryMethod::kAll));
|
||||
Intrinsic,
|
||||
testing::Values("any", "all"));
|
||||
|
||||
using UnaryMethodExpressionVecTest =
|
||||
TypeDeterminerTestWithParam<ast::UnaryMethod>;
|
||||
TEST_P(UnaryMethodExpressionVecTest, Expr_UnaryMethod_Bool) {
|
||||
auto op = GetParam();
|
||||
using Intrinsic_FloatMethod = TypeDeterminerTestWithParam<std::string>;
|
||||
TEST_P(Intrinsic_FloatMethod, Vector) {
|
||||
auto name = GetParam();
|
||||
|
||||
ast::type::F32Type f32;
|
||||
ast::type::VectorType vec3(&f32, 3);
|
||||
|
@ -1441,22 +1509,24 @@ TEST_P(UnaryMethodExpressionVecTest, Expr_UnaryMethod_Bool) {
|
|||
&vec3);
|
||||
mod()->AddGlobalVariable(std::move(var));
|
||||
|
||||
ast::ExpressionList params;
|
||||
params.push_back(std::make_unique<ast::IdentifierExpression>("my_var"));
|
||||
ast::ExpressionList call_params;
|
||||
call_params.push_back(std::make_unique<ast::IdentifierExpression>("my_var"));
|
||||
|
||||
ast::UnaryMethodExpression exp(op, std::move(params));
|
||||
ast::CallExpression expr(std::make_unique<ast::IdentifierExpression>(name),
|
||||
std::move(call_params));
|
||||
|
||||
// Register the variable
|
||||
EXPECT_TRUE(td()->Determine());
|
||||
EXPECT_TRUE(td()->DetermineResultType(&expr));
|
||||
|
||||
EXPECT_TRUE(td()->DetermineResultType(&exp));
|
||||
ASSERT_NE(exp.result_type(), nullptr);
|
||||
ASSERT_TRUE(exp.result_type()->IsVector());
|
||||
EXPECT_TRUE(exp.result_type()->AsVector()->type()->IsBool());
|
||||
EXPECT_EQ(exp.result_type()->AsVector()->size(), 3u);
|
||||
ASSERT_NE(expr.result_type(), nullptr);
|
||||
ASSERT_TRUE(expr.result_type()->IsVector());
|
||||
EXPECT_TRUE(expr.result_type()->AsVector()->type()->IsBool());
|
||||
EXPECT_EQ(expr.result_type()->AsVector()->size(), 3u);
|
||||
}
|
||||
TEST_P(UnaryMethodExpressionVecTest, Expr_UnaryMethod_Vec) {
|
||||
auto op = GetParam();
|
||||
|
||||
TEST_P(Intrinsic_FloatMethod, Scalar) {
|
||||
auto name = GetParam();
|
||||
|
||||
ast::type::F32Type f32;
|
||||
|
||||
|
@ -1464,26 +1534,65 @@ TEST_P(UnaryMethodExpressionVecTest, Expr_UnaryMethod_Vec) {
|
|||
std::make_unique<ast::Variable>("my_var", ast::StorageClass::kNone, &f32);
|
||||
mod()->AddGlobalVariable(std::move(var));
|
||||
|
||||
ast::ExpressionList params;
|
||||
params.push_back(std::make_unique<ast::IdentifierExpression>("my_var"));
|
||||
ast::ExpressionList call_params;
|
||||
call_params.push_back(std::make_unique<ast::IdentifierExpression>("my_var"));
|
||||
|
||||
ast::UnaryMethodExpression exp(op, std::move(params));
|
||||
ast::CallExpression expr(std::make_unique<ast::IdentifierExpression>(name),
|
||||
std::move(call_params));
|
||||
|
||||
// Register the variable
|
||||
EXPECT_TRUE(td()->Determine());
|
||||
|
||||
EXPECT_TRUE(td()->DetermineResultType(&exp));
|
||||
ASSERT_NE(exp.result_type(), nullptr);
|
||||
EXPECT_TRUE(exp.result_type()->IsBool());
|
||||
EXPECT_TRUE(td()->DetermineResultType(&expr));
|
||||
ASSERT_NE(expr.result_type(), nullptr);
|
||||
EXPECT_TRUE(expr.result_type()->IsBool());
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(TypeDeterminerTest,
|
||||
UnaryMethodExpressionVecTest,
|
||||
testing::Values(ast::UnaryMethod::kIsInf,
|
||||
ast::UnaryMethod::kIsNan,
|
||||
ast::UnaryMethod::kIsFinite,
|
||||
ast::UnaryMethod::kIsNormal));
|
||||
|
||||
TEST_F(TypeDeterminerTest, Expr_UnaryMethod_Dot) {
|
||||
TEST_P(Intrinsic_FloatMethod, MissingParam) {
|
||||
auto name = GetParam();
|
||||
|
||||
ast::type::F32Type f32;
|
||||
|
||||
auto var =
|
||||
std::make_unique<ast::Variable>("my_var", ast::StorageClass::kNone, &f32);
|
||||
mod()->AddGlobalVariable(std::move(var));
|
||||
|
||||
ast::ExpressionList call_params;
|
||||
ast::CallExpression expr(std::make_unique<ast::IdentifierExpression>(name),
|
||||
std::move(call_params));
|
||||
|
||||
// Register the variable
|
||||
EXPECT_TRUE(td()->Determine());
|
||||
EXPECT_FALSE(td()->DetermineResultType(&expr));
|
||||
EXPECT_EQ(td()->error(), "incorrect number of parameters for " + name);
|
||||
}
|
||||
|
||||
TEST_P(Intrinsic_FloatMethod, TooManyParams) {
|
||||
auto name = GetParam();
|
||||
|
||||
ast::type::F32Type f32;
|
||||
|
||||
auto var =
|
||||
std::make_unique<ast::Variable>("my_var", ast::StorageClass::kNone, &f32);
|
||||
mod()->AddGlobalVariable(std::move(var));
|
||||
|
||||
ast::ExpressionList call_params;
|
||||
call_params.push_back(std::make_unique<ast::IdentifierExpression>("my_var"));
|
||||
call_params.push_back(std::make_unique<ast::IdentifierExpression>("my_var"));
|
||||
|
||||
ast::CallExpression expr(std::make_unique<ast::IdentifierExpression>(name),
|
||||
std::move(call_params));
|
||||
|
||||
// Register the variable
|
||||
EXPECT_TRUE(td()->Determine());
|
||||
EXPECT_FALSE(td()->DetermineResultType(&expr));
|
||||
EXPECT_EQ(td()->error(), "incorrect number of parameters for " + name);
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
TypeDeterminerTest,
|
||||
Intrinsic_FloatMethod,
|
||||
testing::Values("is_inf", "is_nan", "is_finite", "is_normal"));
|
||||
|
||||
TEST_F(TypeDeterminerTest, Intrinsic_Dot) {
|
||||
ast::type::F32Type f32;
|
||||
ast::type::VectorType vec3(&f32, 3);
|
||||
|
||||
|
@ -1491,21 +1600,21 @@ TEST_F(TypeDeterminerTest, Expr_UnaryMethod_Dot) {
|
|||
&vec3);
|
||||
mod()->AddGlobalVariable(std::move(var));
|
||||
|
||||
ast::ExpressionList params;
|
||||
params.push_back(std::make_unique<ast::IdentifierExpression>("my_var"));
|
||||
params.push_back(std::make_unique<ast::IdentifierExpression>("my_var"));
|
||||
ast::ExpressionList call_params;
|
||||
call_params.push_back(std::make_unique<ast::IdentifierExpression>("my_var"));
|
||||
call_params.push_back(std::make_unique<ast::IdentifierExpression>("my_var"));
|
||||
|
||||
ast::UnaryMethodExpression exp(ast::UnaryMethod::kDot, std::move(params));
|
||||
ast::CallExpression expr(std::make_unique<ast::IdentifierExpression>("dot"),
|
||||
std::move(call_params));
|
||||
|
||||
// Register the variable
|
||||
EXPECT_TRUE(td()->Determine());
|
||||
|
||||
EXPECT_TRUE(td()->DetermineResultType(&exp));
|
||||
ASSERT_NE(exp.result_type(), nullptr);
|
||||
EXPECT_TRUE(exp.result_type()->IsF32());
|
||||
EXPECT_TRUE(td()->DetermineResultType(&expr));
|
||||
ASSERT_NE(expr.result_type(), nullptr);
|
||||
EXPECT_TRUE(expr.result_type()->IsF32());
|
||||
}
|
||||
|
||||
TEST_F(TypeDeterminerTest, Expr_UnaryMethod_OuterProduct) {
|
||||
TEST_F(TypeDeterminerTest, Intrinsic_OuterProduct) {
|
||||
ast::type::F32Type f32;
|
||||
ast::type::VectorType vec3(&f32, 3);
|
||||
ast::type::VectorType vec2(&f32, 2);
|
||||
|
@ -1517,25 +1626,73 @@ TEST_F(TypeDeterminerTest, Expr_UnaryMethod_OuterProduct) {
|
|||
mod()->AddGlobalVariable(std::move(var1));
|
||||
mod()->AddGlobalVariable(std::move(var2));
|
||||
|
||||
ast::ExpressionList params;
|
||||
params.push_back(std::make_unique<ast::IdentifierExpression>("v3"));
|
||||
params.push_back(std::make_unique<ast::IdentifierExpression>("v2"));
|
||||
ast::ExpressionList call_params;
|
||||
call_params.push_back(std::make_unique<ast::IdentifierExpression>("v3"));
|
||||
call_params.push_back(std::make_unique<ast::IdentifierExpression>("v2"));
|
||||
|
||||
ast::UnaryMethodExpression exp(ast::UnaryMethod::kOuterProduct,
|
||||
std::move(params));
|
||||
ast::CallExpression expr(
|
||||
std::make_unique<ast::IdentifierExpression>("outer_product"),
|
||||
std::move(call_params));
|
||||
|
||||
// Register the variable
|
||||
EXPECT_TRUE(td()->Determine());
|
||||
EXPECT_TRUE(td()->DetermineResultType(&expr));
|
||||
|
||||
EXPECT_TRUE(td()->DetermineResultType(&exp));
|
||||
ASSERT_NE(exp.result_type(), nullptr);
|
||||
ASSERT_TRUE(exp.result_type()->IsMatrix());
|
||||
auto* mat = exp.result_type()->AsMatrix();
|
||||
ASSERT_NE(expr.result_type(), nullptr);
|
||||
ASSERT_TRUE(expr.result_type()->IsMatrix());
|
||||
|
||||
auto* mat = expr.result_type()->AsMatrix();
|
||||
EXPECT_TRUE(mat->type()->IsF32());
|
||||
EXPECT_EQ(mat->rows(), 3u);
|
||||
EXPECT_EQ(mat->columns(), 2u);
|
||||
}
|
||||
|
||||
TEST_F(TypeDeterminerTest, Intrinsic_OuterProduct_TooFewParams) {
|
||||
ast::type::F32Type f32;
|
||||
ast::type::VectorType vec3(&f32, 3);
|
||||
ast::type::VectorType vec2(&f32, 2);
|
||||
|
||||
auto var2 =
|
||||
std::make_unique<ast::Variable>("v2", ast::StorageClass::kNone, &vec2);
|
||||
mod()->AddGlobalVariable(std::move(var2));
|
||||
|
||||
ast::ExpressionList call_params;
|
||||
call_params.push_back(std::make_unique<ast::IdentifierExpression>("v2"));
|
||||
|
||||
ast::CallExpression expr(
|
||||
std::make_unique<ast::IdentifierExpression>("outer_product"),
|
||||
std::move(call_params));
|
||||
|
||||
// Register the variable
|
||||
EXPECT_TRUE(td()->Determine());
|
||||
EXPECT_FALSE(td()->DetermineResultType(&expr));
|
||||
EXPECT_EQ(td()->error(), "incorrect number of parameters for outer_product");
|
||||
}
|
||||
|
||||
TEST_F(TypeDeterminerTest, Intrinsic_OuterProduct_TooManyParams) {
|
||||
ast::type::F32Type f32;
|
||||
ast::type::VectorType vec3(&f32, 3);
|
||||
ast::type::VectorType vec2(&f32, 2);
|
||||
|
||||
auto var2 =
|
||||
std::make_unique<ast::Variable>("v2", ast::StorageClass::kNone, &vec2);
|
||||
mod()->AddGlobalVariable(std::move(var2));
|
||||
|
||||
ast::ExpressionList call_params;
|
||||
call_params.push_back(std::make_unique<ast::IdentifierExpression>("v2"));
|
||||
call_params.push_back(std::make_unique<ast::IdentifierExpression>("v2"));
|
||||
call_params.push_back(std::make_unique<ast::IdentifierExpression>("v2"));
|
||||
|
||||
ast::CallExpression expr(
|
||||
std::make_unique<ast::IdentifierExpression>("outer_product"),
|
||||
std::move(call_params));
|
||||
|
||||
// Register the variable
|
||||
EXPECT_TRUE(td()->Determine());
|
||||
EXPECT_FALSE(td()->DetermineResultType(&expr));
|
||||
EXPECT_EQ(td()->error(), "incorrect number of parameters for outer_product");
|
||||
}
|
||||
|
||||
using UnaryOpExpressionTest = TypeDeterminerTestWithParam<ast::UnaryOp>;
|
||||
TEST_P(UnaryOpExpressionTest, Expr_UnaryOp) {
|
||||
auto op = GetParam();
|
||||
|
|
|
@ -54,8 +54,6 @@
|
|||
#include "src/ast/type/vector_type.h"
|
||||
#include "src/ast/type_constructor_expression.h"
|
||||
#include "src/ast/uint_literal.h"
|
||||
#include "src/ast/unary_derivative_expression.h"
|
||||
#include "src/ast/unary_method_expression.h"
|
||||
#include "src/ast/unary_op_expression.h"
|
||||
#include "src/ast/unless_statement.h"
|
||||
#include "src/ast/variable_decl_statement.h"
|
||||
|
@ -166,12 +164,6 @@ bool GeneratorImpl::EmitExpression(ast::Expression* expr) {
|
|||
if (expr->IsMemberAccessor()) {
|
||||
return EmitMemberAccessor(expr->AsMemberAccessor());
|
||||
}
|
||||
if (expr->IsUnaryDerivative()) {
|
||||
return EmitUnaryDerivative(expr->AsUnaryDerivative());
|
||||
}
|
||||
if (expr->IsUnaryMethod()) {
|
||||
return EmitUnaryMethod(expr->AsUnaryMethod());
|
||||
}
|
||||
if (expr->IsUnaryOp()) {
|
||||
return EmitUnaryOp(expr->AsUnaryOp());
|
||||
}
|
||||
|
@ -595,78 +587,6 @@ bool GeneratorImpl::EmitBinary(ast::BinaryExpression* expr) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool GeneratorImpl::EmitUnaryDerivative(ast::UnaryDerivativeExpression* expr) {
|
||||
switch (expr->op()) {
|
||||
case ast::UnaryDerivative::kDpdx:
|
||||
out_ << "dpdx";
|
||||
break;
|
||||
case ast::UnaryDerivative::kDpdy:
|
||||
out_ << "dpdy";
|
||||
break;
|
||||
case ast::UnaryDerivative::kFwidth:
|
||||
out_ << "fwidth";
|
||||
break;
|
||||
}
|
||||
|
||||
if (expr->modifier() != ast::DerivativeModifier::kNone) {
|
||||
out_ << "<" << expr->modifier() << ">";
|
||||
}
|
||||
|
||||
out_ << "(";
|
||||
|
||||
if (!EmitExpression(expr->param())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
out_ << ")";
|
||||
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;
|
||||
}
|
||||
|
||||
bool GeneratorImpl::EmitUnaryOp(ast::UnaryOpExpression* expr) {
|
||||
switch (expr->op()) {
|
||||
case ast::UnaryOp::kNot:
|
||||
|
|
|
@ -190,14 +190,6 @@ class GeneratorImpl {
|
|||
/// @param expr the type constructor expression
|
||||
/// @returns true if the constructor is emitted
|
||||
bool EmitTypeConstructor(ast::TypeConstructorExpression* expr);
|
||||
/// Handles a unary derivative expression
|
||||
/// @param expr the expression to emit
|
||||
/// @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 a unary op expression
|
||||
/// @param expr the expression to emit
|
||||
/// @returns true if the expression was emitted
|
||||
|
|
|
@ -1,83 +0,0 @@
|
|||
// 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 <memory>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "src/ast/identifier_expression.h"
|
||||
#include "src/ast/unary_derivative_expression.h"
|
||||
#include "src/writer/wgsl/generator_impl.h"
|
||||
|
||||
namespace tint {
|
||||
namespace writer {
|
||||
namespace wgsl {
|
||||
namespace {
|
||||
|
||||
struct UnaryDerivativeData {
|
||||
const char* name;
|
||||
ast::UnaryDerivative derivative;
|
||||
};
|
||||
inline std::ostream& operator<<(std::ostream& out, UnaryDerivativeData data) {
|
||||
out << data.derivative;
|
||||
return out;
|
||||
}
|
||||
using UnaryDerivativeTest = testing::TestWithParam<UnaryDerivativeData>;
|
||||
TEST_P(UnaryDerivativeTest, Emit_ModifierNone) {
|
||||
auto params = GetParam();
|
||||
|
||||
auto expr = std::make_unique<ast::IdentifierExpression>("expr");
|
||||
|
||||
ast::UnaryDerivativeExpression derivative(
|
||||
params.derivative, ast::DerivativeModifier::kNone, std::move(expr));
|
||||
|
||||
GeneratorImpl g;
|
||||
ASSERT_TRUE(g.EmitExpression(&derivative)) << g.error();
|
||||
EXPECT_EQ(g.result(), std::string(params.name) + "(expr)");
|
||||
}
|
||||
TEST_P(UnaryDerivativeTest, Emit_ModifierFine) {
|
||||
auto params = GetParam();
|
||||
|
||||
auto expr = std::make_unique<ast::IdentifierExpression>("expr");
|
||||
|
||||
ast::UnaryDerivativeExpression derivative(
|
||||
params.derivative, ast::DerivativeModifier::kFine, std::move(expr));
|
||||
|
||||
GeneratorImpl g;
|
||||
ASSERT_TRUE(g.EmitExpression(&derivative)) << g.error();
|
||||
EXPECT_EQ(g.result(), std::string(params.name) + "<fine>(expr)");
|
||||
}
|
||||
TEST_P(UnaryDerivativeTest, Emit_ModifierCoarse) {
|
||||
auto params = GetParam();
|
||||
|
||||
auto expr = std::make_unique<ast::IdentifierExpression>("expr");
|
||||
|
||||
ast::UnaryDerivativeExpression derivative(
|
||||
params.derivative, ast::DerivativeModifier::kCoarse, std::move(expr));
|
||||
|
||||
GeneratorImpl g;
|
||||
ASSERT_TRUE(g.EmitExpression(&derivative)) << g.error();
|
||||
EXPECT_EQ(g.result(), std::string(params.name) + "<coarse>(expr)");
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
GeneratorImplTest,
|
||||
UnaryDerivativeTest,
|
||||
testing::Values(UnaryDerivativeData{"dpdx", ast::UnaryDerivative::kDpdx},
|
||||
UnaryDerivativeData{"dpdy", ast::UnaryDerivative::kDpdy},
|
||||
UnaryDerivativeData{"fwidth",
|
||||
ast::UnaryDerivative::kFwidth}));
|
||||
|
||||
} // namespace
|
||||
} // namespace wgsl
|
||||
} // namespace writer
|
||||
} // namespace tint
|
|
@ -1,84 +0,0 @@
|
|||
// 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 <memory>
|
||||
|
||||
#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<UnaryMethodData>;
|
||||
TEST_P(UnaryMethodTest, Emit) {
|
||||
auto params = GetParam();
|
||||
|
||||
auto expr = std::make_unique<ast::IdentifierExpression>("expr");
|
||||
ast::ExpressionList 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<UnaryMethodData>;
|
||||
TEST_P(UnaryMethodTest_MultiParam, Emit) {
|
||||
auto params = GetParam();
|
||||
|
||||
auto expr1 = std::make_unique<ast::IdentifierExpression>("expr1");
|
||||
auto expr2 = std::make_unique<ast::IdentifierExpression>("expr2");
|
||||
ast::ExpressionList 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
|
Loading…
Reference in New Issue