QuantumScript (.qts)

QuantumScript is a strict, TypeScript-inspired, natively compiled programming language designed to bridge classical web development and quantum computing. It allows developers to model quantum superposition, entanglement, and wave-function collapse using high-level syntax that runs locally via a Go binary, or directly inside web applications via a client-side WebAssembly (WASM) runner.

💡 Why QuantumScript?
Unlike low-level assembly representations (like OpenQASM) or Python SDK wrapper code, QuantumScript is structured as an actual statically-typed programming language. It performs compile-time verification to prevent common developer errors, like applying quantum operations to classical boolean variables.

Key Language Features

🔒

Strict Type Checking

The compiler enforces distinct boundaries between classical variables (number, string, boolean) and quantum registers (qubit). Attempting to use classical values inside quantum gates throws immediate syntax errors.

♻️

Quantum Garbage Collection

Underneath, the language engine tracks local qubits and automatically uncomputes their history using conjugate transpose adjoint gates when they leave scope, preventing state leakage.

⛓️

Implicit Entanglement

Placing qubit registers inside conditional if blocks automatically converts the statements into multi-controlled quantum operations (like Controlled-NOT gates).

🔌

Hardware SWAP Routing

Compiles directly into OpenQASM 3.0 for actual hardware, automatically generating SWAP gates to map qubits onto linear chip topologies.

Installation & CLI

QuantumScript is built in Go, offering a fast compiler and local simulator engine. You can run quantum algorithms locally using the terminal or embed the WebAssembly bundle in your frontend application.

Local Installation (Windows)

Run the automated installer script from the root of the cloned repository to build and expose the qs CLI tool globally:

.\install.ps1

Using the CLI Compiler

The compiler exposes several subcommands to build and run files ending in .qts or .qs:

1. Scaffold a New Project

qs init my-quantum-project

This creates a new folder containing main.qts and module.qts showcasing modular imports and exports.

2. Run Simulator (1,000 Shots)

qs run main.qts

The engine executes the code 1,000 times, recording statistics on the measured qubits and displaying the probability of collapsing into the state \(|1\rangle\) or \(|0\rangle\).

3. Hardware Noise Simulation

Simulate realistic hardware imperfections by injecting a depolarizing error rate. A noise value of 0.05 adds a 5% chance of a random Pauli error (\(X\), \(Y\), or \(Z\)) after every gate application:

qs run --noise=0.05 main.qts

4. Export to IBM QASM 3.0

qs export-qasm main.qts

Generates OpenQASM 3.0 code ready to be executed on physical IBM quantum computers.

VS Code Extension & LSP

QuantumScript includes a dedicated Language Server Protocol (LSP) server for real-time syntax checking, auto-completions, and type warnings.

To start the server manually:

qs lsp

To enable syntax highlighting and editor errors, install the included VS Code extension located in vscode-extension/ in this repository.

Classical Logic & Math

QuantumScript provides standard classical data types and mathematical structures so you can build classical control loops that prepare or process quantum states.

Declaring Variables

Variables are declared using block-scoped const (read-only) or let (mutable) keywords, matching TypeScript syntax:

const pi: number = 3.14159265;
let iterations: number = 10;
const label: string = "Entanglement Run";
const isVerified: boolean = true;

Object Literals

Structure complex data structures using inline object literals:

const config: object = {
    shots: 1000,
    noiseModel: "depolarizing",
    verbose: false
};
const shotCount: number = config.shots;

Built-in Math Module

The compiler integrates a native Math module containing fundamental mathematical operations and constants (e.g. for rotation gate angles):

Expression Return Type Description
Math.PI or Math.pi number The circle ratio constant \(\pi \approx 3.14159\)
Math.sin(theta) number Trigonometric Sine function
Math.cos(theta) number Trigonometric Cosine function
Math.sqrt(val) number Square root function

Qubits & Quantum Gates

QuantumScript treats the qubit as a native, compiler-tracked reference. Qubits are allocated in the absolute zero state \(|0\rangle\) and manipulated using a set of built-in gate operations.

Qubit Allocation

Instantiate a qubit by invoking the Qubit constructor with the new keyword:

const q: qubit = new Qubit(); // Allocated in state |0⟩

Core Quantum Operations

QuantumScript exposes three core primitives built into the syntax:

1. Superposition: superpose(q)

Applies a Hadamard (H) gate to the qubit, shifting it into a 50/50 superposition of \(|0\rangle\) and \(|1\rangle\):

\[H |0\rangle = \frac{|0\rangle + |1\rangle}{\sqrt{2}}\]

2. Inversion: invert(q)

Applies a Pauli-X (Not) gate. Flips a qubit from \(|0\rangle \to |1\rangle\) or vice-versa.

3. Collapse: measure(q)

Collapses the quantum state vector, returning a classical boolean. If the state collapses to \(|1\rangle\), it returns true. If it collapses to \(|0\rangle\), it returns false.

⚠️ Destruction by Measurement
Measuring a qubit collapses its wave-function permanently into a classical state, breaking any existing entanglement it holds with other qubits in the system.

Standard Gate Library

For fine-tuned algorithms, the following mathematical gates are exposed in the compiler namespace:

  • Pauli Gates: X(q), Y(q), Z(q)
  • Phase Gates: S(q) (90-degree Z rotation), T(q) (45-degree Z rotation)
  • Rotational Gates: Rx(theta, q), Ry(theta, q), Rz(theta, q)
// Rotate a qubit into a half-angle state using Ry
const q: qubit = new Qubit();
Ry(Math.PI / 4, q);

The Adjoint Modifier

You can execute the mathematical inverse (complex conjugate transpose) of any standard operation by prefixing the function call with the adjoint keyword. This is heavily used to reverse operations during uncomputation:

adjoint S(q);           // Becomes S-dagger (Sdg)
adjoint Rx(Math.PI, q); // Becomes Rx(-Math.PI)

Arbitrary State Preparation

The compiler provides a utility function StatePrep(amplitudes: number[], register: qubit[]) to initialize qubits directly into specific state vector configurations. The simulator automatically normalizes the array amplitude vector:

const reg: qubit[] = new Qubit[2];
// Prepares state: 0.6|00⟩ + 0.8|11⟩
StatePrep([0.6, 0.0, 0.0, 0.8], reg);

Loops, Functions & Garbage Collection

QuantumScript allows you to scale algorithms by combining arrays, loops, modular functions, and automatic quantum uncomputation.

Qubit Registers (Arrays)

Allocate a register containing multiple qubits using array syntax:

const register: qubit[] = new Qubit[5]; // Allocate 5 qubits

You can iterate over the register using classical for or while loops:

// Put the entire register into uniform superposition
for (let i = 0; i < 5; i = i + 1) {
    superpose(register[i]);
}

Custom Quantum Functions

Write reusable quantum routines by declaring functions with parameters and return types:

function initializeBellState(c: qubit, t: qubit) {
    superpose(c);
    if (c) {
        invert(t);
    }
}

Automatic Quantum Garbage Collection

When running quantum algorithms, temporary workspace qubits (called ancilla qubits) are often required inside a function block. If these qubits are discarded without returning them to their initial state, they remain entangled with the system. This phenomenon creates **quantum phase noise**, destroying the coherence of the overall algorithm.

QuantumScript solves this automatically at the language level. When a qubit goes out of scope (e.g., at the end of a block or function execution), the compiler:

  1. Traces the entire operations history applied specifically to that qubit in the current scope.
  2. Iterates backward through the history list.
  3. Applies the mathematical adjoint of each gate.
  4. Successfully returns the qubit back to the state \(|0\rangle\), clean of entanglement, before reclaiming the memory index.
💡 Cleaner Circuits
Because the engine automatically handles uncomputation, developers don't need to manually undo gates at the end of local sub-blocks, eliminating manual clean-up code.

Entanglement (Control Context)

In classical programming, an if statement branches execution based on a boolean condition. In QuantumScript, passing a qubit into an if condition shifts the compilation context into a **Quantum Control Block**.

Syntax and Operation

When a qubit condition is evaluated, any quantum gate applied within the branch is conditioned on the state of that controller qubit. This allows you to construct entanglement without needing a separate library of CX, CY, or CZ gates:

const ctrl: qubit = new Qubit();
const target: qubit = new Qubit();

superpose(ctrl); // Shifts control into |0⟩ + |1⟩

// Implicit Controlled Operation (acting as a CNOT)
if (ctrl) {
    invert(target);
}

Because the condition is a qubit in superposition, the gates inside the branch execute *partially* based on the quantum amplitude of the controller. This couples the state vectors of the two qubits, generating **quantum entanglement**.

Multi-Qubit Control

Nesting control blocks increases the control requirements. Nesting two conditions creates a Controlled-Controlled-NOT (Toffoli) equivalent:

const c1: qubit = new Qubit();
const c2: qubit = new Qubit();
const target: qubit = new Qubit();

if (c1) {
    if (c2) {
        invert(target); // Executes as a Toffoli gate
    }
}
⚠️ Compiler Restrictions
You cannot perform classical side-effects (like modifying classical numbers or string variables) inside a quantum control block (an if block conditioned on a qubit). Doing so will trigger a compilation error because a quantum computer cannot branch classical values.

QASM Transpilation & Routing

QuantumScript is built to execute algorithms. In addition to simulating states locally, the compiler includes a transpiler to prepare circuits for physical hardware.

OpenQASM 3.0 Export

OpenQASM is the industry standard assembly language for quantum devices. To export a script into a clean, flat QASM representation, run the export CLI tool:

qs export-qasm main.qts

This writes a main.qts.qasm file declaring the register mappings and physical gate instructions.

Linear Topology SWAP Routing

On physical quantum chips, qubits are wired together on a grid or grid-like lattice (e.g. heavy-hex or linear chains). Two-qubit operations (like Controlled-Not) can only be executed between qubits that are physically adjacent on the chip.

If your code applies a controlled operation between q0 and q3 on a linear topology machine, the compiler must route the quantum information. By setting the topology flag, the QuantumScript compiler automatically routes the states using SWAP operations:

qs export-qasm --topology=linear main.qts

Routing Process Example

To control q3 with q0, the compiler automatically generates the following OpenQASM sequence:

  1. swap q0[0], q1[0]; (Moves state 0 next to 1)
  2. swap q1[0], q2[0]; (Moves state 0 next to 2, adjacent to 3)
  3. cx q2[0], q3[0]; (Applies the physical controlled operation)
  4. swap q1[0], q2[0]; (Reverts state 0 back)
  5. swap q0[0], q1[0]; (Returns system to initial layout)

This automated routing makes writing complex algorithms independent of specific hardware layouts.

Interactive Playground

Write, edit, and simulate QuantumScript code in real time using the built-in Go WebAssembly compiler runtime. Choose an example to get started, adjust the noise level slider, and hit **Run Algorithm**.

📜 QuantumScript Source Code
💥 Noise Level: 0.00
📟 Terminal Console Output Simulator (1000 Shots)
Initializing compiler...
📊 Qubit State Probabilities
Qubit [q0]
0%