jeff/types.rs
1//! "Values" represent typed ports in the jeff language.
2//!
3//! Internally, these are coalesced into a single array at the function
4//! definition and each port contains an index into this array.
5
6use crate::capnp::jeff_capnp;
7
8/// Value type.
9#[derive(Clone, Copy, Debug, PartialEq, Eq)]
10pub enum Type {
11 /// Quantum bit.
12 ///
13 /// Qubits are linear types.
14 Qubit,
15 /// Quantum registers.
16 ///
17 /// A quantum register is an array of slots that can hold qubits.
18 /// Slots of a quantum register can either be empty or filled with a qubit.
19 ///
20 /// Quantum registers are linear types.
21 ///
22 /// The length of the register is not known at compile time, but fixed at runtime.
23 QubitRegister,
24 /// Integers.
25 ///
26 /// The type does not distinguish between signed and unsigned integers.
27 /// Instead it is up to the operation to interpret the integer as signed or unsigned.
28 /// Signed integers are represented using two's complement.
29 ///
30 /// Integers of bitwidth 1 can be used as classical bits or boolean values.
31 Int {
32 /// Bitwidth of the integer.
33 bits: u8,
34 },
35 /// Integer array.
36 ///
37 /// The length of the array is not known at compile time, but fixed at runtime.
38 ///
39 /// Arrays of integers of bitwidth 1 can be used as classical bit arrays.
40 IntArray {
41 /// Bitwidth of the integers.
42 bits: u8,
43 },
44 /// Floating point numbers.
45 Float {
46 /// Precision of the floating point number.
47 precision: FloatPrecision,
48 },
49 /// Array of floating point numbers.
50 ///
51 /// The length of the array is not known at compile time, but fixed at runtime.
52 FloatArray {
53 /// Precision of the floating point numbers.
54 precision: FloatPrecision,
55 },
56}
57
58impl Type {
59 /// Create a new integer type.
60 pub fn int(bits: u8) -> Self {
61 Self::Int { bits }
62 }
63
64 /// Create a new boolean type.
65 pub fn bool() -> Self {
66 Self::Int { bits: 1 }
67 }
68
69 /// Create a new integer array type.
70 pub fn int_array(bits: u8) -> Self {
71 Self::IntArray { bits }
72 }
73
74 /// Create a new floating point type.
75 pub fn float(precision: FloatPrecision) -> Self {
76 Self::Float { precision }
77 }
78
79 /// Create a new floating point array type.
80 pub fn float_array(precision: FloatPrecision) -> Self {
81 Self::FloatArray { precision }
82 }
83
84 /// Parse a type from a capnp reader.
85 pub(crate) fn read_capnp(reader: jeff_capnp::type_::Reader<'_>) -> Self {
86 use jeff_capnp::type_::Which;
87 match reader
88 .which()
89 .expect("Type id was not in the schema. Schema should have been verified.")
90 {
91 Which::Qubit(_) => Self::Qubit,
92 Which::Qureg(_) => Self::QubitRegister,
93 Which::Int(bits) => Self::Int { bits },
94 Which::IntArray(bits) => Self::IntArray { bits },
95 Which::Float(prec) => Self::Float {
96 precision: FloatPrecision::from_capnp(prec.expect(
97 "FloatPrecision id was not in the schema. Schema should have been verified.",
98 )),
99 },
100 Which::FloatArray(prec) => Self::FloatArray {
101 precision: FloatPrecision::from_capnp(prec.expect(
102 "FloatPrecision id was not in the schema. Schema should have been verified.",
103 )),
104 },
105 }
106 }
107
108 /// Build a capnp type from this type.
109 #[allow(unused)]
110 pub(crate) fn build_capnp(&self, mut builder: jeff_capnp::type_::Builder) {
111 match self {
112 Self::Qubit => builder.set_qubit(()),
113 Self::QubitRegister => builder.set_qureg(()),
114 Self::Int { bits } => builder.set_int(*bits),
115 Self::IntArray { bits } => builder.set_int_array(*bits),
116 Self::Float { precision } => builder.set_float(precision.as_capnp()),
117 Self::FloatArray { precision } => builder.set_float_array(precision.as_capnp()),
118 }
119 }
120}
121
122/// Precision of floating point number.
123#[derive(Clone, Copy, Debug, PartialEq, Eq)]
124pub enum FloatPrecision {
125 /// 32-bit floating point number.
126 Float32,
127 /// 64-bit floating point number.
128 Float64,
129}
130
131impl FloatPrecision {
132 /// Parse a float precision from a capnp reader.
133 pub(crate) fn from_capnp(reader: jeff_capnp::FloatPrecision) -> Self {
134 match reader {
135 jeff_capnp::FloatPrecision::Float32 => Self::Float32,
136 jeff_capnp::FloatPrecision::Float64 => Self::Float64,
137 }
138 }
139
140 /// Returns the capnp representation of this float precision.
141 pub(crate) fn as_capnp(&self) -> jeff_capnp::FloatPrecision {
142 match self {
143 Self::Float32 => jeff_capnp::FloatPrecision::Float32,
144 Self::Float64 => jeff_capnp::FloatPrecision::Float64,
145 }
146 }
147
148 /// Returns the bitwidth of the floating point number.
149 pub fn bits(self) -> u8 {
150 match self {
151 Self::Float32 => 32,
152 Self::Float64 => 64,
153 }
154 }
155}