Skip to content

Commit

Permalink
Implement ctrl and negctrl gate modifiers
Browse files Browse the repository at this point in the history
  • Loading branch information
jlapeyre committed Jan 27, 2024
1 parent 0ed8cd4 commit 2012a93
Show file tree
Hide file tree
Showing 8 changed files with 253 additions and 17 deletions.
32 changes: 32 additions & 0 deletions crates/oq3_parser/src/grammar/expressions/atom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ pub(super) fn atom_expr(
T![for] => for_expr(p, None),
T![inv] => inv_modifier_expr(p),
T![pow] => pow_modifier_expr(p),
T![ctrl] => ctrl_modifier_expr(p),
T![negctrl] => negctrl_modifier_expr(p),
// FIXME: This is the simplest gate call. Need to cover
// `mygate(myparam) q1, q2;` as well.
IDENT if la == IDENT => gate_call_expr(p),
Expand Down Expand Up @@ -136,6 +138,36 @@ fn pow_modifier_expr(p: &mut Parser<'_>) -> CompletedMarker {
m.complete(p, POW_GATE_CALL_EXPR)
}

fn ctrl_modifier_expr(p: &mut Parser<'_>) -> CompletedMarker {
let m = p.start();
p.bump(T![ctrl]);
if p.at(T!['(']) {
let m1 = p.start();
p.expect(T!['(']);
expressions::expr(p);
p.expect(T![')']);
m1.complete(p, PAREN_EXPR);
}
p.expect(T![@]);
gate_call_expr(p);
m.complete(p, CTRL_GATE_CALL_EXPR)
}

fn negctrl_modifier_expr(p: &mut Parser<'_>) -> CompletedMarker {
let m = p.start();
p.bump(T![negctrl]);
if p.at(T!['(']) {
let m1 = p.start();
p.expect(T!['(']);
expressions::expr(p);
p.expect(T![')']);
m1.complete(p, PAREN_EXPR);
}
p.expect(T![@]);
gate_call_expr(p);
m.complete(p, NEG_CTRL_GATE_CALL_EXPR)
}

fn gate_call_expr(p: &mut Parser<'_>) -> CompletedMarker {
let m = p.start();
identifier(p); // name of gate
Expand Down
2 changes: 1 addition & 1 deletion crates/oq3_parser/src/syntax_kind/syntax_kind_enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ pub enum SyntaxKind {
QUANTUM_DECLARATION_STATEMENT,
INV_GATE_CALL_EXPR,
CTRL_GATE_CALL_EXPR,
NEGCTRL_GATE_CALL_EXPR,
NEG_CTRL_GATE_CALL_EXPR,
POW_GATE_CALL_EXPR,
#[doc(hidden)]
__LAST,
Expand Down
78 changes: 71 additions & 7 deletions crates/oq3_semantics/src/asg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ pub enum Expr {
GateCallExpr(Box<GateCallExpr>),
InvGateCallExpr(Box<InvGateCallExpr>),
PowGateCallExpr(Box<PowGateCallExpr>),
CtrlGateCallExpr(Box<CtrlGateCallExpr>),
NegCtrlGateCallExpr(Box<NegCtrlGateCallExpr>),
IndexExpression(IndexExpression),
IndexedIdentifier(IndexedIdentifier),
GateOperand(GateOperand),
Expand Down Expand Up @@ -619,13 +621,13 @@ pub struct GateCallExpr {
qubits: Vec<TExpr>,
}

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum GateModifier {
Inv,
Pow(TExpr),
Ctrl(Option<TExpr>),
NegCtrl(Option<TExpr>),
}
// #[derive(Clone, Debug, PartialEq, Eq, Hash)]
// pub enum GateModifier {
// Inv,
// Pow(TExpr),
// Ctrl(Option<TExpr>),
// NegCtrl(Option<TExpr>),
// }

// Following naming in ref parser instead
// We ~~will~~ should try to use the distinction between "parameter", which appears in the signature,
Expand Down Expand Up @@ -738,6 +740,68 @@ impl PowGateCallExpr {
}
}

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct CtrlGateCallExpr {
gate_call: TExpr,
exponent: Option<TExpr>,
}

impl CtrlGateCallExpr {
pub fn new(gate_call: TExpr, exponent: Option<TExpr>) -> CtrlGateCallExpr {
CtrlGateCallExpr {
gate_call,
exponent,
}
}

pub fn gate_call(&self) -> &TExpr {
&self.gate_call
}

pub fn exponent(&self) -> Option<&TExpr> {
self.exponent.as_ref()
}

pub fn to_expr(self) -> Expr {
Expr::CtrlGateCallExpr(Box::new(self))
}

pub fn to_texpr(self) -> TExpr {
TExpr::new(self.to_expr(), Type::ToDo)
}
}

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct NegCtrlGateCallExpr {
gate_call: TExpr,
exponent: Option<TExpr>,
}

impl NegCtrlGateCallExpr {
pub fn new(gate_call: TExpr, exponent: Option<TExpr>) -> NegCtrlGateCallExpr {
NegCtrlGateCallExpr {
gate_call,
exponent,
}
}

pub fn gate_call(&self) -> &TExpr {
&self.gate_call
}

pub fn exponent(&self) -> Option<&TExpr> {
self.exponent.as_ref()
}

pub fn to_expr(self) -> Expr {
Expr::NegCtrlGateCallExpr(Box::new(self))
}

pub fn to_texpr(self) -> TExpr {
TExpr::new(self.to_expr(), Type::ToDo)
}
}

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct GPhaseCall {
arg: TExpr,
Expand Down
19 changes: 19 additions & 0 deletions crates/oq3_semantics/src/syntax_to_semantics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,25 @@ fn from_expr(expr: synast::Expr, context: &mut Context) -> Option<asg::TExpr> {
Some(asg::PowGateCallExpr::new(gate_call, exponent).to_texpr())
}

synast::Expr::CtrlGateCallExpr(ctrl_gate_call) => {
let exponent = match ctrl_gate_call.paren_expr() {
Some(paren_expr) => from_paren_expr(paren_expr, context),
None => None,
};
let gate_call = from_gate_call_expr(ctrl_gate_call.gate_call_expr().unwrap(), context);
Some(asg::CtrlGateCallExpr::new(gate_call, exponent).to_texpr())
}

synast::Expr::NegCtrlGateCallExpr(neg_ctrl_gate_call) => {
let exponent = match neg_ctrl_gate_call.paren_expr() {
Some(paren_expr) => from_paren_expr(paren_expr, context),
None => None,
};
let gate_call =
from_gate_call_expr(neg_ctrl_gate_call.gate_call_expr().unwrap(), context);
Some(asg::NegCtrlGateCallExpr::new(gate_call, exponent).to_texpr())
}

// Everything else is not yet implemented
_ => {
println!("Expression not supported {:?}", expr);
Expand Down
8 changes: 8 additions & 0 deletions crates/oq3_syntax/openqasm3.ungram
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,8 @@ Expr =
| HardwareQubit
| InvGateCallExpr
| PowGateCallExpr
| CtrlGateCallExpr
| NegCtrlGateCallExpr

Identifier =
'ident'
Expand Down Expand Up @@ -303,6 +305,12 @@ InvGateCallExpr =
PowGateCallExpr =
'pow' ParenExpr '@' GateCallExpr

CtrlGateCallExpr =
'ctrl' ParenExpr? '@' GateCallExpr

NegCtrlGateCallExpr =
'negctrl' ParenExpr? '@' GateCallExpr

// label 'then_branch' is handled manually in expr_ext.rs
IfStmt =
'if' condition:Expr then_branch:Expr
Expand Down
94 changes: 94 additions & 0 deletions crates/oq3_syntax/src/ast/generated/nodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -711,6 +711,42 @@ impl PowGateCallExpr {
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct CtrlGateCallExpr {
pub(crate) syntax: SyntaxNode,
}
impl CtrlGateCallExpr {
pub fn ctrl_token(&self) -> Option<SyntaxToken> {
support::token(&self.syntax, T![ctrl])
}
pub fn paren_expr(&self) -> Option<ParenExpr> {
support::child(&self.syntax)
}
pub fn at_token(&self) -> Option<SyntaxToken> {
support::token(&self.syntax, T![@])
}
pub fn gate_call_expr(&self) -> Option<GateCallExpr> {
support::child(&self.syntax)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct NegCtrlGateCallExpr {
pub(crate) syntax: SyntaxNode,
}
impl NegCtrlGateCallExpr {
pub fn negctrl_token(&self) -> Option<SyntaxToken> {
support::token(&self.syntax, T![negctrl])
}
pub fn paren_expr(&self) -> Option<ParenExpr> {
support::child(&self.syntax)
}
pub fn at_token(&self) -> Option<SyntaxToken> {
support::token(&self.syntax, T![@])
}
pub fn gate_call_expr(&self) -> Option<GateCallExpr> {
support::child(&self.syntax)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ConcatenationExpr {
pub(crate) syntax: SyntaxNode,
}
Expand Down Expand Up @@ -1022,6 +1058,8 @@ pub enum Expr {
HardwareQubit(HardwareQubit),
InvGateCallExpr(InvGateCallExpr),
PowGateCallExpr(PowGateCallExpr),
CtrlGateCallExpr(CtrlGateCallExpr),
NegCtrlGateCallExpr(NegCtrlGateCallExpr),
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum GateOperand {
Expand Down Expand Up @@ -1849,6 +1887,36 @@ impl AstNode for PowGateCallExpr {
&self.syntax
}
}
impl AstNode for CtrlGateCallExpr {
fn can_cast(kind: SyntaxKind) -> bool {
kind == CTRL_GATE_CALL_EXPR
}
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
} else {
None
}
}
fn syntax(&self) -> &SyntaxNode {
&self.syntax
}
}
impl AstNode for NegCtrlGateCallExpr {
fn can_cast(kind: SyntaxKind) -> bool {
kind == NEG_CTRL_GATE_CALL_EXPR
}
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
} else {
None
}
}
fn syntax(&self) -> &SyntaxNode {
&self.syntax
}
}
impl AstNode for ConcatenationExpr {
fn can_cast(kind: SyntaxKind) -> bool {
kind == CONCATENATION_EXPR
Expand Down Expand Up @@ -2373,6 +2441,16 @@ impl From<PowGateCallExpr> for Expr {
Expr::PowGateCallExpr(node)
}
}
impl From<CtrlGateCallExpr> for Expr {
fn from(node: CtrlGateCallExpr) -> Expr {
Expr::CtrlGateCallExpr(node)
}
}
impl From<NegCtrlGateCallExpr> for Expr {
fn from(node: NegCtrlGateCallExpr) -> Expr {
Expr::NegCtrlGateCallExpr(node)
}
}
impl AstNode for Expr {
fn can_cast(kind: SyntaxKind) -> bool {
matches!(
Expand All @@ -2396,6 +2474,8 @@ impl AstNode for Expr {
| HARDWARE_QUBIT
| INV_GATE_CALL_EXPR
| POW_GATE_CALL_EXPR
| CTRL_GATE_CALL_EXPR
| NEG_CTRL_GATE_CALL_EXPR
)
}
fn cast(syntax: SyntaxNode) -> Option<Self> {
Expand All @@ -2419,6 +2499,8 @@ impl AstNode for Expr {
HARDWARE_QUBIT => Expr::HardwareQubit(HardwareQubit { syntax }),
INV_GATE_CALL_EXPR => Expr::InvGateCallExpr(InvGateCallExpr { syntax }),
POW_GATE_CALL_EXPR => Expr::PowGateCallExpr(PowGateCallExpr { syntax }),
CTRL_GATE_CALL_EXPR => Expr::CtrlGateCallExpr(CtrlGateCallExpr { syntax }),
NEG_CTRL_GATE_CALL_EXPR => Expr::NegCtrlGateCallExpr(NegCtrlGateCallExpr { syntax }),
_ => return None,
};
Some(res)
Expand All @@ -2444,6 +2526,8 @@ impl AstNode for Expr {
Expr::HardwareQubit(it) => &it.syntax,
Expr::InvGateCallExpr(it) => &it.syntax,
Expr::PowGateCallExpr(it) => &it.syntax,
Expr::CtrlGateCallExpr(it) => &it.syntax,
Expr::NegCtrlGateCallExpr(it) => &it.syntax,
}
}
}
Expand Down Expand Up @@ -2889,6 +2973,16 @@ impl std::fmt::Display for PowGateCallExpr {
std::fmt::Display::fmt(self.syntax(), f)
}
}
impl std::fmt::Display for CtrlGateCallExpr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
}
}
impl std::fmt::Display for NegCtrlGateCallExpr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
}
}
impl std::fmt::Display for ConcatenationExpr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
Expand Down
Loading

0 comments on commit 2012a93

Please sign in to comment.