Replace Statement::(Is|As)* with Castable
Change-Id: I5520752a4b5844be0ecac7921616893d123b246a Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/34315 Reviewed-by: dan sinclair <dsinclair@chromium.org>
This commit is contained in:
parent
4d3ca7f132
commit
1d8098ae94
|
@ -31,10 +31,6 @@ AssignmentStatement::AssignmentStatement(AssignmentStatement&&) = default;
|
||||||
|
|
||||||
AssignmentStatement::~AssignmentStatement() = default;
|
AssignmentStatement::~AssignmentStatement() = default;
|
||||||
|
|
||||||
bool AssignmentStatement::IsAssign() const {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AssignmentStatement::IsValid() const {
|
bool AssignmentStatement::IsValid() const {
|
||||||
if (lhs_ == nullptr || !lhs_->IsValid())
|
if (lhs_ == nullptr || !lhs_->IsValid())
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -55,9 +55,6 @@ class AssignmentStatement : public Castable<AssignmentStatement, Statement> {
|
||||||
/// @returns the right side expression
|
/// @returns the right side expression
|
||||||
Expression* rhs() const { return rhs_; }
|
Expression* rhs() const { return rhs_; }
|
||||||
|
|
||||||
/// @returns true if this is an assignment statement
|
|
||||||
bool IsAssign() const override;
|
|
||||||
|
|
||||||
/// @returns true if the node is valid
|
/// @returns true if the node is valid
|
||||||
bool IsValid() const override;
|
bool IsValid() const override;
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ TEST_F(AssignmentStatementTest, IsAssign) {
|
||||||
auto* rhs = create<ast::IdentifierExpression>("rhs");
|
auto* rhs = create<ast::IdentifierExpression>("rhs");
|
||||||
|
|
||||||
AssignmentStatement stmt(lhs, rhs);
|
AssignmentStatement stmt(lhs, rhs);
|
||||||
EXPECT_TRUE(stmt.IsAssign());
|
EXPECT_TRUE(stmt.Is<AssignmentStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(AssignmentStatementTest, IsValid) {
|
TEST_F(AssignmentStatementTest, IsValid) {
|
||||||
|
|
|
@ -25,10 +25,6 @@ BlockStatement::BlockStatement(BlockStatement&&) = default;
|
||||||
|
|
||||||
BlockStatement::~BlockStatement() = default;
|
BlockStatement::~BlockStatement() = default;
|
||||||
|
|
||||||
bool BlockStatement::IsBlock() const {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BlockStatement::IsValid() const {
|
bool BlockStatement::IsValid() const {
|
||||||
for (auto* stmt : *this) {
|
for (auto* stmt : *this) {
|
||||||
if (stmt == nullptr || !stmt->IsValid()) {
|
if (stmt == nullptr || !stmt->IsValid()) {
|
||||||
|
|
|
@ -87,9 +87,6 @@ class BlockStatement : public Castable<BlockStatement, Statement> {
|
||||||
return statements_.end();
|
return statements_.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @returns true if this is a block statement
|
|
||||||
bool IsBlock() const override;
|
|
||||||
|
|
||||||
/// @returns true if the node is valid
|
/// @returns true if the node is valid
|
||||||
bool IsValid() const override;
|
bool IsValid() const override;
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,7 @@ TEST_F(BlockStatementTest, Creation_WithSource) {
|
||||||
|
|
||||||
TEST_F(BlockStatementTest, IsBlock) {
|
TEST_F(BlockStatementTest, IsBlock) {
|
||||||
BlockStatement b;
|
BlockStatement b;
|
||||||
EXPECT_TRUE(b.IsBlock());
|
EXPECT_TRUE(b.Is<BlockStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(BlockStatementTest, IsValid) {
|
TEST_F(BlockStatementTest, IsValid) {
|
||||||
|
|
|
@ -25,10 +25,6 @@ BreakStatement::BreakStatement(BreakStatement&&) = default;
|
||||||
|
|
||||||
BreakStatement::~BreakStatement() = default;
|
BreakStatement::~BreakStatement() = default;
|
||||||
|
|
||||||
bool BreakStatement::IsBreak() const {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BreakStatement::IsValid() const {
|
bool BreakStatement::IsValid() const {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,9 +32,6 @@ class BreakStatement : public Castable<BreakStatement, Statement> {
|
||||||
BreakStatement(BreakStatement&&);
|
BreakStatement(BreakStatement&&);
|
||||||
~BreakStatement() override;
|
~BreakStatement() override;
|
||||||
|
|
||||||
/// @returns true if this is an break statement
|
|
||||||
bool IsBreak() const override;
|
|
||||||
|
|
||||||
/// @returns true if the node is valid
|
/// @returns true if the node is valid
|
||||||
bool IsValid() const override;
|
bool IsValid() const override;
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ TEST_F(BreakStatementTest, Creation_WithSource) {
|
||||||
|
|
||||||
TEST_F(BreakStatementTest, IsBreak) {
|
TEST_F(BreakStatementTest, IsBreak) {
|
||||||
BreakStatement stmt;
|
BreakStatement stmt;
|
||||||
EXPECT_TRUE(stmt.IsBreak());
|
EXPECT_TRUE(stmt.Is<BreakStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(BreakStatementTest, IsValid) {
|
TEST_F(BreakStatementTest, IsValid) {
|
||||||
|
|
|
@ -27,10 +27,6 @@ CallStatement::CallStatement(CallStatement&&) = default;
|
||||||
|
|
||||||
CallStatement::~CallStatement() = default;
|
CallStatement::~CallStatement() = default;
|
||||||
|
|
||||||
bool CallStatement::IsCall() const {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CallStatement::IsValid() const {
|
bool CallStatement::IsValid() const {
|
||||||
return call_ != nullptr && call_->IsValid();
|
return call_ != nullptr && call_->IsValid();
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,9 +42,6 @@ class CallStatement : public Castable<CallStatement, Statement> {
|
||||||
/// @returns the call expression
|
/// @returns the call expression
|
||||||
CallExpression* expr() const { return call_; }
|
CallExpression* expr() const { return call_; }
|
||||||
|
|
||||||
/// @returns true if this is a call statement
|
|
||||||
bool IsCall() const override;
|
|
||||||
|
|
||||||
/// @returns true if the node is valid
|
/// @returns true if the node is valid
|
||||||
bool IsValid() const override;
|
bool IsValid() const override;
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ TEST_F(CallStatementTest, Creation) {
|
||||||
|
|
||||||
TEST_F(CallStatementTest, IsCall) {
|
TEST_F(CallStatementTest, IsCall) {
|
||||||
CallStatement c;
|
CallStatement c;
|
||||||
EXPECT_TRUE(c.IsCall());
|
EXPECT_TRUE(c.Is<CallStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CallStatementTest, IsValid) {
|
TEST_F(CallStatementTest, IsValid) {
|
||||||
|
|
|
@ -31,10 +31,6 @@ CaseStatement::CaseStatement(CaseStatement&&) = default;
|
||||||
|
|
||||||
CaseStatement::~CaseStatement() = default;
|
CaseStatement::~CaseStatement() = default;
|
||||||
|
|
||||||
bool CaseStatement::IsCase() const {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CaseStatement::IsValid() const {
|
bool CaseStatement::IsValid() const {
|
||||||
return body_ != nullptr && body_->IsValid();
|
return body_ != nullptr && body_->IsValid();
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,9 +70,6 @@ class CaseStatement : public Castable<CaseStatement, Statement> {
|
||||||
/// @returns the case body
|
/// @returns the case body
|
||||||
BlockStatement* body() { return body_; }
|
BlockStatement* body() { return body_; }
|
||||||
|
|
||||||
/// @returns true if this is a case statement
|
|
||||||
bool IsCase() const override;
|
|
||||||
|
|
||||||
/// @returns true if the node is valid
|
/// @returns true if the node is valid
|
||||||
bool IsValid() const override;
|
bool IsValid() const override;
|
||||||
|
|
||||||
|
|
|
@ -99,7 +99,7 @@ TEST_F(CaseStatementTest, IsDefault_WithSelectors) {
|
||||||
|
|
||||||
TEST_F(CaseStatementTest, IsCase) {
|
TEST_F(CaseStatementTest, IsCase) {
|
||||||
CaseStatement c(create<ast::BlockStatement>());
|
CaseStatement c(create<ast::BlockStatement>());
|
||||||
EXPECT_TRUE(c.IsCase());
|
EXPECT_TRUE(c.Is<ast::CaseStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(CaseStatementTest, IsValid) {
|
TEST_F(CaseStatementTest, IsValid) {
|
||||||
|
|
|
@ -25,10 +25,6 @@ ContinueStatement::ContinueStatement(ContinueStatement&&) = default;
|
||||||
|
|
||||||
ContinueStatement::~ContinueStatement() = default;
|
ContinueStatement::~ContinueStatement() = default;
|
||||||
|
|
||||||
bool ContinueStatement::IsContinue() const {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ContinueStatement::IsValid() const {
|
bool ContinueStatement::IsValid() const {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,9 +35,6 @@ class ContinueStatement : public Castable<ContinueStatement, Statement> {
|
||||||
ContinueStatement(ContinueStatement&&);
|
ContinueStatement(ContinueStatement&&);
|
||||||
~ContinueStatement() override;
|
~ContinueStatement() override;
|
||||||
|
|
||||||
/// @returns true if this is an continue statement
|
|
||||||
bool IsContinue() const override;
|
|
||||||
|
|
||||||
/// @returns true if the node is valid
|
/// @returns true if the node is valid
|
||||||
bool IsValid() const override;
|
bool IsValid() const override;
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ TEST_F(ContinueStatementTest, Creation_WithSource) {
|
||||||
|
|
||||||
TEST_F(ContinueStatementTest, IsContinue) {
|
TEST_F(ContinueStatementTest, IsContinue) {
|
||||||
ContinueStatement stmt;
|
ContinueStatement stmt;
|
||||||
EXPECT_TRUE(stmt.IsContinue());
|
EXPECT_TRUE(stmt.Is<ContinueStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ContinueStatementTest, IsValid) {
|
TEST_F(ContinueStatementTest, IsValid) {
|
||||||
|
|
|
@ -25,10 +25,6 @@ DiscardStatement::DiscardStatement(DiscardStatement&&) = default;
|
||||||
|
|
||||||
DiscardStatement::~DiscardStatement() = default;
|
DiscardStatement::~DiscardStatement() = default;
|
||||||
|
|
||||||
bool DiscardStatement::IsDiscard() const {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DiscardStatement::IsValid() const {
|
bool DiscardStatement::IsValid() const {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,9 +32,6 @@ class DiscardStatement : public Castable<DiscardStatement, Statement> {
|
||||||
DiscardStatement(DiscardStatement&&);
|
DiscardStatement(DiscardStatement&&);
|
||||||
~DiscardStatement() override;
|
~DiscardStatement() override;
|
||||||
|
|
||||||
/// @returns true if this is a discard statement
|
|
||||||
bool IsDiscard() const override;
|
|
||||||
|
|
||||||
/// @returns true if the node is valid
|
/// @returns true if the node is valid
|
||||||
bool IsValid() const override;
|
bool IsValid() const override;
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ TEST_F(DiscardStatementTest, Creation_WithSource) {
|
||||||
|
|
||||||
TEST_F(DiscardStatementTest, IsDiscard) {
|
TEST_F(DiscardStatementTest, IsDiscard) {
|
||||||
DiscardStatement stmt;
|
DiscardStatement stmt;
|
||||||
EXPECT_TRUE(stmt.IsDiscard());
|
EXPECT_TRUE(stmt.Is<DiscardStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(DiscardStatementTest, IsValid) {
|
TEST_F(DiscardStatementTest, IsValid) {
|
||||||
|
|
|
@ -34,10 +34,6 @@ ElseStatement::ElseStatement(ElseStatement&&) = default;
|
||||||
|
|
||||||
ElseStatement::~ElseStatement() = default;
|
ElseStatement::~ElseStatement() = default;
|
||||||
|
|
||||||
bool ElseStatement::IsElse() const {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ElseStatement::IsValid() const {
|
bool ElseStatement::IsValid() const {
|
||||||
if (body_ == nullptr || !body_->IsValid()) {
|
if (body_ == nullptr || !body_->IsValid()) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -67,9 +67,6 @@ class ElseStatement : public Castable<ElseStatement, Statement> {
|
||||||
/// @returns the else body
|
/// @returns the else body
|
||||||
BlockStatement* body() { return body_; }
|
BlockStatement* body() { return body_; }
|
||||||
|
|
||||||
/// @returns true if this is a else statement
|
|
||||||
bool IsElse() const override;
|
|
||||||
|
|
||||||
/// @returns true if the node is valid
|
/// @returns true if the node is valid
|
||||||
bool IsValid() const override;
|
bool IsValid() const override;
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,7 @@ TEST_F(ElseStatementTest, Creation_WithSource) {
|
||||||
|
|
||||||
TEST_F(ElseStatementTest, IsElse) {
|
TEST_F(ElseStatementTest, IsElse) {
|
||||||
ElseStatement e(create<BlockStatement>());
|
ElseStatement e(create<BlockStatement>());
|
||||||
EXPECT_TRUE(e.IsElse());
|
EXPECT_TRUE(e.Is<ElseStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ElseStatementTest, HasCondition) {
|
TEST_F(ElseStatementTest, HasCondition) {
|
||||||
|
|
|
@ -26,10 +26,6 @@ FallthroughStatement::FallthroughStatement(FallthroughStatement&&) = default;
|
||||||
|
|
||||||
FallthroughStatement::~FallthroughStatement() = default;
|
FallthroughStatement::~FallthroughStatement() = default;
|
||||||
|
|
||||||
bool FallthroughStatement::IsFallthrough() const {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FallthroughStatement::IsValid() const {
|
bool FallthroughStatement::IsValid() const {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,9 +32,6 @@ class FallthroughStatement : public Castable<FallthroughStatement, Statement> {
|
||||||
FallthroughStatement(FallthroughStatement&&);
|
FallthroughStatement(FallthroughStatement&&);
|
||||||
~FallthroughStatement() override;
|
~FallthroughStatement() override;
|
||||||
|
|
||||||
/// @returns true if this is an fallthrough statement
|
|
||||||
bool IsFallthrough() const override;
|
|
||||||
|
|
||||||
/// @returns true if the node is valid
|
/// @returns true if the node is valid
|
||||||
bool IsValid() const override;
|
bool IsValid() const override;
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ TEST_F(FallthroughStatementTest, Creation_WithSource) {
|
||||||
|
|
||||||
TEST_F(FallthroughStatementTest, IsFallthrough) {
|
TEST_F(FallthroughStatementTest, IsFallthrough) {
|
||||||
FallthroughStatement stmt;
|
FallthroughStatement stmt;
|
||||||
EXPECT_TRUE(stmt.IsFallthrough());
|
EXPECT_TRUE(stmt.Is<FallthroughStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(FallthroughStatementTest, IsValid) {
|
TEST_F(FallthroughStatementTest, IsValid) {
|
||||||
|
|
|
@ -31,10 +31,6 @@ IfStatement::IfStatement(IfStatement&&) = default;
|
||||||
|
|
||||||
IfStatement::~IfStatement() = default;
|
IfStatement::~IfStatement() = default;
|
||||||
|
|
||||||
bool IfStatement::IsIf() const {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IfStatement::IsValid() const {
|
bool IfStatement::IsValid() const {
|
||||||
if (condition_ == nullptr || !condition_->IsValid()) {
|
if (condition_ == nullptr || !condition_->IsValid()) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -71,9 +71,6 @@ class IfStatement : public Castable<IfStatement, Statement> {
|
||||||
/// @returns true if there are else statements
|
/// @returns true if there are else statements
|
||||||
bool has_else_statements() const { return !else_statements_.empty(); }
|
bool has_else_statements() const { return !else_statements_.empty(); }
|
||||||
|
|
||||||
/// @returns true if this is a if statement
|
|
||||||
bool IsIf() const override;
|
|
||||||
|
|
||||||
/// @returns true if the node is valid
|
/// @returns true if the node is valid
|
||||||
bool IsValid() const override;
|
bool IsValid() const override;
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@ TEST_F(IfStatementTest, Creation_WithSource) {
|
||||||
|
|
||||||
TEST_F(IfStatementTest, IsIf) {
|
TEST_F(IfStatementTest, IsIf) {
|
||||||
IfStatement stmt(nullptr, create<BlockStatement>());
|
IfStatement stmt(nullptr, create<BlockStatement>());
|
||||||
EXPECT_TRUE(stmt.IsIf());
|
EXPECT_TRUE(stmt.Is<IfStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(IfStatementTest, IsValid) {
|
TEST_F(IfStatementTest, IsValid) {
|
||||||
|
|
|
@ -29,10 +29,6 @@ LoopStatement::LoopStatement(LoopStatement&&) = default;
|
||||||
|
|
||||||
LoopStatement::~LoopStatement() = default;
|
LoopStatement::~LoopStatement() = default;
|
||||||
|
|
||||||
bool LoopStatement::IsLoop() const {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool LoopStatement::IsValid() const {
|
bool LoopStatement::IsValid() const {
|
||||||
if (body_ == nullptr || !body_->IsValid()) {
|
if (body_ == nullptr || !body_->IsValid()) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -62,9 +62,6 @@ class LoopStatement : public Castable<LoopStatement, Statement> {
|
||||||
return continuing_ != nullptr && !continuing_->empty();
|
return continuing_ != nullptr && !continuing_->empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @returns true if this is a loop statement
|
|
||||||
bool IsLoop() const override;
|
|
||||||
|
|
||||||
/// @returns true if the node is valid
|
/// @returns true if the node is valid
|
||||||
bool IsValid() const override;
|
bool IsValid() const override;
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ TEST_F(LoopStatementTest, Creation_WithSource) {
|
||||||
|
|
||||||
TEST_F(LoopStatementTest, IsLoop) {
|
TEST_F(LoopStatementTest, IsLoop) {
|
||||||
LoopStatement l(create<BlockStatement>(), create<BlockStatement>());
|
LoopStatement l(create<BlockStatement>(), create<BlockStatement>());
|
||||||
EXPECT_TRUE(l.IsLoop());
|
EXPECT_TRUE(l.Is<LoopStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(LoopStatementTest, HasContinuing_WithoutContinuing) {
|
TEST_F(LoopStatementTest, HasContinuing_WithoutContinuing) {
|
||||||
|
|
|
@ -30,10 +30,6 @@ ReturnStatement::ReturnStatement(ReturnStatement&&) = default;
|
||||||
|
|
||||||
ReturnStatement::~ReturnStatement() = default;
|
ReturnStatement::~ReturnStatement() = default;
|
||||||
|
|
||||||
bool ReturnStatement::IsReturn() const {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ReturnStatement::IsValid() const {
|
bool ReturnStatement::IsValid() const {
|
||||||
if (value_ != nullptr) {
|
if (value_ != nullptr) {
|
||||||
return value_->IsValid();
|
return value_->IsValid();
|
||||||
|
|
|
@ -51,9 +51,6 @@ class ReturnStatement : public Castable<ReturnStatement, Statement> {
|
||||||
/// @returns true if the return has a value
|
/// @returns true if the return has a value
|
||||||
bool has_value() const { return value_ != nullptr; }
|
bool has_value() const { return value_ != nullptr; }
|
||||||
|
|
||||||
/// @returns true if this is a return statement
|
|
||||||
bool IsReturn() const override;
|
|
||||||
|
|
||||||
/// @returns true if the node is valid
|
/// @returns true if the node is valid
|
||||||
bool IsValid() const override;
|
bool IsValid() const override;
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ TEST_F(ReturnStatementTest, Creation_WithSource) {
|
||||||
|
|
||||||
TEST_F(ReturnStatementTest, IsReturn) {
|
TEST_F(ReturnStatementTest, IsReturn) {
|
||||||
ReturnStatement r;
|
ReturnStatement r;
|
||||||
EXPECT_TRUE(r.IsReturn());
|
EXPECT_TRUE(r.Is<ReturnStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ReturnStatementTest, HasValue_WithoutValue) {
|
TEST_F(ReturnStatementTest, HasValue_WithoutValue) {
|
||||||
|
|
|
@ -42,247 +42,51 @@ Statement::Statement(Statement&&) = default;
|
||||||
|
|
||||||
Statement::~Statement() = default;
|
Statement::~Statement() = default;
|
||||||
|
|
||||||
bool Statement::IsAssign() const {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Statement::IsBlock() const {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Statement::IsBreak() const {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Statement::IsCase() const {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Statement::IsCall() const {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Statement::IsContinue() const {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Statement::IsDiscard() const {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Statement::IsElse() const {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Statement::IsFallthrough() const {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Statement::IsIf() const {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Statement::IsLoop() const {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Statement::IsReturn() const {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Statement::IsSwitch() const {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Statement::IsVariableDecl() const {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* Statement::Name() const {
|
const char* Statement::Name() const {
|
||||||
if (IsAssign()) {
|
if (Is<AssignmentStatement>()) {
|
||||||
return "assignment statement";
|
return "assignment statement";
|
||||||
}
|
}
|
||||||
if (IsBlock()) {
|
if (Is<BlockStatement>()) {
|
||||||
return "block statement";
|
return "block statement";
|
||||||
}
|
}
|
||||||
if (IsBreak()) {
|
if (Is<BreakStatement>()) {
|
||||||
return "break statement";
|
return "break statement";
|
||||||
}
|
}
|
||||||
if (IsCase()) {
|
if (Is<CaseStatement>()) {
|
||||||
return "case statement";
|
return "case statement";
|
||||||
}
|
}
|
||||||
if (IsCall()) {
|
if (Is<CallStatement>()) {
|
||||||
return "function call";
|
return "function call";
|
||||||
}
|
}
|
||||||
if (IsContinue()) {
|
if (Is<ContinueStatement>()) {
|
||||||
return "continue statement";
|
return "continue statement";
|
||||||
}
|
}
|
||||||
if (IsDiscard()) {
|
if (Is<DiscardStatement>()) {
|
||||||
return "discard statement";
|
return "discard statement";
|
||||||
}
|
}
|
||||||
if (IsElse()) {
|
if (Is<ElseStatement>()) {
|
||||||
return "else statement";
|
return "else statement";
|
||||||
}
|
}
|
||||||
if (IsFallthrough()) {
|
if (Is<FallthroughStatement>()) {
|
||||||
return "fallthrough statement";
|
return "fallthrough statement";
|
||||||
}
|
}
|
||||||
if (IsIf()) {
|
if (Is<IfStatement>()) {
|
||||||
return "if statement";
|
return "if statement";
|
||||||
}
|
}
|
||||||
if (IsLoop()) {
|
if (Is<LoopStatement>()) {
|
||||||
return "loop statement";
|
return "loop statement";
|
||||||
}
|
}
|
||||||
if (IsReturn()) {
|
if (Is<ReturnStatement>()) {
|
||||||
return "return statement";
|
return "return statement";
|
||||||
}
|
}
|
||||||
if (IsSwitch()) {
|
if (Is<SwitchStatement>()) {
|
||||||
return "switch statement";
|
return "switch statement";
|
||||||
}
|
}
|
||||||
if (IsVariableDecl()) {
|
if (Is<VariableDeclStatement>()) {
|
||||||
return "variable declaration";
|
return "variable declaration";
|
||||||
}
|
}
|
||||||
return "statement";
|
return "statement";
|
||||||
}
|
}
|
||||||
|
|
||||||
const AssignmentStatement* Statement::AsAssign() const {
|
|
||||||
assert(IsAssign());
|
|
||||||
return static_cast<const AssignmentStatement*>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
const BlockStatement* Statement::AsBlock() const {
|
|
||||||
assert(IsBlock());
|
|
||||||
return static_cast<const BlockStatement*>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
const BreakStatement* Statement::AsBreak() const {
|
|
||||||
assert(IsBreak());
|
|
||||||
return static_cast<const BreakStatement*>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
const CallStatement* Statement::AsCall() const {
|
|
||||||
assert(IsCall());
|
|
||||||
return static_cast<const CallStatement*>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
const CaseStatement* Statement::AsCase() const {
|
|
||||||
assert(IsCase());
|
|
||||||
return static_cast<const CaseStatement*>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
const ContinueStatement* Statement::AsContinue() const {
|
|
||||||
assert(IsContinue());
|
|
||||||
return static_cast<const ContinueStatement*>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
const DiscardStatement* Statement::AsDiscard() const {
|
|
||||||
assert(IsDiscard());
|
|
||||||
return static_cast<const DiscardStatement*>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
const ElseStatement* Statement::AsElse() const {
|
|
||||||
assert(IsElse());
|
|
||||||
return static_cast<const ElseStatement*>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
const FallthroughStatement* Statement::AsFallthrough() const {
|
|
||||||
assert(IsFallthrough());
|
|
||||||
return static_cast<const FallthroughStatement*>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
const IfStatement* Statement::AsIf() const {
|
|
||||||
assert(IsIf());
|
|
||||||
return static_cast<const IfStatement*>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
const LoopStatement* Statement::AsLoop() const {
|
|
||||||
assert(IsLoop());
|
|
||||||
return static_cast<const LoopStatement*>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
const ReturnStatement* Statement::AsReturn() const {
|
|
||||||
assert(IsReturn());
|
|
||||||
return static_cast<const ReturnStatement*>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
const SwitchStatement* Statement::AsSwitch() const {
|
|
||||||
assert(IsSwitch());
|
|
||||||
return static_cast<const SwitchStatement*>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
const VariableDeclStatement* Statement::AsVariableDecl() const {
|
|
||||||
assert(IsVariableDecl());
|
|
||||||
return static_cast<const VariableDeclStatement*>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
AssignmentStatement* Statement::AsAssign() {
|
|
||||||
assert(IsAssign());
|
|
||||||
return static_cast<AssignmentStatement*>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
BlockStatement* Statement::AsBlock() {
|
|
||||||
assert(IsBlock());
|
|
||||||
return static_cast<BlockStatement*>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
BreakStatement* Statement::AsBreak() {
|
|
||||||
assert(IsBreak());
|
|
||||||
return static_cast<BreakStatement*>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
CallStatement* Statement::AsCall() {
|
|
||||||
assert(IsCall());
|
|
||||||
return static_cast<CallStatement*>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
CaseStatement* Statement::AsCase() {
|
|
||||||
assert(IsCase());
|
|
||||||
return static_cast<CaseStatement*>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
ContinueStatement* Statement::AsContinue() {
|
|
||||||
assert(IsContinue());
|
|
||||||
return static_cast<ContinueStatement*>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
DiscardStatement* Statement::AsDiscard() {
|
|
||||||
assert(IsDiscard());
|
|
||||||
return static_cast<DiscardStatement*>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
ElseStatement* Statement::AsElse() {
|
|
||||||
assert(IsElse());
|
|
||||||
return static_cast<ElseStatement*>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
FallthroughStatement* Statement::AsFallthrough() {
|
|
||||||
assert(IsFallthrough());
|
|
||||||
return static_cast<FallthroughStatement*>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
IfStatement* Statement::AsIf() {
|
|
||||||
assert(IsIf());
|
|
||||||
return static_cast<IfStatement*>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
LoopStatement* Statement::AsLoop() {
|
|
||||||
assert(IsLoop());
|
|
||||||
return static_cast<LoopStatement*>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnStatement* Statement::AsReturn() {
|
|
||||||
assert(IsReturn());
|
|
||||||
return static_cast<ReturnStatement*>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
SwitchStatement* Statement::AsSwitch() {
|
|
||||||
assert(IsSwitch());
|
|
||||||
return static_cast<SwitchStatement*>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
VariableDeclStatement* Statement::AsVariableDecl() {
|
|
||||||
assert(IsVariableDecl());
|
|
||||||
return static_cast<VariableDeclStatement*>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace ast
|
} // namespace ast
|
||||||
} // namespace tint
|
} // namespace tint
|
||||||
|
|
|
@ -23,116 +23,14 @@
|
||||||
namespace tint {
|
namespace tint {
|
||||||
namespace ast {
|
namespace ast {
|
||||||
|
|
||||||
class AssignmentStatement;
|
|
||||||
class BlockStatement;
|
|
||||||
class BreakStatement;
|
|
||||||
class CallStatement;
|
|
||||||
class CaseStatement;
|
|
||||||
class ContinueStatement;
|
|
||||||
class DiscardStatement;
|
|
||||||
class ElseStatement;
|
|
||||||
class FallthroughStatement;
|
|
||||||
class IfStatement;
|
|
||||||
class LoopStatement;
|
|
||||||
class ReturnStatement;
|
|
||||||
class SwitchStatement;
|
|
||||||
class VariableDeclStatement;
|
|
||||||
|
|
||||||
/// Base statement class
|
/// Base statement class
|
||||||
class Statement : public Castable<Statement, Node> {
|
class Statement : public Castable<Statement, Node> {
|
||||||
public:
|
public:
|
||||||
~Statement() override;
|
~Statement() override;
|
||||||
|
|
||||||
/// @returns true if this is an assign statement
|
|
||||||
virtual bool IsAssign() const;
|
|
||||||
/// @returns true if this is a block statement
|
|
||||||
virtual bool IsBlock() const;
|
|
||||||
/// @returns true if this is a break statement
|
|
||||||
virtual bool IsBreak() const;
|
|
||||||
/// @returns true if this is a call statement
|
|
||||||
virtual bool IsCall() const;
|
|
||||||
/// @returns true if this is a case statement
|
|
||||||
virtual bool IsCase() const;
|
|
||||||
/// @returns true if this is a continue statement
|
|
||||||
virtual bool IsContinue() const;
|
|
||||||
/// @returns true if this is a discard statement
|
|
||||||
virtual bool IsDiscard() const;
|
|
||||||
/// @returns true if this is an else statement
|
|
||||||
virtual bool IsElse() const;
|
|
||||||
/// @returns true if this is a fallthrough statement
|
|
||||||
virtual bool IsFallthrough() const;
|
|
||||||
/// @returns true if this is an if statement
|
|
||||||
virtual bool IsIf() const;
|
|
||||||
/// @returns true if this is a loop statement
|
|
||||||
virtual bool IsLoop() const;
|
|
||||||
/// @returns true if this is a return statement
|
|
||||||
virtual bool IsReturn() const;
|
|
||||||
/// @returns true if this is a switch statement
|
|
||||||
virtual bool IsSwitch() const;
|
|
||||||
/// @returns true if this is an variable statement
|
|
||||||
virtual bool IsVariableDecl() const;
|
|
||||||
|
|
||||||
/// @returns the human readable name for the statement type.
|
/// @returns the human readable name for the statement type.
|
||||||
const char* Name() const;
|
const char* Name() const;
|
||||||
|
|
||||||
/// @returns the statement as a const assign statement
|
|
||||||
const AssignmentStatement* AsAssign() const;
|
|
||||||
/// @returns the statement as a const block statement
|
|
||||||
const BlockStatement* AsBlock() const;
|
|
||||||
/// @returns the statement as a const break statement
|
|
||||||
const BreakStatement* AsBreak() const;
|
|
||||||
/// @returns the statement as a const call statement
|
|
||||||
const CallStatement* AsCall() const;
|
|
||||||
/// @returns the statement as a const case statement
|
|
||||||
const CaseStatement* AsCase() const;
|
|
||||||
/// @returns the statement as a const continue statement
|
|
||||||
const ContinueStatement* AsContinue() const;
|
|
||||||
/// @returns the statement as a const discard statement
|
|
||||||
const DiscardStatement* AsDiscard() const;
|
|
||||||
/// @returns the statement as a const else statement
|
|
||||||
const ElseStatement* AsElse() const;
|
|
||||||
/// @returns the statement as a const fallthrough statement
|
|
||||||
const FallthroughStatement* AsFallthrough() const;
|
|
||||||
/// @returns the statement as a const if statement
|
|
||||||
const IfStatement* AsIf() const;
|
|
||||||
/// @returns the statement as a const loop statement
|
|
||||||
const LoopStatement* AsLoop() const;
|
|
||||||
/// @returns the statement as a const return statement
|
|
||||||
const ReturnStatement* AsReturn() const;
|
|
||||||
/// @returns the statement as a const switch statement
|
|
||||||
const SwitchStatement* AsSwitch() const;
|
|
||||||
/// @returns the statement as a const variable statement
|
|
||||||
const VariableDeclStatement* AsVariableDecl() const;
|
|
||||||
|
|
||||||
/// @returns the statement as an assign statement
|
|
||||||
AssignmentStatement* AsAssign();
|
|
||||||
/// @returns the statement as a block statement
|
|
||||||
BlockStatement* AsBlock();
|
|
||||||
/// @returns the statement as a break statement
|
|
||||||
BreakStatement* AsBreak();
|
|
||||||
/// @returns the statement as a call statement
|
|
||||||
CallStatement* AsCall();
|
|
||||||
/// @returns the statement as a case statement
|
|
||||||
CaseStatement* AsCase();
|
|
||||||
/// @returns the statement as a continue statement
|
|
||||||
ContinueStatement* AsContinue();
|
|
||||||
/// @returns the statement as a discard statement
|
|
||||||
DiscardStatement* AsDiscard();
|
|
||||||
/// @returns the statement as a else statement
|
|
||||||
ElseStatement* AsElse();
|
|
||||||
/// @returns the statement as a fallthrough statement
|
|
||||||
FallthroughStatement* AsFallthrough();
|
|
||||||
/// @returns the statement as a if statement
|
|
||||||
IfStatement* AsIf();
|
|
||||||
/// @returns the statement as a loop statement
|
|
||||||
LoopStatement* AsLoop();
|
|
||||||
/// @returns the statement as a return statement
|
|
||||||
ReturnStatement* AsReturn();
|
|
||||||
/// @returns the statement as a switch statement
|
|
||||||
SwitchStatement* AsSwitch();
|
|
||||||
/// @returns the statement as an variable statement
|
|
||||||
VariableDeclStatement* AsVariableDecl();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// Constructor
|
/// Constructor
|
||||||
Statement();
|
Statement();
|
||||||
|
|
|
@ -29,10 +29,6 @@ SwitchStatement::SwitchStatement(const Source& source,
|
||||||
CaseStatementList body)
|
CaseStatementList body)
|
||||||
: Base(source), condition_(condition), body_(body) {}
|
: Base(source), condition_(condition), body_(body) {}
|
||||||
|
|
||||||
bool SwitchStatement::IsSwitch() const {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
SwitchStatement::SwitchStatement(SwitchStatement&&) = default;
|
SwitchStatement::SwitchStatement(SwitchStatement&&) = default;
|
||||||
|
|
||||||
SwitchStatement::~SwitchStatement() = default;
|
SwitchStatement::~SwitchStatement() = default;
|
||||||
|
|
|
@ -60,9 +60,6 @@ class SwitchStatement : public Castable<SwitchStatement, Statement> {
|
||||||
/// @returns the Switch body
|
/// @returns the Switch body
|
||||||
const CaseStatementList& body() const { return body_; }
|
const CaseStatementList& body() const { return body_; }
|
||||||
|
|
||||||
/// @returns true if this is a switch statement
|
|
||||||
bool IsSwitch() const override;
|
|
||||||
|
|
||||||
/// @returns true if the node is valid
|
/// @returns true if the node is valid
|
||||||
bool IsValid() const override;
|
bool IsValid() const override;
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ TEST_F(SwitchStatementTest, Creation_WithSource) {
|
||||||
|
|
||||||
TEST_F(SwitchStatementTest, IsSwitch) {
|
TEST_F(SwitchStatementTest, IsSwitch) {
|
||||||
SwitchStatement stmt;
|
SwitchStatement stmt;
|
||||||
EXPECT_TRUE(stmt.IsSwitch());
|
EXPECT_TRUE(stmt.Is<SwitchStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(SwitchStatementTest, IsValid) {
|
TEST_F(SwitchStatementTest, IsValid) {
|
||||||
|
|
|
@ -30,10 +30,6 @@ VariableDeclStatement::VariableDeclStatement(VariableDeclStatement&&) = default;
|
||||||
|
|
||||||
VariableDeclStatement::~VariableDeclStatement() = default;
|
VariableDeclStatement::~VariableDeclStatement() = default;
|
||||||
|
|
||||||
bool VariableDeclStatement::IsVariableDecl() const {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool VariableDeclStatement::IsValid() const {
|
bool VariableDeclStatement::IsValid() const {
|
||||||
return variable_ != nullptr && variable_->IsValid();
|
return variable_ != nullptr && variable_->IsValid();
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,9 +48,6 @@ class VariableDeclStatement
|
||||||
/// @returns the variable
|
/// @returns the variable
|
||||||
Variable* variable() const { return variable_; }
|
Variable* variable() const { return variable_; }
|
||||||
|
|
||||||
/// @returns true if this is an variable statement
|
|
||||||
bool IsVariableDecl() const override;
|
|
||||||
|
|
||||||
/// @returns true if the node is valid
|
/// @returns true if the node is valid
|
||||||
bool IsValid() const override;
|
bool IsValid() const override;
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@ TEST_F(VariableDeclStatementTest, Creation_WithSource) {
|
||||||
|
|
||||||
TEST_F(VariableDeclStatementTest, IsVariableDecl) {
|
TEST_F(VariableDeclStatementTest, IsVariableDecl) {
|
||||||
VariableDeclStatement s;
|
VariableDeclStatement s;
|
||||||
EXPECT_TRUE(s.IsVariableDecl());
|
EXPECT_TRUE(s.Is<VariableDeclStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(VariableDeclStatementTest, IsValid) {
|
TEST_F(VariableDeclStatementTest, IsValid) {
|
||||||
|
|
|
@ -561,8 +561,8 @@ void FunctionEmitter::PushGuard(const std::string& guard_name,
|
||||||
const auto& top = statements_stack_.back();
|
const auto& top = statements_stack_.back();
|
||||||
auto* cond = create<ast::IdentifierExpression>(guard_name);
|
auto* cond = create<ast::IdentifierExpression>(guard_name);
|
||||||
auto* body = create<ast::BlockStatement>();
|
auto* body = create<ast::BlockStatement>();
|
||||||
auto* const guard_stmt =
|
auto* const guard_stmt = AddStatement(create<ast::IfStatement>(cond, body))
|
||||||
AddStatement(create<ast::IfStatement>(cond, body))->AsIf();
|
->As<ast::IfStatement>();
|
||||||
PushNewStatementBlock(top.construct_, end_id,
|
PushNewStatementBlock(top.construct_, end_id,
|
||||||
[guard_stmt](StatementBlock* s) {
|
[guard_stmt](StatementBlock* s) {
|
||||||
guard_stmt->set_body(s->statements_);
|
guard_stmt->set_body(s->statements_);
|
||||||
|
@ -574,8 +574,8 @@ void FunctionEmitter::PushTrueGuard(uint32_t end_id) {
|
||||||
const auto& top = statements_stack_.back();
|
const auto& top = statements_stack_.back();
|
||||||
auto* cond = MakeTrue();
|
auto* cond = MakeTrue();
|
||||||
auto* body = create<ast::BlockStatement>();
|
auto* body = create<ast::BlockStatement>();
|
||||||
auto* const guard_stmt =
|
auto* const guard_stmt = AddStatement(create<ast::IfStatement>(cond, body))
|
||||||
AddStatement(create<ast::IfStatement>(cond, body))->AsIf();
|
->As<ast::IfStatement>();
|
||||||
guard_stmt->set_condition(MakeTrue());
|
guard_stmt->set_condition(MakeTrue());
|
||||||
PushNewStatementBlock(top.construct_, end_id,
|
PushNewStatementBlock(top.construct_, end_id,
|
||||||
[guard_stmt](StatementBlock* s) {
|
[guard_stmt](StatementBlock* s) {
|
||||||
|
@ -2023,8 +2023,8 @@ bool FunctionEmitter::EmitIfStart(const BlockInfo& block_info) {
|
||||||
block_info.basic_block->terminator()->GetSingleWordInOperand(0);
|
block_info.basic_block->terminator()->GetSingleWordInOperand(0);
|
||||||
auto* cond = MakeExpression(condition_id).expr;
|
auto* cond = MakeExpression(condition_id).expr;
|
||||||
auto* body = create<ast::BlockStatement>();
|
auto* body = create<ast::BlockStatement>();
|
||||||
auto* const if_stmt =
|
auto* const if_stmt = AddStatement(create<ast::IfStatement>(cond, body))
|
||||||
AddStatement(create<ast::IfStatement>(cond, body))->AsIf();
|
->As<ast::IfStatement>();
|
||||||
|
|
||||||
// Generate the code for the condition.
|
// Generate the code for the condition.
|
||||||
|
|
||||||
|
@ -2137,7 +2137,7 @@ bool FunctionEmitter::EmitSwitchStart(const BlockInfo& block_info) {
|
||||||
const auto* branch = block_info.basic_block->terminator();
|
const auto* branch = block_info.basic_block->terminator();
|
||||||
|
|
||||||
auto* const switch_stmt =
|
auto* const switch_stmt =
|
||||||
AddStatement(create<ast::SwitchStatement>())->AsSwitch();
|
AddStatement(create<ast::SwitchStatement>())->As<ast::SwitchStatement>();
|
||||||
const auto selector_id = branch->GetSingleWordInOperand(0);
|
const auto selector_id = branch->GetSingleWordInOperand(0);
|
||||||
// Generate the code for the selector.
|
// Generate the code for the selector.
|
||||||
auto selector = MakeExpression(selector_id);
|
auto selector = MakeExpression(selector_id);
|
||||||
|
@ -2255,7 +2255,7 @@ bool FunctionEmitter::EmitLoopStart(const Construct* construct) {
|
||||||
auto* loop =
|
auto* loop =
|
||||||
AddStatement(create<ast::LoopStatement>(create<ast::BlockStatement>(),
|
AddStatement(create<ast::LoopStatement>(create<ast::BlockStatement>(),
|
||||||
create<ast::BlockStatement>()))
|
create<ast::BlockStatement>()))
|
||||||
->AsLoop();
|
->As<ast::LoopStatement>();
|
||||||
PushNewStatementBlock(
|
PushNewStatementBlock(
|
||||||
construct, construct->end_id,
|
construct, construct->end_id,
|
||||||
[loop](StatementBlock* s) { loop->set_body(s->statements_); });
|
[loop](StatementBlock* s) { loop->set_body(s->statements_); });
|
||||||
|
@ -2266,11 +2266,11 @@ bool FunctionEmitter::EmitContinuingStart(const Construct* construct) {
|
||||||
// A continue construct has the same depth as its associated loop
|
// A continue construct has the same depth as its associated loop
|
||||||
// construct. Start a continue construct.
|
// construct. Start a continue construct.
|
||||||
auto* loop_candidate = LastStatement();
|
auto* loop_candidate = LastStatement();
|
||||||
if (!loop_candidate->IsLoop()) {
|
if (!loop_candidate->Is<ast::LoopStatement>()) {
|
||||||
return Fail() << "internal error: starting continue construct, "
|
return Fail() << "internal error: starting continue construct, "
|
||||||
"expected loop on top of stack";
|
"expected loop on top of stack";
|
||||||
}
|
}
|
||||||
auto* loop = loop_candidate->AsLoop();
|
auto* loop = loop_candidate->As<ast::LoopStatement>();
|
||||||
PushNewStatementBlock(
|
PushNewStatementBlock(
|
||||||
construct, construct->end_id,
|
construct, construct->end_id,
|
||||||
[loop](StatementBlock* s) { loop->set_continuing(s->statements_); });
|
[loop](StatementBlock* s) { loop->set_continuing(s->statements_); });
|
||||||
|
|
|
@ -27,16 +27,21 @@
|
||||||
#include "src/ast/access_control.h"
|
#include "src/ast/access_control.h"
|
||||||
#include "src/ast/array_decoration.h"
|
#include "src/ast/array_decoration.h"
|
||||||
#include "src/ast/assignment_statement.h"
|
#include "src/ast/assignment_statement.h"
|
||||||
|
#include "src/ast/break_statement.h"
|
||||||
#include "src/ast/builtin.h"
|
#include "src/ast/builtin.h"
|
||||||
#include "src/ast/call_statement.h"
|
#include "src/ast/call_statement.h"
|
||||||
#include "src/ast/case_statement.h"
|
#include "src/ast/case_statement.h"
|
||||||
#include "src/ast/constructor_expression.h"
|
#include "src/ast/constructor_expression.h"
|
||||||
|
#include "src/ast/continue_statement.h"
|
||||||
#include "src/ast/else_statement.h"
|
#include "src/ast/else_statement.h"
|
||||||
|
#include "src/ast/switch_statement.h"
|
||||||
#include "src/ast/function.h"
|
#include "src/ast/function.h"
|
||||||
|
#include "src/ast/if_statement.h"
|
||||||
#include "src/ast/literal.h"
|
#include "src/ast/literal.h"
|
||||||
#include "src/ast/loop_statement.h"
|
#include "src/ast/loop_statement.h"
|
||||||
#include "src/ast/module.h"
|
#include "src/ast/module.h"
|
||||||
#include "src/ast/pipeline_stage.h"
|
#include "src/ast/pipeline_stage.h"
|
||||||
|
#include "src/ast/return_statement.h"
|
||||||
#include "src/ast/statement.h"
|
#include "src/ast/statement.h"
|
||||||
#include "src/ast/storage_class.h"
|
#include "src/ast/storage_class.h"
|
||||||
#include "src/ast/struct.h"
|
#include "src/ast/struct.h"
|
||||||
|
@ -44,10 +49,11 @@
|
||||||
#include "src/ast/struct_member.h"
|
#include "src/ast/struct_member.h"
|
||||||
#include "src/ast/struct_member_decoration.h"
|
#include "src/ast/struct_member_decoration.h"
|
||||||
#include "src/ast/type/storage_texture_type.h"
|
#include "src/ast/type/storage_texture_type.h"
|
||||||
|
#include "src/ast/type/struct_type.h"
|
||||||
#include "src/ast/type/texture_type.h"
|
#include "src/ast/type/texture_type.h"
|
||||||
#include "src/ast/type/type.h"
|
#include "src/ast/type/type.h"
|
||||||
#include "src/ast/type/struct_type.h"
|
|
||||||
#include "src/ast/variable.h"
|
#include "src/ast/variable.h"
|
||||||
|
#include "src/ast/variable_decl_statement.h"
|
||||||
#include "src/ast/variable_decoration.h"
|
#include "src/ast/variable_decoration.h"
|
||||||
#include "src/context.h"
|
#include "src/context.h"
|
||||||
#include "src/diagnostic/diagnostic.h"
|
#include "src/diagnostic/diagnostic.h"
|
||||||
|
|
|
@ -36,7 +36,7 @@ TEST_F(ParserImplTest, AssignmentStmt_Parses_ToVariable) {
|
||||||
EXPECT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(e.value, nullptr);
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
|
||||||
ASSERT_TRUE(e->IsAssign());
|
ASSERT_TRUE(e->Is<ast::AssignmentStatement>());
|
||||||
ASSERT_NE(e->lhs(), nullptr);
|
ASSERT_NE(e->lhs(), nullptr);
|
||||||
ASSERT_NE(e->rhs(), nullptr);
|
ASSERT_NE(e->rhs(), nullptr);
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ TEST_F(ParserImplTest, AssignmentStmt_Parses_ToMember) {
|
||||||
EXPECT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(e.value, nullptr);
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
|
||||||
ASSERT_TRUE(e->IsAssign());
|
ASSERT_TRUE(e->Is<ast::AssignmentStatement>());
|
||||||
ASSERT_NE(e->lhs(), nullptr);
|
ASSERT_NE(e->lhs(), nullptr);
|
||||||
ASSERT_NE(e->rhs(), nullptr);
|
ASSERT_NE(e->rhs(), nullptr);
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
#include "src/ast/discard_statement.h"
|
||||||
#include "src/reader/wgsl/parser_impl.h"
|
#include "src/reader/wgsl/parser_impl.h"
|
||||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||||
|
|
||||||
|
@ -30,8 +31,8 @@ TEST_F(ParserImplTest, BodyStmt) {
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_FALSE(e.errored);
|
ASSERT_FALSE(e.errored);
|
||||||
ASSERT_EQ(e->size(), 2u);
|
ASSERT_EQ(e->size(), 2u);
|
||||||
EXPECT_TRUE(e->get(0)->IsDiscard());
|
EXPECT_TRUE(e->get(0)->Is<ast::DiscardStatement>());
|
||||||
EXPECT_TRUE(e->get(1)->IsReturn());
|
EXPECT_TRUE(e->get(1)->Is<ast::ReturnStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, BodyStmt_Empty) {
|
TEST_F(ParserImplTest, BodyStmt_Empty) {
|
||||||
|
|
|
@ -28,7 +28,7 @@ TEST_F(ParserImplTest, BreakStmt) {
|
||||||
EXPECT_FALSE(e.errored);
|
EXPECT_FALSE(e.errored);
|
||||||
EXPECT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(e.value, nullptr);
|
ASSERT_NE(e.value, nullptr);
|
||||||
ASSERT_TRUE(e->IsBreak());
|
ASSERT_TRUE(e->Is<ast::BreakStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -32,8 +32,8 @@ TEST_F(ParserImplTest, Statement_Call) {
|
||||||
EXPECT_TRUE(e.matched);
|
EXPECT_TRUE(e.matched);
|
||||||
EXPECT_FALSE(e.errored);
|
EXPECT_FALSE(e.errored);
|
||||||
|
|
||||||
ASSERT_TRUE(e->IsCall());
|
ASSERT_TRUE(e->Is<ast::CallStatement>());
|
||||||
auto* c = e->AsCall()->expr();
|
auto* c = e->As<ast::CallStatement>()->expr();
|
||||||
|
|
||||||
ASSERT_TRUE(c->func()->IsIdentifier());
|
ASSERT_TRUE(c->func()->IsIdentifier());
|
||||||
auto* func = c->func()->AsIdentifier();
|
auto* func = c->func()->AsIdentifier();
|
||||||
|
@ -50,8 +50,8 @@ TEST_F(ParserImplTest, Statement_Call_WithParams) {
|
||||||
EXPECT_TRUE(e.matched);
|
EXPECT_TRUE(e.matched);
|
||||||
EXPECT_FALSE(e.errored);
|
EXPECT_FALSE(e.errored);
|
||||||
|
|
||||||
ASSERT_TRUE(e->IsCall());
|
ASSERT_TRUE(e->Is<ast::CallStatement>());
|
||||||
auto* c = e->AsCall()->expr();
|
auto* c = e->As<ast::CallStatement>()->expr();
|
||||||
|
|
||||||
ASSERT_TRUE(c->func()->IsIdentifier());
|
ASSERT_TRUE(c->func()->IsIdentifier());
|
||||||
auto* func = c->func()->AsIdentifier();
|
auto* func = c->func()->AsIdentifier();
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
#include "src/ast/fallthrough_statement.h"
|
||||||
#include "src/reader/wgsl/parser_impl.h"
|
#include "src/reader/wgsl/parser_impl.h"
|
||||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||||
|
|
||||||
|
@ -40,8 +41,8 @@ TEST_F(ParserImplTest, CaseBody_Statements) {
|
||||||
EXPECT_FALSE(e.errored);
|
EXPECT_FALSE(e.errored);
|
||||||
EXPECT_TRUE(e.matched);
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_EQ(e->size(), 2u);
|
ASSERT_EQ(e->size(), 2u);
|
||||||
EXPECT_TRUE(e->get(0)->IsVariableDecl());
|
EXPECT_TRUE(e->get(0)->Is<ast::VariableDeclStatement>());
|
||||||
EXPECT_TRUE(e->get(1)->IsAssign());
|
EXPECT_TRUE(e->get(1)->Is<ast::AssignmentStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, CaseBody_InvalidStatement) {
|
TEST_F(ParserImplTest, CaseBody_InvalidStatement) {
|
||||||
|
@ -60,7 +61,7 @@ TEST_F(ParserImplTest, CaseBody_Fallthrough) {
|
||||||
EXPECT_FALSE(e.errored);
|
EXPECT_FALSE(e.errored);
|
||||||
EXPECT_TRUE(e.matched);
|
EXPECT_TRUE(e.matched);
|
||||||
ASSERT_EQ(e->size(), 1u);
|
ASSERT_EQ(e->size(), 1u);
|
||||||
EXPECT_TRUE(e->get(0)->IsFallthrough());
|
EXPECT_TRUE(e->get(0)->Is<ast::FallthroughStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, CaseBody_Fallthrough_MissingSemicolon) {
|
TEST_F(ParserImplTest, CaseBody_Fallthrough_MissingSemicolon) {
|
||||||
|
|
|
@ -28,7 +28,7 @@ TEST_F(ParserImplTest, ContinueStmt) {
|
||||||
EXPECT_FALSE(e.errored);
|
EXPECT_FALSE(e.errored);
|
||||||
EXPECT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(e.value, nullptr);
|
ASSERT_NE(e.value, nullptr);
|
||||||
ASSERT_TRUE(e->IsContinue());
|
ASSERT_TRUE(e->Is<ast::ContinueStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
#include "src/ast/discard_statement.h"
|
||||||
#include "src/reader/wgsl/parser_impl.h"
|
#include "src/reader/wgsl/parser_impl.h"
|
||||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||||
|
|
||||||
|
@ -28,7 +29,7 @@ TEST_F(ParserImplTest, ContinuingStmt) {
|
||||||
EXPECT_FALSE(e.errored);
|
EXPECT_FALSE(e.errored);
|
||||||
EXPECT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_EQ(e->size(), 1u);
|
ASSERT_EQ(e->size(), 1u);
|
||||||
ASSERT_TRUE(e->get(0)->IsDiscard());
|
ASSERT_TRUE(e->get(0)->Is<ast::DiscardStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, ContinuingStmt_InvalidBody) {
|
TEST_F(ParserImplTest, ContinuingStmt_InvalidBody) {
|
||||||
|
|
|
@ -29,7 +29,7 @@ TEST_F(ParserImplTest, ElseStmt) {
|
||||||
EXPECT_FALSE(e.errored);
|
EXPECT_FALSE(e.errored);
|
||||||
EXPECT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(e.value, nullptr);
|
ASSERT_NE(e.value, nullptr);
|
||||||
ASSERT_TRUE(e->IsElse());
|
ASSERT_TRUE(e->Is<ast::ElseStatement>());
|
||||||
ASSERT_EQ(e->condition(), nullptr);
|
ASSERT_EQ(e->condition(), nullptr);
|
||||||
EXPECT_EQ(e->body()->size(), 2u);
|
EXPECT_EQ(e->body()->size(), 2u);
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ TEST_F(ParserImplTest, ElseIfStmt) {
|
||||||
EXPECT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_EQ(e.value.size(), 1u);
|
ASSERT_EQ(e.value.size(), 1u);
|
||||||
|
|
||||||
ASSERT_TRUE(e.value[0]->IsElse());
|
ASSERT_TRUE(e.value[0]->Is<ast::ElseStatement>());
|
||||||
ASSERT_NE(e.value[0]->condition(), nullptr);
|
ASSERT_NE(e.value[0]->condition(), nullptr);
|
||||||
ASSERT_TRUE(e.value[0]->condition()->IsBinary());
|
ASSERT_TRUE(e.value[0]->condition()->IsBinary());
|
||||||
EXPECT_EQ(e.value[0]->body()->size(), 2u);
|
EXPECT_EQ(e.value[0]->body()->size(), 2u);
|
||||||
|
@ -44,12 +44,12 @@ TEST_F(ParserImplTest, ElseIfStmt_Multiple) {
|
||||||
EXPECT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_EQ(e.value.size(), 2u);
|
ASSERT_EQ(e.value.size(), 2u);
|
||||||
|
|
||||||
ASSERT_TRUE(e.value[0]->IsElse());
|
ASSERT_TRUE(e.value[0]->Is<ast::ElseStatement>());
|
||||||
ASSERT_NE(e.value[0]->condition(), nullptr);
|
ASSERT_NE(e.value[0]->condition(), nullptr);
|
||||||
ASSERT_TRUE(e.value[0]->condition()->IsBinary());
|
ASSERT_TRUE(e.value[0]->condition()->IsBinary());
|
||||||
EXPECT_EQ(e.value[0]->body()->size(), 2u);
|
EXPECT_EQ(e.value[0]->body()->size(), 2u);
|
||||||
|
|
||||||
ASSERT_TRUE(e.value[1]->IsElse());
|
ASSERT_TRUE(e.value[1]->Is<ast::ElseStatement>());
|
||||||
ASSERT_NE(e.value[1]->condition(), nullptr);
|
ASSERT_NE(e.value[1]->condition(), nullptr);
|
||||||
ASSERT_TRUE(e.value[1]->condition()->IsIdentifier());
|
ASSERT_TRUE(e.value[1]->condition()->IsIdentifier());
|
||||||
EXPECT_EQ(e.value[1]->body()->size(), 1u);
|
EXPECT_EQ(e.value[1]->body()->size(), 1u);
|
||||||
|
|
|
@ -50,7 +50,7 @@ TEST_F(ParserImplTest, FunctionDecl) {
|
||||||
|
|
||||||
auto* body = f->body();
|
auto* body = f->body();
|
||||||
ASSERT_EQ(body->size(), 1u);
|
ASSERT_EQ(body->size(), 1u);
|
||||||
EXPECT_TRUE(body->get(0)->IsReturn());
|
EXPECT_TRUE(body->get(0)->Is<ast::ReturnStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, FunctionDecl_DecorationList) {
|
TEST_F(ParserImplTest, FunctionDecl_DecorationList) {
|
||||||
|
@ -86,7 +86,7 @@ TEST_F(ParserImplTest, FunctionDecl_DecorationList) {
|
||||||
|
|
||||||
auto* body = f->body();
|
auto* body = f->body();
|
||||||
ASSERT_EQ(body->size(), 1u);
|
ASSERT_EQ(body->size(), 1u);
|
||||||
EXPECT_TRUE(body->get(0)->IsReturn());
|
EXPECT_TRUE(body->get(0)->Is<ast::ReturnStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, FunctionDecl_DecorationList_MultipleEntries) {
|
TEST_F(ParserImplTest, FunctionDecl_DecorationList_MultipleEntries) {
|
||||||
|
@ -130,7 +130,7 @@ fn main() -> void { return; })");
|
||||||
|
|
||||||
auto* body = f->body();
|
auto* body = f->body();
|
||||||
ASSERT_EQ(body->size(), 1u);
|
ASSERT_EQ(body->size(), 1u);
|
||||||
EXPECT_TRUE(body->get(0)->IsReturn());
|
EXPECT_TRUE(body->get(0)->Is<ast::ReturnStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, FunctionDecl_DecorationList_MultipleLists) {
|
TEST_F(ParserImplTest, FunctionDecl_DecorationList_MultipleLists) {
|
||||||
|
@ -175,7 +175,7 @@ fn main() -> void { return; })");
|
||||||
|
|
||||||
auto* body = f->body();
|
auto* body = f->body();
|
||||||
ASSERT_EQ(body->size(), 1u);
|
ASSERT_EQ(body->size(), 1u);
|
||||||
EXPECT_TRUE(body->get(0)->IsReturn());
|
EXPECT_TRUE(body->get(0)->Is<ast::ReturnStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, FunctionDecl_InvalidHeader) {
|
TEST_F(ParserImplTest, FunctionDecl_InvalidHeader) {
|
||||||
|
|
|
@ -31,7 +31,7 @@ TEST_F(ParserImplTest, IfStmt) {
|
||||||
EXPECT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(e.value, nullptr);
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
|
||||||
ASSERT_TRUE(e->IsIf());
|
ASSERT_TRUE(e->Is<ast::IfStatement>());
|
||||||
ASSERT_NE(e->condition(), nullptr);
|
ASSERT_NE(e->condition(), nullptr);
|
||||||
ASSERT_TRUE(e->condition()->IsBinary());
|
ASSERT_TRUE(e->condition()->IsBinary());
|
||||||
EXPECT_EQ(e->body()->size(), 2u);
|
EXPECT_EQ(e->body()->size(), 2u);
|
||||||
|
@ -46,7 +46,7 @@ TEST_F(ParserImplTest, IfStmt_WithElse) {
|
||||||
EXPECT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(e.value, nullptr);
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
|
||||||
ASSERT_TRUE(e->IsIf());
|
ASSERT_TRUE(e->Is<ast::IfStatement>());
|
||||||
ASSERT_NE(e->condition(), nullptr);
|
ASSERT_NE(e->condition(), nullptr);
|
||||||
ASSERT_TRUE(e->condition()->IsBinary());
|
ASSERT_TRUE(e->condition()->IsBinary());
|
||||||
EXPECT_EQ(e->body()->size(), 2u);
|
EXPECT_EQ(e->body()->size(), 2u);
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
#include "src/ast/discard_statement.h"
|
||||||
#include "src/reader/wgsl/parser_impl.h"
|
#include "src/reader/wgsl/parser_impl.h"
|
||||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||||
|
|
||||||
|
@ -30,7 +31,7 @@ TEST_F(ParserImplTest, LoopStmt_BodyNoContinuing) {
|
||||||
ASSERT_NE(e.value, nullptr);
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
|
||||||
ASSERT_EQ(e->body()->size(), 1u);
|
ASSERT_EQ(e->body()->size(), 1u);
|
||||||
EXPECT_TRUE(e->body()->get(0)->IsDiscard());
|
EXPECT_TRUE(e->body()->get(0)->Is<ast::DiscardStatement>());
|
||||||
|
|
||||||
EXPECT_EQ(e->continuing()->size(), 0u);
|
EXPECT_EQ(e->continuing()->size(), 0u);
|
||||||
}
|
}
|
||||||
|
@ -44,10 +45,10 @@ TEST_F(ParserImplTest, LoopStmt_BodyWithContinuing) {
|
||||||
ASSERT_NE(e.value, nullptr);
|
ASSERT_NE(e.value, nullptr);
|
||||||
|
|
||||||
ASSERT_EQ(e->body()->size(), 1u);
|
ASSERT_EQ(e->body()->size(), 1u);
|
||||||
EXPECT_TRUE(e->body()->get(0)->IsDiscard());
|
EXPECT_TRUE(e->body()->get(0)->Is<ast::DiscardStatement>());
|
||||||
|
|
||||||
EXPECT_EQ(e->continuing()->size(), 1u);
|
EXPECT_EQ(e->continuing()->size(), 1u);
|
||||||
EXPECT_TRUE(e->continuing()->get(0)->IsDiscard());
|
EXPECT_TRUE(e->continuing()->get(0)->Is<ast::DiscardStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, LoopStmt_NoBodyNoContinuing) {
|
TEST_F(ParserImplTest, LoopStmt_NoBodyNoContinuing) {
|
||||||
|
@ -70,7 +71,7 @@ TEST_F(ParserImplTest, LoopStmt_NoBodyWithContinuing) {
|
||||||
ASSERT_NE(e.value, nullptr);
|
ASSERT_NE(e.value, nullptr);
|
||||||
ASSERT_EQ(e->body()->size(), 0u);
|
ASSERT_EQ(e->body()->size(), 0u);
|
||||||
ASSERT_EQ(e->continuing()->size(), 1u);
|
ASSERT_EQ(e->continuing()->size(), 1u);
|
||||||
EXPECT_TRUE(e->continuing()->get(0)->IsDiscard());
|
EXPECT_TRUE(e->continuing()->get(0)->Is<ast::DiscardStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, LoopStmt_MissingBracketLeft) {
|
TEST_F(ParserImplTest, LoopStmt_MissingBracketLeft) {
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
#include "src/ast/discard_statement.h"
|
||||||
#include "src/ast/return_statement.h"
|
#include "src/ast/return_statement.h"
|
||||||
#include "src/ast/statement.h"
|
#include "src/ast/statement.h"
|
||||||
#include "src/reader/wgsl/parser_impl.h"
|
#include "src/reader/wgsl/parser_impl.h"
|
||||||
|
@ -29,7 +30,7 @@ TEST_F(ParserImplTest, Statement) {
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
EXPECT_TRUE(e.matched);
|
EXPECT_TRUE(e.matched);
|
||||||
EXPECT_FALSE(e.errored);
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_TRUE(e->IsReturn());
|
ASSERT_TRUE(e->Is<ast::ReturnStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Statement_Semicolon) {
|
TEST_F(ParserImplTest, Statement_Semicolon) {
|
||||||
|
@ -44,8 +45,8 @@ TEST_F(ParserImplTest, Statement_Return_NoValue) {
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
EXPECT_TRUE(e.matched);
|
EXPECT_TRUE(e.matched);
|
||||||
EXPECT_FALSE(e.errored);
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_TRUE(e->IsReturn());
|
ASSERT_TRUE(e->Is<ast::ReturnStatement>());
|
||||||
auto* ret = e->AsReturn();
|
auto* ret = e->As<ast::ReturnStatement>();
|
||||||
ASSERT_EQ(ret->value(), nullptr);
|
ASSERT_EQ(ret->value(), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,8 +57,8 @@ TEST_F(ParserImplTest, Statement_Return_Value) {
|
||||||
|
|
||||||
EXPECT_TRUE(e.matched);
|
EXPECT_TRUE(e.matched);
|
||||||
EXPECT_FALSE(e.errored);
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_TRUE(e->IsReturn());
|
ASSERT_TRUE(e->Is<ast::ReturnStatement>());
|
||||||
auto* ret = e->AsReturn();
|
auto* ret = e->As<ast::ReturnStatement>();
|
||||||
ASSERT_NE(ret->value(), nullptr);
|
ASSERT_NE(ret->value(), nullptr);
|
||||||
EXPECT_TRUE(ret->value()->IsBinary());
|
EXPECT_TRUE(ret->value()->IsBinary());
|
||||||
}
|
}
|
||||||
|
@ -88,7 +89,7 @@ TEST_F(ParserImplTest, Statement_If) {
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
EXPECT_TRUE(e.matched);
|
EXPECT_TRUE(e.matched);
|
||||||
EXPECT_FALSE(e.errored);
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_TRUE(e->IsIf());
|
ASSERT_TRUE(e->Is<ast::IfStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Statement_If_Invalid) {
|
TEST_F(ParserImplTest, Statement_If_Invalid) {
|
||||||
|
@ -107,7 +108,7 @@ TEST_F(ParserImplTest, Statement_Variable) {
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
EXPECT_TRUE(e.matched);
|
EXPECT_TRUE(e.matched);
|
||||||
EXPECT_FALSE(e.errored);
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_TRUE(e->IsVariableDecl());
|
ASSERT_TRUE(e->Is<ast::VariableDeclStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Statement_Variable_Invalid) {
|
TEST_F(ParserImplTest, Statement_Variable_Invalid) {
|
||||||
|
@ -136,7 +137,7 @@ TEST_F(ParserImplTest, Statement_Switch) {
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
EXPECT_TRUE(e.matched);
|
EXPECT_TRUE(e.matched);
|
||||||
EXPECT_FALSE(e.errored);
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_TRUE(e->IsSwitch());
|
ASSERT_TRUE(e->Is<ast::SwitchStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Statement_Switch_Invalid) {
|
TEST_F(ParserImplTest, Statement_Switch_Invalid) {
|
||||||
|
@ -155,7 +156,7 @@ TEST_F(ParserImplTest, Statement_Loop) {
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
EXPECT_TRUE(e.matched);
|
EXPECT_TRUE(e.matched);
|
||||||
EXPECT_FALSE(e.errored);
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_TRUE(e->IsLoop());
|
ASSERT_TRUE(e->Is<ast::LoopStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Statement_Loop_Invalid) {
|
TEST_F(ParserImplTest, Statement_Loop_Invalid) {
|
||||||
|
@ -174,7 +175,7 @@ TEST_F(ParserImplTest, Statement_Assignment) {
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
EXPECT_TRUE(e.matched);
|
EXPECT_TRUE(e.matched);
|
||||||
EXPECT_FALSE(e.errored);
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_TRUE(e->IsAssign());
|
ASSERT_TRUE(e->Is<ast::AssignmentStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Statement_Assignment_Invalid) {
|
TEST_F(ParserImplTest, Statement_Assignment_Invalid) {
|
||||||
|
@ -203,7 +204,7 @@ TEST_F(ParserImplTest, Statement_Break) {
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
EXPECT_TRUE(e.matched);
|
EXPECT_TRUE(e.matched);
|
||||||
EXPECT_FALSE(e.errored);
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_TRUE(e->IsBreak());
|
ASSERT_TRUE(e->Is<ast::BreakStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Statement_Break_MissingSemicolon) {
|
TEST_F(ParserImplTest, Statement_Break_MissingSemicolon) {
|
||||||
|
@ -222,7 +223,7 @@ TEST_F(ParserImplTest, Statement_Continue) {
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
EXPECT_TRUE(e.matched);
|
EXPECT_TRUE(e.matched);
|
||||||
EXPECT_FALSE(e.errored);
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_TRUE(e->IsContinue());
|
ASSERT_TRUE(e->Is<ast::ContinueStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Statement_Continue_MissingSemicolon) {
|
TEST_F(ParserImplTest, Statement_Continue_MissingSemicolon) {
|
||||||
|
@ -242,7 +243,7 @@ TEST_F(ParserImplTest, Statement_Discard) {
|
||||||
ASSERT_NE(e.value, nullptr);
|
ASSERT_NE(e.value, nullptr);
|
||||||
EXPECT_TRUE(e.matched);
|
EXPECT_TRUE(e.matched);
|
||||||
EXPECT_FALSE(e.errored);
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_TRUE(e->IsDiscard());
|
ASSERT_TRUE(e->Is<ast::DiscardStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Statement_Discard_MissingSemicolon) {
|
TEST_F(ParserImplTest, Statement_Discard_MissingSemicolon) {
|
||||||
|
@ -261,8 +262,9 @@ TEST_F(ParserImplTest, Statement_Body) {
|
||||||
ASSERT_FALSE(p->has_error()) << p->error();
|
ASSERT_FALSE(p->has_error()) << p->error();
|
||||||
EXPECT_TRUE(e.matched);
|
EXPECT_TRUE(e.matched);
|
||||||
EXPECT_FALSE(e.errored);
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_TRUE(e->IsBlock());
|
ASSERT_TRUE(e->Is<ast::BlockStatement>());
|
||||||
EXPECT_TRUE(e->AsBlock()->get(0)->IsVariableDecl());
|
EXPECT_TRUE(
|
||||||
|
e->As<ast::BlockStatement>()->get(0)->Is<ast::VariableDeclStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Statement_Body_Invalid) {
|
TEST_F(ParserImplTest, Statement_Body_Invalid) {
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
#include "src/ast/discard_statement.h"
|
||||||
#include "src/ast/statement.h"
|
#include "src/ast/statement.h"
|
||||||
#include "src/reader/wgsl/parser_impl.h"
|
#include "src/reader/wgsl/parser_impl.h"
|
||||||
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
#include "src/reader/wgsl/parser_impl_test_helper.h"
|
||||||
|
@ -28,8 +29,8 @@ TEST_F(ParserImplTest, Statements) {
|
||||||
EXPECT_FALSE(e.errored);
|
EXPECT_FALSE(e.errored);
|
||||||
EXPECT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_EQ(e->size(), 2u);
|
ASSERT_EQ(e->size(), 2u);
|
||||||
EXPECT_TRUE(e->get(0)->IsDiscard());
|
EXPECT_TRUE(e->get(0)->Is<ast::DiscardStatement>());
|
||||||
EXPECT_TRUE(e->get(1)->IsReturn());
|
EXPECT_TRUE(e->get(1)->Is<ast::ReturnStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, Statements_Empty) {
|
TEST_F(ParserImplTest, Statements_Empty) {
|
||||||
|
|
|
@ -29,10 +29,10 @@ TEST_F(ParserImplTest, SwitchBody_Case) {
|
||||||
EXPECT_TRUE(e.matched);
|
EXPECT_TRUE(e.matched);
|
||||||
EXPECT_FALSE(e.errored);
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_NE(e.value, nullptr);
|
ASSERT_NE(e.value, nullptr);
|
||||||
ASSERT_TRUE(e->IsCase());
|
ASSERT_TRUE(e->Is<ast::CaseStatement>());
|
||||||
EXPECT_FALSE(e->IsDefault());
|
EXPECT_FALSE(e->IsDefault());
|
||||||
ASSERT_EQ(e->body()->size(), 1u);
|
ASSERT_EQ(e->body()->size(), 1u);
|
||||||
EXPECT_TRUE(e->body()->get(0)->IsAssign());
|
EXPECT_TRUE(e->body()->get(0)->Is<ast::AssignmentStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, SwitchBody_Case_InvalidConstLiteral) {
|
TEST_F(ParserImplTest, SwitchBody_Case_InvalidConstLiteral) {
|
||||||
|
@ -112,10 +112,10 @@ TEST_F(ParserImplTest, SwitchBody_Default) {
|
||||||
EXPECT_TRUE(e.matched);
|
EXPECT_TRUE(e.matched);
|
||||||
EXPECT_FALSE(e.errored);
|
EXPECT_FALSE(e.errored);
|
||||||
ASSERT_NE(e.value, nullptr);
|
ASSERT_NE(e.value, nullptr);
|
||||||
ASSERT_TRUE(e->IsCase());
|
ASSERT_TRUE(e->Is<ast::CaseStatement>());
|
||||||
EXPECT_TRUE(e->IsDefault());
|
EXPECT_TRUE(e->IsDefault());
|
||||||
ASSERT_EQ(e->body()->size(), 1u);
|
ASSERT_EQ(e->body()->size(), 1u);
|
||||||
EXPECT_TRUE(e->body()->get(0)->IsAssign());
|
EXPECT_TRUE(e->body()->get(0)->Is<ast::AssignmentStatement>());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ParserImplTest, SwitchBody_Default_MissingColon) {
|
TEST_F(ParserImplTest, SwitchBody_Default_MissingColon) {
|
||||||
|
|
|
@ -33,7 +33,7 @@ TEST_F(ParserImplTest, SwitchStmt_WithoutDefault) {
|
||||||
EXPECT_FALSE(e.errored);
|
EXPECT_FALSE(e.errored);
|
||||||
EXPECT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(e.value, nullptr);
|
ASSERT_NE(e.value, nullptr);
|
||||||
ASSERT_TRUE(e->IsSwitch());
|
ASSERT_TRUE(e->Is<ast::SwitchStatement>());
|
||||||
ASSERT_EQ(e->body().size(), 2u);
|
ASSERT_EQ(e->body().size(), 2u);
|
||||||
EXPECT_FALSE(e->body()[0]->IsDefault());
|
EXPECT_FALSE(e->body()[0]->IsDefault());
|
||||||
EXPECT_FALSE(e->body()[1]->IsDefault());
|
EXPECT_FALSE(e->body()[1]->IsDefault());
|
||||||
|
@ -46,7 +46,7 @@ TEST_F(ParserImplTest, SwitchStmt_Empty) {
|
||||||
EXPECT_FALSE(e.errored);
|
EXPECT_FALSE(e.errored);
|
||||||
EXPECT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(e.value, nullptr);
|
ASSERT_NE(e.value, nullptr);
|
||||||
ASSERT_TRUE(e->IsSwitch());
|
ASSERT_TRUE(e->Is<ast::SwitchStatement>());
|
||||||
ASSERT_EQ(e->body().size(), 0u);
|
ASSERT_EQ(e->body().size(), 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ TEST_F(ParserImplTest, SwitchStmt_DefaultInMiddle) {
|
||||||
EXPECT_FALSE(e.errored);
|
EXPECT_FALSE(e.errored);
|
||||||
EXPECT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(e.value, nullptr);
|
ASSERT_NE(e.value, nullptr);
|
||||||
ASSERT_TRUE(e->IsSwitch());
|
ASSERT_TRUE(e->Is<ast::SwitchStatement>());
|
||||||
|
|
||||||
ASSERT_EQ(e->body().size(), 3u);
|
ASSERT_EQ(e->body().size(), 3u);
|
||||||
ASSERT_FALSE(e->body()[0]->IsDefault());
|
ASSERT_FALSE(e->body()[0]->IsDefault());
|
||||||
|
|
|
@ -30,7 +30,7 @@ TEST_F(ParserImplTest, VariableStmt_VariableDecl) {
|
||||||
EXPECT_FALSE(e.errored);
|
EXPECT_FALSE(e.errored);
|
||||||
EXPECT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(e.value, nullptr);
|
ASSERT_NE(e.value, nullptr);
|
||||||
ASSERT_TRUE(e->IsVariableDecl());
|
ASSERT_TRUE(e->Is<ast::VariableDeclStatement>());
|
||||||
ASSERT_NE(e->variable(), nullptr);
|
ASSERT_NE(e->variable(), nullptr);
|
||||||
EXPECT_EQ(e->variable()->name(), "a");
|
EXPECT_EQ(e->variable()->name(), "a");
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ TEST_F(ParserImplTest, VariableStmt_VariableDecl_WithInit) {
|
||||||
EXPECT_FALSE(e.errored);
|
EXPECT_FALSE(e.errored);
|
||||||
EXPECT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(e.value, nullptr);
|
ASSERT_NE(e.value, nullptr);
|
||||||
ASSERT_TRUE(e->IsVariableDecl());
|
ASSERT_TRUE(e->Is<ast::VariableDeclStatement>());
|
||||||
ASSERT_NE(e->variable(), nullptr);
|
ASSERT_NE(e->variable(), nullptr);
|
||||||
EXPECT_EQ(e->variable()->name(), "a");
|
EXPECT_EQ(e->variable()->name(), "a");
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ TEST_F(ParserImplTest, VariableStmt_Const) {
|
||||||
EXPECT_FALSE(e.errored);
|
EXPECT_FALSE(e.errored);
|
||||||
EXPECT_FALSE(p->has_error()) << p->error();
|
EXPECT_FALSE(p->has_error()) << p->error();
|
||||||
ASSERT_NE(e.value, nullptr);
|
ASSERT_NE(e.value, nullptr);
|
||||||
ASSERT_TRUE(e->IsVariableDecl());
|
ASSERT_TRUE(e->Is<ast::VariableDeclStatement>());
|
||||||
|
|
||||||
ASSERT_EQ(e->source().range.begin.line, 1u);
|
ASSERT_EQ(e->source().range.begin.line, 1u);
|
||||||
ASSERT_EQ(e->source().range.begin.column, 7u);
|
ASSERT_EQ(e->source().range.begin.column, 7u);
|
||||||
|
|
|
@ -21,10 +21,14 @@
|
||||||
#include "src/ast/binary_expression.h"
|
#include "src/ast/binary_expression.h"
|
||||||
#include "src/ast/bitcast_expression.h"
|
#include "src/ast/bitcast_expression.h"
|
||||||
#include "src/ast/block_statement.h"
|
#include "src/ast/block_statement.h"
|
||||||
|
#include "src/ast/break_statement.h"
|
||||||
#include "src/ast/call_expression.h"
|
#include "src/ast/call_expression.h"
|
||||||
#include "src/ast/call_statement.h"
|
#include "src/ast/call_statement.h"
|
||||||
#include "src/ast/case_statement.h"
|
#include "src/ast/case_statement.h"
|
||||||
|
#include "src/ast/continue_statement.h"
|
||||||
|
#include "src/ast/discard_statement.h"
|
||||||
#include "src/ast/else_statement.h"
|
#include "src/ast/else_statement.h"
|
||||||
|
#include "src/ast/fallthrough_statement.h"
|
||||||
#include "src/ast/if_statement.h"
|
#include "src/ast/if_statement.h"
|
||||||
#include "src/ast/loop_statement.h"
|
#include "src/ast/loop_statement.h"
|
||||||
#include "src/ast/member_accessor_expression.h"
|
#include "src/ast/member_accessor_expression.h"
|
||||||
|
@ -67,52 +71,47 @@ bool BoundArrayAccessorsTransform::Run() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BoundArrayAccessorsTransform::ProcessStatement(ast::Statement* stmt) {
|
bool BoundArrayAccessorsTransform::ProcessStatement(ast::Statement* stmt) {
|
||||||
if (stmt->IsAssign()) {
|
if (auto* as = stmt->As<ast::AssignmentStatement>()) {
|
||||||
auto* as = stmt->AsAssign();
|
|
||||||
return ProcessExpression(as->lhs()) && ProcessExpression(as->rhs());
|
return ProcessExpression(as->lhs()) && ProcessExpression(as->rhs());
|
||||||
} else if (stmt->IsBlock()) {
|
} else if (auto* block = stmt->As<ast::BlockStatement>()) {
|
||||||
for (auto* s : *(stmt->AsBlock())) {
|
for (auto* s : *block) {
|
||||||
if (!ProcessStatement(s)) {
|
if (!ProcessStatement(s)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (stmt->IsBreak()) {
|
} else if (stmt->Is<ast::BreakStatement>()) {
|
||||||
/* nop */
|
/* nop */
|
||||||
} else if (stmt->IsCall()) {
|
} else if (auto* call = stmt->As<ast::CallStatement>()) {
|
||||||
return ProcessExpression(stmt->AsCall()->expr());
|
return ProcessExpression(call->expr());
|
||||||
} else if (stmt->IsCase()) {
|
} else if (auto* kase = stmt->As<ast::CaseStatement>()) {
|
||||||
return ProcessStatement(stmt->AsCase()->body());
|
return ProcessStatement(kase->body());
|
||||||
} else if (stmt->IsContinue()) {
|
} else if (stmt->Is<ast::ContinueStatement>()) {
|
||||||
/* nop */
|
/* nop */
|
||||||
} else if (stmt->IsDiscard()) {
|
} else if (stmt->Is<ast::DiscardStatement>()) {
|
||||||
/* nop */
|
/* nop */
|
||||||
} else if (stmt->IsElse()) {
|
} else if (auto* e = stmt->As<ast::ElseStatement>()) {
|
||||||
auto* e = stmt->AsElse();
|
|
||||||
return ProcessExpression(e->condition()) && ProcessStatement(e->body());
|
return ProcessExpression(e->condition()) && ProcessStatement(e->body());
|
||||||
} else if (stmt->IsFallthrough()) {
|
} else if (stmt->Is<ast::FallthroughStatement>()) {
|
||||||
/* nop */
|
/* nop */
|
||||||
} else if (stmt->IsIf()) {
|
} else if (auto* i = stmt->As<ast::IfStatement>()) {
|
||||||
auto* e = stmt->AsIf();
|
if (!ProcessExpression(i->condition()) || !ProcessStatement(i->body())) {
|
||||||
if (!ProcessExpression(e->condition()) || !ProcessStatement(e->body())) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (auto* s : e->else_statements()) {
|
for (auto* s : i->else_statements()) {
|
||||||
if (!ProcessStatement(s)) {
|
if (!ProcessStatement(s)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (stmt->IsLoop()) {
|
} else if (auto* l = stmt->As<ast::LoopStatement>()) {
|
||||||
auto* l = stmt->AsLoop();
|
|
||||||
if (l->has_continuing() && !ProcessStatement(l->continuing())) {
|
if (l->has_continuing() && !ProcessStatement(l->continuing())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return ProcessStatement(l->body());
|
return ProcessStatement(l->body());
|
||||||
} else if (stmt->IsReturn()) {
|
} else if (auto* r = stmt->As<ast::ReturnStatement>()) {
|
||||||
if (stmt->AsReturn()->has_value()) {
|
if (r->has_value()) {
|
||||||
return ProcessExpression(stmt->AsReturn()->value());
|
return ProcessExpression(r->value());
|
||||||
}
|
}
|
||||||
} else if (stmt->IsSwitch()) {
|
} else if (auto* s = stmt->As<ast::SwitchStatement>()) {
|
||||||
auto* s = stmt->AsSwitch();
|
|
||||||
if (!ProcessExpression(s->condition())) {
|
if (!ProcessExpression(s->condition())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -122,8 +121,8 @@ bool BoundArrayAccessorsTransform::ProcessStatement(ast::Statement* stmt) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (stmt->IsVariableDecl()) {
|
} else if (auto* vd = stmt->As<ast::VariableDeclStatement>()) {
|
||||||
auto* v = stmt->AsVariableDecl()->variable();
|
auto* v = vd->variable();
|
||||||
if (v->has_constructor() && !ProcessExpression(v->constructor())) {
|
if (v->has_constructor() && !ProcessExpression(v->constructor())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,9 @@
|
||||||
#include "src/ast/call_statement.h"
|
#include "src/ast/call_statement.h"
|
||||||
#include "src/ast/case_statement.h"
|
#include "src/ast/case_statement.h"
|
||||||
#include "src/ast/continue_statement.h"
|
#include "src/ast/continue_statement.h"
|
||||||
|
#include "src/ast/discard_statement.h"
|
||||||
#include "src/ast/else_statement.h"
|
#include "src/ast/else_statement.h"
|
||||||
|
#include "src/ast/fallthrough_statement.h"
|
||||||
#include "src/ast/identifier_expression.h"
|
#include "src/ast/identifier_expression.h"
|
||||||
#include "src/ast/if_statement.h"
|
#include "src/ast/if_statement.h"
|
||||||
#include "src/ast/intrinsic.h"
|
#include "src/ast/intrinsic.h"
|
||||||
|
@ -178,11 +180,11 @@ bool TypeDeterminer::DetermineStatements(const ast::BlockStatement* stmts) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TypeDeterminer::DetermineVariableStorageClass(ast::Statement* stmt) {
|
bool TypeDeterminer::DetermineVariableStorageClass(ast::Statement* stmt) {
|
||||||
if (!stmt->IsVariableDecl()) {
|
if (!stmt->Is<ast::VariableDeclStatement>()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* var = stmt->AsVariableDecl()->variable();
|
auto* var = stmt->As<ast::VariableDeclStatement>()->variable();
|
||||||
// Nothing to do for const
|
// Nothing to do for const
|
||||||
if (var->is_const()) {
|
if (var->is_const()) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -203,39 +205,35 @@ bool TypeDeterminer::DetermineVariableStorageClass(ast::Statement* stmt) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TypeDeterminer::DetermineResultType(ast::Statement* stmt) {
|
bool TypeDeterminer::DetermineResultType(ast::Statement* stmt) {
|
||||||
if (stmt->IsAssign()) {
|
if (auto* a = stmt->As<ast::AssignmentStatement>()) {
|
||||||
auto* a = stmt->AsAssign();
|
|
||||||
return DetermineResultType(a->lhs()) && DetermineResultType(a->rhs());
|
return DetermineResultType(a->lhs()) && DetermineResultType(a->rhs());
|
||||||
}
|
}
|
||||||
if (stmt->IsBlock()) {
|
if (auto* b = stmt->As<ast::BlockStatement>()) {
|
||||||
return DetermineStatements(stmt->AsBlock());
|
return DetermineStatements(b);
|
||||||
}
|
}
|
||||||
if (stmt->IsBreak()) {
|
if (stmt->Is<ast::BreakStatement>()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (stmt->IsCall()) {
|
if (auto* c = stmt->As<ast::CallStatement>()) {
|
||||||
return DetermineResultType(stmt->AsCall()->expr());
|
return DetermineResultType(c->expr());
|
||||||
}
|
}
|
||||||
if (stmt->IsCase()) {
|
if (auto* c = stmt->As<ast::CaseStatement>()) {
|
||||||
auto* c = stmt->AsCase();
|
|
||||||
return DetermineStatements(c->body());
|
return DetermineStatements(c->body());
|
||||||
}
|
}
|
||||||
if (stmt->IsContinue()) {
|
if (stmt->Is<ast::ContinueStatement>()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (stmt->IsDiscard()) {
|
if (stmt->Is<ast::DiscardStatement>()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (stmt->IsElse()) {
|
if (auto* e = stmt->As<ast::ElseStatement>()) {
|
||||||
auto* e = stmt->AsElse();
|
|
||||||
return DetermineResultType(e->condition()) &&
|
return DetermineResultType(e->condition()) &&
|
||||||
DetermineStatements(e->body());
|
DetermineStatements(e->body());
|
||||||
}
|
}
|
||||||
if (stmt->IsFallthrough()) {
|
if (stmt->Is<ast::FallthroughStatement>()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (stmt->IsIf()) {
|
if (auto* i = stmt->As<ast::IfStatement>()) {
|
||||||
auto* i = stmt->AsIf();
|
|
||||||
if (!DetermineResultType(i->condition()) ||
|
if (!DetermineResultType(i->condition()) ||
|
||||||
!DetermineStatements(i->body())) {
|
!DetermineStatements(i->body())) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -248,17 +246,14 @@ bool TypeDeterminer::DetermineResultType(ast::Statement* stmt) {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (stmt->IsLoop()) {
|
if (auto* l = stmt->As<ast::LoopStatement>()) {
|
||||||
auto* l = stmt->AsLoop();
|
|
||||||
return DetermineStatements(l->body()) &&
|
return DetermineStatements(l->body()) &&
|
||||||
DetermineStatements(l->continuing());
|
DetermineStatements(l->continuing());
|
||||||
}
|
}
|
||||||
if (stmt->IsReturn()) {
|
if (auto* r = stmt->As<ast::ReturnStatement>()) {
|
||||||
auto* r = stmt->AsReturn();
|
|
||||||
return DetermineResultType(r->value());
|
return DetermineResultType(r->value());
|
||||||
}
|
}
|
||||||
if (stmt->IsSwitch()) {
|
if (auto* s = stmt->As<ast::SwitchStatement>()) {
|
||||||
auto* s = stmt->AsSwitch();
|
|
||||||
if (!DetermineResultType(s->condition())) {
|
if (!DetermineResultType(s->condition())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -269,8 +264,7 @@ bool TypeDeterminer::DetermineResultType(ast::Statement* stmt) {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (stmt->IsVariableDecl()) {
|
if (auto* v = stmt->As<ast::VariableDeclStatement>()) {
|
||||||
auto* v = stmt->AsVariableDecl();
|
|
||||||
variable_stack_.set(v->variable()->name(), v->variable());
|
variable_stack_.set(v->variable()->name(), v->variable());
|
||||||
return DetermineResultType(v->variable()->constructor());
|
return DetermineResultType(v->variable()->constructor());
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "src/ast/call_statement.h"
|
#include "src/ast/call_statement.h"
|
||||||
|
#include "src/ast/fallthrough_statement.h"
|
||||||
#include "src/ast/function.h"
|
#include "src/ast/function.h"
|
||||||
#include "src/ast/int_literal.h"
|
#include "src/ast/int_literal.h"
|
||||||
#include "src/ast/intrinsic.h"
|
#include "src/ast/intrinsic.h"
|
||||||
|
@ -208,7 +209,7 @@ bool ValidatorImpl::ValidateFunction(const ast::Function* func) {
|
||||||
|
|
||||||
if (!current_function_->return_type()->Is<ast::type::VoidType>()) {
|
if (!current_function_->return_type()->Is<ast::type::VoidType>()) {
|
||||||
if (!func->get_last_statement() ||
|
if (!func->get_last_statement() ||
|
||||||
!func->get_last_statement()->IsReturn()) {
|
!func->get_last_statement()->Is<ast::ReturnStatement>()) {
|
||||||
add_error(func->source(), "v-0002",
|
add_error(func->source(), "v-0002",
|
||||||
"non-void function must end with a return statement");
|
"non-void function must end with a return statement");
|
||||||
return false;
|
return false;
|
||||||
|
@ -284,29 +285,28 @@ bool ValidatorImpl::ValidateStatement(const ast::Statement* stmt) {
|
||||||
if (!stmt) {
|
if (!stmt) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (stmt->IsVariableDecl()) {
|
if (auto* v = stmt->As<ast::VariableDeclStatement>()) {
|
||||||
auto* v = stmt->AsVariableDecl();
|
|
||||||
bool constructor_valid =
|
bool constructor_valid =
|
||||||
v->variable()->has_constructor()
|
v->variable()->has_constructor()
|
||||||
? ValidateExpression(v->variable()->constructor())
|
? ValidateExpression(v->variable()->constructor())
|
||||||
: true;
|
: true;
|
||||||
|
|
||||||
return constructor_valid && ValidateDeclStatement(stmt->AsVariableDecl());
|
return constructor_valid && ValidateDeclStatement(v);
|
||||||
}
|
}
|
||||||
if (stmt->IsAssign()) {
|
if (auto* a = stmt->As<ast::AssignmentStatement>()) {
|
||||||
return ValidateAssign(stmt->AsAssign());
|
return ValidateAssign(a);
|
||||||
}
|
}
|
||||||
if (stmt->IsReturn()) {
|
if (auto* r = stmt->As<ast::ReturnStatement>()) {
|
||||||
return ValidateReturnStatement(stmt->AsReturn());
|
return ValidateReturnStatement(r);
|
||||||
}
|
}
|
||||||
if (stmt->IsCall()) {
|
if (auto* c = stmt->As<ast::CallStatement>()) {
|
||||||
return ValidateCallExpr(stmt->AsCall()->expr());
|
return ValidateCallExpr(c->expr());
|
||||||
}
|
}
|
||||||
if (stmt->IsSwitch()) {
|
if (auto* s = stmt->As<ast::SwitchStatement>()) {
|
||||||
return ValidateSwitch(stmt->AsSwitch());
|
return ValidateSwitch(s);
|
||||||
}
|
}
|
||||||
if (stmt->IsCase()) {
|
if (auto* c = stmt->As<ast::CaseStatement>()) {
|
||||||
return ValidateCase(stmt->AsCase());
|
return ValidateCase(c);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -368,8 +368,10 @@ bool ValidatorImpl::ValidateSwitch(const ast::SwitchStatement* s) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* last_clause = s->body().back();
|
auto* last_clause = s->body().back();
|
||||||
auto* last_stmt_of_last_clause = last_clause->AsCase()->body()->last();
|
auto* last_stmt_of_last_clause =
|
||||||
if (last_stmt_of_last_clause && last_stmt_of_last_clause->IsFallthrough()) {
|
last_clause->As<ast::CaseStatement>()->body()->last();
|
||||||
|
if (last_stmt_of_last_clause &&
|
||||||
|
last_stmt_of_last_clause->Is<ast::FallthroughStatement>()) {
|
||||||
add_error(last_stmt_of_last_clause->source(), "v-0028",
|
add_error(last_stmt_of_last_clause->source(), "v-0028",
|
||||||
"a fallthrough statement must not appear as "
|
"a fallthrough statement must not appear as "
|
||||||
"the last statement in last clause of a switch");
|
"the last statement in last clause of a switch");
|
||||||
|
|
|
@ -26,7 +26,9 @@
|
||||||
#include "src/ast/module.h"
|
#include "src/ast/module.h"
|
||||||
#include "src/ast/return_statement.h"
|
#include "src/ast/return_statement.h"
|
||||||
#include "src/ast/statement.h"
|
#include "src/ast/statement.h"
|
||||||
|
#include "src/ast/switch_statement.h"
|
||||||
#include "src/ast/variable.h"
|
#include "src/ast/variable.h"
|
||||||
|
#include "src/ast/variable_decl_statement.h"
|
||||||
#include "src/diagnostic/diagnostic.h"
|
#include "src/diagnostic/diagnostic.h"
|
||||||
#include "src/diagnostic/formatter.h"
|
#include "src/diagnostic/formatter.h"
|
||||||
#include "src/scope_stack.h"
|
#include "src/scope_stack.h"
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include "src/ast/case_statement.h"
|
#include "src/ast/case_statement.h"
|
||||||
#include "src/ast/decorated_variable.h"
|
#include "src/ast/decorated_variable.h"
|
||||||
#include "src/ast/else_statement.h"
|
#include "src/ast/else_statement.h"
|
||||||
|
#include "src/ast/fallthrough_statement.h"
|
||||||
#include "src/ast/float_literal.h"
|
#include "src/ast/float_literal.h"
|
||||||
#include "src/ast/identifier_expression.h"
|
#include "src/ast/identifier_expression.h"
|
||||||
#include "src/ast/if_statement.h"
|
#include "src/ast/if_statement.h"
|
||||||
|
@ -75,7 +76,8 @@ bool last_is_break_or_fallthrough(const ast::BlockStatement* stmts) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return stmts->last()->IsBreak() || stmts->last()->IsFallthrough();
|
return stmts->last()->Is<ast::BreakStatement>() ||
|
||||||
|
stmts->last()->Is<ast::FallthroughStatement>();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string get_buffer_name(ast::Expression* expr) {
|
std::string get_buffer_name(ast::Expression* expr) {
|
||||||
|
@ -1601,11 +1603,10 @@ bool GeneratorImpl::EmitLoop(std::ostream& out, ast::LoopStatement* stmt) {
|
||||||
// the for loop into the continuing scope. Then, the variable declarations
|
// the for loop into the continuing scope. Then, the variable declarations
|
||||||
// will be turned into assignments.
|
// will be turned into assignments.
|
||||||
for (auto* s : *stmt->body()) {
|
for (auto* s : *stmt->body()) {
|
||||||
if (!s->IsVariableDecl()) {
|
if (auto* v = s->As<ast::VariableDeclStatement>()) {
|
||||||
continue;
|
if (!EmitVariable(out, v->variable(), true)) {
|
||||||
}
|
return false;
|
||||||
if (!EmitVariable(out, s->AsVariableDecl()->variable(), true)) {
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1630,10 +1631,11 @@ bool GeneratorImpl::EmitLoop(std::ostream& out, ast::LoopStatement* stmt) {
|
||||||
for (auto* s : *(stmt->body())) {
|
for (auto* s : *(stmt->body())) {
|
||||||
// If we have a continuing block we've already emitted the variable
|
// If we have a continuing block we've already emitted the variable
|
||||||
// declaration before the loop, so treat it as an assignment.
|
// declaration before the loop, so treat it as an assignment.
|
||||||
if (s->IsVariableDecl() && stmt->has_continuing()) {
|
auto* decl = s->As<ast::VariableDeclStatement>();
|
||||||
|
if (decl != nullptr && stmt->has_continuing()) {
|
||||||
make_indent(out);
|
make_indent(out);
|
||||||
|
|
||||||
auto* var = s->AsVariableDecl()->variable();
|
auto* var = decl->variable();
|
||||||
|
|
||||||
std::ostringstream pre;
|
std::ostringstream pre;
|
||||||
std::ostringstream constructor_out;
|
std::ostringstream constructor_out;
|
||||||
|
@ -1963,51 +1965,51 @@ bool GeneratorImpl::EmitReturn(std::ostream& out, ast::ReturnStatement* stmt) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GeneratorImpl::EmitStatement(std::ostream& out, ast::Statement* stmt) {
|
bool GeneratorImpl::EmitStatement(std::ostream& out, ast::Statement* stmt) {
|
||||||
if (stmt->IsAssign()) {
|
if (auto* a = stmt->As<ast::AssignmentStatement>()) {
|
||||||
return EmitAssign(out, stmt->AsAssign());
|
return EmitAssign(out, a);
|
||||||
}
|
}
|
||||||
if (stmt->IsBlock()) {
|
if (auto* b = stmt->As<ast::BlockStatement>()) {
|
||||||
return EmitIndentedBlockAndNewline(out, stmt->AsBlock());
|
return EmitIndentedBlockAndNewline(out, b);
|
||||||
}
|
}
|
||||||
if (stmt->IsBreak()) {
|
if (auto* b = stmt->As<ast::BreakStatement>()) {
|
||||||
return EmitBreak(out, stmt->AsBreak());
|
return EmitBreak(out, b);
|
||||||
}
|
}
|
||||||
if (stmt->IsCall()) {
|
if (auto* c = stmt->As<ast::CallStatement>()) {
|
||||||
make_indent(out);
|
make_indent(out);
|
||||||
std::ostringstream pre;
|
std::ostringstream pre;
|
||||||
std::ostringstream call_out;
|
std::ostringstream call_out;
|
||||||
if (!EmitCall(pre, call_out, stmt->AsCall()->expr())) {
|
if (!EmitCall(pre, call_out, c->expr())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
out << pre.str();
|
out << pre.str();
|
||||||
out << call_out.str() << ";" << std::endl;
|
out << call_out.str() << ";" << std::endl;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (stmt->IsContinue()) {
|
if (auto* c = stmt->As<ast::ContinueStatement>()) {
|
||||||
return EmitContinue(out, stmt->AsContinue());
|
return EmitContinue(out, c);
|
||||||
}
|
}
|
||||||
if (stmt->IsDiscard()) {
|
if (auto* d = stmt->As<ast::DiscardStatement>()) {
|
||||||
return EmitDiscard(out, stmt->AsDiscard());
|
return EmitDiscard(out, d);
|
||||||
}
|
}
|
||||||
if (stmt->IsFallthrough()) {
|
if (auto* f = stmt->As<ast::FallthroughStatement>()) {
|
||||||
make_indent(out);
|
make_indent(out);
|
||||||
out << "/* fallthrough */" << std::endl;
|
out << "/* fallthrough */" << std::endl;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (stmt->IsIf()) {
|
if (auto* i = stmt->As<ast::IfStatement>()) {
|
||||||
return EmitIf(out, stmt->AsIf());
|
return EmitIf(out, i);
|
||||||
}
|
}
|
||||||
if (stmt->IsLoop()) {
|
if (auto* l = stmt->As<ast::LoopStatement>()) {
|
||||||
return EmitLoop(out, stmt->AsLoop());
|
return EmitLoop(out, l);
|
||||||
}
|
}
|
||||||
if (stmt->IsReturn()) {
|
if (auto* r = stmt->As<ast::ReturnStatement>()) {
|
||||||
return EmitReturn(out, stmt->AsReturn());
|
return EmitReturn(out, r);
|
||||||
}
|
}
|
||||||
if (stmt->IsSwitch()) {
|
if (auto* s = stmt->As<ast::SwitchStatement>()) {
|
||||||
return EmitSwitch(out, stmt->AsSwitch());
|
return EmitSwitch(out, s);
|
||||||
}
|
}
|
||||||
if (stmt->IsVariableDecl()) {
|
if (auto* v = stmt->As<ast::VariableDeclStatement>()) {
|
||||||
return EmitVariable(out, stmt->AsVariableDecl()->variable(), false);
|
return EmitVariable(out, v->variable(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
error_ = "unknown statement type: " + stmt->str();
|
error_ = "unknown statement type: " + stmt->str();
|
||||||
|
|
|
@ -19,10 +19,19 @@
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
|
#include "src/ast/assignment_statement.h"
|
||||||
|
#include "src/ast/break_statement.h"
|
||||||
|
#include "src/ast/case_statement.h"
|
||||||
|
#include "src/ast/continue_statement.h"
|
||||||
|
#include "src/ast/discard_statement.h"
|
||||||
|
#include "src/ast/if_statement.h"
|
||||||
#include "src/ast/intrinsic.h"
|
#include "src/ast/intrinsic.h"
|
||||||
#include "src/ast/literal.h"
|
#include "src/ast/literal.h"
|
||||||
|
#include "src/ast/loop_statement.h"
|
||||||
#include "src/ast/module.h"
|
#include "src/ast/module.h"
|
||||||
|
#include "src/ast/return_statement.h"
|
||||||
#include "src/ast/scalar_constructor_expression.h"
|
#include "src/ast/scalar_constructor_expression.h"
|
||||||
|
#include "src/ast/switch_statement.h"
|
||||||
#include "src/ast/type/struct_type.h"
|
#include "src/ast/type/struct_type.h"
|
||||||
#include "src/ast/type_constructor_expression.h"
|
#include "src/ast/type_constructor_expression.h"
|
||||||
#include "src/context.h"
|
#include "src/context.h"
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include "src/ast/continue_statement.h"
|
#include "src/ast/continue_statement.h"
|
||||||
#include "src/ast/decorated_variable.h"
|
#include "src/ast/decorated_variable.h"
|
||||||
#include "src/ast/else_statement.h"
|
#include "src/ast/else_statement.h"
|
||||||
|
#include "src/ast/fallthrough_statement.h"
|
||||||
#include "src/ast/float_literal.h"
|
#include "src/ast/float_literal.h"
|
||||||
#include "src/ast/function.h"
|
#include "src/ast/function.h"
|
||||||
#include "src/ast/identifier_expression.h"
|
#include "src/ast/identifier_expression.h"
|
||||||
|
@ -80,7 +81,8 @@ bool last_is_break_or_fallthrough(const ast::BlockStatement* stmts) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return stmts->last()->IsBreak() || stmts->last()->IsFallthrough();
|
return stmts->last()->Is<ast::BreakStatement>() ||
|
||||||
|
stmts->last()->Is<ast::FallthroughStatement>();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t adjust_for_alignment(uint32_t count, uint32_t alignment) {
|
uint32_t adjust_for_alignment(uint32_t count, uint32_t alignment) {
|
||||||
|
@ -1540,11 +1542,10 @@ bool GeneratorImpl::EmitLoop(ast::LoopStatement* stmt) {
|
||||||
// the for loop into the continuing scope. Then, the variable declarations
|
// the for loop into the continuing scope. Then, the variable declarations
|
||||||
// will be turned into assignments.
|
// will be turned into assignments.
|
||||||
for (auto* s : *(stmt->body())) {
|
for (auto* s : *(stmt->body())) {
|
||||||
if (!s->IsVariableDecl()) {
|
if (auto* decl = s->As<ast::VariableDeclStatement>()) {
|
||||||
continue;
|
if (!EmitVariable(decl->variable(), true)) {
|
||||||
}
|
return false;
|
||||||
if (!EmitVariable(s->AsVariableDecl()->variable(), true)) {
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1569,10 +1570,11 @@ bool GeneratorImpl::EmitLoop(ast::LoopStatement* stmt) {
|
||||||
for (auto* s : *(stmt->body())) {
|
for (auto* s : *(stmt->body())) {
|
||||||
// If we have a continuing block we've already emitted the variable
|
// If we have a continuing block we've already emitted the variable
|
||||||
// declaration before the loop, so treat it as an assignment.
|
// declaration before the loop, so treat it as an assignment.
|
||||||
if (s->IsVariableDecl() && stmt->has_continuing()) {
|
auto* decl = s->As<ast::VariableDeclStatement>();
|
||||||
|
if (decl != nullptr && stmt->has_continuing()) {
|
||||||
make_indent();
|
make_indent();
|
||||||
|
|
||||||
auto* var = s->AsVariableDecl()->variable();
|
auto* var = decl->variable();
|
||||||
out_ << var->name() << " = ";
|
out_ << var->name() << " = ";
|
||||||
if (var->constructor() != nullptr) {
|
if (var->constructor() != nullptr) {
|
||||||
if (!EmitExpression(var->constructor())) {
|
if (!EmitExpression(var->constructor())) {
|
||||||
|
@ -1716,48 +1718,48 @@ bool GeneratorImpl::EmitIndentedBlockAndNewline(ast::BlockStatement* stmt) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GeneratorImpl::EmitStatement(ast::Statement* stmt) {
|
bool GeneratorImpl::EmitStatement(ast::Statement* stmt) {
|
||||||
if (stmt->IsAssign()) {
|
if (auto* a = stmt->As<ast::AssignmentStatement>()) {
|
||||||
return EmitAssign(stmt->AsAssign());
|
return EmitAssign(a);
|
||||||
}
|
}
|
||||||
if (stmt->IsBlock()) {
|
if (auto* b = stmt->As<ast::BlockStatement>()) {
|
||||||
return EmitIndentedBlockAndNewline(stmt->AsBlock());
|
return EmitIndentedBlockAndNewline(b);
|
||||||
}
|
}
|
||||||
if (stmt->IsBreak()) {
|
if (auto* b = stmt->As<ast::BreakStatement>()) {
|
||||||
return EmitBreak(stmt->AsBreak());
|
return EmitBreak(b);
|
||||||
}
|
}
|
||||||
if (stmt->IsCall()) {
|
if (auto* c = stmt->As<ast::CallStatement>()) {
|
||||||
make_indent();
|
make_indent();
|
||||||
if (!EmitCall(stmt->AsCall()->expr())) {
|
if (!EmitCall(c->expr())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
out_ << ";" << std::endl;
|
out_ << ";" << std::endl;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (stmt->IsContinue()) {
|
if (auto* c = stmt->As<ast::ContinueStatement>()) {
|
||||||
return EmitContinue(stmt->AsContinue());
|
return EmitContinue(c);
|
||||||
}
|
}
|
||||||
if (stmt->IsDiscard()) {
|
if (auto* d = stmt->As<ast::DiscardStatement>()) {
|
||||||
return EmitDiscard(stmt->AsDiscard());
|
return EmitDiscard(d);
|
||||||
}
|
}
|
||||||
if (stmt->IsFallthrough()) {
|
if (auto* f = stmt->As<ast::FallthroughStatement>()) {
|
||||||
make_indent();
|
make_indent();
|
||||||
out_ << "/* fallthrough */" << std::endl;
|
out_ << "/* fallthrough */" << std::endl;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (stmt->IsIf()) {
|
if (auto* i = stmt->As<ast::IfStatement>()) {
|
||||||
return EmitIf(stmt->AsIf());
|
return EmitIf(i);
|
||||||
}
|
}
|
||||||
if (stmt->IsLoop()) {
|
if (auto* l = stmt->As<ast::LoopStatement>()) {
|
||||||
return EmitLoop(stmt->AsLoop());
|
return EmitLoop(l);
|
||||||
}
|
}
|
||||||
if (stmt->IsReturn()) {
|
if (auto* r = stmt->As<ast::ReturnStatement>()) {
|
||||||
return EmitReturn(stmt->AsReturn());
|
return EmitReturn(r);
|
||||||
}
|
}
|
||||||
if (stmt->IsSwitch()) {
|
if (auto* s = stmt->As<ast::SwitchStatement>()) {
|
||||||
return EmitSwitch(stmt->AsSwitch());
|
return EmitSwitch(s);
|
||||||
}
|
}
|
||||||
if (stmt->IsVariableDecl()) {
|
if (auto* v = stmt->As<ast::VariableDeclStatement>()) {
|
||||||
return EmitVariable(stmt->AsVariableDecl()->variable(), false);
|
return EmitVariable(v->variable(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
error_ = "unknown statement type: " + stmt->str();
|
error_ = "unknown statement type: " + stmt->str();
|
||||||
|
|
|
@ -19,10 +19,20 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include "src/ast/assignment_statement.h"
|
||||||
|
#include "src/ast/break_statement.h"
|
||||||
|
#include "src/ast/case_statement.h"
|
||||||
|
#include "src/ast/continue_statement.h"
|
||||||
|
#include "src/ast/discard_statement.h"
|
||||||
|
#include "src/ast/else_statement.h"
|
||||||
|
#include "src/ast/if_statement.h"
|
||||||
#include "src/ast/intrinsic.h"
|
#include "src/ast/intrinsic.h"
|
||||||
#include "src/ast/literal.h"
|
#include "src/ast/literal.h"
|
||||||
|
#include "src/ast/loop_statement.h"
|
||||||
#include "src/ast/module.h"
|
#include "src/ast/module.h"
|
||||||
|
#include "src/ast/return_statement.h"
|
||||||
#include "src/ast/scalar_constructor_expression.h"
|
#include "src/ast/scalar_constructor_expression.h"
|
||||||
|
#include "src/ast/switch_statement.h"
|
||||||
#include "src/ast/type/struct_type.h"
|
#include "src/ast/type/struct_type.h"
|
||||||
#include "src/ast/type_constructor_expression.h"
|
#include "src/ast/type_constructor_expression.h"
|
||||||
#include "src/scope_stack.h"
|
#include "src/scope_stack.h"
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include "src/ast/constructor_expression.h"
|
#include "src/ast/constructor_expression.h"
|
||||||
#include "src/ast/decorated_variable.h"
|
#include "src/ast/decorated_variable.h"
|
||||||
#include "src/ast/else_statement.h"
|
#include "src/ast/else_statement.h"
|
||||||
|
#include "src/ast/fallthrough_statement.h"
|
||||||
#include "src/ast/float_literal.h"
|
#include "src/ast/float_literal.h"
|
||||||
#include "src/ast/identifier_expression.h"
|
#include "src/ast/identifier_expression.h"
|
||||||
#include "src/ast/if_statement.h"
|
#include "src/ast/if_statement.h"
|
||||||
|
@ -109,7 +110,7 @@ uint32_t pipeline_stage_to_execution_model(ast::PipelineStage stage) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LastIsFallthrough(const ast::BlockStatement* stmts) {
|
bool LastIsFallthrough(const ast::BlockStatement* stmts) {
|
||||||
return !stmts->empty() && stmts->last()->IsFallthrough();
|
return !stmts->empty() && stmts->last()->Is<ast::FallthroughStatement>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// A terminator is anything which will case a SPIR-V terminator to be emitted.
|
// A terminator is anything which will case a SPIR-V terminator to be emitted.
|
||||||
|
@ -121,8 +122,11 @@ bool LastIsTerminator(const ast::BlockStatement* stmts) {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* last = stmts->last();
|
auto* last = stmts->last();
|
||||||
return last->IsBreak() || last->IsContinue() || last->IsDiscard() ||
|
return last->Is<ast::BreakStatement>() ||
|
||||||
last->IsReturn() || last->IsFallthrough();
|
last->Is<ast::ContinueStatement>() ||
|
||||||
|
last->Is<ast::DiscardStatement>() ||
|
||||||
|
last->Is<ast::ReturnStatement>() ||
|
||||||
|
last->Is<ast::FallthroughStatement>();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t IndexFromName(char name) {
|
uint32_t IndexFromName(char name) {
|
||||||
|
@ -2359,42 +2363,42 @@ bool Builder::GenerateLoopStatement(ast::LoopStatement* stmt) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Builder::GenerateStatement(ast::Statement* stmt) {
|
bool Builder::GenerateStatement(ast::Statement* stmt) {
|
||||||
if (stmt->IsAssign()) {
|
if (auto* a = stmt->As<ast::AssignmentStatement>()) {
|
||||||
return GenerateAssignStatement(stmt->AsAssign());
|
return GenerateAssignStatement(a);
|
||||||
}
|
}
|
||||||
if (stmt->IsBlock()) {
|
if (auto* b = stmt->As<ast::BlockStatement>()) {
|
||||||
return GenerateBlockStatement(stmt->AsBlock());
|
return GenerateBlockStatement(b);
|
||||||
}
|
}
|
||||||
if (stmt->IsBreak()) {
|
if (auto* b = stmt->As<ast::BreakStatement>()) {
|
||||||
return GenerateBreakStatement(stmt->AsBreak());
|
return GenerateBreakStatement(b);
|
||||||
}
|
}
|
||||||
if (stmt->IsCall()) {
|
if (auto* c = stmt->As<ast::CallStatement>()) {
|
||||||
return GenerateCallExpression(stmt->AsCall()->expr()) != 0;
|
return GenerateCallExpression(c->expr()) != 0;
|
||||||
}
|
}
|
||||||
if (stmt->IsContinue()) {
|
if (auto* c = stmt->As<ast::ContinueStatement>()) {
|
||||||
return GenerateContinueStatement(stmt->AsContinue());
|
return GenerateContinueStatement(c);
|
||||||
}
|
}
|
||||||
if (stmt->IsDiscard()) {
|
if (auto* d = stmt->As<ast::DiscardStatement>()) {
|
||||||
return GenerateDiscardStatement(stmt->AsDiscard());
|
return GenerateDiscardStatement(d);
|
||||||
}
|
}
|
||||||
if (stmt->IsFallthrough()) {
|
if (stmt->Is<ast::FallthroughStatement>()) {
|
||||||
// Do nothing here, the fallthrough gets handled by the switch code.
|
// Do nothing here, the fallthrough gets handled by the switch code.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (stmt->IsIf()) {
|
if (auto* i = stmt->As<ast::IfStatement>()) {
|
||||||
return GenerateIfStatement(stmt->AsIf());
|
return GenerateIfStatement(i);
|
||||||
}
|
}
|
||||||
if (stmt->IsLoop()) {
|
if (auto* l = stmt->As<ast::LoopStatement>()) {
|
||||||
return GenerateLoopStatement(stmt->AsLoop());
|
return GenerateLoopStatement(l);
|
||||||
}
|
}
|
||||||
if (stmt->IsReturn()) {
|
if (auto* r = stmt->As<ast::ReturnStatement>()) {
|
||||||
return GenerateReturnStatement(stmt->AsReturn());
|
return GenerateReturnStatement(r);
|
||||||
}
|
}
|
||||||
if (stmt->IsSwitch()) {
|
if (auto* s = stmt->As<ast::SwitchStatement>()) {
|
||||||
return GenerateSwitchStatement(stmt->AsSwitch());
|
return GenerateSwitchStatement(s);
|
||||||
}
|
}
|
||||||
if (stmt->IsVariableDecl()) {
|
if (auto* v = stmt->As<ast::VariableDeclStatement>()) {
|
||||||
return GenerateVariableDeclStatement(stmt->AsVariableDecl());
|
return GenerateVariableDeclStatement(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
error_ = "Unknown statement: " + stmt->str();
|
error_ = "Unknown statement: " + stmt->str();
|
||||||
|
|
|
@ -22,11 +22,19 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "spirv/unified1/spirv.h"
|
#include "spirv/unified1/spirv.h"
|
||||||
|
#include "src/ast/assignment_statement.h"
|
||||||
|
#include "src/ast/break_statement.h"
|
||||||
#include "src/ast/builtin.h"
|
#include "src/ast/builtin.h"
|
||||||
|
#include "src/ast/continue_statement.h"
|
||||||
|
#include "src/ast/discard_statement.h"
|
||||||
#include "src/ast/else_statement.h"
|
#include "src/ast/else_statement.h"
|
||||||
|
#include "src/ast/if_statement.h"
|
||||||
#include "src/ast/literal.h"
|
#include "src/ast/literal.h"
|
||||||
|
#include "src/ast/loop_statement.h"
|
||||||
#include "src/ast/module.h"
|
#include "src/ast/module.h"
|
||||||
|
#include "src/ast/return_statement.h"
|
||||||
#include "src/ast/struct_member.h"
|
#include "src/ast/struct_member.h"
|
||||||
|
#include "src/ast/switch_statement.h"
|
||||||
#include "src/ast/type/access_control_type.h"
|
#include "src/ast/type/access_control_type.h"
|
||||||
#include "src/ast/type/array_type.h"
|
#include "src/ast/type/array_type.h"
|
||||||
#include "src/ast/type/matrix_type.h"
|
#include "src/ast/type/matrix_type.h"
|
||||||
|
@ -35,6 +43,7 @@
|
||||||
#include "src/ast/type/struct_type.h"
|
#include "src/ast/type/struct_type.h"
|
||||||
#include "src/ast/type/vector_type.h"
|
#include "src/ast/type/vector_type.h"
|
||||||
#include "src/ast/type_constructor_expression.h"
|
#include "src/ast/type_constructor_expression.h"
|
||||||
|
#include "src/ast/variable_decl_statement.h"
|
||||||
#include "src/context.h"
|
#include "src/context.h"
|
||||||
#include "src/scope_stack.h"
|
#include "src/scope_stack.h"
|
||||||
#include "src/writer/spirv/function.h"
|
#include "src/writer/spirv/function.h"
|
||||||
|
|
|
@ -796,46 +796,46 @@ bool GeneratorImpl::EmitBlockAndNewline(const ast::BlockStatement* stmt) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GeneratorImpl::EmitStatement(ast::Statement* stmt) {
|
bool GeneratorImpl::EmitStatement(ast::Statement* stmt) {
|
||||||
if (stmt->IsAssign()) {
|
if (auto* a = stmt->As<ast::AssignmentStatement>()) {
|
||||||
return EmitAssign(stmt->AsAssign());
|
return EmitAssign(a);
|
||||||
}
|
}
|
||||||
if (stmt->IsBlock()) {
|
if (auto* b = stmt->As<ast::BlockStatement>()) {
|
||||||
return EmitIndentedBlockAndNewline(stmt->AsBlock());
|
return EmitIndentedBlockAndNewline(b);
|
||||||
}
|
}
|
||||||
if (stmt->IsBreak()) {
|
if (auto* b = stmt->As<ast::BreakStatement>()) {
|
||||||
return EmitBreak(stmt->AsBreak());
|
return EmitBreak(b);
|
||||||
}
|
}
|
||||||
if (stmt->IsCall()) {
|
if (auto* c = stmt->As<ast::CallStatement>()) {
|
||||||
make_indent();
|
make_indent();
|
||||||
if (!EmitCall(stmt->AsCall()->expr())) {
|
if (!EmitCall(c->expr())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
out_ << ";" << std::endl;
|
out_ << ";" << std::endl;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (stmt->IsContinue()) {
|
if (auto* c = stmt->As<ast::ContinueStatement>()) {
|
||||||
return EmitContinue(stmt->AsContinue());
|
return EmitContinue(c);
|
||||||
}
|
}
|
||||||
if (stmt->IsDiscard()) {
|
if (auto* d = stmt->As<ast::DiscardStatement>()) {
|
||||||
return EmitDiscard(stmt->AsDiscard());
|
return EmitDiscard(d);
|
||||||
}
|
}
|
||||||
if (stmt->IsFallthrough()) {
|
if (auto* f = stmt->As<ast::FallthroughStatement>()) {
|
||||||
return EmitFallthrough(stmt->AsFallthrough());
|
return EmitFallthrough(f);
|
||||||
}
|
}
|
||||||
if (stmt->IsIf()) {
|
if (auto* i = stmt->As<ast::IfStatement>()) {
|
||||||
return EmitIf(stmt->AsIf());
|
return EmitIf(i);
|
||||||
}
|
}
|
||||||
if (stmt->IsLoop()) {
|
if (auto* l = stmt->As<ast::LoopStatement>()) {
|
||||||
return EmitLoop(stmt->AsLoop());
|
return EmitLoop(l);
|
||||||
}
|
}
|
||||||
if (stmt->IsReturn()) {
|
if (auto* r = stmt->As<ast::ReturnStatement>()) {
|
||||||
return EmitReturn(stmt->AsReturn());
|
return EmitReturn(r);
|
||||||
}
|
}
|
||||||
if (stmt->IsSwitch()) {
|
if (auto* s = stmt->As<ast::SwitchStatement>()) {
|
||||||
return EmitSwitch(stmt->AsSwitch());
|
return EmitSwitch(s);
|
||||||
}
|
}
|
||||||
if (stmt->IsVariableDecl()) {
|
if (auto* v = stmt->As<ast::VariableDeclStatement>()) {
|
||||||
return EmitVariable(stmt->AsVariableDecl()->variable());
|
return EmitVariable(v->variable());
|
||||||
}
|
}
|
||||||
|
|
||||||
error_ = "unknown statement type: " + stmt->str();
|
error_ = "unknown statement type: " + stmt->str();
|
||||||
|
|
|
@ -19,10 +19,20 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "src/ast/array_accessor_expression.h"
|
#include "src/ast/array_accessor_expression.h"
|
||||||
|
#include "src/ast/assignment_statement.h"
|
||||||
|
#include "src/ast/break_statement.h"
|
||||||
|
#include "src/ast/case_statement.h"
|
||||||
#include "src/ast/constructor_expression.h"
|
#include "src/ast/constructor_expression.h"
|
||||||
|
#include "src/ast/continue_statement.h"
|
||||||
|
#include "src/ast/discard_statement.h"
|
||||||
|
#include "src/ast/fallthrough_statement.h"
|
||||||
#include "src/ast/identifier_expression.h"
|
#include "src/ast/identifier_expression.h"
|
||||||
|
#include "src/ast/if_statement.h"
|
||||||
|
#include "src/ast/loop_statement.h"
|
||||||
#include "src/ast/module.h"
|
#include "src/ast/module.h"
|
||||||
|
#include "src/ast/return_statement.h"
|
||||||
#include "src/ast/scalar_constructor_expression.h"
|
#include "src/ast/scalar_constructor_expression.h"
|
||||||
|
#include "src/ast/switch_statement.h"
|
||||||
#include "src/ast/type/storage_texture_type.h"
|
#include "src/ast/type/storage_texture_type.h"
|
||||||
#include "src/ast/type/struct_type.h"
|
#include "src/ast/type/struct_type.h"
|
||||||
#include "src/ast/type/type.h"
|
#include "src/ast/type/type.h"
|
||||||
|
|
Loading…
Reference in New Issue