Skip to content

Commit

Permalink
Merge pull request chapel-lang#17804 from dlongnecke-cray/next-add-while
Browse files Browse the repository at this point in the history
next: Parse While and DoWhile loops

This is for `compiler/next`.

Add nodes for `While` and `DoWhile` loops, and wire up the parser
actions for them.

Reviewed by @lydia-duncan and @mppf. Thanks!

TESTING:

- [x] All `compiler/next` tests pass

Signed-off-by: David Longnecker <[email protected]>
  • Loading branch information
dlongnecke-cray authored May 26, 2021
2 parents 34cded4 + 99372f0 commit 7e877bf
Show file tree
Hide file tree
Showing 13 changed files with 730 additions and 10 deletions.
15 changes: 14 additions & 1 deletion compiler/next/include/chpl/uast/Builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,13 +122,26 @@ class Builder final {
// Builder methods are actually type methods on the individual AST
// elements. This prevents the Builder API from growing unreasonably large.

/// \cond DO_NOT_DOCUMENT

// Use this in the parser to get a mutable view of a node's children so
// that the node can be modified in place. Later we can also add a method
// such as 'swapChildren' if we need it.
/// \cond DO_NOT_DOCUMENT
ASTList& mutableRefToChildren(ASTNode* ast) {
return ast->children_;
}

// Use this to take the children of an AST node. The AST node is marked
// as owned because it is consumed.
ASTList takeChildren(owned<ASTNode> ast) {
auto ret = std::move(ast->children_);
assert(ast->children_.size() == 0);
return ret;
}

// Use this to flatten top level blocks within an ASTList.
ASTList flattenTopLevelBlocks(ASTList lst);

/// \endcond
};

Expand Down
103 changes: 103 additions & 0 deletions compiler/next/include/chpl/uast/DoWhile.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/*
* Copyright 2021 Hewlett Packard Enterprise Development LP
* Other additional copyright holders may be indicated within.
*
* The entirety of this work is licensed under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
*
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef CHPL_UAST_DOWHILE_H
#define CHPL_UAST_DOWHILE_H

#include "chpl/queries/Location.h"
#include "chpl/uast/Loop.h"

namespace chpl {
namespace uast {


/**
This class represents a do-while loop. For example:
\rst
.. code-block:: chapel
// Example 1:
var i = 0;
do {
writeln(i);
i += 1;
} while i < 5;
\endrst
*/
class DoWhile final : public Loop {
private:
DoWhile(ASTList children, int loopBodyChildNum, int numLoopBodyStmts,
int conditionChildNum,
bool isBodyBlock)
: Loop(asttags::DoWhile, std::move(children),
loopBodyChildNum,
numLoopBodyStmts,
/*usesDo*/ true),
conditionChildNum_(conditionChildNum),
isBodyBlock_(isBodyBlock) {
assert(isExpressionASTList(children_));
assert(condition());
}

bool contentsMatchInner(const ASTNode* other) const override;

void markUniqueStringsInner(Context* context) const override {
loopMarkUniqueStringsInner(context);
}

int conditionChildNum_;
bool isBodyBlock_;

public:
~DoWhile() override = default;

/**
Create and return a do-while loop.
*/
static owned<DoWhile> build(Builder* builder, Location loc,
ASTList stmts,
owned<Expression> condition,
bool isBodyBlock);

/**
Return the condition of this do-while loop.
*/
const Expression* condition() const {
auto ret = child(conditionChildNum_);
assert(ret->isExpression());
return (const Expression*)ret;
}

/**
Returns true if this do-while loop body is a block.
*/
bool isBodyBlock() const {
return isBodyBlock_;
}

};


} // end namespace uast
} // end namespace chpl

#endif
94 changes: 94 additions & 0 deletions compiler/next/include/chpl/uast/While.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
/*
* Copyright 2021 Hewlett Packard Enterprise Development LP
* Other additional copyright holders may be indicated within.
*
* The entirety of this work is licensed under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
*
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef CHPL_UAST_WHILE_H
#define CHPL_UAST_WHILE_H

#include "chpl/queries/Location.h"
#include "chpl/uast/Loop.h"

namespace chpl {
namespace uast {


/**
This class represents a while loop. For example:
\rst
.. code-block:: chapel
// Example 1:
var i = 0;
while i < 5 {
writeln(i);
i += 1;
}
\endrst
*/
class While final : public Loop {
private:
While(ASTList children, int8_t conditionChildNum,
int loopBodyChildNum,
int numLoopBodyStmts,
bool usesDo)
: Loop(asttags::While, std::move(children), loopBodyChildNum,
numLoopBodyStmts,
usesDo),
conditionChildNum_(conditionChildNum) {
assert(isExpressionASTList(children_));
assert(condition());
}

bool contentsMatchInner(const ASTNode* other) const override;

void markUniqueStringsInner(Context* context) const override {
loopMarkUniqueStringsInner(context);
}

int8_t conditionChildNum_;

public:
~While() override = default;

/**
Create and return a while loop.
*/
static owned<While> build(Builder* builder, Location loc,
owned<Expression> condition,
ASTList stmts,
bool usesDo);

/**
Return the condition of this while loop.
*/
const Expression* condition() const {
auto ret = child(conditionChildNum_);
assert(ret->isExpression());
return (const Expression*)ret;
}

};


} // end namespace uast
} // end namespace chpl

#endif
2 changes: 2 additions & 0 deletions compiler/next/lib/frontend/Parser/ParserContextImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,8 @@ ParserContext::gatherCommentsFromList(ParserExprList* lst,

void ParserContext::appendComments(CommentsAndStmt*cs,
std::vector<ParserComment>* comments) {
if (comments == nullptr) return;

if (cs->comments == nullptr) {
cs->comments = comments;
return;
Expand Down
38 changes: 29 additions & 9 deletions compiler/next/lib/frontend/Parser/chapel.ypp
Original file line number Diff line number Diff line change
Expand Up @@ -1300,17 +1300,37 @@ extern_block_stmt:

loop_stmt:
TDO stmt TWHILE expr TSEMI
{
$$ = TODOSTMT(@$);
}
{
const bool isBodyBlock = $2.stmt->isBlock();
auto exprLst = context->makeList($2);
auto comments = context->gatherCommentsFromList(exprLst, @1);

// Append any comment appearing before 'while' into the exprs of $2.
exprLst = context->appendList(exprLst, context->gatherComments(@3));

auto astLst = context->consumeList(exprLst);
auto statements = BUILDER->flattenTopLevelBlocks(std::move(astLst));
auto node = DoWhile::build(BUILDER, LOC(@1), std::move(statements),
toOwned($4),
isBodyBlock);
$$ = { .comments=comments, .stmt=node.release() };
}
| TWHILE expr do_stmt
{
$$ = TODOSTMT(@$);
}
{
auto comments = context->gatherCommentsFromList($3.exprList, @1);
auto node = While::build(BUILDER, LOC(@1), toOwned($2),
context->consumeList($3.exprList),
$3.usesDo);
$$ = { .comments=comments, .stmt=node.release() };
}
| TWHILE ifvar do_stmt
{
$$ = TODOSTMT(@$);
}
{
auto comments = context->gatherCommentsFromList($3.exprList, @1);
auto node = While::build(BUILDER, LOC(@1), toOwned($2),
context->consumeList($3.exprList),
$3.usesDo);
$$ = { .comments=comments, .stmt=node.release() };
}
| TCOFORALL expr TIN expr opt_task_intent_ls do_stmt
{
$$ = TODOSTMT(@$);
Expand Down
2 changes: 2 additions & 0 deletions compiler/next/lib/frontend/Parser/parser-dependencies.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "chpl/uast/Call.h"
#include "chpl/uast/Comment.h"
#include "chpl/uast/Dot.h"
#include "chpl/uast/DoWhile.h"
#include "chpl/uast/Enum.h"
#include "chpl/uast/EnumElement.h"
#include "chpl/uast/ErroneousExpression.h"
Expand All @@ -49,6 +50,7 @@
#include "chpl/uast/Serial.h"
#include "chpl/uast/TaskVar.h"
#include "chpl/uast/Variable.h"
#include "chpl/uast/While.h"
#include "chpl/uast/Zip.h"

#include <cstdint>
Expand Down
18 changes: 18 additions & 0 deletions compiler/next/lib/uast/Builder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,24 @@ void Builder::Result::updateFilePaths(Context* context, const Result& keep) {
}
}

ASTList Builder::flattenTopLevelBlocks(ASTList lst) {
ASTList ret;

for (auto& ast : lst) {
if (ast->isBlock()) {
for (auto& child : takeChildren(std::move(ast))) {
ret.push_back(std::move(child));
}
} else {
ret.push_back(std::move(ast));
}
}

lst.clear();

return ret;
}


} // namespace uast
} // namespace chpl
2 changes: 2 additions & 0 deletions compiler/next/lib/uast/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ target_sources(libchplcomp-obj
ControlFlow.cpp
Decl.cpp
Dot.cpp
DoWhile.cpp
Enum.cpp
EnumElement.cpp
ErroneousExpression.cpp
Expand All @@ -53,6 +54,7 @@ target_sources(libchplcomp-obj
Variable.cpp
VarLikeDecl.cpp
Visitor.cpp
While.cpp
WithClause.cpp
Zip.cpp

Expand Down
Loading

0 comments on commit 7e877bf

Please sign in to comment.