microsoft / qsharp-compiler

Q# compiler, command line tool, and Q# language server
https://docs.microsoft.com/quantum
MIT License
682 stars 171 forks source link

`EntryPoint` only accepts flat arguments #451

Open crazy4pi314 opened 4 years ago

crazy4pi314 commented 4 years ago

Describe the bug

The new @EntryPoint attribute does not take structured arguments (sensibly) as it is intended to work with command line applications. However, if I am using an @EntryPoint from a C# or other host I think it would make sense to be able to pass structured arguments. My use case is as follows (project here):

qsharp

    @EntryPoint()
    operation TestImplicitQRAM(queryAddress : Int, memoryData : (Int, Bool[])[]) : Int {
        ...
    }

I have a sample to demonstrate this new library, and I want to be able to "fuzz" it by generating random data for the qRAM to store and then query what is there after. The data is in the form of an array of tuples of (address, data-value) and I don't really want to de-structure this to pass into separate arguments of TestImplicitQRAM. Currently I am just hardcoding data to get around this but would really like to help work out a way to pass structured arguments from non-standalone hosts!

To Reproduce See the usecase linked to here: qRAM Library

Expected behavior

I expect that from non-standalone hosts (C#, F#, etc.) that @EntryPoint can accept arguments that are not flat (nested).

bamarsha commented 4 years ago

(Int, Bool[])[]

OK, this type is hitting two limitations of entry points at once. :)

  1. Tuples with unnamed items are not supported; this implies that arrays of tuples are also not supported.
  2. Arrays inside arrays are not supported.

I agree that it would be nice to support both of them, especially since we recommend using @EntryPoint even for programs with a C#/F#/Python host. For consistency I think we should support them in the default command-line interface as well.

We managed to avoid doing any particularly complicated parsing on the command-line by not supporting these types. For 1D arrays, those naturally map to a space-separated list of command-line arguments. For arrays of tuples and nested arrays, I don't see a way around a proper recursive parser that supports Q#-like syntax for unnamed tuples and nested arrays. So this would be:

--memory-data '(0, [true, false])' '(1, [true, true, true])' ...

where the quotes ' are there so that the shell treats it as one argument. Does this seem right or did you have a different syntax in mind?

By the way, for this specific case, is it possible to replace (Int, Bool[])[] with BigInt[], where the Int address is the index in the array and the Bool[] data is a BigInt - or do you need to support non-contiguous memory addresses?