quil-lang / quilc

The optimizing Quil compiler.
Apache License 2.0
457 stars 72 forks source link

920 quil spec 2024 1 conformance #921

Open macrologist opened 5 months ago

macrologist commented 5 months ago

See #920

This PR includes support for a number of requirements introduced into the forthcoming quil spec version 2024.1

Chief among the changes:

macrologist commented 5 months ago

There is now a fair bit of machinery in place surrounding the use of Externs. The following cases are supported:

  1. You want to specify the existence of externs available to the control hardware so that you can CALL them to mutate classical memory.
  2. You want to use externs within quilc numerical expressions that appear in defgate bodies or in gate parameter positions

Case 1 is simple.

In the following example, we assert that a function called randomize is available to some system that processes native Quil code. From what the fragment suggests, randomize probably sets the value of its first argument to some random in the range of its other two arguments:

EXTERN randomize 
DECLARE x REAL
CALL randomize x -3.1415 3.1415
RX(x) 0

Case 2 is more complicated.

In order to use an extern in an expression, the Quil standard insists that the function be known to not mutate any of its arguments, and that it return a value. The inclusion of the PRAGMA EXTERN into quilc satisfies these two requirements.

quilc will evaluate function calls in numeric expressions when those functions belong to a sanctioned list function names. In order to avoid surprises (i.e that extern functions also evaluate their arguments when able), we require that extern functions to appear within numeric expressions must also be registered with quilc. Unregistered functions will signal an error indicating as much. For the moment, this means that users who wish to make use of externs in their expressions must produce a custom build of quilc that registers those externs with the compiler.

Here we register a name "quadroot" for use as an extern.

(defun m-extensions::quadroot (val) (sqrt (sqrt val)))
(cl-quil::register-classical-function  "quadroot" 'my-extensions::quadroot)

We must still declare the extern and provide it a type in our Quil source code in order to benefit from the registered function

EXTERN quadroot
PRAGMA EXTERN quadroot "REAL (val:REAL)"
RX(quadroot(10.2)) 0