Skip to content

Commit

Permalink
Partially implement parsing measure from text through ASG
Browse files Browse the repository at this point in the history
Statements like `c = measure q` are analyzed correctly.
But `c[0] = measure q` is not analyzed correctly. The code
that builds the assignment statement assumes the LHS is an identifier.
The ASG should be able to handle valid lvalues. But we cannot yet
construct statements with them.
  • Loading branch information
jlapeyre committed Jan 17, 2024
1 parent ff464b8 commit 5e0ad92
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 9 deletions.
6 changes: 4 additions & 2 deletions crates/oq3_parser/src/grammar/items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,11 +233,13 @@ pub(crate) fn ident_or_index_expr(p: &mut Parser<'_>) {
p.bump(IDENT);
match p.current() {
T!['['] => {
let newm = m.complete(p, IDENT);
let newm = m.complete(p, IDENTIFIER);
expressions::index_expr(p, newm);
}
_ => {
m.complete(p, IDENT);
// FIXME: m.complete(p, IDENT) is valid, but it should not be
// it is a source of bugs!
m.complete(p, IDENTIFIER);
}
}
}
Expand Down
19 changes: 18 additions & 1 deletion crates/oq3_semantics/src/asg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ pub enum Expr {
Range(Range),
Call, // stub function (def) call
Set, // stub
Measure, // stub
MeasureExpression(MeasureExpression),
}

/// Typed expression implemented by tagging an `Expr` with a `Type`.
Expand Down Expand Up @@ -562,6 +562,23 @@ impl GateDeclaration {
}
}

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct MeasureExpression {
operand: Box<TExpr>,
}

impl MeasureExpression {
pub fn new(operand: TExpr) -> MeasureExpression {
MeasureExpression { operand: Box::new(operand) }
}

// FIXME: type may not be correct here.
// This assumes a single qubit is measured.
pub fn to_texpr(self) -> TExpr {
TExpr::new(Expr::MeasureExpression(self), Type::Bit(IsConst::False))
}
}

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct GateCall {
name: SymbolIdResult,
Expand Down
37 changes: 32 additions & 5 deletions crates/oq3_semantics/src/syntax_to_semantics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,9 @@ pub fn syntax_to_semantic<T: SourceTrait>(

fn from_expr_stmt(expr_stmt: synast::ExprStmt, context: &mut Context) -> Option<asg::Stmt> {
let expr = from_expr(expr_stmt.expr().unwrap(), context);
if expr.is_none() {
dbg!(expr_stmt);
}
expr.map_or_else(
|| panic!("expr::ExprStmt is None"),
|ex| Some(asg::Stmt::ExprStmt(ex)),
Expand Down Expand Up @@ -228,14 +231,38 @@ fn from_expr(expr: synast::Expr, context: &mut Context) -> Option<asg::TExpr> {
Some(indexed_identifier.to_texpr())
}

synast::Expr::MeasureExpression(_measure_expr) => None,
synast::Expr::MeasureExpression(ref measure_expr) => {
let gate_operand = measure_expr.gate_operand().unwrap(); // FIXME: check this
let gate_operand_asg = from_gate_operand(gate_operand, context);
Some(asg::MeasureExpression::new(gate_operand_asg).to_texpr())
}

// Everything else is not yet implemented
_ => {
println!("Expression not supported {:?}", expr);
println!("MeasureExpression not supported {:?}", expr);
None
}
}
}

fn from_gate_operand(gate_operand: synast::GateOperand, context: &mut Context) -> asg::TExpr {
match gate_operand {
synast::GateOperand::HardwareQubit(ref hwq) => {
asg::GateOperand::HardwareQubit(ast_hardware_qubit(hwq))
.to_texpr(Type::HardwareQubit)
}
synast::GateOperand::Identifier(identifier) => {
let (astidentifier, typ) = ast_identifier(&identifier, context);
asg::GateOperand::Identifier(astidentifier).to_texpr(typ)
}
synast::GateOperand::IndexedIdentifier(indexed_identifier) => {
let (indexed_identifier, typ) =
ast_indexed_identifier(&indexed_identifier, context);
asg::GateOperand::IndexedIdentifier(indexed_identifier).to_texpr(typ)
}
}
}

fn from_index_operator(
index_op: synast::IndexOperator,
context: &mut Context,
Expand Down Expand Up @@ -571,19 +598,19 @@ fn from_assignment_stmt(
assignment_stmt: &synast::AssignmentStmt,
context: &mut Context,
) -> Option<asg::Stmt> {
let nameb = assignment_stmt.name();
let nameb = assignment_stmt.name(); // LHS of assignment
let name = nameb.as_ref().unwrap();
let name_str = name.string();
let expr = from_expr(assignment_stmt.expr().unwrap(), context); // rhs of `=` operator

let (symbol_id, typ) = context.lookup_symbol(name_str.as_str(), name).as_tuple();
let is_mutating_const = symbol_id.is_ok() && typ.is_const();
let lvalue = asg::LValue::Identifier(symbol_id);
let ret_stmt = Some(asg::Assignment::new(lvalue, expr.unwrap()).to_stmt());
let stmt_asg = Some(asg::Assignment::new(lvalue, expr.unwrap()).to_stmt());
if is_mutating_const {
context.insert_error(MutateConstError, assignment_stmt);
}
ret_stmt
stmt_asg
}

//
Expand Down
3 changes: 2 additions & 1 deletion crates/oq3_semantics/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,8 @@ impl Type {
pub fn is_const(&self) -> bool {
use Type::*;
match self {
Bit(c) | Int(_, c) => matches!(*c, IsConst::True),
Bit(c) | Int(_, c) | UInt(_, c) | Float(_, c) | Angle(_, c) | Complex(_, c) | Bool(c)
| Duration(c) | Stretch(c) | BitArray(_, c) => matches!(*c, IsConst::True),
_ => true,
}
}
Expand Down

0 comments on commit 5e0ad92

Please sign in to comment.