Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add multi-dimensional array literals #26782

Draft
wants to merge 12 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 61 additions & 20 deletions compiler/passes/convert-uast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1711,45 +1711,86 @@ struct Converter final : UastConverter {

/// Array, Domain, Range, Tuple ///

void convertArrayRow(const uast::ArrayRow* node, CallExpr* actualList) {
for (auto expr : node->exprs()) {
if (expr->isArrayRow()) {
convertArrayRow(expr->toArrayRow(), actualList);
} else {
actualList->insertAtTail(convertAST(expr));
}
}
}

Expr* visit(const uast::Array* node) {
CallExpr* actualList = new CallExpr(PRIM_ACTUALS_LIST);
Expr* shapeList = nullptr;
bool isAssociativeList = false;

for (auto expr : node->exprs()) {
bool hasConvertedThisIter = false;

if (auto opCall = expr->toOpCall()) {
if (opCall->op() == USTR("=>")) {
isAssociativeList = true;
INT_ASSERT(opCall->numActuals() == 2);
Expr* lhs = convertAST(opCall->actual(0));
Expr* rhs = convertAST(opCall->actual(1));
actualList->insertAtTail(lhs);
actualList->insertAtTail(rhs);
hasConvertedThisIter = true;
} else {
if (isAssociativeList) CHPL_UNIMPL("Invalid associative list");
bool isNDArray = node->numExprs() >= 1 && node->expr(0)->isArrayRow();
if (!isNDArray) {
for (auto expr : node->exprs()) {
bool hasConvertedThisIter = false;

if (auto opCall = expr->toOpCall()) {
if (opCall->op() == USTR("=>")) {
isAssociativeList = true;
INT_ASSERT(opCall->numActuals() == 2);
Expr* lhs = convertAST(opCall->actual(0));
Expr* rhs = convertAST(opCall->actual(1));
actualList->insertAtTail(lhs);
actualList->insertAtTail(rhs);
hasConvertedThisIter = true;
} else {
if (isAssociativeList) CHPL_UNIMPL("Invalid associative list");
}
}

if (!hasConvertedThisIter) {
actualList->insertAtTail(convertAST(expr));
}
}

if (!hasConvertedThisIter) {
actualList->insertAtTail(convertAST(expr));
} else {
CallExpr* shapeActualList = new CallExpr(PRIM_ACTUALS_LIST);
shapeActualList->insertAtTail(
new SymExpr(new_IntSymbol(node->numExprs(), INT_SIZE_64)));
const uast::AstNode* cur = node->expr(0);
while (cur->isArrayRow()) {
auto row = cur->toArrayRow();
shapeActualList->insertAtTail(
new SymExpr(new_IntSymbol(row->numExprs(), INT_SIZE_64)));
cur = row->expr(0);
}
shapeList = new CallExpr("_build_tuple", shapeActualList);

for (auto expr : node->exprs()) {
convertArrayRow(expr->toArrayRow(), actualList);
}
}

Expr* ret = nullptr;

if (isAssociativeList) {
ret = new CallExpr("chpl__buildAssociativeArrayExpr", actualList);
if (!isNDArray) {
INT_ASSERT(shapeList == nullptr);
if (isAssociativeList) {
ret = new CallExpr("chpl__buildAssociativeArrayExpr", actualList);
} else {
ret = new CallExpr("chpl__buildArrayExpr", actualList);
}
} else {
ret = new CallExpr("chpl__buildArrayExpr", actualList);
INT_ASSERT(shapeList != nullptr);
ret = new CallExpr("chpl__buildNDArrayExpr", shapeList, actualList);
}

INT_ASSERT(ret != nullptr);

return ret;
}

Expr* visit(const uast::ArrayRow* node) {
INT_FATAL("Should not be called directly!");
return nullptr;
}

Expr* visit(const uast::Domain* node) {
CallExpr* actualList = new CallExpr(PRIM_ACTUALS_LIST);

Expand Down
10 changes: 5 additions & 5 deletions frontend/include/chpl/uast/Array.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,11 @@ class Array final : public AstNode {
private:
bool trailingComma_,
associative_;

Array(AstList children, bool trailingComma, bool associative)
: AstNode(asttags::Array, std::move(children)) {
trailingComma_ = trailingComma;
associative_ = associative;
: AstNode(asttags::Array, std::move(children)),
trailingComma_(trailingComma),
associative_(associative) {
}

void serializeInner(Serializer& ser) const override {
Expand Down Expand Up @@ -87,7 +87,7 @@ class Array final : public AstNode {

bool hasTrailingComma() const { return this->trailingComma_; }
bool isAssociative() const { return this->associative_; }

/**
Return a way to iterate over the expressions of this array.
*/
Expand Down
91 changes: 91 additions & 0 deletions frontend/include/chpl/uast/ArrayRow.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* Copyright 2021-2025 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_ARRAY_ROW_H
#define CHPL_UAST_ARRAY_ROW_H

#include "chpl/framework/Location.h"
#include "chpl/uast/AstNode.h"

namespace chpl {
namespace uast {


class ArrayRow final : public AstNode {
friend class AstNode;

private:

ArrayRow(AstList children)
: AstNode(asttags::ArrayRow, std::move(children)) {
}

void serializeInner(Serializer& ser) const override {
}

explicit ArrayRow(Deserializer& des)
: AstNode(asttags::ArrayRow, des) {
}

bool contentsMatchInner(const AstNode* other) const override {
return true;
}

void markUniqueStringsInner(Context* context) const override {
}

// void dumpInner(const DumpSettings& s) const;

public:
~ArrayRow() override = default;

/**
Create and return an ArrayRow expression.
*/
static owned<ArrayRow> build(Builder* builder, Location loc, AstList exprs);

/**
Return a way to iterate over the expressions of this array.
*/
AstListIteratorPair<AstNode> exprs() const {
return AstListIteratorPair<AstNode>(children_.begin(),
children_.end());
}

/**
Return the number of expressions in this array.
*/
int numExprs() const {
return this->numChildren();
}

/**
Return the i'th expression in this array.
*/
const AstNode* expr(int i) const {
const AstNode* ast = this->child(i);
return ast;
}
};


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

#endif
1 change: 1 addition & 0 deletions frontend/include/chpl/uast/all-uast.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "chpl/uast/AnonFormal.h"
#include "chpl/uast/AstNode.h"
#include "chpl/uast/Array.h"
#include "chpl/uast/ArrayRow.h"
#include "chpl/uast/As.h"
#include "chpl/uast/Attribute.h"
#include "chpl/uast/AttributeGroup.h"
Expand Down
1 change: 1 addition & 0 deletions frontend/include/chpl/uast/uast-classes-list.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
AST_NODE(AnonFormal) //
AST_NODE(As) //
AST_NODE(Array) //
AST_NODE(ArrayRow) //
AST_NODE(Attribute) //
AST_NODE(AttributeGroup) //
//AST_NODE(AssociativeArray) //
Expand Down
5 changes: 5 additions & 0 deletions frontend/lib/parsing/ParserContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,11 @@ struct ParserContext {
AstList consumeList(ParserExprList* lst);
AstList consume(AstNode* e);

ParserNDArrayList* makeNDArrayList();
ParserNDArrayList* appendNDArrayList(ParserNDArrayList* dst,
NDArrayElement e);
Array* buildNDArray(YYLTYPE location, ParserNDArrayList* lst);

void consumeNamedActuals(MaybeNamedActualList* lst,
AstList& actualsOut,
std::vector<UniqueString>& namesOut);
Expand Down
51 changes: 51 additions & 0 deletions frontend/lib/parsing/ParserContextImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,57 @@ AstList ParserContext::consume(AstNode* e) {
return ret;
}

ParserNDArrayList* ParserContext::makeNDArrayList() {
return new ParserNDArrayList();
}
ParserNDArrayList* ParserContext::appendNDArrayList(ParserNDArrayList* dst,
NDArrayElement e) {
dst->push_back(e);
return dst;
}

static inline AstList buildArrayRows(ParserContext* context, ParserNDArrayList* lst,
Location location, int start, int stop) {
CHPL_ASSERT(start <= stop);
if (start == stop) {
// there is a single row, so just return it
return context->consumeList((*lst)[start].exprs);
}

// find the largest number of consecutive sep
int maxSep = 0;
for (int i = start; i <= stop; i++) {
maxSep = std::max(maxSep, (*lst)[i].nSeparator);
}
CHPL_ASSERT(maxSep > 0);

// iterate through the list from start to stop, each time we find a maxSep
// recurse on the sublist from the last maxSep to the current element
AstList ret;
int start_ = start;
for (int i = start_; i <= stop; i++) {
if ((*lst)[i].nSeparator == maxSep) {
auto newRows = buildArrayRows(context, lst, location, start_, i-1);
ret.push_back(ArrayRow::build(context->builder, location, std::move(newRows)));
start_ = i+1;
}
}
// add the last row
auto newRows = buildArrayRows(context, lst, location, start_, stop);
ret.push_back(ArrayRow::build(context->builder, location, std::move(newRows)));

return ret;
}
Array* ParserContext::buildNDArray(YYLTYPE location, ParserNDArrayList* lst) {
CHPL_ASSERT(lst->size() > 0);
auto loc = convertLocation(location);

AstList rows = buildArrayRows(this, lst, loc, 0, lst->size()-1);
return Array::build(builder, loc, std::move(rows)).release();
}



void ParserContext::consumeNamedActuals(MaybeNamedActualList* lst,
AstList& actualsOut,
std::vector<UniqueString>& namesOut) {
Expand Down
Loading