Skip to content

Get dyno resolving array slicing #27024

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

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
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
6 changes: 5 additions & 1 deletion frontend/lib/resolution/InitResolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,11 @@ static const ArrayType* arrayTypeFromSubsHelper(
} else if (instanceBct->id().symbolPath() ==
"DefaultAssociative.DefaultAssociativeArr" ||
instanceBct->id().symbolPath() ==
"ArrayViewReindex.ArrayViewReindexArr") {
"ArrayViewReindex.ArrayViewReindexArr" ||
instanceBct->id().symbolPath() ==
"ArrayViewSlice.ArrayViewSliceArr" ||
instanceBct->id().symbolPath() ==
"ArrayViewRankChange.ArrayViewRankChangeArr") {
auto [domInstanceQt] = extractFields(rc, instanceBct, "dom");
auto domain = domainTypeFromInstance(rc, domInstanceQt);
CHPL_ASSERT(domain);
Expand Down
6 changes: 5 additions & 1 deletion frontend/lib/resolution/Resolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5648,9 +5648,13 @@ void Resolver::exit(const Dot* dot) {

// Try to resolve a it as a field/parenless proc so we can resolve 'this' on
// it later if needed.
// Special case: Don't try to resolve calls to array.domain here, as we
// need to proceed to the handling logic below.
if (!receiver.type().isUnknown() && receiver.type().type() &&
receiver.type().type()->getCompositeType() &&
dot->field() != "init") {
dot->field() != USTR("init") &&
!(receiver.type().type()->isArrayType() &&
dot->field() == USTR("domain"))) {
Comment on lines +5651 to +5657
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you know how production does this? I assume it's not like this. I'd prefer to mimic production if possible.

Copy link
Contributor Author

@arifthpe arifthpe Apr 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's handled in convert-uast by just replacing any instance of .domain with ._dom:

} else if (member == USTR("domain")) {
return buildDotExpr(base, "_dom");

So I think this is a pretty faithful dyno equivalent

std::vector<CallInfoActual> actuals;
actuals.push_back(CallInfoActual(receiver.type(), USTR("this")));
auto ci = CallInfo(/* name */ dot->field(),
Expand Down
64 changes: 50 additions & 14 deletions frontend/test/resolution/testArrays.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,8 @@
#include "chpl/uast/Record.h"
#include "chpl/uast/Variable.h"

// TODO:
// - Slices

// Test using an array with a type expression consisting of the given domain
// and element type.
// Optionally accepts arguments to test indexing into the array with (in
// addition to doing so with the default value of the domain's index type).
static void testArray(std::string domainType,
std::string eltType,
std::string testIdxArg = "") {
std::string eltType) {
std::string arrayText;
arrayText += "[" + domainType + "] " + eltType;
printf("Testing array type expression: %s\n", arrayText.c_str());
Expand Down Expand Up @@ -94,8 +86,7 @@ module M {

// indexing
var idx : index(A.domain);
var x1 = A[idx];
var x2 = A[)""" + (testIdxArg.empty() ? "idx" : testIdxArg) + R"""(];
var x = A[idx];

// iteration
for loopI in A {
Expand Down Expand Up @@ -185,8 +176,7 @@ module M {
assert(findVarType(m, rr, "assocIndices").type()->isArrayType());
}

assert(findVarType(m, rr, "x1").type() == eType.type());
assert(findVarType(m, rr, "x2").type() == eType.type());
assert(findVarType(m, rr, "x").type() == eType.type());

assert(findVarType(m, rr, "z").type() == eType.type());

Expand Down Expand Up @@ -254,11 +244,52 @@ static void testArrayLiteral(std::string arrayLiteral, std::string domainType,
assert(guard.realizeErrors() == 0);
}

static void testArraySlicing(std::string arrayLiteral, std::string sliceArgs,
std::string resultType) {
printf("Testing slicing array %s with %s\n", arrayLiteral.c_str(),
sliceArgs.c_str());

Context* context = buildStdContext();
ErrorGuard guard(context);

auto vars = resolveTypesOfVariables(context,
R"""(
module M {
var A = )""" + arrayLiteral + R"""(;
var mySlice = A[)""" + sliceArgs + R"""(];
type gotSliceTy = mySlice.type;
type expectedSliceTy = )""" + resultType + R"""(;
}
)""",
{"A", "gotSliceTy", "expectedSliceTy"});
auto arrType = vars.at("A");
assert(arrType.type());
assert(!arrType.type()->isUnknownType());
assert(arrType.type()->isArrayType());

auto gotSliceTy = vars.at("gotSliceTy");
assert(gotSliceTy.type());
assert(!gotSliceTy.type()->isUnknownType());

auto expectedSliceTy = vars.at("expectedSliceTy");
assert(expectedSliceTy.type());
assert(!expectedSliceTy.type()->isUnknownType());

// Compare types approximately by stringifying, since they won't have the
// same underlying instance
std::stringstream ss1, ss2;
gotSliceTy.type()->stringify(ss1, chpl::StringifyKind::CHPL_SYNTAX);
expectedSliceTy.type()->stringify(ss2, chpl::StringifyKind::CHPL_SYNTAX);
assert(ss1.str() == ss2.str());

assert(guard.realizeErrors() == 0);
}

int main() {
// rectangular
testArray("domain(1)", "int");
testArray("domain(1)", "string");
testArray("domain(2)", "int", "0, 1");
testArray("domain(2)", "int");

// 1D literals
testArrayLiteral("[1, 2, 3]", "domain(1)", "int");
Expand All @@ -274,6 +305,11 @@ int main() {
testArrayLiteral("[1;]", "domain(2)", "int");
testArrayLiteral("[1, 2; 3, 4;; 5, 6; 7, 8]", "domain(3)", "int");

// slices
testArraySlicing("[1, 2, 3]", "0..1", "[0..1] int");
testArraySlicing("[1, 2; 3, 4]", "0, 1", "int"); // testing multi-dim indexing, not really a slice
testArraySlicing("[1, 2; 3, 4;; 5, 6; 7, 8]", "0..1, 0..1, 1", "[0..1, 0..1] int");

// associative
testArray("domain(int)", "int");
testArray("domain(int, true)", "int");
Expand Down