Skip to content

Commit

Permalink
Support pow gate modifier
Browse files Browse the repository at this point in the history
  • Loading branch information
jlapeyre committed Jan 27, 2024
1 parent 2744aa5 commit 0ed8cd4
Show file tree
Hide file tree
Showing 11 changed files with 149 additions and 96 deletions.
2 changes: 0 additions & 2 deletions crates/oq3_parser/src/grammar/expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -343,8 +343,6 @@ fn postfix_expr(
}

// Consumes either a function (def) call, or a gate call.
// expressions::gate_call_stmt also consumes gate calls in a different context.
// I think the present function gets all gate calls that include params in parens.
fn call_expr(p: &mut Parser<'_>, lhs: CompletedMarker) -> CompletedMarker {
assert!(p.at(T!['(']));
let m = lhs.precede(p);
Expand Down
35 changes: 27 additions & 8 deletions crates/oq3_parser/src/grammar/expressions/atom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ pub(super) fn atom_expr(
T!['{'] => block_expr(p),
T![for] => for_expr(p, None),
T![inv] => inv_modifier_expr(p),
T![pow] => pow_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 All @@ -105,25 +106,43 @@ pub(super) fn atom_expr(

fn inv_modifier_expr(p: &mut Parser<'_>) -> CompletedMarker {
let m = p.start();
assert!(p.at(T![inv]));
p.bump(T![inv]);
p.expect(T![@]);
if p.at(T![@]) {
p.bump(T![@]);
} else if p.at(T!['(']) {
p.error("Modifier `inv` accepts no parameter. Expecting `@`");
} else {
p.error("Expecting `@`");
}
gate_call_expr(p);
m.complete(p, INV_GATE_CALL_EXPR)
}

fn pow_modifier_expr(p: &mut Parser<'_>) -> CompletedMarker {
let m = p.start();
assert!(p.at(T![pow]));
p.bump(T![pow]);
if p.at(T!['(']) {
let m1 = p.start();
p.expect(T!['(']);
expressions::expr(p);
p.expect(T![')']);
m1.complete(p, PAREN_EXPR);
} else {
p.error("expecting argument to pow gate modifier");
}
p.expect(T![@]);
gate_call_expr(p);
m.complete(p, POW_GATE_CALL_EXPR)
}

fn gate_call_expr(p: &mut Parser<'_>) -> CompletedMarker {
let m = p.start();
// expressions::var_name(p);
identifier(p); // name of gate
// disable following assert, because we may arrive here from gate modifiers
// assert!(!p.at(T!['(']));
// This is never true, I hope
if p.at(T!['(']) {
expressions::call_arg_list(p);
}
params::arg_list_gate_call_qubits(p);
// p.expect(SEMICOLON);
m.complete(p, GATE_CALL_EXPR)
}

Expand All @@ -147,7 +166,7 @@ fn measure_expression(p: &mut Parser<'_>) -> CompletedMarker {
// FIXME: changed it back to IDENTIFIER
pub(crate) fn identifier(p: &mut Parser<'_>) -> CompletedMarker {
let m = p.start();
p.bump(IDENT);
p.expect(IDENT);
m.complete(p, IDENTIFIER)
}

Expand Down
67 changes: 0 additions & 67 deletions crates/oq3_parser/src/grammar/items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,6 @@ pub(super) fn opt_item(p: &mut Parser<'_>, m: Marker) -> Result<(), Marker> {
match p.current() {
T![qubit] => qubit_declaration_stmt(p, m),
T![const] => expressions::classical_declaration_stmt(p, m),
// IDENT if (la == IDENT || la == HARDWAREIDENT) => gate_call_stmt(p, m),
IDENT if (la == T![=] && p.nth(2) != T![=]) => assignment_statement_with_marker(p, m),
T![gate] => gate_definition(p, m),
T![break] => break_(p, m),
Expand All @@ -120,33 +119,13 @@ pub(super) fn opt_item(p: &mut Parser<'_>, m: Marker) -> Result<(), Marker> {
T![OPENQASM] => version_string(p, m),
T![include] => include(p, m),
T![gphase] => gphase_call(p, m),
// T![pow] => pow_modifier(p, m),
// T![ctrl] => ctrl_modifier(p, m),
// T![negctrl] => negctrl_modifier(p, m),
// This is already done elsewhere
// T![let] => let_stmt(p, m),
_ => return Err(m),
}
Ok(())
}

// expressions::call_expr also handles some occurences of gate calls
// FIXME: params in parens are likely always caught in expressions::call_expr
fn gate_call_stmt(p: &mut Parser<'_>, m: Marker) {
println!("*******************************************************************");
// expressions::var_name(p);
expressions::atom::identifier(p); // name of gate
// disable following assert, because we may arrive here from gate modifiers
// assert!(!p.at(T!['(']));
// This is never true, I hope
if p.at(T!['(']) {
expressions::call_arg_list(p);
}
params::arg_list_gate_call_qubits(p);
p.expect(SEMICOLON);
m.complete(p, GATE_CALL_STMT);
}

fn gphase_call(p: &mut Parser<'_>, m: Marker) {
assert!(p.at(T![gphase]));
p.bump(T![gphase]);
Expand All @@ -155,52 +134,6 @@ fn gphase_call(p: &mut Parser<'_>, m: Marker) {
m.complete(p, G_PHASE_CALL_STMT);
}

// fn pow_modifier(p: &mut Parser<'_>, m: Marker) {
// assert!(p.at(T![pow]));
// p.bump(T![pow]);
// if p.at(T!['(']) {
// p.expect(T!['(']);
// expressions::expr(p);
// p.expect(T![')']);
// } else {
// p.error("expecting argument to pow gate modifier");
// }
// p.expect(T![@]);
// println!("***********************************************");
// let m1 = p.start();
// println!("***********************************************");
// gate_call_stmt(p, m1);
// m.complete(p, MODIFIED_GATE_CALL);
// }

// fn ctrl_modifier(p: &mut Parser<'_>, m: Marker) {
// assert!(p.at(T![ctrl]));
// p.bump(T![ctrl]);
// if p.at(T!['(']) {
// p.bump(T!['(']);
// expressions::expr(p);
// p.expect(T![')']);
// }
// p.expect(T![@]);
// let m1 = p.start();
// gate_call_stmt(p, m1);
// m.complete(p, MODIFIED_GATE_CALL);
// }

// fn negctrl_modifier(p: &mut Parser<'_>, m: Marker) {
// assert!(p.at(T![negctrl]));
// p.bump(T![negctrl]);
// if p.at(T!['(']) {
// p.bump(T!['(']);
// expressions::expr(p);
// p.expect(T![')']);
// }
// p.expect(T![@]);
// let m1 = p.start();
// gate_call_stmt(p, m1);
// m.complete(p, MODIFIED_GATE_CALL);
// }

fn if_stmt(p: &mut Parser<'_>, m: Marker) {
assert!(p.at(T![if]));
// let m = p.start();
Expand Down
2 changes: 0 additions & 2 deletions crates/oq3_parser/src/grammar/params.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,6 @@ fn _param_list_openqasm(p: &mut Parser<'_>, flavor: DefFlavor, m: Option<Marker>
let m = param_marker.take().unwrap_or_else(|| p.start());
if !(p.current().is_type_name() || p.at_ts(PARAM_FIRST)) {
p.error("expected value parameter");
println!("!!!! Got {:?}", p.current());
m.abandon(p);
break;
}
Expand All @@ -118,7 +117,6 @@ fn _param_list_openqasm(p: &mut Parser<'_>, flavor: DefFlavor, m: Option<Marker>
expressions::expr_or_range_expr(p);
true
}
// SetExpression => { m.abandon(p); expressions::expr(p); true }
GateCallQubits => arg_gate_call_qubit(p, m),
DefParams | DefCalParams => param_typed(p, m),
_ => param_untyped(p, m),
Expand Down
8 changes: 3 additions & 5 deletions crates/oq3_parser/src/syntax_kind/syntax_kind_enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,12 +225,10 @@ pub enum SyntaxKind {
MEASURE_EXPRESSION,
OLD_STYLE_DECLARATION_STATEMENT,
QUANTUM_DECLARATION_STATEMENT,
INV_GATE_CALL,
INV_GATE_CALL_EXPR,
CTRL_GATE_CALL,
NEGCTRL_GATE_CALL,
POW_GATE_CALL,
MODIFIED_GATE_CALL,
CTRL_GATE_CALL_EXPR,
NEGCTRL_GATE_CALL_EXPR,
POW_GATE_CALL_EXPR,
#[doc(hidden)]
__LAST,
}
Expand Down
40 changes: 40 additions & 0 deletions crates/oq3_semantics/src/asg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ pub enum Expr {
HardwareQubit(HardwareQubit),
GateCallExpr(Box<GateCallExpr>),
InvGateCallExpr(Box<InvGateCallExpr>),
PowGateCallExpr(Box<PowGateCallExpr>),
IndexExpression(IndexExpression),
IndexedIdentifier(IndexedIdentifier),
GateOperand(GateOperand),
Expand Down Expand Up @@ -696,6 +697,45 @@ impl InvGateCallExpr {
pub fn gate_call(&self) -> &TExpr {
&self.gate_call
}

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

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

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

impl PowGateCallExpr {
pub fn new(gate_call: TExpr, exponent: TExpr) -> PowGateCallExpr {
PowGateCallExpr {
gate_call,
exponent,
}
}

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

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

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

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

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
Expand Down
25 changes: 20 additions & 5 deletions crates/oq3_semantics/src/syntax_to_semantics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,9 +189,14 @@ fn from_expr_stmt(expr_stmt: synast::ExprStmt, context: &mut Context) -> Option<
)
}

fn from_paren_expr(paren_expr: synast::ParenExpr, context: &mut Context) -> Option<asg::TExpr> {
from_expr(paren_expr.expr().unwrap(), context)
}

fn from_expr(expr: synast::Expr, context: &mut Context) -> Option<asg::TExpr> {
match expr {
synast::Expr::ParenExpr(paren_expr) => from_expr(paren_expr.expr().unwrap(), context),
// synast::Expr::ParenExpr(paren_expr) => from_expr(paren_expr.expr().unwrap(), context),
synast::Expr::ParenExpr(paren_expr) => from_paren_expr(paren_expr, context),
synast::Expr::BinExpr(bin_expr) => {
let synast_op = bin_expr.op_kind().unwrap();
let left_syn = bin_expr.lhs().unwrap();
Expand Down Expand Up @@ -241,10 +246,20 @@ fn from_expr(expr: synast::Expr, context: &mut Context) -> Option<asg::TExpr> {

synast::Expr::GateCallExpr(gate_call) => Some(from_gate_call_expr(gate_call, context)),

synast::Expr::InvGateCallExpr(inv_gate_call) => Some(from_gate_call_expr(
inv_gate_call.gate_call_expr().unwrap(),
context,
)),
synast::Expr::InvGateCallExpr(inv_gate_call) => Some(
asg::InvGateCallExpr::new(from_gate_call_expr(
inv_gate_call.gate_call_expr().unwrap(),
context,
))
.to_texpr(),
),

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

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

Identifier =
'ident'
Expand Down Expand Up @@ -299,6 +300,9 @@ GPhaseCallStmt =
InvGateCallExpr =
'inv' '@' GateCallExpr

PowGateCallExpr =
'pow' ParenExpr '@' GateCallExpr

// label 'then_branch' is handled manually in expr_ext.rs
IfStmt =
'if' condition:Expr then_branch:Expr
Expand Down
Loading

0 comments on commit 0ed8cd4

Please sign in to comment.