Skip to content

Add initial semantic analysis/transform #2214

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
144 changes: 72 additions & 72 deletions compiler/qsc_qasm3/src/ast.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

// while we work through the conversion, allow dead code to avoid warnings
#![allow(dead_code)]

mod display_utils;
pub(crate) mod display_utils;

use display_utils::{
write_field, write_header, write_indented_list, write_list_field, write_opt_field,
write_opt_list_field, writeln_field, writeln_header, writeln_list_field, writeln_opt_field,
};

use num_bigint::BigInt;
use qsc_data_structures::span::{Span, WithSpan};
use std::{
Expand Down Expand Up @@ -66,6 +64,7 @@ pub struct Annotation {
pub identifier: Rc<str>,
pub value: Option<Rc<str>>,
}

impl Display for Annotation {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
let identifier = format!("\"{}\"", self.identifier);
Expand Down Expand Up @@ -145,21 +144,6 @@ impl WithSpan for Path {
}
}

#[derive(Clone, Debug)]
pub enum AssignmentExpr {
Expr(Expr),
Measurement(MeasureExpr),
}

impl Display for AssignmentExpr {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
AssignmentExpr::Expr(expr) => write!(f, "AssignmentExpr {expr}"),
AssignmentExpr::Measurement(measure) => write!(f, "AssignmentExpr {measure}"),
}
}
}

#[derive(Clone, Debug)]
pub struct MeasureExpr {
pub span: Span,
Expand Down Expand Up @@ -282,8 +266,12 @@ impl Display for GateOperand {
}

impl WithSpan for GateOperand {
fn with_span(self, _span: Span) -> Self {
self
fn with_span(self, span: Span) -> Self {
match self {
GateOperand::IndexedIdent(ident) => GateOperand::IndexedIdent(ident.with_span(span)),
GateOperand::HardwareQubit(qubit) => GateOperand::HardwareQubit(qubit.with_span(span)),
GateOperand::Err => GateOperand::Err,
}
}
}

Expand All @@ -299,6 +287,12 @@ impl Display for HardwareQubit {
}
}

impl WithSpan for HardwareQubit {
fn with_span(self, span: Span) -> Self {
Self { span, ..self }
}
}

#[derive(Clone, Debug)]
pub struct AliasDeclStmt {
pub span: Span,
Expand Down Expand Up @@ -482,6 +476,15 @@ pub enum Identifier {
IndexedIdent(Box<IndexedIdent>),
}

impl Identifier {
pub fn span(&self) -> Span {
match self {
Identifier::Ident(ident) => ident.span,
Identifier::IndexedIdent(ident) => ident.span,
}
}
}

impl Display for Identifier {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
Expand Down Expand Up @@ -533,6 +536,12 @@ impl Display for IndexedIdent {
}
}

impl WithSpan for IndexedIdent {
fn with_span(self, span: Span) -> Self {
Self { span, ..self }
}
}

#[derive(Clone, Debug)]
pub struct ExprStmt {
pub span: Span,
Expand Down Expand Up @@ -598,6 +607,12 @@ pub struct RangeDefinition {
pub step: Option<Expr>,
}

impl WithSpan for RangeDefinition {
fn with_span(self, span: Span) -> Self {
Self { span, ..self }
}
}

impl Display for RangeDefinition {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
writeln_header(f, "RangeDefinition", self.span)?;
Expand Down Expand Up @@ -641,7 +656,7 @@ impl Display for GateModifierKind {
#[derive(Clone, Debug)]
pub struct ClassicalArgument {
pub span: Span,
pub r#type: ScalarType,
pub ty: ScalarType,
pub name: Identifier,
pub access: Option<AccessControl>,
}
Expand All @@ -652,13 +667,13 @@ impl Display for ClassicalArgument {
write!(
f,
"ClassicalArgument {}: {}, {}, {}",
self.span, self.r#type, self.name, access
self.span, self.ty, self.name, access
)
} else {
write!(
f,
"ClassicalArgument {}: {}, {}",
self.span, self.r#type, self.name
self.span, self.ty, self.name
)
}
}
Expand Down Expand Up @@ -726,6 +741,7 @@ pub enum ScalarTypeKind {
BoolType,
Duration,
Stretch,
// Any usage of Err should have pushed a parse error
#[default]
Err,
}
Expand Down Expand Up @@ -1106,15 +1122,15 @@ impl Display for MeasureStmt {
#[derive(Clone, Debug)]
pub struct ClassicalDeclarationStmt {
pub span: Span,
pub r#type: Box<TypeDef>,
pub ty: Box<TypeDef>,
pub identifier: Ident,
pub init_expr: Option<Box<ValueExpression>>,
}

impl Display for ClassicalDeclarationStmt {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
writeln_header(f, "ClassicalDeclarationStmt", self.span)?;
writeln_field(f, "type", &self.r#type)?;
writeln_field(f, "type", &self.ty)?;
writeln_field(f, "ident", &self.identifier)?;
write_opt_field(f, "init_expr", self.init_expr.as_ref())
}
Expand All @@ -1139,31 +1155,31 @@ impl Display for ValueExpression {
pub struct IODeclaration {
pub span: Span,
pub io_identifier: IOKeyword,
pub r#type: TypeDef,
pub ty: TypeDef,
pub ident: Box<Ident>,
}

impl Display for IODeclaration {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
writeln_header(f, "IODeclaration", self.span)?;
writeln_field(f, "io_keyword", &self.io_identifier)?;
writeln_field(f, "type", &self.r#type)?;
writeln_field(f, "type", &self.ty)?;
write_field(f, "ident", &self.ident)
}
}

#[derive(Clone, Debug)]
pub struct ConstantDeclStmt {
pub span: Span,
pub r#type: TypeDef,
pub ty: TypeDef,
pub identifier: Box<Ident>,
pub init_expr: Expr,
}

impl Display for ConstantDeclStmt {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
writeln_header(f, "ConstantDeclStmt", self.span)?;
writeln_field(f, "type", &self.r#type)?;
writeln_field(f, "type", &self.ty)?;
writeln_field(f, "ident", &self.identifier)?;
write_field(f, "init_expr", &self.init_expr)
}
Expand Down Expand Up @@ -1225,34 +1241,30 @@ impl Default for TypedParameter {
Self::Scalar(ScalarTypedParameter {
span: Span::default(),
ident: Ident::default(),
r#type: Box::default(),
ty: Box::default(),
})
}
}

#[derive(Clone, Debug)]
pub struct ScalarTypedParameter {
pub span: Span,
pub r#type: Box<ScalarType>,
pub ty: Box<ScalarType>,
pub ident: Ident,
}

impl Display for ScalarTypedParameter {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
writeln_header(f, "ScalarTypedParameter", self.span)?;
writeln_field(f, "type", &self.r#type)?;
writeln_field(f, "type", &self.ty)?;
write_field(f, "ident", &self.ident)
}
}

impl WithSpan for ScalarTypedParameter {
fn with_span(self, span: Span) -> Self {
let Self { r#type, ident, .. } = self;
Self {
span,
r#type,
ident,
}
let Self { ty, ident, .. } = self;
Self { span, ty, ident }
}
}

Expand Down Expand Up @@ -1281,26 +1293,22 @@ impl WithSpan for QuantumTypedParameter {
#[derive(Clone, Debug)]
pub struct ArrayTypedParameter {
pub span: Span,
pub r#type: Box<ArrayReferenceType>,
pub ty: Box<ArrayReferenceType>,
pub ident: Ident,
}

impl Display for ArrayTypedParameter {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
writeln_header(f, "ArrayTypedParameter", self.span)?;
writeln_field(f, "type", &self.r#type)?;
writeln_field(f, "type", &self.ty)?;
write_field(f, "ident", &self.ident)
}
}

impl WithSpan for ArrayTypedParameter {
fn with_span(self, span: Span) -> Self {
let Self { r#type, ident, .. } = self;
Self {
span,
r#type,
ident,
}
let Self { ty, ident, .. } = self;
Self { span, ty, ident }
}
}

Expand All @@ -1323,21 +1331,6 @@ impl Display for DefStmt {
}
}

#[derive(Clone, Debug)]
pub enum Operand {
Classical(ClassicalArgument),
Quantum(QuantumArgument),
}

impl Display for Operand {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
Operand::Classical(arg) => write!(f, "{arg}"),
Operand::Quantum(arg) => write!(f, "{arg}"),
}
}
}

#[derive(Clone, Debug)]
pub struct ReturnStmt {
pub span: Span,
Expand Down Expand Up @@ -1369,7 +1362,7 @@ impl Display for WhileLoop {
#[derive(Clone, Debug)]
pub struct ForStmt {
pub span: Span,
pub r#type: ScalarType,
pub ty: ScalarType,
pub identifier: Identifier,
pub set_declaration: Box<EnumerableSet>,
pub block: List<Stmt>,
Expand All @@ -1378,7 +1371,7 @@ pub struct ForStmt {
impl Display for ForStmt {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
writeln_header(f, "ForStmt", self.span)?;
writeln_field(f, "variable_type", &self.r#type)?;
writeln_field(f, "variable_type", &self.ty)?;
writeln_field(f, "variable_name", &self.identifier)?;
writeln_field(f, "iterable", &self.set_declaration)?;
write_list_field(f, "block", &self.block)
Expand Down Expand Up @@ -1550,14 +1543,14 @@ impl Display for FunctionCall {
#[derive(Clone, Debug)]
pub struct Cast {
pub span: Span,
pub r#type: TypeDef,
pub ty: TypeDef,
pub arg: Expr,
}

impl Display for Cast {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
writeln_header(f, "Cast", self.span)?;
writeln_field(f, "type", &self.r#type)?;
writeln_field(f, "type", &self.ty)?;
write_field(f, "arg", &self.arg)
}
}
Expand Down Expand Up @@ -1592,9 +1585,9 @@ impl Display for Lit {
#[derive(Clone, Debug)]
pub enum LiteralKind {
Array(List<Expr>),
Bitstring { value: BigInt, width: usize },
Bitstring(BigInt, u32),
Bool(bool),
Duration { value: f64, unit: TimeUnit },
Duration(f64, TimeUnit),
Float(f64),
Imaginary(f64),
Int(i64),
Expand All @@ -1606,11 +1599,12 @@ impl Display for LiteralKind {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
LiteralKind::Array(exprs) => write_list_field(f, "Array", exprs),
LiteralKind::Bitstring { value, width } => {
LiteralKind::Bitstring(value, width) => {
let width = *width as usize;
write!(f, "Bitstring(\"{:0>width$}\")", value.to_str_radix(2))
}
LiteralKind::Bool(b) => write!(f, "Bool({b:?})"),
LiteralKind::Duration { value, unit } => {
LiteralKind::Duration(value, unit) => {
write!(f, "Duration({value:?}, {unit:?})")
}
LiteralKind::Float(value) => write!(f, "Float({value:?})"),
Expand Down Expand Up @@ -1663,8 +1657,14 @@ pub enum IndexSetItem {

/// This is needed to able to use `IndexSetItem` in the `seq` combinator.
impl WithSpan for IndexSetItem {
fn with_span(self, _span: Span) -> Self {
self
fn with_span(self, span: Span) -> Self {
match self {
IndexSetItem::RangeDefinition(range) => {
IndexSetItem::RangeDefinition(range.with_span(span))
}
IndexSetItem::Expr(expr) => IndexSetItem::Expr(expr.with_span(span)),
IndexSetItem::Err => IndexSetItem::Err,
}
}
}

Expand Down
Loading