Complete Language Reference
Sansqrit DSL — Complete Syntax
The definitive, exhaustive reference for every capability of the Sansqrit Domain-Specific Language. This page documents 33 keywords, 22 operators, 8 data types, 25 statement types, 80+ built-in functions including 46 quantum gates, 19 algorithms, 17 circuits, 15 math functions, 12 collection functions, 7 string methods, 5 I/O functions, and 5 physical constants. Every entry includes syntax, parameters, return type, and a runnable example. Source: github.com/sansqrit/sansqritR
Language Mindmap
This infographic shows the complete structure of the Sansqrit DSL. Every node is a capability documented on this page. The language is organized into three layers: classical computing (variables, control flow, functions), quantum computing (gates, algorithms, circuits), and domain packages (chemistry, biology, ML).
Quick Start — Your First Program
Sansqrit programs are saved as .sq files and executed with cargo run --bin sansqrit -- run program.sq. The language is Python-like in appearance but quantum-native: gate functions and measurement are first-class operations, not library calls. Here is a complete program that creates a Bell state, measures it 1000 times, and prints the results:
-- bell.sq — A complete Sansqrit program
print("Creating a Bell state...")
simulate {
let q = quantum_register(2) -- allocate 2 qubits
H(q[0]) -- Hadamard on qubit 0
CNOT(q[0], q[1]) -- entangle qubits 0 and 1
let result = measure_all(q, shots=1000)
print(f"Results: {result}") -- {"00": ~500, "11": ~500}
print(f"⟨Z₀⟩ = {expectation_z(q[0]):.4f}")
}
print("Done!")
How the lexer processes this: The lexer reads each character and produces tokens: KW_PRINT, LPAREN, STRING("Creating..."), RPAREN, NEWLINE, KW_SIMULATE, LBRACE, etc. The parser then builds an AST with a Simulate statement containing a body of LetDecl, ExprStmt (gate calls), and LetDecl (measurement). The interpreter executes these sequentially, dispatching gate calls to the QuantumEngine.
Keywords (33)
Reserved words that cannot be used as variable names. These are recognized by the lexer and have special meaning in the parser. The complete list:
| Keyword | Purpose | Example |
|---|---|---|
let | Declare a mutable variable | let x = 42 |
const | Declare an immutable constant | const N = 100 |
fn | Define a function | fn add(a, b) { return a + b } |
return | Return value from function | return result |
class | Define a class with methods | class Qubit { ... } |
struct | Define a data structure | struct Point { x, y } |
extends | Class inheritance | class Cat extends Animal { } |
if | Conditional branch | if x > 0 { ... } |
else | Alternative branch | else { ... } |
for | Iterate over a range or collection | for i in range(10) { ... } |
while | Loop with condition | while x < 100 { x += 1 } |
loop | Infinite loop (use break to exit) | loop { if done { break } } |
break | Exit a loop | break |
continue | Skip to next iteration | continue |
match | Pattern matching | match x { 1 => "one", _ => "other" } |
in | Membership test / for-in iteration | if "a" in list { ... } |
and | Logical AND | if a and b { ... } |
or | Logical OR | if a or b { ... } |
not | Logical NOT | if not done { ... } |
true | Boolean true literal | let flag = true |
false | Boolean false literal | let flag = false |
None | Null/nothing value | let result = None |
import | Import a module or package | import chemistry |
as | Alias for imports | import chemistry as chem |
simulate | Open a quantum simulation block | simulate { ... } |
quantum | Quantum hardware block (future) | quantum { ... } |
classical | Classical computation block | classical { ... } |
circuit | Define a reusable quantum circuit | circuit MyCircuit(n) { ... } |
molecule | Define a molecular system | molecule H2 { ... } |
try | Begin error handling block | try { risky() } |
catch | Catch an error | catch e { print(e) } |
finally | Always-execute cleanup | finally { cleanup() } |
raise | Throw an error | raise "invalid input" |
yield | Generator yield (future) | yield value |
Data Types (8)
Sansqrit is dynamically typed — variables can hold any type and types are checked at runtime. The eight fundamental data types are:
| Type | Literal Syntax | Description | Example |
|---|---|---|---|
Int | 42, -7, 0xFF | 64-bit signed integer | let n = 1024 |
Float | 3.14, 1e-6, .5 | 64-bit IEEE 754 float | let pi = 3.14159 |
String | "hello", 'world' | UTF-8 string | let s = "quantum" |
Bool | true, false | Boolean | let flag = true |
List | [1, 2, 3] | Ordered, mutable collection | let v = [1, 2, 3] |
Dict | {"a": 1} | Key-value map | let d = {"x": 10} |
Set | {1, 2, 3} | Unordered unique elements | let s = {1, 2, 3} |
None | None | Null/absent value | let r = None |
-- Type examples
let age = 42 -- Int
let energy = -1.137 -- Float
let name = "Sansqrit" -- String
let active = true -- Bool
let primes = [2, 3, 5, 7] -- List
let config = {"shots": 1000} -- Dict
let unique = {1, 2, 3} -- Set
let result = None -- None
-- Type checking
print(type(age)) -- "Int"
print(type(energy)) -- "Float"
print(type(primes)) -- "List"
Operators (22)
Listed from lowest to highest precedence. Operators higher in the table bind more loosely.
| Operator | Name | Precedence | Example | Result |
|---|---|---|---|---|
|> | Pipeline | 1 (lowest) | [3,1,2] |> sort |> print | [1,2,3] |
or | Logical OR | 2 | a or b | true/false |
and | Logical AND | 3 | a and b | true/false |
not | Logical NOT | 4 | not x | true/false |
in | Membership | 5 | 3 in [1,2,3] | true |
== != | Equality | 6 | x == 42 | true/false |
< > <= >= | Comparison | 7 | x < 10 | true/false |
| | Bitwise OR | 8 | 5 | 3 | 7 |
^ | Bitwise XOR | 9 | 5 ^ 3 | 6 |
& | Bitwise AND | 10 | 5 & 3 | 1 |
<< >> | Bit shift | 11 | 1 << 4 | 16 |
+ - | Add / Subtract | 12 | 3 + 4 | 7 |
* / // % | Mul / Div / IntDiv / Mod | 13 | 7 // 2 | 3 |
** | Power | 14 | 2 ** 10 | 1024 |
-x ~x | Unary neg / bitwise NOT | 15 (highest) | -3 | -3 |
Assignment Operators
let x = 10 -- assign
x += 5 -- add-assign: x = 15
x -= 3 -- subtract-assign: x = 12
x *= 2 -- multiply-assign: x = 24
x /= 4 -- divide-assign: x = 6.0
Variables & Constants
Variables are declared with let (mutable) or const (immutable). Sansqrit uses lexical scoping — variables are visible in the block where they are declared and all nested blocks.
let x = 42 -- mutable: can be reassigned
x = 99 -- OK: x is mutable
const PI_APPROX = 3.14 -- immutable: cannot be reassigned
-- PI_APPROX = 3.0 -- ERROR: cannot reassign const
-- Type annotation (optional)
let name: String = "Alice"
let count: Int = 0
-- Multiple assignments
let a = 1
let b = 2
let c = a + b -- c = 3
Control Flow
if / else / else if
if energy < -1.0 {
print("Ground state found!")
} else if energy < 0.0 {
print("Bound state")
} else {
print("Unbound")
}
for loop
-- Range iteration
for i in range(10) { print(i) } -- 0,1,2,...,9
for i in range(2, 8) { print(i) } -- 2,3,...,7
for x in range_step(0.0,1.0,0.1) { } -- float stepping
-- Collection iteration
for item in ["H", "He", "Li"] { print(item) }
-- Enumerated iteration
for (i, val) in enumerate(["a","b","c"]) {
print(f"{i}: {val}") -- 0: a, 1: b, 2: c
}
-- Zip iteration
for (a, b) in zip([1,2], ["x","y"]) { print(a, b) }
while / loop
let n = 1
while n < 1000 { n *= 2 }
print(n) -- 1024
loop {
let r = measure(q[0])
if r == 1 { break }
}
match (Pattern Matching)
match gate_name {
"H" => print("Hadamard"),
"X" | "Y" | "Z" => print("Pauli gate"),
"CNOT" => print("Entangling gate"),
_ => print(f"Unknown: {gate_name}")
}
Functions & Lambdas
-- Named function with default parameter
fn greet(name, greeting="Hello") {
return f"{greeting}, {name}!"
}
print(greet("Alice")) -- "Hello, Alice!"
print(greet("Bob", "Hi")) -- "Hi, Bob!"
-- Lambda (anonymous function)
let square = fn(x) { x ** 2 }
print(square(5)) -- 25
-- Higher-order functions
let doubled = map([1,2,3], fn(x) { x * 2 }) -- [2, 4, 6]
let evens = filter([1,2,3,4], fn(x) { x % 2 == 0 }) -- [2, 4]
let total = reduce([1,2,3,4], fn(a,b) { a + b }, 0) -- 10
Classes & Structs
-- Struct: data-only container
struct Point { x, y }
let p = Point(3.0, 4.0)
print(p.x) -- 3.0
-- Class: data + methods
class Particle {
fn init(self, mass, charge) {
self.mass = mass
self.charge = charge
}
fn energy(self, velocity) {
return 0.5 * self.mass * velocity ** 2
}
}
let electron = Particle(9.1e-31, -1.6e-19)
print(electron.energy(1e6))
-- Inheritance
class Photon extends Particle { }
Strings & F-Strings
let s = "Hello, World"
let s2 = 'single quotes work too'
-- F-strings (formatted string literals) — embed expressions
let e = -1.137
print(f"Energy = {e:.6f} Hartree") -- "Energy = -1.137000 Hartree"
print(f"2 + 3 = {2 + 3}") -- "2 + 3 = 5"
print(f"Pi ≈ {PI:.4f}") -- "Pi ≈ 3.1416"
-- String methods
print(s.upper()) -- "HELLO, WORLD"
print(s.lower()) -- "hello, world"
print(s.contains("World")) -- true
print(s.replace("World", "Quantum")) -- "Hello, Quantum"
print(s.split(", ")) -- ["Hello", "World"]
print(len(s)) -- 12
Collections
-- Lists
let nums = [1, 2, 3, 4, 5]
nums.append(6) -- [1,2,3,4,5,6]
let last = nums.pop() -- 6 (removes last element)
print(nums[0]) -- 1 (indexing)
print(nums[-1]) -- 5 (negative index)
-- List comprehensions
let squares = [x**2 for x in range(10)] -- [0,1,4,9,...,81]
-- Dictionaries
let d = {"H": 1, "He": 2, "Li": 3}
print(d["H"]) -- 1
d["Be"] = 4 -- add entry
Pipeline Operator ( |> )
The pipeline operator passes the result of the left expression as the first argument to the right function. It enables a data-flow style of programming that is especially natural for quantum circuits.
-- Without pipeline (nested calls, hard to read):
print(sort(filter([5,2,8,1,9], fn(x) { x > 3 })))
-- With pipeline (left-to-right, readable):
[5,2,8,1,9] |> filter(fn(x) { x > 3 }) |> sort |> print
-- Output: [5, 8, 9]
Error Handling
try {
let result = shor_factor(1) -- might fail for N=1
} catch e {
print(f"Error: {e}")
} finally {
print("Cleanup complete")
}
-- Raise custom errors
fn validate_qubits(n) {
if n < 1 { raise "Need at least 1 qubit" }
}
Import System
import chemistry -- import entire package
import biology as bio -- import with alias
import medical
import physics
import genetics
import ml
import math
-- Available packages:
-- chemistry : VQE, PES, Trotter, molecular Hamiltonians
-- biology : DNA/RNA, protein folding, alignment
-- medical : drug screening, vaccine design, binding energy
-- physics : Ising model, Heisenberg chain, time evolution
-- genetics : CRISPR guide design, GWAS, variant calling
-- ml : QNN, QSVM, QPCA, variational classifiers
-- math : Shor factoring, Grover search, HHL solver
Simulate Block
The simulate block is where quantum operations happen. It creates a QuantumEngine instance, executes the body, and captures measurement results. You can specify the engine tier explicitly or let Sansqrit auto-select based on qubit count.
-- Auto-select engine (default)
simulate {
let q = quantum_register(4)
H(q[0])
print(measure_all(q, shots=1000))
}
-- Force chunked engine for large circuits
simulate(engine="Chunked") {
let q = quantum_register(100)
H(q[0])
for i in range(99) { CNOT(q[i], q[i+1]) }
print(measure_all(q, shots=100))
}
-- Force sparse engine
simulate(engine="Sparse") { /* ... */ }
-- Force dense engine
simulate(engine="Dense") { /* ... */ }
Quantum Operations — Complete Reference
quantum_register(n) → Qubit Array
Allocates n qubits, all initialized to |0⟩. Returns an array-like object that supports indexing with q[i].
let q = quantum_register(8) -- 8 qubits, all |0⟩
print(n_qubits()) -- 8
All 46 Gate Functions
Every gate is called as a function inside a simulate block. Single-qubit gates take one qubit argument. Parametric gates take a qubit and angle(s). Two-qubit gates take two qubits. Three-qubit gates take three qubits. Multi-qubit gates take lists.
| Category | Gate | Syntax | Parameters |
|---|---|---|---|
| Single (18) | Identity | I(q[0]) | none |
| Pauli X/Y/Z | X(q[0]), Y(q[0]), Z(q[0]) | none | |
| Hadamard | H(q[0]) | none | |
| S / S† | S(q[0]), Sdg(q[0]) | none | |
| T / T† | T(q[0]), Tdg(q[0]) | none | |
| √X / √X† | SX(q[0]), SXdg(q[0]) | none | |
| Rx / Ry / Rz | Rx(q[0], θ) | θ: rotation angle | |
| Phase / U1 | Phase(q[0], θ), U1(q[0], λ) | θ or λ | |
| U2 | U2(q[0], φ, λ) | φ, λ | |
| U3 | U3(q[0], θ, φ, λ) | θ, φ, λ | |
| Batch | H_all(q), Rx_all(q, θ), Ry_all(q, θ) | optional θ | |
| Two (21) | CNOT / CZ / CY | CNOT(q[0],q[1]) | none |
| CH / CSX | CH(q[0],q[1]) | none | |
| SWAP variants | SWAP(a,b), iSWAP(a,b), SqrtSWAP(a,b), fSWAP(a,b), DCX(a,b) | none | |
| CRx / CRy / CRz | CRx(c, t, θ) | θ | |
| CP | CP(c, t, θ) | θ | |
| CU | CU(c, t, θ, φ, λ) | θ, φ, λ | |
| RXX / RYY / RZZ / RZX | RZZ(q[0], q[1], θ) | θ | |
| ECR / MS | ECR(q[0],q[1]), MS(q[0],q[1]) | none | |
| Three (3) | Toffoli / CCX | Toffoli(c0,c1,target) | none |
| Fredkin / CSWAP / CCZ | CCZ(q[0],q[1],q[2]) | none | |
| Multi (4) | MCX / MCZ / C3X / C4X | MCX([c0,c1,...],target) | none |
Measurement Functions
| Function | Syntax | Returns | Description |
|---|---|---|---|
measure | measure(q[i]) | 0 or 1 | Collapse qubit, return classical bit |
measure_all | measure_all(q, shots=N) | Dict of bitstring→count | Sample N times without collapse |
probabilities | probabilities(q) | List of (bitstring, prob) | Get exact probability distribution |
expectation_z | expectation_z(q[i]) | Float in [-1, 1] | ⟨Z⟩ on single qubit |
expectation_zz | expectation_zz(q[i], q[j]) | Float in [-1, 1] | ⟨Z⊗Z⟩ on two qubits |
engine_nnz | engine_nnz() | Int | Count non-zero amplitudes |
n_qubits | n_qubits() | Int | Total qubit count |
Circuit Constructor Functions (17)
| Function | Syntax | Description |
|---|---|---|
bell_state | bell_state(q[0], q[1]) | (|00⟩+|11⟩)/√2 |
ghz_state | ghz_state(q) | (|00...0⟩+|11...1⟩)/√2 |
w_state | w_state(q) | Equal superposition: exactly one |1⟩ |
cluster_state | cluster_state(q) | Graph state for MBQC |
dicke_state | dicke_state(q, k=2) | D(n,k): C(n,k) terms |
cat_state | cat_state(q) | Schrödinger cat = GHZ alias |
qft | qft(q) | Quantum Fourier Transform |
iqft | iqft(q) | Inverse QFT |
draper_qft_adder | draper_qft_adder(a, b) | A = A + B using QFT |
quantum_multiplier | quantum_multiplier(a,b,result) | result = a × b |
amplitude_encoding | amplitude_encoding(q, data) | Encode vector into amplitudes |
angle_encoding | angle_encoding(q, data) | Encode data as Ry angles |
basis_encoding | basis_encoding(q, value) | Encode integer as basis state |
random_circuit | random_circuit(q, depth, seed) | Benchmarking circuit |
bit_flip_encode | bit_flip_encode(d, a1, a2) | 3-qubit X error correction |
phase_flip_encode | phase_flip_encode(d, a1, a2) | 3-qubit Z error correction |
shor_9qubit_encode | shor_9qubit_encode(q[0..9]) | Full QEC |
Algorithm Functions (19)
| Function | Syntax | Returns |
|---|---|---|
grover_search | grover_search(n_qubits, target, shots) | GroverResult {solution, probability, n_queries, histogram} |
grover_search_multi | grover_search_multi(n_qubits, targets, shots) | GroverResult |
shor_factor | shor_factor(N) | ShorResult {factors, period, success} |
vqe | vqe(n_qubits, hamiltonian, layers, max_iter, tol) | VqeResult {energy, params, converged, history} |
vqe_h2 | vqe_h2(bond_length, max_iter) | VqeResult |
qaoa_maxcut | qaoa_maxcut(edges, n_nodes, layers, shots) | QaoaResult {best_bitstring, best_cost} |
quantum_phase_estimation | estimate_phase(n_counting_bits, unitary_angle) | QpeResult {phase, phase_bits} |
hhl_solve | hhl_solve(A, b) | HhlResult {solution, condition_number} |
bernstein_vazirani | bernstein_vazirani(n_bits, oracle_secret) | List of bits |
simon_algorithm | simon_algorithm(n_bits, secret) | List of bits |
deutsch_jozsa | deutsch_jozsa(n_bits, oracle_type) | "constant" or "balanced" |
quantum_walk_line | quantum_walk_line(n_positions, n_steps, shots) | MeasurementResult |
quantum_counting | quantum_counting(search_bits, counting_bits, solutions) | QaeResult {count_estimate} |
swap_test | swap_test(engine1, engine2, shots) | Float (overlap) |
teleport | teleport(engine) | (bit0, bit1) |
superdense_coding | superdense_coding(bit0, bit1) | (received0, received1) |
bb84_qkd | bb84_qkd(key_length) | (alice_key, bob_key, error_rate) |
amplitude_estimation | amplitude_estimation(n_qubits, eval_bits, target) | QaeResult |
variational_classifier | variational_classifier(features, data, layers, epochs, lr) | (params, accuracy) |
Math Functions (15)
| Function | Syntax | Description | Example |
|---|---|---|---|
sqrt | sqrt(x) | Square root | sqrt(16) → 4.0 |
abs | abs(x) | Absolute value | abs(-5) → 5 |
sin | sin(x) | Sine (radians) | sin(PI/2) → 1.0 |
cos | cos(x) | Cosine (radians) | cos(0) → 1.0 |
tan | tan(x) | Tangent (radians) | tan(PI/4) → 1.0 |
log | log(x) | Natural logarithm (ln) | log(E) → 1.0 |
exp | exp(x) | e^x | exp(1) → 2.718... |
pow | pow(x, y) | x raised to power y | pow(2, 10) → 1024 |
floor | floor(x) | Round down to int | floor(3.7) → 3 |
ceil | ceil(x) | Round up to int | ceil(3.2) → 4 |
round | round(x) or round(x, n) | Round to n decimal places | round(3.456, 2) → 3.46 |
sum | sum(list) | Sum of all elements | sum([1,2,3]) → 6 |
mean | mean(list) | Arithmetic mean | mean([2,4,6]) → 4.0 |
min | min(list) or min(a,b) | Minimum value | min([5,1,3]) → 1 |
max | max(list) or max(a,b) | Maximum value | max([5,1,3]) → 5 |
Collection Functions (12)
| Function | Syntax | Description | Example |
|---|---|---|---|
len | len(x) | Length of string, list, or dict | len([1,2,3]) → 3 |
range | range(n) or range(start,end) | Generate integer range | range(5) → [0,1,2,3,4] |
range_step | range_step(start, end, step) | Float range with step | range_step(0,1,0.2) → [0,0.2,0.4,0.6,0.8] |
enumerate | enumerate(list) | Index + value pairs | enumerate(["a","b"]) → [(0,"a"),(1,"b")] |
zip | zip(a, b) | Pair elements from two lists | zip([1,2],[3,4]) → [(1,3),(2,4)] |
map | map(list, fn) | Apply function to each element | map([1,2,3], fn(x){x*2}) → [2,4,6] |
filter | filter(list, fn) | Keep elements where fn returns true | filter([1,2,3,4], fn(x){x>2}) → [3,4] |
reduce | reduce(list, fn, init) | Fold list into single value | reduce([1,2,3], fn(a,b){a+b}, 0) → 6 |
sort | sort(list) | Sort ascending | sort([3,1,2]) → [1,2,3] |
append | list.append(val) | Add element to end | [1,2].append(3) → [1,2,3] |
pop | list.pop() | Remove and return last | [1,2,3].pop() → 3 |
top_k | top_k(result, k) | Top k measurement results | top_k(histogram, 3) |
String Methods (7)
| Method | Syntax | Returns | Example |
|---|---|---|---|
upper | s.upper() | Uppercase string | "hello".upper() → "HELLO" |
lower | s.lower() | Lowercase string | "HELLO".lower() → "hello" |
contains | s.contains(sub) | Bool | "quantum".contains("ant") → true |
replace | s.replace(old, new) | New string | "ab".replace("a","x") → "xb" |
split | s.split(delim) | List of strings | "a,b,c".split(",") → ["a","b","c"] |
join | delim.join(list) | Joined string | ", ".join(["a","b"]) → "a, b" |
len | len(s) | Int | len("hello") → 5 |
I/O Functions (5)
| Function | Syntax | Description |
|---|---|---|
print | print(value, ...) | Print values to stdout, space-separated |
read_csv | read_csv("file.csv") | Read CSV file into list of dicts |
write_csv | write_csv("out.csv", data) | Write list of dicts to CSV |
read_json | read_json("file.json") | Read JSON file into dict |
read_file | read_file("file.txt") | Read entire text file as string |
Type Conversion Functions (5)
| Function | Syntax | Example |
|---|---|---|
int | int(x) | int(3.7) → 3, int("42") → 42 |
float | float(x) | float(3) → 3.0, float("3.14") → 3.14 |
str | str(x) | str(42) → "42" |
bool | bool(x) | bool(0) → false, bool(1) → true |
type | type(x) | type(42) → "Int", type([]) → "List" |
Built-in Constants
| Constant | Value | Description |
|---|---|---|
PI | 3.141592653589793 | π — fundamental to all rotation gates |
E | 2.718281828459045 | Euler's number — natural logarithm base |
PLANCK | 6.62607015 × 10⁻³⁴ | Planck's constant (J·s) |
BOLTZMANN | 1.380649 × 10⁻²³ | Boltzmann's constant (J/K) |
AVOGADRO | 6.02214076 × 10²³ | Avogadro's number (mol⁻¹) |
Molecule Declaration
molecule H2 {
atoms: [H, H],
bond_length: 0.74,
basis_set: "STO-3G"
}
molecule LiH {
atoms: [Li, H],
bond_length: 1.6,
basis_set: "STO-3G"
}
-- Use in VQE:
simulate {
let r = vqe(H2)
print(f"H₂ energy: {r.energy:.6f} Ha")
}
Circuit Declaration
circuit BellPair(q0, q1) {
H(q0)
CNOT(q0, q1)
}
circuit QFTCircuit(qubits) {
for i in range(len(qubits)) {
H(qubits[i])
for j in range(i+1, len(qubits)) {
CP(qubits[j], qubits[i], PI / (1 << (j-i)))
}
}
}
simulate {
let q = quantum_register(4)
BellPair(q[0], q[1])
QFTCircuit(q)
print(measure_all(q, shots=1000))
}
Comments