From aec71d55e1ec9cba9fb557e6eec60d7d54a81dc2 Mon Sep 17 00:00:00 2001 From: John Lapeyre Date: Mon, 25 Mar 2024 00:38:54 -0400 Subject: [PATCH] Implement complex type specification (and declaration) The following are now parsed correctly and construct the correct type in `oq3_semantics`: `complex w;` `complex[float] w;` `complex[float[32]] w;` Note that this does not yet implement complex literals. Nor any other behavior peculiar to complex numbers. --- crates/oq3_parser/src/grammar/expressions.rs | 23 ++++++++++++++++++- .../oq3_semantics/src/syntax_to_semantics.rs | 21 ++++++++++++++--- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/crates/oq3_parser/src/grammar/expressions.rs b/crates/oq3_parser/src/grammar/expressions.rs index f1fa36e..9ec1d33 100644 --- a/crates/oq3_parser/src/grammar/expressions.rs +++ b/crates/oq3_parser/src/grammar/expressions.rs @@ -408,6 +408,10 @@ pub(crate) fn array_type_spec(p: &mut Parser<'_>) -> bool { // Parse a scalar or quantum type. // Don't record error if array is found. Do not parse array. fn non_array_type_spec(p: &mut Parser<'_>) -> bool { + if p.at(T![complex]) { + complex_type_spec(p); + return true; + } let m = p.start(); type_name(p); if p.at(T!['[']) { @@ -417,6 +421,22 @@ fn non_array_type_spec(p: &mut Parser<'_>) -> bool { true } +fn complex_type_spec(p: &mut Parser<'_>) { + assert!(p.at(T![complex])); + let m = p.start(); + p.bump_any(); + // designator is optional for `complex`. + if p.at(T!['[']) { + p.bump(T!['[']); + if !p.at(T![float]) { + p.error("Expecting `float` in complex designator`"); + } + non_array_type_spec(p); + p.expect(T![']']); + } + m.complete(p, SCALAR_TYPE); +} + pub(crate) fn qubit_type_spec(p: &mut Parser<'_>) -> bool { assert!(p.at(T![qubit])); let m = p.start(); @@ -432,8 +452,9 @@ pub(crate) fn qubit_type_spec(p: &mut Parser<'_>) -> bool { } pub(crate) fn designator(p: &mut Parser<'_>) -> bool { + assert!(p.at(T!['['])); let m = p.start(); - p.eat(T!['[']); + p.bump(T!['[']); // Log error for a literal designator that is not integer. We are // conservative here. I am not sure that an expression that begins with one // of the following literals cannot have an integer type. I am pretty sure diff --git a/crates/oq3_semantics/src/syntax_to_semantics.rs b/crates/oq3_semantics/src/syntax_to_semantics.rs index 3939ab3..941d73a 100644 --- a/crates/oq3_semantics/src/syntax_to_semantics.rs +++ b/crates/oq3_semantics/src/syntax_to_semantics.rs @@ -908,8 +908,24 @@ fn from_scalar_type( isconst: bool, context: &mut Context, ) -> Type { - // We only support literal integer designators at the moment. - let width = match scalar_type.designator().and_then(|desg| desg.expr()) { + // If the scalar type is `complex`, then scalar_type.scalar_type() will return + // the base type, which is a float type. If scalar_type.scalar_type() is `None`, + // then it is a simple scalar type and the designator is in scalar_type.designator. + // Note that this is the point where we throw away the token `float`, which is + // superfluous. + // In OQ3 source, `complex` types have a different syntax from other scalar types. + // Eg, we write `int[32]`, but we don't write `complex[32]`, but rather `complex[float[32]]`. + // However `Type::Complex` has exactly the same form as other scalar types. In this case + // `width` is understood to be the width of each of real and imaginary components. + let designator = if let Some(float_type) = scalar_type.scalar_type() { + // complex + float_type.designator() + } else { + // not complex + scalar_type.designator() + }; + let width = match designator.and_then(|desg| desg.expr()) { + // We only support literal integer designators at the moment. Some(synast::Expr::Literal(ref literal)) => { match literal.kind() { synast::LiteralKind::IntNumber(int_num) => Some(int_num.value().unwrap() as u32), @@ -957,7 +973,6 @@ fn from_classical_declaration_statement( } let scalar_type = type_decl.scalar_type().unwrap(); let typ = from_scalar_type(&scalar_type, type_decl.const_token().is_some(), context); - let name_str = type_decl.name().unwrap().string(); let initializer = from_expr(type_decl.expr(), context); // FIXME: This error and several others can and should be moved to a subsequent pass.