Skip to content

Add the missing built-in constant-expression functions (#390) - #407

Draft
TheGupta2012 wants to merge 1 commit into
feature-385-391-bit-repr-negative-indicesfrom
feature-390-builtin-const-functions
Draft

Add the missing built-in constant-expression functions (#390)#407
TheGupta2012 wants to merge 1 commit into
feature-385-391-bit-repr-negative-indicesfrom
feature-390-builtin-const-functions

Conversation

@TheGupta2012

Copy link
Copy Markdown
Member

Closes #390.

Problem

FUNCTION_MAP provided only 10 of the spec's built-in constant expression functions. ceiling, floor, exp, log, mod, popcount, rotl, and rotr all failed with the generic Invalid initialization value for constant 'c', in a const initializer and as a gate argument alike. The evaluator also passed only arguments[0], so no multi-argument function could work and sqrt(2.0, 3.0) was silently accepted.

Approach

  • FUNCTION_MAP now maps each name to (implementation, arity). The evaluator dispatches through a single _evaluate_builtin_function, which checks arity, evaluates every argument, and turns a TypeError / ValueError from the implementation into a located error.
  • rotl / rotr preserve the operand's declared width. The width comes from a BitValue, a bitstring literal, or the declaration of a bit[n] / uint[n] identifier. A widthless operand (rotl(37, 3)) is rejected rather than given a guessed width.
  • A new FunctionCallError(ValidationError) covers an unknown name, a wrong arity, and a wrong argument type. raise_qasm3_error merges it into the statement-level message, so the user gets both the context and the function name: Invalid initialization value for constant 'c': Function 'sqrt' expects 1 argument(s), but 2 were given. One change site instead of one per wrapper, and no existing message is altered.
  • _handle_function_init_expression emits a BitstringLiteral for a BitValue assigned to a bit[n], and an IntegerLiteral for an integral result. np.mod returns np.int64, which the old isinstance check missed, leaving mod(7, 2) un-unrolled in the output.

Tests

tests/qasm3/test_expressions.py, 22 new cases: every function in both a const initializer and a gate argument; rotl(a, n) == rotr(a, -n) and width preservation across rotations of 0, 1, 3, 8, 11, and -3; width recovery from a uint[8] declaration; arity errors for 1-, 2-, and 0-argument mistakes; type errors for ceiling("01"), rotl("1010", 1.5), popcount(1.5), and rotl(37, 3); and the unknown-name message.

pow

const int c = pow(2, 3); still fails at parse time in openqasm3 1.0.1, verified against the installed version — pow is also the gate-modifier keyword, so the grammar cannot tell the two apart.

No upstream issue should be filed. Upstream already removed pow from the spec for exactly this reason: openqasm/openqasm#627 proposed the deprecation, and openqasm/openqasm#635 landed it on 2025-10-15. ** is the supported spelling and pyqasm already handles it. A test pins both halves of that: pow(2, 3) raises a parse error, 2 ** 3 validates.

Stacked on #404 (feature-385-391-bit-repr-negative-indices); rebases onto main once #404 merges.

🤖 Generated with Claude Code

Adds ceiling, floor, exp, log, mod, popcount, rotl, and rotr to FUNCTION_MAP,
each usable in a const initializer and as a gate argument.

FUNCTION_MAP now carries an arity alongside each implementation, so the
evaluator can dispatch multi-argument calls and reject a wrong argument count.
rotl and rotr preserve the operand's declared width by resolving it from a
BitValue, a bitstring literal, or the declaration of a bit[n] / uint[n]
identifier; a widthless operand is rejected rather than given a guessed width.

An unknown function name, a wrong arity, or a wrong argument type now raises a
FunctionCallError, which raise_qasm3_error merges into the statement-level
message so the offending function is named instead of only reporting
"Invalid initialization value".

pow is excluded: it is ambiguous with the gate modifier of the same name, and
upstream removed it from the spec in openqasm/openqasm#635.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@argus-eye

argus-eye Bot commented Aug 24, 2026

Copy link
Copy Markdown

Argus review

Auto-review is off for this repo. Tick the box below to run a review on this PR.

  • Trigger Argus review

Estimated cost

  • Files changed: 6
  • Diff lines (±): 278
  • Historical avg: ~243.6k tokens · ~$0.95 · across last 10 review(s)

Tip: you can also comment @argus-eye review at any time.

@coderabbitai

coderabbitai Bot commented Aug 24, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: ea048537-3ee9-48a8-8593-caf87640459a

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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.

1 participant