Skip to content

Classical types indexing in OpenQASM #2564

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 5 commits into
base: main
Choose a base branch
from

Conversation

orpuente-MS
Copy link
Contributor

@orpuente-MS orpuente-MS commented Jun 24, 2025

This PR adds classical type indexing support to our OpenQASM compiler and fixes two bugs.

Highlights

The major challenge of this PR was supporting classical type indexing in the left-hand side of assignment expressions. The idea to make it work is compiling

int[4] a = 0b1111;
a[1:][1:] = "01";

to this

mutable a = 15;
a = {
    mutable bitarray = Std.OpenQASM.Convert.IntAsResultArrayBE(a, 4);
    bitarray[1...][1...] = [Zero, One];
    Std.OpenQASM.Convert.ResultArrayAsIntBE(bitarray)
};

so that we can leverage Q#'s array semantics.
 
The indexing infrastructure is now simpler. Instead of having different codepaths for indexed identifiers and indexed expressions, now we just have a codepath for indexed expressions. (The codepath for indexed identifiers was redundant).

Multiple indexing is now expressed as nested IndexedExpr structs with a single index each, instead of a single IndexedExpr with a list of indices. This makes thinking about indexing simpler, since now the utility functions to handle indexing just need to handle a single index. It also makes compilation simpler, since this is how the Q# AST is structured.

Bug fixes:

  1. Consecutive slices into an array now act on the same dimension, instead of acting on consecutive dimensions.
  2. AngleAsResultArrayBE is now correctly exported in the Angle.qs file instead of AngleAsResultArray.

Copy link

Change in memory usage detected by benchmark.

Memory Report for 11dfc2b

Test This Branch On Main Difference
compile core + standard lib 25669290 bytes 25677846 bytes -8556 bytes

Comment on lines +134 to 137
fn index_array(self, ctx: &mut Lowerer, index: &Index, collection_span: Span) -> Option<Self> {
if let LiteralKind::Bitstring(value, size) = self {
// A bit array accepts a single index.
if indices.len() != 1 {
ctx.push_const_eval_error(ConstEvalError::TooManyIndices(collection_span));
return None;
}

let index = indices.first().expect("there is exactly one index");

Self::index_bitarray(ctx, value, size, index)
} else {
Copy link
Collaborator

Choose a reason for hiding this comment

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

In what case can the bitarray take multiple indices?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You can apply multiple consecutive slices to a bitarray

const bit[4] a = "1010";
a[1:][1:]

Copy link

Change in memory usage detected by benchmark.

Memory Report for 966a8c5

Test This Branch On Main Difference
compile core + standard lib 25669290 bytes 25677846 bytes -8556 bytes

Copy link

Change in memory usage detected by benchmark.

Memory Report for 4b97c11

Test This Branch On Main Difference
compile core + standard lib 25669290 bytes 25677846 bytes -8556 bytes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants