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:
Ben Clayton 2021-07-02 19:27:42 +00:00
parent 15e3561134
commit 65cd25951a
7 changed files with 399 additions and 0 deletions

View File

@ -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",

View File

@ -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

View File

@ -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

View File

@ -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_

View File

@ -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

View File

@ -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

View File

@ -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",