From fbeb0c689312403c233ce1f0d05f24130069e182 Mon Sep 17 00:00:00 2001 From: John Lapeyre Date: Fri, 19 Jan 2024 00:16:44 -0500 Subject: [PATCH] Implement IndexedIdentifier for lvalue of assignment All of the failing examples given in #38 are included as (passing) tests. Either in this PR or in earlier PRs. Closes #38 --- crates/oq3_semantics/src/asg.rs | 9 ++++- .../oq3_semantics/src/syntax_to_semantics.rs | 40 ++++++++++++------- .../oq3_semantics/tests/from_string_tests.rs | 25 ++++++++++++ crates/oq3_syntax/src/ast/expr_ext.rs | 6 +++ 4 files changed, 64 insertions(+), 16 deletions(-) diff --git a/crates/oq3_semantics/src/asg.rs b/crates/oq3_semantics/src/asg.rs index 5a5797c..9793ba9 100644 --- a/crates/oq3_semantics/src/asg.rs +++ b/crates/oq3_semantics/src/asg.rs @@ -359,8 +359,13 @@ impl ExpressionList { #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub enum LValue { Identifier(SymbolIdResult), - ArraySlice(ArraySlice), - RegisterSlice(RegisterSlice), + // We want to remove IndexedIdentifier in favor of more precise types below. + IndexedIdentifier(IndexedIdentifier), + // FIXME: We really want the following which carry more semantic content. + // We have to check types to determine which of these we have. They + // also have (sometimes) differing syntax. + // ArraySlice(ArraySlice), + // RegisterSlice(RegisterSlice), } // For example `expr` in `v[expr]`, or `1:3` in `v[1:3]` diff --git a/crates/oq3_semantics/src/syntax_to_semantics.rs b/crates/oq3_semantics/src/syntax_to_semantics.rs index 919c5a0..1e49362 100644 --- a/crates/oq3_semantics/src/syntax_to_semantics.rs +++ b/crates/oq3_semantics/src/syntax_to_semantics.rs @@ -588,26 +588,38 @@ fn from_classical_declaration_statement( asg::DeclareClassical::new(symbol_id, initializer).to_stmt() } -// FIXME: In oq3_syntax we have both Name and Identifier. We only need one, I think. -// This will be changed. - +// FIXME: Refactor this. It was done in a hurry. fn from_assignment_stmt( assignment_stmt: &synast::AssignmentStmt, context: &mut Context, ) -> Option { 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 stmt_asg = Some(asg::Assignment::new(lvalue, expr.unwrap()).to_stmt()); - if is_mutating_const { - context.insert_error(MutateConstError, assignment_stmt); + if nameb.is_some() { + 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 stmt_asg = Some(asg::Assignment::new(lvalue, expr.unwrap()).to_stmt()); + if is_mutating_const { + context.insert_error(MutateConstError, assignment_stmt); + } + return stmt_asg; } - stmt_asg + let indexed_identifier_ast = assignment_stmt.indexed_identifier(); + let (indexed_identifier, _typ) = + ast_indexed_identifier(&indexed_identifier_ast.unwrap(), context); + let expr = from_expr(assignment_stmt.expr().unwrap(), context); // rhs of `=` operator + // let is_mutating_const = symbol_id.is_ok() && typ.is_const(); + let lvalue = asg::LValue::IndexedIdentifier(indexed_identifier); + 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); + // } + // stmt_asg } // diff --git a/crates/oq3_semantics/tests/from_string_tests.rs b/crates/oq3_semantics/tests/from_string_tests.rs index 3eeb805..6d03333 100644 --- a/crates/oq3_semantics/tests/from_string_tests.rs +++ b/crates/oq3_semantics/tests/from_string_tests.rs @@ -257,3 +257,28 @@ barrier $0, $1; assert!(errors.is_empty()); assert_eq!(program.len(), 3); } + +#[test] +fn test_from_string_assign_indexed() { + let code = r#" +qubit q; +bit[2] c; +c[0] = measure q; +"#; + let (program, errors, _symbol_table) = parse_string(code); + assert!(errors.is_empty()); + assert_eq!(program.len(), 3); +} + +#[test] +fn test_from_string_assign_indexed_2() { + let code = r#" +OPENQASM 3.0; + +bit[2] out; +out[0] = measure $0; +"#; + let (program, errors, _symbol_table) = parse_string(code); + assert!(errors.is_empty()); + assert_eq!(program.len(), 2); +} diff --git a/crates/oq3_syntax/src/ast/expr_ext.rs b/crates/oq3_syntax/src/ast/expr_ext.rs index f805c47..397a398 100644 --- a/crates/oq3_syntax/src/ast/expr_ext.rs +++ b/crates/oq3_syntax/src/ast/expr_ext.rs @@ -421,6 +421,12 @@ impl ast::IndexedIdentifier { } } +impl ast::AssignmentStmt { + pub fn indexed_identifier(&self) -> Option { + support::child(&self.syntax) + } +} + impl ast::GateCallStmt { // This may be redundant pub fn name(&self) -> Option {