Skip to content

Negative indices and negative ranges are rejected on arrays, registers and aliases #391

Description

@TheGupta2012

Limitation

OpenQASM 3 indexes from the end with negative integers, where -1 is the last element. The
spec uses this in Arrays,
Classical value bit slicing and
Register concatenation and slicing.

pyqasm treats every index as non-negative. Negative indices either produce an
out-of-range error or a generic initialisation error.

Example QASM failure

Arrays — straight from the spec's Arrays section:

OPENQASM 3.0;
array[int[32], 5] myArray = {0, 1, 2, 3, 4};
int[32] alsoLastElem = myArray[-1];        // 4
// ValidationError: Invalid initialization value for variable 'alsoLastElem'
OPENQASM 3.0;
array[float[32], 3, 2] multiDim = {{1.1, 1.2}, {2.1, 2.2}, {3.1, 3.2}};
float[32] alsoLastLastElem = multiDim[-1, -1];   // 3.2
// ValidationError: Invalid initialization value for variable 'x'

Negative index as an assignment target:

OPENQASM 3.0;
array[int[32], 5] a = {0, 1, 2, 3, 4};
a[-1] = 10;
// ValidationError: Invalid index for variable 'a'

Qubit registers:

OPENQASM 3.0;
include "stdgates.inc";
qubit[4] q;
h q[-1];
// ValidationError: Index -1 out of range for register of size 4 in qubit

Negative ranges, from the spec's Register concatenation and slicing section:

OPENQASM 3.0;
qubit[6] two;
let last_three = two[-4:-1];
// ValidationError: Index -4 out of range for register of size 6 in qubit

Bit registers:

OPENQASM 3.0;
bit[4] b = "1010";
bit c = b[-1];
// ValidationError: Invalid initialization value for variable 'c'

Change Requested

  1. Normalise a negative index i on a dimension of size n to i + n before the bounds
    check, everywhere an index is resolved.
  2. Apply the same normalisation to both endpoints of a range expression, including the
    stepped form [-4:2:-1].
  3. Support this uniformly across arrays (including multi-dimensional and assignment targets),
    bit[n], qubit[n], and let aliases.
  4. After normalisation, an index still outside [0, n) must raise the existing out-of-range
    ValidationError — reporting the index as written in the source, not the normalised value.

Implementation Details

  • The single most valuable change is a shared helper, e.g.
    Qasm3Analyzer.normalize_index(index: int, size: int, span) -> int, applied at every index
    resolution site so the behaviour cannot drift between paths.
  • Call sites to update in src/pyqasm/analyzer.py: analyze_classical_indices and the qubit
    index validation that produces "Index -1 out of range for register of size 4".
  • Range handling lives in Qasm3Transformer.get_qubits_from_range_definition
    (src/pyqasm/transformer.py:129) and get_target_qubits
    (src/pyqasm/transformer.py:383). Both endpoints need normalising before the range is
    expanded, and the step sign must still be honoured afterwards.
  • Watch the interaction with remove_idle_qubits / reverse_qubit_order, which rewrite
    indices post-unroll. Since normalisation happens during resolution, they should see only
    concrete non-negative indices — worth an explicit test to confirm.
  • Note the spec's reversed form myInt[-1:-16], which is a descending range. Confirm the
    intended iteration order and cover it.
  • Tests: extend tests/qasm3/ array, alias and measurement tests with negative reads, negative
    writes, negative ranges, stepped negative ranges, and an out-of-range negative index that
    must still error.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

enhancementNew feature or requestllm-assistedUsed LLMs to fine tune issue description.qasm3Related to openqasm3qasm3-coverageAdding support for qasm3 constructs

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions