Skip to content

Commit

Permalink
Migrate the standard library to the project system (#1912)
Browse files Browse the repository at this point in the history
This PR migrates the standard library into a Q# project structure.

Previously, we provided the modern standard library API via re-export,
while the "true" stdlib was defined in the old explicit-namespace style.
Now, that is inverted: the stdlib's code is housed in a project with
implicit namespaces, and the legacy (`Microsoft.Quantum.____`) API is
provided via re-exports.

Why do this? Well, for one, the standard library should look like a
regular library and use the latest features we have.
Secondarily, auto-imports and other language dev tools now refer to
these items by their `Std.__` name, not their `Microsoft.Quantum.__`
name. See the video below for an example of this in completions:


https://github.com/user-attachments/assets/fa96e5b7-0cca-4a44-9224-7742d50f8370

Go-to def rendering the new paths:


https://github.com/user-attachments/assets/5fea33ec-9478-4c16-9e78-b8f8b1420ed0



Note that `Unstable.*` has not been migrated to the modern API, as we
want to explore stabilizing state preparation (#1910)

Core is also not included, but for different reasons: #1911. Coming in a
Follow Up PR™️ (`alex/1911` if you want to preview the work there)
  • Loading branch information
sezna authored Sep 17, 2024
1 parent 82e2a62 commit 7f6e302
Show file tree
Hide file tree
Showing 151 changed files with 7,221 additions and 7,218 deletions.
2 changes: 1 addition & 1 deletion compiler/qsc/benches/eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ pub fn large_nested_iteration(c: &mut Criterion) {
[("none".into(), "".into())],
Some(
indoc! {"{
open Microsoft.Quantum.Arrays;
import Std.Arrays.*;
mutable arr = [[0, size = 100], size = 1000];
for i in IndexRange(arr) {
mutable inner = arr[i];
Expand Down
4 changes: 2 additions & 2 deletions compiler/qsc/benches/large.qs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
// Licensed under the MIT License.

namespace Large {
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Measurement;
import Std.Intrinsic.*;
import Std.Measurement.*;

operation ThousandQubitsParityX(qs : Qubit[]) : Result {
mutable res = Zero;
Expand Down
6 changes: 3 additions & 3 deletions compiler/qsc/src/codegen/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ mod base_profile {
#[test]
fn simple() {
let source = "namespace Test {
open Microsoft.Quantum.Math;
import Std.Math.*;
open QIR.Intrinsic;
@EntryPoint()
operation Main() : Result {
Expand Down Expand Up @@ -393,7 +393,7 @@ mod adaptive_profile {
#[test]
fn simple() {
let source = "namespace Test {
open Microsoft.Quantum.Math;
import Std.Math.*;
open QIR.Intrinsic;
@EntryPoint()
operation Main() : Result {
Expand Down Expand Up @@ -608,7 +608,7 @@ mod adaptive_ri_profile {
#[test]
fn simple() {
let source = "namespace Test {
open Microsoft.Quantum.Math;
import Std.Math.*;
open QIR.Intrinsic;
@EntryPoint()
operation Main() : Result {
Expand Down
20 changes: 10 additions & 10 deletions compiler/qsc/src/interpret/circuit_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ fn m_base_profile() {
let mut interpreter = interpreter(
r"
namespace Test {
open Microsoft.Quantum.Measurement;
import Std.Measurement.*;
@EntryPoint()
operation Main() : Result[] {
use q = Qubit();
Expand Down Expand Up @@ -187,7 +187,7 @@ fn m_unrestricted_profile() {
let mut interpreter = interpreter(
r"
namespace Test {
open Microsoft.Quantum.Measurement;
import Std.Measurement.*;
@EntryPoint()
operation Main() : Result[] {
use q = Qubit();
Expand Down Expand Up @@ -215,7 +215,7 @@ fn mresetz_unrestricted_profile() {
let mut interpreter = interpreter(
r"
namespace Test {
open Microsoft.Quantum.Measurement;
import Std.Measurement.*;
@EntryPoint()
operation Main() : Result[] {
use q = Qubit();
Expand Down Expand Up @@ -243,7 +243,7 @@ fn mresetz_base_profile() {
let mut interpreter = interpreter(
r"
namespace Test {
open Microsoft.Quantum.Measurement;
import Std.Measurement.*;
@EntryPoint()
operation Main() : Result[] {
use q = Qubit();
Expand Down Expand Up @@ -271,7 +271,7 @@ fn unrestricted_profile_result_comparison() {
let mut interpreter = interpreter(
r"
namespace Test {
open Microsoft.Quantum.Measurement;
import Std.Measurement.*;
@EntryPoint()
operation Main() : Result[] {
use q1 = Qubit();
Expand Down Expand Up @@ -439,7 +439,7 @@ fn custom_intrinsic_mixed_args() {
let mut interpreter = interpreter(
r"
namespace Test {
open Microsoft.Quantum.ResourceEstimation;
import Std.ResourceEstimation.*;
@EntryPoint()
operation Main() : Unit {
Expand Down Expand Up @@ -555,7 +555,7 @@ fn operation_with_qubit_arrays() {
@EntryPoint()
operation Main() : Result[] { [] }
open Microsoft.Quantum.Measurement;
import Std.Measurement.*;
operation Test(q1: Qubit[], q2: Qubit[][], q3: Qubit[][][], q: Qubit) : Result[] {
for q in q1 {
H(q);
Expand Down Expand Up @@ -925,7 +925,7 @@ mod debugger_stepping {
let circs = generate_circuit_steps(
r"
namespace Test {
open Microsoft.Quantum.Measurement;
import Std.Measurement.*;
@EntryPoint()
operation Main() : Result[] {
use q = Qubit();
Expand Down Expand Up @@ -974,7 +974,7 @@ mod debugger_stepping {
let circs = generate_circuit_steps(
r"
namespace Test {
open Microsoft.Quantum.Measurement;
import Std.Measurement.*;
@EntryPoint()
operation Main() : Result[] {
use q = Qubit();
Expand Down Expand Up @@ -1012,7 +1012,7 @@ mod debugger_stepping {
let circs = generate_circuit_steps(
r"
namespace Test {
open Microsoft.Quantum.Measurement;
import Std.Measurement.*;
@EntryPoint()
operation Main() : Result[] {
use q = Qubit();
Expand Down
16 changes: 8 additions & 8 deletions compiler/qsc/src/interpret/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ mod given_interpreter {
#[test]
fn open_namespace() {
let mut interpreter = get_interpreter();
let (result, output) = line(&mut interpreter, "open Microsoft.Quantum.Diagnostics;");
let (result, output) = line(&mut interpreter, "import Std.Diagnostics.*;");
is_only_value(&result, &output, &Value::unit());
let (result, output) = line(&mut interpreter, "DumpMachine()");
is_unit_with_output(&result, &output, "STATE:\n|0⟩: 1+0i");
Expand Down Expand Up @@ -328,7 +328,7 @@ mod given_interpreter {
#[test]
fn global_qubits() {
let mut interpreter = get_interpreter();
let (result, output) = line(&mut interpreter, "open Microsoft.Quantum.Diagnostics;");
let (result, output) = line(&mut interpreter, "import Std.Diagnostics.*;");
is_only_value(&result, &output, &Value::unit());
let (result, output) = line(&mut interpreter, "DumpMachine()");
is_unit_with_output(&result, &output, "STATE:\n|0⟩: 1+0i");
Expand Down Expand Up @@ -453,7 +453,7 @@ mod given_interpreter {
is_only_value(&result, &output, &Value::unit());
let (result, output) = line(&mut interpreter, "open Other;");
is_only_value(&result, &output, &Value::unit());
let (result, output) = line(&mut interpreter, "open Microsoft.Quantum.Diagnostics;");
let (result, output) = line(&mut interpreter, "import Std.Diagnostics.*;");
is_only_value(&result, &output, &Value::unit());
let (result, output) = line(&mut interpreter, "DumpMachine();");
is_only_error(
Expand All @@ -463,7 +463,7 @@ mod given_interpreter {
name error: `DumpMachine` could refer to the item in `Other` or `Microsoft.Quantum.Diagnostics`
ambiguous name [line_3] [DumpMachine]
found in this namespace [line_1] [Other]
and also in this namespace [line_2] [Microsoft.Quantum.Diagnostics]
and also in this namespace [line_2] [Std.Diagnostics]
type error: insufficient type information to infer type
[line_3] [DumpMachine()]
"#]],
Expand All @@ -479,7 +479,7 @@ mod given_interpreter {
&output,
&expect![[r#"
runtime error: qubits in invocation are not unique
[qsharp-library-source:intrinsic.qs] [(control, target)]
[qsharp-library-source:Std/Intrinsic.qs] [(control, target)]
"#]],
);
}
Expand Down Expand Up @@ -749,7 +749,7 @@ mod given_interpreter {
&mut interpreter,
indoc! {r#"
namespace Test {
open Microsoft.Quantum.Math;
import Std.Math.*;
open QIR.Intrinsic;
@EntryPoint()
operation Main() : Result {
Expand Down Expand Up @@ -1552,7 +1552,7 @@ mod given_interpreter {
fn debugger_execution_with_call_to_library_succeeds() {
let source = indoc! { r#"
namespace Test {
open Microsoft.Quantum.Math;
import Std.Math.*;
@EntryPoint()
operation Main() : Int {
Binom(31, 7)
Expand All @@ -1579,7 +1579,7 @@ mod given_interpreter {
fn debugger_execution_with_early_return_succeeds() {
let source = indoc! { r#"
namespace Test {
open Microsoft.Quantum.Arrays;
import Std.Arrays.*;
operation Max20(i : Int) : Int {
if (i > 20) {
Expand Down
2 changes: 1 addition & 1 deletion compiler/qsc/src/location.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ mod tests {

expect![[r#"
Location {
source: "qsharp-library-source:arrays.qs",
source: "qsharp-library-source:Std/Arrays.qs",
range: Range {
start: Position {
line: 0,
Expand Down
9 changes: 8 additions & 1 deletion compiler/qsc_codegen/src/qsharp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,19 +162,26 @@ impl<W: Write> Visitor<'_> for QSharpGen<W> {
ImportOrExportItem {
ref path,
ref is_glob,
..
ref alias,
},
) in decl.items.iter().enumerate()
{
let is_last = ix == decl.items.len() - 1;
self.visit_path(path);

if *is_glob {
self.write(".*");
}

if let Some(ref alias) = alias {
self.write(&format!(" as {}", alias.name));
}

if !is_last {
self.write(", ");
};
}

self.write(";");
}
}
Expand Down
24 changes: 12 additions & 12 deletions compiler/qsc_codegen/src/qsharp/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,20 @@ fn open() {
check(
indoc! {r#"
namespace Sample {
open Microsoft.Quantum.Intrinsic as sics;
import Std.Intrinsic as sics;
open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Intrinsic as intrin;
import Std.Diagnostics.*;
import Std.Intrinsic as intrin;
@EntryPoint()
operation Entry() : Unit {
}
}"#},
None,
&expect![[r#"
namespace Sample {
open Microsoft.Quantum.Intrinsic as sics;
open Microsoft.Quantum.Diagnostics;
open Microsoft.Quantum.Intrinsic as intrin;
import Std.Intrinsic as sics;
import Std.Diagnostics.*;
import Std.Intrinsic as intrin;
@EntryPoint()
operation Entry() : Unit {}
}"#]],
Expand Down Expand Up @@ -472,7 +472,7 @@ fn lambda_fns() {
check(
indoc! {r#"
namespace A {
open Microsoft.Quantum.Arrays;
import Std.Arrays.*;
operation B() : Unit {
let add = (x, y) -> x + y;
let intArray = [1, 2, 3, 4, 5];
Expand Down Expand Up @@ -501,7 +501,7 @@ fn lambda_fns() {
None,
&expect![[r#"
namespace A {
open Microsoft.Quantum.Arrays;
import Std.Arrays.*;
operation B() : Unit {
let add = (x, y) -> x + y;
let intArray = [1, 2, 3, 4, 5];
Expand Down Expand Up @@ -534,7 +534,7 @@ fn ranges() {
check(
indoc! {r#"
namespace A {
open Microsoft.Quantum.Arrays;
import Std.Arrays.*;
operation B() : Unit {
let range = 1..3;
let range = 2..2..5;
Expand All @@ -558,7 +558,7 @@ fn ranges() {
None,
&expect![[r#"
namespace A {
open Microsoft.Quantum.Arrays;
import Std.Arrays.*;
operation B() : Unit {
let range = 1..3;
let range = 2..2..5;
Expand Down Expand Up @@ -620,7 +620,7 @@ fn field_access_and_string_interning() {
check(
indoc! {r#"
namespace A {
open Microsoft.Quantum.Math;
import Std.Math.*;
function ComplexAsString(x : Complex) : String {
if x.Imag < 0.0 {
$"{x.Real} - {AbsD(x.Imag)}i"
Expand All @@ -632,7 +632,7 @@ fn field_access_and_string_interning() {
None,
&expect![[r#"
namespace A {
open Microsoft.Quantum.Math;
import Std.Math.*;
function ComplexAsString(x : Complex) : String {
if x.Imag < 0. {
$"{x.Real} - {AbsD(x.Imag)}i"
Expand Down
12 changes: 6 additions & 6 deletions compiler/qsc_data_structures/src/namespaces.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ mod tests;
use rustc_hash::{FxHashMap, FxHashSet};
use std::{cell::RefCell, collections::BTreeMap, fmt::Display, iter::Peekable, ops::Deref, rc::Rc};

pub const PRELUDE: [[&str; 3]; 4] = [
["Microsoft", "Quantum", "Canon"],
["Microsoft", "Quantum", "Core"],
["Microsoft", "Quantum", "Intrinsic"],
["Microsoft", "Quantum", "Measurement"],
pub const PRELUDE: &[&[&str]; 4] = &[
&["Std", "Canon"],
&["Microsoft", "Quantum", "Core"],
&["Std", "Intrinsic"],
&["Std", "Measurement"],
];

/// An ID that corresponds to a namespace in the global scope.
Expand Down Expand Up @@ -279,7 +279,7 @@ impl Default for NamespaceTreeRoot {
memo: RefCell::new(FxHashMap::default()),
};
// insert the prelude namespaces using the `NamespaceTreeRoot` API
for ns in &PRELUDE {
for ns in PRELUDE {
let iter = ns.iter().map(|s| Rc::from(*s)).peekable();
let _ = tree.insert_or_find_namespace(iter);
}
Expand Down
Loading

0 comments on commit 7f6e302

Please sign in to comment.