Chapel: Indexing into an array literal results in surprising behavior

Created on 17 Dec 2020  Â·  4Comments  Â·  Source: chapel-lang/chapel

Summary of Problem

When indexing into an array literal, like [1, 2, 3][1], we seem to get 1 1 1 as the output rather than 2, as expected. My guess is that this is being interpreted as an index-less loop expression for reasons that aren't clear to me (e.g., equivalent to [i in [1, 2, 3]] [1]) and seem incorrect.

Steps to Reproduce

Associated Future Test(s):
test/arrays/indexing/arrLitIndexing.chpl #16882

Configuration Information

  • Output of chpl --version: chpl version 1.24.0 pre-release (c3cb383326)
Compiler Bug

Most helpful comment

I suspect this is probably a fairly simple fix

It looks like I may have been overly optimistic. It seems that the following rule in the parser:

| TLSBR expr_ls TRSBR expr %prec TFOR

currently handles this [1, 2, 3][1] case, as well as [D] real as a type expression and [D] i as a forall expression. I was hoping that I could change it to:

| TLSBR expr TRSBR expr %prec TFOR

to handle the latter two, causing the former to fall into the normal "array literal" + "indexing" rules, but this results in conflicts (which can also probably be dealt with, but with more effort than I was hoping for).

All 4 comments

This isn't particularly high priority, but I ran across it while reviewing Engin's "index string literal" PR (#16879) and wanted to note it before forgetting.

Trying the issue with chapel-1.22.0, the literal seems to give the expected result when enclosed with ().
Though I have no idea what () does, is it possible that the difference between [literal] and ([literal]) might have some clue for the unexpected behavior of [literal]?

writeln( [1, 2, 3][1] );  // 1 1 1

writeln( ( [1, 2, 3] )[1] );  // 2

writeln( [i in [1, 2, 3]][1] );  // 1 1 1

// writeln( ( [i in [1, 2, 3]] )[1] );  // syntax error: near ')'

// writeln( "hello"[0] ); // syntax error: near '['

writeln( ("hello")[0] ); // h

Hi @ty1027 — Thanks for those observations. I think that this bolsters the theory that the expression is incorrectly being treated as a loop expression, in the sense that the parenthesis would force the [1, 2, 3] expression to be evaluated in isolation first, and made into an array literal. The reason I think it's inappropriate for the compiler to treat [1, 2, 3] as a loop expression is that a loop expression shouldn't support a top-level comma-separated list of expressions. That is, while I can say something like [a in A] I shoud not be able to say something like [elem in A, B, C] and therefore shouldn't be able to say [A, B, C] (dropping the loop index). Instead, in both forms the A, B, C should be put into some sort of collection like a tuple, array, or domain.

I suspect this is probably a fairly simple fix, where something is automatically wrapping them in a collection but shouldn't. But I haven't had time to look into it yet (and wasn't sure I'd be able to before our holiday break starts).

I suspect this is probably a fairly simple fix

It looks like I may have been overly optimistic. It seems that the following rule in the parser:

| TLSBR expr_ls TRSBR expr %prec TFOR

currently handles this [1, 2, 3][1] case, as well as [D] real as a type expression and [D] i as a forall expression. I was hoping that I could change it to:

| TLSBR expr TRSBR expr %prec TFOR

to handle the latter two, causing the former to fall into the normal "array literal" + "indexing" rules, but this results in conflicts (which can also probably be dealt with, but with more effort than I was hoping for).

Was this page helpful?
0 / 5 - 0 ratings