From 3e99dd0a97c2127ff1be156554d99aa3e4433bf1 Mon Sep 17 00:00:00 2001 From: John Lapeyre Date: Thu, 18 Jan 2024 22:07:11 -0500 Subject: [PATCH] Set type of measurement expression correctly (#52) * Set type of measurement expression correctly That is measuring a qubit or hardware qubit results in a bit. Measuring a qubit register results in a bit register of the same length. * Log semantic error for incorrectly typed args to `measure`. Closes #51 --- crates/oq3_semantics/src/asg.rs | 10 +++++++--- crates/oq3_semantics/src/syntax_to_semantics.rs | 14 ++++++++++---- crates/oq3_semantics/tests/from_string_tests.rs | 2 +- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/crates/oq3_semantics/src/asg.rs b/crates/oq3_semantics/src/asg.rs index d69ea14..7bb110c 100644 --- a/crates/oq3_semantics/src/asg.rs +++ b/crates/oq3_semantics/src/asg.rs @@ -55,6 +55,7 @@ impl Program { let _ = &self.stmts.push(stmt); } + // FIXME: This should probably log a semantic error rather than panic. // The check should be done when checking syntax. // This check may be overly restrictive, as one might want to manipulate // or construct a `Program` in a way other than sequentially translating @@ -578,10 +579,13 @@ impl MeasureExpression { &self.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)) + let out_type = match self.operand.get_type() { + Type::Qubit | Type::HardwareQubit => Type::Bit(IsConst::False), + Type::QubitArray(dims) => Type::BitArray(dims.clone(), IsConst::False), + _ => Type::Undefined, + }; + TExpr::new(Expr::MeasureExpression(self), out_type) } } diff --git a/crates/oq3_semantics/src/syntax_to_semantics.rs b/crates/oq3_semantics/src/syntax_to_semantics.rs index 2043f4a..63a8d40 100644 --- a/crates/oq3_semantics/src/syntax_to_semantics.rs +++ b/crates/oq3_semantics/src/syntax_to_semantics.rs @@ -247,12 +247,18 @@ fn from_gate_operand(gate_operand: synast::GateOperand, context: &mut Context) - 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); + synast::GateOperand::Identifier(ref identifier) => { + let (astidentifier, typ) = ast_identifier(identifier, context); + if !matches!(typ, Type::Qubit | Type::HardwareQubit) { + context.insert_error(IncompatibleTypesError, &gate_operand); + } asg::GateOperand::Identifier(astidentifier).to_texpr(typ) } - synast::GateOperand::IndexedIdentifier(indexed_identifier) => { - let (indexed_identifier, typ) = ast_indexed_identifier(&indexed_identifier, context); + synast::GateOperand::IndexedIdentifier(ref indexed_identifier) => { + let (indexed_identifier, typ) = ast_indexed_identifier(indexed_identifier, context); + if !matches!(typ, Type::QubitArray(_)) { + context.insert_error(IncompatibleTypesError, &gate_operand); + } asg::GateOperand::IndexedIdentifier(indexed_identifier).to_texpr(typ) } } diff --git a/crates/oq3_semantics/tests/from_string_tests.rs b/crates/oq3_semantics/tests/from_string_tests.rs index f07e8b7..63fb0c7 100644 --- a/crates/oq3_semantics/tests/from_string_tests.rs +++ b/crates/oq3_semantics/tests/from_string_tests.rs @@ -152,7 +152,7 @@ fn test_gate_call() { mygate(x, y) q; "##; let (program, errors, _symbol_table) = parse_string(code); - assert_eq!(errors.len(), 4); + assert_eq!(errors.len(), 5); assert_eq!(program.len(), 1); }