ast: Add ForLoopStatement node
Currently entirely unused. Bug: tint:952 Change-Id: I3ba2823024b81e927d8fe8a80fac4f82c02eac3e Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/56761 Kokoro: Kokoro <noreply+kokoro@google.com> Auto-Submit: Ben Clayton <bclayton@google.com> Reviewed-by: David Neto <dneto@google.com> Commit-Queue: Ben Clayton <bclayton@google.com>
This commit is contained in:
parent
15e3561134
commit
65cd25951a
|
@ -354,6 +354,8 @@ libtint_source_set("libtint_core_all_src") {
|
|||
"ast/fallthrough_statement.h",
|
||||
"ast/float_literal.cc",
|
||||
"ast/float_literal.h",
|
||||
"ast/for_loop_statement.cc",
|
||||
"ast/for_loop_statement.h",
|
||||
"ast/function.cc",
|
||||
"ast/function.h",
|
||||
"ast/group_decoration.cc",
|
||||
|
|
|
@ -98,6 +98,8 @@ set(TINT_LIB_SRCS
|
|||
ast/fallthrough_statement.h
|
||||
ast/float_literal.cc
|
||||
ast/float_literal.h
|
||||
ast/for_loop_statement.cc
|
||||
ast/for_loop_statement.h
|
||||
ast/function.cc
|
||||
ast/function.h
|
||||
ast/group_decoration.cc
|
||||
|
@ -550,6 +552,7 @@ if(${TINT_BUILD_TESTS})
|
|||
ast/f32_test.cc
|
||||
ast/fallthrough_statement_test.cc
|
||||
ast/float_literal_test.cc
|
||||
ast/for_loop_statement_test.cc
|
||||
ast/function_test.cc
|
||||
ast/group_decoration_test.cc
|
||||
ast/i32_test.cc
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
// Copyright 2021 The Tint Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "src/ast/for_loop_statement.h"
|
||||
|
||||
#include "src/program_builder.h"
|
||||
|
||||
TINT_INSTANTIATE_TYPEINFO(tint::ast::ForLoopStatement);
|
||||
|
||||
namespace tint {
|
||||
namespace ast {
|
||||
|
||||
ForLoopStatement::ForLoopStatement(ProgramID program_id,
|
||||
const Source& source,
|
||||
Statement* initializer,
|
||||
Expression* condition,
|
||||
Statement* continuing,
|
||||
BlockStatement* body)
|
||||
: Base(program_id, source),
|
||||
initializer_(initializer),
|
||||
condition_(condition),
|
||||
continuing_(continuing),
|
||||
body_(body) {
|
||||
TINT_ASSERT(AST, body_);
|
||||
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, initializer_, program_id);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, condition_, program_id);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, continuing_, program_id);
|
||||
TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, body_, program_id);
|
||||
}
|
||||
|
||||
ForLoopStatement::ForLoopStatement(ForLoopStatement&&) = default;
|
||||
|
||||
ForLoopStatement::~ForLoopStatement() = default;
|
||||
|
||||
ForLoopStatement* ForLoopStatement::Clone(CloneContext* ctx) const {
|
||||
// Clone arguments outside of create() call to have deterministic ordering
|
||||
auto src = ctx->Clone(source());
|
||||
|
||||
auto* init = ctx->Clone(initializer_);
|
||||
auto* cond = ctx->Clone(condition_);
|
||||
auto* cont = ctx->Clone(continuing_);
|
||||
auto* b = ctx->Clone(body_);
|
||||
return ctx->dst->create<ForLoopStatement>(src, init, cond, cont, b);
|
||||
}
|
||||
|
||||
void ForLoopStatement::to_str(const sem::Info& sem,
|
||||
std::ostream& out,
|
||||
size_t indent) const {
|
||||
make_indent(out, indent);
|
||||
out << "ForLoop {" << std::endl;
|
||||
|
||||
if (initializer_) {
|
||||
make_indent(out, indent + 2);
|
||||
out << "initializer:" << std::endl;
|
||||
initializer_->to_str(sem, out, indent + 4);
|
||||
}
|
||||
|
||||
if (condition_) {
|
||||
make_indent(out, indent + 2);
|
||||
out << "condition:" << std::endl;
|
||||
condition_->to_str(sem, out, indent + 4);
|
||||
}
|
||||
|
||||
if (continuing_) {
|
||||
make_indent(out, indent + 2);
|
||||
out << "continuing:" << std::endl;
|
||||
continuing_->to_str(sem, out, indent + 4);
|
||||
}
|
||||
|
||||
make_indent(out, indent + 2);
|
||||
out << "body:" << std::endl;
|
||||
for (auto* stmt : *body_) {
|
||||
stmt->to_str(sem, out, indent + 4);
|
||||
}
|
||||
|
||||
out << "}" << std::endl;
|
||||
}
|
||||
|
||||
} // namespace ast
|
||||
} // namespace tint
|
|
@ -0,0 +1,91 @@
|
|||
// Copyright 2021 The Tint Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef SRC_AST_FOR_LOOP_STATEMENT_H_
|
||||
#define SRC_AST_FOR_LOOP_STATEMENT_H_
|
||||
|
||||
#include "src/ast/block_statement.h"
|
||||
|
||||
namespace tint {
|
||||
namespace ast {
|
||||
|
||||
class Expression;
|
||||
|
||||
/// A for loop statement
|
||||
class ForLoopStatement : public Castable<ForLoopStatement, Statement> {
|
||||
public:
|
||||
/// Constructor
|
||||
/// @param program_id the identifier of the program that owns this node
|
||||
/// @param source the for loop statement source
|
||||
/// @param initializer the optional loop initializer statement
|
||||
/// @param condition the optional loop condition expression
|
||||
/// @param continuing the optional continuing statement
|
||||
/// @param body the loop body
|
||||
ForLoopStatement(ProgramID program_id,
|
||||
const Source& source,
|
||||
Statement* initializer,
|
||||
Expression* condition,
|
||||
Statement* continuing,
|
||||
BlockStatement* body);
|
||||
/// Move constructor
|
||||
ForLoopStatement(ForLoopStatement&&);
|
||||
~ForLoopStatement() override;
|
||||
|
||||
/// @returns the initializer statement
|
||||
const Statement* initializer() const { return initializer_; }
|
||||
/// @returns the initializer statement
|
||||
Statement* initializer() { return initializer_; }
|
||||
|
||||
/// @returns the condition expression
|
||||
const Expression* condition() const { return condition_; }
|
||||
/// @returns the condition expression
|
||||
Expression* condition() { return condition_; }
|
||||
|
||||
/// @returns the continuing statement
|
||||
const Statement* continuing() const { return continuing_; }
|
||||
/// @returns the continuing statement
|
||||
Statement* continuing() { return continuing_; }
|
||||
|
||||
/// @returns the loop body block
|
||||
const BlockStatement* body() const { return body_; }
|
||||
/// @returns the loop body block
|
||||
BlockStatement* body() { return body_; }
|
||||
|
||||
/// Clones this node and all transitive child nodes using the `CloneContext`
|
||||
/// `ctx`.
|
||||
/// @param ctx the clone context
|
||||
/// @return the newly cloned node
|
||||
ForLoopStatement* Clone(CloneContext* ctx) const override;
|
||||
|
||||
/// Writes a representation of the node to the output stream
|
||||
/// @param sem the semantic info for the program
|
||||
/// @param out the stream to write to
|
||||
/// @param indent number of spaces to indent the node when writing
|
||||
void to_str(const sem::Info& sem,
|
||||
std::ostream& out,
|
||||
size_t indent) const override;
|
||||
|
||||
private:
|
||||
ForLoopStatement(const ForLoopStatement&) = delete;
|
||||
|
||||
Statement* const initializer_;
|
||||
Expression* const condition_;
|
||||
Statement* const continuing_;
|
||||
BlockStatement* const body_;
|
||||
};
|
||||
|
||||
} // namespace ast
|
||||
} // namespace tint
|
||||
|
||||
#endif // SRC_AST_FOR_LOOP_STATEMENT_H_
|
|
@ -0,0 +1,175 @@
|
|||
// Copyright 2021 The Tint Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "gtest/gtest-spi.h"
|
||||
#include "src/ast/binary_expression.h"
|
||||
#include "src/ast/test_helper.h"
|
||||
|
||||
namespace tint {
|
||||
namespace ast {
|
||||
namespace {
|
||||
|
||||
using ForLoopStatementTest = TestHelper;
|
||||
|
||||
TEST_F(ForLoopStatementTest, Creation) {
|
||||
auto* init = Decl(Var("i", ty.u32()));
|
||||
auto* cond =
|
||||
create<BinaryExpression>(BinaryOp::kLessThan, Expr("i"), Expr(5u));
|
||||
auto* cont = Assign("i", Add("i", 1));
|
||||
auto* body = Block(Return());
|
||||
auto* l = For(init, cond, cont, body);
|
||||
|
||||
EXPECT_EQ(l->initializer(), init);
|
||||
EXPECT_EQ(l->condition(), cond);
|
||||
EXPECT_EQ(l->continuing(), cont);
|
||||
EXPECT_EQ(l->body(), body);
|
||||
}
|
||||
|
||||
TEST_F(ForLoopStatementTest, Creation_WithSource) {
|
||||
auto* body = Block(Return());
|
||||
auto* l = For(Source{{20u, 2u}}, nullptr, nullptr, nullptr, body);
|
||||
auto src = l->source();
|
||||
EXPECT_EQ(src.range.begin.line, 20u);
|
||||
EXPECT_EQ(src.range.begin.column, 2u);
|
||||
}
|
||||
|
||||
TEST_F(ForLoopStatementTest, Creation_Null_InitCondCont) {
|
||||
auto* body = Block(Return());
|
||||
auto* l = For(nullptr, nullptr, nullptr, body);
|
||||
EXPECT_EQ(l->body(), body);
|
||||
}
|
||||
|
||||
TEST_F(ForLoopStatementTest, Assert_Null_Body) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b;
|
||||
b.For(nullptr, nullptr, nullptr, nullptr);
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
TEST_F(ForLoopStatementTest, Assert_DifferentProgramID_Initializer) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.For(b2.Block(), nullptr, nullptr, b1.Block());
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
TEST_F(ForLoopStatementTest, Assert_DifferentProgramID_Condition) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.For(nullptr, b2.Expr(true), nullptr, b1.Block());
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
TEST_F(ForLoopStatementTest, Assert_DifferentProgramID_Continuing) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.For(nullptr, nullptr, b2.Block(), b1.Block());
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
TEST_F(ForLoopStatementTest, Assert_DifferentProgramID_Body) {
|
||||
EXPECT_FATAL_FAILURE(
|
||||
{
|
||||
ProgramBuilder b1;
|
||||
ProgramBuilder b2;
|
||||
b1.For(nullptr, nullptr, nullptr, b2.Block());
|
||||
},
|
||||
"internal compiler error");
|
||||
}
|
||||
|
||||
TEST_F(ForLoopStatementTest, ToStr) {
|
||||
auto* body = Block(Return());
|
||||
auto* l = For(nullptr, nullptr, nullptr, body);
|
||||
|
||||
EXPECT_EQ(str(l), R"(ForLoop {
|
||||
body:
|
||||
Return{}
|
||||
}
|
||||
)");
|
||||
}
|
||||
|
||||
TEST_F(ForLoopStatementTest, ToStr_With_Init) {
|
||||
auto* body = Block(Return());
|
||||
auto* l = For(Block(), nullptr, nullptr, body);
|
||||
|
||||
EXPECT_EQ(str(l), R"(ForLoop {
|
||||
initializer:
|
||||
Block{
|
||||
}
|
||||
body:
|
||||
Return{}
|
||||
}
|
||||
)");
|
||||
}
|
||||
|
||||
TEST_F(ForLoopStatementTest, ToStr_With_Cond) {
|
||||
auto* body = Block(Return());
|
||||
auto* l = For(nullptr, Expr(true), nullptr, body);
|
||||
|
||||
EXPECT_EQ(str(l), R"(ForLoop {
|
||||
condition:
|
||||
ScalarConstructor[not set]{true}
|
||||
body:
|
||||
Return{}
|
||||
}
|
||||
)");
|
||||
}
|
||||
|
||||
TEST_F(ForLoopStatementTest, ToStr_With_Cont) {
|
||||
auto* body = Block(Return());
|
||||
auto* l = For(nullptr, nullptr, Block(), body);
|
||||
|
||||
EXPECT_EQ(str(l), R"(ForLoop {
|
||||
continuing:
|
||||
Block{
|
||||
}
|
||||
body:
|
||||
Return{}
|
||||
}
|
||||
)");
|
||||
}
|
||||
|
||||
TEST_F(ForLoopStatementTest, ToStr_With_All) {
|
||||
auto* body = Block(Return());
|
||||
auto* l = For(Block(), Expr(true), Block(), body);
|
||||
|
||||
EXPECT_EQ(str(l), R"(ForLoop {
|
||||
initializer:
|
||||
Block{
|
||||
}
|
||||
condition:
|
||||
ScalarConstructor[not set]{true}
|
||||
continuing:
|
||||
Block{
|
||||
}
|
||||
body:
|
||||
Return{}
|
||||
}
|
||||
)");
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace ast
|
||||
} // namespace tint
|
|
@ -35,6 +35,7 @@
|
|||
#include "src/ast/external_texture.h"
|
||||
#include "src/ast/f32.h"
|
||||
#include "src/ast/float_literal.h"
|
||||
#include "src/ast/for_loop_statement.h"
|
||||
#include "src/ast/i32.h"
|
||||
#include "src/ast/if_statement.h"
|
||||
#include "src/ast/interpolate_decoration.h"
|
||||
|
@ -1920,6 +1921,40 @@ class ProgramBuilder {
|
|||
return create<ast::LoopStatement>(body, continuing);
|
||||
}
|
||||
|
||||
/// Creates a ast::ForLoopStatement with input body and optional initializer,
|
||||
/// condition and continuing.
|
||||
/// @param source the source information
|
||||
/// @param init the optional loop initializer
|
||||
/// @param cond the optional loop condition
|
||||
/// @param cont the optional loop continuing
|
||||
/// @param body the loop body
|
||||
/// @returns the for loop statement pointer
|
||||
template <typename COND>
|
||||
ast::ForLoopStatement* For(const Source& source,
|
||||
ast::Statement* init,
|
||||
COND&& cond,
|
||||
ast::Statement* cont,
|
||||
ast::BlockStatement* body) {
|
||||
return create<ast::ForLoopStatement>(
|
||||
source, init, Expr(std::forward<COND>(cond)), cont, body);
|
||||
}
|
||||
|
||||
/// Creates a ast::ForLoopStatement with input body and optional initializer,
|
||||
/// condition and continuing.
|
||||
/// @param init the optional loop initializer
|
||||
/// @param cond the optional loop condition
|
||||
/// @param cont the optional loop continuing
|
||||
/// @param body the loop body
|
||||
/// @returns the for loop statement pointer
|
||||
template <typename COND>
|
||||
ast::ForLoopStatement* For(ast::Statement* init,
|
||||
COND&& cond,
|
||||
ast::Statement* cont,
|
||||
ast::BlockStatement* body) {
|
||||
return create<ast::ForLoopStatement>(init, Expr(std::forward<COND>(cond)),
|
||||
cont, body);
|
||||
}
|
||||
|
||||
/// Creates a ast::VariableDeclStatement for the input variable
|
||||
/// @param source the source information
|
||||
/// @param var the variable to wrap in a decl statement
|
||||
|
|
|
@ -169,6 +169,7 @@ tint_unittests_source_set("tint_unittests_core_src") {
|
|||
"../src/ast/f32_test.cc",
|
||||
"../src/ast/fallthrough_statement_test.cc",
|
||||
"../src/ast/float_literal_test.cc",
|
||||
"../src/ast/for_loop_statement_test.cc",
|
||||
"../src/ast/function_test.cc",
|
||||
"../src/ast/group_decoration_test.cc",
|
||||
"../src/ast/i32_test.cc",
|
||||
|
|
Loading…
Reference in New Issue