diff --git a/Cargo.lock b/Cargo.lock index 6a89a2bcfe..e65899b1bc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1208,6 +1208,7 @@ dependencies = [ "qsc_partial_eval", "qsc_passes", "qsc_project", + "qsc_qasm3", "qsc_rca", "rustc-hash", "thiserror", @@ -1485,6 +1486,10 @@ dependencies = [ "oq3_source_file", "oq3_syntax", "qsc", + "qsc_ast", + "qsc_data_structures", + "qsc_frontend", + "qsc_parse", "qsc_qasm3", "rustc-hash", "thiserror", @@ -1558,7 +1563,6 @@ dependencies = [ "num-complex", "pyo3", "qsc", - "qsc_qasm3", "resource_estimator", "rustc-hash", "serde_json", diff --git a/compiler/qsc/Cargo.toml b/compiler/qsc/Cargo.toml index 06a4950dd6..0ae849b56c 100644 --- a/compiler/qsc/Cargo.toml +++ b/compiler/qsc/Cargo.toml @@ -31,6 +31,7 @@ qsc_passes = { path = "../qsc_passes" } qsc_parse = { path = "../qsc_parse" } qsc_partial_eval = { path = "../qsc_partial_eval" } qsc_project = { path = "../qsc_project", features = ["fs"] } +qsc_qasm3 = { path = "../qsc_qasm3", features = ["fs"] } qsc_rca = { path = "../qsc_rca" } qsc_circuit = { path = "../qsc_circuit" } rustc-hash = { workspace = true } diff --git a/compiler/qsc/src/lib.rs b/compiler/qsc/src/lib.rs index 5847ab4449..b5d0ab39c8 100644 --- a/compiler/qsc/src/lib.rs +++ b/compiler/qsc/src/lib.rs @@ -74,3 +74,9 @@ pub mod parse { pub mod partial_eval { pub use qsc_partial_eval::Error; } + +pub mod qasm3 { + pub use qsc_qasm3::io::*; + pub use qsc_qasm3::parse::*; + pub use qsc_qasm3::*; +} diff --git a/compiler/qsc_qasm3/Cargo.toml b/compiler/qsc_qasm3/Cargo.toml index 2c3115ed3a..b7a5d9f294 100644 --- a/compiler/qsc_qasm3/Cargo.toml +++ b/compiler/qsc_qasm3/Cargo.toml @@ -11,7 +11,10 @@ version.workspace = true bitflags = { workspace = true } num-bigint = { workspace = true } miette = { workspace = true } -qsc = { path = "../qsc" } +qsc_ast = { path = "../qsc_ast" } +qsc_data_structures = { path = "../qsc_data_structures" } +qsc_frontend = { path = "../qsc_frontend" } +qsc_parse = { path = "../qsc_parse" } rustc-hash = { workspace = true } thiserror = { workspace = true } oq3_source_file = { workspace = true } @@ -27,6 +30,7 @@ indoc = { workspace = true } miette = { workspace = true, features = ["fancy"] } # Self import adding fs feature so that we can test # loading qasm from file. +qsc = { path = "../qsc" } qsc_qasm3 = { path = ".", features = ["fs"] } [features] diff --git a/compiler/qsc_qasm3/src/ast_builder.rs b/compiler/qsc_qasm3/src/ast_builder.rs index 3eaa5e958e..4269334548 100644 --- a/compiler/qsc_qasm3/src/ast_builder.rs +++ b/compiler/qsc_qasm3/src/ast_builder.rs @@ -5,14 +5,12 @@ use std::rc::Rc; use num_bigint::BigInt; -use qsc::{ - ast::{ - self, Attr, Block, CallableBody, CallableDecl, CallableKind, Expr, ExprKind, Ident, Item, - Lit, Mutability, NodeId, Pat, PatKind, Path, PathKind, QubitInit, QubitInitKind, - QubitSource, Stmt, StmtKind, TopLevelNode, Ty, TyKind, - }, - Span, +use qsc_ast::ast::{ + self, Attr, Block, CallableBody, CallableDecl, CallableKind, Expr, ExprKind, Ident, Item, Lit, + Mutability, NodeId, Pat, PatKind, Path, PathKind, QubitInit, QubitInitKind, QubitSource, Stmt, + StmtKind, TopLevelNode, Ty, TyKind, }; +use qsc_data_structures::span::Span; use crate::{ runtime::RuntimeFunctions, @@ -203,7 +201,7 @@ where } } -pub(crate) fn build_lit_result_expr(value: qsc::ast::Result, span: Span) -> Expr { +pub(crate) fn build_lit_result_expr(value: qsc_ast::ast::Result, span: Span) -> Expr { Expr { id: NodeId::default(), span, @@ -231,7 +229,7 @@ pub(crate) fn build_lit_result_array_expr_from_bitstring>( build_lit_result_array_expr(values, span) } -pub(crate) fn build_lit_result_array_expr(values: Vec, span: Span) -> Expr { +pub(crate) fn build_lit_result_array_expr(values: Vec, span: Span) -> Expr { let exprs: Vec<_> = values .into_iter() .map(|v| build_lit_result_expr(v, Span::default())) @@ -239,7 +237,7 @@ pub(crate) fn build_lit_result_array_expr(values: Vec, span: S build_expr_array_expr(exprs, span) } -pub(crate) fn build_expr_array_expr(values: Vec, span: Span) -> Expr { +pub(crate) fn build_expr_array_expr(values: Vec, span: Span) -> Expr { let exprs: Vec<_> = values.into_iter().map(Box::new).collect(); Expr { id: NodeId::default(), @@ -314,7 +312,7 @@ pub(crate) fn build_binary_expr( } } -pub(crate) fn is_complex_binop_supported(op: qsc::ast::BinOp) -> bool { +pub(crate) fn is_complex_binop_supported(op: qsc_ast::ast::BinOp) -> bool { matches!( op, ast::BinOp::Add | ast::BinOp::Sub | ast::BinOp::Mul | ast::BinOp::Div | ast::BinOp::Exp @@ -1005,7 +1003,7 @@ pub(crate) fn build_top_level_ns_with_item>( ns: S, entry: ast::Item, ) -> TopLevelNode { - TopLevelNode::Namespace(qsc::ast::Namespace { + TopLevelNode::Namespace(qsc_ast::ast::Namespace { id: NodeId::default(), span: whole_span, name: [Ident { @@ -1031,10 +1029,10 @@ pub(crate) fn build_operation_with_stmts>( // as an entry point. We will get a Q# compilation error if we // attribute an operation with EntryPoint and it has input parameters. if input_pats.is_empty() { - attrs.push(Box::new(qsc::ast::Attr { + attrs.push(Box::new(qsc_ast::ast::Attr { id: NodeId::default(), span: Span::default(), - name: Box::new(qsc::ast::Ident { + name: Box::new(qsc_ast::ast::Ident { name: Rc::from("EntryPoint"), ..Default::default() }), @@ -1044,15 +1042,15 @@ pub(crate) fn build_operation_with_stmts>( let input_pats = input_pats.into_iter().map(Box::new).collect::>(); let input = match input_pats.len() { 0 => Box::new(Pat { - kind: Box::new(qsc::ast::PatKind::Tuple(input_pats.into_boxed_slice())), + kind: Box::new(qsc_ast::ast::PatKind::Tuple(input_pats.into_boxed_slice())), ..Default::default() }), 1 => Box::new(Pat { - kind: Box::new(qsc::ast::PatKind::Paren(input_pats[0].clone())), + kind: Box::new(qsc_ast::ast::PatKind::Paren(input_pats[0].clone())), ..Default::default() }), - _ => Box::new(qsc::ast::Pat { - kind: Box::new(qsc::ast::PatKind::Tuple(input_pats.into_boxed_slice())), + _ => Box::new(qsc_ast::ast::Pat { + kind: Box::new(qsc_ast::ast::PatKind::Tuple(input_pats.into_boxed_slice())), ..Default::default() }), }; @@ -1062,17 +1060,17 @@ pub(crate) fn build_operation_with_stmts>( .map(Box::new) .collect::>() .into_boxed_slice(); - qsc::ast::Item { + qsc_ast::ast::Item { id: NodeId::default(), span: whole_span, doc: "".into(), attrs: attrs.into_boxed_slice(), - kind: Box::new(qsc::ast::ItemKind::Callable(Box::new( - qsc::ast::CallableDecl { + kind: Box::new(qsc_ast::ast::ItemKind::Callable(Box::new( + qsc_ast::ast::CallableDecl { id: NodeId::default(), span: whole_span, - kind: qsc::ast::CallableKind::Operation, - name: Box::new(qsc::ast::Ident { + kind: qsc_ast::ast::CallableKind::Operation, + name: Box::new(qsc_ast::ast::Ident { name: Rc::from(name.as_ref()), ..Default::default() }), @@ -1080,20 +1078,22 @@ pub(crate) fn build_operation_with_stmts>( input, output: Box::new(output_ty), functors: None, - body: Box::new(qsc::ast::CallableBody::Block(Box::new(qsc::ast::Block { - id: NodeId::default(), - span: whole_span, - stmts, - }))), + body: Box::new(qsc_ast::ast::CallableBody::Block(Box::new( + qsc_ast::ast::Block { + id: NodeId::default(), + span: whole_span, + stmts, + }, + ))), }, ))), } } pub(crate) fn build_arg_pat(name: String, span: Span, ty: Ty) -> Pat { - qsc::ast::Pat { - kind: Box::new(qsc::ast::PatKind::Bind( - Box::new(qsc::ast::Ident { + qsc_ast::ast::Pat { + kind: Box::new(qsc_ast::ast::PatKind::Bind( + Box::new(qsc_ast::ast::Ident { name: Rc::from(name), span, ..Default::default() diff --git a/compiler/qsc_qasm3/src/compile.rs b/compiler/qsc_qasm3/src/compile.rs index db40fdbc6c..abbc10e70d 100644 --- a/compiler/qsc_qasm3/src/compile.rs +++ b/compiler/qsc_qasm3/src/compile.rs @@ -52,9 +52,9 @@ use oq3_syntax::ast::{ }; use oq3_syntax::SyntaxNode; use oq3_syntax::{AstNode, HasTextName}; -use qsc::ast; -use qsc::Span; -use qsc::{error::WithSource, SourceMap}; +use qsc_ast::ast; +use qsc_data_structures::span::Span; +use qsc_frontend::{compile::SourceMap, error::WithSource}; use crate::{parse::QasmSource, QasmCompileUnit}; diff --git a/compiler/qsc_qasm3/src/lib.rs b/compiler/qsc_qasm3/src/lib.rs index f4bf212ebb..b1d6fd35c1 100644 --- a/compiler/qsc_qasm3/src/lib.rs +++ b/compiler/qsc_qasm3/src/lib.rs @@ -19,7 +19,9 @@ pub(crate) mod tests; use std::{fmt::Write, sync::Arc}; use miette::Diagnostic; -use qsc::Span; +use qsc_ast::ast::Package; +use qsc_data_structures::span::Span; +use qsc_frontend::{compile::SourceMap, error::WithSource}; use thiserror::Error; #[derive(Clone, Debug, Diagnostic, Eq, Error, PartialEq)] @@ -458,8 +460,6 @@ pub enum ProgramType { Fragments, } -use qsc::{ast::Package, error::WithSource, SourceMap}; - /// Represents the signature of an operation. /// This is used to create a function signature for the /// operation that is created from the QASM source code. diff --git a/compiler/qsc_qasm3/src/oqasm_helpers.rs b/compiler/qsc_qasm3/src/oqasm_helpers.rs index bdfbca7fd8..bbac93ad6e 100644 --- a/compiler/qsc_qasm3/src/oqasm_helpers.rs +++ b/compiler/qsc_qasm3/src/oqasm_helpers.rs @@ -3,7 +3,7 @@ use oq3_semantics::types::Type; use oq3_syntax::ast::{ArithOp, BinaryOp, Designator, Expr, Literal, LiteralKind}; -use qsc::Span; +use qsc_data_structures::span::Span; /// Extracts a Q# ```Span``` from the QASM3 syntax named element pub(crate) fn span_for_named_item(value: &T) -> Span { diff --git a/compiler/qsc_qasm3/src/parse.rs b/compiler/qsc_qasm3/src/parse.rs index 85b6c6e19c..be6c74ff1d 100644 --- a/compiler/qsc_qasm3/src/parse.rs +++ b/compiler/qsc_qasm3/src/parse.rs @@ -5,7 +5,8 @@ use crate::io::SourceResolver; use crate::oqasm_helpers::text_range_to_span; use oq3_syntax::SyntaxNode; use oq3_syntax::{ast::Stmt, ParseOrErrors, SourceFile}; -use qsc::{error::WithSource, SourceMap}; +use qsc_frontend::compile::SourceMap; +use qsc_frontend::error::WithSource; use std::path::{Path, PathBuf}; use std::sync::Arc; diff --git a/compiler/qsc_qasm3/src/runtime.rs b/compiler/qsc_qasm3/src/runtime.rs index db19ec12c4..2b0080d5fd 100644 --- a/compiler/qsc_qasm3/src/runtime.rs +++ b/compiler/qsc_qasm3/src/runtime.rs @@ -3,10 +3,8 @@ use bitflags::bitflags; -use qsc::{ - ast::{Stmt, TopLevelNode}, - LanguageFeatures, -}; +use qsc_ast::ast::{Stmt, TopLevelNode}; +use qsc_data_structures::language_features::LanguageFeatures; /// Runtime functions that are used in the generated AST. /// These functions are not part of the QASM3 standard, but are used to implement @@ -200,7 +198,7 @@ pub(crate) fn get_result_array_as_int_be_decl() -> Stmt { } fn parse_stmt(name: &str) -> Stmt { - let (nodes, errors) = qsc::parse::top_level_nodes(name, LanguageFeatures::default()); + let (nodes, errors) = qsc_parse::top_level_nodes(name, LanguageFeatures::default()); assert!(errors.is_empty(), "Failed to parse POW: {errors:?}"); assert!( nodes.len() == 1, diff --git a/compiler/qsc_qasm3/src/symbols.rs b/compiler/qsc_qasm3/src/symbols.rs index 428ecb402d..679fe0b1a6 100644 --- a/compiler/qsc_qasm3/src/symbols.rs +++ b/compiler/qsc_qasm3/src/symbols.rs @@ -2,7 +2,7 @@ // Licensed under the MIT License. use oq3_semantics::types::{IsConst, Type}; -use qsc::Span; +use qsc_data_structures::span::Span; use rustc_hash::FxHashMap; /// We need a symbol table to keep track of the symbols in the program. diff --git a/compiler/qsc_qasm3/src/types.rs b/compiler/qsc_qasm3/src/types.rs index 02ad9b36ea..6b24bfd83a 100644 --- a/compiler/qsc_qasm3/src/types.rs +++ b/compiler/qsc_qasm3/src/types.rs @@ -4,7 +4,7 @@ use std::fmt::{self, Display, Formatter}; use oq3_semantics::types::ArrayDims; -use qsc::Span; +use qsc_data_structures::span::Span; use rustc_hash::FxHashMap; thread_local! { @@ -73,7 +73,7 @@ pub(crate) fn get_qsharp_gate_name>(gate_name: S) -> Option<&'stat #[derive(Debug, Clone, PartialEq)] pub struct QasmTypedExpr { pub ty: oq3_semantics::types::Type, - pub expr: qsc::ast::Expr, + pub expr: qsc_ast::ast::Expr, } #[derive(Clone, Debug, PartialEq)] diff --git a/pip/Cargo.toml b/pip/Cargo.toml index 004ed6d939..26a611b22c 100644 --- a/pip/Cargo.toml +++ b/pip/Cargo.toml @@ -14,7 +14,6 @@ noisy_simulator = { path = "../noisy_simulator" } num-bigint = { workspace = true } num-complex = { workspace = true } qsc = { path = "../compiler/qsc" } -qsc_qasm3 = { path = "../compiler/qsc_qasm3", features = ["fs"]} resource_estimator = { path = "../resource_estimator" } miette = { workspace = true, features = ["fancy-no-syscall"] } rustc-hash = { workspace = true } diff --git a/pip/src/interop.rs b/pip/src/interop.rs index 3f3fb75dbe..dee2fd1548 100644 --- a/pip/src/interop.rs +++ b/pip/src/interop.rs @@ -10,16 +10,16 @@ use pyo3::prelude::*; use pyo3::types::{PyDict, PyList}; use qsc::interpret::output::Receiver; use qsc::interpret::{into_errors, Interpreter}; +use qsc::qasm3::io::SourceResolver; +use qsc::qasm3::{ + qasm_to_program, CompilerConfig, OperationSignature, QasmCompileUnit, QubitSemantics, +}; use qsc::target::Profile; use qsc::{ ast::Package, error::WithSource, interpret, project::FileSystem, LanguageFeatures, PackageStore, SourceMap, }; use qsc::{Backend, PackageType, SparseSim}; -use qsc_qasm3::io::SourceResolver; -use qsc_qasm3::{ - qasm_to_program, CompilerConfig, OperationSignature, QasmCompileUnit, QubitSemantics, -}; use crate::fs::file_system; use crate::interpreter::{ @@ -261,7 +261,7 @@ pub(crate) fn compile_qasm, R: SourceResolver>( program_ty: ProgramType, output_semantics: OutputSemantics, ) -> PyResult { - let parse_result = qsc_qasm3::parse::parse_source( + let parse_result = qsc::qasm3::parse::parse_source( source, format!("{}.qasm", operation_name.as_ref()), resolver, @@ -494,7 +494,7 @@ fn into_estimation_errors(errors: Vec) -> Vec>) -> String { +pub(crate) fn format_qasm_errors(errors: Vec>) -> String { errors .into_iter() .map(|e| { diff --git a/pip/src/interpreter.rs b/pip/src/interpreter.rs index 3d641dcd12..0ff710244c 100644 --- a/pip/src/interpreter.rs +++ b/pip/src/interpreter.rs @@ -184,12 +184,12 @@ pub(crate) enum OutputSemantics { ResourceEstimation, } -impl From for qsc_qasm3::OutputSemantics { +impl From for qsc::qasm3::OutputSemantics { fn from(output_semantics: OutputSemantics) -> Self { match output_semantics { - OutputSemantics::Qiskit => qsc_qasm3::OutputSemantics::Qiskit, - OutputSemantics::OpenQasm => qsc_qasm3::OutputSemantics::OpenQasm, - OutputSemantics::ResourceEstimation => qsc_qasm3::OutputSemantics::ResourceEstimation, + OutputSemantics::Qiskit => qsc::qasm3::OutputSemantics::Qiskit, + OutputSemantics::OpenQasm => qsc::qasm3::OutputSemantics::OpenQasm, + OutputSemantics::ResourceEstimation => qsc::qasm3::OutputSemantics::ResourceEstimation, } } } @@ -215,12 +215,12 @@ pub enum ProgramType { Fragments, } -impl From for qsc_qasm3::ProgramType { +impl From for qsc::qasm3::ProgramType { fn from(output_semantics: ProgramType) -> Self { match output_semantics { - ProgramType::File => qsc_qasm3::ProgramType::File, - ProgramType::Operation => qsc_qasm3::ProgramType::Operation, - ProgramType::Fragments => qsc_qasm3::ProgramType::Fragments, + ProgramType::File => qsc::qasm3::ProgramType::File, + ProgramType::Operation => qsc::qasm3::ProgramType::Operation, + ProgramType::Fragments => qsc::qasm3::ProgramType::Fragments, } } }