Skip to content

Commit

Permalink
Implement complex type specification (and declaration)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
jlapeyre committed Mar 25, 2024
1 parent 8b7a788 commit aec71d5
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 4 deletions.
23 changes: 22 additions & 1 deletion crates/oq3_parser/src/grammar/expressions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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!['[']) {
Expand All @@ -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();
Expand All @@ -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
Expand Down
21 changes: 18 additions & 3 deletions crates/oq3_semantics/src/syntax_to_semantics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -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.
Expand Down

0 comments on commit aec71d5

Please sign in to comment.