Skip to content

Conversation

@antalsz
Copy link
Contributor

@antalsz antalsz commented Mar 24, 2025

This branch adds support for multi-argument functions in Quil expressions, so you can write e.g.

SET-PHASE 0 "tx0" 2*some_extern_function(x, sin(y), z*z)

The major weakness of this PR is that I had to manually expand a call to rigetti_pyo3::py_wrap_union_enum! in quil_py/src/expression.rs and edit the result due to some type errors I couldn't fix. This has proven very difficult to address.

One question for this MR, that can block merge or not as we decide, is what to do about type checking for extern function calls in expressions. Typechecking can be more complex now; there's a "FUTURE WORK" comment in quil_rs::program::type_check::should_be_real where we simply punt on checking extern functions. This isn't a regression, as it doesn't affect existing programs, and it's similar to how we don't check CALL instructions now (although for those we always succeed, and for extern functions in expressions we always fail). Fixing this would require either (1) ignoring non-real function arguments, or (2) doing actual type-checking on those. Both are entirely doable but maybe not necessary for v1.

@github-actions
Copy link

github-actions bot commented Mar 24, 2025

PR Preview Action v1.6.0

🚀 View preview at
https://rigetti.github.io/quil-rs/pr-preview/pr-446/

Built to branch quil-py-docs at 2025-03-26 19:57 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

Copy link
Collaborator

@erichulburd erichulburd left a comment

Choose a reason for hiding this comment

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

I've a added a couple discussions to resolve before approving.

Copy link
Collaborator

@erichulburd erichulburd left a comment

Choose a reason for hiding this comment

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

I encourage making the documentation comment above, but I otherwise agree to merge as-is.

I do think we should create three follow on issues (or add a comment where they might otherwise exist):

  1. Implement argument resolution for FunctionCallExpression. Essentially, we get the ExternSignatureMap from Program::try_extern_signature_map_from_pragma_map and then do something analogous to Call:resolve_arguments. This may not be strictly required for downstream implementations, but it seems most appropriate to keep them in quil-rs. If this turns out to be sub-optimal for some reason or other, we can let the issue languish or close it out with an explanation.
  2. Implement type checking for CALL and FunctionCallExpression. Will build on the mechanics established in (1).
  3. Support expressions in CALL, MOVE, ADD, and other classical instructions. This otherwise imposes unnecessary restrictions in Quil expressiveness. We should open a PR to get this change into the spec prior to implementation.

Expression::FunctionCall(FunctionCallExpression { expression, .. }) => {
expression.get_memory_references()
}
Expression::FunctionCall(FunctionCallExpression { arguments, .. }) => arguments
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think somewhere we should explicitly reference the quote you pulled from the spec:

Extern CALLs may appear in arithmetic expressions with some restrictions: the extern MUST have a declared function signature, which MUST include a return type, and which MUST NOT include any mutable parameters.

This is why we can simply return Vec<MemoryReference> here (all presumed to be reads), while Call::get_memory_accesses returns a MemoryAccessesResult.

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