Repository: QuTech-Delft/OpenSquirrel (language: python)

Issue:
Rename open_squirrel back to opensquirrel



Discussion / hints:

Fix patch:
diff --git a/docs/reference.md b/docs/reference.md
index 97ad11d6..ee3055fc 100644
--- a/docs/reference.md
+++ b/docs/reference.md
@@ -16,7 +16,7 @@
 ::: opensquirrel.instruction_library
 ::: opensquirrel.merger.general_merger
 ::: opensquirrel.parser.libqasm.libqasm_ir_creator
-::: opensquirrel.squirrel_ir
+::: opensquirrel.ir
 ::: opensquirrel.utils.identity_filter
 ::: opensquirrel.utils.matrix_expander
 
diff --git a/docs/reference/index.html b/docs/reference/index.html
index 5a72addf..329d19ac 100644
--- a/docs/reference/index.html
+++ b/docs/reference/index.html
@@ -2,90 +2,90 @@
 <!doctype html>
 <html lang="en" class="no-js">
   <head>
-    
+
       <meta charset="utf-8">
       <meta name="viewport" content="width=device-width,initial-scale=1">
-      
-      
-      
+
+
+
         <link rel="canonical" href="http://127.0.0.1:8000/C%3A/Users/elenbaascpc/projects/qi2/OpenSquirrel/OpenSquirrel/docs/reference/">
-      
-      
-      
-      
+
+
+
+
       <link rel="icon" href="../../../../../../../../../assets/images/favicon.png">
       <meta name="generator" content="mkdocs-1.5.3, mkdocs-material-9.5.18">
-    
-    
-      
+
+
+
         <title>Reference - OpenSquirrel</title>
-      
-    
-    
+
+
+
       <link rel="stylesheet" href="../../../../../../../../../assets/stylesheets/main.66ac8b77.min.css">
-      
-      
-
-
-    
-    
-      
-    
-    
-      
-        
-        
+
+
+
+
+
+
+
+
+
+
+
+
         <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
         <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback">
         <style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style>
-      
-    
-    
+
+
+
       <link rel="stylesheet" href="../../../../../../../../../assets/_mkdocstrings.css">
-    
+
     <script>__md_scope=new URL("../../../../../../../../..",location),__md_hash=e=>[...e].reduce((e,_)=>(e<<5)-e+_.charCodeAt(0),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
-    
-      
 
-    
-    
-    
+
+
+
+
+
   </head>
-  
-  
+
+
     <body dir="ltr">
-  
-    
+
+
     <input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
     <input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
     <label class="md-overlay" for="__drawer"></label>
     <div data-md-component="skip">
-      
-        
+
+
         <a href="#opensquirrel.circuit" class="md-skip">
           Skip to content
         </a>
-      
+
     </div>
     <div data-md-component="announce">
-      
+
     </div>
-    
-    
-      
 
-  
+
+
+
+
 
 <header class="md-header md-header--shadow" data-md-component="header">
   <nav class="md-header__inner md-grid" aria-label="Header">
     <a href="../../../../../../../../.." title="OpenSquirrel" class="md-header__button md-logo" aria-label="OpenSquirrel" data-md-component="logo">
-      
-  
+
+
   <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"/></svg>
 
     </a>
     <label class="md-header__button md-icon" for="__drawer">
-      
+
       <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2Z"/></svg>
     </label>
     <div class="md-header__title" data-md-component="header-title">
@@ -97,21 +97,21 @@
         </div>
         <div class="md-header__topic" data-md-component="header-topic">
           <span class="md-ellipsis">
-            
+
               Reference
-            
+
           </span>
         </div>
       </div>
     </div>
-    
-    
+
+
       <script>var media,input,key,value,palette=__md_get("__palette");if(palette&&palette.color){"(prefers-color-scheme)"===palette.color.media&&(media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']"),palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent"));for([key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script>
-    
-    
-    
+
+
+
       <label class="md-header__button md-icon" for="__search">
-        
+
         <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5Z"/></svg>
       </label>
       <div class="md-search" data-md-component="search" role="dialog">
@@ -120,19 +120,19 @@
     <form class="md-search__form" name="search">
       <input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
       <label class="md-search__icon md-icon" for="__search">
-        
+
         <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5Z"/></svg>
-        
+
         <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"/></svg>
       </label>
       <nav class="md-search__options" aria-label="Search">
-        
+
         <button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">
-          
+
           <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41Z"/></svg>
         </button>
       </nav>
-      
+
     </form>
     <div class="md-search__output">
       <div class="md-search__scrollwrap" data-md-scrollfix>
@@ -146,524 +146,524 @@
     </div>
   </div>
 </div>
-    
-    
+
+
   </nav>
-  
+
 </header>
-    
+
     <div class="md-container" data-md-component="container">
-      
-      
-        
-          
-        
-      
+
+
+
+
+
+
       <main class="md-main" data-md-component="main">
         <div class="md-main__inner md-grid">
-          
-            
-              
+
+
+
               <div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
                 <div class="md-sidebar__scrollwrap">
                   <div class="md-sidebar__inner">
-                    
+
 
 
 
 <nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0">
   <label class="md-nav__title" for="__drawer">
     <a href="../../../../../../../../.." title="OpenSquirrel" class="md-nav__button md-logo" aria-label="OpenSquirrel" data-md-component="logo">
-      
-  
+
+
   <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54Z"/></svg>
 
     </a>
     OpenSquirrel
   </label>
-  
+
   <ul class="md-nav__list" data-md-scrollfix>
-    
-      
-      
-  
-  
-  
-  
+
+
+
+
+
+
+
     <li class="md-nav__item">
       <a href="../../../../../../../../.." class="md-nav__link">
-        
-  
+
+
   <span class="md-ellipsis">
     OpenSquirrel
   </span>
-  
+
 
       </a>
     </li>
-  
-
-    
-      
-      
-  
-  
-  
-  
+
+
+
+
+
+
+
+
+
     <li class="md-nav__item">
       <a href="../../../../../../../../../tutorial/" class="md-nav__link">
-        
-  
+
+
   <span class="md-ellipsis">
     Tutorial
   </span>
-  
+
 
       </a>
     </li>
-  
-
-    
-      
-      
-  
-  
-  
-  
+
+
+
+
+
+
+
+
+
     <li class="md-nav__item">
       <a href="../../../../../../../../../how-to-guides/" class="md-nav__link">
-        
-  
+
+
   <span class="md-ellipsis">
     How-To Guides
   </span>
-  
+
 
       </a>
     </li>
-  
-
-    
-      
-      
-  
-  
-  
-  
+
+
+
+
+
+
+
+
+
     <li class="md-nav__item">
       <a href="../../../../../../../../../reference/" class="md-nav__link">
-        
-  
+
+
   <span class="md-ellipsis">
     Reference
   </span>
-  
+
 
       </a>
     </li>
-  
 
-    
+
+
   </ul>
 </nav>
                   </div>
                 </div>
               </div>
-            
-            
-              
+
+
+
               <div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" >
                 <div class="md-sidebar__scrollwrap">
                   <div class="md-sidebar__inner">
-                    
+
 
 <nav class="md-nav md-nav--secondary" aria-label="Table of contents">
-  
-  
-  
-  
+
+
+
+
     <label class="md-nav__title" for="__toc">
       <span class="md-nav__icon md-icon"></span>
       Table of contents
     </label>
     <ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
-      
+
         <li class="md-nav__item">
   <a href="#opensquirrel.circuit" class="md-nav__link">
     <span class="md-ellipsis">
       circuit
     </span>
   </a>
-  
+
 </li>
-      
+
         <li class="md-nav__item">
   <a href="#opensquirrel.circuit.Circuit" class="md-nav__link">
     <span class="md-ellipsis">
       Circuit
     </span>
   </a>
-  
+
     <nav class="md-nav" aria-label="Circuit">
       <ul class="md-nav__list">
-        
+
           <li class="md-nav__item">
   <a href="#opensquirrel.circuit.Circuit.__init__" class="md-nav__link">
     <span class="md-ellipsis">
       __init__
     </span>
   </a>
-  
+
 </li>
-        
+
           <li class="md-nav__item">
   <a href="#opensquirrel.circuit.Circuit.__repr__" class="md-nav__link">
     <span class="md-ellipsis">
       __repr__
     </span>
   </a>
-  
+
 </li>
-        
+
           <li class="md-nav__item">
   <a href="#opensquirrel.circuit.Circuit.decompose" class="md-nav__link">
     <span class="md-ellipsis">
       decompose
     </span>
   </a>
-  
+
 </li>
-        
+
           <li class="md-nav__item">
   <a href="#opensquirrel.circuit.Circuit.from_string" class="md-nav__link">
     <span class="md-ellipsis">
       from_string
     </span>
   </a>
-  
+
 </li>
-        
+
           <li class="md-nav__item">
   <a href="#opensquirrel.circuit.Circuit.merge_single_qubit_gates" class="md-nav__link">
     <span class="md-ellipsis">
       merge_single_qubit_gates
     </span>
   </a>
-  
+
 </li>
-        
+
           <li class="md-nav__item">
   <a href="#opensquirrel.circuit.Circuit.replace" class="md-nav__link">
     <span class="md-ellipsis">
       replace
     </span>
   </a>
-  
+
 </li>
-        
+
           <li class="md-nav__item">
   <a href="#opensquirrel.circuit.Circuit.test_get_circuit_matrix" class="md-nav__link">
     <span class="md-ellipsis">
       test_get_circuit_matrix
     </span>
   </a>
-  
+
 </li>
-        
+
       </ul>
     </nav>
-  
+
 </li>
-      
+
         <li class="md-nav__item">
   <a href="#opensquirrel.circuit_builder" class="md-nav__link">
     <span class="md-ellipsis">
       circuit_builder
     </span>
   </a>
-  
+
 </li>
-      
+
         <li class="md-nav__item">
   <a href="#opensquirrel.circuit_builder.CircuitBuilder" class="md-nav__link">
     <span class="md-ellipsis">
       CircuitBuilder
     </span>
   </a>
-  
+
 </li>
-      
+
         <li class="md-nav__item">
   <a href="#opensquirrel.circuit_matrix_calculator" class="md-nav__link">
     <span class="md-ellipsis">
       circuit_matrix_calculator
     </span>
   </a>
-  
+
 </li>
-      
+
         <li class="md-nav__item">
   <a href="#opensquirrel.circuit_matrix_calculator.get_circuit_matrix" class="md-nav__link">
     <span class="md-ellipsis">
       get_circuit_matrix
     </span>
   </a>
-  
+
 </li>
-      
+
         <li class="md-nav__item">
   <a href="#opensquirrel.common" class="md-nav__link">
     <span class="md-ellipsis">
       common
     </span>
   </a>
-  
+
 </li>
-      
+
         <li class="md-nav__item">
   <a href="#opensquirrel.decomposer.cnot_decomposer" class="md-nav__link">
     <span class="md-ellipsis">
       cnot_decomposer
     </span>
   </a>
-  
+
 </li>
-      
+
         <li class="md-nav__item">
   <a href="#opensquirrel.decomposer.cnot_decomposer.CNOTDecomposer" class="md-nav__link">
     <span class="md-ellipsis">
       CNOTDecomposer
     </span>
   </a>
-  
+
 </li>
-      
+
         <li class="md-nav__item">
   <a href="#opensquirrel.decomposer.general_decomposer" class="md-nav__link">
     <span class="md-ellipsis">
       general_decomposer
     </span>
   </a>
-  
+
 </li>
-      
+
         <li class="md-nav__item">
   <a href="#opensquirrel.decomposer.general_decomposer.decompose" class="md-nav__link">
     <span class="md-ellipsis">
       decompose
     </span>
   </a>
-  
+
 </li>
-      
+
         <li class="md-nav__item">
   <a href="#opensquirrel.decomposer.general_decomposer.replace" class="md-nav__link">
     <span class="md-ellipsis">
       replace
     </span>
   </a>
-  
+
 </li>
-      
+
         <li class="md-nav__item">
   <a href="#opensquirrel.decomposer.mckay_decomposer" class="md-nav__link">
     <span class="md-ellipsis">
       mckay_decomposer
     </span>
   </a>
-  
+
 </li>
-      
+
         <li class="md-nav__item">
   <a href="#opensquirrel.decomposer.mckay_decomposer.McKayDecomposer" class="md-nav__link">
     <span class="md-ellipsis">
       McKayDecomposer
     </span>
   </a>
-  
+
     <nav class="md-nav" aria-label="McKayDecomposer">
       <ul class="md-nav__list">
-        
+
           <li class="md-nav__item">
   <a href="#opensquirrel.decomposer.mckay_decomposer.McKayDecomposer.decompose" class="md-nav__link">
     <span class="md-ellipsis">
       decompose
     </span>
   </a>
-  
+
 </li>
-        
+
       </ul>
     </nav>
-  
+
 </li>
-      
+
         <li class="md-nav__item">
   <a href="#opensquirrel.decomposer.zyz_decomposer" class="md-nav__link">
     <span class="md-ellipsis">
       zyz_decomposer
     </span>
   </a>
-  
+
 </li>
-      
+
         <li class="md-nav__item">
   <a href="#opensquirrel.decomposer.zyz_decomposer.get_zyz_decomposition_angles" class="md-nav__link">
     <span class="md-ellipsis">
       get_zyz_decomposition_angles
     </span>
   </a>
-  
+
 </li>
-      
+
         <li class="md-nav__item">
   <a href="#opensquirrel.default_gates" class="md-nav__link">
     <span class="md-ellipsis">
       default_gates
     </span>
   </a>
-  
+
 </li>
-      
+
         <li class="md-nav__item">
   <a href="#opensquirrel.default_measurements" class="md-nav__link">
     <span class="md-ellipsis">
       default_measurements
     </span>
   </a>
-  
+
 </li>
-      
+
         <li class="md-nav__item">
   <a href="#opensquirrel.exporter.export_format" class="md-nav__link">
     <span class="md-ellipsis">
       export_format
     </span>
   </a>
-  
+
 </li>
-      
+
         <li class="md-nav__item">
   <a href="#opensquirrel.exporter.quantify_scheduler_exporter" class="md-nav__link">
     <span class="md-ellipsis">
       quantify_scheduler_exporter
     </span>
   </a>
-  
+
 </li>
-      
+
         <li class="md-nav__item">
   <a href="#opensquirrel.exporter.writer" class="md-nav__link">
     <span class="md-ellipsis">
       writer
     </span>
   </a>
-  
+
 </li>
-      
+
         <li class="md-nav__item">
   <a href="#opensquirrel.instruction_library" class="md-nav__link">
     <span class="md-ellipsis">
       instruction_library
     </span>
   </a>
-  
+
 </li>
-      
+
         <li class="md-nav__item">
   <a href="#opensquirrel.merger.general_merger" class="md-nav__link">
     <span class="md-ellipsis">
       general_merger
     </span>
   </a>
-  
+
 </li>
-      
+
         <li class="md-nav__item">
   <a href="#opensquirrel.merger.general_merger.compose_bloch_sphere_rotations" class="md-nav__link">
     <span class="md-ellipsis">
       compose_bloch_sphere_rotations
     </span>
   </a>
-  
+
 </li>
-      
+
         <li class="md-nav__item">
   <a href="#opensquirrel.parser.libqasm.libqasm_ir_creator" class="md-nav__link">
     <span class="md-ellipsis">
       libqasm_ir_creator
     </span>
   </a>
-  
+
 </li>
-      
+
         <li class="md-nav__item">
-  <a href="#opensquirrel.squirrel_ir" class="md-nav__link">
+  <a href="#opensquirrel.ir" class="md-nav__link">
     <span class="md-ellipsis">
-      squirrel_ir
+      ir
     </span>
   </a>
-  
+
 </li>
-      
+
         <li class="md-nav__item">
   <a href="#opensquirrel.utils.identity_filter" class="md-nav__link">
     <span class="md-ellipsis">
       identity_filter
     </span>
   </a>
-  
+
 </li>
-      
+
         <li class="md-nav__item">
   <a href="#opensquirrel.utils.matrix_expander" class="md-nav__link">
     <span class="md-ellipsis">
       matrix_expander
     </span>
   </a>
-  
+
 </li>
-      
+
         <li class="md-nav__item">
   <a href="#opensquirrel.utils.matrix_expander.expand_ket" class="md-nav__link">
     <span class="md-ellipsis">
       expand_ket
     </span>
   </a>
-  
+
 </li>
-      
+
         <li class="md-nav__item">
   <a href="#opensquirrel.utils.matrix_expander.get_matrix" class="md-nav__link">
     <span class="md-ellipsis">
       get_matrix
     </span>
   </a>
-  
+
 </li>
-      
+
         <li class="md-nav__item">
   <a href="#opensquirrel.utils.matrix_expander.get_reduced_ket" class="md-nav__link">
     <span class="md-ellipsis">
       get_reduced_ket
     </span>
   </a>
-  
+
 </li>
-      
+
     </ul>
-  
+
 </nav>
                   </div>
                 </div>
               </div>
-            
-          
-          
+
+
+
             <div class="md-content" data-md-component="content">
               <article class="md-content__inner md-typeset">
-                
-                  
+
+
 
 
   <h1>Reference</h1>
@@ -679,7 +679,7 @@ <h1>Reference</h1>
 <a id="opensquirrel.circuit"></a>
   <div class="doc doc-contents first">
 
-  
+
 
   <div class="doc doc-children">
 
@@ -703,7 +703,7 @@ <h2 id="opensquirrel.circuit.Circuit" class="doc doc-heading">
 
   <div class="doc doc-contents ">
 
-  
+
       <p>The Circuit class is the only interface to access OpenSquirrel's features.</p>
 
 
@@ -861,10 +861,10 @@ <h2 id="opensquirrel.circuit.Circuit" class="doc doc-heading">
 <a id="__codelineno-0-39" name="__codelineno-0-39"></a>
 <a id="__codelineno-0-40" name="__codelineno-0-40"></a><span class="sd">    &quot;&quot;&quot;</span>
 <a id="__codelineno-0-41" name="__codelineno-0-41"></a>
-<a id="__codelineno-0-42" name="__codelineno-0-42"></a>    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">squirrel_ir</span><span class="p">:</span> <span class="n">SquirrelIR</span><span class="p">):</span>
-<a id="__codelineno-0-43" name="__codelineno-0-43"></a><span class="w">        </span><span class="sd">&quot;&quot;&quot;Create a circuit object from a SquirrelIR object.&quot;&quot;&quot;</span>
+<a id="__codelineno-0-42" name="__codelineno-0-42"></a>    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">ir</span><span class="p">:</span> <span class="n">IR</span><span class="p">):</span>
+<a id="__codelineno-0-43" name="__codelineno-0-43"></a><span class="w">        </span><span class="sd">&quot;&quot;&quot;Create a circuit object from a IR object.&quot;&quot;&quot;</span>
 <a id="__codelineno-0-44" name="__codelineno-0-44"></a>
-<a id="__codelineno-0-45" name="__codelineno-0-45"></a>        <span class="bp">self</span><span class="o">.</span><span class="n">squirrel_ir</span> <span class="o">=</span> <span class="n">squirrel_ir</span>
+<a id="__codelineno-0-45" name="__codelineno-0-45"></a>        <span class="bp">self</span><span class="o">.</span><span class="n">ir</span> <span class="o">=</span> <span class="n">ir</span>
 <a id="__codelineno-0-46" name="__codelineno-0-46"></a>
 <a id="__codelineno-0-47" name="__codelineno-0-47"></a>    <span class="nd">@classmethod</span>
 <a id="__codelineno-0-48" name="__codelineno-0-48"></a>    <span class="k">def</span> <span class="nf">from_string</span><span class="p">(</span>
@@ -895,15 +895,15 @@ <h2 id="opensquirrel.circuit.Circuit" class="doc doc-heading">
 <a id="__codelineno-0-73" name="__codelineno-0-73"></a>            <span class="n">gate_aliases</span><span class="o">=</span><span class="n">gate_aliases</span><span class="p">,</span>
 <a id="__codelineno-0-74" name="__codelineno-0-74"></a>            <span class="n">measurement_set</span><span class="o">=</span><span class="n">measurement_set</span><span class="p">,</span>
 <a id="__codelineno-0-75" name="__codelineno-0-75"></a>        <span class="p">)</span>
-<a id="__codelineno-0-76" name="__codelineno-0-76"></a>        <span class="k">return</span> <span class="n">Circuit</span><span class="p">(</span><span class="n">libqasm_ir_creator</span><span class="o">.</span><span class="n">squirrel_ir_from_string</span><span class="p">(</span><span class="n">cqasm3_string</span><span class="p">))</span>
+<a id="__codelineno-0-76" name="__codelineno-0-76"></a>        <span class="k">return</span> <span class="n">Circuit</span><span class="p">(</span><span class="n">libqasm_ir_creator</span><span class="o">.</span><span class="n">ir_from_string</span><span class="p">(</span><span class="n">cqasm3_string</span><span class="p">))</span>
 <a id="__codelineno-0-77" name="__codelineno-0-77"></a>
 <a id="__codelineno-0-78" name="__codelineno-0-78"></a>    <span class="nd">@property</span>
 <a id="__codelineno-0-79" name="__codelineno-0-79"></a>    <span class="k">def</span> <span class="nf">number_of_qubits</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
-<a id="__codelineno-0-80" name="__codelineno-0-80"></a>        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">squirrel_ir</span><span class="o">.</span><span class="n">number_of_qubits</span>
+<a id="__codelineno-0-80" name="__codelineno-0-80"></a>        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">ir</span><span class="o">.</span><span class="n">number_of_qubits</span>
 <a id="__codelineno-0-81" name="__codelineno-0-81"></a>
 <a id="__codelineno-0-82" name="__codelineno-0-82"></a>    <span class="nd">@property</span>
 <a id="__codelineno-0-83" name="__codelineno-0-83"></a>    <span class="k">def</span> <span class="nf">qubit_register_name</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
-<a id="__codelineno-0-84" name="__codelineno-0-84"></a>        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">squirrel_ir</span><span class="o">.</span><span class="n">qubit_register_name</span>
+<a id="__codelineno-0-84" name="__codelineno-0-84"></a>        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">ir</span><span class="o">.</span><span class="n">qubit_register_name</span>
 <a id="__codelineno-0-85" name="__codelineno-0-85"></a>
 <a id="__codelineno-0-86" name="__codelineno-0-86"></a>    <span class="k">def</span> <span class="nf">merge_single_qubit_gates</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
 <a id="__codelineno-0-87" name="__codelineno-0-87"></a><span class="w">        </span><span class="sd">&quot;&quot;&quot;Merge all consecutive 1-qubit gates in the circuit.</span>
@@ -911,11 +911,11 @@ <h2 id="opensquirrel.circuit.Circuit" class="doc doc-heading">
 <a id="__codelineno-0-89" name="__codelineno-0-89"></a><span class="sd">        Gates obtained from merging other gates become anonymous gates.</span>
 <a id="__codelineno-0-90" name="__codelineno-0-90"></a>
 <a id="__codelineno-0-91" name="__codelineno-0-91"></a><span class="sd">        &quot;&quot;&quot;</span>
-<a id="__codelineno-0-92" name="__codelineno-0-92"></a>        <span class="n">merger</span><span class="o">.</span><span class="n">merge_single_qubit_gates</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">squirrel_ir</span><span class="p">)</span>
+<a id="__codelineno-0-92" name="__codelineno-0-92"></a>        <span class="n">merger</span><span class="o">.</span><span class="n">merge_single_qubit_gates</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">ir</span><span class="p">)</span>
 <a id="__codelineno-0-93" name="__codelineno-0-93"></a>
 <a id="__codelineno-0-94" name="__codelineno-0-94"></a>    <span class="k">def</span> <span class="nf">decompose</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">decomposer</span><span class="p">:</span> <span class="n">Decomposer</span><span class="p">):</span>
 <a id="__codelineno-0-95" name="__codelineno-0-95"></a><span class="w">        </span><span class="sd">&quot;&quot;&quot;Generic decomposition pass. It applies the given decomposer function to every gate in the circuit.&quot;&quot;&quot;</span>
-<a id="__codelineno-0-96" name="__codelineno-0-96"></a>        <span class="n">replacer</span><span class="o">.</span><span class="n">decompose</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">squirrel_ir</span><span class="p">,</span> <span class="n">decomposer</span><span class="p">)</span>
+<a id="__codelineno-0-96" name="__codelineno-0-96"></a>        <span class="n">replacer</span><span class="o">.</span><span class="n">decompose</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">ir</span><span class="p">,</span> <span class="n">decomposer</span><span class="p">)</span>
 <a id="__codelineno-0-97" name="__codelineno-0-97"></a>
 <a id="__codelineno-0-98" name="__codelineno-0-98"></a>    <span class="k">def</span> <span class="nf">replace</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">gate_generator</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[</span><span class="o">...</span><span class="p">,</span> <span class="n">Gate</span><span class="p">],</span> <span class="n">f</span><span class="p">):</span>
 <a id="__codelineno-0-99" name="__codelineno-0-99"></a><span class="w">        </span><span class="sd">&quot;&quot;&quot;Manually replace occurrences of a given gate with a list of gates.</span>
@@ -923,7 +923,7 @@ <h2 id="opensquirrel.circuit.Circuit" class="doc doc-heading">
 <a id="__codelineno-0-101" name="__codelineno-0-101"></a><span class="sd">        and returns the decomposition as a list of gates.</span>
 <a id="__codelineno-0-102" name="__codelineno-0-102"></a>
 <a id="__codelineno-0-103" name="__codelineno-0-103"></a><span class="sd">        &quot;&quot;&quot;</span>
-<a id="__codelineno-0-104" name="__codelineno-0-104"></a>        <span class="n">replacer</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">squirrel_ir</span><span class="p">,</span> <span class="n">gate_generator</span><span class="p">,</span> <span class="n">f</span><span class="p">)</span>
+<a id="__codelineno-0-104" name="__codelineno-0-104"></a>        <span class="n">replacer</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">ir</span><span class="p">,</span> <span class="n">gate_generator</span><span class="p">,</span> <span class="n">f</span><span class="p">)</span>
 <a id="__codelineno-0-105" name="__codelineno-0-105"></a>
 <a id="__codelineno-0-106" name="__codelineno-0-106"></a>    <span class="k">def</span> <span class="nf">test_get_circuit_matrix</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">np</span><span class="o">.</span><span class="n">ndarray</span><span class="p">:</span>
 <a id="__codelineno-0-107" name="__codelineno-0-107"></a><span class="w">        </span><span class="sd">&quot;&quot;&quot;Get the (large) unitary matrix corresponding to the circuit.</span>
@@ -933,20 +933,20 @@ <h2 id="opensquirrel.circuit.Circuit" class="doc doc-heading">
 <a id="__codelineno-0-111" name="__codelineno-0-111"></a><span class="sd">        * result is stored as a numpy array of complex numbers</span>
 <a id="__codelineno-0-112" name="__codelineno-0-112"></a>
 <a id="__codelineno-0-113" name="__codelineno-0-113"></a><span class="sd">        &quot;&quot;&quot;</span>
-<a id="__codelineno-0-114" name="__codelineno-0-114"></a>        <span class="k">return</span> <span class="n">circuit_matrix_calculator</span><span class="o">.</span><span class="n">get_circuit_matrix</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">squirrel_ir</span><span class="p">)</span>
+<a id="__codelineno-0-114" name="__codelineno-0-114"></a>        <span class="k">return</span> <span class="n">circuit_matrix_calculator</span><span class="o">.</span><span class="n">get_circuit_matrix</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">ir</span><span class="p">)</span>
 <a id="__codelineno-0-115" name="__codelineno-0-115"></a>
 <a id="__codelineno-0-116" name="__codelineno-0-116"></a>    <span class="k">def</span> <span class="fm">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
 <a id="__codelineno-0-117" name="__codelineno-0-117"></a><span class="w">        </span><span class="sd">&quot;&quot;&quot;Write the circuit to a cQasm3 string.&quot;&quot;&quot;</span>
-<a id="__codelineno-0-118" name="__codelineno-0-118"></a>        <span class="k">return</span> <span class="n">writer</span><span class="o">.</span><span class="n">squirrel_ir_to_string</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">squirrel_ir</span><span class="p">)</span>
+<a id="__codelineno-0-118" name="__codelineno-0-118"></a>        <span class="k">return</span> <span class="n">writer</span><span class="o">.</span><span class="n">ir_to_string</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">ir</span><span class="p">)</span>
 <a id="__codelineno-0-119" name="__codelineno-0-119"></a>
 <a id="__codelineno-0-120" name="__codelineno-0-120"></a>    <span class="k">def</span> <span class="nf">export</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">fmt</span><span class="p">:</span> <span class="n">ExportFormat</span> <span class="o">=</span> <span class="kc">None</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kc">None</span><span class="p">:</span>
 <a id="__codelineno-0-121" name="__codelineno-0-121"></a>        <span class="k">if</span> <span class="n">fmt</span> <span class="o">==</span> <span class="n">ExportFormat</span><span class="o">.</span><span class="n">QUANTIFY_SCHEDULER</span><span class="p">:</span>
-<a id="__codelineno-0-122" name="__codelineno-0-122"></a>            <span class="k">return</span> <span class="n">quantify_scheduler_exporter</span><span class="o">.</span><span class="n">export</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">squirrel_ir</span><span class="p">)</span>
+<a id="__codelineno-0-122" name="__codelineno-0-122"></a>            <span class="k">return</span> <span class="n">quantify_scheduler_exporter</span><span class="o">.</span><span class="n">export</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">ir</span><span class="p">)</span>
 <a id="__codelineno-0-123" name="__codelineno-0-123"></a>        <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;Unknown exporter format&quot;</span><span class="p">)</span>
 </code></pre></div></td></tr></table></div>
             </details>
 
-  
+
 
   <div class="doc doc-children">
 
@@ -964,24 +964,24 @@ <h2 id="opensquirrel.circuit.Circuit" class="doc doc-heading">
 
 
 <h3 id="opensquirrel.circuit.Circuit.__init__" class="doc doc-heading">
-          <code class="highlight language-python"><span class="fm">__init__</span><span class="p">(</span><span class="n">squirrel_ir</span><span class="p">)</span></code>
+          <code class="highlight language-python"><span class="fm">__init__</span><span class="p">(</span><span class="n">ir</span><span class="p">)</span></code>
 
 </h3>
 
 
   <div class="doc doc-contents ">
-  
-      <p>Create a circuit object from a SquirrelIR object.</p>
+
+      <p>Create a circuit object from a IR object.</p>
 
           <details class="quote">
             <summary>Source code in <code>opensquirrel\circuit.py</code></summary>
             <div class="highlight"><table class="highlighttable"><tr><td class="linenos"><div class="linenodiv"><pre><span></span><span class="normal"><a href="#__codelineno-0-42">42</a></span>
 <span class="normal"><a href="#__codelineno-0-43">43</a></span>
 <span class="normal"><a href="#__codelineno-0-44">44</a></span>
-<span class="normal"><a href="#__codelineno-0-45">45</a></span></pre></div></td><td class="code"><div><pre><span></span><code><a id="__codelineno-0-42" name="__codelineno-0-42"></a><span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">squirrel_ir</span><span class="p">:</span> <span class="n">SquirrelIR</span><span class="p">):</span>
-<a id="__codelineno-0-43" name="__codelineno-0-43"></a><span class="w">    </span><span class="sd">&quot;&quot;&quot;Create a circuit object from a SquirrelIR object.&quot;&quot;&quot;</span>
+<span class="normal"><a href="#__codelineno-0-45">45</a></span></pre></div></td><td class="code"><div><pre><span></span><code><a id="__codelineno-0-42" name="__codelineno-0-42"></a><span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">ir</span><span class="p">:</span> <span class="n">IR</span><span class="p">):</span>
+<a id="__codelineno-0-43" name="__codelineno-0-43"></a><span class="w">    </span><span class="sd">&quot;&quot;&quot;Create a circuit object from a IR object.&quot;&quot;&quot;</span>
 <a id="__codelineno-0-44" name="__codelineno-0-44"></a>
-<a id="__codelineno-0-45" name="__codelineno-0-45"></a>    <span class="bp">self</span><span class="o">.</span><span class="n">squirrel_ir</span> <span class="o">=</span> <span class="n">squirrel_ir</span>
+<a id="__codelineno-0-45" name="__codelineno-0-45"></a>    <span class="bp">self</span><span class="o">.</span><span class="n">ir</span> <span class="o">=</span> <span class="n">ir</span>
 </code></pre></div></td></tr></table></div>
           </details>
   </div>
@@ -1000,7 +1000,7 @@ <h3 id="opensquirrel.circuit.Circuit.__repr__" class="doc doc-heading">
 
 
   <div class="doc doc-contents ">
-  
+
       <p>Write the circuit to a cQasm3 string.</p>
 
           <details class="quote">
@@ -1009,7 +1009,7 @@ <h3 id="opensquirrel.circuit.Circuit.__repr__" class="doc doc-heading">
 <span class="normal"><a href="#__codelineno-0-117">117</a></span>
 <span class="normal"><a href="#__codelineno-0-118">118</a></span></pre></div></td><td class="code"><div><pre><span></span><code><a id="__codelineno-0-116" name="__codelineno-0-116"></a><span class="k">def</span> <span class="fm">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
 <a id="__codelineno-0-117" name="__codelineno-0-117"></a><span class="w">    </span><span class="sd">&quot;&quot;&quot;Write the circuit to a cQasm3 string.&quot;&quot;&quot;</span>
-<a id="__codelineno-0-118" name="__codelineno-0-118"></a>    <span class="k">return</span> <span class="n">writer</span><span class="o">.</span><span class="n">squirrel_ir_to_string</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">squirrel_ir</span><span class="p">)</span>
+<a id="__codelineno-0-118" name="__codelineno-0-118"></a>    <span class="k">return</span> <span class="n">writer</span><span class="o">.</span><span class="n">ir_to_string</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">ir</span><span class="p">)</span>
 </code></pre></div></td></tr></table></div>
           </details>
   </div>
@@ -1028,7 +1028,7 @@ <h3 id="opensquirrel.circuit.Circuit.decompose" class="doc doc-heading">
 
 
   <div class="doc doc-contents ">
-  
+
       <p>Generic decomposition pass. It applies the given decomposer function to every gate in the circuit.</p>
 
           <details class="quote">
@@ -1037,7 +1037,7 @@ <h3 id="opensquirrel.circuit.Circuit.decompose" class="doc doc-heading">
 <span class="normal"><a href="#__codelineno-0-95">95</a></span>
 <span class="normal"><a href="#__codelineno-0-96">96</a></span></pre></div></td><td class="code"><div><pre><span></span><code><a id="__codelineno-0-94" name="__codelineno-0-94"></a><span class="k">def</span> <span class="nf">decompose</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">decomposer</span><span class="p">:</span> <span class="n">Decomposer</span><span class="p">):</span>
 <a id="__codelineno-0-95" name="__codelineno-0-95"></a><span class="w">    </span><span class="sd">&quot;&quot;&quot;Generic decomposition pass. It applies the given decomposer function to every gate in the circuit.&quot;&quot;&quot;</span>
-<a id="__codelineno-0-96" name="__codelineno-0-96"></a>    <span class="n">replacer</span><span class="o">.</span><span class="n">decompose</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">squirrel_ir</span><span class="p">,</span> <span class="n">decomposer</span><span class="p">)</span>
+<a id="__codelineno-0-96" name="__codelineno-0-96"></a>    <span class="n">replacer</span><span class="o">.</span><span class="n">decompose</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">ir</span><span class="p">,</span> <span class="n">decomposer</span><span class="p">)</span>
 </code></pre></div></td></tr></table></div>
           </details>
   </div>
@@ -1051,7 +1051,7 @@ <h3 id="opensquirrel.circuit.Circuit.decompose" class="doc doc-heading">
 
 <h3 id="opensquirrel.circuit.Circuit.from_string" class="doc doc-heading">
           <code class="highlight language-python"><span class="n">from_string</span><span class="p">(</span><span class="n">cqasm3_string</span><span class="p">,</span> <span class="n">gate_set</span><span class="o">=</span><span class="n">default_gate_set</span><span class="p">,</span> <span class="n">gate_aliases</span><span class="o">=</span><span class="n">default_gate_aliases</span><span class="p">,</span> <span class="n">measurement_set</span><span class="o">=</span><span class="n">default_measurement_set</span><span class="p">)</span></code>
-  
+
   <span class="doc doc-labels">
       <small class="doc doc-label doc-label-classmethod"><code>classmethod</code></small>
   </span>
@@ -1060,7 +1060,7 @@ <h3 id="opensquirrel.circuit.Circuit.from_string" class="doc doc-heading">
 
 
   <div class="doc doc-contents ">
-  
+
       <p>Create a circuit object from a cQasm3 string. All the gates in the circuit need to be defined in
 the <code>gates</code> argument.</p>
 <ul>
@@ -1100,7 +1100,7 @@ <h3 id="opensquirrel.circuit.Circuit.from_string" class="doc doc-heading">
         <tr>
           <td><code>gate_set</code></td>
           <td>
-                <code>[<span title="typing.Callable">Callable</span>[..., <span title="opensquirrel.squirrel_ir.Gate">Gate</span>]]</code>
+                <code>[<span title="typing.Callable">Callable</span>[..., <span title="opensquirrel.ir.Gate">Gate</span>]]</code>
           </td>
           <td>
             <div class="doc-md-description">
@@ -1114,7 +1114,7 @@ <h3 id="opensquirrel.circuit.Circuit.from_string" class="doc doc-heading">
         <tr>
           <td><code>gate_aliases</code></td>
           <td>
-                <code><span title="typing.Dict">Dict</span>[str, <span title="typing.Callable">Callable</span>[..., <span title="opensquirrel.squirrel_ir.Gate">Gate</span>]]</code>
+                <code><span title="typing.Dict">Dict</span>[str, <span title="typing.Callable">Callable</span>[..., <span title="opensquirrel.ir.Gate">Gate</span>]]</code>
           </td>
           <td>
             <div class="doc-md-description">
@@ -1128,7 +1128,7 @@ <h3 id="opensquirrel.circuit.Circuit.from_string" class="doc doc-heading">
         <tr>
           <td><code>measurement_set</code></td>
           <td>
-                <code>[<span title="typing.Callable">Callable</span>[..., <span title="opensquirrel.squirrel_ir.Measure">Measure</span>]]</code>
+                <code>[<span title="typing.Callable">Callable</span>[..., <span title="opensquirrel.ir.Measure">Measure</span>]]</code>
           </td>
           <td>
             <div class="doc-md-description">
@@ -1202,7 +1202,7 @@ <h3 id="opensquirrel.circuit.Circuit.from_string" class="doc doc-heading">
 <a id="__codelineno-0-73" name="__codelineno-0-73"></a>        <span class="n">gate_aliases</span><span class="o">=</span><span class="n">gate_aliases</span><span class="p">,</span>
 <a id="__codelineno-0-74" name="__codelineno-0-74"></a>        <span class="n">measurement_set</span><span class="o">=</span><span class="n">measurement_set</span><span class="p">,</span>
 <a id="__codelineno-0-75" name="__codelineno-0-75"></a>    <span class="p">)</span>
-<a id="__codelineno-0-76" name="__codelineno-0-76"></a>    <span class="k">return</span> <span class="n">Circuit</span><span class="p">(</span><span class="n">libqasm_ir_creator</span><span class="o">.</span><span class="n">squirrel_ir_from_string</span><span class="p">(</span><span class="n">cqasm3_string</span><span class="p">))</span>
+<a id="__codelineno-0-76" name="__codelineno-0-76"></a>    <span class="k">return</span> <span class="n">Circuit</span><span class="p">(</span><span class="n">libqasm_ir_creator</span><span class="o">.</span><span class="n">ir_from_string</span><span class="p">(</span><span class="n">cqasm3_string</span><span class="p">))</span>
 </code></pre></div></td></tr></table></div>
           </details>
   </div>
@@ -1221,7 +1221,7 @@ <h3 id="opensquirrel.circuit.Circuit.merge_single_qubit_gates" class="doc doc-he
 
 
   <div class="doc doc-contents ">
-  
+
       <p>Merge all consecutive 1-qubit gates in the circuit.</p>
 <p>Gates obtained from merging other gates become anonymous gates.</p>
 
@@ -1239,7 +1239,7 @@ <h3 id="opensquirrel.circuit.Circuit.merge_single_qubit_gates" class="doc doc-he
 <a id="__codelineno-0-89" name="__codelineno-0-89"></a><span class="sd">    Gates obtained from merging other gates become anonymous gates.</span>
 <a id="__codelineno-0-90" name="__codelineno-0-90"></a>
 <a id="__codelineno-0-91" name="__codelineno-0-91"></a><span class="sd">    &quot;&quot;&quot;</span>
-<a id="__codelineno-0-92" name="__codelineno-0-92"></a>    <span class="n">merger</span><span class="o">.</span><span class="n">merge_single_qubit_gates</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">squirrel_ir</span><span class="p">)</span>
+<a id="__codelineno-0-92" name="__codelineno-0-92"></a>    <span class="n">merger</span><span class="o">.</span><span class="n">merge_single_qubit_gates</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">ir</span><span class="p">)</span>
 </code></pre></div></td></tr></table></div>
           </details>
   </div>
@@ -1258,7 +1258,7 @@ <h3 id="opensquirrel.circuit.Circuit.replace" class="doc doc-heading">
 
 
   <div class="doc doc-contents ">
-  
+
       <p>Manually replace occurrences of a given gate with a list of gates.
 <code>f</code> is a callable that takes the arguments of the gate that is to be replaced
 and returns the decomposition as a list of gates.</p>
@@ -1277,7 +1277,7 @@ <h3 id="opensquirrel.circuit.Circuit.replace" class="doc doc-heading">
 <a id="__codelineno-0-101" name="__codelineno-0-101"></a><span class="sd">    and returns the decomposition as a list of gates.</span>
 <a id="__codelineno-0-102" name="__codelineno-0-102"></a>
 <a id="__codelineno-0-103" name="__codelineno-0-103"></a><span class="sd">    &quot;&quot;&quot;</span>
-<a id="__codelineno-0-104" name="__codelineno-0-104"></a>    <span class="n">replacer</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">squirrel_ir</span><span class="p">,</span> <span class="n">gate_generator</span><span class="p">,</span> <span class="n">f</span><span class="p">)</span>
+<a id="__codelineno-0-104" name="__codelineno-0-104"></a>    <span class="n">replacer</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">ir</span><span class="p">,</span> <span class="n">gate_generator</span><span class="p">,</span> <span class="n">f</span><span class="p">)</span>
 </code></pre></div></td></tr></table></div>
           </details>
   </div>
@@ -1296,7 +1296,7 @@ <h3 id="opensquirrel.circuit.Circuit.test_get_circuit_matrix" class="doc doc-hea
 
 
   <div class="doc doc-contents ">
-  
+
       <p>Get the (large) unitary matrix corresponding to the circuit.</p>
 <ul>
 <li>this matrix has 4**n elements, where n is the number of qubits</li>
@@ -1322,7 +1322,7 @@ <h3 id="opensquirrel.circuit.Circuit.test_get_circuit_matrix" class="doc doc-hea
 <a id="__codelineno-0-111" name="__codelineno-0-111"></a><span class="sd">    * result is stored as a numpy array of complex numbers</span>
 <a id="__codelineno-0-112" name="__codelineno-0-112"></a>
 <a id="__codelineno-0-113" name="__codelineno-0-113"></a><span class="sd">    &quot;&quot;&quot;</span>
-<a id="__codelineno-0-114" name="__codelineno-0-114"></a>    <span class="k">return</span> <span class="n">circuit_matrix_calculator</span><span class="o">.</span><span class="n">get_circuit_matrix</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">squirrel_ir</span><span class="p">)</span>
+<a id="__codelineno-0-114" name="__codelineno-0-114"></a>    <span class="k">return</span> <span class="n">circuit_matrix_calculator</span><span class="o">.</span><span class="n">get_circuit_matrix</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">ir</span><span class="p">)</span>
 </code></pre></div></td></tr></table></div>
           </details>
   </div>
@@ -1354,7 +1354,7 @@ <h3 id="opensquirrel.circuit.Circuit.test_get_circuit_matrix" class="doc doc-hea
 <a id="opensquirrel.circuit_builder"></a>
   <div class="doc doc-contents first">
 
-  
+
 
   <div class="doc doc-children">
 
@@ -1380,7 +1380,7 @@ <h2 id="opensquirrel.circuit_builder.CircuitBuilder" class="doc doc-heading">
           <p class="doc doc-class-bases">
             Bases: <code><span title="opensquirrel.instruction_library.GateLibrary">GateLibrary</span></code></p>
 
-  
+
       <p>A class using the builder pattern to make construction of circuits easy from Python.
 Adds corresponding gate when a method is called. Checks gates are known and called with the right arguments.
 Mainly here to allow for Qiskit-style circuit construction:</p>
@@ -1485,13 +1485,13 @@ <h2 id="opensquirrel.circuit_builder.CircuitBuilder" class="doc doc-heading">
 <a id="__codelineno-0-35" name="__codelineno-0-35"></a>        <span class="n">gate_aliases</span><span class="p">:</span> <span class="n">Dict</span><span class="p">[</span><span class="nb">str</span><span class="p">,</span> <span class="n">Callable</span><span class="p">[</span><span class="o">...</span><span class="p">,</span> <span class="n">Gate</span><span class="p">]]</span> <span class="o">=</span> <span class="n">default_gate_aliases</span><span class="p">,</span>
 <a id="__codelineno-0-36" name="__codelineno-0-36"></a>    <span class="p">):</span>
 <a id="__codelineno-0-37" name="__codelineno-0-37"></a>        <span class="n">GateLibrary</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">gate_set</span><span class="p">,</span> <span class="n">gate_aliases</span><span class="p">)</span>
-<a id="__codelineno-0-38" name="__codelineno-0-38"></a>        <span class="bp">self</span><span class="o">.</span><span class="n">squirrel_ir</span> <span class="o">=</span> <span class="n">SquirrelIR</span><span class="p">(</span>
+<a id="__codelineno-0-38" name="__codelineno-0-38"></a>        <span class="bp">self</span><span class="o">.</span><span class="n">ir</span> <span class="o">=</span> <span class="n">IR</span><span class="p">(</span>
 <a id="__codelineno-0-39" name="__codelineno-0-39"></a>            <span class="n">number_of_qubits</span><span class="o">=</span><span class="n">number_of_qubits</span><span class="p">,</span> <span class="n">qubit_register_name</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">_default_qubit_register_name</span>
 <a id="__codelineno-0-40" name="__codelineno-0-40"></a>        <span class="p">)</span>
 <a id="__codelineno-0-41" name="__codelineno-0-41"></a>
 <a id="__codelineno-0-42" name="__codelineno-0-42"></a>    <span class="k">def</span> <span class="fm">__getattr__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">attr</span><span class="p">):</span>
 <a id="__codelineno-0-43" name="__codelineno-0-43"></a>        <span class="k">def</span> <span class="nf">add_comment</span><span class="p">(</span><span class="n">comment_string</span><span class="p">:</span> <span class="nb">str</span><span class="p">):</span>
-<a id="__codelineno-0-44" name="__codelineno-0-44"></a>            <span class="bp">self</span><span class="o">.</span><span class="n">squirrel_ir</span><span class="o">.</span><span class="n">add_comment</span><span class="p">(</span><span class="n">Comment</span><span class="p">(</span><span class="n">comment_string</span><span class="p">))</span>
+<a id="__codelineno-0-44" name="__codelineno-0-44"></a>            <span class="bp">self</span><span class="o">.</span><span class="n">ir</span><span class="o">.</span><span class="n">add_comment</span><span class="p">(</span><span class="n">Comment</span><span class="p">(</span><span class="n">comment_string</span><span class="p">))</span>
 <a id="__codelineno-0-45" name="__codelineno-0-45"></a>            <span class="k">return</span> <span class="bp">self</span>
 <a id="__codelineno-0-46" name="__codelineno-0-46"></a>
 <a id="__codelineno-0-47" name="__codelineno-0-47"></a>        <span class="k">def</span> <span class="nf">add_this_gate</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">):</span>
@@ -1503,17 +1503,17 @@ <h2 id="opensquirrel.circuit_builder.CircuitBuilder" class="doc doc-heading">
 <a id="__codelineno-0-53" name="__codelineno-0-53"></a>                        <span class="sa">f</span><span class="s2">&quot;Wrong argument type for gate `</span><span class="si">{</span><span class="n">attr</span><span class="si">}</span><span class="s2">`, got </span><span class="si">{</span><span class="nb">type</span><span class="p">(</span><span class="n">args</span><span class="p">[</span><span class="n">i</span><span class="p">])</span><span class="si">}</span><span class="s2"> but expected </span><span class="si">{</span><span class="n">par</span><span class="o">.</span><span class="n">annotation</span><span class="si">}</span><span class="s2">&quot;</span>
 <a id="__codelineno-0-54" name="__codelineno-0-54"></a>                    <span class="p">)</span>
 <a id="__codelineno-0-55" name="__codelineno-0-55"></a>
-<a id="__codelineno-0-56" name="__codelineno-0-56"></a>            <span class="bp">self</span><span class="o">.</span><span class="n">squirrel_ir</span><span class="o">.</span><span class="n">add_gate</span><span class="p">(</span><span class="n">generator_f</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">))</span>
+<a id="__codelineno-0-56" name="__codelineno-0-56"></a>            <span class="bp">self</span><span class="o">.</span><span class="n">ir</span><span class="o">.</span><span class="n">add_gate</span><span class="p">(</span><span class="n">generator_f</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">))</span>
 <a id="__codelineno-0-57" name="__codelineno-0-57"></a>            <span class="k">return</span> <span class="bp">self</span>
 <a id="__codelineno-0-58" name="__codelineno-0-58"></a>
 <a id="__codelineno-0-59" name="__codelineno-0-59"></a>        <span class="k">return</span> <span class="n">add_comment</span> <span class="k">if</span> <span class="n">attr</span> <span class="o">==</span> <span class="s2">&quot;comment&quot;</span> <span class="k">else</span> <span class="n">add_this_gate</span>
 <a id="__codelineno-0-60" name="__codelineno-0-60"></a>
 <a id="__codelineno-0-61" name="__codelineno-0-61"></a>    <span class="k">def</span> <span class="nf">to_circuit</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Circuit</span><span class="p">:</span>
-<a id="__codelineno-0-62" name="__codelineno-0-62"></a>        <span class="k">return</span> <span class="n">Circuit</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">squirrel_ir</span><span class="p">)</span>
+<a id="__codelineno-0-62" name="__codelineno-0-62"></a>        <span class="k">return</span> <span class="n">Circuit</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">ir</span><span class="p">)</span>
 </code></pre></div></td></tr></table></div>
             </details>
 
-  
+
 
   <div class="doc doc-children">
 
@@ -1550,7 +1550,7 @@ <h2 id="opensquirrel.circuit_builder.CircuitBuilder" class="doc doc-heading">
 <a id="opensquirrel.circuit_matrix_calculator"></a>
   <div class="doc doc-contents first">
 
-  
+
 
   <div class="doc doc-children">
 
@@ -1568,13 +1568,13 @@ <h2 id="opensquirrel.circuit_builder.CircuitBuilder" class="doc doc-heading">
 
 
 <h2 id="opensquirrel.circuit_matrix_calculator.get_circuit_matrix" class="doc doc-heading">
-          <code class="highlight language-python"><span class="n">get_circuit_matrix</span><span class="p">(</span><span class="n">squirrel_ir</span><span class="p">)</span></code>
+          <code class="highlight language-python"><span class="n">get_circuit_matrix</span><span class="p">(</span><span class="n">ir</span><span class="p">)</span></code>
 
 </h2>
 
 
   <div class="doc doc-contents ">
-  
+
       <p>Compute the Numpy unitary matrix corresponding to the circuit.
 The size of this matrix grows exponentially with the number of qubits.</p>
 
@@ -1590,15 +1590,15 @@ <h2 id="opensquirrel.circuit_matrix_calculator.get_circuit_matrix" class="doc do
 <span class="normal"><a href="#__codelineno-0-27">27</a></span>
 <span class="normal"><a href="#__codelineno-0-28">28</a></span>
 <span class="normal"><a href="#__codelineno-0-29">29</a></span>
-<span class="normal"><a href="#__codelineno-0-30">30</a></span></pre></div></td><td class="code"><div><pre><span></span><code><a id="__codelineno-0-20" name="__codelineno-0-20"></a><span class="k">def</span> <span class="nf">get_circuit_matrix</span><span class="p">(</span><span class="n">squirrel_ir</span><span class="p">:</span> <span class="n">SquirrelIR</span><span class="p">):</span>
+<span class="normal"><a href="#__codelineno-0-30">30</a></span></pre></div></td><td class="code"><div><pre><span></span><code><a id="__codelineno-0-20" name="__codelineno-0-20"></a><span class="k">def</span> <span class="nf">get_circuit_matrix</span><span class="p">(</span><span class="n">ir</span><span class="p">:</span> <span class="n">IR</span><span class="p">):</span>
 <a id="__codelineno-0-21" name="__codelineno-0-21"></a><span class="w">    </span><span class="sd">&quot;&quot;&quot;</span>
 <a id="__codelineno-0-22" name="__codelineno-0-22"></a><span class="sd">    Compute the Numpy unitary matrix corresponding to the circuit.</span>
 <a id="__codelineno-0-23" name="__codelineno-0-23"></a><span class="sd">    The size of this matrix grows exponentially with the number of qubits.</span>
 <a id="__codelineno-0-24" name="__codelineno-0-24"></a><span class="sd">    &quot;&quot;&quot;</span>
 <a id="__codelineno-0-25" name="__codelineno-0-25"></a>
-<a id="__codelineno-0-26" name="__codelineno-0-26"></a>    <span class="n">impl</span> <span class="o">=</span> <span class="n">_CircuitMatrixCalculator</span><span class="p">(</span><span class="n">squirrel_ir</span><span class="o">.</span><span class="n">number_of_qubits</span><span class="p">)</span>
+<a id="__codelineno-0-26" name="__codelineno-0-26"></a>    <span class="n">impl</span> <span class="o">=</span> <span class="n">_CircuitMatrixCalculator</span><span class="p">(</span><span class="n">ir</span><span class="o">.</span><span class="n">number_of_qubits</span><span class="p">)</span>
 <a id="__codelineno-0-27" name="__codelineno-0-27"></a>
-<a id="__codelineno-0-28" name="__codelineno-0-28"></a>    <span class="n">squirrel_ir</span><span class="o">.</span><span class="n">accept</span><span class="p">(</span><span class="n">impl</span><span class="p">)</span>
+<a id="__codelineno-0-28" name="__codelineno-0-28"></a>    <span class="n">ir</span><span class="o">.</span><span class="n">accept</span><span class="p">(</span><span class="n">impl</span><span class="p">)</span>
 <a id="__codelineno-0-29" name="__codelineno-0-29"></a>
 <a id="__codelineno-0-30" name="__codelineno-0-30"></a>    <span class="k">return</span> <span class="n">impl</span><span class="o">.</span><span class="n">matrix</span>
 </code></pre></div></td></tr></table></div>
@@ -1622,7 +1622,7 @@ <h2 id="opensquirrel.circuit_matrix_calculator.get_circuit_matrix" class="doc do
 <a id="opensquirrel.common"></a>
   <div class="doc doc-contents first">
 
-  
+
 
   <div class="doc doc-children">
 
@@ -1649,7 +1649,7 @@ <h2 id="opensquirrel.circuit_matrix_calculator.get_circuit_matrix" class="doc do
 <a id="opensquirrel.decomposer.cnot_decomposer"></a>
   <div class="doc doc-contents first">
 
-  
+
 
   <div class="doc doc-children">
 
@@ -1675,7 +1675,7 @@ <h2 id="opensquirrel.decomposer.cnot_decomposer.CNOTDecomposer" class="doc doc-h
           <p class="doc doc-class-bases">
             Bases: <code><span title="opensquirrel.decomposer.general_decomposer.Decomposer">Decomposer</span></code></p>
 
-  
+
       <p>Decomposes 2-qubit controlled unitary gates to CNOT + Rz/Ry.
 Applying single-qubit gate fusion after this pass might be beneficial.</p>
 <p>Source of the math: https://threeplusone.com/pubs/on_gates.pdf, chapter 7.5 "ABC decomposition"</p>
@@ -1824,7 +1824,7 @@ <h2 id="opensquirrel.decomposer.cnot_decomposer.CNOTDecomposer" class="doc doc-h
 </code></pre></div></td></tr></table></div>
             </details>
 
-  
+
 
   <div class="doc doc-children">
 
@@ -1861,7 +1861,7 @@ <h2 id="opensquirrel.decomposer.cnot_decomposer.CNOTDecomposer" class="doc doc-h
 <a id="opensquirrel.decomposer.general_decomposer"></a>
   <div class="doc doc-contents first">
 
-  
+
 
   <div class="doc doc-children">
 
@@ -1879,13 +1879,13 @@ <h2 id="opensquirrel.decomposer.cnot_decomposer.CNOTDecomposer" class="doc doc-h
 
 
 <h2 id="opensquirrel.decomposer.general_decomposer.decompose" class="doc doc-heading">
-          <code class="highlight language-python"><span class="n">decompose</span><span class="p">(</span><span class="n">squirrel_ir</span><span class="p">,</span> <span class="n">decomposer</span><span class="p">)</span></code>
+          <code class="highlight language-python"><span class="n">decompose</span><span class="p">(</span><span class="n">ir</span><span class="p">,</span> <span class="n">decomposer</span><span class="p">)</span></code>
 
 </h2>
 
 
   <div class="doc doc-contents ">
-  
+
       <p>Applies <code>decomposer</code> to every gate in the circuit, replacing each gate by the output of <code>decomposer</code>.
 When <code>decomposer</code> decides to not decomposer a gate, it needs to return a list with the intact gate as single element.</p>
 
@@ -1908,13 +1908,13 @@ <h2 id="opensquirrel.decomposer.general_decomposer.decompose" class="doc doc-hea
 <span class="normal"><a href="#__codelineno-0-76">76</a></span>
 <span class="normal"><a href="#__codelineno-0-77">77</a></span>
 <span class="normal"><a href="#__codelineno-0-78">78</a></span>
-<span class="normal"><a href="#__codelineno-0-79">79</a></span></pre></div></td><td class="code"><div><pre><span></span><code><a id="__codelineno-0-62" name="__codelineno-0-62"></a><span class="k">def</span> <span class="nf">decompose</span><span class="p">(</span><span class="n">squirrel_ir</span><span class="p">:</span> <span class="n">SquirrelIR</span><span class="p">,</span> <span class="n">decomposer</span><span class="p">:</span> <span class="n">Decomposer</span><span class="p">):</span>
+<span class="normal"><a href="#__codelineno-0-79">79</a></span></pre></div></td><td class="code"><div><pre><span></span><code><a id="__codelineno-0-62" name="__codelineno-0-62"></a><span class="k">def</span> <span class="nf">decompose</span><span class="p">(</span><span class="n">ir</span><span class="p">:</span> <span class="n">IR</span><span class="p">,</span> <span class="n">decomposer</span><span class="p">:</span> <span class="n">Decomposer</span><span class="p">):</span>
 <a id="__codelineno-0-63" name="__codelineno-0-63"></a><span class="w">    </span><span class="sd">&quot;&quot;&quot;Applies `decomposer` to every gate in the circuit, replacing each gate by the output of `decomposer`.</span>
 <a id="__codelineno-0-64" name="__codelineno-0-64"></a><span class="sd">    When `decomposer` decides to not decomposer a gate, it needs to return a list with the intact gate as single element.</span>
 <a id="__codelineno-0-65" name="__codelineno-0-65"></a><span class="sd">    &quot;&quot;&quot;</span>
 <a id="__codelineno-0-66" name="__codelineno-0-66"></a>    <span class="n">statement_index</span> <span class="o">=</span> <span class="mi">0</span>
-<a id="__codelineno-0-67" name="__codelineno-0-67"></a>    <span class="k">while</span> <span class="n">statement_index</span> <span class="o">&lt;</span> <span class="nb">len</span><span class="p">(</span><span class="n">squirrel_ir</span><span class="o">.</span><span class="n">statements</span><span class="p">):</span>
-<a id="__codelineno-0-68" name="__codelineno-0-68"></a>        <span class="n">statement</span> <span class="o">=</span> <span class="n">squirrel_ir</span><span class="o">.</span><span class="n">statements</span><span class="p">[</span><span class="n">statement_index</span><span class="p">]</span>
+<a id="__codelineno-0-67" name="__codelineno-0-67"></a>    <span class="k">while</span> <span class="n">statement_index</span> <span class="o">&lt;</span> <span class="nb">len</span><span class="p">(</span><span class="n">ir</span><span class="o">.</span><span class="n">statements</span><span class="p">):</span>
+<a id="__codelineno-0-68" name="__codelineno-0-68"></a>        <span class="n">statement</span> <span class="o">=</span> <span class="n">ir</span><span class="o">.</span><span class="n">statements</span><span class="p">[</span><span class="n">statement_index</span><span class="p">]</span>
 <a id="__codelineno-0-69" name="__codelineno-0-69"></a>
 <a id="__codelineno-0-70" name="__codelineno-0-70"></a>        <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">statement</span><span class="p">,</span> <span class="n">Gate</span><span class="p">):</span>
 <a id="__codelineno-0-71" name="__codelineno-0-71"></a>            <span class="n">statement_index</span> <span class="o">+=</span> <span class="mi">1</span>
@@ -1924,7 +1924,7 @@ <h2 id="opensquirrel.decomposer.general_decomposer.decompose" class="doc doc-hea
 <a id="__codelineno-0-75" name="__codelineno-0-75"></a>
 <a id="__codelineno-0-76" name="__codelineno-0-76"></a>        <span class="n">check_valid_replacement</span><span class="p">(</span><span class="n">statement</span><span class="p">,</span> <span class="n">replacement</span><span class="p">)</span>
 <a id="__codelineno-0-77" name="__codelineno-0-77"></a>
-<a id="__codelineno-0-78" name="__codelineno-0-78"></a>        <span class="n">squirrel_ir</span><span class="o">.</span><span class="n">statements</span><span class="p">[</span><span class="n">statement_index</span> <span class="p">:</span> <span class="n">statement_index</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">replacement</span>
+<a id="__codelineno-0-78" name="__codelineno-0-78"></a>        <span class="n">ir</span><span class="o">.</span><span class="n">statements</span><span class="p">[</span><span class="n">statement_index</span> <span class="p">:</span> <span class="n">statement_index</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">replacement</span>
 <a id="__codelineno-0-79" name="__codelineno-0-79"></a>        <span class="n">statement_index</span> <span class="o">+=</span> <span class="nb">len</span><span class="p">(</span><span class="n">replacement</span><span class="p">)</span>
 </code></pre></div></td></tr></table></div>
           </details>
@@ -1938,13 +1938,13 @@ <h2 id="opensquirrel.decomposer.general_decomposer.decompose" class="doc doc-hea
 
 
 <h2 id="opensquirrel.decomposer.general_decomposer.replace" class="doc doc-heading">
-          <code class="highlight language-python"><span class="n">replace</span><span class="p">(</span><span class="n">squirrel_ir</span><span class="p">,</span> <span class="n">gate_generator</span><span class="p">,</span> <span class="n">f</span><span class="p">)</span></code>
+          <code class="highlight language-python"><span class="n">replace</span><span class="p">(</span><span class="n">ir</span><span class="p">,</span> <span class="n">gate_generator</span><span class="p">,</span> <span class="n">f</span><span class="p">)</span></code>
 
 </h2>
 
 
   <div class="doc doc-contents ">
-  
+
       <p>Does the same as decomposer, but only applies to a given gate.</p>
 
           <details class="quote">
@@ -1959,7 +1959,7 @@ <h2 id="opensquirrel.decomposer.general_decomposer.replace" class="doc doc-headi
 <span class="normal"><a href="#__codelineno-0-100">100</a></span>
 <span class="normal"><a href="#__codelineno-0-101">101</a></span>
 <span class="normal"><a href="#__codelineno-0-102">102</a></span>
-<span class="normal"><a href="#__codelineno-0-103">103</a></span></pre></div></td><td class="code"><div><pre><span></span><code><a id="__codelineno-0-93" name="__codelineno-0-93"></a><span class="k">def</span> <span class="nf">replace</span><span class="p">(</span><span class="n">squirrel_ir</span><span class="p">:</span> <span class="n">SquirrelIR</span><span class="p">,</span> <span class="n">gate_generator</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[</span><span class="o">...</span><span class="p">,</span> <span class="n">Gate</span><span class="p">],</span> <span class="n">f</span><span class="p">):</span>
+<span class="normal"><a href="#__codelineno-0-103">103</a></span></pre></div></td><td class="code"><div><pre><span></span><code><a id="__codelineno-0-93" name="__codelineno-0-93"></a><span class="k">def</span> <span class="nf">replace</span><span class="p">(</span><span class="n">ir</span><span class="p">:</span> <span class="n">IR</span><span class="p">,</span> <span class="n">gate_generator</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[</span><span class="o">...</span><span class="p">,</span> <span class="n">Gate</span><span class="p">],</span> <span class="n">f</span><span class="p">):</span>
 <a id="__codelineno-0-94" name="__codelineno-0-94"></a><span class="w">    </span><span class="sd">&quot;&quot;&quot;Does the same as decomposer, but only applies to a given gate.&quot;&quot;&quot;</span>
 <a id="__codelineno-0-95" name="__codelineno-0-95"></a>
 <a id="__codelineno-0-96" name="__codelineno-0-96"></a>    <span class="k">def</span> <span class="nf">generic_replacer</span><span class="p">(</span><span class="n">g</span><span class="p">:</span> <span class="n">Gate</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="p">[</span><span class="n">Gate</span><span class="p">]:</span>
@@ -1969,7 +1969,7 @@ <h2 id="opensquirrel.decomposer.general_decomposer.replace" class="doc doc-headi
 <a id="__codelineno-0-100" name="__codelineno-0-100"></a>
 <a id="__codelineno-0-101" name="__codelineno-0-101"></a>    <span class="n">generic_replacer</span> <span class="o">=</span> <span class="n">_GenericReplacer</span><span class="p">(</span><span class="n">gate_generator</span><span class="p">,</span> <span class="n">f</span><span class="p">)</span>
 <a id="__codelineno-0-102" name="__codelineno-0-102"></a>
-<a id="__codelineno-0-103" name="__codelineno-0-103"></a>    <span class="n">decompose</span><span class="p">(</span><span class="n">squirrel_ir</span><span class="p">,</span> <span class="n">generic_replacer</span><span class="p">)</span>
+<a id="__codelineno-0-103" name="__codelineno-0-103"></a>    <span class="n">decompose</span><span class="p">(</span><span class="n">ir</span><span class="p">,</span> <span class="n">generic_replacer</span><span class="p">)</span>
 </code></pre></div></td></tr></table></div>
           </details>
   </div>
@@ -1991,7 +1991,7 @@ <h2 id="opensquirrel.decomposer.general_decomposer.replace" class="doc doc-headi
 <a id="opensquirrel.decomposer.mckay_decomposer"></a>
   <div class="doc doc-contents first">
 
-  
+
 
   <div class="doc doc-children">
 
@@ -2122,7 +2122,7 @@ <h2 id="opensquirrel.decomposer.mckay_decomposer.McKayDecomposer" class="doc doc
 </code></pre></div></td></tr></table></div>
             </details>
 
-  
+
 
   <div class="doc doc-children">
 
@@ -2141,7 +2141,7 @@ <h2 id="opensquirrel.decomposer.mckay_decomposer.McKayDecomposer" class="doc doc
 
 <h3 id="opensquirrel.decomposer.mckay_decomposer.McKayDecomposer.decompose" class="doc doc-heading">
           <code class="highlight language-python"><span class="n">decompose</span><span class="p">(</span><span class="n">g</span><span class="p">)</span></code>
-  
+
   <span class="doc doc-labels">
       <small class="doc doc-label doc-label-staticmethod"><code>staticmethod</code></small>
   </span>
@@ -2150,7 +2150,7 @@ <h3 id="opensquirrel.decomposer.mckay_decomposer.McKayDecomposer.decompose" clas
 
 
   <div class="doc doc-contents ">
-  
+
       <p>Return the McKay decomposition of a 1-qubit gate as a list of gates.
         gate   ----&gt;    Rz.Rx(pi/2).Rz.Rx(pi/2).Rz</p>
 <p>The global phase is deemed <em>irrelevant</em>, therefore a simulator backend might produce different output
@@ -2287,7 +2287,7 @@ <h3 id="opensquirrel.decomposer.mckay_decomposer.McKayDecomposer.decompose" clas
 <a id="opensquirrel.decomposer.zyz_decomposer"></a>
   <div class="doc doc-contents first">
 
-  
+
 
   <div class="doc doc-children">
 
@@ -2311,7 +2311,7 @@ <h2 id="opensquirrel.decomposer.zyz_decomposer.get_zyz_decomposition_angles" cla
 
 
   <div class="doc doc-contents ">
-  
+
       <p>Gives the angles used in the Z-Y-Z decomposition of the Bloch sphere rotation
 characterized by a rotation around <code>axis</code> of angle <code>alpha</code>.</p>
 
@@ -2541,7 +2541,7 @@ <h2 id="opensquirrel.decomposer.zyz_decomposer.get_zyz_decomposition_angles" cla
 <a id="opensquirrel.default_gates"></a>
   <div class="doc doc-contents first">
 
-  
+
 
   <div class="doc doc-children">
 
@@ -2568,7 +2568,7 @@ <h2 id="opensquirrel.decomposer.zyz_decomposer.get_zyz_decomposition_angles" cla
 <a id="opensquirrel.default_measurements"></a>
   <div class="doc doc-contents first">
 
-  
+
 
   <div class="doc doc-children">
 
@@ -2595,7 +2595,7 @@ <h2 id="opensquirrel.decomposer.zyz_decomposer.get_zyz_decomposition_angles" cla
 <a id="opensquirrel.exporter.export_format"></a>
   <div class="doc doc-contents first">
 
-  
+
 
   <div class="doc doc-children">
 
@@ -2622,7 +2622,7 @@ <h2 id="opensquirrel.decomposer.zyz_decomposer.get_zyz_decomposition_angles" cla
 <a id="opensquirrel.exporter.quantify_scheduler_exporter"></a>
   <div class="doc doc-contents first">
 
-  
+
 
   <div class="doc doc-children">
 
@@ -2649,7 +2649,7 @@ <h2 id="opensquirrel.decomposer.zyz_decomposer.get_zyz_decomposition_angles" cla
 <a id="opensquirrel.exporter.writer"></a>
   <div class="doc doc-contents first">
 
-  
+
 
   <div class="doc doc-children">
 
@@ -2676,7 +2676,7 @@ <h2 id="opensquirrel.decomposer.zyz_decomposer.get_zyz_decomposition_angles" cla
 <a id="opensquirrel.instruction_library"></a>
   <div class="doc doc-contents first">
 
-  
+
 
   <div class="doc doc-children">
 
@@ -2703,7 +2703,7 @@ <h2 id="opensquirrel.decomposer.zyz_decomposer.get_zyz_decomposition_angles" cla
 <a id="opensquirrel.merger.general_merger"></a>
   <div class="doc doc-contents first">
 
-  
+
 
   <div class="doc doc-children">
 
@@ -2727,7 +2727,7 @@ <h2 id="opensquirrel.merger.general_merger.compose_bloch_sphere_rotations" class
 
 
   <div class="doc doc-contents ">
-  
+
       <p>Computes the Bloch sphere rotation resulting from the composition of two Bloch sphere rotations.
 The first rotation is applied and then the second.
 The resulting gate is anonymous except if <code>a</code> is the identity and <code>b</code> is not anonymous, or vice versa.</p>
@@ -2837,7 +2837,7 @@ <h2 id="opensquirrel.merger.general_merger.compose_bloch_sphere_rotations" class
 <a id="opensquirrel.parser.libqasm.libqasm_ir_creator"></a>
   <div class="doc doc-contents first">
 
-  
+
 
   <div class="doc doc-children">
 
@@ -2861,10 +2861,10 @@ <h2 id="opensquirrel.merger.general_merger.compose_bloch_sphere_rotations" class
 
 
 
-<a id="opensquirrel.squirrel_ir"></a>
+<a id="opensquirrel.ir"></a>
   <div class="doc doc-contents first">
 
-  
+
 
   <div class="doc doc-children">
 
@@ -2891,7 +2891,7 @@ <h2 id="opensquirrel.merger.general_merger.compose_bloch_sphere_rotations" class
 <a id="opensquirrel.utils.identity_filter"></a>
   <div class="doc doc-contents first">
 
-  
+
 
   <div class="doc doc-children">
 
@@ -2918,7 +2918,7 @@ <h2 id="opensquirrel.merger.general_merger.compose_bloch_sphere_rotations" class
 <a id="opensquirrel.utils.matrix_expander"></a>
   <div class="doc doc-contents first">
 
-  
+
 
   <div class="doc doc-children">
 
@@ -2942,7 +2942,7 @@ <h2 id="opensquirrel.utils.matrix_expander.expand_ket" class="doc doc-heading">
 
 
   <div class="doc doc-contents ">
-  
+
       <p>Given a base quantum ket on n qubits and a reduced ket on a subset of those qubits, this computes the expanded ket
 where the reduction qubits and the other qubits are set based on the reduced ket and the base ket, respectively.
 Roughly equivalent to the <code>pdep</code> assembly instruction (bits deposit).</p>
@@ -2993,7 +2993,7 @@ <h2 id="opensquirrel.utils.matrix_expander.expand_ket" class="doc doc-heading">
         <tr>
           <td><code>qubits</code></td>
           <td>
-                <code><span title="typing.List">List</span>[<span title="opensquirrel.squirrel_ir.Qubit">Qubit</span>]</code>
+                <code><span title="typing.List">List</span>[<span title="opensquirrel.ir.Qubit">Qubit</span>]</code>
           </td>
           <td>
             <div class="doc-md-description">
@@ -3157,7 +3157,7 @@ <h2 id="opensquirrel.utils.matrix_expander.get_matrix" class="doc doc-heading">
 
 
   <div class="doc doc-contents ">
-  
+
       <p>Compute the unitary matrix corresponding to the gate applied to those qubit operands, taken among any number of
 qubits. This can be used for, e.g.,
 - testing,
@@ -3180,7 +3180,7 @@ <h2 id="opensquirrel.utils.matrix_expander.get_matrix" class="doc doc-heading">
         <tr>
           <td><code>gate</code></td>
           <td>
-                <code><span title="opensquirrel.squirrel_ir.Gate">Gate</span></code>
+                <code><span title="opensquirrel.ir.Gate">Gate</span></code>
           </td>
           <td>
             <div class="doc-md-description">
@@ -3344,7 +3344,7 @@ <h2 id="opensquirrel.utils.matrix_expander.get_reduced_ket" class="doc doc-headi
 
 
   <div class="doc doc-contents ">
-  
+
       <p>Given a quantum ket represented by its corresponding base-10 integer, this computes the reduced ket
 where only the given qubits appear, in order.
 Roughly equivalent to the <code>pext</code> assembly instruction (bits extraction).</p>
@@ -3380,7 +3380,7 @@ <h2 id="opensquirrel.utils.matrix_expander.get_reduced_ket" class="doc doc-headi
         <tr>
           <td><code>qubits</code></td>
           <td>
-                <code><span title="typing.List">List</span>[<span title="opensquirrel.squirrel_ir.Qubit">Qubit</span>]</code>
+                <code><span title="typing.List">List</span>[<span title="opensquirrel.ir.Qubit">Qubit</span>]</code>
           </td>
           <td>
             <div class="doc-md-description">
@@ -3527,51 +3527,51 @@ <h2 id="opensquirrel.utils.matrix_expander.get_reduced_ket" class="doc doc-headi
 
 
 
-                
+
               </article>
             </div>
-          
-          
+
+
 <script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script>
         </div>
-        
+
       </main>
-      
+
         <footer class="md-footer">
-  
+
   <div class="md-footer-meta md-typeset">
     <div class="md-footer-meta__inner md-grid">
       <div class="md-copyright">
-  
-  
+
+
     Made with
     <a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
       Material for MkDocs
     </a>
-  
+
 </div>
-      
+
     </div>
   </div>
 </footer>
-      
+
     </div>
     <div class="md-dialog" data-md-component="dialog">
       <div class="md-dialog__inner md-typeset"></div>
     </div>
-    
-    
+
+
     <script id="__config" type="application/json">{"base": "../../../../../../../../..", "features": [], "search": "../../../../../../../../../assets/javascripts/workers/search.b8dbb3d2.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}}</script>
-    
-    
+
+
       <script src="../../../../../../../../../assets/javascripts/bundle.3220b9d7.min.js"></script>
-      
+
         <script src="../../../../../../../../../javascripts/mathjax.js"></script>
-      
+
         <script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
-      
+
         <script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
-      
-    
+
+
   </body>
-</html>
\ No newline at end of file
+</html>
diff --git a/docs/tutorial.md b/docs/tutorial.md
index 9ef72c19..7cb13be0 100644
--- a/docs/tutorial.md
+++ b/docs/tutorial.md
@@ -5,7 +5,9 @@
 OpenSquirrel is available through the Python Package Index ([PyPI](<https://pypi.org/project/opensquirrel/>)). Accordingly, the installation is as easy as ABC:
 
 ```python
-! pip install opensquirrel
+! pip
+install
+opensquirrel
 
 import opensquirrel
 ```
@@ -47,9 +49,10 @@ For creation of a circuit through Python, the `CircuitBuilder` can be used accor
 
 ```python
 from opensquirrel import CircuitBuilder
-from opensquirrel.squirrel_ir import Qubit, Int, Float
+from opensquirrel.ir import Qubit, Int, Float
 
-my_circuit_from_builder = CircuitBuilder(number_of_qubits=2).ry(Qubit(0), Float(0.23)).cnot(Qubit(0), Qubit(1)).to_circuit()
+my_circuit_from_builder = CircuitBuilder(qubit_register_size=2).ry(Qubit(0), Float(0.23)).cnot(Qubit(0),
+                                                                                               Qubit(1)).to_circuit()
 my_circuit_from_builder
 ```
 
@@ -63,7 +66,7 @@ my_circuit_from_builder
 You can naturally use the functionalities available in Python to create your circuit:
 
 ```python
-builder = CircuitBuilder(number_of_qubits=10)
+builder = CircuitBuilder(qubit_register_size=10)
 for i in range(0, 10, 2):
     builder.h(Qubit(i))
 
@@ -83,11 +86,11 @@ builder.to_circuit()
 For instance, you can generate a quantum fourier transform (QFT) circuit as follows:
 
 ```python
-number_of_qubits = 5
-qft = CircuitBuilder(number_of_qubits=number_of_qubits)
-for i in range(number_of_qubits):
+qubit_register_size = 5
+qft = CircuitBuilder(qubit_register_size)
+for i in range(qubit_register_size):
       qft.h(Qubit(i))
-      for c in range(i + 1, number_of_qubits):
+      for c in range(i + 1, qubit_register_size):
             qft.crk(Qubit(c), Qubit(i), Int(c-i+1))
 
 qft.to_circuit()
@@ -117,24 +120,6 @@ qft.to_circuit()
 
 As you can see, gates require _strong types_. For instance, you cannot do:
 
-```python
-try:
-    Circuit.from_string(
-        """
-        version 3.0
-        qubit[2] q
-
-        cnot q[0], 3 // The CNOT expects a qubit as second argument.
-        """
-    )
-except Exception as e:
-    print(e)
-```
-
-    Argument #1 passed to gate `cnot` is of type <class 'opensquirrel.squirrel_ir.Int'> but should be <class 'opensquirrel.squirrel_ir.Qubit'>
-
-The issue is that the CNOT expects a qubit as second input argument, where an integer has been provided. By default, OpenSquirrel does not use LibQASM (the cQASM parser library), but will do so soon. You can enable this, which changes the error message:
-
 ```python
 try:
     Circuit.from_string(
@@ -152,16 +137,18 @@ except Exception as e:
 
     Parsing error: Error at <unknown>:5:9..13: failed to resolve overload for cnot with argument pack (qubit, int)
 
+The issue is that the CNOT expects a qubit as second input argument, where an integer has been provided.
+
 The same holds for the `CircuitBuilder`, _i.e._, it also throws an error if arguments are passed of an unexpected type:
 
 ```python
 try:
-    CircuitBuilder(number_of_qubits=2).cnot(Qubit(0), Int(3))
+    CircuitBuilder(qubit_register_size=2).cnot(Qubit(0), Int(3))
 except Exception as e:
     print(e)
 ```
 
-    Wrong argument type for gate `cnot`, got <class 'opensquirrel.squirrel_ir.Int'> but expected <class 'opensquirrel.squirrel_ir.Qubit'>
+    Wrong argument type for gate `cnot`, got <class 'opensquirrel.ir.Int'> but expected <class 'opensquirrel.ir.Qubit'>
 
 ## Modifying a circuit
 
@@ -172,7 +159,7 @@ OpenSquirrel can merge consecutive quantum gates. Currently, this is only done f
 ```python
 import math
 
-builder = CircuitBuilder(number_of_qubits=1)
+builder = CircuitBuilder(qubit_register_size=1)
 for i in range(16):
   builder.rx(Qubit(0), Float(math.pi / 16))
 
@@ -192,7 +179,7 @@ circuit
 You can inspect what the gate has become in terms of the Bloch sphere rotation it represents:
 
 ```python
-circuit.squirrel_ir.statements[0]
+circuit.ir.statements[0]
 ```
 
     BlochSphereRotation(Qubit[0], axis=[1. 0. 0.], angle=3.141592653589795, phase=0.0)
@@ -247,20 +234,22 @@ Once you have defined your new quantum gates, you can pass them as a custom `gat
 import numpy as np
 import cmath
 from opensquirrel import default_gates
-from opensquirrel.squirrel_ir import named_gate, MatrixGate
+from opensquirrel.ir import named_gate, MatrixGate
+
 
 # Definition of the Sycamore gate as a MatrixGate
 @named_gate
 def syc(q1: Qubit, q2: Qubit):
-      return MatrixGate(
-            matrix=np.array([
-                [1, 0, 0, 0],
-                [0, 0, -1j, 0],
-                [0, -1j, 0, 0],
-                [0, 0, 0, cmath.rect(1, - math.pi / 6)]
-                ]),
-            operands=[q1, q2]
-      )
+    return MatrixGate(
+        matrix=np.array([
+            [1, 0, 0, 0],
+            [0, 0, -1j, 0],
+            [0, -1j, 0, 0],
+            [0, 0, 0, cmath.rect(1, - math.pi / 6)]
+        ]),
+        operands=[q1, q2]
+    )
+
 
 my_extended_gate_set = default_gates.default_gate_set.copy()
 my_extended_gate_set.append(syc)
@@ -309,7 +298,7 @@ circuit.replace(cnot,
                     cz(control, target),
                     h(target),
                 ]
-            )
+                )
 circuit
 ```
 
@@ -514,7 +503,7 @@ Once we have our angles, we can implement the OpenSquirrel decomposition; we wil
 Here is what our final ZYZ decomposition looks like:
 
 ```python
-from opensquirrel.squirrel_ir import Gate, BlochSphereRotation
+from opensquirrel.ir import Gate, BlochSphereRotation
 from opensquirrel.decomposer.general_decomposer import Decomposer
 from opensquirrel.default_gates import rz, ry
 
diff --git a/opensquirrel/circuit.py b/opensquirrel/circuit.py
index e281a2a6..eb3c3f42 100644
--- a/opensquirrel/circuit.py
+++ b/opensquirrel/circuit.py
@@ -4,17 +4,14 @@
 
 import numpy as np
 
-from opensquirrel import circuit_matrix_calculator
 from opensquirrel.decomposer import general_decomposer
 from opensquirrel.decomposer.general_decomposer import Decomposer
 from opensquirrel.default_gates import default_gate_aliases, default_gate_set
 from opensquirrel.default_measurements import default_measurement_set
-from opensquirrel.exporter import quantify_scheduler_exporter, writer
 from opensquirrel.exporter.export_format import ExportFormat
-from opensquirrel.mapper import IdentityMapper, Mapper, map_qubits
-from opensquirrel.merger import general_merger
-from opensquirrel.parser.libqasm.libqasm_ir_creator import LibqasmIRCreator
-from opensquirrel.squirrel_ir import Gate, Measure, SquirrelIR
+from opensquirrel.ir import IR, Gate, Measure
+from opensquirrel.mapper import IdentityMapper, Mapper
+from opensquirrel.register_manager import RegisterManager
 
 
 class Circuit:
@@ -39,13 +36,21 @@ class Circuit:
         rz q[0], 1.5707963
         x90 q[0]
         <BLANKLINE>
-
     """
 
-    def __init__(self, squirrel_ir: SquirrelIR):
-        """Create a circuit object from a SquirrelIR object."""
+    def __init__(self, register_manager: RegisterManager, ir: IR):
+        """Create a circuit object from a register manager and an IR."""
+        self.register_manager = register_manager
+        self.ir = ir
+
+    def __repr__(self) -> str:
+        """Write the circuit to a cQASM 3 string."""
+        from opensquirrel.exporter import writer
+
+        return writer.circuit_to_string(self)
 
-        self.squirrel_ir = squirrel_ir
+    def __eq__(self, other):
+        return self.register_manager == other.register_manager and self.ir == other.ir
 
     @classmethod
     def from_string(
@@ -58,80 +63,65 @@ def from_string(
         """Create a circuit object from a cQasm3 string. All the gates in the circuit need to be defined in
         the `gates` argument.
 
-        * type-checking is performed, eliminating qubit indices errors and incoherencies
+        * type-checking is performed, eliminating qubit indices errors and incoherences
         * checks that used gates are supported and mentioned in `gates` with appropriate signatures
         * does not support map or variables, and other things...
         * for example of `gates` dictionary, please look at TestGates.py
 
-
         Args:
-            cqasm3_string: a cqasm 3 string
+            cqasm3_string: a cQASM 3 string
             gate_set: an array of gate semantic functions. See default_gates for examples
             gate_aliases: a dictionary of extra gate aliases, mapping strings to functions in the gate set
             measurement_set: an array of measurement semantic functions. See default_measurements for examples
-
         """
-        libqasm_ir_creator = LibqasmIRCreator(
+        from opensquirrel.parser.libqasm.parser import Parser
+
+        parser = Parser(
             gate_set=gate_set,
             gate_aliases=gate_aliases,
             measurement_set=measurement_set,
         )
-        return Circuit(libqasm_ir_creator.squirrel_ir_from_string(cqasm3_string))
+        return parser.circuit_from_string(cqasm3_string)
 
     @property
-    def number_of_qubits(self) -> int:
-        return self.squirrel_ir.number_of_qubits
+    def qubit_register_size(self) -> int:
+        return self.register_manager.qubit_register_size
 
     @property
     def qubit_register_name(self) -> str:
-        return self.squirrel_ir.qubit_register_name
+        return self.register_manager.qubit_register_name
 
     def merge_single_qubit_gates(self):
         """Merge all consecutive 1-qubit gates in the circuit.
 
         Gates obtained from merging other gates become anonymous gates.
-
         """
-        general_merger.merge_single_qubit_gates(self.squirrel_ir)
+        from opensquirrel.merger import general_merger
+
+        general_merger.merge_single_qubit_gates(self)
 
     def decompose(self, decomposer: Decomposer):
         """Generic decomposition pass. It applies the given decomposer function to every gate in the circuit."""
-        general_decomposer.decompose(self.squirrel_ir, decomposer)
+        general_decomposer.decompose(self.ir, decomposer)
 
-    def map_qubits(self, mapper: Mapper | None = None) -> None:
+    def map(self, mapper: Mapper) -> None:
         """Generic qubit mapper pass.
-
-        Maps the virtual qubits of the circuit to physical qubits of the target hardware.
-
-        Args:
-            mapper: Mapper pass to use. If ``None`` (default) is provided, use the ``IdentityMapper``.
+        Map the (virtual) qubits of the circuit to the physical qubits of the target hardware.
         """
-        mapper = IdentityMapper() if mapper is None else mapper
-        map_qubits(self.squirrel_ir, mapper)
+        from opensquirrel.mapper.qubit_remapper import remap_ir
+
+        remap_ir(self, mapper.get_mapping())
 
     def replace(self, gate_generator: Callable[..., Gate], f):
         """Manually replace occurrences of a given gate with a list of gates.
         `f` is a callable that takes the arguments of the gate that is to be replaced
         and returns the decomposition as a list of gates.
-
-        """
-        general_decomposer.replace(self.squirrel_ir, gate_generator, f)
-
-    def test_get_circuit_matrix(self) -> np.ndarray:
-        """Get the (large) unitary matrix corresponding to the circuit.
-
-        * this matrix has 4**n elements, where n is the number of qubits
-        * therefore this function is only here for testing purposes on small number of qubits
-        * result is stored as a numpy array of complex numbers
-
         """
-        return circuit_matrix_calculator.get_circuit_matrix(self.squirrel_ir)
-
-    def __repr__(self) -> str:
-        """Write the circuit to a cQasm3 string."""
-        return writer.squirrel_ir_to_string(self.squirrel_ir)
+        general_decomposer.replace(self.ir, gate_generator, f)
 
     def export(self, fmt: ExportFormat = None) -> None:
         if fmt == ExportFormat.QUANTIFY_SCHEDULER:
-            return quantify_scheduler_exporter.export(self.squirrel_ir)
+            from opensquirrel.exporter import quantify_scheduler_exporter
+
+            return quantify_scheduler_exporter.export(self)
         raise ValueError("Unknown exporter format")
diff --git a/opensquirrel/circuit_builder.py b/opensquirrel/circuit_builder.py
index 0dba13a8..a9ef69dc 100644
--- a/opensquirrel/circuit_builder.py
+++ b/opensquirrel/circuit_builder.py
@@ -1,20 +1,31 @@
+from __future__ import annotations
+
 import inspect
 from typing import Callable, Dict
 
 from opensquirrel.circuit import Circuit
 from opensquirrel.default_gates import default_gate_aliases, default_gate_set
-from opensquirrel.instruction_library import GateLibrary
-from opensquirrel.squirrel_ir import Comment, Gate, Qubit, SquirrelIR
+from opensquirrel.default_measurements import default_measurement_set
+from opensquirrel.instruction_library import GateLibrary, MeasurementLibrary
+from opensquirrel.ir import IR, Comment, Gate, Qubit
+from opensquirrel.register_manager import RegisterManager
 
 
-class CircuitBuilder(GateLibrary):
+class CircuitBuilder(GateLibrary, MeasurementLibrary):
     """
     A class using the builder pattern to make construction of circuits easy from Python.
-    Adds corresponding gate when a method is called. Checks gates are known and called with the right arguments.
+    Adds corresponding instruction when a method is called. Checks that instructions are known and called with the right
+    arguments.
     Mainly here to allow for Qiskit-style circuit construction:
 
+    Args:
+        qubit_register_size (int): Size of the qubit register
+        gate_set (list): Supported gates
+        gate_aliases (dict): Supported gate aliases
+        measurement_set (list): Supported measure instructions
+
     Example:
-        >>> CircuitBuilder(number_of_qubits=3).h(Qubit(0)).cnot(Qubit(0), Qubit(1)).cnot(Qubit(0), Qubit(2)). \
+        >>> CircuitBuilder(qubit_register_size=3).H(Qubit(0)).CNOT(Qubit(0), Qubit(1)).CNOT(Qubit(0), Qubit(2)). \
         to_circuit()
         version 3.0
         <BLANKLINE>
@@ -24,39 +35,46 @@ class CircuitBuilder(GateLibrary):
         cnot q[0], q[1]
         cnot q[0], q[2]
         <BLANKLINE>
-    """
 
-    _default_qubit_register_name = "q"
+    """
 
     def __init__(
         self,
-        number_of_qubits: int,
+        qubit_register_size: int,
         gate_set: [Callable[..., Gate]] = default_gate_set,
         gate_aliases: Dict[str, Callable[..., Gate]] = default_gate_aliases,
+        measurement_set: List[Callable[..., Measure]] = default_measurement_set,
     ):
         GateLibrary.__init__(self, gate_set, gate_aliases)
-        self.squirrel_ir = SquirrelIR(
-            number_of_qubits=number_of_qubits, qubit_register_name=self._default_qubit_register_name
-        )
+        MeasurementLibrary.__init__(self, measurement_set)
+        self.register_manager = RegisterManager(qubit_register_size)
+        self.ir = IR()
 
     def __getattr__(self, attr):
-        def add_comment(comment_string: str):
-            self.squirrel_ir.add_comment(Comment(comment_string))
+        def add_comment(comment_string: str) -> CircuitBuilder:
+            self.ir.add_comment(Comment(comment_string))
             return self
 
-        def add_this_gate(*args):
-            generator_f = GateLibrary.get_gate_f(self, attr)
+        def add_instruction(*args: tuple) -> CircuitBuilder:
+            if any(attr == measure.__name__ for measure in self.measurement_set):
+                generator_f = MeasurementLibrary.get_measurement_f(self, attr)
+                _check_generator_f_args(generator_f, args)
+                self.ir.add_measurement(generator_f(*args))
+            else:
+                generator_f = GateLibrary.get_gate_f(self, attr)
+                _check_generator_f_args(generator_f, args)
+                self.ir.add_gate(generator_f(*args))
+            return self
 
+        def _check_generator_f_args(generator_f, args):
             for i, par in enumerate(inspect.signature(generator_f).parameters.values()):
                 if not isinstance(args[i], par.annotation):
                     raise TypeError(
-                        f"Wrong argument type for gate `{attr}`, got {type(args[i])} but expected {par.annotation}"
+                        f"Wrong argument type for instruction `{attr}`, got {type(args[i])} but expected"
+                        f" {par.annotation}"
                     )
 
-            self.squirrel_ir.add_gate(generator_f(*args))
-            return self
-
-        return add_comment if attr == "comment" else add_this_gate
+        return add_comment if attr == "comment" else add_instruction
 
     def to_circuit(self) -> Circuit:
-        return Circuit(self.squirrel_ir)
+        return Circuit(self.register_manager, self.ir)
diff --git a/opensquirrel/circuit_matrix_calculator.py b/opensquirrel/circuit_matrix_calculator.py
index fb9e0283..319c7123 100644
--- a/opensquirrel/circuit_matrix_calculator.py
+++ b/opensquirrel/circuit_matrix_calculator.py
@@ -1,30 +1,30 @@
 import numpy as np
 
-from opensquirrel.squirrel_ir import Comment, Gate, SquirrelIR, SquirrelIRVisitor
+from opensquirrel.circuit import Circuit
+from opensquirrel.ir import IR, Comment, Gate, IRVisitor
 from opensquirrel.utils.matrix_expander import get_matrix
 
 
-class _CircuitMatrixCalculator(SquirrelIRVisitor):
-    def __init__(self, number_of_qubits):
-        self.number_of_qubits = number_of_qubits
-        self.matrix = np.eye(1 << self.number_of_qubits, dtype=np.complex128)
+class _CircuitMatrixCalculator(IRVisitor):
+    def __init__(self, qubit_register_size):
+        self.qubit_register_size = qubit_register_size
+        self.matrix = np.eye(1 << self.qubit_register_size, dtype=np.complex128)
 
     def visit_gate(self, gate: Gate):
-        big_matrix = get_matrix(gate, number_of_qubits=self.number_of_qubits)
+        big_matrix = get_matrix(gate, qubit_register_size=self.qubit_register_size)
         self.matrix = big_matrix @ self.matrix
 
     def visit_comment(self, comment: Comment):
         pass
 
 
-def get_circuit_matrix(squirrel_ir: SquirrelIR):
+def get_circuit_matrix(circuit: Circuit):
+    """Compute the (large) unitary matrix corresponding to the circuit.
+    This matrix has 4**n elements, where n is the number of qubits.
+    Result is stored as a numpy array of complex numbers.
     """
-    Compute the Numpy unitary matrix corresponding to the circuit.
-    The size of this matrix grows exponentially with the number of qubits.
-    """
-
-    impl = _CircuitMatrixCalculator(squirrel_ir.number_of_qubits)
+    impl = _CircuitMatrixCalculator(circuit.qubit_register_size)
 
-    squirrel_ir.accept(impl)
+    circuit.ir.accept(impl)
 
     return impl.matrix
diff --git a/opensquirrel/decomposer/cnot_decomposer.py b/opensquirrel/decomposer/cnot_decomposer.py
index e3dba01d..30a0d0cc 100644
--- a/opensquirrel/decomposer/cnot_decomposer.py
+++ b/opensquirrel/decomposer/cnot_decomposer.py
@@ -4,8 +4,8 @@
 from opensquirrel.decomposer.general_decomposer import Decomposer
 from opensquirrel.decomposer.zyz_decomposer import get_zyz_decomposition_angles
 from opensquirrel.default_gates import CNOT, Ry, Rz, X
+from opensquirrel.ir import BlochSphereRotation, ControlledGate, Float, Gate
 from opensquirrel.merger import general_merger
-from opensquirrel.squirrel_ir import BlochSphereRotation, ControlledGate, Float, Gate
 from opensquirrel.utils.identity_filter import filter_out_identities
 
 
diff --git a/opensquirrel/decomposer/general_decomposer.py b/opensquirrel/decomposer/general_decomposer.py
index d51f1919..fbf31ea3 100644
--- a/opensquirrel/decomposer/general_decomposer.py
+++ b/opensquirrel/decomposer/general_decomposer.py
@@ -2,15 +2,7 @@
 from typing import Callable, List
 
 from opensquirrel.common import are_matrices_equivalent_up_to_global_phase
-from opensquirrel.squirrel_ir import (
-    BlochSphereRotation,
-    ControlledGate,
-    Gate,
-    MatrixGate,
-    Qubit,
-    SquirrelIR,
-    SquirrelIRVisitor,
-)
+from opensquirrel.ir import IR, Gate
 
 
 class Decomposer(ABC):
@@ -20,63 +12,42 @@ def decompose(gate: Gate) -> [Gate]:
         raise NotImplementedError()
 
 
-class _QubitReIndexer(SquirrelIRVisitor):
-    def __init__(self, mappings: List[Qubit]):
-        self.mappings = mappings
+def check_gate_replacement(gate: Gate, replacement_gates: List[Gate]):
+    gate_qubit_indices = [q.index for q in gate.get_qubit_operands()]
+    replacement_gates_qubit_indices = set()
+    [replacement_gates_qubit_indices.update([q.index for q in g.get_qubit_operands()]) for g in replacement_gates]
 
-    def visit_bloch_sphere_rotation(self, g: BlochSphereRotation):
-        result = BlochSphereRotation(
-            qubit=Qubit(self.mappings.index(g.qubit)), angle=g.angle, axis=g.axis, phase=g.phase
-        )
-        return result
+    if set(gate_qubit_indices) != replacement_gates_qubit_indices:
+        raise ValueError(f"Replacement for gate {gate.name} does not seem to operate on the right qubits")
 
-    def visit_matrix_gate(self, g: MatrixGate):
-        mapped_operands = [Qubit(self.mappings.index(op)) for op in g.operands]
-        result = MatrixGate(matrix=g.matrix, operands=mapped_operands)
-        return result
+    from opensquirrel.circuit_matrix_calculator import get_circuit_matrix
+    from opensquirrel.reindexer import get_reindexed_circuit
 
-    def visit_controlled_gate(self, controlled_gate: ControlledGate):
-        control_qubit = Qubit(self.mappings.index(controlled_gate.control_qubit))
-        target_gate = controlled_gate.target_gate.accept(self)
-        result = ControlledGate(control_qubit=control_qubit, target_gate=target_gate)
-        return result
+    replaced_matrix = get_circuit_matrix(get_reindexed_circuit([gate], gate_qubit_indices))
+    replacement_matrix = get_circuit_matrix(get_reindexed_circuit(replacement_gates, gate_qubit_indices))
+    if not are_matrices_equivalent_up_to_global_phase(replaced_matrix, replacement_matrix):
+        raise Exception(f"Replacement for gate {gate.name} does not preserve the quantum state")
 
 
-def check_valid_replacement(statement, replacement):
-    expected_qubit_operands = statement.get_qubit_operands()
-    replacement_qubit_operands = set()
-    [replacement_qubit_operands.update(g.get_qubit_operands()) for g in replacement]
-
-    if set(expected_qubit_operands) != replacement_qubit_operands:
-        raise ValueError(f"Replacement for gate {statement.name} does not seem to operate on the right qubits")
-
-    from opensquirrel.utils.matrix_expander import get_matrix_after_qubit_remapping
-
-    replacement_matrix = get_matrix_after_qubit_remapping(replacement, expected_qubit_operands)
-    replaced_matrix = get_matrix_after_qubit_remapping([statement], expected_qubit_operands)
-
-    if not are_matrices_equivalent_up_to_global_phase(replacement_matrix, replaced_matrix):
-        raise Exception(f"Replacement for gate {statement.name} does not preserve the quantum state")
-
-
-def decompose(squirrel_ir: SquirrelIR, decomposer: Decomposer):
+def decompose(ir: IR, decomposer: Decomposer):
     """Applies `decomposer` to every gate in the circuit, replacing each gate by the output of `decomposer`.
-    When `decomposer` decides to not decomposer a gate, it needs to return a list with the intact gate as single element.
+    When `decomposer` decides to not decomposer a gate, it needs to return a list with the intact gate as single
+    element.
     """
     statement_index = 0
-    while statement_index < len(squirrel_ir.statements):
-        statement = squirrel_ir.statements[statement_index]
+    while statement_index < len(ir.statements):
+        statement = ir.statements[statement_index]
 
         if not isinstance(statement, Gate):
             statement_index += 1
             continue
 
-        replacement: List[Gate] = decomposer.decompose(statement)
-
-        check_valid_replacement(statement, replacement)
+        gate = statement
+        replacement_gates: List[Gate] = decomposer.decompose(statement)
+        check_gate_replacement(gate, replacement_gates)
 
-        squirrel_ir.statements[statement_index : statement_index + 1] = replacement
-        statement_index += len(replacement)
+        ir.statements[statement_index : statement_index + 1] = replacement_gates
+        statement_index += len(replacement_gates)
 
 
 class _GenericReplacer(Decomposer):
@@ -90,14 +61,8 @@ def decompose(self, g: Gate) -> [Gate]:
         return self.replacement_function(*g.arguments)
 
 
-def replace(squirrel_ir: SquirrelIR, gate_generator: Callable[..., Gate], f):
+def replace(ir: IR, gate_generator: Callable[..., Gate], f):
     """Does the same as decomposer, but only applies to a given gate."""
-
-    def generic_replacer(g: Gate) -> [Gate]:
-        if g.is_anonymous or g.generator != gate_generator:
-            return [g]
-        return f(*g.arguments)
-
     generic_replacer = _GenericReplacer(gate_generator, f)
 
-    decompose(squirrel_ir, generic_replacer)
+    decompose(ir, generic_replacer)
diff --git a/opensquirrel/decomposer/mckay_decomposer.py b/opensquirrel/decomposer/mckay_decomposer.py
index bfd3f4f5..aa06bd76 100644
--- a/opensquirrel/decomposer/mckay_decomposer.py
+++ b/opensquirrel/decomposer/mckay_decomposer.py
@@ -3,7 +3,7 @@
 from opensquirrel.common import ATOL, normalize_angle
 from opensquirrel.decomposer.general_decomposer import Decomposer
 from opensquirrel.default_gates import X90, Rz
-from opensquirrel.squirrel_ir import BlochSphereRotation, Float, Gate
+from opensquirrel.ir import BlochSphereRotation, Float, Gate
 
 
 class McKayDecomposer(Decomposer):
diff --git a/opensquirrel/decomposer/zyz_decomposer.py b/opensquirrel/decomposer/zyz_decomposer.py
index 55431e0a..113ef662 100644
--- a/opensquirrel/decomposer/zyz_decomposer.py
+++ b/opensquirrel/decomposer/zyz_decomposer.py
@@ -4,7 +4,7 @@
 from opensquirrel.common import ATOL
 from opensquirrel.decomposer.general_decomposer import Decomposer
 from opensquirrel.default_gates import Ry, Rz
-from opensquirrel.squirrel_ir import BlochSphereRotation, Float, Gate
+from opensquirrel.ir import BlochSphereRotation, Float, Gate
 from opensquirrel.utils.identity_filter import filter_out_identities
 
 
diff --git a/opensquirrel/default_gates.py b/opensquirrel/default_gates.py
index 7cb880af..d6b6c8de 100644
--- a/opensquirrel/default_gates.py
+++ b/opensquirrel/default_gates.py
@@ -2,16 +2,12 @@
 
 import numpy as np
 
-from opensquirrel.squirrel_ir import (
-    BlochSphereRotation,
-    ControlledGate,
-    Float,
-    Gate,
-    Int,
-    MatrixGate,
-    Qubit,
-    named_gate,
-)
+from opensquirrel.ir import BlochSphereRotation, ControlledGate, Float, Gate, Int, MatrixGate, Qubit, named_gate
+
+
+@named_gate
+def I(q: Qubit) -> Gate:
+    return BlochSphereRotation.identity(q)
 
 
 @named_gate
@@ -147,7 +143,8 @@ def CCZ(control1: Qubit, control2: Qubit, target: Qubit) -> Gate:
     return ControlledGate(control1, CZ(control2, target))
 
 
-default_gate_set = [
+default_bloch_sphere_rotations_without_params = [
+    I,
     H,
     X,
     X90,
@@ -160,9 +157,15 @@ def CCZ(control1: Qubit, control2: Qubit, target: Qubit) -> Gate:
     Sdag,
     T,
     Tdag,
+]
+default_bloch_sphere_rotations = [
+    *default_bloch_sphere_rotations_without_params,
     Rx,
     Ry,
     Rz,
+]
+default_gate_set = [
+    *default_bloch_sphere_rotations,
     CNOT,
     CZ,
     CR,
@@ -172,4 +175,7 @@ def CCZ(control1: Qubit, control2: Qubit, target: Qubit) -> Gate:
     CCZ,
 ]
 
-default_gate_aliases = {"Hadamard": H}
+default_gate_aliases = {
+    "Hadamard": H,
+    "Identity": I,
+}
diff --git a/opensquirrel/default_measurements.py b/opensquirrel/default_measurements.py
index cac52e0e..35524c42 100644
--- a/opensquirrel/default_measurements.py
+++ b/opensquirrel/default_measurements.py
@@ -1,4 +1,4 @@
-from opensquirrel.squirrel_ir import Measure, Qubit, named_measurement
+from opensquirrel.ir import Measure, Qubit, named_measurement
 
 
 @named_measurement
diff --git a/opensquirrel/exporter/quantify_scheduler_exporter.py b/opensquirrel/exporter/quantify_scheduler_exporter.py
index e229ae78..aca10337 100644
--- a/opensquirrel/exporter/quantify_scheduler_exporter.py
+++ b/opensquirrel/exporter/quantify_scheduler_exporter.py
@@ -1,15 +1,9 @@
 import math
 
+from opensquirrel.circuit import Circuit
 from opensquirrel.common import ATOL
 from opensquirrel.default_gates import X, Z
-from opensquirrel.squirrel_ir import (
-    BlochSphereRotation,
-    ControlledGate,
-    MatrixGate,
-    Qubit,
-    SquirrelIR,
-    SquirrelIRVisitor,
-)
+from opensquirrel.ir import IR, BlochSphereRotation, ControlledGate, IRVisitor, MatrixGate, Measure, Qubit
 
 try:
     import quantify_scheduler
@@ -17,14 +11,13 @@
 except Exception as e:
     pass
 
-
 _unsupported_gates_exception = Exception(
     "Cannot exporter circuit: it contains unsupported gates - decomposer them to the "
     "Quantify-scheduler gate set first (rxy, rz, cnot, cz)"
 )
 
 
-class _ScheduleCreator(SquirrelIRVisitor):
+class _ScheduleCreator(IRVisitor):
     def _get_qubit_string(self, q: Qubit) -> str:
         return f"{self.qubit_register_name}[{q.index}]"
 
@@ -32,6 +25,10 @@ def __init__(self, qubit_register_name: str):
         self.qubit_register_name = qubit_register_name
         self.schedule = quantify_scheduler.Schedule("Exported OpenSquirrel circuit")
 
+    def visit_measure(self, g: Measure):
+        self.schedule.add(quantify_scheduler_gates.Measure(self._get_qubit_string(g.qubit)))
+        return
+
     def visit_bloch_sphere_rotation(self, g: BlochSphereRotation):
         if abs(g.axis[2]) < ATOL:
             # Rxy rotation.
@@ -74,7 +71,7 @@ def visit_controlled_gate(self, g: ControlledGate):
         raise _unsupported_gates_exception
 
 
-def export(squirrel_ir: SquirrelIR):
+def export(circuit: Circuit):
     if "quantify_scheduler" not in globals():
 
         class QuantifySchedulerNotInstalled:
@@ -86,6 +83,6 @@ def __getattr__(self, attr_name):
         global quantify_scheduler_gates
         quantify_scheduler_gates = QuantifySchedulerNotInstalled()
 
-    schedule_creator = _ScheduleCreator(squirrel_ir.qubit_register_name)
-    squirrel_ir.accept(schedule_creator)
+    schedule_creator = _ScheduleCreator(circuit.qubit_register_name)
+    circuit.ir.accept(schedule_creator)
     return schedule_creator.schedule
diff --git a/opensquirrel/exporter/writer.py b/opensquirrel/exporter/writer.py
index 22c51ab1..5f337312 100644
--- a/opensquirrel/exporter/writer.py
+++ b/opensquirrel/exporter/writer.py
@@ -1,15 +1,19 @@
-from opensquirrel.squirrel_ir import Comment, Float, Gate, Int, Measure, Qubit, SquirrelIR, SquirrelIRVisitor
+from opensquirrel.circuit import Circuit
+from opensquirrel.ir import Comment, Float, Gate, Int, IRVisitor, Measure, Qubit
 
 
-class _WriterImpl(SquirrelIRVisitor):
+class _WriterImpl(IRVisitor):
     number_of_significant_digits = 8
 
-    def __init__(self, number_of_qubits, qubit_register_name):
-        self.qubit_register_name = qubit_register_name
-        self.output = f"""version 3.0\n\nqubit[{number_of_qubits}] {qubit_register_name}\n\n"""
+    def __init__(self, register_manager):
+        self.register_manager = register_manager
+        qubit_register_size = self.register_manager.qubit_register_size
+        qubit_register_name = self.register_manager.qubit_register_name
+        self.output = f"""version 3.0\n\nqubit[{qubit_register_size}] {qubit_register_name}\n\n"""
 
     def visit_qubit(self, qubit: Qubit):
-        return f"{self.qubit_register_name}[{qubit.index}]"
+        qubit_register_name = self.register_manager.qubit_register_name
+        return f"{qubit_register_name}[{qubit.index}]"
 
     def visit_int(self, i: Int):
         return f"{i.value}"
@@ -21,11 +25,10 @@ def visit_measure(self, measure: Measure):
         self.output += f"{measure.name} {measure.arguments[0].accept(self)}\n"
 
     def visit_gate(self, gate: Gate):
+        gate_name = gate.name
         if gate.is_anonymous:
-            self.output += "<anonymous-gate>\n"
+            self.output += f"{gate_name}\n"
             return
-
-        gate_name = gate.name
         if any(not isinstance(arg, Qubit) for arg in gate.arguments):
             params = [arg.accept(self) for arg in gate.arguments if not isinstance(arg, Qubit)]
             gate_name += f"({', '.join(params)})"
@@ -36,9 +39,9 @@ def visit_comment(self, comment: Comment):
         self.output += f"\n/* {comment.str} */\n\n"
 
 
-def squirrel_ir_to_string(squirrel_ir: SquirrelIR):
-    writer_impl = _WriterImpl(squirrel_ir.number_of_qubits, squirrel_ir.qubit_register_name)
+def circuit_to_string(circuit: Circuit):
+    writer_impl = _WriterImpl(circuit.register_manager)
 
-    squirrel_ir.accept(writer_impl)
+    circuit.ir.accept(writer_impl)
 
     return writer_impl.output
diff --git a/opensquirrel/instruction_library.py b/opensquirrel/instruction_library.py
index 0a75722d..9819c206 100644
--- a/opensquirrel/instruction_library.py
+++ b/opensquirrel/instruction_library.py
@@ -2,7 +2,7 @@
 
 
 class InstructionLibrary(ABC):
-    pass
+    """Abstract base class for instruction libraries."""
 
 
 class GateLibrary(InstructionLibrary):
@@ -13,9 +13,9 @@ def __init__(self, gate_set, gate_aliases):
     def get_gate_f(self, gate_name: str):
         try:
             generator_f = next(f for f in self.gate_set if f.__name__ == gate_name)
-        except StopIteration:
+        except StopIteration as exc:
             if gate_name not in self.gate_aliases:
-                raise ValueError(f"Unknown gate `{gate_name}`")
+                raise ValueError(f"Unknown instruction `{gate_name}`") from exc
             generator_f = self.gate_aliases[gate_name]
         return generator_f
 
@@ -28,5 +28,5 @@ def get_measurement_f(self, measurement_name: str):
         try:
             generator_f = next(f for f in self.measurement_set if f.__name__ == measurement_name)
             return generator_f
-        except StopIteration:
-            raise ValueError(f"Unknown measurement `{measurement_name}`")
+        except StopIteration as exc:
+            raise ValueError(f"Unknown instruction `{measurement_name}`") from exc
diff --git a/opensquirrel/squirrel_ir.py b/opensquirrel/ir.py
similarity index 68%
rename from opensquirrel/squirrel_ir.py
rename to opensquirrel/ir.py
index 37c3da86..ff557899 100644
--- a/opensquirrel/squirrel_ir.py
+++ b/opensquirrel/ir.py
@@ -2,7 +2,6 @@
 
 import inspect
 from abc import ABC, abstractmethod
-from collections.abc import Mapping
 from dataclasses import dataclass
 from functools import wraps
 from typing import Callable, List, Optional, Tuple
@@ -12,7 +11,7 @@
 from opensquirrel.common import ATOL, are_matrices_equivalent_up_to_global_phase, normalize_angle, normalize_axis
 
 
-class SquirrelIRVisitor(ABC):
+class IRVisitor(ABC):
     def visit_comment(self, comment: "Comment"):
         pass
 
@@ -43,7 +42,7 @@ def visit_controlled_gate(self, controlled_gate: "ControlledGate"):
 
 class IRNode(ABC):
     @abstractmethod
-    def accept(self, visitor: SquirrelIRVisitor):
+    def accept(self, visitor: IRVisitor):
         pass
 
 
@@ -55,7 +54,7 @@ class Expression(IRNode, ABC):
 class Float(Expression):
     value: float
 
-    def accept(self, visitor: SquirrelIRVisitor):
+    def accept(self, visitor: IRVisitor):
         return visitor.visit_float(self)
 
 
@@ -63,7 +62,7 @@ def accept(self, visitor: SquirrelIRVisitor):
 class Int(Expression):
     value: int
 
-    def accept(self, visitor: SquirrelIRVisitor):
+    def accept(self, visitor: IRVisitor):
         return visitor.visit_int(self)
 
 
@@ -77,7 +76,7 @@ def __hash__(self):
     def __repr__(self):
         return f"Qubit[{self.index}]"
 
-    def accept(self, visitor: SquirrelIRVisitor):
+    def accept(self, visitor: IRVisitor):
         return visitor.visit_qubit(self)
 
 
@@ -92,7 +91,7 @@ class Measure(Statement, ABC):
     def __init__(
         self,
         qubit: Qubit,
-        axis: Tuple[float, float, float],
+        axis: Tuple[float, float, float] = (0, 0, 1),
         generator=None,
         arguments=None,
     ):
@@ -113,20 +112,12 @@ def __eq__(self, other):
             return False
         return self.qubit == other.qubit and np.allclose(self.axis, other.axis, atol=ATOL)
 
-    def accept(self, visitor: SquirrelIRVisitor):
-        visitor.visit_measure(self)
+    def accept(self, visitor: IRVisitor):
+        return visitor.visit_measure(self)
 
     def get_qubit_operands(self) -> List[Qubit]:
         return [self.qubit]
 
-    def relabel(self, mapping: Mapping[int, int]) -> None:
-        """Relabel the qubits using the given mapping.
-
-        Args:
-            mapping: Mapping from the indices of the original qubits to the indices of the qubits after replacement.
-        """
-        self.qubit = Qubit(mapping[self.qubit.index])
-
 
 class Gate(Statement, ABC):
     # Note: two gates are considered equal even when their generators/arguments are different.
@@ -137,37 +128,18 @@ def __init__(self, generator, arguments):
         self.generator = generator
         self.arguments = arguments
 
-    def _check_is_anonymous(self) -> bool:
-        """A check to verify if BlochSphereRotation is a pre-defined single qubit gate.
-
-        Returns:
-            Whether the BlochSphereRotation reflects a gate or not (is an anonymous gate).
-        """
-        if self.arguments is not None:
-            return False
-        from opensquirrel.default_gates import default_gate_set
-
-        for _, gate in enumerate(default_gate_set):
-            gate_args = inspect.signature(gate).parameters.values()
-            if len(list(gate_args)) == 1:
-                output_bloch = gate(self.get_qubit_operands())
-                if np.allclose(output_bloch.axis, self.axis) and np.allclose(output_bloch.phase, self.phase):
-                    Gate.__init__(self, gate, self.get_qubit_operands())
-                    return False
-        return True
-
     def __eq__(self, other):
         if not isinstance(other, Gate):
             return False
-        return _compare_gate_classes(self, other)
+        return compare_gates(self, other)
 
     @property
     def name(self) -> Optional[str]:
-        return self.generator.__name__ if self.generator else "<anonymous>"
+        return self.generator.__name__ if self.generator else "<anonymous-gate>"
 
     @property
     def is_anonymous(self) -> bool:
-        return self._check_is_anonymous()
+        return self.arguments is None
 
     @abstractmethod
     def get_qubit_operands(self) -> List[Qubit]:
@@ -185,15 +157,6 @@ def is_identity(self) -> bool:
             Boolean value stating whether the Gate is an identity Gate.
         """
 
-    @abstractmethod
-    def relabel(self, mapping: Mapping[int, int]) -> None:
-        """Relabel the qubits using the given mapping.
-
-        Args:
-            mapping: Mapping from the indices of the original qubits to the indices of the qubits
-            after replacement.
-        """
-
 
 class BlochSphereRotation(Gate):
     generator: Optional[Callable[..., "BlochSphereRotation"]] = None
@@ -236,7 +199,7 @@ def __eq__(self, other):
             return abs(self.angle + other.angle) < ATOL
         return False
 
-    def accept(self, visitor: SquirrelIRVisitor):
+    def accept(self, visitor: IRVisitor):
         visitor.visit_gate(self)
         return visitor.visit_bloch_sphere_rotation(self)
 
@@ -247,14 +210,25 @@ def is_identity(self) -> bool:
         # Angle and phase are already normalized.
         return abs(self.angle) < ATOL and abs(self.phase) < ATOL
 
-    def relabel(self, mapping: Mapping[int, int]) -> None:
-        """Relabel the qubits using the given mapping.
+    def get_default_bloch(self) -> BlochSphereRotation | None:
+        """A check to verify if this BlochSphereRotation is close to a default BlochSphereRotation.
 
-        Args:
-            mapping: Mapping from the indices of the original qubits to the indices of the qubits
-            after replacement.
+        Notice we don't try to match Rx, Ry, and Rz rotations, as those gates use an extra angle parameter.
+
+        Returns:
+             A default BlockSphereRotation if this BlochSphereRotation is close to it, or None otherwise.
         """
-        self.qubit = Qubit(mapping[self.qubit.index])
+        from opensquirrel.default_gates import default_bloch_sphere_rotations_without_params
+
+        for _, gate_function in enumerate(default_bloch_sphere_rotations_without_params):
+            gate = gate_function(*self.get_qubit_operands())
+            if (
+                np.allclose(gate.axis, self.axis)
+                and np.allclose(gate.angle, self.angle)
+                and np.allclose(gate.phase, self.phase)
+            ):
+                return gate
+        return None
 
 
 class MatrixGate(Gate):
@@ -271,7 +245,7 @@ def __init__(self, matrix: np.ndarray, operands: List[Qubit], generator=None, ar
     def __repr__(self):
         return f"MatrixGate(qubits={self.operands}, matrix={self.matrix})"
 
-    def accept(self, visitor: SquirrelIRVisitor):
+    def accept(self, visitor: IRVisitor):
         visitor.visit_gate(self)
         return visitor.visit_matrix_gate(self)
 
@@ -281,15 +255,6 @@ def get_qubit_operands(self) -> List[Qubit]:
     def is_identity(self) -> bool:
         return np.allclose(self.matrix, np.eye(2 ** len(self.operands)))
 
-    def relabel(self, mapping: Mapping[int, int]) -> None:
-        """Relabel the qubits using the given mapping.
-
-        Args:
-            mapping: Mapping from the indices of the original qubits to the indices of the qubits
-            after replacement.
-        """
-        self.operands = [Qubit(mapping[qubit.index]) for qubit in self.operands]
-
 
 class ControlledGate(Gate):
     generator: Optional[Callable[..., "ControlledGate"]] = None
@@ -302,7 +267,7 @@ def __init__(self, control_qubit: Qubit, target_gate: Gate, generator=None, argu
     def __repr__(self):
         return f"ControlledGate(control_qubit={self.control_qubit}, {self.target_gate})"
 
-    def accept(self, visitor: SquirrelIRVisitor):
+    def accept(self, visitor: IRVisitor):
         visitor.visit_gate(self)
         return visitor.visit_controlled_gate(self)
 
@@ -312,27 +277,6 @@ def get_qubit_operands(self) -> List[Qubit]:
     def is_identity(self) -> bool:
         return self.target_gate.is_identity()
 
-    def relabel(self, mapping: Mapping[int, int]) -> None:
-        """Relabel the qubits using the given mapping.
-
-        Args:
-            mapping: Mapping from the indices of the original qubits to the indices of the qubits
-            after replacement.
-        """
-        self.control_qubit = Qubit(mapping[self.control_qubit.index])
-        self.target_gate.relabel(mapping)
-
-
-def _compare_gate_classes(g1: Gate, g2: Gate) -> bool:
-    union_mapping = list(set(g1.get_qubit_operands()) | set(g2.get_qubit_operands()))
-
-    from opensquirrel.utils.matrix_expander import get_matrix_after_qubit_remapping
-
-    matrix_g1 = get_matrix_after_qubit_remapping([g1], union_mapping)
-    matrix_g2 = get_matrix_after_qubit_remapping([g2], union_mapping)
-
-    return are_matrices_equivalent_up_to_global_phase(matrix_g1, matrix_g2)
-
 
 def named_gate(gate_generator: Callable[..., Gate]) -> Callable[..., Gate]:
     @wraps(gate_generator)
@@ -382,6 +326,18 @@ def wrapper(*args, **kwargs):
     return wrapper
 
 
+def compare_gates(g1: Gate, g2: Gate) -> bool:
+    union_mapping = [q.index for q in list(set(g1.get_qubit_operands()) | set(g2.get_qubit_operands()))]
+
+    from opensquirrel.circuit_matrix_calculator import get_circuit_matrix
+    from opensquirrel.reindexer import get_reindexed_circuit
+
+    matrix_g1 = get_circuit_matrix(get_reindexed_circuit([g1], union_mapping))
+    matrix_g2 = get_circuit_matrix(get_reindexed_circuit([g2], union_mapping))
+
+    return are_matrices_equivalent_up_to_global_phase(matrix_g1, matrix_g2)
+
+
 @dataclass
 class Comment(Statement):
     str: str
@@ -389,21 +345,14 @@ class Comment(Statement):
     def __post_init__(self):
         assert "*/" not in self.str, "Comment contains illegal characters"
 
-    def accept(self, visitor: SquirrelIRVisitor):
+    def accept(self, visitor: IRVisitor):
         return visitor.visit_comment(self)
 
 
-class SquirrelIR:
+class IR:
     # This is just a list of gates (for now?)
-    def __init__(
-        self,
-        *,
-        number_of_qubits: int,
-        qubit_register_name: str = "q",
-    ):
-        self.number_of_qubits: int = number_of_qubits
+    def __init__(self):
         self.statements: List[Statement] = []
-        self.qubit_register_name: str = qubit_register_name
 
     def add_gate(self, gate: Gate):
         self.statements.append(gate)
@@ -415,17 +364,11 @@ def add_comment(self, comment: Comment):
         self.statements.append(comment)
 
     def __eq__(self, other):
-        if self.number_of_qubits != other.number_of_qubits:
-            return False
-
-        if self.qubit_register_name != other.qubit_register_name:
-            return False
-
         return self.statements == other.statements
 
     def __repr__(self):
-        return f"""IR ({self.number_of_qubits} qubits, register {self.qubit_register_name}): {self.statements}"""
+        return f"""IR: {self.statements}"""
 
-    def accept(self, visitor: SquirrelIRVisitor):
+    def accept(self, visitor: IRVisitor):
         for statement in self.statements:
             statement.accept(visitor)
diff --git a/opensquirrel/mapper/__init__.py b/opensquirrel/mapper/__init__.py
index bcd97242..a0557640 100644
--- a/opensquirrel/mapper/__init__.py
+++ b/opensquirrel/mapper/__init__.py
@@ -1,4 +1,4 @@
-from opensquirrel.mapper.general_mapper import Mapper, map_qubits
+from opensquirrel.mapper.general_mapper import Mapper
 from opensquirrel.mapper.simple_mappers import HardcodedMapper, IdentityMapper
 
-__all__ = ["map_qubits", "Mapper", "IdentityMapper", "HardcodedMapper"]
+__all__ = ["Mapper", "IdentityMapper", "HardcodedMapper"]
diff --git a/opensquirrel/mapper/general_mapper.py b/opensquirrel/mapper/general_mapper.py
index 1c1fb726..de8cd495 100644
--- a/opensquirrel/mapper/general_mapper.py
+++ b/opensquirrel/mapper/general_mapper.py
@@ -2,36 +2,20 @@
 
 from __future__ import annotations
 
-from abc import ABC, abstractmethod
+from opensquirrel.mapper.mapping import Mapping
 
-from opensquirrel.squirrel_ir import Gate, Measure, SquirrelIR
 
-
-def map_qubits(squirrel_ir: SquirrelIR, mapper: Mapper) -> None:
-    """Map the virtual qubits in the `squirrel_ir` to physical qubits using `mapper`.
-
-    Args:
-        squirrel_ir: IR to apply mapping to.
-        mapper: Mapping pass to use.
-    """
-
-    mapping = mapper.map(squirrel_ir)
-
-    for statement in squirrel_ir.statements:
-        if isinstance(statement, (Gate, Measure)):
-            statement.relabel(mapping)
-
-
-class Mapper(ABC):
+class Mapper:
     """Base class for the Mapper pass."""
 
-    @abstractmethod
-    def map(self, squirrel_ir: SquirrelIR) -> dict[int, int]:
-        """Produce a mapping from the virtual qubits in the `squirrel_ir` to the physical qubits.
+    def __init__(self, qubit_register_size: int, mapping: Mapping | None = None) -> None:
+        """Use ``IdentityMapper`` as the fallback case for ``Mapper``"""
+        physical_qubit_register = range(qubit_register_size)
+        self.mapping = mapping if mapping is not None else Mapping(physical_qubit_register)
 
-        Args:
-            squirrel_ir: IR to apply mapping to.
+        if qubit_register_size != self.mapping.size():
+            raise ValueError("Qubit register size and mapping size differ.")
 
-        Returns:
-            Mapping from virtual qubits to physical qubits.
-        """
+    def get_mapping(self) -> Mapping:
+        """Get mapping."""
+        return self.mapping
diff --git a/opensquirrel/mapper/mapping.py b/opensquirrel/mapper/mapping.py
new file mode 100644
index 00000000..ba8638ee
--- /dev/null
+++ b/opensquirrel/mapper/mapping.py
@@ -0,0 +1,40 @@
+from typing import Dict, List, Tuple
+
+
+class Mapping:
+    """A Mapping is a dictionary where:
+       - the keys are virtual qubit indices (from 0 to virtual_qubit_register_size-1), and
+       - the values are physical qubit indices.
+
+    Args:
+        physical_qubit_register: a list of physical qubit indices.
+
+    Raises:
+        ValueError: If the mapping is incorrect.
+    """
+
+    def __init__(self, physical_qubit_register: List[int]) -> None:
+        self.data: Dict[int, int] = dict(enumerate(physical_qubit_register))
+        if (self.data.keys()) != set(self.data.values()):
+            raise ValueError("The mapping is incorrect.")
+
+    def __eq__(self, other):
+        return self.data == other.data
+
+    def __getitem__(self, key: int) -> int:
+        return self.data[key]
+
+    def __len__(self) -> int:
+        return len(self.data)
+
+    def size(self) -> int:
+        return len(self.data)
+
+    def items(self) -> List[Tuple[int, int]]:
+        return self.data.items()
+
+    def keys(self) -> List[int]:
+        return list(self.data.keys())
+
+    def values(self) -> List[int]:
+        return list(self.data.values())
diff --git a/opensquirrel/mapper/qubit_remapper.py b/opensquirrel/mapper/qubit_remapper.py
new file mode 100644
index 00000000..587abada
--- /dev/null
+++ b/opensquirrel/mapper/qubit_remapper.py
@@ -0,0 +1,75 @@
+from typing import List
+
+from opensquirrel.circuit import Circuit
+from opensquirrel.ir import (
+    IR,
+    BlochSphereRotation,
+    Comment,
+    ControlledGate,
+    Gate,
+    IRVisitor,
+    MatrixGate,
+    Measure,
+    Qubit,
+)
+from opensquirrel.mapper.mapping import Mapping
+
+
+class _QubitRemapper(IRVisitor):
+    """
+    Remap a whole IR.
+
+    Args:
+        mapping: a list of qubit indices, e.g. [3, 1, 0, 2]
+
+    Returns:
+         A new IR where the qubit indices are replaced by the values passed in mapping.
+         E.g., for mapping = [3, 1, 0, 2]:
+         - Qubit(index=0) becomes Qubit(index=3),
+         - Qubit(index=1) becomes Qubit(index=1),
+         - Qubit(index=2) becomes Qubit(index=0), and
+         - Qubit(index=3) becomes Qubit(index=2).
+    """
+
+    def __init__(self, mapping: Mapping):
+        self.mapping = mapping
+
+    def visit_comment(self, comment: Comment):
+        return comment
+
+    def visit_qubit(self, qubit: Qubit):
+        qubit.index = self.mapping[qubit.index]
+        return qubit
+
+    def visit_measure(self, measure: Measure):
+        measure.qubit.accept(self)
+        return measure
+
+    def visit_bloch_sphere_rotation(self, g: BlochSphereRotation):
+        g.qubit.accept(self)
+        return g
+
+    def visit_matrix_gate(self, g: MatrixGate):
+        [op.accept(self) for op in g.operands]
+        return g
+
+    def visit_controlled_gate(self, controlled_gate: ControlledGate):
+        controlled_gate.control_qubit.accept(self)
+        controlled_gate.target_gate.accept(self)
+        return controlled_gate
+
+
+def get_remapped_ir(circuit: Circuit, mapping: Mapping) -> IR:
+    assert len(mapping) <= circuit.qubit_register_size
+    qubit_remapper = _QubitRemapper(mapping)
+    replacement_ir = circuit.ir
+    for statement in replacement_ir.statements:
+        statement.accept(qubit_remapper)
+    return replacement_ir
+
+
+def remap_ir(circuit: Circuit, mapping: Mapping) -> None:
+    assert len(mapping) <= circuit.qubit_register_size
+    qubit_remapper = _QubitRemapper(mapping)
+    for statement in circuit.ir.statements:
+        statement.accept(qubit_remapper)
diff --git a/opensquirrel/mapper/simple_mappers.py b/opensquirrel/mapper/simple_mappers.py
index 6d10f0c3..673f7767 100644
--- a/opensquirrel/mapper/simple_mappers.py
+++ b/opensquirrel/mapper/simple_mappers.py
@@ -4,56 +4,17 @@
 * HardcodedMapper
 """
 
-from __future__ import annotations
-
-from collections.abc import Mapping
-from typing import SupportsInt
-
 from opensquirrel.mapper.general_mapper import Mapper
-from opensquirrel.squirrel_ir import SquirrelIR
+from opensquirrel.mapper.mapping import Mapping
 
 
 class IdentityMapper(Mapper):
-
-    def map(self, squirrel_ir: SquirrelIR) -> dict[int, int]:
-        """Produce an IdentityMapping.
-
-        Args:
-            squirrel_ir: IR to map.
-
-        Returns:
-            Mapping from virtual qubits to physical qubits. Each virtual qubit is mapped to the physical qubit with
-            the same index.
-        """
-        return {i: i for i in range(squirrel_ir.number_of_qubits)}
+    def __init__(self, qubit_register_size: int) -> None:
+        """An ``IdentityMapper`` maps each virtual qubit to exactly the same physical qubit."""
+        super().__init__(qubit_register_size)
 
 
 class HardcodedMapper(Mapper):
-
-    def __init__(self, mapping: Mapping[SupportsInt, SupportsInt]) -> None:
-        """Init of the ``HardcodedMapper``.
-
-        Args:
-            mapping: Mapping with as keys the virtual qubits and as values the physical qubits.
-
-        Raises:
-            ValueError: If `mapping` is not a valid mapping.
-        """
-        # Check if the provided mapping is valid
-        self.mapping = {int(virtual_qubit): int(physical_qubit) for virtual_qubit, physical_qubit in mapping.items()}
-        if set(self.mapping.keys()) != set(self.mapping.values()):
-            raise ValueError("The set of physical qubits is not equal to the set of virtual qubits.")
-
-    def map(self, squirrel_ir: SquirrelIR) -> dict[int, int]:
-        """Retrieve the hardcoded mapping.
-
-        Args:
-            squirrel_ir: IR to apply mapping to.
-
-        Returns:
-            Mapping from virtual qubits to physical qubits.
-        """
-        if set(range(squirrel_ir.number_of_qubits)) != set(self.mapping.keys()):
-            raise ValueError("Virtual qubits are not labeled correctly.")
-
-        return self.mapping
+    def __init__(self, qubit_register_size: int, mapping: Mapping) -> None:
+        """A ``HardcodedMapper`` maps each virtual qubit to a hardcoded physical qubit"""
+        super().__init__(qubit_register_size, mapping)
diff --git a/opensquirrel/mapper/utils.py b/opensquirrel/mapper/utils.py
index 2efb0b5a..2a1503a6 100644
--- a/opensquirrel/mapper/utils.py
+++ b/opensquirrel/mapper/utils.py
@@ -1,12 +1,11 @@
 import networkx as nx
 
-from opensquirrel.squirrel_ir import Gate, SquirrelIR
+from opensquirrel.ir import IR, Gate
 
 
-def make_interaction_graph(squirrel_ir: SquirrelIR) -> nx.Graph:
-
+def make_interaction_graph(ir: IR) -> nx.Graph:
     interaction_graph = nx.Graph()
-    gates = (statement for statement in squirrel_ir.statements if isinstance(statement, Gate))
+    gates = (statement for statement in ir.statements if isinstance(statement, Gate))
 
     for gate in gates:
         target_qubits = gate.get_qubit_operands()
diff --git a/opensquirrel/merger/general_merger.py b/opensquirrel/merger/general_merger.py
index 09d206a7..0bfc6509 100644
--- a/opensquirrel/merger/general_merger.py
+++ b/opensquirrel/merger/general_merger.py
@@ -1,10 +1,10 @@
-import math
-from math import acos, cos, sin
+from math import acos, cos, floor, log, sin
 
 import numpy as np
 
+from opensquirrel.circuit import Circuit
 from opensquirrel.common import ATOL
-from opensquirrel.squirrel_ir import BlochSphereRotation, Gate, Measure, Qubit, SquirrelIR
+from opensquirrel.ir import BlochSphereRotation, Gate, Measure, Qubit
 
 
 def compose_bloch_sphere_rotations(a: BlochSphereRotation, b: BlochSphereRotation) -> BlochSphereRotation:
@@ -25,7 +25,7 @@ def compose_bloch_sphere_rotations(a: BlochSphereRotation, b: BlochSphereRotatio
     if abs(sin(combined_angle / 2)) < ATOL:
         return BlochSphereRotation.identity(a.qubit)
 
-    order_of_magnitude = abs(math.floor(math.log(ATOL, 10)))
+    order_of_magnitude = abs(floor(log(ATOL, 10)))
     combined_axis = np.round(
         (
             1
@@ -54,14 +54,19 @@ def compose_bloch_sphere_rotations(a: BlochSphereRotation, b: BlochSphereRotatio
     )
 
 
-def merge_single_qubit_gates(squirrel_ir: SquirrelIR):
+def merge_single_qubit_gates(circuit: Circuit):
+    """Merge all consecutive 1-qubit gates in the circuit.
+
+    Gates obtained from merging other gates become anonymous gates.
+    """
     accumulators_per_qubit: dict[Qubit, BlochSphereRotation] = {
-        Qubit(q): BlochSphereRotation.identity(Qubit(q)) for q in range(squirrel_ir.number_of_qubits)
+        Qubit(q): BlochSphereRotation.identity(Qubit(q)) for q in range(circuit.qubit_register_size)
     }
 
+    ir = circuit.ir
     statement_index = 0
-    while statement_index < len(squirrel_ir.statements):
-        statement = squirrel_ir.statements[statement_index]
+    while statement_index < len(ir.statements):
+        statement = ir.statements[statement_index]
 
         if not isinstance(statement, Gate) and not isinstance(statement, Measure):
             # Skip, since statement is not a gate or measurement
@@ -75,18 +80,19 @@ def merge_single_qubit_gates(squirrel_ir: SquirrelIR):
             composed = compose_bloch_sphere_rotations(statement, already_accumulated)
             accumulators_per_qubit[statement.qubit] = composed
 
-            del squirrel_ir.statements[statement_index]
+            del ir.statements[statement_index]
             continue
 
         for qubit_operand in statement.get_qubit_operands():
             if not accumulators_per_qubit[qubit_operand].is_identity():
-                squirrel_ir.statements.insert(statement_index, accumulators_per_qubit[qubit_operand])
+                ir.statements.insert(statement_index, accumulators_per_qubit[qubit_operand])
                 accumulators_per_qubit[qubit_operand] = BlochSphereRotation.identity(qubit_operand)
                 statement_index += 1
         statement_index += 1
 
     for accumulated_bloch_sphere_rotation in accumulators_per_qubit.values():
         if not accumulated_bloch_sphere_rotation.is_identity():
-            squirrel_ir.statements.append(accumulated_bloch_sphere_rotation)
-
-    squirrel_ir.statements = sorted(squirrel_ir.statements, key=lambda obj: isinstance(obj, Measure))
+            default_bloch = accumulated_bloch_sphere_rotation.get_default_bloch()
+            if default_bloch is not None:
+                accumulated_bloch_sphere_rotation = default_bloch
+            ir.statements.append(accumulated_bloch_sphere_rotation)
diff --git a/opensquirrel/parser/libqasm/libqasm_ir_creator.py b/opensquirrel/parser/libqasm/libqasm_ir_creator.py
deleted file mode 100644
index 3a862303..00000000
--- a/opensquirrel/parser/libqasm/libqasm_ir_creator.py
+++ /dev/null
@@ -1,146 +0,0 @@
-import inspect
-import itertools
-
-import cqasm.v3x as cqasm
-
-from opensquirrel.default_gates import default_gate_aliases, default_gate_set
-from opensquirrel.default_measurements import default_measurement_set
-from opensquirrel.instruction_library import GateLibrary, MeasurementLibrary
-from opensquirrel.squirrel_ir import Float, Int, Qubit, SquirrelIR
-
-_cqasm_type_to_squirrel_type = {
-    cqasm.types.QubitArray: Qubit,
-    cqasm.values.ConstInt: Int,
-    cqasm.values.ConstFloat: Float,
-}
-
-
-class LibqasmIRCreator(GateLibrary, MeasurementLibrary):
-    def __init__(
-        self,
-        gate_set=default_gate_set,
-        gate_aliases=default_gate_aliases,
-        measurement_set=default_measurement_set,
-    ):
-        GateLibrary.__init__(self, gate_set, gate_aliases)
-        MeasurementLibrary.__init__(self, measurement_set)
-        self.squirrel_ir = None
-
-    @staticmethod
-    def _get_qubits(cqasm_qubits_expression):
-        return [Qubit(index.value) for index in cqasm_qubits_expression.indices]
-
-    @staticmethod
-    def _get_literal(cqasm_literal_expression):
-        assert type(cqasm_literal_expression) in [cqasm.values.ConstInt, cqasm.values.ConstFloat]
-
-        if isinstance(cqasm_literal_expression, cqasm.values.ConstInt):
-            return Int(cqasm_literal_expression.value)
-
-        if isinstance(cqasm_literal_expression, cqasm.values.ConstFloat):
-            return Float(cqasm_literal_expression.value)
-
-        return None
-
-    @staticmethod
-    def _check_cqasm_type(cqasm_expression, expected_squirrel_type):
-        cqasm_type = (
-            type(cqasm_expression.variable.typ)
-            if isinstance(cqasm_expression, cqasm.values.IndexRef)
-            else type(cqasm_expression)
-        )
-
-        # The below is already guaranteed by Libqasm, therefore it's just an assert.
-        assert _cqasm_type_to_squirrel_type[cqasm_type] == expected_squirrel_type
-
-    @classmethod
-    def _get_expanded_squirrel_args(cls, generator_f, cqasm_args):
-        parameters = inspect.signature(generator_f).parameters.values()
-
-        ### The below is already guaranteed by LibQasm, therefore it's just an assert.
-        assert len(parameters) == len(cqasm_args)
-        for cqasm_arg, expected_parameter in zip(cqasm_args, parameters):
-            cls._check_cqasm_type(cqasm_expression=cqasm_arg, expected_squirrel_type=expected_parameter.annotation)
-
-        number_of_operands = next(
-            len(cqasm_arg.indices)
-            for cqasm_arg, expected_parameter in zip(cqasm_args, parameters)
-            if expected_parameter.annotation == Qubit
-        )
-
-        expanded_args = [
-            (
-                cls._get_qubits(cqasm_arg)
-                if expected_parameter.annotation == Qubit
-                else [cls._get_literal(cqasm_arg)] * number_of_operands
-            )
-            for cqasm_arg, expected_parameter in zip(cqasm_args, parameters)
-        ]
-
-        return zip(*expanded_args)
-
-    @staticmethod
-    def _get_cqasm_param_type_letters(squirrel_type):
-        if squirrel_type == Qubit:
-            return "Q", "V"  # "V" is to allow array notations like q[3, 5, 7] and q[3:6]
-
-        if squirrel_type == Float:
-            return "f"
-
-        if squirrel_type == Int:
-            return "i"
-
-        raise TypeError("Unsupported type")
-
-    def _create_analyzer(self):
-        without_defaults = True
-        analyzer = cqasm.Analyzer("3.0.0", without_defaults)
-        for generator_f in self.gate_set:
-            for set_of_letters in itertools.product(
-                *(
-                    self._get_cqasm_param_type_letters(p.annotation)
-                    for p in inspect.signature(generator_f).parameters.values()
-                )
-            ):
-                param_types = "".join(set_of_letters)
-                analyzer.register_instruction(generator_f.__name__, param_types)
-
-        for generator_f in self.measurement_set:
-            for set_of_letters in itertools.product(
-                *(
-                    self._get_cqasm_param_type_letters(p.annotation)
-                    for p in inspect.signature(generator_f).parameters.values()
-                )
-            ):
-                param_types = "".join(set_of_letters)
-                analyzer.register_instruction(generator_f.__name__, param_types)
-
-        return analyzer
-
-    def squirrel_ir_from_string(self, s: str):
-        analyzer = self._create_analyzer()
-
-        ast = analyzer.analyze_string(s)
-
-        if isinstance(ast, list):
-            raise Exception("Parsing error: " + ", ".join(ast))
-
-        number_of_qubits = ast.qubit_variable_declaration.typ.size
-
-        # FIXME: libqasm should return bytes, not the __repr__ of a bytes object ("b'q'")
-        qubit_register_name = ast.qubit_variable_declaration.name[2:-1]
-
-        squirrel_ir = SquirrelIR(number_of_qubits=number_of_qubits, qubit_register_name=qubit_register_name)
-
-        for statement in ast.block.statements:
-            if "measure" in statement.name[2:-1]:
-                generator_f = self.get_measurement_f(statement.name[2:-1])
-            else:
-                generator_f = self.get_gate_f(statement.name[2:-1])
-
-            expanded_squirrel_args = LibqasmIRCreator._get_expanded_squirrel_args(generator_f, statement.operands)
-
-            for arg_set in expanded_squirrel_args:
-                squirrel_ir.add_gate(generator_f(*arg_set))
-
-        return squirrel_ir
diff --git a/opensquirrel/parser/libqasm/parser.py b/opensquirrel/parser/libqasm/parser.py
new file mode 100644
index 00000000..4a8eb158
--- /dev/null
+++ b/opensquirrel/parser/libqasm/parser.py
@@ -0,0 +1,144 @@
+import inspect
+import itertools
+
+import cqasm.v3x as cqasm
+
+from opensquirrel.circuit import Circuit
+from opensquirrel.default_gates import default_gate_aliases, default_gate_set
+from opensquirrel.default_measurements import default_measurement_set
+from opensquirrel.instruction_library import GateLibrary, MeasurementLibrary
+from opensquirrel.ir import IR, Float, Int, Qubit
+from opensquirrel.register_manager import RegisterManager
+
+
+class Parser(GateLibrary, MeasurementLibrary):
+    def __init__(
+        self,
+        gate_set=default_gate_set,
+        gate_aliases=default_gate_aliases,
+        measurement_set=default_measurement_set,
+    ):
+        GateLibrary.__init__(self, gate_set, gate_aliases)
+        MeasurementLibrary.__init__(self, measurement_set)
+        self.ir = None
+
+    @staticmethod
+    def _parse_ast_string(string):
+        # FIXME: libqasm should return bytes, not the __repr__ of a bytes object ("b'q'")
+        return string[2:-1]
+
+    @staticmethod
+    def _ast_literal_to_ir_literal(cqasm_literal_expression):
+        assert type(cqasm_literal_expression) in [cqasm.values.ConstInt, cqasm.values.ConstFloat]
+        if isinstance(cqasm_literal_expression, cqasm.values.ConstInt):
+            return Int(cqasm_literal_expression.value)
+        if isinstance(cqasm_literal_expression, cqasm.values.ConstFloat):
+            return Float(cqasm_literal_expression.value)
+        return None
+
+    @staticmethod
+    def _type_of(ast_expression):
+        if isinstance(ast_expression, cqasm.values.IndexRef) or isinstance(ast_expression, cqasm.values.VariableRef):
+            return type(ast_expression.variable.typ)
+        else:
+            return type(ast_expression)
+
+    @staticmethod
+    def _size_of(ast_expression) -> int:
+        if isinstance(ast_expression, cqasm.values.IndexRef):
+            return len(ast_expression.indices)
+        elif isinstance(ast_expression, cqasm.values.VariableRef):
+            return int(ast_expression.variable.typ.size)
+        else:
+            return 1
+
+    @staticmethod
+    def _is_qubit_type(ast_expression):
+        ast_type = Parser._type_of(ast_expression)
+        return ast_type == cqasm.types.Qubit or ast_type == cqasm.types.QubitArray
+
+    @staticmethod
+    def _is_bit_type(ast_expression):
+        ast_type = Parser._type_of(ast_expression)
+        return ast_type == cqasm.types.Bit or ast_type == cqasm.types.BitArray
+
+    @staticmethod
+    def _get_qubits(ast_qubit_expression, register_manager):
+        ret = []
+        variable_name = Parser._parse_ast_string(ast_qubit_expression.variable.name)
+        if isinstance(ast_qubit_expression, cqasm.values.VariableRef):
+            qubit_range = register_manager.get_qubit_range(variable_name)
+            ret = [Qubit(index) for index in range(qubit_range.first, qubit_range.first + qubit_range.size)]
+        if isinstance(ast_qubit_expression, cqasm.values.IndexRef):
+            indices = [int(i.value) for i in ast_qubit_expression.indices]
+            ret = [Qubit(index) for index in register_manager.get_qubit_indices(variable_name, indices)]
+        return ret
+
+    @classmethod
+    def _get_expanded_statement_args(cls, ast_args, register_manager):
+        number_of_operands = 0
+        for ast_arg in ast_args:
+            if Parser._is_qubit_type(ast_arg):
+                number_of_operands += Parser._size_of(ast_arg)
+        expanded_args = []
+        for ast_arg in ast_args:
+            if Parser._is_qubit_type(ast_arg):
+                expanded_args.append(cls._get_qubits(ast_arg, register_manager))
+            elif not Parser._is_bit_type(ast_arg):
+                expanded_args.append([cls._ast_literal_to_ir_literal(ast_arg)] * number_of_operands)
+            else:  # Bit type
+                pass
+        return zip(*expanded_args)
+
+    @staticmethod
+    def _get_cqasm_param_type_letters(squirrel_type):
+        if squirrel_type == Qubit:
+            return "Q", "V"  # "V" is to allow array notations like q[3, 5, 7] and q[3:6]
+
+        if squirrel_type == Float:
+            return "f"
+
+        if squirrel_type == Int:
+            return "i"
+
+        raise TypeError("Unsupported type")
+
+    def _create_analyzer(self):
+        # TODO: we are temporarily using the default analyzer,
+        # mainly because there is a misalignment between the AST and the IR measure nodes
+        # The AST currently produces measure nodes with a bit argument,
+        # but the IR doesn't consider yet that bit argument
+        # In the future, we may want to go back to no using the default analyzer again,
+        # so that all gates are registered based on OpenSquirrel's default gate set
+        without_defaults = False
+        analyzer = cqasm.Analyzer("3.0", without_defaults)
+        return analyzer
+
+    @staticmethod
+    def _check_analysis_result(result):
+        if isinstance(result, list):
+            raise Exception("Parsing error: " + ", ".join(result))
+
+    def circuit_from_string(self, s: str):
+        # Analysis result will be either an Abstract Syntax Tree (AST) or a list of error messages
+        analyzer = self._create_analyzer()
+        analysis_result = analyzer.analyze_string(s)
+        Parser._check_analysis_result(analysis_result)
+        ast = analysis_result
+
+        # Create RegisterManager
+        register_manager = RegisterManager.from_ast(ast)
+
+        # Parse statements
+        ir = IR()
+        for statement in ast.block.statements:
+            statement_name = self._parse_ast_string(statement.name)
+            if "measure" in statement_name:
+                generator_f = self.get_measurement_f(statement_name)
+            else:
+                generator_f = self.get_gate_f(statement_name)
+            expanded_args = Parser._get_expanded_statement_args(statement.operands, register_manager)
+            for arg_set in expanded_args:
+                ir.add_gate(generator_f(*arg_set))
+
+        return Circuit(register_manager, ir)
diff --git a/opensquirrel/register_manager.py b/opensquirrel/register_manager.py
new file mode 100644
index 00000000..8b94649a
--- /dev/null
+++ b/opensquirrel/register_manager.py
@@ -0,0 +1,100 @@
+from dataclasses import dataclass
+from typing import Dict, List
+
+import cqasm.v3x as cqasm
+
+from opensquirrel.mapper import Mapper
+
+
+def is_qubit_type(variable):
+    return isinstance(variable.typ, cqasm.types.Qubit) or isinstance(variable.typ, cqasm.types.QubitArray)
+
+
+@dataclass
+class QubitRange:
+    first: int = 0
+    size: int = 0
+
+
+class RegisterManager:
+    """RegisterManager keeps track of a (virtual) qubit register, i.e., an array of consecutive qubits,
+    and the mappings between the (logical) qubit variable names, as used in an input cQASM program,
+    and the (virtual) qubit register.
+
+    For example, given an input program that defines 'qubit[3] q':
+    - variable 'q' is mapped to qubits 0 to 2 in the qubit register, and
+    - positions 0 to 2 in the qubit register are mapped to variable 'q'.
+
+    The mapping of qubit variable names to positions in the qubit register is an implementation detail,
+    i.e., it is not guaranteed that qubit register indices are assigned to qubit variable names in the order
+    these variables are defined in the input program.
+    """
+
+    # TODO:
+    # In the future, when variables of different types can be defined (e.g. float q)
+    # we will have to prevent a variable being called 'q' or 'b'.
+    # A possible way to do this is to introduce variable name mangling in the IR
+    # (e.g., store 'float q' as 'float _float__q')
+    _default_qubit_register_name = "q"
+
+    def __init__(
+        self,
+        qubit_register_size: int,
+        variable_name_to_qubit_range: Dict[str, QubitRange] = dict(),
+        qubit_index_to_variable_name: Dict[int, str] = dict(),
+    ) -> None:
+        self.qubit_register_size = qubit_register_size
+        self.qubit_register_name = self._default_qubit_register_name
+        self.variable_name_to_qubit_range = variable_name_to_qubit_range
+        self.qubit_index_to_variable_name = qubit_index_to_variable_name
+
+    def __repr__(self) -> str:
+        return (
+            f"qubit_register_size: {self.qubit_register_size}\n"
+            + f"variable_name_to_qubit_range: {self.variable_name_to_qubit_range}\n"
+            + f"qubit_index_to_variable_name: {self.qubit_index_to_variable_name}"
+        )
+
+    @staticmethod
+    def _parse_ast_string(string):
+        # FIXME: libqasm should return bytes, not the __repr__ of a bytes object ("b'q'")
+        return string[2:-1]
+
+    @classmethod
+    def from_ast(cls, ast):
+        qubit_register_size: int = 0
+        variable_name_to_qubit_range: Dict[str, QubitRange] = dict()
+        qubit_index_to_variable_name: Dict[int, str] = dict()
+
+        qubit_variables = [v for v in ast.variables if is_qubit_type(v)]
+        qubit_register_size = sum([qv.typ.size for qv in qubit_variables])
+        current_qubit_index: int = 0
+        for qv in qubit_variables:
+            qv_name = RegisterManager._parse_ast_string(qv.name)
+            qv_size = qv.typ.size
+            variable_name_to_qubit_range[qv_name] = QubitRange(current_qubit_index, qv_size)
+            for _ in range(qv_size):
+                qubit_index_to_variable_name[current_qubit_index] = qv_name
+                current_qubit_index += 1
+        return cls(qubit_register_size, variable_name_to_qubit_range, qubit_index_to_variable_name)
+
+    def __eq__(self, other):
+        return (
+            self.qubit_register_size == other.qubit_register_size
+            and self.qubit_register_name == other.qubit_register_name
+            and self.variable_name_to_qubit_range == other.variable_name_to_qubit_range
+            and self.qubit_index_to_variable_name == other.qubit_index_to_variable_name
+        )
+
+    def get_qubit_register_size(self) -> int:
+        return self.qubit_register_size
+
+    def get_qubit_range(self, variable_name: str) -> QubitRange:
+        return self.variable_name_to_qubit_range[variable_name]
+
+    def get_qubit_indices(self, variable_name: str, indices: List[int]) -> List[int]:
+        start_index = self.get_qubit_range(variable_name).first
+        return [start_index + i for i in indices]
+
+    def get_variable_name(self, index: int) -> str:
+        return self.qubit_register_name[index]
diff --git a/opensquirrel/reindexer/__init__.py b/opensquirrel/reindexer/__init__.py
new file mode 100644
index 00000000..bd1322af
--- /dev/null
+++ b/opensquirrel/reindexer/__init__.py
@@ -0,0 +1,3 @@
+from opensquirrel.reindexer.qubit_reindexer import _QubitReindexer, get_reindexed_circuit
+
+__all__ = ["_QubitReindexer", "get_reindexed_circuit"]
diff --git a/opensquirrel/reindexer/qubit_reindexer.py b/opensquirrel/reindexer/qubit_reindexer.py
new file mode 100644
index 00000000..f53f6a2a
--- /dev/null
+++ b/opensquirrel/reindexer/qubit_reindexer.py
@@ -0,0 +1,61 @@
+from typing import List
+
+from opensquirrel.circuit import Circuit
+from opensquirrel.ir import (
+    IR,
+    BlochSphereRotation,
+    Comment,
+    ControlledGate,
+    Gate,
+    IRVisitor,
+    MatrixGate,
+    Measure,
+    Qubit,
+)
+from opensquirrel.mapper.mapping import Mapping
+from opensquirrel.register_manager import RegisterManager
+
+
+class _QubitReindexer(IRVisitor):
+    """
+    Reindex a whole IR.
+
+    Args:
+        qubit_indices: a list of qubit indices, e.g. [3, 1]
+
+    Returns:
+         A new IR where the qubit indices are replaced by their positions in qubit indices.
+         E.g., for mapping = [3, 1]:
+         - Qubit(index=1) becomes Qubit(index=1), and
+         - Qubit(index=3) becomes Qubit(index=0).
+    """
+
+    def __init__(self, qubit_indices: List[int]):
+        self.qubit_indices = qubit_indices
+
+    def visit_measure(self, measure: Measure):
+        return Measure(qubit=Qubit(self.qubit_indices.index(measure.qubit.index)), axis=measure.axis)
+
+    def visit_bloch_sphere_rotation(self, g: BlochSphereRotation):
+        return BlochSphereRotation(
+            qubit=Qubit(self.qubit_indices.index(g.qubit.index)), angle=g.angle, axis=g.axis, phase=g.phase
+        )
+
+    def visit_matrix_gate(self, g: MatrixGate):
+        reindexed_operands = [Qubit(self.qubit_indices.index(op.index)) for op in g.operands]
+        return MatrixGate(matrix=g.matrix, operands=reindexed_operands)
+
+    def visit_controlled_gate(self, controlled_gate: ControlledGate):
+        control_qubit = Qubit(self.qubit_indices.index(controlled_gate.control_qubit.index))
+        target_gate = controlled_gate.target_gate.accept(self)
+        return ControlledGate(control_qubit=control_qubit, target_gate=target_gate)
+
+
+def get_reindexed_circuit(replacement_gates: List[Gate], qubit_indices: List[int]) -> Circuit:
+    qubit_reindexer = _QubitReindexer(qubit_indices)
+    register_manager = RegisterManager(qubit_register_size=len(qubit_indices))
+    replacement_ir = IR()
+    for gate in replacement_gates:
+        gate_with_reindexed_qubits = gate.accept(qubit_reindexer)
+        replacement_ir.add_gate(gate_with_reindexed_qubits)
+    return Circuit(register_manager, replacement_ir)
diff --git a/opensquirrel/utils/__init__.py b/opensquirrel/utils/__init__.py
index c81ad40d..b159fe59 100644
--- a/opensquirrel/utils/__init__.py
+++ b/opensquirrel/utils/__init__.py
@@ -1,3 +1,3 @@
-from opensquirrel.utils.matrix_expander import get_matrix, get_matrix_after_qubit_remapping
+from opensquirrel.utils.matrix_expander import get_matrix
 
-__all__ = ["get_matrix", "get_matrix_after_qubit_remapping"]
+__all__ = ["get_matrix"]
diff --git a/opensquirrel/utils/check_passes/check_mapper.py b/opensquirrel/utils/check_passes/check_mapper.py
index 56265db7..d38dad06 100644
--- a/opensquirrel/utils/check_passes/check_mapper.py
+++ b/opensquirrel/utils/check_passes/check_mapper.py
@@ -4,58 +4,44 @@
 
 from copy import deepcopy
 
+from opensquirrel.circuit import Circuit
+from opensquirrel.ir import IR, BlochSphereRotation, Comment, ControlledGate, Measure, Qubit
 from opensquirrel.mapper.general_mapper import Mapper
-from opensquirrel.squirrel_ir import BlochSphereRotation, Comment, ControlledGate, Measure, Qubit, SquirrelIR
+from opensquirrel.mapper.mapping import Mapping
+from opensquirrel.register_manager import RegisterManager
 
 
 def check_mapper(mapper: Mapper) -> None:
     """Check if the `mapper` complies with the OpenSquirrel requirements.
 
-    If an implementation of ``Mapper`` passes these checks it should be compatible with the ``Circuit.map_qubits``
-    method.
+    If an implementation of ``Mapper`` passes these checks it should be compatible with the ``Circuit.map`` method.
 
     Args:
         mapper: Mapper to check.
     """
-
     assert isinstance(mapper, Mapper)
 
-    squirrel_ir = SquirrelIR(number_of_qubits=10)
-    _check_scenario(squirrel_ir, mapper)
+    register_manager = RegisterManager(qubit_register_size=10)
+    ir = IR()
+    circuit = Circuit(register_manager, ir)
+    _check_scenario(circuit, mapper)
 
-    squirrel_ir = SquirrelIR(number_of_qubits=10)
-    squirrel_ir.add_comment(Comment("comment"))
-    squirrel_ir.add_gate(BlochSphereRotation(Qubit(42), (1, 0, 0), 1, 2))
-    squirrel_ir.add_gate(ControlledGate(Qubit(42), BlochSphereRotation.identity(Qubit(100))))
-    squirrel_ir.add_measurement(Measure(Qubit(42), (0, 0, 1)))
-    _check_scenario(squirrel_ir, mapper)
+    ir = IR()
+    ir.add_comment(Comment("comment"))
+    ir.add_gate(BlochSphereRotation(Qubit(42), (1, 0, 0), 1, 2))
+    ir.add_gate(ControlledGate(Qubit(42), BlochSphereRotation.identity(Qubit(100))))
+    ir.add_measurement(Measure(Qubit(42), (0, 0, 1)))
+    Circuit(register_manager, ir)
+    _check_scenario(circuit, mapper)
 
 
-def _check_scenario(squirrel_ir: SquirrelIR, mapper: Mapper) -> None:
+def _check_scenario(circuit: Circuit, mapper: Mapper) -> None:
     """Check if the given scenario can be mapped.
 
     Args:
-        squirrel_ir: SquirrelIR containing the scenario to check against.
-        mapping: Mapping to check.
-    """
-    squirrel_ir_copy = deepcopy(squirrel_ir)
-    mapping = mapper.map(squirrel_ir)
-
-    assert squirrel_ir == squirrel_ir_copy, "A Mapper pass should not change the SquirrelIR."
-    _check_mapping_format(mapping, squirrel_ir.number_of_qubits)
-
-
-def _check_mapping_format(mapping: dict[int, int], number_of_qubits: int) -> None:
-    """Check if the mapping has the expected format.
-
-    Args:
-        mapping: Mapping to check.
-        n_qubits: Number of qubits in the circuit.
+        circuit: Circuit containing the scenario to check against.
+        mapper: Mapper to use.
     """
-    assert isinstance(
-        mapping, dict
-    ), f"Output mapping should be an instance of <class 'dict'>, but was of type {type(mapping)}"
-    assert set(mapping.keys()) == set(
-        mapping.values()
-    ), "The set of virtual qubits is not equal to the set of phyical qubits."
-    assert set(range(number_of_qubits)) == set(mapping.keys()), "Virtual qubits are not labeled correctly."
+    ir_copy = deepcopy(circuit.ir)
+    circuit.map(mapper)
+    assert circuit.ir == ir_copy, "A Mapper pass should not change the IR"
diff --git a/opensquirrel/utils/identity_filter.py b/opensquirrel/utils/identity_filter.py
index e829d858..eee12e29 100644
--- a/opensquirrel/utils/identity_filter.py
+++ b/opensquirrel/utils/identity_filter.py
@@ -1,4 +1,4 @@
-from opensquirrel.squirrel_ir import Gate
+from opensquirrel.ir import Gate
 
 
 def filter_out_identities(l: [Gate]):
diff --git a/opensquirrel/utils/matrix_expander.py b/opensquirrel/utils/matrix_expander.py
index 297fd7fc..27be827a 100644
--- a/opensquirrel/utils/matrix_expander.py
+++ b/opensquirrel/utils/matrix_expander.py
@@ -3,9 +3,9 @@
 
 import numpy as np
 
+from opensquirrel.circuit import Circuit
 from opensquirrel.common import can1
-from opensquirrel.decomposer.general_decomposer import _QubitReIndexer
-from opensquirrel.squirrel_ir import BlochSphereRotation, ControlledGate, Gate, Qubit, SquirrelIR, SquirrelIRVisitor
+from opensquirrel.ir import IR, BlochSphereRotation, ControlledGate, Gate, IRVisitor, Qubit
 
 
 def get_reduced_ket(ket: int, qubits: List[Qubit]) -> int:
@@ -87,22 +87,24 @@ def expand_ket(base_ket: int, reduced_ket: int, qubits: List[Qubit]) -> int:
     return expanded_ket
 
 
-class MatrixExpander(SquirrelIRVisitor):
-    def __init__(self, number_of_qubits: int):
-        self.number_of_qubits = number_of_qubits
+class MatrixExpander(IRVisitor):
+    def __init__(self, qubit_register_size: int):
+        self.qubit_register_size = qubit_register_size
 
     def visit_bloch_sphere_rotation(self, rot):
-        assert rot.qubit.index < self.number_of_qubits
+        assert rot.qubit.index < self.qubit_register_size
 
         result = np.kron(
-            np.kron(np.eye(1 << (self.number_of_qubits - rot.qubit.index - 1)), can1(rot.axis, rot.angle, rot.phase)),
+            np.kron(
+                np.eye(1 << (self.qubit_register_size - rot.qubit.index - 1)), can1(rot.axis, rot.angle, rot.phase)
+            ),
             np.eye(1 << rot.qubit.index),
         )
-        assert result.shape == (1 << self.number_of_qubits, 1 << self.number_of_qubits)
+        assert result.shape == (1 << self.qubit_register_size, 1 << self.qubit_register_size)
         return result
 
     def visit_controlled_gate(self, gate):
-        assert gate.control_qubit.index < self.number_of_qubits
+        assert gate.control_qubit.index < self.qubit_register_size
 
         expanded_matrix = gate.target_gate.accept(self)
         for col_index, col in enumerate(expanded_matrix.T):
@@ -122,13 +124,13 @@ def visit_matrix_gate(self, gate):
         # since qubit #i corresponds to the i-th LEAST significant bit.
         qubit_operands = list(reversed(gate.operands))
 
-        assert all(q.index < self.number_of_qubits for q in qubit_operands)
+        assert all(q.index < self.qubit_register_size for q in qubit_operands)
 
         m = gate.matrix
 
         assert m.shape == (1 << len(qubit_operands), 1 << len(qubit_operands))
 
-        expanded_matrix = np.zeros((1 << self.number_of_qubits, 1 << self.number_of_qubits), dtype=m.dtype)
+        expanded_matrix = np.zeros((1 << self.qubit_register_size, 1 << self.qubit_register_size), dtype=m.dtype)
 
         for expanded_matrix_column in range(expanded_matrix.shape[1]):
             small_matrix_col = get_reduced_ket(expanded_matrix_column, qubit_operands)
@@ -137,11 +139,11 @@ def visit_matrix_gate(self, gate):
                 expanded_matrix_row = expand_ket(expanded_matrix_column, small_matrix_row, qubit_operands)
                 expanded_matrix[expanded_matrix_row][expanded_matrix_column] = value
 
-        assert expanded_matrix.shape == (1 << self.number_of_qubits, 1 << self.number_of_qubits)
+        assert expanded_matrix.shape == (1 << self.qubit_register_size, 1 << self.qubit_register_size)
         return expanded_matrix
 
 
-def get_matrix(gate: Gate, number_of_qubits: int) -> np.ndarray:
+def get_matrix(gate: Gate, qubit_register_size: int) -> np.ndarray:
     """
     Compute the unitary matrix corresponding to the gate applied to those qubit operands, taken among any number of
     qubits. This can be used for, e.g.,
@@ -151,7 +153,7 @@ def get_matrix(gate: Gate, number_of_qubits: int) -> np.ndarray:
 
     Args:
         gate: The gate, including the qubits on which it is operated on.
-        number_of_qubits: The total number of qubits.
+        qubit_register_size: The size of the qubit register.
 
     Examples:
         >>> X = lambda q: BlochSphereRotation(qubit=q, axis=(1, 0, 0), angle=math.pi, phase=math.pi / 2)
@@ -182,17 +184,5 @@ def get_matrix(gate: Gate, number_of_qubits: int) -> np.ndarray:
                [0, 0, 0, 1, 0, 0, 0, 0]])
     """
 
-    expander = MatrixExpander(number_of_qubits)
+    expander = MatrixExpander(qubit_register_size)
     return gate.accept(expander)
-
-
-def get_matrix_after_qubit_remapping(replacement: List[Gate], qubit_mappings: List[Qubit]):
-    from opensquirrel.circuit_matrix_calculator import get_circuit_matrix
-
-    replacement_ir = SquirrelIR(number_of_qubits=len(qubit_mappings), qubit_register_name="q_temp")
-    qubit_remapper = _QubitReIndexer(qubit_mappings)
-    for gate in replacement:
-        gate_with_remapped_qubits = gate.accept(qubit_remapper)
-        replacement_ir.add_gate(gate_with_remapped_qubits)
-
-    return get_circuit_matrix(replacement_ir)
diff --git a/poetry.lock b/poetry.lock
index 160e0ce1..a547aa89 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -78,13 +78,13 @@ test = ["coverage", "pytest", "pytest-cov"]
 
 [[package]]
 name = "astroid"
-version = "3.1.0"
+version = "3.2.1"
 description = "An abstract syntax tree for Python with inference support."
 optional = false
 python-versions = ">=3.8.0"
 files = [
-    {file = "astroid-3.1.0-py3-none-any.whl", hash = "sha256:951798f922990137ac090c53af473db7ab4e70c770e6d7fae0cec59f74411819"},
-    {file = "astroid-3.1.0.tar.gz", hash = "sha256:ac248253bfa4bd924a0de213707e7ebeeb3138abeb48d798784ead1e56d419d4"},
+    {file = "astroid-3.2.1-py3-none-any.whl", hash = "sha256:b452064132234819f023b94f4bd045b250ea0009f372b4377cfcd87f10806ca5"},
+    {file = "astroid-3.2.1.tar.gz", hash = "sha256:902564b36796ba1eab3ad2c7a694861fbd926f574d5dbb5fa1d86778a2ba2d91"},
 ]
 
 [package.dependencies]
@@ -180,13 +180,13 @@ msal-extensions = ">=0.3.0"
 
 [[package]]
 name = "babel"
-version = "2.14.0"
+version = "2.15.0"
 description = "Internationalization utilities"
 optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
 files = [
-    {file = "Babel-2.14.0-py3-none-any.whl", hash = "sha256:efb1a25b7118e67ce3a259bed20545c29cb68be8ad2c784c83689981b7a57287"},
-    {file = "Babel-2.14.0.tar.gz", hash = "sha256:6919867db036398ba21eb5c7a0f6b28ab8cbc3ae7a73a44ebe34ae74a4e7d363"},
+    {file = "Babel-2.15.0-py3-none-any.whl", hash = "sha256:08706bdad8d0a3413266ab61bd6c34d0c28d6e1e7badf40a2cebe67644e2e1fb"},
+    {file = "babel-2.15.0.tar.gz", hash = "sha256:8daf0e265d05768bc6c7a314cf1321e9a123afc328cc635c18622a2f30a04413"},
 ]
 
 [package.dependencies]
@@ -525,17 +525,6 @@ traitlets = ">=4"
 [package.extras]
 test = ["pytest"]
 
-[[package]]
-name = "contextlib2"
-version = "21.6.0"
-description = "Backports and enhancements for the contextlib module"
-optional = false
-python-versions = ">=3.6"
-files = [
-    {file = "contextlib2-21.6.0-py2.py3-none-any.whl", hash = "sha256:3fbdb64466afd23abaf6c977627b75b6139a5a3e8ce38405c5b413aed7a0471f"},
-    {file = "contextlib2-21.6.0.tar.gz", hash = "sha256:ab1e2bfe1d01d968e1b7e8d9023bc51ef3509bba217bb730cee3827e1ee82869"},
-]
-
 [[package]]
 name = "contourpy"
 version = "1.1.1"
@@ -609,63 +598,63 @@ test-no-images = ["pytest", "pytest-cov", "wurlitzer"]
 
 [[package]]
 name = "coverage"
-version = "7.5.0"
+version = "7.5.1"
 description = "Code coverage measurement for Python"
 optional = false
 python-versions = ">=3.8"
 files = [
-    {file = "coverage-7.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:432949a32c3e3f820af808db1833d6d1631664d53dd3ce487aa25d574e18ad1c"},
-    {file = "coverage-7.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2bd7065249703cbeb6d4ce679c734bef0ee69baa7bff9724361ada04a15b7e3b"},
-    {file = "coverage-7.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbfe6389c5522b99768a93d89aca52ef92310a96b99782973b9d11e80511f932"},
-    {file = "coverage-7.5.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:39793731182c4be939b4be0cdecde074b833f6171313cf53481f869937129ed3"},
-    {file = "coverage-7.5.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85a5dbe1ba1bf38d6c63b6d2c42132d45cbee6d9f0c51b52c59aa4afba057517"},
-    {file = "coverage-7.5.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:357754dcdfd811462a725e7501a9b4556388e8ecf66e79df6f4b988fa3d0b39a"},
-    {file = "coverage-7.5.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a81eb64feded34f40c8986869a2f764f0fe2db58c0530d3a4afbcde50f314880"},
-    {file = "coverage-7.5.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:51431d0abbed3a868e967f8257c5faf283d41ec882f58413cf295a389bb22e58"},
-    {file = "coverage-7.5.0-cp310-cp310-win32.whl", hash = "sha256:f609ebcb0242d84b7adeee2b06c11a2ddaec5464d21888b2c8255f5fd6a98ae4"},
-    {file = "coverage-7.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:6782cd6216fab5a83216cc39f13ebe30adfac2fa72688c5a4d8d180cd52e8f6a"},
-    {file = "coverage-7.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e768d870801f68c74c2b669fc909839660180c366501d4cc4b87efd6b0eee375"},
-    {file = "coverage-7.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:84921b10aeb2dd453247fd10de22907984eaf80901b578a5cf0bb1e279a587cb"},
-    {file = "coverage-7.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:710c62b6e35a9a766b99b15cdc56d5aeda0914edae8bb467e9c355f75d14ee95"},
-    {file = "coverage-7.5.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c379cdd3efc0658e652a14112d51a7668f6bfca7445c5a10dee7eabecabba19d"},
-    {file = "coverage-7.5.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fea9d3ca80bcf17edb2c08a4704259dadac196fe5e9274067e7a20511fad1743"},
-    {file = "coverage-7.5.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:41327143c5b1d715f5f98a397608f90ab9ebba606ae4e6f3389c2145410c52b1"},
-    {file = "coverage-7.5.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:565b2e82d0968c977e0b0f7cbf25fd06d78d4856289abc79694c8edcce6eb2de"},
-    {file = "coverage-7.5.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cf3539007202ebfe03923128fedfdd245db5860a36810136ad95a564a2fdffff"},
-    {file = "coverage-7.5.0-cp311-cp311-win32.whl", hash = "sha256:bf0b4b8d9caa8d64df838e0f8dcf68fb570c5733b726d1494b87f3da85db3a2d"},
-    {file = "coverage-7.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:9c6384cc90e37cfb60435bbbe0488444e54b98700f727f16f64d8bfda0b84656"},
-    {file = "coverage-7.5.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fed7a72d54bd52f4aeb6c6e951f363903bd7d70bc1cad64dd1f087980d309ab9"},
-    {file = "coverage-7.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cbe6581fcff7c8e262eb574244f81f5faaea539e712a058e6707a9d272fe5b64"},
-    {file = "coverage-7.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad97ec0da94b378e593ef532b980c15e377df9b9608c7c6da3506953182398af"},
-    {file = "coverage-7.5.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bd4bacd62aa2f1a1627352fe68885d6ee694bdaebb16038b6e680f2924a9b2cc"},
-    {file = "coverage-7.5.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:adf032b6c105881f9d77fa17d9eebe0ad1f9bfb2ad25777811f97c5362aa07f2"},
-    {file = "coverage-7.5.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4ba01d9ba112b55bfa4b24808ec431197bb34f09f66f7cb4fd0258ff9d3711b1"},
-    {file = "coverage-7.5.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:f0bfe42523893c188e9616d853c47685e1c575fe25f737adf473d0405dcfa7eb"},
-    {file = "coverage-7.5.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a9a7ef30a1b02547c1b23fa9a5564f03c9982fc71eb2ecb7f98c96d7a0db5cf2"},
-    {file = "coverage-7.5.0-cp312-cp312-win32.whl", hash = "sha256:3c2b77f295edb9fcdb6a250f83e6481c679335ca7e6e4a955e4290350f2d22a4"},
-    {file = "coverage-7.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:427e1e627b0963ac02d7c8730ca6d935df10280d230508c0ba059505e9233475"},
-    {file = "coverage-7.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9dd88fce54abbdbf4c42fb1fea0e498973d07816f24c0e27a1ecaf91883ce69e"},
-    {file = "coverage-7.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a898c11dca8f8c97b467138004a30133974aacd572818c383596f8d5b2eb04a9"},
-    {file = "coverage-7.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:07dfdd492d645eea1bd70fb1d6febdcf47db178b0d99161d8e4eed18e7f62fe7"},
-    {file = "coverage-7.5.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d3d117890b6eee85887b1eed41eefe2e598ad6e40523d9f94c4c4b213258e4a4"},
-    {file = "coverage-7.5.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6afd2e84e7da40fe23ca588379f815fb6dbbb1b757c883935ed11647205111cb"},
-    {file = "coverage-7.5.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a9960dd1891b2ddf13a7fe45339cd59ecee3abb6b8326d8b932d0c5da208104f"},
-    {file = "coverage-7.5.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ced268e82af993d7801a9db2dbc1d2322e786c5dc76295d8e89473d46c6b84d4"},
-    {file = "coverage-7.5.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e7c211f25777746d468d76f11719e64acb40eed410d81c26cefac641975beb88"},
-    {file = "coverage-7.5.0-cp38-cp38-win32.whl", hash = "sha256:262fffc1f6c1a26125d5d573e1ec379285a3723363f3bd9c83923c9593a2ac25"},
-    {file = "coverage-7.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:eed462b4541c540d63ab57b3fc69e7d8c84d5957668854ee4e408b50e92ce26a"},
-    {file = "coverage-7.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d0194d654e360b3e6cc9b774e83235bae6b9b2cac3be09040880bb0e8a88f4a1"},
-    {file = "coverage-7.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:33c020d3322662e74bc507fb11488773a96894aa82a622c35a5a28673c0c26f5"},
-    {file = "coverage-7.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cbdf2cae14a06827bec50bd58e49249452d211d9caddd8bd80e35b53cb04631"},
-    {file = "coverage-7.5.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3235d7c781232e525b0761730e052388a01548bd7f67d0067a253887c6e8df46"},
-    {file = "coverage-7.5.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2de4e546f0ec4b2787d625e0b16b78e99c3e21bc1722b4977c0dddf11ca84e"},
-    {file = "coverage-7.5.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4d0e206259b73af35c4ec1319fd04003776e11e859936658cb6ceffdeba0f5be"},
-    {file = "coverage-7.5.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2055c4fb9a6ff624253d432aa471a37202cd8f458c033d6d989be4499aed037b"},
-    {file = "coverage-7.5.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:075299460948cd12722a970c7eae43d25d37989da682997687b34ae6b87c0ef0"},
-    {file = "coverage-7.5.0-cp39-cp39-win32.whl", hash = "sha256:280132aada3bc2f0fac939a5771db4fbb84f245cb35b94fae4994d4c1f80dae7"},
-    {file = "coverage-7.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:c58536f6892559e030e6924896a44098bc1290663ea12532c78cef71d0df8493"},
-    {file = "coverage-7.5.0-pp38.pp39.pp310-none-any.whl", hash = "sha256:2b57780b51084d5223eee7b59f0d4911c31c16ee5aa12737c7a02455829ff067"},
-    {file = "coverage-7.5.0.tar.gz", hash = "sha256:cf62d17310f34084c59c01e027259076479128d11e4661bb6c9acb38c5e19bb8"},
+    {file = "coverage-7.5.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c0884920835a033b78d1c73b6d3bbcda8161a900f38a488829a83982925f6c2e"},
+    {file = "coverage-7.5.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:39afcd3d4339329c5f58de48a52f6e4e50f6578dd6099961cf22228feb25f38f"},
+    {file = "coverage-7.5.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a7b0ceee8147444347da6a66be737c9d78f3353b0681715b668b72e79203e4a"},
+    {file = "coverage-7.5.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a9ca3f2fae0088c3c71d743d85404cec8df9be818a005ea065495bedc33da35"},
+    {file = "coverage-7.5.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fd215c0c7d7aab005221608a3c2b46f58c0285a819565887ee0b718c052aa4e"},
+    {file = "coverage-7.5.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:4bf0655ab60d754491004a5efd7f9cccefcc1081a74c9ef2da4735d6ee4a6223"},
+    {file = "coverage-7.5.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:61c4bf1ba021817de12b813338c9be9f0ad5b1e781b9b340a6d29fc13e7c1b5e"},
+    {file = "coverage-7.5.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:db66fc317a046556a96b453a58eced5024af4582a8dbdc0c23ca4dbc0d5b3146"},
+    {file = "coverage-7.5.1-cp310-cp310-win32.whl", hash = "sha256:b016ea6b959d3b9556cb401c55a37547135a587db0115635a443b2ce8f1c7228"},
+    {file = "coverage-7.5.1-cp310-cp310-win_amd64.whl", hash = "sha256:df4e745a81c110e7446b1cc8131bf986157770fa405fe90e15e850aaf7619bc8"},
+    {file = "coverage-7.5.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:796a79f63eca8814ca3317a1ea443645c9ff0d18b188de470ed7ccd45ae79428"},
+    {file = "coverage-7.5.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4fc84a37bfd98db31beae3c2748811a3fa72bf2007ff7902f68746d9757f3746"},
+    {file = "coverage-7.5.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6175d1a0559986c6ee3f7fccfc4a90ecd12ba0a383dcc2da30c2b9918d67d8a3"},
+    {file = "coverage-7.5.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1fc81d5878cd6274ce971e0a3a18a8803c3fe25457165314271cf78e3aae3aa2"},
+    {file = "coverage-7.5.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:556cf1a7cbc8028cb60e1ff0be806be2eded2daf8129b8811c63e2b9a6c43bca"},
+    {file = "coverage-7.5.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:9981706d300c18d8b220995ad22627647be11a4276721c10911e0e9fa44c83e8"},
+    {file = "coverage-7.5.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:d7fed867ee50edf1a0b4a11e8e5d0895150e572af1cd6d315d557758bfa9c057"},
+    {file = "coverage-7.5.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:ef48e2707fb320c8f139424a596f5b69955a85b178f15af261bab871873bb987"},
+    {file = "coverage-7.5.1-cp311-cp311-win32.whl", hash = "sha256:9314d5678dcc665330df5b69c1e726a0e49b27df0461c08ca12674bcc19ef136"},
+    {file = "coverage-7.5.1-cp311-cp311-win_amd64.whl", hash = "sha256:5fa567e99765fe98f4e7d7394ce623e794d7cabb170f2ca2ac5a4174437e90dd"},
+    {file = "coverage-7.5.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b6cf3764c030e5338e7f61f95bd21147963cf6aa16e09d2f74f1fa52013c1206"},
+    {file = "coverage-7.5.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2ec92012fefebee89a6b9c79bc39051a6cb3891d562b9270ab10ecfdadbc0c34"},
+    {file = "coverage-7.5.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:16db7f26000a07efcf6aea00316f6ac57e7d9a96501e990a36f40c965ec7a95d"},
+    {file = "coverage-7.5.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:beccf7b8a10b09c4ae543582c1319c6df47d78fd732f854ac68d518ee1fb97fa"},
+    {file = "coverage-7.5.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8748731ad392d736cc9ccac03c9845b13bb07d020a33423fa5b3a36521ac6e4e"},
+    {file = "coverage-7.5.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7352b9161b33fd0b643ccd1f21f3a3908daaddf414f1c6cb9d3a2fd618bf2572"},
+    {file = "coverage-7.5.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:7a588d39e0925f6a2bff87154752481273cdb1736270642aeb3635cb9b4cad07"},
+    {file = "coverage-7.5.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:68f962d9b72ce69ea8621f57551b2fa9c70509af757ee3b8105d4f51b92b41a7"},
+    {file = "coverage-7.5.1-cp312-cp312-win32.whl", hash = "sha256:f152cbf5b88aaeb836127d920dd0f5e7edff5a66f10c079157306c4343d86c19"},
+    {file = "coverage-7.5.1-cp312-cp312-win_amd64.whl", hash = "sha256:5a5740d1fb60ddf268a3811bcd353de34eb56dc24e8f52a7f05ee513b2d4f596"},
+    {file = "coverage-7.5.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e2213def81a50519d7cc56ed643c9e93e0247f5bbe0d1247d15fa520814a7cd7"},
+    {file = "coverage-7.5.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5037f8fcc2a95b1f0e80585bd9d1ec31068a9bcb157d9750a172836e98bc7a90"},
+    {file = "coverage-7.5.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c3721c2c9e4c4953a41a26c14f4cef64330392a6d2d675c8b1db3b645e31f0e"},
+    {file = "coverage-7.5.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca498687ca46a62ae590253fba634a1fe9836bc56f626852fb2720f334c9e4e5"},
+    {file = "coverage-7.5.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0cdcbc320b14c3e5877ee79e649677cb7d89ef588852e9583e6b24c2e5072661"},
+    {file = "coverage-7.5.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:57e0204b5b745594e5bc14b9b50006da722827f0b8c776949f1135677e88d0b8"},
+    {file = "coverage-7.5.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8fe7502616b67b234482c3ce276ff26f39ffe88adca2acf0261df4b8454668b4"},
+    {file = "coverage-7.5.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:9e78295f4144f9dacfed4f92935fbe1780021247c2fabf73a819b17f0ccfff8d"},
+    {file = "coverage-7.5.1-cp38-cp38-win32.whl", hash = "sha256:1434e088b41594baa71188a17533083eabf5609e8e72f16ce8c186001e6b8c41"},
+    {file = "coverage-7.5.1-cp38-cp38-win_amd64.whl", hash = "sha256:0646599e9b139988b63704d704af8e8df7fa4cbc4a1f33df69d97f36cb0a38de"},
+    {file = "coverage-7.5.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4cc37def103a2725bc672f84bd939a6fe4522310503207aae4d56351644682f1"},
+    {file = "coverage-7.5.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:fc0b4d8bfeabd25ea75e94632f5b6e047eef8adaed0c2161ada1e922e7f7cece"},
+    {file = "coverage-7.5.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d0a0f5e06881ecedfe6f3dd2f56dcb057b6dbeb3327fd32d4b12854df36bf26"},
+    {file = "coverage-7.5.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9735317685ba6ec7e3754798c8871c2f49aa5e687cc794a0b1d284b2389d1bd5"},
+    {file = "coverage-7.5.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d21918e9ef11edf36764b93101e2ae8cc82aa5efdc7c5a4e9c6c35a48496d601"},
+    {file = "coverage-7.5.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c3e757949f268364b96ca894b4c342b41dc6f8f8b66c37878aacef5930db61be"},
+    {file = "coverage-7.5.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:79afb6197e2f7f60c4824dd4b2d4c2ec5801ceb6ba9ce5d2c3080e5660d51a4f"},
+    {file = "coverage-7.5.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d1d0d98d95dd18fe29dc66808e1accf59f037d5716f86a501fc0256455219668"},
+    {file = "coverage-7.5.1-cp39-cp39-win32.whl", hash = "sha256:1cc0fe9b0b3a8364093c53b0b4c0c2dd4bb23acbec4c9240b5f284095ccf7981"},
+    {file = "coverage-7.5.1-cp39-cp39-win_amd64.whl", hash = "sha256:dde0070c40ea8bb3641e811c1cfbf18e265d024deff6de52c5950677a8fb1e0f"},
+    {file = "coverage-7.5.1-pp38.pp39.pp310-none-any.whl", hash = "sha256:6537e7c10cc47c595828b8a8be04c72144725c383c4702703ff4e42e44577312"},
+    {file = "coverage-7.5.1.tar.gz", hash = "sha256:54de9ef3a9da981f7af93eafde4ede199e0846cd819eb27c88e2b712aae9708c"},
 ]
 
 [package.dependencies]
@@ -676,43 +665,43 @@ toml = ["tomli"]
 
 [[package]]
 name = "cryptography"
-version = "42.0.5"
+version = "42.0.7"
 description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
 optional = false
 python-versions = ">=3.7"
 files = [
-    {file = "cryptography-42.0.5-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:a30596bae9403a342c978fb47d9b0ee277699fa53bbafad14706af51fe543d16"},
-    {file = "cryptography-42.0.5-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:b7ffe927ee6531c78f81aa17e684e2ff617daeba7f189f911065b2ea2d526dec"},
-    {file = "cryptography-42.0.5-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2424ff4c4ac7f6b8177b53c17ed5d8fa74ae5955656867f5a8affaca36a27abb"},
-    {file = "cryptography-42.0.5-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:329906dcc7b20ff3cad13c069a78124ed8247adcac44b10bea1130e36caae0b4"},
-    {file = "cryptography-42.0.5-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:b03c2ae5d2f0fc05f9a2c0c997e1bc18c8229f392234e8a0194f202169ccd278"},
-    {file = "cryptography-42.0.5-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:f8837fe1d6ac4a8052a9a8ddab256bc006242696f03368a4009be7ee3075cdb7"},
-    {file = "cryptography-42.0.5-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:0270572b8bd2c833c3981724b8ee9747b3ec96f699a9665470018594301439ee"},
-    {file = "cryptography-42.0.5-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:b8cac287fafc4ad485b8a9b67d0ee80c66bf3574f655d3b97ef2e1082360faf1"},
-    {file = "cryptography-42.0.5-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:16a48c23a62a2f4a285699dba2e4ff2d1cff3115b9df052cdd976a18856d8e3d"},
-    {file = "cryptography-42.0.5-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:2bce03af1ce5a5567ab89bd90d11e7bbdff56b8af3acbbec1faded8f44cb06da"},
-    {file = "cryptography-42.0.5-cp37-abi3-win32.whl", hash = "sha256:b6cd2203306b63e41acdf39aa93b86fb566049aeb6dc489b70e34bcd07adca74"},
-    {file = "cryptography-42.0.5-cp37-abi3-win_amd64.whl", hash = "sha256:98d8dc6d012b82287f2c3d26ce1d2dd130ec200c8679b6213b3c73c08b2b7940"},
-    {file = "cryptography-42.0.5-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:5e6275c09d2badf57aea3afa80d975444f4be8d3bc58f7f80d2a484c6f9485c8"},
-    {file = "cryptography-42.0.5-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4985a790f921508f36f81831817cbc03b102d643b5fcb81cd33df3fa291a1a1"},
-    {file = "cryptography-42.0.5-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7cde5f38e614f55e28d831754e8a3bacf9ace5d1566235e39d91b35502d6936e"},
-    {file = "cryptography-42.0.5-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:7367d7b2eca6513681127ebad53b2582911d1736dc2ffc19f2c3ae49997496bc"},
-    {file = "cryptography-42.0.5-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:cd2030f6650c089aeb304cf093f3244d34745ce0cfcc39f20c6fbfe030102e2a"},
-    {file = "cryptography-42.0.5-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a2913c5375154b6ef2e91c10b5720ea6e21007412f6437504ffea2109b5a33d7"},
-    {file = "cryptography-42.0.5-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:c41fb5e6a5fe9ebcd58ca3abfeb51dffb5d83d6775405305bfa8715b76521922"},
-    {file = "cryptography-42.0.5-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:3eaafe47ec0d0ffcc9349e1708be2aaea4c6dd4978d76bf6eb0cb2c13636c6fc"},
-    {file = "cryptography-42.0.5-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:1b95b98b0d2af784078fa69f637135e3c317091b615cd0905f8b8a087e86fa30"},
-    {file = "cryptography-42.0.5-cp39-abi3-win32.whl", hash = "sha256:1f71c10d1e88467126f0efd484bd44bca5e14c664ec2ede64c32f20875c0d413"},
-    {file = "cryptography-42.0.5-cp39-abi3-win_amd64.whl", hash = "sha256:a011a644f6d7d03736214d38832e030d8268bcff4a41f728e6030325fea3e400"},
-    {file = "cryptography-42.0.5-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:9481ffe3cf013b71b2428b905c4f7a9a4f76ec03065b05ff499bb5682a8d9ad8"},
-    {file = "cryptography-42.0.5-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:ba334e6e4b1d92442b75ddacc615c5476d4ad55cc29b15d590cc6b86efa487e2"},
-    {file = "cryptography-42.0.5-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:ba3e4a42397c25b7ff88cdec6e2a16c2be18720f317506ee25210f6d31925f9c"},
-    {file = "cryptography-42.0.5-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:111a0d8553afcf8eb02a4fea6ca4f59d48ddb34497aa8706a6cf536f1a5ec576"},
-    {file = "cryptography-42.0.5-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:cd65d75953847815962c84a4654a84850b2bb4aed3f26fadcc1c13892e1e29f6"},
-    {file = "cryptography-42.0.5-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:e807b3188f9eb0eaa7bbb579b462c5ace579f1cedb28107ce8b48a9f7ad3679e"},
-    {file = "cryptography-42.0.5-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:f12764b8fffc7a123f641d7d049d382b73f96a34117e0b637b80643169cec8ac"},
-    {file = "cryptography-42.0.5-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:37dd623507659e08be98eec89323469e8c7b4c1407c85112634ae3dbdb926fdd"},
-    {file = "cryptography-42.0.5.tar.gz", hash = "sha256:6fe07eec95dfd477eb9530aef5bead34fec819b3aaf6c5bd6d20565da607bfe1"},
+    {file = "cryptography-42.0.7-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:a987f840718078212fdf4504d0fd4c6effe34a7e4740378e59d47696e8dfb477"},
+    {file = "cryptography-42.0.7-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:bd13b5e9b543532453de08bcdc3cc7cebec6f9883e886fd20a92f26940fd3e7a"},
+    {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a79165431551042cc9d1d90e6145d5d0d3ab0f2d66326c201d9b0e7f5bf43604"},
+    {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a47787a5e3649008a1102d3df55424e86606c9bae6fb77ac59afe06d234605f8"},
+    {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:02c0eee2d7133bdbbc5e24441258d5d2244beb31da5ed19fbb80315f4bbbff55"},
+    {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:5e44507bf8d14b36b8389b226665d597bc0f18ea035d75b4e53c7b1ea84583cc"},
+    {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:7f8b25fa616d8b846aef64b15c606bb0828dbc35faf90566eb139aa9cff67af2"},
+    {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:93a3209f6bb2b33e725ed08ee0991b92976dfdcf4e8b38646540674fc7508e13"},
+    {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:e6b8f1881dac458c34778d0a424ae5769de30544fc678eac51c1c8bb2183e9da"},
+    {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:3de9a45d3b2b7d8088c3fbf1ed4395dfeff79d07842217b38df14ef09ce1d8d7"},
+    {file = "cryptography-42.0.7-cp37-abi3-win32.whl", hash = "sha256:789caea816c6704f63f6241a519bfa347f72fbd67ba28d04636b7c6b7da94b0b"},
+    {file = "cryptography-42.0.7-cp37-abi3-win_amd64.whl", hash = "sha256:8cb8ce7c3347fcf9446f201dc30e2d5a3c898d009126010cbd1f443f28b52678"},
+    {file = "cryptography-42.0.7-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:a3a5ac8b56fe37f3125e5b72b61dcde43283e5370827f5233893d461b7360cd4"},
+    {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:779245e13b9a6638df14641d029add5dc17edbef6ec915688f3acb9e720a5858"},
+    {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d563795db98b4cd57742a78a288cdbdc9daedac29f2239793071fe114f13785"},
+    {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:31adb7d06fe4383226c3e963471f6837742889b3c4caa55aac20ad951bc8ffda"},
+    {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:efd0bf5205240182e0f13bcaea41be4fdf5c22c5129fc7ced4a0282ac86998c9"},
+    {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a9bc127cdc4ecf87a5ea22a2556cab6c7eda2923f84e4f3cc588e8470ce4e42e"},
+    {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:3577d029bc3f4827dd5bf8bf7710cac13527b470bbf1820a3f394adb38ed7d5f"},
+    {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2e47577f9b18723fa294b0ea9a17d5e53a227867a0a4904a1a076d1646d45ca1"},
+    {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:1a58839984d9cb34c855197043eaae2c187d930ca6d644612843b4fe8513c886"},
+    {file = "cryptography-42.0.7-cp39-abi3-win32.whl", hash = "sha256:e6b79d0adb01aae87e8a44c2b64bc3f3fe59515280e00fb6d57a7267a2583cda"},
+    {file = "cryptography-42.0.7-cp39-abi3-win_amd64.whl", hash = "sha256:16268d46086bb8ad5bf0a2b5544d8a9ed87a0e33f5e77dd3c3301e63d941a83b"},
+    {file = "cryptography-42.0.7-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2954fccea107026512b15afb4aa664a5640cd0af630e2ee3962f2602693f0c82"},
+    {file = "cryptography-42.0.7-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:362e7197754c231797ec45ee081f3088a27a47c6c01eff2ac83f60f85a50fe60"},
+    {file = "cryptography-42.0.7-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:4f698edacf9c9e0371112792558d2f705b5645076cc0aaae02f816a0171770fd"},
+    {file = "cryptography-42.0.7-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:5482e789294854c28237bba77c4c83be698be740e31a3ae5e879ee5444166582"},
+    {file = "cryptography-42.0.7-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:e9b2a6309f14c0497f348d08a065d52f3020656f675819fc405fb63bbcd26562"},
+    {file = "cryptography-42.0.7-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d8e3098721b84392ee45af2dd554c947c32cc52f862b6a3ae982dbb90f577f14"},
+    {file = "cryptography-42.0.7-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c65f96dad14f8528a447414125e1fc8feb2ad5a272b8f68477abbcc1ea7d94b9"},
+    {file = "cryptography-42.0.7-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:36017400817987670037fbb0324d71489b6ead6231c9604f8fc1f7d008087c68"},
+    {file = "cryptography-42.0.7.tar.gz", hash = "sha256:ecbfbc00bf55888edda9868a4cf927205de8499e7fabe6c050322298382953f2"},
 ]
 
 [package.dependencies]
@@ -745,13 +734,13 @@ tests = ["pytest", "pytest-cov", "pytest-xdist"]
 
 [[package]]
 name = "dataclasses-json"
-version = "0.6.4"
+version = "0.6.6"
 description = "Easily serialize dataclasses to and from JSON."
 optional = false
-python-versions = ">=3.7,<4.0"
+python-versions = "<4.0,>=3.7"
 files = [
-    {file = "dataclasses_json-0.6.4-py3-none-any.whl", hash = "sha256:f90578b8a3177f7552f4e1a6e535e84293cd5da421fcce0642d49c0d7bdf8df2"},
-    {file = "dataclasses_json-0.6.4.tar.gz", hash = "sha256:73696ebf24936560cca79a2430cbc4f3dd23ac7bf46ed17f38e5e5e7657a6377"},
+    {file = "dataclasses_json-0.6.6-py3-none-any.whl", hash = "sha256:e54c5c87497741ad454070ba0ed411523d46beb5da102e221efb873801b0ba85"},
+    {file = "dataclasses_json-0.6.6.tar.gz", hash = "sha256:0c09827d26fffda27f1be2fed7a7a01a29c5ddcd2eb6393ad5ebf9d77e9deae8"},
 ]
 
 [package.dependencies]
@@ -877,13 +866,13 @@ devel = ["colorama", "json-spec", "jsonschema", "pylint", "pytest", "pytest-benc
 
 [[package]]
 name = "filelock"
-version = "3.13.4"
+version = "3.14.0"
 description = "A platform independent file lock."
 optional = false
 python-versions = ">=3.8"
 files = [
-    {file = "filelock-3.13.4-py3-none-any.whl", hash = "sha256:404e5e9253aa60ad457cae1be07c0f0ca90a63931200a47d9b6a6af84fd7b45f"},
-    {file = "filelock-3.13.4.tar.gz", hash = "sha256:d13f466618bfde72bd2c18255e269f72542c6e70e7bac83a0232d6b1cc5c8cf4"},
+    {file = "filelock-3.14.0-py3-none-any.whl", hash = "sha256:43339835842f110ca7ae60f1e1c160714c5a6afd15a2873419ab185334975c0f"},
+    {file = "filelock-3.14.0.tar.gz", hash = "sha256:6ea72da3be9b8c82afd3edcf99f2fffbb5076335a5ae4d03248bb5b6c3eae78a"},
 ]
 
 [package.extras]
@@ -986,13 +975,13 @@ dev = ["flake8", "markdown", "twine", "wheel"]
 
 [[package]]
 name = "google-api-core"
-version = "2.18.0"
+version = "2.19.0"
 description = "Google API client core library"
 optional = false
 python-versions = ">=3.7"
 files = [
-    {file = "google-api-core-2.18.0.tar.gz", hash = "sha256:62d97417bfc674d6cef251e5c4d639a9655e00c45528c4364fbfebb478ce72a9"},
-    {file = "google_api_core-2.18.0-py3-none-any.whl", hash = "sha256:5a63aa102e0049abe85b5b88cb9409234c1f70afcda21ce1e40b285b9629c1d6"},
+    {file = "google-api-core-2.19.0.tar.gz", hash = "sha256:cf1b7c2694047886d2af1128a03ae99e391108a08804f87cfd35970e49c9cd10"},
+    {file = "google_api_core-2.19.0-py3-none-any.whl", hash = "sha256:8661eec4078c35428fd3f69a2c7ee29e342896b70f01d1a1cbcb334372dd6251"},
 ]
 
 [package.dependencies]
@@ -1049,13 +1038,13 @@ grpc = ["grpcio (>=1.44.0,<2.0.0.dev0)"]
 
 [[package]]
 name = "griffe"
-version = "0.44.0"
+version = "0.45.0"
 description = "Signatures for entire Python programs. Extract the structure, the frame, the skeleton of your project, to generate API documentation or find breaking changes in your API."
 optional = false
 python-versions = ">=3.8"
 files = [
-    {file = "griffe-0.44.0-py3-none-any.whl", hash = "sha256:8a4471c469ba980b87c843f1168850ce39d0c1d0c7be140dca2480f76c8e5446"},
-    {file = "griffe-0.44.0.tar.gz", hash = "sha256:34aee1571042f9bf00529bc715de4516fb6f482b164e90d030300601009e0223"},
+    {file = "griffe-0.45.0-py3-none-any.whl", hash = "sha256:90fe5c90e1b0ca7dd6fee78f9009f4e01b37dbc9ab484a9b2c1578915db1e571"},
+    {file = "griffe-0.45.0.tar.gz", hash = "sha256:85cb2868d026ea51c89bdd589ad3ccc94abc5bd8d5d948e3d4450778a2a05b4a"},
 ]
 
 [package.dependencies]
@@ -1323,13 +1312,13 @@ testing = ["Django", "attrs", "colorama", "docopt", "pytest (<7.0.0)"]
 
 [[package]]
 name = "jinja2"
-version = "3.1.3"
+version = "3.1.4"
 description = "A very fast and expressive template engine."
 optional = false
 python-versions = ">=3.7"
 files = [
-    {file = "Jinja2-3.1.3-py3-none-any.whl", hash = "sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa"},
-    {file = "Jinja2-3.1.3.tar.gz", hash = "sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90"},
+    {file = "jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"},
+    {file = "jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369"},
 ]
 
 [package.dependencies]
@@ -1340,13 +1329,13 @@ i18n = ["Babel (>=2.7)"]
 
 [[package]]
 name = "jsonschema"
-version = "4.21.1"
+version = "4.22.0"
 description = "An implementation of JSON Schema validation for Python"
 optional = false
 python-versions = ">=3.8"
 files = [
-    {file = "jsonschema-4.21.1-py3-none-any.whl", hash = "sha256:7996507afae316306f9e2290407761157c6f78002dcf7419acb99822143d1c6f"},
-    {file = "jsonschema-4.21.1.tar.gz", hash = "sha256:85727c00279f5fa6bedbe6238d2aa6403bedd8b4864ab11207d07df3cc1b2ee5"},
+    {file = "jsonschema-4.22.0-py3-none-any.whl", hash = "sha256:ff4cfd6b1367a40e7bc6411caec72effadd3db0bbe5017de188f2d6108335802"},
+    {file = "jsonschema-4.22.0.tar.gz", hash = "sha256:5b22d434a45935119af990552c862e5d6d564e8f6601206b305a61fdf661a2b7"},
 ]
 
 [package.dependencies]
@@ -1564,31 +1553,36 @@ test = ["pytest (>=7.4)", "pytest-cov (>=4.1)"]
 
 [[package]]
 name = "libqasm"
-version = "0.6.5"
-description = "libQasm Python Package"
+version = "0.6.6"
+description = "libqasm Python Package"
 optional = false
 python-versions = "*"
 files = [
-    {file = "libqasm-0.6.5-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:5446052b2fbc7a912a2fa867754f023b28442275c4c744887cc2523868f168b1"},
-    {file = "libqasm-0.6.5-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5bbb15bf73df98e9e7b6347e959f3863398e04392ab7ab0abfe35ba398afd655"},
-    {file = "libqasm-0.6.5-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f47cd551751cbd8f9b76459f387fab56762ca8ce9903ad6625ea1f3fe08af1d0"},
-    {file = "libqasm-0.6.5-cp310-cp310-win_amd64.whl", hash = "sha256:38138777814f9d914b6eed8b48899d6e85f0a5194691d5a8ed7e9fdf2aa9d2f2"},
-    {file = "libqasm-0.6.5-cp311-cp311-macosx_10_10_universal2.whl", hash = "sha256:d41f1a457d1acfc36a87cdc8b0fc3a1e1e49ea38d0028ae8bac85c7ab8f017b0"},
-    {file = "libqasm-0.6.5-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f4afe389e4fc0849ba7b6add5e49cd5e459ccc652db9e5730a8c300daceb4a94"},
-    {file = "libqasm-0.6.5-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f13c922ce229bc9c990cca058691e3aa538eb26ad1f93291d1129e832a815ea5"},
-    {file = "libqasm-0.6.5-cp311-cp311-win_amd64.whl", hash = "sha256:314b34d851a2597b4b16d82c762725beb6e740374d47cd345870f458b4324684"},
-    {file = "libqasm-0.6.5-cp312-cp312-macosx_10_10_universal2.whl", hash = "sha256:56d0945bccbcb8054a9cbfef9d54f8eade565b606a0b104d65d1add1a50f87b8"},
-    {file = "libqasm-0.6.5-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3af5c9340268c55f68d4c811af68beb24bdb055e7e316965eb4eaacfaa64a6a5"},
-    {file = "libqasm-0.6.5-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b61d615e28c1f0a98d2e78742b3fdd35deee0e5c384dc359c56b70ba12b06142"},
-    {file = "libqasm-0.6.5-cp312-cp312-win_amd64.whl", hash = "sha256:ebdf826ad1d27530ce05d580abcbd05a46718f72ff466d0958e3c8cd9ccd9da6"},
-    {file = "libqasm-0.6.5-cp38-cp38-macosx_11_0_x86_64.whl", hash = "sha256:9661e0cf6edec1550b65239911c243d5c2ca9f43835ae50e59b1cdf4ae2f4782"},
-    {file = "libqasm-0.6.5-cp38-cp38-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e5dd8c324579235f751cf62fa52c049bf56516e2b53ebfea0073a3b7399aa552"},
-    {file = "libqasm-0.6.5-cp38-cp38-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b5d655edbe69e405bf5097f292a164554279bc971f8adea00bdaff5d5dfc4261"},
-    {file = "libqasm-0.6.5-cp38-cp38-win_amd64.whl", hash = "sha256:607766991a084a546a57064fb82b2cb6329e8372ec75643f8e7973aaf0dbd189"},
-    {file = "libqasm-0.6.5-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:30f5477ea327d4461ab43867fa2d9e806b155f6b14d36c40cda13621cd15692b"},
-    {file = "libqasm-0.6.5-cp39-cp39-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cd1934516ead4de6693bf3bed271ff675a77f2980cd84924c2412f853baacf8d"},
-    {file = "libqasm-0.6.5-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7d817bff81fbf9dc90252c7fbae346577fd329ccd1a2328ae7df811be2e8b93b"},
-    {file = "libqasm-0.6.5-cp39-cp39-win_amd64.whl", hash = "sha256:9228d794311fa4b08bf432d14a965ba40ecd3c3e266416ddd273219c27606071"},
+    {file = "libqasm-0.6.6-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:5f7e0bf4a5086d24b23f62462ab5fa2c78358d2f0bc89f7440b66a11511ec908"},
+    {file = "libqasm-0.6.6-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:3febe56ab802da4d7ba2c98ad13915d16b7abf1c931dc86cb32f60504d86ef10"},
+    {file = "libqasm-0.6.6-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ad2075cca3f67fd3df5af75038d74f2f2b09f6abd77db2097caf6002475806b7"},
+    {file = "libqasm-0.6.6-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ce85489d7b2037034a5290038df1f1f98fea7cf63f02bd85e32315b933e6ed2a"},
+    {file = "libqasm-0.6.6-cp310-cp310-win_amd64.whl", hash = "sha256:333519170c3b0928bf0268c72ccd35ed31b23e95fda1771863c6f09cecae967a"},
+    {file = "libqasm-0.6.6-cp311-cp311-macosx_10_10_universal2.whl", hash = "sha256:fa3a1f6963d549c56bdd2835cdaa0c32ea2d98e53071a297d4d98982190b4894"},
+    {file = "libqasm-0.6.6-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:44309ed847730890a2753f03e58fea26e7d51cf6d8db96f147bddcd41fae2648"},
+    {file = "libqasm-0.6.6-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f7f959a482dc74912f7e6fd45878f7f7b5dafeb66e87098cb3d9470b0f97cde"},
+    {file = "libqasm-0.6.6-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:30c917e10847385d6c01981723f96b3c39882e99b44e2e6d38c525f492c321fa"},
+    {file = "libqasm-0.6.6-cp311-cp311-win_amd64.whl", hash = "sha256:59ceda3d21abfd53a712837d9d502fd53566effe095aaa390c29d4765b70688f"},
+    {file = "libqasm-0.6.6-cp312-cp312-macosx_10_10_universal2.whl", hash = "sha256:7e217987fbec408094a4556f9f79f1fc03919a249b1005c216f02990e32289ba"},
+    {file = "libqasm-0.6.6-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:39a65c8b91b3ec8d6d9986d7c20975653a1cfd3031a05b0032f75a5fde073c29"},
+    {file = "libqasm-0.6.6-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f7c6c58ce4f55559cabdb41b0c808d52009d394af5a63a43e6deea7c43a18cde"},
+    {file = "libqasm-0.6.6-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3edbd092668662bab54d39632c5fb7ce8eee952343561ca43afaa1fd2ad67b1a"},
+    {file = "libqasm-0.6.6-cp312-cp312-win_amd64.whl", hash = "sha256:f6a1a15a982a04e9e2f4eac54efa56cef451295ecbd6d2136bbace7fe06fd900"},
+    {file = "libqasm-0.6.6-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:1eae1f527a8027454e3cd32e4b358238ce8d082d93ed5dd4b7b2e426593b8bd8"},
+    {file = "libqasm-0.6.6-cp38-cp38-macosx_11_0_x86_64.whl", hash = "sha256:649e2bdf490fc2153c406f008ca0cc937013280a2c29fdc297ddbdcfd5f0d23b"},
+    {file = "libqasm-0.6.6-cp38-cp38-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:231339d32b30142af8f01190ab1f587f9f2b3f1ea70953868e5a5009b5045d01"},
+    {file = "libqasm-0.6.6-cp38-cp38-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6d00cc65e29dbadec3b8e464d9e6078726cec11401d504b7abc1b5798b785db2"},
+    {file = "libqasm-0.6.6-cp38-cp38-win_amd64.whl", hash = "sha256:1c311672f7fd8d048ee2cd2bb0d43a2e86a78613d5951afc3ec26f74b1850f09"},
+    {file = "libqasm-0.6.6-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:4a61e271bbb0e6d26f3782555f405bb83323c2501fdd2b77b0760392ef3e0540"},
+    {file = "libqasm-0.6.6-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:213e0b029f6b277a3068a9864c13653a782caf9ce1bb2b648b2ad7bae866a6ff"},
+    {file = "libqasm-0.6.6-cp39-cp39-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0700e0c971ae8da045696300588ef2d56a3c8aa39140a44e344630a2e8ba030e"},
+    {file = "libqasm-0.6.6-cp39-cp39-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:026d1ef42567294557ba55fd7db7a6f9b7d5f434c96906b37f4e33e09f2feb0c"},
+    {file = "libqasm-0.6.6-cp39-cp39-win_amd64.whl", hash = "sha256:2e3aaf3471be7d10332a3dd4f7e84e074aebaa040c8d6996a156ecc50e4cf430"},
 ]
 
 [package.dependencies]
@@ -1745,13 +1739,13 @@ files = [
 
 [[package]]
 name = "marshmallow"
-version = "3.21.1"
+version = "3.21.2"
 description = "A lightweight library for converting complex datatypes to and from native Python datatypes."
 optional = false
 python-versions = ">=3.8"
 files = [
-    {file = "marshmallow-3.21.1-py3-none-any.whl", hash = "sha256:f085493f79efb0644f270a9bf2892843142d80d7174bbbd2f3713f2a589dc633"},
-    {file = "marshmallow-3.21.1.tar.gz", hash = "sha256:4e65e9e0d80fc9e609574b9983cf32579f305c718afb30d7233ab818571768c3"},
+    {file = "marshmallow-3.21.2-py3-none-any.whl", hash = "sha256:70b54a6282f4704d12c0a41599682c5c5450e843b9ec406308653b47c59648a1"},
+    {file = "marshmallow-3.21.2.tar.gz", hash = "sha256:82408deadd8b33d56338d2182d455db632c6313aa2af61916672146bb32edc56"},
 ]
 
 [package.dependencies]
@@ -1759,7 +1753,7 @@ packaging = ">=17.0"
 
 [package.extras]
 dev = ["marshmallow[tests]", "pre-commit (>=3.5,<4.0)", "tox"]
-docs = ["alabaster (==0.7.16)", "autodocsumm (==0.2.12)", "sphinx (==7.2.6)", "sphinx-issues (==4.0.0)", "sphinx-version-warning (==1.1.2)"]
+docs = ["alabaster (==0.7.16)", "autodocsumm (==0.2.12)", "sphinx (==7.3.7)", "sphinx-issues (==4.1.0)", "sphinx-version-warning (==1.1.2)"]
 tests = ["pytest", "pytz", "simplejson"]
 
 [[package]]
@@ -1974,13 +1968,13 @@ pyyaml = ">=5.1"
 
 [[package]]
 name = "mkdocs-material"
-version = "9.5.20"
+version = "9.5.23"
 description = "Documentation that simply works"
 optional = false
 python-versions = ">=3.8"
 files = [
-    {file = "mkdocs_material-9.5.20-py3-none-any.whl", hash = "sha256:ad0094a7597bcb5d0cc3e8e543a10927c2581f7f647b9bb4861600f583180f9b"},
-    {file = "mkdocs_material-9.5.20.tar.gz", hash = "sha256:986eef0250d22f70fb06ce0f4eac64cc92bd797a589ec3892ce31fad976fe3da"},
+    {file = "mkdocs_material-9.5.23-py3-none-any.whl", hash = "sha256:ffd08a5beaef3cd135aceb58ded8b98bbbbf2b70e5b656f6a14a63c917d9b001"},
+    {file = "mkdocs_material-9.5.23.tar.gz", hash = "sha256:4627fc3f15de2cba2bde9debc2fd59b9888ef494beabfe67eb352e23d14bf288"},
 ]
 
 [package.dependencies]
@@ -2014,13 +2008,13 @@ files = [
 
 [[package]]
 name = "mkdocstrings"
-version = "0.25.0"
+version = "0.25.1"
 description = "Automatic documentation from sources, for MkDocs."
 optional = false
 python-versions = ">=3.8"
 files = [
-    {file = "mkdocstrings-0.25.0-py3-none-any.whl", hash = "sha256:df1b63f26675fcde8c1b77e7ea996cd2f93220b148e06455428f676f5dc838f1"},
-    {file = "mkdocstrings-0.25.0.tar.gz", hash = "sha256:066986b3fb5b9ef2d37c4417255a808f7e63b40ff8f67f6cab8054d903fbc91d"},
+    {file = "mkdocstrings-0.25.1-py3-none-any.whl", hash = "sha256:da01fcc2670ad61888e8fe5b60afe9fee5781017d67431996832d63e887c2e51"},
+    {file = "mkdocstrings-0.25.1.tar.gz", hash = "sha256:c3a2515f31577f311a9ee58d089e4c51fc6046dbd9e9b4c3de4c3194667fe9bf"},
 ]
 
 [package.dependencies]
@@ -2043,18 +2037,18 @@ python-legacy = ["mkdocstrings-python-legacy (>=0.2.1)"]
 
 [[package]]
 name = "mkdocstrings-python"
-version = "1.10.0"
+version = "1.10.2"
 description = "A Python handler for mkdocstrings."
 optional = false
 python-versions = ">=3.8"
 files = [
-    {file = "mkdocstrings_python-1.10.0-py3-none-any.whl", hash = "sha256:ba833fbd9d178a4b9d5cb2553a4df06e51dc1f51e41559a4d2398c16a6f69ecc"},
-    {file = "mkdocstrings_python-1.10.0.tar.gz", hash = "sha256:71678fac657d4d2bb301eed4e4d2d91499c095fd1f8a90fa76422a87a5693828"},
+    {file = "mkdocstrings_python-1.10.2-py3-none-any.whl", hash = "sha256:e8e596b37f45c09b67bec253e035fe18988af5bbbbf44e0ccd711742eed750e5"},
+    {file = "mkdocstrings_python-1.10.2.tar.gz", hash = "sha256:38a4fd41953defb458a107033440c229c7e9f98f35a24e84d888789c97da5a63"},
 ]
 
 [package.dependencies]
 griffe = ">=0.44"
-mkdocstrings = ">=0.24.2"
+mkdocstrings = ">=0.25"
 
 [[package]]
 name = "msal"
@@ -2573,13 +2567,13 @@ files = [
 
 [[package]]
 name = "platformdirs"
-version = "4.2.1"
+version = "4.2.2"
 description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`."
 optional = false
 python-versions = ">=3.8"
 files = [
-    {file = "platformdirs-4.2.1-py3-none-any.whl", hash = "sha256:17d5a1161b3fd67b390023cb2d3b026bbd40abde6fdb052dfbd3a29c3ba22ee1"},
-    {file = "platformdirs-4.2.1.tar.gz", hash = "sha256:031cd18d4ec63ec53e82dceaac0417d218a6863f7745dfcc9efe7793b7039bdf"},
+    {file = "platformdirs-4.2.2-py3-none-any.whl", hash = "sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee"},
+    {file = "platformdirs-4.2.2.tar.gz", hash = "sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3"},
 ]
 
 [package.extras]
@@ -2589,13 +2583,13 @@ type = ["mypy (>=1.8)"]
 
 [[package]]
 name = "plotly"
-version = "5.21.0"
+version = "5.22.0"
 description = "An open-source, interactive data visualization library for Python"
 optional = false
 python-versions = ">=3.8"
 files = [
-    {file = "plotly-5.21.0-py3-none-any.whl", hash = "sha256:a33f41fd5922e45b2b253f795b200d14452eb625790bb72d0a72cf1328a6abbf"},
-    {file = "plotly-5.21.0.tar.gz", hash = "sha256:69243f8c165d4be26c0df1c6f0b7b258e2dfeefe032763404ad7e7fb7d7c2073"},
+    {file = "plotly-5.22.0-py3-none-any.whl", hash = "sha256:68fc1901f098daeb233cc3dd44ec9dc31fb3ca4f4e53189344199c43496ed006"},
+    {file = "plotly-5.22.0.tar.gz", hash = "sha256:859fdadbd86b5770ae2466e542b761b247d1c6b49daed765b95bb8c7063e7469"},
 ]
 
 [package.dependencies]
@@ -2888,17 +2882,16 @@ typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0"
 
 [[package]]
 name = "pygments"
-version = "2.17.2"
+version = "2.18.0"
 description = "Pygments is a syntax highlighting package written in Python."
 optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
 files = [
-    {file = "pygments-2.17.2-py3-none-any.whl", hash = "sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c"},
-    {file = "pygments-2.17.2.tar.gz", hash = "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367"},
+    {file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"},
+    {file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"},
 ]
 
 [package.extras]
-plugins = ["importlib-metadata"]
 windows-terminal = ["colorama (>=0.4.6)"]
 
 [[package]]
@@ -2923,17 +2916,17 @@ tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"]
 
 [[package]]
 name = "pylint"
-version = "3.1.0"
+version = "3.2.0"
 description = "python code static checker"
 optional = false
 python-versions = ">=3.8.0"
 files = [
-    {file = "pylint-3.1.0-py3-none-any.whl", hash = "sha256:507a5b60953874766d8a366e8e8c7af63e058b26345cfcb5f91f89d987fd6b74"},
-    {file = "pylint-3.1.0.tar.gz", hash = "sha256:6a69beb4a6f63debebaab0a3477ecd0f559aa726af4954fc948c51f7a2549e23"},
+    {file = "pylint-3.2.0-py3-none-any.whl", hash = "sha256:9f20c05398520474dac03d7abb21ab93181f91d4c110e1e0b32bc0d016c34fa4"},
+    {file = "pylint-3.2.0.tar.gz", hash = "sha256:ad8baf17c8ea5502f23ae38d7c1b7ec78bd865ce34af9a0b986282e2611a8ff2"},
 ]
 
 [package.dependencies]
-astroid = ">=3.1.0,<=3.2.0-dev0"
+astroid = ">=3.2.0,<=3.3.0-dev0"
 colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""}
 dill = [
     {version = ">=0.2", markers = "python_version < \"3.11\""},
@@ -3251,99 +3244,99 @@ pyyaml = "*"
 
 [[package]]
 name = "pyzmq"
-version = "26.0.2"
+version = "26.0.3"
 description = "Python bindings for 0MQ"
 optional = false
 python-versions = ">=3.7"
 files = [
-    {file = "pyzmq-26.0.2-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:1a60a03b01e8c9c58932ec0cca15b1712d911c2800eb82d4281bc1ae5b6dad50"},
-    {file = "pyzmq-26.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:949067079e14ea1973bd740255e0840118c163d4bce8837f539d749f145cf5c3"},
-    {file = "pyzmq-26.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:37e7edfa6cf96d036a403775c96afa25058d1bb940a79786a9a2fc94a783abe3"},
-    {file = "pyzmq-26.0.2-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:903cc7a84a7d4326b43755c368780800e035aa3d711deae84a533fdffa8755b0"},
-    {file = "pyzmq-26.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6cb2e41af165e5f327d06fbdd79a42a4e930267fade4e9f92d17f3ccce03f3a7"},
-    {file = "pyzmq-26.0.2-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:55353b8189adcfc4c125fc4ce59d477744118e9c0ec379dd0999c5fa120ac4f5"},
-    {file = "pyzmq-26.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:f961423ff6236a752ced80057a20e623044df95924ed1009f844cde8b3a595f9"},
-    {file = "pyzmq-26.0.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ba77fe84fe4f5f3dc0ef681a6d366685c8ffe1c8439c1d7530997b05ac06a04b"},
-    {file = "pyzmq-26.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:52589f0a745ef61b9c75c872cf91f8c1f7c0668eb3dd99d7abd639d8c0fb9ca7"},
-    {file = "pyzmq-26.0.2-cp310-cp310-win32.whl", hash = "sha256:b7b6d2a46c7afe2ad03ec8faf9967090c8ceae85c4d8934d17d7cae6f9062b64"},
-    {file = "pyzmq-26.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:86531e20de249d9204cc6d8b13d5a30537748c78820215161d8a3b9ea58ca111"},
-    {file = "pyzmq-26.0.2-cp310-cp310-win_arm64.whl", hash = "sha256:f26a05029ecd2bd306b941ff8cb80f7620b7901421052bc429d238305b1cbf2f"},
-    {file = "pyzmq-26.0.2-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:70770e296a9cb03d955540c99360aab861cbb3cba29516abbd106a15dbd91268"},
-    {file = "pyzmq-26.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2740fd7161b39e178554ebf21aa5667a1c9ef0cd2cb74298fd4ef017dae7aec4"},
-    {file = "pyzmq-26.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f5e3706c32dea077faa42b1c92d825b7f86c866f72532d342e0be5e64d14d858"},
-    {file = "pyzmq-26.0.2-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0fa1416876194927f7723d6b7171b95e1115602967fc6bfccbc0d2d51d8ebae1"},
-    {file = "pyzmq-26.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ef9a79a48794099c57dc2df00340b5d47c5caa1792f9ddb8c7a26b1280bd575"},
-    {file = "pyzmq-26.0.2-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:1c60fcdfa3229aeee4291c5d60faed3a813b18bdadb86299c4bf49e8e51e8605"},
-    {file = "pyzmq-26.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e943c39c206b04df2eb5d71305761d7c3ca75fd49452115ea92db1b5b98dbdef"},
-    {file = "pyzmq-26.0.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:8da0ed8a598693731c76659880a668f4748b59158f26ed283a93f7f04d47447e"},
-    {file = "pyzmq-26.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7bf51970b11d67096bede97cdbad0f4333f7664f4708b9b2acb352bf4faa3140"},
-    {file = "pyzmq-26.0.2-cp311-cp311-win32.whl", hash = "sha256:6f8e6bd5d066be605faa9fe5ec10aa1a46ad9f18fc8646f2b9aaefc8fb575742"},
-    {file = "pyzmq-26.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:6d03da3a0ae691b361edcb39530075461202f699ce05adbb15055a0e1c9bcaa4"},
-    {file = "pyzmq-26.0.2-cp311-cp311-win_arm64.whl", hash = "sha256:f84e33321b68ff00b60e9dbd1a483e31ab6022c577c8de525b8e771bd274ce68"},
-    {file = "pyzmq-26.0.2-cp312-cp312-macosx_10_15_universal2.whl", hash = "sha256:44c33ebd1c62a01db7fbc24e18bdda569d6639217d13d5929e986a2b0f69070d"},
-    {file = "pyzmq-26.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ac04f904b4fce4afea9cdccbb78e24d468cb610a839d5a698853e14e2a3f9ecf"},
-    {file = "pyzmq-26.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2133de5ba9adc5f481884ccb699eac9ce789708292945c05746880f95b241c0"},
-    {file = "pyzmq-26.0.2-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7753c67c570d7fc80c2dc59b90ca1196f1224e0e2e29a548980c95fe0fe27fc1"},
-    {file = "pyzmq-26.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d4e51632e6b12e65e8d9d7612446ecda2eda637a868afa7bce16270194650dd"},
-    {file = "pyzmq-26.0.2-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:d6c38806f6ecd0acf3104b8d7e76a206bcf56dadd6ce03720d2fa9d9157d5718"},
-    {file = "pyzmq-26.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:48f496bbe14686b51cec15406323ae6942851e14022efd7fc0e2ecd092c5982c"},
-    {file = "pyzmq-26.0.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:e84a3161149c75bb7a7dc8646384186c34033e286a67fec1ad1bdedea165e7f4"},
-    {file = "pyzmq-26.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:dabf796c67aa9f5a4fcc956d47f0d48b5c1ed288d628cf53aa1cf08e88654343"},
-    {file = "pyzmq-26.0.2-cp312-cp312-win32.whl", hash = "sha256:3eee4c676af1b109f708d80ef0cf57ecb8aaa5900d1edaf90406aea7e0e20e37"},
-    {file = "pyzmq-26.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:26721fec65846b3e4450dad050d67d31b017f97e67f7e0647b5f98aa47f828cf"},
-    {file = "pyzmq-26.0.2-cp312-cp312-win_arm64.whl", hash = "sha256:653955c6c233e90de128a1b8e882abc7216f41f44218056bd519969c8c413a15"},
-    {file = "pyzmq-26.0.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:becd8d8fb068fbb5a52096efd83a2d8e54354383f691781f53a4c26aee944542"},
-    {file = "pyzmq-26.0.2-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:7a15e5465e7083c12517209c9dd24722b25e9b63c49a563922922fc03554eb35"},
-    {file = "pyzmq-26.0.2-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e8158ac8616941f874841f9fa0f6d2f1466178c2ff91ea08353fdc19de0d40c2"},
-    {file = "pyzmq-26.0.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea2c6a53e28c7066ea7db86fcc0b71d78d01b818bb11d4a4341ec35059885295"},
-    {file = "pyzmq-26.0.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:bdbc7dab0b0e9c62c97b732899c4242e3282ba803bad668e03650b59b165466e"},
-    {file = "pyzmq-26.0.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:e74b6d5ef57bb65bf1b4a37453d8d86d88550dde3fb0f23b1f1a24e60c70af5b"},
-    {file = "pyzmq-26.0.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ed4c6ee624ecbc77b18aeeb07bf0700d26571ab95b8f723f0d02e056b5bce438"},
-    {file = "pyzmq-26.0.2-cp37-cp37m-win32.whl", hash = "sha256:8a98b3cb0484b83c19d8fb5524c8a469cd9f10e743f5904ac285d92678ee761f"},
-    {file = "pyzmq-26.0.2-cp37-cp37m-win_amd64.whl", hash = "sha256:aa5f95d71b6eca9cec28aa0a2f8310ea53dea313b63db74932879ff860c1fb8d"},
-    {file = "pyzmq-26.0.2-cp38-cp38-macosx_10_15_universal2.whl", hash = "sha256:5ff56c76ce77b9805378a7a73032c17cbdb1a5b84faa1df03c5d3e306e5616df"},
-    {file = "pyzmq-26.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bab697fc1574fee4b81da955678708567c43c813c84c91074e452bda5346c921"},
-    {file = "pyzmq-26.0.2-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:0c0fed8aa9ba0488ee1cbdaa304deea92d52fab43d373297002cfcc69c0a20c5"},
-    {file = "pyzmq-26.0.2-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:606b922699fcec472ed814dda4dc3ff7c748254e0b26762a0ba21a726eb1c107"},
-    {file = "pyzmq-26.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45f0fd82bad4d199fa993fbf0ac586a7ac5879addbe436a35a389df7e0eb4c91"},
-    {file = "pyzmq-26.0.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:166c5e41045939a52c01e6f374e493d9a6a45dfe677360d3e7026e38c42e8906"},
-    {file = "pyzmq-26.0.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:d566e859e8b8d5bca08467c093061774924b3d78a5ba290e82735b2569edc84b"},
-    {file = "pyzmq-26.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:264ee0e72b72ca59279dc320deab5ae0fac0d97881aed1875ce4bde2e56ffde0"},
-    {file = "pyzmq-26.0.2-cp38-cp38-win32.whl", hash = "sha256:3152bbd3a4744cbdd83dfb210ed701838b8b0c9065cef14671d6d91df12197d0"},
-    {file = "pyzmq-26.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:bf77601d75ca692c179154b7e5943c286a4aaffec02c491afe05e60493ce95f2"},
-    {file = "pyzmq-26.0.2-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:c770a7545b3deca2db185b59175e710a820dd4ed43619f4c02e90b0e227c6252"},
-    {file = "pyzmq-26.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d47175f0a380bfd051726bc5c0054036ae4a5d8caf922c62c8a172ccd95c1a2a"},
-    {file = "pyzmq-26.0.2-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:9bce298c1ce077837e110367c321285dc4246b531cde1abfc27e4a5bbe2bed4d"},
-    {file = "pyzmq-26.0.2-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c40b09b7e184d6e3e1be1c8af2cc320c0f9f610d8a5df3dd866e6e6e4e32b235"},
-    {file = "pyzmq-26.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d420d856bf728713874cefb911398efe69e1577835851dd297a308a78c14c249"},
-    {file = "pyzmq-26.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d792d3cab987058451e55c70c5926e93e2ceb68ca5a2334863bb903eb860c9cb"},
-    {file = "pyzmq-26.0.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:83ec17729cf6d3464dab98a11e98294fcd50e6b17eaabd3d841515c23f6dbd3a"},
-    {file = "pyzmq-26.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:47c17d5ebfa88ae90f08960c97b49917098665b8cd8be31f2c24e177bcf37a0f"},
-    {file = "pyzmq-26.0.2-cp39-cp39-win32.whl", hash = "sha256:d509685d1cd1d018705a811c5f9d5bc237790936ead6d06f6558b77e16cc7235"},
-    {file = "pyzmq-26.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:c7cc8cc009e8f6989a6d86c96f87dae5f5fb07d6c96916cdc7719d546152c7db"},
-    {file = "pyzmq-26.0.2-cp39-cp39-win_arm64.whl", hash = "sha256:3ada31cb879cd7532f4a85b501f4255c747d4813ab76b35c49ed510ce4865b45"},
-    {file = "pyzmq-26.0.2-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0a6ceaddc830dd3ca86cb8451cf373d1f05215368e11834538c2902ed5205139"},
-    {file = "pyzmq-26.0.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a967681463aa7a99eb9a62bb18229b653b45c10ff0947b31cc0837a83dfb86f"},
-    {file = "pyzmq-26.0.2-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6472a73bc115bc40a2076609a90894775abe6faf19a78375675a2f889a613071"},
-    {file = "pyzmq-26.0.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d6aea92bcccfe5e5524d3c70a6f16ffdae548390ddad26f4207d55c55a40593"},
-    {file = "pyzmq-26.0.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:e025f6351e49d48a5aa2f5a09293aa769b0ee7369c25bed551647234b7fa0c75"},
-    {file = "pyzmq-26.0.2-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:40bd7ebe4dbb37d27f0c56e2a844f360239343a99be422085e13e97da13f73f9"},
-    {file = "pyzmq-26.0.2-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:1dd40d586ad6f53764104df6e01810fe1b4e88fd353774629a5e6fe253813f79"},
-    {file = "pyzmq-26.0.2-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f2aca15e9ad8c8657b5b3d7ae3d1724dc8c1c1059c06b4b674c3aa36305f4930"},
-    {file = "pyzmq-26.0.2-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:450ec234736732eb0ebeffdb95a352450d4592f12c3e087e2a9183386d22c8bf"},
-    {file = "pyzmq-26.0.2-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:f43be2bebbd09360a2f23af83b243dc25ffe7b583ea8c722e6df03e03a55f02f"},
-    {file = "pyzmq-26.0.2-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:867f55e54aff254940bcec5eec068e7c0ac1e6bf360ab91479394a8bf356b0e6"},
-    {file = "pyzmq-26.0.2-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:b4dbc033c5ad46f8c429bf238c25a889b8c1d86bfe23a74e1031a991cb3f0000"},
-    {file = "pyzmq-26.0.2-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6e8dd2961462e337e21092ec2da0c69d814dcb1b6e892955a37444a425e9cfb8"},
-    {file = "pyzmq-26.0.2-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35391e72df6c14a09b697c7b94384947c1dd326aca883ff98ff137acdf586c33"},
-    {file = "pyzmq-26.0.2-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:1c3d3c92fa54eda94ab369ca5b8d35059987c326ba5e55326eb068862f64b1fc"},
-    {file = "pyzmq-26.0.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e7aa61a9cc4f0523373e31fc9255bf4567185a099f85ca3598e64de484da3ab2"},
-    {file = "pyzmq-26.0.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee53a8191271f144cc20b12c19daa9f1546adc84a2f33839e3338039b55c373c"},
-    {file = "pyzmq-26.0.2-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ac60a980f07fa988983f7bfe6404ef3f1e4303f5288a01713bc1266df6d18783"},
-    {file = "pyzmq-26.0.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88896b1b4817d7b2fe1ec7205c4bbe07bf5d92fb249bf2d226ddea8761996068"},
-    {file = "pyzmq-26.0.2-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:18dfffe23751edee917764ffa133d5d3fef28dfd1cf3adebef8c90bc854c74c4"},
-    {file = "pyzmq-26.0.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:6926dd14cfe6967d3322640b6d5c3c3039db71716a5e43cca6e3b474e73e0b36"},
-    {file = "pyzmq-26.0.2.tar.gz", hash = "sha256:f0f9bb370449158359bb72a3e12c658327670c0ffe6fbcd1af083152b64f9df0"},
+    {file = "pyzmq-26.0.3-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:44dd6fc3034f1eaa72ece33588867df9e006a7303725a12d64c3dff92330f625"},
+    {file = "pyzmq-26.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:acb704195a71ac5ea5ecf2811c9ee19ecdc62b91878528302dd0be1b9451cc90"},
+    {file = "pyzmq-26.0.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5dbb9c997932473a27afa93954bb77a9f9b786b4ccf718d903f35da3232317de"},
+    {file = "pyzmq-26.0.3-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6bcb34f869d431799c3ee7d516554797f7760cb2198ecaa89c3f176f72d062be"},
+    {file = "pyzmq-26.0.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:38ece17ec5f20d7d9b442e5174ae9f020365d01ba7c112205a4d59cf19dc38ee"},
+    {file = "pyzmq-26.0.3-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:ba6e5e6588e49139a0979d03a7deb9c734bde647b9a8808f26acf9c547cab1bf"},
+    {file = "pyzmq-26.0.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:3bf8b000a4e2967e6dfdd8656cd0757d18c7e5ce3d16339e550bd462f4857e59"},
+    {file = "pyzmq-26.0.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:2136f64fbb86451dbbf70223635a468272dd20075f988a102bf8a3f194a411dc"},
+    {file = "pyzmq-26.0.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e8918973fbd34e7814f59143c5f600ecd38b8038161239fd1a3d33d5817a38b8"},
+    {file = "pyzmq-26.0.3-cp310-cp310-win32.whl", hash = "sha256:0aaf982e68a7ac284377d051c742610220fd06d330dcd4c4dbb4cdd77c22a537"},
+    {file = "pyzmq-26.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:f1a9b7d00fdf60b4039f4455afd031fe85ee8305b019334b72dcf73c567edc47"},
+    {file = "pyzmq-26.0.3-cp310-cp310-win_arm64.whl", hash = "sha256:80b12f25d805a919d53efc0a5ad7c0c0326f13b4eae981a5d7b7cc343318ebb7"},
+    {file = "pyzmq-26.0.3-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:a72a84570f84c374b4c287183debc776dc319d3e8ce6b6a0041ce2e400de3f32"},
+    {file = "pyzmq-26.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7ca684ee649b55fd8f378127ac8462fb6c85f251c2fb027eb3c887e8ee347bcd"},
+    {file = "pyzmq-26.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e222562dc0f38571c8b1ffdae9d7adb866363134299264a1958d077800b193b7"},
+    {file = "pyzmq-26.0.3-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f17cde1db0754c35a91ac00b22b25c11da6eec5746431d6e5092f0cd31a3fea9"},
+    {file = "pyzmq-26.0.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b7c0c0b3244bb2275abe255d4a30c050d541c6cb18b870975553f1fb6f37527"},
+    {file = "pyzmq-26.0.3-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:ac97a21de3712afe6a6c071abfad40a6224fd14fa6ff0ff8d0c6e6cd4e2f807a"},
+    {file = "pyzmq-26.0.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:88b88282e55fa39dd556d7fc04160bcf39dea015f78e0cecec8ff4f06c1fc2b5"},
+    {file = "pyzmq-26.0.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:72b67f966b57dbd18dcc7efbc1c7fc9f5f983e572db1877081f075004614fcdd"},
+    {file = "pyzmq-26.0.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f4b6cecbbf3b7380f3b61de3a7b93cb721125dc125c854c14ddc91225ba52f83"},
+    {file = "pyzmq-26.0.3-cp311-cp311-win32.whl", hash = "sha256:eed56b6a39216d31ff8cd2f1d048b5bf1700e4b32a01b14379c3b6dde9ce3aa3"},
+    {file = "pyzmq-26.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:3191d312c73e3cfd0f0afdf51df8405aafeb0bad71e7ed8f68b24b63c4f36500"},
+    {file = "pyzmq-26.0.3-cp311-cp311-win_arm64.whl", hash = "sha256:b6907da3017ef55139cf0e417c5123a84c7332520e73a6902ff1f79046cd3b94"},
+    {file = "pyzmq-26.0.3-cp312-cp312-macosx_10_15_universal2.whl", hash = "sha256:068ca17214038ae986d68f4a7021f97e187ed278ab6dccb79f837d765a54d753"},
+    {file = "pyzmq-26.0.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:7821d44fe07335bea256b9f1f41474a642ca55fa671dfd9f00af8d68a920c2d4"},
+    {file = "pyzmq-26.0.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eeb438a26d87c123bb318e5f2b3d86a36060b01f22fbdffd8cf247d52f7c9a2b"},
+    {file = "pyzmq-26.0.3-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:69ea9d6d9baa25a4dc9cef5e2b77b8537827b122214f210dd925132e34ae9b12"},
+    {file = "pyzmq-26.0.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7daa3e1369355766dea11f1d8ef829905c3b9da886ea3152788dc25ee6079e02"},
+    {file = "pyzmq-26.0.3-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:6ca7a9a06b52d0e38ccf6bca1aeff7be178917893f3883f37b75589d42c4ac20"},
+    {file = "pyzmq-26.0.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:1b7d0e124948daa4d9686d421ef5087c0516bc6179fdcf8828b8444f8e461a77"},
+    {file = "pyzmq-26.0.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:e746524418b70f38550f2190eeee834db8850088c834d4c8406fbb9bc1ae10b2"},
+    {file = "pyzmq-26.0.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:6b3146f9ae6af82c47a5282ac8803523d381b3b21caeae0327ed2f7ecb718798"},
+    {file = "pyzmq-26.0.3-cp312-cp312-win32.whl", hash = "sha256:2b291d1230845871c00c8462c50565a9cd6026fe1228e77ca934470bb7d70ea0"},
+    {file = "pyzmq-26.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:926838a535c2c1ea21c903f909a9a54e675c2126728c21381a94ddf37c3cbddf"},
+    {file = "pyzmq-26.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:5bf6c237f8c681dfb91b17f8435b2735951f0d1fad10cc5dfd96db110243370b"},
+    {file = "pyzmq-26.0.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0c0991f5a96a8e620f7691e61178cd8f457b49e17b7d9cfa2067e2a0a89fc1d5"},
+    {file = "pyzmq-26.0.3-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:dbf012d8fcb9f2cf0643b65df3b355fdd74fc0035d70bb5c845e9e30a3a4654b"},
+    {file = "pyzmq-26.0.3-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:01fbfbeb8249a68d257f601deb50c70c929dc2dfe683b754659569e502fbd3aa"},
+    {file = "pyzmq-26.0.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c8eb19abe87029c18f226d42b8a2c9efdd139d08f8bf6e085dd9075446db450"},
+    {file = "pyzmq-26.0.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:5344b896e79800af86ad643408ca9aa303a017f6ebff8cee5a3163c1e9aec987"},
+    {file = "pyzmq-26.0.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:204e0f176fd1d067671157d049466869b3ae1fc51e354708b0dc41cf94e23a3a"},
+    {file = "pyzmq-26.0.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a42db008d58530efa3b881eeee4991146de0b790e095f7ae43ba5cc612decbc5"},
+    {file = "pyzmq-26.0.3-cp37-cp37m-win32.whl", hash = "sha256:8d7a498671ca87e32b54cb47c82a92b40130a26c5197d392720a1bce1b3c77cf"},
+    {file = "pyzmq-26.0.3-cp37-cp37m-win_amd64.whl", hash = "sha256:3b4032a96410bdc760061b14ed6a33613ffb7f702181ba999df5d16fb96ba16a"},
+    {file = "pyzmq-26.0.3-cp38-cp38-macosx_10_15_universal2.whl", hash = "sha256:2cc4e280098c1b192c42a849de8de2c8e0f3a84086a76ec5b07bfee29bda7d18"},
+    {file = "pyzmq-26.0.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5bde86a2ed3ce587fa2b207424ce15b9a83a9fa14422dcc1c5356a13aed3df9d"},
+    {file = "pyzmq-26.0.3-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:34106f68e20e6ff253c9f596ea50397dbd8699828d55e8fa18bd4323d8d966e6"},
+    {file = "pyzmq-26.0.3-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ebbbd0e728af5db9b04e56389e2299a57ea8b9dd15c9759153ee2455b32be6ad"},
+    {file = "pyzmq-26.0.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f6b1d1c631e5940cac5a0b22c5379c86e8df6a4ec277c7a856b714021ab6cfad"},
+    {file = "pyzmq-26.0.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:e891ce81edd463b3b4c3b885c5603c00141151dd9c6936d98a680c8c72fe5c67"},
+    {file = "pyzmq-26.0.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:9b273ecfbc590a1b98f014ae41e5cf723932f3b53ba9367cfb676f838038b32c"},
+    {file = "pyzmq-26.0.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b32bff85fb02a75ea0b68f21e2412255b5731f3f389ed9aecc13a6752f58ac97"},
+    {file = "pyzmq-26.0.3-cp38-cp38-win32.whl", hash = "sha256:f6c21c00478a7bea93caaaef9e7629145d4153b15a8653e8bb4609d4bc70dbfc"},
+    {file = "pyzmq-26.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:3401613148d93ef0fd9aabdbddb212de3db7a4475367f49f590c837355343972"},
+    {file = "pyzmq-26.0.3-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:2ed8357f4c6e0daa4f3baf31832df8a33334e0fe5b020a61bc8b345a3db7a606"},
+    {file = "pyzmq-26.0.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c1c8f2a2ca45292084c75bb6d3a25545cff0ed931ed228d3a1810ae3758f975f"},
+    {file = "pyzmq-26.0.3-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:b63731993cdddcc8e087c64e9cf003f909262b359110070183d7f3025d1c56b5"},
+    {file = "pyzmq-26.0.3-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b3cd31f859b662ac5d7f4226ec7d8bd60384fa037fc02aee6ff0b53ba29a3ba8"},
+    {file = "pyzmq-26.0.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:115f8359402fa527cf47708d6f8a0f8234f0e9ca0cab7c18c9c189c194dbf620"},
+    {file = "pyzmq-26.0.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:715bdf952b9533ba13dfcf1f431a8f49e63cecc31d91d007bc1deb914f47d0e4"},
+    {file = "pyzmq-26.0.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:e1258c639e00bf5e8a522fec6c3eaa3e30cf1c23a2f21a586be7e04d50c9acab"},
+    {file = "pyzmq-26.0.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:15c59e780be8f30a60816a9adab900c12a58d79c1ac742b4a8df044ab2a6d920"},
+    {file = "pyzmq-26.0.3-cp39-cp39-win32.whl", hash = "sha256:d0cdde3c78d8ab5b46595054e5def32a755fc028685add5ddc7403e9f6de9879"},
+    {file = "pyzmq-26.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:ce828058d482ef860746bf532822842e0ff484e27f540ef5c813d516dd8896d2"},
+    {file = "pyzmq-26.0.3-cp39-cp39-win_arm64.whl", hash = "sha256:788f15721c64109cf720791714dc14afd0f449d63f3a5487724f024345067381"},
+    {file = "pyzmq-26.0.3-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:2c18645ef6294d99b256806e34653e86236eb266278c8ec8112622b61db255de"},
+    {file = "pyzmq-26.0.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7e6bc96ebe49604df3ec2c6389cc3876cabe475e6bfc84ced1bf4e630662cb35"},
+    {file = "pyzmq-26.0.3-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:971e8990c5cc4ddcff26e149398fc7b0f6a042306e82500f5e8db3b10ce69f84"},
+    {file = "pyzmq-26.0.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8416c23161abd94cc7da80c734ad7c9f5dbebdadfdaa77dad78244457448223"},
+    {file = "pyzmq-26.0.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:082a2988364b60bb5de809373098361cf1dbb239623e39e46cb18bc035ed9c0c"},
+    {file = "pyzmq-26.0.3-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d57dfbf9737763b3a60d26e6800e02e04284926329aee8fb01049635e957fe81"},
+    {file = "pyzmq-26.0.3-pp37-pypy37_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:77a85dca4c2430ac04dc2a2185c2deb3858a34fe7f403d0a946fa56970cf60a1"},
+    {file = "pyzmq-26.0.3-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:4c82a6d952a1d555bf4be42b6532927d2a5686dd3c3e280e5f63225ab47ac1f5"},
+    {file = "pyzmq-26.0.3-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4496b1282c70c442809fc1b151977c3d967bfb33e4e17cedbf226d97de18f709"},
+    {file = "pyzmq-26.0.3-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:e4946d6bdb7ba972dfda282f9127e5756d4f299028b1566d1245fa0d438847e6"},
+    {file = "pyzmq-26.0.3-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:03c0ae165e700364b266876d712acb1ac02693acd920afa67da2ebb91a0b3c09"},
+    {file = "pyzmq-26.0.3-pp38-pypy38_pp73-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:3e3070e680f79887d60feeda051a58d0ac36622e1759f305a41059eff62c6da7"},
+    {file = "pyzmq-26.0.3-pp38-pypy38_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:6ca08b840fe95d1c2bd9ab92dac5685f949fc6f9ae820ec16193e5ddf603c3b2"},
+    {file = "pyzmq-26.0.3-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e76654e9dbfb835b3518f9938e565c7806976c07b37c33526b574cc1a1050480"},
+    {file = "pyzmq-26.0.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:871587bdadd1075b112e697173e946a07d722459d20716ceb3d1bd6c64bd08ce"},
+    {file = "pyzmq-26.0.3-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d0a2d1bd63a4ad79483049b26514e70fa618ce6115220da9efdff63688808b17"},
+    {file = "pyzmq-26.0.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0270b49b6847f0d106d64b5086e9ad5dc8a902413b5dbbb15d12b60f9c1747a4"},
+    {file = "pyzmq-26.0.3-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:703c60b9910488d3d0954ca585c34f541e506a091a41930e663a098d3b794c67"},
+    {file = "pyzmq-26.0.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:74423631b6be371edfbf7eabb02ab995c2563fee60a80a30829176842e71722a"},
+    {file = "pyzmq-26.0.3-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:4adfbb5451196842a88fda3612e2c0414134874bffb1c2ce83ab4242ec9e027d"},
+    {file = "pyzmq-26.0.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:3516119f4f9b8671083a70b6afaa0a070f5683e431ab3dc26e9215620d7ca1ad"},
+    {file = "pyzmq-26.0.3.tar.gz", hash = "sha256:dba7d9f2e047dfa2bca3b01f4f84aa5246725203d6284e3790f2ca15fba6b40a"},
 ]
 
 [package.dependencies]
@@ -3523,13 +3516,13 @@ test = ["pytest", "pytest-mock"]
 
 [[package]]
 name = "referencing"
-version = "0.35.0"
+version = "0.35.1"
 description = "JSON Referencing + Python"
 optional = false
 python-versions = ">=3.8"
 files = [
-    {file = "referencing-0.35.0-py3-none-any.whl", hash = "sha256:8080727b30e364e5783152903672df9b6b091c926a146a759080b62ca3126cd6"},
-    {file = "referencing-0.35.0.tar.gz", hash = "sha256:191e936b0c696d0af17ad7430a3dc68e88bc11be6514f4757dc890f04ab05889"},
+    {file = "referencing-0.35.1-py3-none-any.whl", hash = "sha256:eda6d3234d62814d1c64e305c1331c9a3a6132da475ab6382eaa997b21ee75de"},
+    {file = "referencing-0.35.1.tar.gz", hash = "sha256:25b42124a6c8b632a425174f24087783efb348a6f1e0008e63cd4466fedf703c"},
 ]
 
 [package.dependencies]
@@ -3538,104 +3531,90 @@ rpds-py = ">=0.7.0"
 
 [[package]]
 name = "regex"
-version = "2024.4.16"
+version = "2024.5.15"
 description = "Alternative regular expression module, to replace re."
 optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
 files = [
-    {file = "regex-2024.4.16-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:fb83cc090eac63c006871fd24db5e30a1f282faa46328572661c0a24a2323a08"},
-    {file = "regex-2024.4.16-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8c91e1763696c0eb66340c4df98623c2d4e77d0746b8f8f2bee2c6883fd1fe18"},
-    {file = "regex-2024.4.16-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:10188fe732dec829c7acca7422cdd1bf57d853c7199d5a9e96bb4d40db239c73"},
-    {file = "regex-2024.4.16-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:956b58d692f235cfbf5b4f3abd6d99bf102f161ccfe20d2fd0904f51c72c4c66"},
-    {file = "regex-2024.4.16-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a70b51f55fd954d1f194271695821dd62054d949efd6368d8be64edd37f55c86"},
-    {file = "regex-2024.4.16-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c02fcd2bf45162280613d2e4a1ca3ac558ff921ae4e308ecb307650d3a6ee51"},
-    {file = "regex-2024.4.16-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c4ed75ea6892a56896d78f11006161eea52c45a14994794bcfa1654430984b22"},
-    {file = "regex-2024.4.16-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bd727ad276bb91928879f3aa6396c9a1d34e5e180dce40578421a691eeb77f47"},
-    {file = "regex-2024.4.16-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7cbc5d9e8a1781e7be17da67b92580d6ce4dcef5819c1b1b89f49d9678cc278c"},
-    {file = "regex-2024.4.16-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:78fddb22b9ef810b63ef341c9fcf6455232d97cfe03938cbc29e2672c436670e"},
-    {file = "regex-2024.4.16-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:445ca8d3c5a01309633a0c9db57150312a181146315693273e35d936472df912"},
-    {file = "regex-2024.4.16-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:95399831a206211d6bc40224af1c635cb8790ddd5c7493e0bd03b85711076a53"},
-    {file = "regex-2024.4.16-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:7731728b6568fc286d86745f27f07266de49603a6fdc4d19c87e8c247be452af"},
-    {file = "regex-2024.4.16-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4facc913e10bdba42ec0aee76d029aedda628161a7ce4116b16680a0413f658a"},
-    {file = "regex-2024.4.16-cp310-cp310-win32.whl", hash = "sha256:911742856ce98d879acbea33fcc03c1d8dc1106234c5e7d068932c945db209c0"},
-    {file = "regex-2024.4.16-cp310-cp310-win_amd64.whl", hash = "sha256:e0a2df336d1135a0b3a67f3bbf78a75f69562c1199ed9935372b82215cddd6e2"},
-    {file = "regex-2024.4.16-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1210365faba7c2150451eb78ec5687871c796b0f1fa701bfd2a4a25420482d26"},
-    {file = "regex-2024.4.16-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9ab40412f8cd6f615bfedea40c8bf0407d41bf83b96f6fc9ff34976d6b7037fd"},
-    {file = "regex-2024.4.16-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fd80d1280d473500d8086d104962a82d77bfbf2b118053824b7be28cd5a79ea5"},
-    {file = "regex-2024.4.16-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bb966fdd9217e53abf824f437a5a2d643a38d4fd5fd0ca711b9da683d452969"},
-    {file = "regex-2024.4.16-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:20b7a68444f536365af42a75ccecb7ab41a896a04acf58432db9e206f4e525d6"},
-    {file = "regex-2024.4.16-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b74586dd0b039c62416034f811d7ee62810174bb70dffcca6439f5236249eb09"},
-    {file = "regex-2024.4.16-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c8290b44d8b0af4e77048646c10c6e3aa583c1ca67f3b5ffb6e06cf0c6f0f89"},
-    {file = "regex-2024.4.16-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2d80a6749724b37853ece57988b39c4e79d2b5fe2869a86e8aeae3bbeef9eb0"},
-    {file = "regex-2024.4.16-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:3a1018e97aeb24e4f939afcd88211ace472ba566efc5bdf53fd8fd7f41fa7170"},
-    {file = "regex-2024.4.16-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:8d015604ee6204e76569d2f44e5a210728fa917115bef0d102f4107e622b08d5"},
-    {file = "regex-2024.4.16-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:3d5ac5234fb5053850d79dd8eb1015cb0d7d9ed951fa37aa9e6249a19aa4f336"},
-    {file = "regex-2024.4.16-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:0a38d151e2cdd66d16dab550c22f9521ba79761423b87c01dae0a6e9add79c0d"},
-    {file = "regex-2024.4.16-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:159dc4e59a159cb8e4e8f8961eb1fa5d58f93cb1acd1701d8aff38d45e1a84a6"},
-    {file = "regex-2024.4.16-cp311-cp311-win32.whl", hash = "sha256:ba2336d6548dee3117520545cfe44dc28a250aa091f8281d28804aa8d707d93d"},
-    {file = "regex-2024.4.16-cp311-cp311-win_amd64.whl", hash = "sha256:8f83b6fd3dc3ba94d2b22717f9c8b8512354fd95221ac661784df2769ea9bba9"},
-    {file = "regex-2024.4.16-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:80b696e8972b81edf0af2a259e1b2a4a661f818fae22e5fa4fa1a995fb4a40fd"},
-    {file = "regex-2024.4.16-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d61ae114d2a2311f61d90c2ef1358518e8f05eafda76eaf9c772a077e0b465ec"},
-    {file = "regex-2024.4.16-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8ba6745440b9a27336443b0c285d705ce73adb9ec90e2f2004c64d95ab5a7598"},
-    {file = "regex-2024.4.16-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6295004b2dd37b0835ea5c14a33e00e8cfa3c4add4d587b77287825f3418d310"},
-    {file = "regex-2024.4.16-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4aba818dcc7263852aabb172ec27b71d2abca02a593b95fa79351b2774eb1d2b"},
-    {file = "regex-2024.4.16-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d0800631e565c47520aaa04ae38b96abc5196fe8b4aa9bd864445bd2b5848a7a"},
-    {file = "regex-2024.4.16-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:08dea89f859c3df48a440dbdcd7b7155bc675f2fa2ec8c521d02dc69e877db70"},
-    {file = "regex-2024.4.16-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eeaa0b5328b785abc344acc6241cffde50dc394a0644a968add75fcefe15b9d4"},
-    {file = "regex-2024.4.16-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4e819a806420bc010489f4e741b3036071aba209f2e0989d4750b08b12a9343f"},
-    {file = "regex-2024.4.16-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:c2d0e7cbb6341e830adcbfa2479fdeebbfbb328f11edd6b5675674e7a1e37730"},
-    {file = "regex-2024.4.16-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:91797b98f5e34b6a49f54be33f72e2fb658018ae532be2f79f7c63b4ae225145"},
-    {file = "regex-2024.4.16-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:d2da13568eff02b30fd54fccd1e042a70fe920d816616fda4bf54ec705668d81"},
-    {file = "regex-2024.4.16-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:370c68dc5570b394cbaadff50e64d705f64debed30573e5c313c360689b6aadc"},
-    {file = "regex-2024.4.16-cp312-cp312-win32.whl", hash = "sha256:904c883cf10a975b02ab3478bce652f0f5346a2c28d0a8521d97bb23c323cc8b"},
-    {file = "regex-2024.4.16-cp312-cp312-win_amd64.whl", hash = "sha256:785c071c982dce54d44ea0b79cd6dfafddeccdd98cfa5f7b86ef69b381b457d9"},
-    {file = "regex-2024.4.16-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e2f142b45c6fed48166faeb4303b4b58c9fcd827da63f4cf0a123c3480ae11fb"},
-    {file = "regex-2024.4.16-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e87ab229332ceb127a165612d839ab87795972102cb9830e5f12b8c9a5c1b508"},
-    {file = "regex-2024.4.16-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:81500ed5af2090b4a9157a59dbc89873a25c33db1bb9a8cf123837dcc9765047"},
-    {file = "regex-2024.4.16-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b340cccad138ecb363324aa26893963dcabb02bb25e440ebdf42e30963f1a4e0"},
-    {file = "regex-2024.4.16-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c72608e70f053643437bd2be0608f7f1c46d4022e4104d76826f0839199347a"},
-    {file = "regex-2024.4.16-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a01fe2305e6232ef3e8f40bfc0f0f3a04def9aab514910fa4203bafbc0bb4682"},
-    {file = "regex-2024.4.16-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:03576e3a423d19dda13e55598f0fd507b5d660d42c51b02df4e0d97824fdcae3"},
-    {file = "regex-2024.4.16-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:549c3584993772e25f02d0656ac48abdda73169fe347263948cf2b1cead622f3"},
-    {file = "regex-2024.4.16-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:34422d5a69a60b7e9a07a690094e824b66f5ddc662a5fc600d65b7c174a05f04"},
-    {file = "regex-2024.4.16-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:5f580c651a72b75c39e311343fe6875d6f58cf51c471a97f15a938d9fe4e0d37"},
-    {file = "regex-2024.4.16-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:3399dd8a7495bbb2bacd59b84840eef9057826c664472e86c91d675d007137f5"},
-    {file = "regex-2024.4.16-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8d1f86f3f4e2388aa3310b50694ac44daefbd1681def26b4519bd050a398dc5a"},
-    {file = "regex-2024.4.16-cp37-cp37m-win32.whl", hash = "sha256:dd5acc0a7d38fdc7a3a6fd3ad14c880819008ecb3379626e56b163165162cc46"},
-    {file = "regex-2024.4.16-cp37-cp37m-win_amd64.whl", hash = "sha256:ba8122e3bb94ecda29a8de4cf889f600171424ea586847aa92c334772d200331"},
-    {file = "regex-2024.4.16-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:743deffdf3b3481da32e8a96887e2aa945ec6685af1cfe2bcc292638c9ba2f48"},
-    {file = "regex-2024.4.16-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7571f19f4a3fd00af9341c7801d1ad1967fc9c3f5e62402683047e7166b9f2b4"},
-    {file = "regex-2024.4.16-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:df79012ebf6f4efb8d307b1328226aef24ca446b3ff8d0e30202d7ebcb977a8c"},
-    {file = "regex-2024.4.16-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e757d475953269fbf4b441207bb7dbdd1c43180711b6208e129b637792ac0b93"},
-    {file = "regex-2024.4.16-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4313ab9bf6a81206c8ac28fdfcddc0435299dc88cad12cc6305fd0e78b81f9e4"},
-    {file = "regex-2024.4.16-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d83c2bc678453646f1a18f8db1e927a2d3f4935031b9ad8a76e56760461105dd"},
-    {file = "regex-2024.4.16-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9df1bfef97db938469ef0a7354b2d591a2d438bc497b2c489471bec0e6baf7c4"},
-    {file = "regex-2024.4.16-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62120ed0de69b3649cc68e2965376048793f466c5a6c4370fb27c16c1beac22d"},
-    {file = "regex-2024.4.16-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c2ef6f7990b6e8758fe48ad08f7e2f66c8f11dc66e24093304b87cae9037bb4a"},
-    {file = "regex-2024.4.16-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8fc6976a3395fe4d1fbeb984adaa8ec652a1e12f36b56ec8c236e5117b585427"},
-    {file = "regex-2024.4.16-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:03e68f44340528111067cecf12721c3df4811c67268b897fbe695c95f860ac42"},
-    {file = "regex-2024.4.16-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:ec7e0043b91115f427998febaa2beb82c82df708168b35ece3accb610b91fac1"},
-    {file = "regex-2024.4.16-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:c21fc21a4c7480479d12fd8e679b699f744f76bb05f53a1d14182b31f55aac76"},
-    {file = "regex-2024.4.16-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:12f6a3f2f58bb7344751919a1876ee1b976fe08b9ffccb4bbea66f26af6017b9"},
-    {file = "regex-2024.4.16-cp38-cp38-win32.whl", hash = "sha256:479595a4fbe9ed8f8f72c59717e8cf222da2e4c07b6ae5b65411e6302af9708e"},
-    {file = "regex-2024.4.16-cp38-cp38-win_amd64.whl", hash = "sha256:0534b034fba6101611968fae8e856c1698da97ce2efb5c2b895fc8b9e23a5834"},
-    {file = "regex-2024.4.16-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a7ccdd1c4a3472a7533b0a7aa9ee34c9a2bef859ba86deec07aff2ad7e0c3b94"},
-    {file = "regex-2024.4.16-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6f2f017c5be19984fbbf55f8af6caba25e62c71293213f044da3ada7091a4455"},
-    {file = "regex-2024.4.16-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:803b8905b52de78b173d3c1e83df0efb929621e7b7c5766c0843704d5332682f"},
-    {file = "regex-2024.4.16-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:684008ec44ad275832a5a152f6e764bbe1914bea10968017b6feaecdad5736e0"},
-    {file = "regex-2024.4.16-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:65436dce9fdc0aeeb0a0effe0839cb3d6a05f45aa45a4d9f9c60989beca78b9c"},
-    {file = "regex-2024.4.16-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea355eb43b11764cf799dda62c658c4d2fdb16af41f59bb1ccfec517b60bcb07"},
-    {file = "regex-2024.4.16-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98c1165f3809ce7774f05cb74e5408cd3aa93ee8573ae959a97a53db3ca3180d"},
-    {file = "regex-2024.4.16-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cccc79a9be9b64c881f18305a7c715ba199e471a3973faeb7ba84172abb3f317"},
-    {file = "regex-2024.4.16-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:00169caa125f35d1bca6045d65a662af0202704489fada95346cfa092ec23f39"},
-    {file = "regex-2024.4.16-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:6cc38067209354e16c5609b66285af17a2863a47585bcf75285cab33d4c3b8df"},
-    {file = "regex-2024.4.16-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:23cff1b267038501b179ccbbd74a821ac4a7192a1852d1d558e562b507d46013"},
-    {file = "regex-2024.4.16-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:b9d320b3bf82a39f248769fc7f188e00f93526cc0fe739cfa197868633d44701"},
-    {file = "regex-2024.4.16-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:89ec7f2c08937421bbbb8b48c54096fa4f88347946d4747021ad85f1b3021b3c"},
-    {file = "regex-2024.4.16-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4918fd5f8b43aa7ec031e0fef1ee02deb80b6afd49c85f0790be1dc4ce34cb50"},
-    {file = "regex-2024.4.16-cp39-cp39-win32.whl", hash = "sha256:684e52023aec43bdf0250e843e1fdd6febbe831bd9d52da72333fa201aaa2335"},
-    {file = "regex-2024.4.16-cp39-cp39-win_amd64.whl", hash = "sha256:e697e1c0238133589e00c244a8b676bc2cfc3ab4961318d902040d099fec7483"},
-    {file = "regex-2024.4.16.tar.gz", hash = "sha256:fa454d26f2e87ad661c4f0c5a5fe4cf6aab1e307d1b94f16ffdfcb089ba685c0"},
+    {file = "regex-2024.5.15-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a81e3cfbae20378d75185171587cbf756015ccb14840702944f014e0d93ea09f"},
+    {file = "regex-2024.5.15-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7b59138b219ffa8979013be7bc85bb60c6f7b7575df3d56dc1e403a438c7a3f6"},
+    {file = "regex-2024.5.15-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a0bd000c6e266927cb7a1bc39d55be95c4b4f65c5be53e659537537e019232b1"},
+    {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5eaa7ddaf517aa095fa8da0b5015c44d03da83f5bd49c87961e3c997daed0de7"},
+    {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba68168daedb2c0bab7fd7e00ced5ba90aebf91024dea3c88ad5063c2a562cca"},
+    {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6e8d717bca3a6e2064fc3a08df5cbe366369f4b052dcd21b7416e6d71620dca1"},
+    {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1337b7dbef9b2f71121cdbf1e97e40de33ff114801263b275aafd75303bd62b5"},
+    {file = "regex-2024.5.15-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f9ebd0a36102fcad2f03696e8af4ae682793a5d30b46c647eaf280d6cfb32796"},
+    {file = "regex-2024.5.15-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9efa1a32ad3a3ea112224897cdaeb6aa00381627f567179c0314f7b65d354c62"},
+    {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1595f2d10dff3d805e054ebdc41c124753631b6a471b976963c7b28543cf13b0"},
+    {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b802512f3e1f480f41ab5f2cfc0e2f761f08a1f41092d6718868082fc0d27143"},
+    {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:a0981022dccabca811e8171f913de05720590c915b033b7e601f35ce4ea7019f"},
+    {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:19068a6a79cf99a19ccefa44610491e9ca02c2be3305c7760d3831d38a467a6f"},
+    {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:1b5269484f6126eee5e687785e83c6b60aad7663dafe842b34691157e5083e53"},
+    {file = "regex-2024.5.15-cp310-cp310-win32.whl", hash = "sha256:ada150c5adfa8fbcbf321c30c751dc67d2f12f15bd183ffe4ec7cde351d945b3"},
+    {file = "regex-2024.5.15-cp310-cp310-win_amd64.whl", hash = "sha256:ac394ff680fc46b97487941f5e6ae49a9f30ea41c6c6804832063f14b2a5a145"},
+    {file = "regex-2024.5.15-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f5b1dff3ad008dccf18e652283f5e5339d70bf8ba7c98bf848ac33db10f7bc7a"},
+    {file = "regex-2024.5.15-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c6a2b494a76983df8e3d3feea9b9ffdd558b247e60b92f877f93a1ff43d26656"},
+    {file = "regex-2024.5.15-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a32b96f15c8ab2e7d27655969a23895eb799de3665fa94349f3b2fbfd547236f"},
+    {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:10002e86e6068d9e1c91eae8295ef690f02f913c57db120b58fdd35a6bb1af35"},
+    {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ec54d5afa89c19c6dd8541a133be51ee1017a38b412b1321ccb8d6ddbeb4cf7d"},
+    {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:10e4ce0dca9ae7a66e6089bb29355d4432caed736acae36fef0fdd7879f0b0cb"},
+    {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3e507ff1e74373c4d3038195fdd2af30d297b4f0950eeda6f515ae3d84a1770f"},
+    {file = "regex-2024.5.15-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d1f059a4d795e646e1c37665b9d06062c62d0e8cc3c511fe01315973a6542e40"},
+    {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0721931ad5fe0dda45d07f9820b90b2148ccdd8e45bb9e9b42a146cb4f695649"},
+    {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:833616ddc75ad595dee848ad984d067f2f31be645d603e4d158bba656bbf516c"},
+    {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:287eb7f54fc81546346207c533ad3c2c51a8d61075127d7f6d79aaf96cdee890"},
+    {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:19dfb1c504781a136a80ecd1fff9f16dddf5bb43cec6871778c8a907a085bb3d"},
+    {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:119af6e56dce35e8dfb5222573b50c89e5508d94d55713c75126b753f834de68"},
+    {file = "regex-2024.5.15-cp311-cp311-win32.whl", hash = "sha256:1c1c174d6ec38d6c8a7504087358ce9213d4332f6293a94fbf5249992ba54efa"},
+    {file = "regex-2024.5.15-cp311-cp311-win_amd64.whl", hash = "sha256:9e717956dcfd656f5055cc70996ee2cc82ac5149517fc8e1b60261b907740201"},
+    {file = "regex-2024.5.15-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:632b01153e5248c134007209b5c6348a544ce96c46005d8456de1d552455b014"},
+    {file = "regex-2024.5.15-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e64198f6b856d48192bf921421fdd8ad8eb35e179086e99e99f711957ffedd6e"},
+    {file = "regex-2024.5.15-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68811ab14087b2f6e0fc0c2bae9ad689ea3584cad6917fc57be6a48bbd012c49"},
+    {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8ec0c2fea1e886a19c3bee0cd19d862b3aa75dcdfb42ebe8ed30708df64687a"},
+    {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d0c0c0003c10f54a591d220997dd27d953cd9ccc1a7294b40a4be5312be8797b"},
+    {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2431b9e263af1953c55abbd3e2efca67ca80a3de8a0437cb58e2421f8184717a"},
+    {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a605586358893b483976cffc1723fb0f83e526e8f14c6e6614e75919d9862cf"},
+    {file = "regex-2024.5.15-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:391d7f7f1e409d192dba8bcd42d3e4cf9e598f3979cdaed6ab11288da88cb9f2"},
+    {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9ff11639a8d98969c863d4617595eb5425fd12f7c5ef6621a4b74b71ed8726d5"},
+    {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4eee78a04e6c67e8391edd4dad3279828dd66ac4b79570ec998e2155d2e59fd5"},
+    {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8fe45aa3f4aa57faabbc9cb46a93363edd6197cbc43523daea044e9ff2fea83e"},
+    {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:d0a3d8d6acf0c78a1fff0e210d224b821081330b8524e3e2bc5a68ef6ab5803d"},
+    {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c486b4106066d502495b3025a0a7251bf37ea9540433940a23419461ab9f2a80"},
+    {file = "regex-2024.5.15-cp312-cp312-win32.whl", hash = "sha256:c49e15eac7c149f3670b3e27f1f28a2c1ddeccd3a2812cba953e01be2ab9b5fe"},
+    {file = "regex-2024.5.15-cp312-cp312-win_amd64.whl", hash = "sha256:673b5a6da4557b975c6c90198588181029c60793835ce02f497ea817ff647cb2"},
+    {file = "regex-2024.5.15-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:87e2a9c29e672fc65523fb47a90d429b70ef72b901b4e4b1bd42387caf0d6835"},
+    {file = "regex-2024.5.15-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c3bea0ba8b73b71b37ac833a7f3fd53825924165da6a924aec78c13032f20850"},
+    {file = "regex-2024.5.15-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bfc4f82cabe54f1e7f206fd3d30fda143f84a63fe7d64a81558d6e5f2e5aaba9"},
+    {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5bb9425fe881d578aeca0b2b4b3d314ec88738706f66f219c194d67179337cb"},
+    {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:64c65783e96e563103d641760664125e91bd85d8e49566ee560ded4da0d3e704"},
+    {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cf2430df4148b08fb4324b848672514b1385ae3807651f3567871f130a728cc3"},
+    {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5397de3219a8b08ae9540c48f602996aa6b0b65d5a61683e233af8605c42b0f2"},
+    {file = "regex-2024.5.15-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:455705d34b4154a80ead722f4f185b04c4237e8e8e33f265cd0798d0e44825fa"},
+    {file = "regex-2024.5.15-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b2b6f1b3bb6f640c1a92be3bbfbcb18657b125b99ecf141fb3310b5282c7d4ed"},
+    {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:3ad070b823ca5890cab606c940522d05d3d22395d432f4aaaf9d5b1653e47ced"},
+    {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:5b5467acbfc153847d5adb21e21e29847bcb5870e65c94c9206d20eb4e99a384"},
+    {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:e6662686aeb633ad65be2a42b4cb00178b3fbf7b91878f9446075c404ada552f"},
+    {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:2b4c884767504c0e2401babe8b5b7aea9148680d2e157fa28f01529d1f7fcf67"},
+    {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:3cd7874d57f13bf70078f1ff02b8b0aa48d5b9ed25fc48547516c6aba36f5741"},
+    {file = "regex-2024.5.15-cp38-cp38-win32.whl", hash = "sha256:e4682f5ba31f475d58884045c1a97a860a007d44938c4c0895f41d64481edbc9"},
+    {file = "regex-2024.5.15-cp38-cp38-win_amd64.whl", hash = "sha256:d99ceffa25ac45d150e30bd9ed14ec6039f2aad0ffa6bb87a5936f5782fc1569"},
+    {file = "regex-2024.5.15-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:13cdaf31bed30a1e1c2453ef6015aa0983e1366fad2667657dbcac7b02f67133"},
+    {file = "regex-2024.5.15-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cac27dcaa821ca271855a32188aa61d12decb6fe45ffe3e722401fe61e323cd1"},
+    {file = "regex-2024.5.15-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7dbe2467273b875ea2de38ded4eba86cbcbc9a1a6d0aa11dcf7bd2e67859c435"},
+    {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:64f18a9a3513a99c4bef0e3efd4c4a5b11228b48aa80743be822b71e132ae4f5"},
+    {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d347a741ea871c2e278fde6c48f85136c96b8659b632fb57a7d1ce1872547600"},
+    {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1878b8301ed011704aea4c806a3cadbd76f84dece1ec09cc9e4dc934cfa5d4da"},
+    {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4babf07ad476aaf7830d77000874d7611704a7fcf68c9c2ad151f5d94ae4bfc4"},
+    {file = "regex-2024.5.15-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:35cb514e137cb3488bce23352af3e12fb0dbedd1ee6e60da053c69fb1b29cc6c"},
+    {file = "regex-2024.5.15-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cdd09d47c0b2efee9378679f8510ee6955d329424c659ab3c5e3a6edea696294"},
+    {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:72d7a99cd6b8f958e85fc6ca5b37c4303294954eac1376535b03c2a43eb72629"},
+    {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:a094801d379ab20c2135529948cb84d417a2169b9bdceda2a36f5f10977ebc16"},
+    {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:c0c18345010870e58238790a6779a1219b4d97bd2e77e1140e8ee5d14df071aa"},
+    {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:16093f563098448ff6b1fa68170e4acbef94e6b6a4e25e10eae8598bb1694b5d"},
+    {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:e38a7d4e8f633a33b4c7350fbd8bad3b70bf81439ac67ac38916c4a86b465456"},
+    {file = "regex-2024.5.15-cp39-cp39-win32.whl", hash = "sha256:71a455a3c584a88f654b64feccc1e25876066c4f5ef26cd6dd711308aa538694"},
+    {file = "regex-2024.5.15-cp39-cp39-win_amd64.whl", hash = "sha256:cab12877a9bdafde5500206d1020a584355a97884dfd388af3699e9137bf7388"},
+    {file = "regex-2024.5.15.tar.gz", hash = "sha256:d3ee02d9e5f482cc8309134a91eeaacbdd2261ba111b0fef3748eeb4913e6a2c"},
 ]
 
 [[package]]
@@ -3681,110 +3660,110 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"]
 
 [[package]]
 name = "rpds-py"
-version = "0.18.0"
+version = "0.18.1"
 description = "Python bindings to Rust's persistent data structures (rpds)"
 optional = false
 python-versions = ">=3.8"
 files = [
-    {file = "rpds_py-0.18.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:5b4e7d8d6c9b2e8ee2d55c90b59c707ca59bc30058269b3db7b1f8df5763557e"},
-    {file = "rpds_py-0.18.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c463ed05f9dfb9baebef68048aed8dcdc94411e4bf3d33a39ba97e271624f8f7"},
-    {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01e36a39af54a30f28b73096dd39b6802eddd04c90dbe161c1b8dbe22353189f"},
-    {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d62dec4976954a23d7f91f2f4530852b0c7608116c257833922a896101336c51"},
-    {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dd18772815d5f008fa03d2b9a681ae38d5ae9f0e599f7dda233c439fcaa00d40"},
-    {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:923d39efa3cfb7279a0327e337a7958bff00cc447fd07a25cddb0a1cc9a6d2da"},
-    {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:39514da80f971362f9267c600b6d459bfbbc549cffc2cef8e47474fddc9b45b1"},
-    {file = "rpds_py-0.18.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a34d557a42aa28bd5c48a023c570219ba2593bcbbb8dc1b98d8cf5d529ab1434"},
-    {file = "rpds_py-0.18.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:93df1de2f7f7239dc9cc5a4a12408ee1598725036bd2dedadc14d94525192fc3"},
-    {file = "rpds_py-0.18.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:34b18ba135c687f4dac449aa5157d36e2cbb7c03cbea4ddbd88604e076aa836e"},
-    {file = "rpds_py-0.18.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c0b5dcf9193625afd8ecc92312d6ed78781c46ecbf39af9ad4681fc9f464af88"},
-    {file = "rpds_py-0.18.0-cp310-none-win32.whl", hash = "sha256:c4325ff0442a12113a6379af66978c3fe562f846763287ef66bdc1d57925d337"},
-    {file = "rpds_py-0.18.0-cp310-none-win_amd64.whl", hash = "sha256:7223a2a5fe0d217e60a60cdae28d6949140dde9c3bcc714063c5b463065e3d66"},
-    {file = "rpds_py-0.18.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:3a96e0c6a41dcdba3a0a581bbf6c44bb863f27c541547fb4b9711fd8cf0ffad4"},
-    {file = "rpds_py-0.18.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30f43887bbae0d49113cbaab729a112251a940e9b274536613097ab8b4899cf6"},
-    {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fcb25daa9219b4cf3a0ab24b0eb9a5cc8949ed4dc72acb8fa16b7e1681aa3c58"},
-    {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d68c93e381010662ab873fea609bf6c0f428b6d0bb00f2c6939782e0818d37bf"},
-    {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b34b7aa8b261c1dbf7720b5d6f01f38243e9b9daf7e6b8bc1fd4657000062f2c"},
-    {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2e6d75ab12b0bbab7215e5d40f1e5b738aa539598db27ef83b2ec46747df90e1"},
-    {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b8612cd233543a3781bc659c731b9d607de65890085098986dfd573fc2befe5"},
-    {file = "rpds_py-0.18.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:aec493917dd45e3c69d00a8874e7cbed844efd935595ef78a0f25f14312e33c6"},
-    {file = "rpds_py-0.18.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:661d25cbffaf8cc42e971dd570d87cb29a665f49f4abe1f9e76be9a5182c4688"},
-    {file = "rpds_py-0.18.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1df3659d26f539ac74fb3b0c481cdf9d725386e3552c6fa2974f4d33d78e544b"},
-    {file = "rpds_py-0.18.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a1ce3ba137ed54f83e56fb983a5859a27d43a40188ba798993812fed73c70836"},
-    {file = "rpds_py-0.18.0-cp311-none-win32.whl", hash = "sha256:69e64831e22a6b377772e7fb337533c365085b31619005802a79242fee620bc1"},
-    {file = "rpds_py-0.18.0-cp311-none-win_amd64.whl", hash = "sha256:998e33ad22dc7ec7e030b3df701c43630b5bc0d8fbc2267653577e3fec279afa"},
-    {file = "rpds_py-0.18.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:7f2facbd386dd60cbbf1a794181e6aa0bd429bd78bfdf775436020172e2a23f0"},
-    {file = "rpds_py-0.18.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1d9a5be316c15ffb2b3c405c4ff14448c36b4435be062a7f578ccd8b01f0c4d8"},
-    {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cd5bf1af8efe569654bbef5a3e0a56eca45f87cfcffab31dd8dde70da5982475"},
-    {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5417558f6887e9b6b65b4527232553c139b57ec42c64570569b155262ac0754f"},
-    {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:56a737287efecafc16f6d067c2ea0117abadcd078d58721f967952db329a3e5c"},
-    {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8f03bccbd8586e9dd37219bce4d4e0d3ab492e6b3b533e973fa08a112cb2ffc9"},
-    {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4457a94da0d5c53dc4b3e4de1158bdab077db23c53232f37a3cb7afdb053a4e3"},
-    {file = "rpds_py-0.18.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0ab39c1ba9023914297dd88ec3b3b3c3f33671baeb6acf82ad7ce883f6e8e157"},
-    {file = "rpds_py-0.18.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9d54553c1136b50fd12cc17e5b11ad07374c316df307e4cfd6441bea5fb68496"},
-    {file = "rpds_py-0.18.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0af039631b6de0397ab2ba16eaf2872e9f8fca391b44d3d8cac317860a700a3f"},
-    {file = "rpds_py-0.18.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:84ffab12db93b5f6bad84c712c92060a2d321b35c3c9960b43d08d0f639d60d7"},
-    {file = "rpds_py-0.18.0-cp312-none-win32.whl", hash = "sha256:685537e07897f173abcf67258bee3c05c374fa6fff89d4c7e42fb391b0605e98"},
-    {file = "rpds_py-0.18.0-cp312-none-win_amd64.whl", hash = "sha256:e003b002ec72c8d5a3e3da2989c7d6065b47d9eaa70cd8808b5384fbb970f4ec"},
-    {file = "rpds_py-0.18.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:08f9ad53c3f31dfb4baa00da22f1e862900f45908383c062c27628754af2e88e"},
-    {file = "rpds_py-0.18.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c0013fe6b46aa496a6749c77e00a3eb07952832ad6166bd481c74bda0dcb6d58"},
-    {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e32a92116d4f2a80b629778280103d2a510a5b3f6314ceccd6e38006b5e92dcb"},
-    {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e541ec6f2ec456934fd279a3120f856cd0aedd209fc3852eca563f81738f6861"},
-    {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bed88b9a458e354014d662d47e7a5baafd7ff81c780fd91584a10d6ec842cb73"},
-    {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2644e47de560eb7bd55c20fc59f6daa04682655c58d08185a9b95c1970fa1e07"},
-    {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e8916ae4c720529e18afa0b879473049e95949bf97042e938530e072fde061d"},
-    {file = "rpds_py-0.18.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:465a3eb5659338cf2a9243e50ad9b2296fa15061736d6e26240e713522b6235c"},
-    {file = "rpds_py-0.18.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:ea7d4a99f3b38c37eac212dbd6ec42b7a5ec51e2c74b5d3223e43c811609e65f"},
-    {file = "rpds_py-0.18.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:67071a6171e92b6da534b8ae326505f7c18022c6f19072a81dcf40db2638767c"},
-    {file = "rpds_py-0.18.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:41ef53e7c58aa4ef281da975f62c258950f54b76ec8e45941e93a3d1d8580594"},
-    {file = "rpds_py-0.18.0-cp38-none-win32.whl", hash = "sha256:fdea4952db2793c4ad0bdccd27c1d8fdd1423a92f04598bc39425bcc2b8ee46e"},
-    {file = "rpds_py-0.18.0-cp38-none-win_amd64.whl", hash = "sha256:7cd863afe7336c62ec78d7d1349a2f34c007a3cc6c2369d667c65aeec412a5b1"},
-    {file = "rpds_py-0.18.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:5307def11a35f5ae4581a0b658b0af8178c65c530e94893345bebf41cc139d33"},
-    {file = "rpds_py-0.18.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:77f195baa60a54ef9d2de16fbbfd3ff8b04edc0c0140a761b56c267ac11aa467"},
-    {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:39f5441553f1c2aed4de4377178ad8ff8f9d733723d6c66d983d75341de265ab"},
-    {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9a00312dea9310d4cb7dbd7787e722d2e86a95c2db92fbd7d0155f97127bcb40"},
-    {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8f2fc11e8fe034ee3c34d316d0ad8808f45bc3b9ce5857ff29d513f3ff2923a1"},
-    {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:586f8204935b9ec884500498ccc91aa869fc652c40c093bd9e1471fbcc25c022"},
-    {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ddc2f4dfd396c7bfa18e6ce371cba60e4cf9d2e5cdb71376aa2da264605b60b9"},
-    {file = "rpds_py-0.18.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5ddcba87675b6d509139d1b521e0c8250e967e63b5909a7e8f8944d0f90ff36f"},
-    {file = "rpds_py-0.18.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:7bd339195d84439cbe5771546fe8a4e8a7a045417d8f9de9a368c434e42a721e"},
-    {file = "rpds_py-0.18.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:d7c36232a90d4755b720fbd76739d8891732b18cf240a9c645d75f00639a9024"},
-    {file = "rpds_py-0.18.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:6b0817e34942b2ca527b0e9298373e7cc75f429e8da2055607f4931fded23e20"},
-    {file = "rpds_py-0.18.0-cp39-none-win32.whl", hash = "sha256:99f70b740dc04d09e6b2699b675874367885217a2e9f782bdf5395632ac663b7"},
-    {file = "rpds_py-0.18.0-cp39-none-win_amd64.whl", hash = "sha256:6ef687afab047554a2d366e112dd187b62d261d49eb79b77e386f94644363294"},
-    {file = "rpds_py-0.18.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ad36cfb355e24f1bd37cac88c112cd7730873f20fb0bdaf8ba59eedf8216079f"},
-    {file = "rpds_py-0.18.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:36b3ee798c58ace201289024b52788161e1ea133e4ac93fba7d49da5fec0ef9e"},
-    {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8a2f084546cc59ea99fda8e070be2fd140c3092dc11524a71aa8f0f3d5a55ca"},
-    {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e4461d0f003a0aa9be2bdd1b798a041f177189c1a0f7619fe8c95ad08d9a45d7"},
-    {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8db715ebe3bb7d86d77ac1826f7d67ec11a70dbd2376b7cc214199360517b641"},
-    {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:793968759cd0d96cac1e367afd70c235867831983f876a53389ad869b043c948"},
-    {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66e6a3af5a75363d2c9a48b07cb27c4ea542938b1a2e93b15a503cdfa8490795"},
-    {file = "rpds_py-0.18.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6ef0befbb5d79cf32d0266f5cff01545602344eda89480e1dd88aca964260b18"},
-    {file = "rpds_py-0.18.0-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:1d4acf42190d449d5e89654d5c1ed3a4f17925eec71f05e2a41414689cda02d1"},
-    {file = "rpds_py-0.18.0-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:a5f446dd5055667aabaee78487f2b5ab72e244f9bc0b2ffebfeec79051679984"},
-    {file = "rpds_py-0.18.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:9dbbeb27f4e70bfd9eec1be5477517365afe05a9b2c441a0b21929ee61048124"},
-    {file = "rpds_py-0.18.0-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:22806714311a69fd0af9b35b7be97c18a0fc2826e6827dbb3a8c94eac6cf7eeb"},
-    {file = "rpds_py-0.18.0-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:b34ae4636dfc4e76a438ab826a0d1eed2589ca7d9a1b2d5bb546978ac6485461"},
-    {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8c8370641f1a7f0e0669ddccca22f1da893cef7628396431eb445d46d893e5cd"},
-    {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c8362467a0fdeccd47935f22c256bec5e6abe543bf0d66e3d3d57a8fb5731863"},
-    {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:11a8c85ef4a07a7638180bf04fe189d12757c696eb41f310d2426895356dcf05"},
-    {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b316144e85316da2723f9d8dc75bada12fa58489a527091fa1d5a612643d1a0e"},
-    {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf1ea2e34868f6fbf070e1af291c8180480310173de0b0c43fc38a02929fc0e3"},
-    {file = "rpds_py-0.18.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e546e768d08ad55b20b11dbb78a745151acbd938f8f00d0cfbabe8b0199b9880"},
-    {file = "rpds_py-0.18.0-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:4901165d170a5fde6f589acb90a6b33629ad1ec976d4529e769c6f3d885e3e80"},
-    {file = "rpds_py-0.18.0-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:618a3d6cae6ef8ec88bb76dd80b83cfe415ad4f1d942ca2a903bf6b6ff97a2da"},
-    {file = "rpds_py-0.18.0-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:ed4eb745efbff0a8e9587d22a84be94a5eb7d2d99c02dacf7bd0911713ed14dd"},
-    {file = "rpds_py-0.18.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:6c81e5f372cd0dc5dc4809553d34f832f60a46034a5f187756d9b90586c2c307"},
-    {file = "rpds_py-0.18.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:43fbac5f22e25bee1d482c97474f930a353542855f05c1161fd804c9dc74a09d"},
-    {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d7faa6f14017c0b1e69f5e2c357b998731ea75a442ab3841c0dbbbfe902d2c4"},
-    {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:08231ac30a842bd04daabc4d71fddd7e6d26189406d5a69535638e4dcb88fe76"},
-    {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:044a3e61a7c2dafacae99d1e722cc2d4c05280790ec5a05031b3876809d89a5c"},
-    {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3f26b5bd1079acdb0c7a5645e350fe54d16b17bfc5e71f371c449383d3342e17"},
-    {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:482103aed1dfe2f3b71a58eff35ba105289b8d862551ea576bd15479aba01f66"},
-    {file = "rpds_py-0.18.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1374f4129f9bcca53a1bba0bb86bf78325a0374577cf7e9e4cd046b1e6f20e24"},
-    {file = "rpds_py-0.18.0-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:635dc434ff724b178cb192c70016cc0ad25a275228f749ee0daf0eddbc8183b1"},
-    {file = "rpds_py-0.18.0-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:bc362ee4e314870a70f4ae88772d72d877246537d9f8cb8f7eacf10884862432"},
-    {file = "rpds_py-0.18.0-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:4832d7d380477521a8c1644bbab6588dfedea5e30a7d967b5fb75977c45fd77f"},
-    {file = "rpds_py-0.18.0.tar.gz", hash = "sha256:42821446ee7a76f5d9f71f9e33a4fb2ffd724bb3e7f93386150b61a43115788d"},
+    {file = "rpds_py-0.18.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:d31dea506d718693b6b2cffc0648a8929bdc51c70a311b2770f09611caa10d53"},
+    {file = "rpds_py-0.18.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:732672fbc449bab754e0b15356c077cc31566df874964d4801ab14f71951ea80"},
+    {file = "rpds_py-0.18.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4a98a1f0552b5f227a3d6422dbd61bc6f30db170939bd87ed14f3c339aa6c7c9"},
+    {file = "rpds_py-0.18.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7f1944ce16401aad1e3f7d312247b3d5de7981f634dc9dfe90da72b87d37887d"},
+    {file = "rpds_py-0.18.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:38e14fb4e370885c4ecd734f093a2225ee52dc384b86fa55fe3f74638b2cfb09"},
+    {file = "rpds_py-0.18.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:08d74b184f9ab6289b87b19fe6a6d1a97fbfea84b8a3e745e87a5de3029bf944"},
+    {file = "rpds_py-0.18.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d70129cef4a8d979caa37e7fe957202e7eee8ea02c5e16455bc9808a59c6b2f0"},
+    {file = "rpds_py-0.18.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ce0bb20e3a11bd04461324a6a798af34d503f8d6f1aa3d2aa8901ceaf039176d"},
+    {file = "rpds_py-0.18.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:81c5196a790032e0fc2464c0b4ab95f8610f96f1f2fa3d4deacce6a79852da60"},
+    {file = "rpds_py-0.18.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:f3027be483868c99b4985fda802a57a67fdf30c5d9a50338d9db646d590198da"},
+    {file = "rpds_py-0.18.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d44607f98caa2961bab4fa3c4309724b185b464cdc3ba6f3d7340bac3ec97cc1"},
+    {file = "rpds_py-0.18.1-cp310-none-win32.whl", hash = "sha256:c273e795e7a0f1fddd46e1e3cb8be15634c29ae8ff31c196debb620e1edb9333"},
+    {file = "rpds_py-0.18.1-cp310-none-win_amd64.whl", hash = "sha256:8352f48d511de5f973e4f2f9412736d7dea76c69faa6d36bcf885b50c758ab9a"},
+    {file = "rpds_py-0.18.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:6b5ff7e1d63a8281654b5e2896d7f08799378e594f09cf3674e832ecaf396ce8"},
+    {file = "rpds_py-0.18.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8927638a4d4137a289e41d0fd631551e89fa346d6dbcfc31ad627557d03ceb6d"},
+    {file = "rpds_py-0.18.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:154bf5c93d79558b44e5b50cc354aa0459e518e83677791e6adb0b039b7aa6a7"},
+    {file = "rpds_py-0.18.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:07f2139741e5deb2c5154a7b9629bc5aa48c766b643c1a6750d16f865a82c5fc"},
+    {file = "rpds_py-0.18.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8c7672e9fba7425f79019db9945b16e308ed8bc89348c23d955c8c0540da0a07"},
+    {file = "rpds_py-0.18.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:489bdfe1abd0406eba6b3bb4fdc87c7fa40f1031de073d0cfb744634cc8fa261"},
+    {file = "rpds_py-0.18.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c20f05e8e3d4fc76875fc9cb8cf24b90a63f5a1b4c5b9273f0e8225e169b100"},
+    {file = "rpds_py-0.18.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:967342e045564cef76dfcf1edb700b1e20838d83b1aa02ab313e6a497cf923b8"},
+    {file = "rpds_py-0.18.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2cc7c1a47f3a63282ab0f422d90ddac4aa3034e39fc66a559ab93041e6505da7"},
+    {file = "rpds_py-0.18.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f7afbfee1157e0f9376c00bb232e80a60e59ed716e3211a80cb8506550671e6e"},
+    {file = "rpds_py-0.18.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9e6934d70dc50f9f8ea47081ceafdec09245fd9f6032669c3b45705dea096b88"},
+    {file = "rpds_py-0.18.1-cp311-none-win32.whl", hash = "sha256:c69882964516dc143083d3795cb508e806b09fc3800fd0d4cddc1df6c36e76bb"},
+    {file = "rpds_py-0.18.1-cp311-none-win_amd64.whl", hash = "sha256:70a838f7754483bcdc830444952fd89645569e7452e3226de4a613a4c1793fb2"},
+    {file = "rpds_py-0.18.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:3dd3cd86e1db5aadd334e011eba4e29d37a104b403e8ca24dcd6703c68ca55b3"},
+    {file = "rpds_py-0.18.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:05f3d615099bd9b13ecf2fc9cf2d839ad3f20239c678f461c753e93755d629ee"},
+    {file = "rpds_py-0.18.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35b2b771b13eee8729a5049c976197ff58a27a3829c018a04341bcf1ae409b2b"},
+    {file = "rpds_py-0.18.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ee17cd26b97d537af8f33635ef38be873073d516fd425e80559f4585a7b90c43"},
+    {file = "rpds_py-0.18.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b646bf655b135ccf4522ed43d6902af37d3f5dbcf0da66c769a2b3938b9d8184"},
+    {file = "rpds_py-0.18.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:19ba472b9606c36716062c023afa2484d1e4220548751bda14f725a7de17b4f6"},
+    {file = "rpds_py-0.18.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e30ac5e329098903262dc5bdd7e2086e0256aa762cc8b744f9e7bf2a427d3f8"},
+    {file = "rpds_py-0.18.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d58ad6317d188c43750cb76e9deacf6051d0f884d87dc6518e0280438648a9ac"},
+    {file = "rpds_py-0.18.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e1735502458621921cee039c47318cb90b51d532c2766593be6207eec53e5c4c"},
+    {file = "rpds_py-0.18.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:f5bab211605d91db0e2995a17b5c6ee5edec1270e46223e513eaa20da20076ac"},
+    {file = "rpds_py-0.18.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2fc24a329a717f9e2448f8cd1f960f9dac4e45b6224d60734edeb67499bab03a"},
+    {file = "rpds_py-0.18.1-cp312-none-win32.whl", hash = "sha256:1805d5901779662d599d0e2e4159d8a82c0b05faa86ef9222bf974572286b2b6"},
+    {file = "rpds_py-0.18.1-cp312-none-win_amd64.whl", hash = "sha256:720edcb916df872d80f80a1cc5ea9058300b97721efda8651efcd938a9c70a72"},
+    {file = "rpds_py-0.18.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:c827576e2fa017a081346dce87d532a5310241648eb3700af9a571a6e9fc7e74"},
+    {file = "rpds_py-0.18.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:aa3679e751408d75a0b4d8d26d6647b6d9326f5e35c00a7ccd82b78ef64f65f8"},
+    {file = "rpds_py-0.18.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0abeee75434e2ee2d142d650d1e54ac1f8b01e6e6abdde8ffd6eeac6e9c38e20"},
+    {file = "rpds_py-0.18.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed402d6153c5d519a0faf1bb69898e97fb31613b49da27a84a13935ea9164dfc"},
+    {file = "rpds_py-0.18.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:338dee44b0cef8b70fd2ef54b4e09bb1b97fc6c3a58fea5db6cc083fd9fc2724"},
+    {file = "rpds_py-0.18.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7750569d9526199c5b97e5a9f8d96a13300950d910cf04a861d96f4273d5b104"},
+    {file = "rpds_py-0.18.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:607345bd5912aacc0c5a63d45a1f73fef29e697884f7e861094e443187c02be5"},
+    {file = "rpds_py-0.18.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:207c82978115baa1fd8d706d720b4a4d2b0913df1c78c85ba73fe6c5804505f0"},
+    {file = "rpds_py-0.18.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:6d1e42d2735d437e7e80bab4d78eb2e459af48c0a46e686ea35f690b93db792d"},
+    {file = "rpds_py-0.18.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:5463c47c08630007dc0fe99fb480ea4f34a89712410592380425a9b4e1611d8e"},
+    {file = "rpds_py-0.18.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:06d218939e1bf2ca50e6b0ec700ffe755e5216a8230ab3e87c059ebb4ea06afc"},
+    {file = "rpds_py-0.18.1-cp38-none-win32.whl", hash = "sha256:312fe69b4fe1ffbe76520a7676b1e5ac06ddf7826d764cc10265c3b53f96dbe9"},
+    {file = "rpds_py-0.18.1-cp38-none-win_amd64.whl", hash = "sha256:9437ca26784120a279f3137ee080b0e717012c42921eb07861b412340f85bae2"},
+    {file = "rpds_py-0.18.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:19e515b78c3fc1039dd7da0a33c28c3154458f947f4dc198d3c72db2b6b5dc93"},
+    {file = "rpds_py-0.18.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a7b28c5b066bca9a4eb4e2f2663012debe680f097979d880657f00e1c30875a0"},
+    {file = "rpds_py-0.18.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:673fdbbf668dd958eff750e500495ef3f611e2ecc209464f661bc82e9838991e"},
+    {file = "rpds_py-0.18.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d960de62227635d2e61068f42a6cb6aae91a7fe00fca0e3aeed17667c8a34611"},
+    {file = "rpds_py-0.18.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:352a88dc7892f1da66b6027af06a2e7e5d53fe05924cc2cfc56495b586a10b72"},
+    {file = "rpds_py-0.18.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4e0ee01ad8260184db21468a6e1c37afa0529acc12c3a697ee498d3c2c4dcaf3"},
+    {file = "rpds_py-0.18.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4c39ad2f512b4041343ea3c7894339e4ca7839ac38ca83d68a832fc8b3748ab"},
+    {file = "rpds_py-0.18.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:aaa71ee43a703c321906813bb252f69524f02aa05bf4eec85f0c41d5d62d0f4c"},
+    {file = "rpds_py-0.18.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:6cd8098517c64a85e790657e7b1e509b9fe07487fd358e19431cb120f7d96338"},
+    {file = "rpds_py-0.18.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:4adec039b8e2928983f885c53b7cc4cda8965b62b6596501a0308d2703f8af1b"},
+    {file = "rpds_py-0.18.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:32b7daaa3e9389db3695964ce8e566e3413b0c43e3394c05e4b243a4cd7bef26"},
+    {file = "rpds_py-0.18.1-cp39-none-win32.whl", hash = "sha256:2625f03b105328729f9450c8badda34d5243231eef6535f80064d57035738360"},
+    {file = "rpds_py-0.18.1-cp39-none-win_amd64.whl", hash = "sha256:bf18932d0003c8c4d51a39f244231986ab23ee057d235a12b2684ea26a353590"},
+    {file = "rpds_py-0.18.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:cbfbea39ba64f5e53ae2915de36f130588bba71245b418060ec3330ebf85678e"},
+    {file = "rpds_py-0.18.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:a3d456ff2a6a4d2adcdf3c1c960a36f4fd2fec6e3b4902a42a384d17cf4e7a65"},
+    {file = "rpds_py-0.18.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7700936ef9d006b7ef605dc53aa364da2de5a3aa65516a1f3ce73bf82ecfc7ae"},
+    {file = "rpds_py-0.18.1-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:51584acc5916212e1bf45edd17f3a6b05fe0cbb40482d25e619f824dccb679de"},
+    {file = "rpds_py-0.18.1-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:942695a206a58d2575033ff1e42b12b2aece98d6003c6bc739fbf33d1773b12f"},
+    {file = "rpds_py-0.18.1-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b906b5f58892813e5ba5c6056d6a5ad08f358ba49f046d910ad992196ea61397"},
+    {file = "rpds_py-0.18.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6f8e3fecca256fefc91bb6765a693d96692459d7d4c644660a9fff32e517843"},
+    {file = "rpds_py-0.18.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7732770412bab81c5a9f6d20aeb60ae943a9b36dcd990d876a773526468e7163"},
+    {file = "rpds_py-0.18.1-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:bd1105b50ede37461c1d51b9698c4f4be6e13e69a908ab7751e3807985fc0346"},
+    {file = "rpds_py-0.18.1-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:618916f5535784960f3ecf8111581f4ad31d347c3de66d02e728de460a46303c"},
+    {file = "rpds_py-0.18.1-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:17c6d2155e2423f7e79e3bb18151c686d40db42d8645e7977442170c360194d4"},
+    {file = "rpds_py-0.18.1-pp38-pypy38_pp73-macosx_10_12_x86_64.whl", hash = "sha256:6c4c4c3f878df21faf5fac86eda32671c27889e13570645a9eea0a1abdd50922"},
+    {file = "rpds_py-0.18.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:fab6ce90574645a0d6c58890e9bcaac8d94dff54fb51c69e5522a7358b80ab64"},
+    {file = "rpds_py-0.18.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:531796fb842b53f2695e94dc338929e9f9dbf473b64710c28af5a160b2a8927d"},
+    {file = "rpds_py-0.18.1-pp38-pypy38_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:740884bc62a5e2bbb31e584f5d23b32320fd75d79f916f15a788d527a5e83644"},
+    {file = "rpds_py-0.18.1-pp38-pypy38_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:998125738de0158f088aef3cb264a34251908dd2e5d9966774fdab7402edfab7"},
+    {file = "rpds_py-0.18.1-pp38-pypy38_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e2be6e9dd4111d5b31ba3b74d17da54a8319d8168890fbaea4b9e5c3de630ae5"},
+    {file = "rpds_py-0.18.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d0cee71bc618cd93716f3c1bf56653740d2d13ddbd47673efa8bf41435a60daa"},
+    {file = "rpds_py-0.18.1-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2c3caec4ec5cd1d18e5dd6ae5194d24ed12785212a90b37f5f7f06b8bedd7139"},
+    {file = "rpds_py-0.18.1-pp38-pypy38_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:27bba383e8c5231cd559affe169ca0b96ec78d39909ffd817f28b166d7ddd4d8"},
+    {file = "rpds_py-0.18.1-pp38-pypy38_pp73-musllinux_1_2_i686.whl", hash = "sha256:a888e8bdb45916234b99da2d859566f1e8a1d2275a801bb8e4a9644e3c7e7909"},
+    {file = "rpds_py-0.18.1-pp38-pypy38_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:6031b25fb1b06327b43d841f33842b383beba399884f8228a6bb3df3088485ff"},
+    {file = "rpds_py-0.18.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:48c2faaa8adfacefcbfdb5f2e2e7bdad081e5ace8d182e5f4ade971f128e6bb3"},
+    {file = "rpds_py-0.18.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:d85164315bd68c0806768dc6bb0429c6f95c354f87485ee3593c4f6b14def2bd"},
+    {file = "rpds_py-0.18.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6afd80f6c79893cfc0574956f78a0add8c76e3696f2d6a15bca2c66c415cf2d4"},
+    {file = "rpds_py-0.18.1-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fa242ac1ff583e4ec7771141606aafc92b361cd90a05c30d93e343a0c2d82a89"},
+    {file = "rpds_py-0.18.1-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d21be4770ff4e08698e1e8e0bce06edb6ea0626e7c8f560bc08222880aca6a6f"},
+    {file = "rpds_py-0.18.1-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c45a639e93a0c5d4b788b2613bd637468edd62f8f95ebc6fcc303d58ab3f0a8"},
+    {file = "rpds_py-0.18.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:910e71711d1055b2768181efa0a17537b2622afeb0424116619817007f8a2b10"},
+    {file = "rpds_py-0.18.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b9bb1f182a97880f6078283b3505a707057c42bf55d8fca604f70dedfdc0772a"},
+    {file = "rpds_py-0.18.1-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:1d54f74f40b1f7aaa595a02ff42ef38ca654b1469bef7d52867da474243cc633"},
+    {file = "rpds_py-0.18.1-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:8d2e182c9ee01135e11e9676e9a62dfad791a7a467738f06726872374a83db49"},
+    {file = "rpds_py-0.18.1-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:636a15acc588f70fda1661234761f9ed9ad79ebed3f2125d44be0862708b666e"},
+    {file = "rpds_py-0.18.1.tar.gz", hash = "sha256:dc48b479d540770c811fbd1eb9ba2bb66951863e448efec2e2c102625328e92f"},
 ]
 
 [[package]]
@@ -3880,18 +3859,15 @@ files = [
 
 [[package]]
 name = "schema"
-version = "0.7.5"
+version = "0.7.7"
 description = "Simple data validation library"
 optional = false
 python-versions = "*"
 files = [
-    {file = "schema-0.7.5-py2.py3-none-any.whl", hash = "sha256:f3ffdeeada09ec34bf40d7d79996d9f7175db93b7a5065de0faa7f41083c1e6c"},
-    {file = "schema-0.7.5.tar.gz", hash = "sha256:f06717112c61895cabc4707752b88716e8420a8819d71404501e114f91043197"},
+    {file = "schema-0.7.7-py2.py3-none-any.whl", hash = "sha256:5d976a5b50f36e74e2157b47097b60002bd4d42e65425fcc9c9befadb4255dde"},
+    {file = "schema-0.7.7.tar.gz", hash = "sha256:7da553abd2958a19dc2547c388cde53398b39196175a9be59ea1caf5ab0a1807"},
 ]
 
-[package.dependencies]
-contextlib2 = ">=0.5.5"
-
 [[package]]
 name = "scipy"
 version = "1.10.1"
@@ -4032,17 +4008,18 @@ widechars = ["wcwidth"]
 
 [[package]]
 name = "tenacity"
-version = "8.2.3"
+version = "8.3.0"
 description = "Retry code until it succeeds"
 optional = false
-python-versions = ">=3.7"
+python-versions = ">=3.8"
 files = [
-    {file = "tenacity-8.2.3-py3-none-any.whl", hash = "sha256:ce510e327a630c9e1beaf17d42e6ffacc88185044ad85cf74c0a8887c6a0f88c"},
-    {file = "tenacity-8.2.3.tar.gz", hash = "sha256:5398ef0d78e63f40007c1fb4c0bff96e1911394d2fa8d194f77619c05ff6cc8a"},
+    {file = "tenacity-8.3.0-py3-none-any.whl", hash = "sha256:3649f6443dbc0d9b01b9d8020a9c4ec7a1ff5f6f3c6c8a036ef371f573fe9185"},
+    {file = "tenacity-8.3.0.tar.gz", hash = "sha256:953d4e6ad24357bceffbc9707bc74349aca9d245f68eb65419cf0c249a1949a2"},
 ]
 
 [package.extras]
-doc = ["reno", "sphinx", "tornado (>=4.5)"]
+doc = ["reno", "sphinx"]
+test = ["pytest", "tornado (>=4.5)", "typeguard"]
 
 [[package]]
 name = "tomli"
@@ -4057,13 +4034,13 @@ files = [
 
 [[package]]
 name = "tomlkit"
-version = "0.12.4"
+version = "0.12.5"
 description = "Style preserving TOML library"
 optional = false
 python-versions = ">=3.7"
 files = [
-    {file = "tomlkit-0.12.4-py3-none-any.whl", hash = "sha256:5cd82d48a3dd89dee1f9d64420aa20ae65cfbd00668d6f094d7578a78efbb77b"},
-    {file = "tomlkit-0.12.4.tar.gz", hash = "sha256:7ca1cfc12232806517a8515047ba66a19369e71edf2439d0f5824f91032b6cc3"},
+    {file = "tomlkit-0.12.5-py3-none-any.whl", hash = "sha256:af914f5a9c59ed9d0762c7b64d3b5d5df007448eb9cd2edc8a46b1eafead172f"},
+    {file = "tomlkit-0.12.5.tar.gz", hash = "sha256:eef34fba39834d4d6b73c9ba7f3e4d1c417a4e56f89a7e96e090dd0d24b8fb3c"},
 ]
 
 [[package]]
@@ -4099,13 +4076,13 @@ files = [
 
 [[package]]
 name = "tqdm"
-version = "4.66.2"
+version = "4.66.4"
 description = "Fast, Extensible Progress Meter"
 optional = false
 python-versions = ">=3.7"
 files = [
-    {file = "tqdm-4.66.2-py3-none-any.whl", hash = "sha256:1ee4f8a893eb9bef51c6e35730cebf234d5d0b6bd112b0271e10ed7c24a02bd9"},
-    {file = "tqdm-4.66.2.tar.gz", hash = "sha256:6cd52cdf0fef0e0f543299cfc96fec90d7b8a7e88745f411ec33eb44d5ed3531"},
+    {file = "tqdm-4.66.4-py3-none-any.whl", hash = "sha256:b75ca56b413b030bc3f00af51fd2c1a1a5eac6a0c1cca83cbb37a5c52abce644"},
+    {file = "tqdm-4.66.4.tar.gz", hash = "sha256:e4d936c9de8727928f3be6079590e97d9abfe8d39a590be678eb5919ffc186bb"},
 ]
 
 [package.dependencies]
@@ -4208,13 +4185,13 @@ zstd = ["zstandard (>=0.18.0)"]
 
 [[package]]
 name = "versioningit"
-version = "3.1.0"
+version = "3.1.1"
 description = "Versioning It with your Version In Git"
 optional = false
 python-versions = ">=3.7"
 files = [
-    {file = "versioningit-3.1.0-py3-none-any.whl", hash = "sha256:a2f94968a37fac1192b5b6465356c64e77ae05fc7d32a7d7dddf10339ad147a0"},
-    {file = "versioningit-3.1.0.tar.gz", hash = "sha256:7aac713c31a53eb367a6bbc2e8b3de8cc2b86d10d45c5101afd651446cb10fd7"},
+    {file = "versioningit-3.1.1-py3-none-any.whl", hash = "sha256:3f5a855d98a2a85e909264f2eac3cce380b71f7632e7de55bc22bff9f03639ee"},
+    {file = "versioningit-3.1.1.tar.gz", hash = "sha256:b0ba586e5af08b87dbe3354082910a1d0502c36202d496e1ae60ef3b41ee29c1"},
 ]
 
 [package.dependencies]
@@ -4684,20 +4661,20 @@ zhinst = ">=20.01"
 
 [[package]]
 name = "zipp"
-version = "3.18.1"
+version = "3.18.2"
 description = "Backport of pathlib-compatible object wrapper for zip files"
 optional = false
 python-versions = ">=3.8"
 files = [
-    {file = "zipp-3.18.1-py3-none-any.whl", hash = "sha256:206f5a15f2af3dbaee80769fb7dc6f249695e940acca08dfb2a4769fe61e538b"},
-    {file = "zipp-3.18.1.tar.gz", hash = "sha256:2884ed22e7d8961de1c9a05142eb69a247f120291bc0206a00a7642f09b5b715"},
+    {file = "zipp-3.18.2-py3-none-any.whl", hash = "sha256:dce197b859eb796242b0622af1b8beb0a722d52aa2f57133ead08edd5bf5374e"},
+    {file = "zipp-3.18.2.tar.gz", hash = "sha256:6278d9ddbcfb1f1089a88fde84481528b07b0e10474e09dcfe53dad4069fa059"},
 ]
 
 [package.extras]
 docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
-testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"]
+testing = ["big-O", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"]
 
 [metadata]
 lock-version = "2.0"
 python-versions = "^3.8"
-content-hash = "d4eb85e0643f750a74750af2e36294e4bce2dc3d2413f963cd9a269b4f929e62"
+content-hash = "c71eca6fab9aa5027dc79770194b5d91d869d0ce109f20878b70a15e4e10ecb6"
diff --git a/pyproject.toml b/pyproject.toml
index d373f752..caf24305 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -35,7 +35,7 @@ numpy = [
     { version = "1.24", python = "<3.9" },
     { version = "^1.26", python = "^3.9" },
 ]
-libqasm = "0.6.5"
+libqasm = "0.6.6"
 networkx = "^3.0.0"
 
 [tool.poetry.group.dev.dependencies]
@@ -69,7 +69,7 @@ pyqt5-qt5=[
 ]
 quantify-scheduler=[
     # quantify-scheduler is not released for newer Python versions, i.e. > 3.9.
-    # Its is only required for exporting opensquirrel circuits to the
+    # Its is only required for exporting OpenSquirrel circuits to the
     # Schedule format and testing this functionality.
     { version = "^0.18.0", python = "<3.10" },
 ]


Test patch:
diff --git a/test/decomposer/__init__.py b/test/decomposer/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/test/test_cnot_decomposer.py b/test/decomposer/test_cnot_decomposer.py
similarity index 96%
rename from test/test_cnot_decomposer.py
rename to test/decomposer/test_cnot_decomposer.py
index 98b92f7c..97c8e76f 100644
--- a/test/test_cnot_decomposer.py
+++ b/test/decomposer/test_cnot_decomposer.py
@@ -3,7 +3,7 @@
 
 from opensquirrel.decomposer.cnot_decomposer import CNOTDecomposer
 from opensquirrel.default_gates import *
-from opensquirrel.squirrel_ir import Float, Qubit
+from opensquirrel.ir import Float, Qubit
 
 
 class CNOTDecomposerTest(IREqualityTestBase):
diff --git a/test/test_mckay_decomposer.py b/test/decomposer/test_mckay_decomposer.py
similarity index 98%
rename from test/test_mckay_decomposer.py
rename to test/decomposer/test_mckay_decomposer.py
index 6a02a5b7..648e6532 100644
--- a/test/test_mckay_decomposer.py
+++ b/test/decomposer/test_mckay_decomposer.py
@@ -3,7 +3,7 @@
 
 from opensquirrel.decomposer.mckay_decomposer import McKayDecomposer
 from opensquirrel.default_gates import *
-from opensquirrel.squirrel_ir import Float, Qubit
+from opensquirrel.ir import Float, Qubit
 
 
 class DecomposeMcKayTests(IREqualityTestBase):
diff --git a/test/exporter/test_quantify_scheduler_exporter.py b/test/exporter/test_quantify_scheduler_exporter.py
index 228b0da3..87b98008 100644
--- a/test/exporter/test_quantify_scheduler_exporter.py
+++ b/test/exporter/test_quantify_scheduler_exporter.py
@@ -4,10 +4,12 @@
 import unittest
 import unittest.mock
 
+from opensquirrel.circuit import Circuit
 from opensquirrel.common import ATOL
 from opensquirrel.default_gates import CCZ, CZ, SWAP, H, Ry, Rz, X
 from opensquirrel.exporter import quantify_scheduler_exporter
-from opensquirrel.squirrel_ir import BlochSphereRotation, Float, Gate, Qubit, SquirrelIR
+from opensquirrel.ir import IR, BlochSphereRotation, Float, Gate, Measure, Qubit
+from opensquirrel.register_manager import RegisterManager
 
 
 class FloatEq(float):
@@ -38,39 +40,44 @@ def __exit__(self, exc_type, exc_value, exc_traceback):
 
 class QuantifySchedulerExporterTest(unittest.TestCase):
     def test_export(self):
-        squirrel_ir = SquirrelIR(number_of_qubits=2, qubit_register_name="test")
-        squirrel_ir.add_gate(X(Qubit(0)))
-        squirrel_ir.add_gate(CZ(Qubit(0), Qubit(1)))
-        squirrel_ir.add_gate(Rz(Qubit(1), Float(2.34)))
-        squirrel_ir.add_gate(Ry(Qubit(2), Float(1.23)))
+        register_manager = RegisterManager(qubit_register_size=3)
+        ir = IR()
+        ir.add_gate(X(Qubit(0)))
+        ir.add_gate(CZ(Qubit(0), Qubit(1)))
+        ir.add_gate(Rz(Qubit(1), Float(2.34)))
+        ir.add_gate(Ry(Qubit(2), Float(1.23)))
+        ir.add_measurement(Measure(Qubit(0)))
+        ir.add_measurement(Measure(Qubit(1)))
+        ir.add_measurement(Measure(Qubit(2)))
 
         with MockedQuantifyScheduler() as (mock_quantify_scheduler, mock_quantify_scheduler_gates):
             mock_schedule = unittest.mock.MagicMock()
             mock_quantify_scheduler.Schedule.return_value = mock_schedule
 
-            quantify_scheduler_exporter.export(squirrel_ir)
+            quantify_scheduler_exporter.export(Circuit(register_manager, ir))
 
             mock_quantify_scheduler.Schedule.assert_called_with("Exported OpenSquirrel circuit")
 
             mock_quantify_scheduler_gates.Rxy.assert_has_calls(
                 [
-                    unittest.mock.call(theta=FloatEq(math.degrees(math.pi)), phi=FloatEq(0), qubit="test[0]"),
+                    unittest.mock.call(theta=FloatEq(math.degrees(math.pi)), phi=FloatEq(0), qubit="q[0]"),
                     unittest.mock.call(
-                        theta=FloatEq(math.degrees(1.23)), phi=FloatEq(math.degrees(math.pi / 2)), qubit="test[2]"
+                        theta=FloatEq(math.degrees(1.23)), phi=FloatEq(math.degrees(math.pi / 2)), qubit="q[2]"
                     ),
                 ]
             )
-            mock_quantify_scheduler_gates.CZ.assert_called_once_with(qC="test[0]", qT="test[1]")
-            mock_quantify_scheduler_gates.Rz.assert_called_once_with(theta=FloatEq(math.degrees(2.34)), qubit="test[1]")
-            self.assertEqual(mock_schedule.add.call_count, 4)
+            mock_quantify_scheduler_gates.CZ.assert_called_once_with(qC="q[0]", qT="q[1]")
+            mock_quantify_scheduler_gates.Rz.assert_called_once_with(theta=FloatEq(math.degrees(2.34)), qubit="q[1]")
+            self.assertEqual(mock_schedule.add.call_count, 7)
 
     def check_gate_not_supported(self, g: Gate):
-        squirrel_ir = SquirrelIR(number_of_qubits=20, qubit_register_name="test")
-        squirrel_ir.add_gate(g)
+        register_manager = RegisterManager(qubit_register_size=3)
+        ir = IR()
+        ir.add_gate(g)
 
         with MockedQuantifyScheduler():
             with self.assertRaisesRegex(Exception, "Cannot exporter circuit: it contains unsupported gates"):
-                quantify_scheduler_exporter.export(squirrel_ir)
+                quantify_scheduler_exporter.export(Circuit(register_manager, ir))
 
     def test_gates_not_supported(self):
         self.check_gate_not_supported(H(Qubit(0)))
diff --git a/test/ir_equality_test_base.py b/test/ir_equality_test_base.py
index db14d44d..af4ff8da 100644
--- a/test/ir_equality_test_base.py
+++ b/test/ir_equality_test_base.py
@@ -1,6 +1,7 @@
 import unittest
 
 from opensquirrel import circuit_matrix_calculator
+from opensquirrel.circuit import Circuit
 from opensquirrel.common import are_matrices_equivalent_up_to_global_phase
 
 
@@ -8,29 +9,22 @@ class IREqualityTestBase(unittest.TestCase):
     def check_equivalence_up_to_global_phase(self, matrix_a, matrix_b):
         self.assertTrue(are_matrices_equivalent_up_to_global_phase(matrix_a, matrix_b))
 
-    def modify_ir_and_check(self, ir, action, expected_ir=None):
+    def modify_circuit_and_check(self, circuit, action, expected_circuit=None):
         """
-        Checks whether the IR action preserves:
+        Checks whether the action preserves:
         - the number of qubits,
         - the qubit register name(s),
         - the circuit matrix up to a global phase factor.
         """
-
         # Store matrix before decompositions.
-        expected_matrix = circuit_matrix_calculator.get_circuit_matrix(ir)
-
-        expected_number_of_qubits = ir.number_of_qubits
-        expected_qubit_register_name = ir.qubit_register_name
-
-        action(ir)
+        expected_matrix = circuit_matrix_calculator.get_circuit_matrix(circuit)
 
-        self.assertEqual(ir.number_of_qubits, expected_number_of_qubits)
-        self.assertEqual(ir.qubit_register_name, expected_qubit_register_name)
+        action(circuit)
 
         # Get matrix after decompositions.
-        actual_matrix = circuit_matrix_calculator.get_circuit_matrix(ir)
+        actual_matrix = circuit_matrix_calculator.get_circuit_matrix(circuit)
 
         self.check_equivalence_up_to_global_phase(actual_matrix, expected_matrix)
 
-        if expected_ir is not None:
-            self.assertEqual(ir, expected_ir)
+        if expected_circuit is not None:
+            self.assertEqual(circuit, expected_circuit)
diff --git a/test/mapper/test_general_mapper.py b/test/mapper/test_general_mapper.py
index 0dca5440..3cd37876 100644
--- a/test/mapper/test_general_mapper.py
+++ b/test/mapper/test_general_mapper.py
@@ -1,21 +1,23 @@
 from __future__ import annotations
 
+from typing import List
+
 import pytest
 
 from opensquirrel import Circuit
 from opensquirrel.default_gates import CNOT, H
-from opensquirrel.mapper import HardcodedMapper, Mapper, map_qubits
-from opensquirrel.squirrel_ir import Comment, Measure, Qubit, SquirrelIR, Statement
+from opensquirrel.ir import IR, Comment, Measure, Qubit, Statement
+from opensquirrel.mapper import HardcodedMapper, Mapper
+from opensquirrel.mapper.mapping import Mapping
+from opensquirrel.register_manager import RegisterManager
 
 
 class TestMapper:
-
     def test_init(self) -> None:
         with pytest.raises(TypeError):
             Mapper()
 
     def test_implementation(self) -> None:
-
         class Mapper2(Mapper):
             pass
 
@@ -23,26 +25,26 @@ class Mapper2(Mapper):
             Mapper2()
 
         class Mapper3(Mapper2):
-            def map(self, squirrel_ir: SquirrelIR) -> dict[int, int]:
-                return {0: 0}
+            def __init__(self, qubit_register_size: int) -> None:
+                super().__init__(qubit_register_size, Mapping([0]))
 
-        Mapper3()
+        Mapper3(qubit_register_size=1)
 
 
 class TestMapQubits:
-
-    @pytest.fixture(name="squirrel_ir")
-    def squirrel_ir_fixture(self) -> SquirrelIR:
-        squirrel_ir = SquirrelIR(number_of_qubits=3)
-        squirrel_ir.add_gate(H(Qubit(0)))
-        squirrel_ir.add_gate(CNOT(Qubit(0), Qubit(1)))
-        squirrel_ir.add_gate(CNOT(Qubit(1), Qubit(2)))
-        squirrel_ir.add_comment(Comment("Qubit[1]"))
-        squirrel_ir.add_measurement(Measure(Qubit(0), axis=(0, 0, 1)))
-        return squirrel_ir
+    @pytest.fixture(name="circuit")
+    def circuit_fixture(self) -> Circuit:
+        register_manager = RegisterManager(qubit_register_size=3)
+        ir = IR()
+        ir.add_gate(H(Qubit(0)))
+        ir.add_gate(CNOT(Qubit(0), Qubit(1)))
+        ir.add_gate(CNOT(Qubit(1), Qubit(2)))
+        ir.add_comment(Comment("Qubit[1]"))
+        ir.add_measurement(Measure(Qubit(0), axis=(0, 0, 1)))
+        return Circuit(register_manager, ir)
 
     @pytest.fixture(name="expected_statements")
-    def expected_statements_fixture(self) -> list[Statement]:
+    def expected_statements_fixture(self) -> List[Statement]:
         return [
             H(Qubit(1)),
             CNOT(Qubit(1), Qubit(0)),
@@ -51,20 +53,7 @@ def expected_statements_fixture(self) -> list[Statement]:
             Measure(Qubit(1), axis=(0, 0, 1)),
         ]
 
-    def test_map_qubits(self, squirrel_ir: SquirrelIR, expected_statements: list[Statement]) -> None:
-        mapper = HardcodedMapper({0: 1, 1: 0, 2: 2})
-        map_qubits(squirrel_ir, mapper)
-
-        # Check that the circuit is altered as expected
-        mapped_statements = squirrel_ir.statements
-        assert mapped_statements == expected_statements
-
-    def test_map_qubits_circuit(self, squirrel_ir: SquirrelIR, expected_statements: list[Statement]) -> None:
-        circuit = Circuit(squirrel_ir)
-
-        mapper = HardcodedMapper({0: 1, 1: 0, 2: 2})
-        circuit.map_qubits(mapper)
-
-        # Check that the circuit is altered as expected
-        mapped_statements = circuit.squirrel_ir.statements
-        assert mapped_statements == expected_statements
+    def test_circuit_map(self, circuit: Circuit, expected_statements: list[Statement]) -> None:
+        mapper = HardcodedMapper(circuit.qubit_register_size, Mapping([1, 0, 2]))
+        circuit.map(mapper)
+        assert circuit.ir.statements == expected_statements
diff --git a/test/mapper/test_mapping.py b/test/mapper/test_mapping.py
new file mode 100644
index 00000000..53b363f7
--- /dev/null
+++ b/test/mapper/test_mapping.py
@@ -0,0 +1,15 @@
+import pytest
+
+from opensquirrel.mapper.mapping import Mapping
+
+
+class TestMapping:
+    def test_1_physical_qubit(self) -> None:
+        Mapping([0])
+
+    def test_2_physical_qubits(self) -> None:
+        Mapping([0, 1])
+
+    def test_incorrect(self) -> None:
+        with pytest.raises(ValueError):
+            Mapping([0, 2])
diff --git a/test/mapper/test_qubit_remapper.py b/test/mapper/test_qubit_remapper.py
new file mode 100644
index 00000000..75381c6d
--- /dev/null
+++ b/test/mapper/test_qubit_remapper.py
@@ -0,0 +1,78 @@
+from typing import List
+
+import pytest
+
+from opensquirrel.circuit import Circuit
+from opensquirrel.default_gates import CNOT, H, X, Y
+from opensquirrel.ir import IR, Qubit
+from opensquirrel.mapper.mapping import Mapping
+from opensquirrel.mapper.qubit_remapper import get_remapped_ir, remap_ir
+from opensquirrel.register_manager import RegisterManager
+
+
+class TestRemapper:
+    @pytest.fixture
+    def circuit_3(self) -> Circuit:
+        ir = IR()
+        ir.add_gate(H(Qubit(0)))
+        ir.add_gate(CNOT(Qubit(0), Qubit(1)))
+        ir.add_gate(H(Qubit(2)))
+        return Circuit(RegisterManager(qubit_register_size=3), ir)
+
+    @pytest.fixture
+    def circuit_3_remapped(self) -> Circuit:
+        ir = IR()
+        ir.add_gate(H(Qubit(2)))
+        ir.add_gate(CNOT(Qubit(2), Qubit(1)))
+        ir.add_gate(H(Qubit(0)))
+        return Circuit(RegisterManager(qubit_register_size=3), ir)
+
+    @pytest.fixture
+    def circuit_4(self) -> Circuit:
+        ir = IR()
+        ir.add_gate(H(Qubit(0)))
+        ir.add_gate(CNOT(Qubit(0), Qubit(1)))
+        ir.add_gate(X(Qubit(2)))
+        ir.add_gate(Y(Qubit(3)))
+        return Circuit(RegisterManager(qubit_register_size=4), ir)
+
+    @pytest.fixture
+    def circuit_4_remapped(self) -> Circuit:
+        ir = IR()
+        ir.add_gate(H(Qubit(3)))
+        ir.add_gate(CNOT(Qubit(3), Qubit(1)))
+        ir.add_gate(X(Qubit(0)))
+        ir.add_gate(Y(Qubit(2)))
+        return Circuit(RegisterManager(qubit_register_size=4), ir)
+
+    @pytest.fixture
+    def mapping_3(self) -> Mapping:
+        return Mapping([2, 1, 0])
+
+    @pytest.fixture
+    def mapping_4(self) -> Mapping:
+        return Mapping([3, 1, 0, 2])
+
+    def test_get_remapped_ir_raise_assert(self, circuit_3: Circuit, mapping_4: Mapping) -> None:
+        with pytest.raises(AssertionError):
+            get_remapped_ir(circuit_3, mapping_4)
+
+    def test_get_remapped_ir_3_ok(self, circuit_3: Circuit, circuit_3_remapped: Circuit, mapping_3: Mapping) -> None:
+        circuit_3.ir = get_remapped_ir(circuit_3, mapping_3)
+        assert circuit_3 == circuit_3_remapped
+
+    def test_get_remapped_ir_4_ok(self, circuit_4: Circuit, circuit_4_remapped: Circuit, mapping_4: Mapping) -> None:
+        circuit_4.ir = get_remapped_ir(circuit_4, mapping_4)
+        assert circuit_4 == circuit_4_remapped
+
+    def test_remap_ir_raise_assert(self, circuit_3: Circuit, mapping_4: Mapping) -> None:
+        with pytest.raises(AssertionError):
+            remap_ir(circuit_3, mapping_4)
+
+    def test_remap_ir_3_ok(self, circuit_3: Circuit, circuit_3_remapped: Circuit, mapping_3: Mapping) -> None:
+        remap_ir(circuit_3, mapping_3)
+        assert circuit_3 == circuit_3_remapped
+
+    def test_remap_ir_4_ok(self, circuit_4: Circuit, circuit_4_remapped: Circuit, mapping_4: Mapping) -> None:
+        remap_ir(circuit_4, mapping_4)
+        assert circuit_4 == circuit_4_remapped
diff --git a/test/mapper/test_simple_mappers.py b/test/mapper/test_simple_mappers.py
index 425d6618..96df46ed 100644
--- a/test/mapper/test_simple_mappers.py
+++ b/test/mapper/test_simple_mappers.py
@@ -3,40 +3,31 @@
 import pytest
 
 from opensquirrel.mapper import HardcodedMapper, IdentityMapper
-from opensquirrel.squirrel_ir import SquirrelIR
+from opensquirrel.mapper.mapping import Mapping
 from opensquirrel.utils.check_passes import check_mapper
 
 
 class TestIdentityMapper:
     @pytest.fixture(name="mapper")
     def mapper_fixture(self) -> IdentityMapper:
-        return IdentityMapper()
+        return IdentityMapper(qubit_register_size=3)
 
     def test_compliance(self, mapper: IdentityMapper) -> None:
         check_mapper(mapper)
 
-    def test_mapping(self, mapper: IdentityMapper) -> None:
-        squirrel_ir = SquirrelIR(number_of_qubits=3)
-        mapping = mapper.map(squirrel_ir)
-        assert mapping == {0: 0, 1: 1, 2: 2}
+    def test_get_mapping(self, mapper: IdentityMapper) -> None:
+        assert mapper.get_mapping() == Mapping([0, 1, 2])
 
 
 class TestHardcodedMapper:
-
     @pytest.fixture(name="mapper")
     def mapper_fixture(self) -> HardcodedMapper:
-        mapping = {i: (i + 1) % 10 for i in range(10)}
-        return HardcodedMapper(mapping)
+        qubit_register_size = 10
+        mapping = Mapping([(i + 1) % qubit_register_size for i in range(qubit_register_size)])
+        return HardcodedMapper(qubit_register_size, mapping)
 
     def test_compliance(self, mapper: HardcodedMapper) -> None:
         check_mapper(mapper)
 
-    def test_mapping(self, mapper: HardcodedMapper) -> None:
-        squirrel_ir = SquirrelIR(number_of_qubits=10)
-        mapping = mapper.map(squirrel_ir)
-        assert mapping == {0: 1, 1: 2, 2: 3, 3: 4, 4: 5, 5: 6, 6: 7, 7: 8, 8: 9, 9: 0}
-
-    @pytest.mark.parametrize("incorrect_mapping", [{0: 0, 1: 0}, {0: 1}])
-    def test_errors(self, incorrect_mapping: dict[int, int]) -> None:
-        with pytest.raises(ValueError):
-            HardcodedMapper(incorrect_mapping)
+    def test_get_mapping(self, mapper: HardcodedMapper) -> None:
+        assert mapper.get_mapping() == Mapping([1, 2, 3, 4, 5, 6, 7, 8, 9, 0])
diff --git a/test/merger/__init__.py b/test/merger/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/test/test_merger.py b/test/merger/test_merger.py
similarity index 67%
rename from test/test_merger.py
rename to test/merger/test_merger.py
index cdcc247c..23c19eef 100644
--- a/test/test_merger.py
+++ b/test/merger/test_merger.py
@@ -1,10 +1,12 @@
 import unittest
 from test.ir_equality_test_base import IREqualityTestBase
 
+from opensquirrel.circuit import Circuit
 from opensquirrel.default_gates import *
+from opensquirrel.ir import IR, Float, Qubit
 from opensquirrel.merger import general_merger
 from opensquirrel.merger.general_merger import compose_bloch_sphere_rotations
-from opensquirrel.squirrel_ir import Float, Qubit, SquirrelIR
+from opensquirrel.register_manager import RegisterManager
 
 
 class MergerTest(IREqualityTestBase):
@@ -25,55 +27,66 @@ def test_compose_bloch_sphere_rotations_different_axis(self):
         self.assertEqual(composed, BlochSphereRotation(qubit=q, axis=(1, 1, 0), angle=math.pi))
 
     def test_single_gate(self):
-        ir = SquirrelIR(number_of_qubits=2, qubit_register_name="q")
+        register_manager = RegisterManager(qubit_register_size=2)
+        ir = IR()
         ir.add_gate(Ry(Qubit(0), Float(1.2345)))
+        circuit = Circuit(register_manager, ir)
 
-        expected_ir = SquirrelIR(number_of_qubits=2, qubit_register_name="q")
+        expected_ir = IR()
         expected_ir.add_gate(Ry(Qubit(0), Float(1.2345)))
+        expected_circuit = Circuit(register_manager, expected_ir)
 
-        self.modify_ir_and_check(ir, action=general_merger.merge_single_qubit_gates, expected_ir=expected_ir)
+        self.modify_circuit_and_check(circuit, general_merger.merge_single_qubit_gates, expected_circuit)
 
         # Check that when no fusion happens, generator and arguments of gates are preserved.
         self.assertEqual(ir.statements[0].generator, Ry)
         self.assertEqual(ir.statements[0].arguments, (Qubit(0), Float(1.2345)))
 
     def test_two_hadamards(self):
-        ir = SquirrelIR(number_of_qubits=4, qubit_register_name="q")
-
+        register_manager = RegisterManager(qubit_register_size=4)
+        ir = IR()
         ir.add_gate(H(Qubit(2)))
         ir.add_gate(H(Qubit(2)))
+        circuit = Circuit(register_manager, ir)
 
-        expected_ir = SquirrelIR(number_of_qubits=4, qubit_register_name="q")
+        expected_ir = IR()
+        expected_circuit = Circuit(register_manager, expected_ir)
 
-        self.modify_ir_and_check(ir, action=general_merger.merge_single_qubit_gates, expected_ir=expected_ir)
+        self.modify_circuit_and_check(circuit, general_merger.merge_single_qubit_gates, expected_circuit)
 
     def test_two_hadamards_different_qubits(self):
-        ir = SquirrelIR(number_of_qubits=4, qubit_register_name="q")
+        register_manager = RegisterManager(qubit_register_size=4)
+        ir = IR()
         ir.add_gate(H(Qubit(0)))
         ir.add_gate(H(Qubit(2)))
+        circuit = Circuit(register_manager, ir)
 
-        expected_ir = SquirrelIR(number_of_qubits=4, qubit_register_name="q")
+        expected_ir = IR()
         expected_ir.add_gate(H(Qubit(0)))
         expected_ir.add_gate(H(Qubit(2)))
+        expected_circuit = Circuit(register_manager, expected_ir)
 
-        self.modify_ir_and_check(ir, action=general_merger.merge_single_qubit_gates, expected_ir=expected_ir)
+        self.modify_circuit_and_check(circuit, general_merger.merge_single_qubit_gates, expected_circuit)
 
     def test_merge_different_qubits(self):
-        ir = SquirrelIR(number_of_qubits=4, qubit_register_name="q")
+        register_manager = RegisterManager(qubit_register_size=4)
+        ir = IR()
         ir.add_gate(Ry(Qubit(0), Float(math.pi / 2)))
         ir.add_gate(Rx(Qubit(0), Float(math.pi)))
         ir.add_gate(Rz(Qubit(1), Float(1.2345)))
         ir.add_gate(Ry(Qubit(2), Float(1)))
         ir.add_gate(Ry(Qubit(2), Float(3.234)))
+        circuit = Circuit(register_manager, ir)
 
-        expected_ir = SquirrelIR(number_of_qubits=4, qubit_register_name="q")
+        expected_ir = IR()
         expected_ir.add_gate(
             BlochSphereRotation(qubit=Qubit(0), axis=(1, 0, 1), angle=math.pi)
         )  # This is hadamard with 0 phase...
         expected_ir.add_gate(Rz(Qubit(1), Float(1.2345)))
         expected_ir.add_gate(Ry(Qubit(2), Float(4.234)))
+        expected_circuit = Circuit(register_manager, expected_ir)
 
-        self.modify_ir_and_check(ir, action=general_merger.merge_single_qubit_gates, expected_ir=expected_ir)
+        self.modify_circuit_and_check(circuit, general_merger.merge_single_qubit_gates, expected_circuit)
 
         self.assertTrue(ir.statements[0].is_anonymous)  # When fusion happens, the resulting gate is anonymous.
         self.assertEqual(ir.statements[1].generator, Rz)  # Otherwise it keeps the same generator and arguments.
@@ -81,23 +94,26 @@ def test_merge_different_qubits(self):
         self.assertTrue(ir.statements[2].is_anonymous)
 
     def test_merge_and_flush(self):
-        ir = SquirrelIR(number_of_qubits=4, qubit_register_name="q")
+        register_manager = RegisterManager(qubit_register_size=4)
+        ir = IR()
         ir.add_gate(Ry(Qubit(0), Float(math.pi / 2)))
         ir.add_gate(Rz(Qubit(1), Float(1.5)))
         ir.add_gate(Rx(Qubit(0), Float(math.pi)))
         ir.add_gate(Rz(Qubit(1), Float(-2.5)))
         ir.add_gate(CNOT(Qubit(0), Qubit(1)))
         ir.add_gate(Ry(Qubit(0), Float(3.234)))
+        circuit = Circuit(register_manager, ir)
 
-        expected_ir = SquirrelIR(number_of_qubits=4, qubit_register_name="q")
+        expected_ir = IR()
         expected_ir.add_gate(
             BlochSphereRotation(qubit=Qubit(0), axis=(1, 0, 1), angle=math.pi)
         )  # This is hadamard with 0 phase...
         expected_ir.add_gate(Rz(Qubit(1), Float(-1.0)))
         expected_ir.add_gate(CNOT(Qubit(0), Qubit(1)))
         expected_ir.add_gate(Ry(Qubit(0), Float(3.234)))
+        expected_circuit = Circuit(register_manager, expected_ir)
 
-        self.modify_ir_and_check(ir, action=general_merger.merge_single_qubit_gates, expected_ir=expected_ir)
+        self.modify_circuit_and_check(circuit, general_merger.merge_single_qubit_gates, expected_circuit)
 
         self.assertTrue(ir.statements[0].is_anonymous)
         self.assertEqual(ir.statements[3].generator, Ry)
diff --git a/test/parser/__init__.py b/test/parser/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/test/parser/libqasm/__init__.py b/test/parser/libqasm/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/test/test_libqasm.py b/test/parser/libqasm/test_libqasm.py
similarity index 59%
rename from test/test_libqasm.py
rename to test/parser/libqasm/test_libqasm.py
index 110055ab..cd991f3e 100644
--- a/test/test_libqasm.py
+++ b/test/parser/libqasm/test_libqasm.py
@@ -1,34 +1,36 @@
 import unittest
 
 from opensquirrel.default_gates import *
-from opensquirrel.parser.libqasm.libqasm_ir_creator import LibqasmIRCreator
+from opensquirrel.parser.libqasm.parser import Parser
 
 
 class LibqasmTest(unittest.TestCase):
     def setUp(self):
-        self.libqasm_ir_creator = LibqasmIRCreator(gate_set=default_gate_set, gate_aliases=default_gate_aliases)
+        self.parser = Parser(gate_set=default_gate_set, gate_aliases=default_gate_aliases)
 
     def test_simple(self):
-        ir = self.libqasm_ir_creator.squirrel_ir_from_string(
+        circuit = self.parser.circuit_from_string(
             """
 version 3.0
 
-qubit[2] my_qubits
+qubit[2] q
 
-H my_qubits[0]
-Ry my_qubits[1], 1.234
-CNOT my_qubits[0], my_qubits[1]
-CR my_qubits[1], my_qubits[0], 5.123
-CRk my_qubits[0], my_qubits[1], 23
-        """
+H q[0]
+I q[0]
+Ry q[1], 1.234
+CNOT q[0], q[1]
+CR q[1], q[0], 5.123
+CRk q[0], q[1], 23
+"""
         )
 
-        self.assertEqual(ir.number_of_qubits, 2)
-        self.assertEqual(ir.qubit_register_name, "my_qubits")
+        self.assertEqual(circuit.qubit_register_size, 2)
+        self.assertEqual(circuit.qubit_register_name, "q")
         self.assertEqual(
-            ir.statements,
+            circuit.ir.statements,
             [
                 H(Qubit(0)),
+                I(Qubit(0)),
                 Ry(Qubit(1), Float(1.234)),
                 CNOT(Qubit(0), Qubit(1)),
                 CR(Qubit(1), Qubit(0), Float(5.123)),
@@ -37,7 +39,7 @@ def test_simple(self):
         )
 
     def test_sgmq(self):
-        ir = self.libqasm_ir_creator.squirrel_ir_from_string(
+        circuit = self.parser.circuit_from_string(
             """
 version 3.0
 
@@ -46,13 +48,13 @@ def test_sgmq(self):
 H q[5:9]
 X q[13,17]
 CRk q[0, 3], q[1, 4], 23
-        """
+"""
         )
 
-        self.assertEqual(ir.number_of_qubits, 20)
-        self.assertEqual(ir.qubit_register_name, "q")
+        self.assertEqual(circuit.qubit_register_size, 20)
+        self.assertEqual(circuit.qubit_register_name, "q")
         self.assertEqual(
-            ir.statements,
+            circuit.ir.statements,
             [
                 H(Qubit(5)),
                 H(Qubit(6)),
@@ -68,17 +70,17 @@ def test_sgmq(self):
 
     def test_error(self):
         with self.assertRaisesRegex(Exception, "Error at <unknown file name>:1:30..31: failed to resolve variable 'q'"):
-            self.libqasm_ir_creator.squirrel_ir_from_string("""version 3.0; qubit[20] qu; H q[5]""")
+            self.parser.circuit_from_string("""version 3.0; qubit[20] qu; H q[5]""")
 
     def test_wrong_gate_argument_number_or_types(self):
         with self.assertRaisesRegex(
             Exception,
             r"Parsing error: Error at <unknown file name>:1:26\.\.27: failed to resolve instruction 'H' with argument pack \(qubit, int\)",
         ):
-            self.libqasm_ir_creator.squirrel_ir_from_string("""version 3.0; qubit[1] q; H q[0], 1""")
+            self.parser.circuit_from_string("""version 3.0; qubit[1] q; H q[0], 1""")
 
         with self.assertRaisesRegex(
             Exception,
             r"Parsing error: Error at <unknown file name>:1:26\.\.30: failed to resolve instruction 'CNOT' with argument pack \(qubit, int\)",
         ):
-            self.libqasm_ir_creator.squirrel_ir_from_string("""version 3.0; qubit[1] q; CNOT q[0], 1""")
+            self.parser.circuit_from_string("""version 3.0; qubit[1] q; CNOT q[0], 1""")
diff --git a/test/reindexer/test_qubit_reindexer.py b/test/reindexer/test_qubit_reindexer.py
new file mode 100644
index 00000000..63453ee4
--- /dev/null
+++ b/test/reindexer/test_qubit_reindexer.py
@@ -0,0 +1,84 @@
+import math
+from typing import List
+
+import numpy as np
+import pytest
+
+from opensquirrel.circuit import Circuit
+from opensquirrel.default_gates import Y90, X
+from opensquirrel.ir import IR, BlochSphereRotation, ControlledGate, Gate, MatrixGate, Measure, Qubit
+from opensquirrel.register_manager import RegisterManager
+from opensquirrel.reindexer.qubit_reindexer import get_reindexed_circuit
+
+
+class TestReindexer:
+    @pytest.fixture
+    def replacement_gates_2(self) -> List[Gate]:
+        return [Y90(Qubit(1)), X(Qubit(3))]
+
+    @pytest.fixture
+    def replacement_gates_4(self) -> List[Gate]:
+        return [
+            Measure(Qubit(1)),
+            BlochSphereRotation(Qubit(3), axis=(0, 0, 1), angle=math.pi),
+            MatrixGate(
+                np.array(
+                    [
+                        [1, 0, 0, 0],
+                        [0, 0, 1, 0],
+                        [0, 1, 0, 0],
+                        [0, 0, 0, 1],
+                    ]
+                ),
+                [Qubit(0), Qubit(3)],
+            ),
+            ControlledGate(Qubit(1), X(Qubit(2))),
+        ]
+
+    @pytest.fixture
+    def circuit_3_reindexed(self) -> Circuit:
+        ir = IR()
+        ir.add_gate(Y90(Qubit(1)))
+        ir.add_gate(X(Qubit(0)))
+        return Circuit(RegisterManager(qubit_register_size=2), ir)
+
+    @pytest.fixture
+    def circuit_4_reindexed(self) -> Circuit:
+        ir = IR()
+        ir.add_gate(Measure(Qubit(0)))
+        ir.add_gate(BlochSphereRotation(Qubit(2), axis=(0, 0, 1), angle=math.pi))
+        ir.add_gate(
+            MatrixGate(
+                np.array(
+                    [
+                        [1, 0, 0, 0],
+                        [0, 0, 1, 0],
+                        [0, 1, 0, 0],
+                        [0, 0, 0, 1],
+                    ]
+                ),
+                [Qubit(1), Qubit(2)],
+            )
+        )
+        ir.add_gate(ControlledGate(Qubit(0), X(Qubit(3))))
+        return Circuit(RegisterManager(qubit_register_size=4), ir)
+
+    @pytest.fixture
+    def qubit_indices_2(self) -> List[int]:
+        return [3, 1]
+
+    @pytest.fixture
+    def qubit_indices_4(self) -> List[int]:
+        return [1, 0, 3, 2]
+
+    def test_get_reindexed_circuit_3(
+        self, replacement_gates_2: List[Gate], qubit_indices_2: List[int], circuit_3_reindexed: Circuit
+    ) -> None:
+        circuit_3 = get_reindexed_circuit(replacement_gates_2, qubit_indices_2)
+        assert circuit_3 == circuit_3_reindexed
+
+    def test_get_reindexed_circuit_4(
+        self, replacement_gates_4: List[Gate], qubit_indices_4: List[int], circuit_4_reindexed: Circuit
+    ) -> None:
+        circuit_4 = get_reindexed_circuit(replacement_gates_4, qubit_indices_4)
+        assert circuit_4 == circuit_4_reindexed
diff --git a/test/test_circuit_builder.py b/test/test_circuit_builder.py
index a4cd4526..6248b725 100644
--- a/test/test_circuit_builder.py
+++ b/test/test_circuit_builder.py
@@ -1,65 +1,104 @@
-import unittest
+import re
+
+import pytest
 
 from opensquirrel.circuit_builder import CircuitBuilder
-from opensquirrel.default_gates import *
-from opensquirrel.squirrel_ir import Qubit
+from opensquirrel.default_gates import CNOT, H, I
+from opensquirrel.ir import Comment, Measure, Qubit
 
 
-class CircuitBuilderTest(unittest.TestCase):
+class TestCircuitBuilder:
     def test_simple(self):
-        print(default_gate_aliases)
-        builder = CircuitBuilder(3)
+        builder = CircuitBuilder(2)
 
+        builder.comment("A single line comment.")
         builder.H(Qubit(0))
         builder.CNOT(Qubit(0), Qubit(1))
 
         circuit = builder.to_circuit()
 
-        self.assertEqual(circuit.number_of_qubits, 3)
-        self.assertEqual(circuit.qubit_register_name, "q")
-        self.assertEqual(
-            circuit.squirrel_ir.statements,
-            [
-                H(Qubit(0)),
-                CNOT(Qubit(0), Qubit(1)),
-            ],
-        )
+        assert circuit.qubit_register_size == 2
+        assert circuit.qubit_register_name == "q"
+        assert circuit.ir.statements == [
+            Comment("A single line comment."),
+            H(Qubit(0)),
+            CNOT(Qubit(0), Qubit(1)),
+        ]
+
+    def test_identity(self):
+        builder = CircuitBuilder(1)
+        builder.I(Qubit(0))
+
+        circuit = builder.to_circuit()
+
+        assert circuit.qubit_register_size == 1
+        assert circuit.qubit_register_name == "q"
+        assert circuit.ir.statements == [
+            I(Qubit(0)),
+        ]
+
+    def test_single_measure(self):
+        builder = CircuitBuilder(1)
+        builder.measure(Qubit(0))
+
+        circuit = builder.to_circuit()
+
+        assert circuit.qubit_register_size == 1
+        assert circuit.qubit_register_name == "q"
+        assert circuit.ir.statements == [
+            Measure(Qubit(0)),
+        ]
+
+    def test_circuit_measure(self):
+        builder = CircuitBuilder(2)
+
+        builder.H(Qubit(0))
+        builder.CNOT(Qubit(0), Qubit(1))
+        builder.measure(Qubit(0))
+        builder.measure(Qubit(1))
+
+        circuit = builder.to_circuit()
+
+        assert circuit.qubit_register_size == 2
+        assert circuit.qubit_register_name == "q"
+        assert circuit.ir.statements == [
+            H(Qubit(0)),
+            CNOT(Qubit(0), Qubit(1)),
+            Measure(Qubit(0)),
+            Measure(Qubit(1)),
+        ]
 
     def test_chain(self):
         builder = CircuitBuilder(3)
 
         circuit = builder.H(Qubit(0)).CNOT(Qubit(0), Qubit(1)).to_circuit()
 
-        self.assertEqual(
-            circuit.squirrel_ir.statements,
-            [
-                H(Qubit(0)),
-                CNOT(Qubit(0), Qubit(1)),
-            ],
-        )
+        assert circuit.ir.statements == [
+            H(Qubit(0)),
+            CNOT(Qubit(0), Qubit(1)),
+        ]
 
-    def test_unknown_gate(self):
+    def test_unknown_instruction(self):
         builder = CircuitBuilder(3)
 
-        with self.assertRaisesRegex(Exception, "Unknown gate `UN`"):
-            builder.UN(0)
+        with pytest.raises(Exception) as exception_info:
+            builder.unknown(0)
+        assert re.search("Unknown instruction `unknown`", str(exception_info.value))
 
     def test_wrong_number_of_arguments(self):
         builder = CircuitBuilder(3)
 
-        with self.assertRaisesRegex(TypeError, r"H\(\) takes 1 positional argument but 2 were given"):
+        with pytest.raises(Exception) as exception_info:
             builder.H(Qubit(0), Qubit(1))
+        assert re.search(r"H\(\) takes 1 positional argument but 2 were given", str(exception_info.value))
 
     def test_wrong_argument_type(self):
         builder = CircuitBuilder(3)
 
-        with self.assertRaisesRegex(
-            TypeError,
-            "Wrong argument type for gate `H`, got <class 'int'> but expected "
-            "<class 'opensquirrel.squirrel_ir.Qubit'>",
-        ):
+        with pytest.raises(Exception) as exception_info:
             builder.H(0)
-
-
-if __name__ == "__main__":
-    unittest.main()
+        assert re.search(
+            "Wrong argument type for instruction `H`, got <class 'int'> but expected <class "
+            "'opensquirrel.ir.Qubit'>",
+            str(exception_info.value),
+        )
diff --git a/test/test_circuit_matrix_calculator.py b/test/test_circuit_matrix_calculator.py
index a2e555ee..778524e4 100644
--- a/test/test_circuit_matrix_calculator.py
+++ b/test/test_circuit_matrix_calculator.py
@@ -1,18 +1,22 @@
 import unittest
 
 from opensquirrel import circuit_matrix_calculator
+from opensquirrel.circuit import Circuit
 from opensquirrel.default_gates import *
-from opensquirrel.squirrel_ir import Qubit, SquirrelIR
+from opensquirrel.ir import IR, Qubit
+from opensquirrel.register_manager import RegisterManager
 
 
 class CircuitMatrixCalculatorTest(unittest.TestCase):
     def test_hadamard(self):
-        squirrel_ir = SquirrelIR(number_of_qubits=1)
-        squirrel_ir.add_gate(H(Qubit(0)))
+        register_manager = RegisterManager(qubit_register_size=1)
+        ir = IR()
+        ir.add_gate(H(Qubit(0)))
+        circuit = Circuit(register_manager, ir)
 
         self.assertTrue(
             np.allclose(
-                circuit_matrix_calculator.get_circuit_matrix(squirrel_ir),
+                circuit_matrix_calculator.get_circuit_matrix(circuit),
                 math.sqrt(0.5)
                 * np.array(
                     [
@@ -24,21 +28,25 @@ def test_hadamard(self):
         )
 
     def test_double_hadamard(self):
-        squirrel_ir = SquirrelIR(number_of_qubits=1)
-        squirrel_ir.add_gate(H(Qubit(0)))
-        squirrel_ir.add_gate(H(Qubit(0)))
+        register_manager = RegisterManager(qubit_register_size=1)
+        ir = IR()
+        ir.add_gate(H(Qubit(0)))
+        ir.add_gate(H(Qubit(0)))
+        circuit = Circuit(register_manager, ir)
 
-        self.assertTrue(np.allclose(circuit_matrix_calculator.get_circuit_matrix(squirrel_ir), np.eye(2)))
+        self.assertTrue(np.allclose(circuit_matrix_calculator.get_circuit_matrix(circuit), np.eye(2)))
 
     def test_triple_hadamard(self):
-        squirrel_ir = SquirrelIR(number_of_qubits=1)
-        squirrel_ir.add_gate(H(Qubit(0)))
-        squirrel_ir.add_gate(H(Qubit(0)))
-        squirrel_ir.add_gate(H(Qubit(0)))
+        register_manager = RegisterManager(qubit_register_size=1)
+        ir = IR()
+        ir.add_gate(H(Qubit(0)))
+        ir.add_gate(H(Qubit(0)))
+        ir.add_gate(H(Qubit(0)))
+        circuit = Circuit(register_manager, ir)
 
         self.assertTrue(
             np.allclose(
-                circuit_matrix_calculator.get_circuit_matrix(squirrel_ir),
+                circuit_matrix_calculator.get_circuit_matrix(circuit),
                 math.sqrt(0.5)
                 * np.array(
                     [
@@ -50,13 +58,15 @@ def test_triple_hadamard(self):
         )
 
     def test_hadamard_x(self):
-        squirrel_ir = SquirrelIR(number_of_qubits=2)
-        squirrel_ir.add_gate(H(Qubit(0)))
-        squirrel_ir.add_gate(X(Qubit(1)))
+        register_manager = RegisterManager(qubit_register_size=2)
+        ir = IR()
+        ir.add_gate(H(Qubit(0)))
+        ir.add_gate(X(Qubit(1)))
+        circuit = Circuit(register_manager, ir)
 
         self.assertTrue(
             np.allclose(
-                circuit_matrix_calculator.get_circuit_matrix(squirrel_ir),
+                circuit_matrix_calculator.get_circuit_matrix(circuit),
                 math.sqrt(0.5)
                 * np.array(
                     [
@@ -70,13 +80,15 @@ def test_hadamard_x(self):
         )
 
     def test_x_hadamard(self):
-        squirrel_ir = SquirrelIR(number_of_qubits=2)
-        squirrel_ir.add_gate(H(Qubit(1)))
-        squirrel_ir.add_gate(X(Qubit(0)))
+        register_manager = RegisterManager(qubit_register_size=2)
+        ir = IR()
+        ir.add_gate(H(Qubit(1)))
+        ir.add_gate(X(Qubit(0)))
+        circuit = Circuit(register_manager, ir)
 
         self.assertTrue(
             np.allclose(
-                circuit_matrix_calculator.get_circuit_matrix(squirrel_ir),
+                circuit_matrix_calculator.get_circuit_matrix(circuit),
                 math.sqrt(0.5)
                 * np.array(
                     [
@@ -90,12 +102,14 @@ def test_x_hadamard(self):
         )
 
     def test_cnot(self):
-        squirrel_ir = SquirrelIR(number_of_qubits=2)
-        squirrel_ir.add_gate(CNOT(Qubit(1), Qubit(0)))
+        register_manager = RegisterManager(qubit_register_size=2)
+        ir = IR()
+        ir.add_gate(CNOT(Qubit(1), Qubit(0)))
+        circuit = Circuit(register_manager, ir)
 
         self.assertTrue(
             np.allclose(
-                circuit_matrix_calculator.get_circuit_matrix(squirrel_ir),
+                circuit_matrix_calculator.get_circuit_matrix(circuit),
                 np.array(
                     [
                         [1, 0, 0, 0],
@@ -108,12 +122,14 @@ def test_cnot(self):
         )
 
     def test_cnot_reversed(self):
-        squirrel_ir = SquirrelIR(number_of_qubits=2)
-        squirrel_ir.add_gate(CNOT(Qubit(0), Qubit(1)))
+        register_manager = RegisterManager(qubit_register_size=2)
+        ir = IR()
+        ir.add_gate(CNOT(Qubit(0), Qubit(1)))
+        circuit = Circuit(register_manager, ir)
 
         self.assertTrue(
             np.allclose(
-                circuit_matrix_calculator.get_circuit_matrix(squirrel_ir),
+                circuit_matrix_calculator.get_circuit_matrix(circuit),
                 np.array(
                     [
                         [1, 0, 0, 0],
@@ -126,13 +142,15 @@ def test_cnot_reversed(self):
         )
 
     def test_hadamard_cnot(self):
-        squirrel_ir = SquirrelIR(number_of_qubits=2)
-        squirrel_ir.add_gate(H(Qubit(0)))
-        squirrel_ir.add_gate(CNOT(Qubit(0), Qubit(1)))
+        register_manager = RegisterManager(qubit_register_size=2)
+        ir = IR()
+        ir.add_gate(H(Qubit(0)))
+        ir.add_gate(CNOT(Qubit(0), Qubit(1)))
+        circuit = Circuit(register_manager, ir)
 
         self.assertTrue(
             np.allclose(
-                circuit_matrix_calculator.get_circuit_matrix(squirrel_ir),
+                circuit_matrix_calculator.get_circuit_matrix(circuit),
                 math.sqrt(0.5)
                 * np.array(
                     [
@@ -146,14 +164,16 @@ def test_hadamard_cnot(self):
         )
 
     def test_hadamard_cnot_0_2(self):
-        squirrel_ir = SquirrelIR(number_of_qubits=3)
-        squirrel_ir.add_gate(H(Qubit(0)))
-        squirrel_ir.add_gate(CNOT(Qubit(0), Qubit(2)))
+        register_manager = RegisterManager(qubit_register_size=3)
+        ir = IR()
+        ir.add_gate(H(Qubit(0)))
+        ir.add_gate(CNOT(Qubit(0), Qubit(2)))
+        circuit = Circuit(register_manager, ir)
 
-        print(circuit_matrix_calculator.get_circuit_matrix(squirrel_ir))
+        print(circuit_matrix_calculator.get_circuit_matrix(circuit))
         self.assertTrue(
             np.allclose(
-                circuit_matrix_calculator.get_circuit_matrix(squirrel_ir),
+                circuit_matrix_calculator.get_circuit_matrix(circuit),
                 math.sqrt(0.5)
                 * np.array(
                     [
diff --git a/test/test_integration.py b/test/test_integration.py
index 0332c0fa..42ff1d78 100644
--- a/test/test_integration.py
+++ b/test/test_integration.py
@@ -13,17 +13,17 @@
 
 class IntegrationTest(unittest.TestCase):
     def test_simple(self):
-        myCircuit = Circuit.from_string(
+        circuit = Circuit.from_string(
             """
-                version 3.0
+            version 3.0
 
-                qubit[3] qreg
+            qubit[3] q
 
-                Ry(1.23) qreg[0]
-                Ry(2.34) qreg[1]
-                CNOT qreg[0], qreg[1]
-                Rx(-2.3) qreg[0]
-                Ry(-3.14) qreg[1]
+            Ry(1.23) q[0]
+            Ry(2.34) q[1]
+            CNOT q[0], q[1]
+            Rx(-2.3) q[0]
+            Ry(-3.14) q[1]
             """
         )
 
@@ -34,7 +34,7 @@ def test_simple(self):
         #    -----⊕----         --- H --•-- H ---
         #
 
-        myCircuit.replace(
+        circuit.replace(
             CNOT,
             lambda control, target: [
                 H(target),
@@ -44,155 +44,232 @@ def test_simple(self):
         )
 
         # Do 1q-gate fusion and decomposer with McKay decomposition.
+        circuit.merge_single_qubit_gates()
+        circuit.decompose(decomposer=McKayDecomposer)
 
-        myCircuit.merge_single_qubit_gates()
-
-        myCircuit.decompose(decomposer=McKayDecomposer)
-
-        # Write the transformed circuit as a cQasm3 string.
-
-        output = str(myCircuit)
+        # Write the transformed circuit as a cQASM v3 string.
         self.assertEqual(
-            output,
+            str(circuit),
             """version 3.0
 
-qubit[3] qreg
-
-Rz(3.1415927) qreg[0]
-X90 qreg[0]
-Rz(1.9115927) qreg[0]
-X90 qreg[0]
-Rz(3.1415927) qreg[1]
-X90 qreg[1]
-Rz(2.372389) qreg[1]
-X90 qreg[1]
-Rz(3.1415927) qreg[1]
-CZ qreg[0], qreg[1]
-Rz(1.5707963) qreg[0]
-X90 qreg[0]
-Rz(0.84159265) qreg[0]
-X90 qreg[0]
-Rz(1.5707963) qreg[0]
-Rz(3.1415927) qreg[1]
-X90 qreg[1]
-Rz(1.5723889) qreg[1]
-X90 qreg[1]
-Rz(3.1415927) qreg[1]
+qubit[3] q
+
+Rz(3.1415927) q[0]
+X90 q[0]
+Rz(1.9115927) q[0]
+X90 q[0]
+Rz(3.1415927) q[1]
+X90 q[1]
+Rz(2.372389) q[1]
+X90 q[1]
+Rz(3.1415927) q[1]
+CZ q[0], q[1]
+Rz(1.5707963) q[0]
+X90 q[0]
+Rz(0.84159265) q[0]
+X90 q[0]
+Rz(1.5707963) q[0]
+Rz(3.1415927) q[1]
+X90 q[1]
+Rz(1.5723889) q[1]
+X90 q[1]
+Rz(3.1415927) q[1]
 """,
         )
 
     def test_measurement(self):
-        myCircuit = Circuit.from_string(
+        circuit = Circuit.from_string(
             """
-                version 3.0
+            version 3.0
 
-                qubit[3] qreg
+            qubit[3] q
+            bit[3] b
 
-                Ry(2.34) qreg[2]
-                Rz(1.5707963) qreg[0]
-                Ry(-0.2) qreg[0]
-                CNOT qreg[1], qreg[0]
-                Rz(1.5789) qreg[0]
-                CNOT qreg[1], qreg[0]
-                Rz(2.5707963) qreg[1]
-                measure qreg[0,2]
+            Ry(2.34) q[2]
+            Rz(1.5707963) q[0]
+            Ry(-0.2) q[0]
+            CNOT q[1], q[0]
+            Rz(1.5789) q[0]
+            CNOT q[1], q[0]
+            Rz(2.5707963) q[1]
+            b[0, 2] = measure q[0, 2]
             """,
         )
-        myCircuit.merge_single_qubit_gates()
-        myCircuit.decompose(decomposer=McKayDecomposer)
+        circuit.merge_single_qubit_gates()
+        circuit.decompose(decomposer=McKayDecomposer)
         self.assertEqual(
-            str(myCircuit),
+            str(circuit),
             """version 3.0
 
-qubit[3] qreg
-
-Rz(1.5707963) qreg[0]
-X90 qreg[0]
-Rz(2.9415927) qreg[0]
-X90 qreg[0]
-Rz(3.1415926) qreg[0]
-CNOT qreg[1], qreg[0]
-Rz(1.5789) qreg[0]
-CNOT qreg[1], qreg[0]
-Rz(3.1415927) qreg[2]
-X90 qreg[2]
-Rz(0.80159265) qreg[2]
-X90 qreg[2]
-Rz(2.5707963) qreg[1]
-measure qreg[0]
-measure qreg[2]
+qubit[3] q
+
+Rz(1.5707963) q[0]
+X90 q[0]
+Rz(2.9415927) q[0]
+X90 q[0]
+Rz(3.1415926) q[0]
+CNOT q[1], q[0]
+Rz(1.5789) q[0]
+CNOT q[1], q[0]
+measure q[0]
+Rz(3.1415927) q[2]
+X90 q[2]
+Rz(0.80159265) q[2]
+X90 q[2]
+measure q[2]
+Rz(2.5707963) q[1]
 """,
         )
 
     def test_consecutive_measurements(self):
-        myCircuit = Circuit.from_string(
+        circuit = Circuit.from_string(
             """
-                version 3.0
+            version 3.0
+
+            qubit[3] q
+            bit[3] b
+
+            H q[0]
+            H q[1]
+            H q[2]
+            b[0] = measure q[0]
+            b[1] = measure q[1]
+            b[2] = measure q[2]
+            """
+        )
+        circuit.merge_single_qubit_gates()
+        circuit.decompose(decomposer=McKayDecomposer)
+        self.assertEqual(
+            str(circuit),
+            """version 3.0
+
+qubit[3] q
+
+X90 q[0]
+Rz(1.5707963) q[0]
+X90 q[0]
+measure q[0]
+X90 q[1]
+Rz(1.5707963) q[1]
+X90 q[1]
+measure q[1]
+X90 q[2]
+Rz(1.5707963) q[2]
+X90 q[2]
+measure q[2]
+""",
+        )
 
-                qubit[3] qreg
+    def test_measurements_unrolling(self):
+        circuit = Circuit.from_string(
+            """
+            version 3.0
 
-                H qreg[0]
-                H qreg[1]
-                H qreg[2]
-                measure qreg[0]
-                measure qreg[1]
-                measure qreg[2]
+            qubit[3] q
+            bit[3] b
+
+            H q[0]
+            H q[1]
+            H q[2]
+            b = measure q
             """
         )
-        myCircuit.merge_single_qubit_gates()
-        myCircuit.decompose(decomposer=McKayDecomposer)
+        circuit.merge_single_qubit_gates()
+        circuit.decompose(decomposer=McKayDecomposer)
         self.assertEqual(
-            str(myCircuit),
+            str(circuit),
             """version 3.0
 
-qubit[3] qreg
-
-X90 qreg[0]
-Rz(1.5707963) qreg[0]
-X90 qreg[0]
-X90 qreg[1]
-Rz(1.5707963) qreg[1]
-X90 qreg[1]
-X90 qreg[2]
-Rz(1.5707963) qreg[2]
-X90 qreg[2]
-measure qreg[0]
-measure qreg[1]
-measure qreg[2]
+qubit[3] q
+
+X90 q[0]
+Rz(1.5707963) q[0]
+X90 q[0]
+measure q[0]
+X90 q[1]
+Rz(1.5707963) q[1]
+X90 q[1]
+measure q[1]
+X90 q[2]
+Rz(1.5707963) q[2]
+X90 q[2]
+measure q[2]
 """,
         )
 
     def test_measure_order(self):
-        myCircuit = Circuit.from_string(
+        circuit = Circuit.from_string(
             """
-                version 3.0
+            version 3.0
 
-                qubit[2] qreg
+            qubit[2] q
+            bit[2] b
 
-                Rz(-2.3561945) qreg[1]
-                Rz(1.5707963) qreg[1]
-                measure qreg[1,0]
+            Rz(-2.3561945) q[1]
+            Rz(1.5707963) q[1]
+            b[1, 0] = measure q[1, 0]
             """
         )
-        myCircuit.merge_single_qubit_gates()
-        myCircuit.decompose(decomposer=McKayDecomposer)
-        output = str(myCircuit)
-        expected = """version 3.0
-
-qubit[2] qreg
-
-Rz(2.7488936) qreg[1]
-X90 qreg[1]
-Rz(3.1415927) qreg[1]
-X90 qreg[1]
-Rz(-0.3926991) qreg[1]
-measure qreg[1]
-measure qreg[0]
-"""
-        self.assertEqual(output, expected)
+        circuit.merge_single_qubit_gates()
+        circuit.decompose(decomposer=McKayDecomposer)
+        self.assertEqual(
+            str(circuit),
+            """version 3.0
+
+qubit[2] q
+
+Rz(2.7488936) q[1]
+X90 q[1]
+Rz(3.1415927) q[1]
+X90 q[1]
+Rz(-0.3926991) q[1]
+measure q[1]
+measure q[0]
+""",
+        )
+
+    def test_multiple_qubit_bit_definitions_and_mid_circuit_measure_instructions(self):
+        circuit = Circuit.from_string(
+            """
+            version 3.0
+
+            qubit q0
+            bit b0
+            X q0
+            b0 = measure q0
+
+            qubit q1
+            bit b1
+            H q1
+            CNOT q1, q0
+            b1 = measure q1
+            b0 = measure q0
+            """
+        )
+        circuit.merge_single_qubit_gates()
+        circuit.decompose(decomposer=McKayDecomposer)
+        self.assertEqual(
+            str(circuit),
+            """version 3.0
+
+qubit[2] q
+
+Rz(-1.5707963) q[0]
+X90 q[0]
+X90 q[0]
+Rz(-1.5707963) q[0]
+measure q[0]
+X90 q[1]
+Rz(1.5707963) q[1]
+X90 q[1]
+CNOT q[1], q[0]
+measure q[1]
+measure q[0]
+""",
+        )
 
     def test_qi(self):
-        myCircuit = Circuit.from_string(
+        circuit = Circuit.from_string(
             """
             version 3.0
 
@@ -202,7 +279,7 @@ def test_qi(self):
             /* This is a multi-
             line comment block */
 
-            qubit[4] q   // Qubit (register) declaration
+            qubit[4] q
 
             // Let us create a Bell state on 2 qubits and a |+> state on the third qubit
 
@@ -221,11 +298,12 @@ def test_qi(self):
             """
         )
 
-        myCircuit.merge_single_qubit_gates()
+        circuit.merge_single_qubit_gates()
+        circuit.decompose(decomposer=McKayDecomposer)
 
-        myCircuit.decompose(decomposer=McKayDecomposer)
-        output = str(myCircuit)
-        expected = """version 3.0
+        self.assertEqual(
+            str(circuit),
+            """version 3.0
 
 qubit[4] q
 
@@ -250,42 +328,43 @@ def test_qi(self):
 Rz(1.5707963) q[1]
 X90 q[1]
 Rz(3.1415927) q[1]
-"""
-
-        self.assertEqual(output, expected)
+""",
+        )
 
     def test_libqasm_error(self):
         with self.assertRaisesRegex(
             Exception,
-            r"Parsing error: Error at <unknown file name>:4:21\.\.23: failed to resolve instruction 'Ry' with argument pack \(qubit, float, int\)",
+            r"Parsing error: Error at <unknown file name>:4:17\.\.19: failed to resolve instruction 'Ry' with argument pack \(qubit, float, int\)",
         ):
             Circuit.from_string(
                 """
-                    version 3.0
-                    qubit[3] qreg
-                    Ry qreg[0], 1.23, 1
+                version 3.0
+                qubit[3] q
+                Ry q[0], 1.23, 1
                 """,
             )
 
     def test_export_quantify_scheduler(self):
-        myCircuit = Circuit.from_string(
+        circuit = Circuit.from_string(
             """
-                version 3.0
+            version 3.0
 
-                qubit[3] qreg
+            qubit[3] q
+            bit[3] b
 
-                H qreg[1]
-                CZ qreg[0], qreg[1]
-                CNOT qreg[0], qreg[1]
-                CRk(4) qreg[0], qreg[1]
-                H qreg[0]
+            H q[1]
+            CZ q[0], q[1]
+            CNOT q[0], q[1]
+            CRk(4) q[0], q[1]
+            H q[0]
+            b[0:1] = measure q[0:1]
             """
         )
 
-        myCircuit.decompose(decomposer=CNOTDecomposer)
+        circuit.decompose(decomposer=CNOTDecomposer)
 
         # Quantify-scheduler prefers CZ.
-        myCircuit.replace(
+        circuit.replace(
             CNOT,
             lambda control, target: [
                 H(target),
@@ -295,19 +374,19 @@ def test_export_quantify_scheduler(self):
         )
 
         # Reduce gate count by single-qubit gate fusion.
-        myCircuit.merge_single_qubit_gates()
+        circuit.merge_single_qubit_gates()
 
         # FIXME: for best gate count we need a Z-XY decomposer.
         # See https://github.com/QuTech-Delft/OpenSquirrel/issues/98
-        myCircuit.decompose(decomposer=ZYZDecomposer)
+        circuit.decompose(decomposer=ZYZDecomposer)
 
         if importlib.util.find_spec("quantify_scheduler") is None:
             with self.assertRaisesRegex(
                 Exception, "quantify-scheduler is not installed, or cannot be installed on " "your system"
             ):
-                myCircuit.export(fmt=ExportFormat.QUANTIFY_SCHEDULER)
+                circuit.export(fmt=ExportFormat.QUANTIFY_SCHEDULER)
         else:
-            exported_schedule = myCircuit.export(fmt=ExportFormat.QUANTIFY_SCHEDULER)
+            exported_schedule = circuit.export(fmt=ExportFormat.QUANTIFY_SCHEDULER)
 
             self.assertEqual(exported_schedule.name, "Exported OpenSquirrel circuit")
 
@@ -319,50 +398,51 @@ def test_export_quantify_scheduler(self):
             self.assertEqual(
                 operations,
                 [
-                    "Rz(-180, 'qreg[1]')",
-                    "Rxy(90, 90, 'qreg[1]')",
-                    "CZ (qreg[0], qreg[1])",
-                    "Rz(-180, 'qreg[1]')",
-                    "Rxy(90, 90, 'qreg[1]')",
-                    "CZ (qreg[0], qreg[1])",
-                    "Rz(90, 'qreg[1]')",
-                    "Rxy(11.25, 90, 'qreg[1]')",
-                    "Rz(-90, 'qreg[1]')",
-                    "CZ (qreg[0], qreg[1])",
-                    "Rz(90, 'qreg[1]')",
-                    "Rxy(-11.25, 90, 'qreg[1]')",
-                    "Rz(-90, 'qreg[1]')",
-                    "CZ (qreg[0], qreg[1])",
-                    "Rz(11.25, 'qreg[0]')",
-                    "Rxy(-90, 90, 'qreg[0]')",
-                    "Rz(-180, 'qreg[0]')",
-                    "Rz(-180, 'qreg[1]')",
-                    "Rxy(90, 90, 'qreg[1]')",
+                    "Rz(-180, 'q[1]')",
+                    "Rxy(90, 90, 'q[1]')",
+                    "CZ (q[0], q[1])",
+                    "Rz(-180, 'q[1]')",
+                    "Rxy(90, 90, 'q[1]')",
+                    "CZ (q[0], q[1])",
+                    "Rz(90, 'q[1]')",
+                    "Rxy(11.25, 90, 'q[1]')",
+                    "Rz(-90, 'q[1]')",
+                    "CZ (q[0], q[1])",
+                    "Rz(90, 'q[1]')",
+                    "Rxy(-11.25, 90, 'q[1]')",
+                    "Rz(-90, 'q[1]')",
+                    "CZ (q[0], q[1])",
+                    "Rz(11.25, 'q[0]')",
+                    "Rxy(-90, 90, 'q[0]')",
+                    "Rz(-180, 'q[0]')",
+                    "Rz(-180, 'q[1]')",
+                    "Rxy(90, 90, 'q[1]')",
+                    "Measure q[0]",
+                    "Measure q[1]",
                 ],
             )
 
-    def test_H_identity_integration(self):
-        myCircuit = Circuit.from_string(
+    def test_merge_y90_x_to_h(self):
+        circuit = Circuit.from_string(
             """
             version 3.0
 
-            qubit[1] q   // Qubit (register) declaration
-
-            Y90 q[0]
-            X q[0]
+            qubit q
 
+            Y90 q
+            X q
             """
         )
-        myCircuit.merge_single_qubit_gates()
-        output = str(myCircuit)
-        expected = """version 3.0
+        circuit.merge_single_qubit_gates()
+        self.assertEqual(
+            str(circuit),
+            """version 3.0
 
 qubit[1] q
 
 H q[0]
-"""
-
-        self.assertEqual(expected, output)
+""",
+        )
 
 
 if __name__ == "__main__":
diff --git a/test/test_squirrel_ir.py b/test/test_ir.py
similarity index 78%
rename from test/test_squirrel_ir.py
rename to test/test_ir.py
index 99d99e9e..b711f883 100644
--- a/test/test_squirrel_ir.py
+++ b/test/test_ir.py
@@ -1,237 +1,196 @@
-from __future__ import annotations
-
-import math
-
-import numpy as np
-import pytest
-from numpy.typing import NDArray
-
-from opensquirrel.common import ATOL
-from opensquirrel.squirrel_ir import BlochSphereRotation, ControlledGate, MatrixGate, Measure, Qubit
-
-
-class TestSquirrelIR:
-    def test_cnot_equality(self):
-        matrix = np.array(
-            [
-                [1, 0, 0, 0],
-                [0, 1, 0, 0],
-                [0, 0, 0, 1],
-                [0, 0, 1, 0],
-            ]
-        )
-        cnot_matrix_gate = MatrixGate(matrix, operands=[Qubit(4), Qubit(100)])
-
-        cnot_controlled_gate = ControlledGate(
-            Qubit(4), BlochSphereRotation(qubit=Qubit(100), axis=(1, 0, 0), angle=math.pi, phase=math.pi / 2)
-        )
-
-        assert cnot_controlled_gate == cnot_matrix_gate
-
-    def test_different_qubits_gate(self):
-        matrix = np.array(
-            [
-                [1, 0, 0, 0],
-                [0, 1, 0, 0],
-                [0, 0, 1, 0],
-                [0, 0, 0, 1],
-            ]
-        )
-        large_identity_matrix_gate = MatrixGate(matrix, operands=[Qubit(0), Qubit(2)])
-        small_identity_control_gate = ControlledGate(
-            Qubit(4), BlochSphereRotation(qubit=Qubit(2), axis=(1, 0, 0), angle=0, phase=0)
-        )
-
-        assert large_identity_matrix_gate == small_identity_control_gate
-
-    def test_inverse_gate(self):
-        matrix = np.array(
-            [
-                [1, 0, 0, 0],
-                [0, 0, 0, 1],
-                [0, 0, 1, 0],
-                [0, 1, 0, 0],
-            ]
-        )
-        inverted_matrix_gate = MatrixGate(matrix, operands=[Qubit(0), Qubit(1)])
-
-        inverted_cnot_gate = ControlledGate(
-            Qubit(1), BlochSphereRotation(qubit=Qubit(0), axis=(1, 0, 0), angle=math.pi, phase=math.pi / 2)
-        )
-
-        assert inverted_matrix_gate == inverted_cnot_gate
-
-    def test_global_phase(self):
-        matrix = np.array(
-            [
-                [1j, 0, 0, 0],
-                [0, 0, 0, 1j],
-                [0, 0, 1j, 0],
-                [0, 1j, 0, 0],
-            ]
-        )
-        inverted_matrix_with_phase = MatrixGate(matrix, operands=[Qubit(0), Qubit(1)])
-
-        inverted_cnot_gate = ControlledGate(
-            Qubit(1), BlochSphereRotation(qubit=Qubit(0), axis=(1, 0, 0), angle=math.pi, phase=math.pi / 2)
-        )
-
-        assert inverted_matrix_with_phase == inverted_cnot_gate
-
-    def test_cnot_inequality(self):
-        matrix = np.array(
-            [
-                [1, 0, 0, 0],
-                [0, 0, 1, 0],
-                [0, 1, 0, 0],
-                [0, 0, 0, 1],
-            ]
-        )
-        swap_matrix_gate = MatrixGate(matrix, operands=[Qubit(4), Qubit(100)])
-
-        cnot_controlled_gate = ControlledGate(
-            Qubit(4), BlochSphereRotation(qubit=Qubit(100), axis=(1, 0, 0), angle=math.pi, phase=math.pi / 2)
-        )
-
-        assert cnot_controlled_gate != swap_matrix_gate
-
-
-class TestMeasure:
-
-    @pytest.fixture(name="measure")
-    def measure_fixture(self) -> Measure:
-        return Measure(Qubit(42), axis=(0, 0, 1))
-
-    def test_repr(self, measure: Measure) -> None:
-        expected_repr = "Measure(Qubit[42], axis=[0. 0. 1.])"
-        assert repr(measure) == expected_repr
-
-    def test_equality(self, measure: Measure) -> None:
-        measure_eq = Measure(Qubit(42), axis=(0, 0, 1))
-        assert measure == measure_eq
-
-    @pytest.mark.parametrize(
-        "other_measure",
-        [Measure(Qubit(43), axis=(0, 0, 1)), Measure(Qubit(42), axis=(1, 0, 0)), "test"],
-        ids=["qubit", "axis", "type"],
-    )
-    def test_inequality(self, measure: Measure, other_measure: Measure | str) -> None:
-        assert measure != other_measure
-
-    def test_get_qubit_operands(self, measure: Measure) -> None:
-        assert measure.get_qubit_operands() == [Qubit(42)]
-
-    @pytest.mark.parametrize(
-        "mapping, expected_output",
-        [({42: 42}, Measure(Qubit(42), axis=(0, 0, 1))), ({42: 0}, Measure(Qubit(0), axis=(0, 0, 1)))],
-    )
-    def test_relabel(self, measure: Measure, mapping: dict[int, int], expected_output: Measure) -> None:
-        measure.relabel(mapping)
-        assert measure == expected_output
-
-
-class TestBlochSphereRotation:
-
-    @pytest.fixture(name="gate")
-    def gate_fixture(self) -> BlochSphereRotation:
-        return BlochSphereRotation(qubit=Qubit(42), axis=(1, 0, 0), angle=math.pi, phase=math.tau)
-
-    def test_identity(self) -> None:
-        expected_result = BlochSphereRotation(qubit=Qubit(42), axis=(1, 0, 0), angle=0, phase=0)
-        assert BlochSphereRotation.identity(Qubit(42)) == expected_result
-
-    @pytest.mark.parametrize(
-        "other_gate",
-        [
-            BlochSphereRotation(qubit=Qubit(42), axis=(1, 0, 0), angle=math.pi, phase=math.tau),
-            BlochSphereRotation(qubit=Qubit(42), axis=(1 + ATOL / 2, 0, 0), angle=math.pi, phase=math.tau),
-            BlochSphereRotation(qubit=Qubit(42), axis=(1, 0, 0), angle=math.pi + ATOL / 2, phase=math.tau),
-            BlochSphereRotation(qubit=Qubit(42), axis=(1, 0, 0), angle=math.pi, phase=math.tau + ATOL / 2),
-            BlochSphereRotation(qubit=Qubit(42), axis=(1, 0, 0), angle=math.pi + math.tau, phase=math.tau),
-        ],
-        ids=["all_equal", "close_axis", "close_angle", "close_phase", "angle+tau"],
-    )
-    def test_equality(self, gate: BlochSphereRotation, other_gate: BlochSphereRotation) -> None:
-        assert gate == other_gate
-
-    @pytest.mark.parametrize(
-        "other_gate",
-        [
-            BlochSphereRotation(qubit=Qubit(43), axis=(1, 0, 0), angle=math.pi, phase=math.tau),
-            BlochSphereRotation(qubit=Qubit(42), axis=(0, 1, 0), angle=math.pi, phase=math.tau),
-            BlochSphereRotation(qubit=Qubit(42), axis=(1, 0, 0), angle=0, phase=math.tau),
-            BlochSphereRotation(qubit=Qubit(42), axis=(1, 0, 0), angle=math.pi, phase=1),
-            "test",
-        ],
-        ids=["qubit", "axis", "angle", "phase", "type"],
-    )
-    def test_inequality(self, gate: BlochSphereRotation, other_gate: BlochSphereRotation | str) -> None:
-        assert gate != other_gate
-
-    def test_get_qubit_operands(self, gate: BlochSphereRotation) -> None:
-        assert gate.get_qubit_operands() == [Qubit(42)]
-
-    def test_is_identity(self, gate: BlochSphereRotation) -> bool:
-        assert BlochSphereRotation.identity(42).is_identity()
-        assert not gate.is_identity()
-
-    @pytest.mark.parametrize(
-        "mapping, expected_output",
-        [
-            ({42: 42}, BlochSphereRotation(qubit=Qubit(42), axis=(1, 0, 0), angle=math.pi, phase=math.tau)),
-            ({42: 0}, BlochSphereRotation(qubit=Qubit(0), axis=(1, 0, 0), angle=math.pi, phase=math.tau)),
-        ],
-    )
-    def test_relabel(self, gate: Measure, mapping: dict[int, int], expected_output: Measure) -> None:
-        gate.relabel(mapping)
-        assert gate == expected_output
-
-
-class TestMatrixGate:
-
-    @pytest.fixture(name="gate")
-    def gate_fixture(self) -> MatrixGate:
-        cnot_matrix = np.array(
-            [
-                [1, 0, 0, 0],
-                [0, 1, 0, 0],
-                [0, 0, 0, 1],
-                [0, 0, 1, 0],
-            ]
-        )
-        cnot_matrix_gate = MatrixGate(cnot_matrix, operands=[Qubit(42), Qubit(100)])
-        return cnot_matrix_gate
-
-    def test_repr(self, gate: MatrixGate):
-        assert (
-            repr(gate)
-            == "MatrixGate(qubits=[Qubit[42], Qubit[100]], matrix=[[1 0 0 0]\n [0 1 0 0]\n [0 0 0 1]\n [0 0 1 0]])"
-        )
-
-    def test_get_qubit_operands(self, gate: MatrixGate) -> None:
-        assert gate.get_qubit_operands() == [Qubit(42), Qubit(100)]
-
-    def test_is_identity(self, gate: MatrixGate) -> None:
-        assert MatrixGate(np.eye(4), operands=[Qubit(42), Qubit(100)]).is_identity()
-        assert not gate.is_identity()
-
-    @pytest.mark.parametrize(
-        "mapping, expected_output",
-        [
-            (
-                {42: 42, 100: 100},
-                MatrixGate(
-                    np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]]), operands=[Qubit(42), Qubit(100)]
-                ),
-            ),
-            (
-                {42: 100, 100: 42},
-                MatrixGate(
-                    np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]]), operands=[Qubit(100), Qubit(42)]
-                ),
-            ),
-        ],
-    )
-    def test_relabel(self, gate: MatrixGate, mapping: dict[int, int], expected_output: MatrixGate) -> None:
-        gate.relabel(mapping)
-        assert gate == expected_output
+from __future__ import annotations
+
+import math
+
+import numpy as np
+import pytest
+from numpy.typing import NDArray
+
+from opensquirrel.common import ATOL
+from opensquirrel.ir import BlochSphereRotation, ControlledGate, MatrixGate, Measure, Qubit
+
+
+class TestIR:
+    def test_cnot_equality(self):
+        matrix = np.array(
+            [
+                [1, 0, 0, 0],
+                [0, 1, 0, 0],
+                [0, 0, 0, 1],
+                [0, 0, 1, 0],
+            ]
+        )
+        cnot_matrix_gate = MatrixGate(matrix, operands=[Qubit(4), Qubit(100)])
+
+        cnot_controlled_gate = ControlledGate(
+            Qubit(4), BlochSphereRotation(qubit=Qubit(100), axis=(1, 0, 0), angle=math.pi, phase=math.pi / 2)
+        )
+
+        assert cnot_controlled_gate == cnot_matrix_gate
+
+    def test_different_qubits_gate(self):
+        matrix = np.array(
+            [
+                [1, 0, 0, 0],
+                [0, 1, 0, 0],
+                [0, 0, 1, 0],
+                [0, 0, 0, 1],
+            ]
+        )
+        large_identity_matrix_gate = MatrixGate(matrix, operands=[Qubit(0), Qubit(2)])
+        small_identity_control_gate = ControlledGate(
+            Qubit(4), BlochSphereRotation(qubit=Qubit(2), axis=(1, 0, 0), angle=0, phase=0)
+        )
+
+        assert large_identity_matrix_gate == small_identity_control_gate
+
+    def test_inverse_gate(self):
+        matrix = np.array(
+            [
+                [1, 0, 0, 0],
+                [0, 0, 0, 1],
+                [0, 0, 1, 0],
+                [0, 1, 0, 0],
+            ]
+        )
+        inverted_matrix_gate = MatrixGate(matrix, operands=[Qubit(0), Qubit(1)])
+
+        inverted_cnot_gate = ControlledGate(
+            Qubit(1), BlochSphereRotation(qubit=Qubit(0), axis=(1, 0, 0), angle=math.pi, phase=math.pi / 2)
+        )
+
+        assert inverted_matrix_gate == inverted_cnot_gate
+
+    def test_global_phase(self):
+        matrix = np.array(
+            [
+                [1j, 0, 0, 0],
+                [0, 0, 0, 1j],
+                [0, 0, 1j, 0],
+                [0, 1j, 0, 0],
+            ]
+        )
+        inverted_matrix_with_phase = MatrixGate(matrix, operands=[Qubit(0), Qubit(1)])
+
+        inverted_cnot_gate = ControlledGate(
+            Qubit(1), BlochSphereRotation(qubit=Qubit(0), axis=(1, 0, 0), angle=math.pi, phase=math.pi / 2)
+        )
+
+        assert inverted_matrix_with_phase == inverted_cnot_gate
+
+    def test_cnot_inequality(self):
+        matrix = np.array(
+            [
+                [1, 0, 0, 0],
+                [0, 0, 1, 0],
+                [0, 1, 0, 0],
+                [0, 0, 0, 1],
+            ]
+        )
+        swap_matrix_gate = MatrixGate(matrix, operands=[Qubit(4), Qubit(100)])
+
+        cnot_controlled_gate = ControlledGate(
+            Qubit(4), BlochSphereRotation(qubit=Qubit(100), axis=(1, 0, 0), angle=math.pi, phase=math.pi / 2)
+        )
+
+        assert cnot_controlled_gate != swap_matrix_gate
+
+
+class TestMeasure:
+
+    @pytest.fixture(name="measure")
+    def measure_fixture(self) -> Measure:
+        return Measure(Qubit(42), axis=(0, 0, 1))
+
+    def test_repr(self, measure: Measure) -> None:
+        expected_repr = "Measure(Qubit[42], axis=[0. 0. 1.])"
+        assert repr(measure) == expected_repr
+
+    def test_equality(self, measure: Measure) -> None:
+        measure_eq = Measure(Qubit(42), axis=(0, 0, 1))
+        assert measure == measure_eq
+
+    @pytest.mark.parametrize(
+        "other_measure",
+        [Measure(Qubit(43), axis=(0, 0, 1)), Measure(Qubit(42), axis=(1, 0, 0)), "test"],
+        ids=["qubit", "axis", "type"],
+    )
+    def test_inequality(self, measure: Measure, other_measure: Measure | str) -> None:
+        assert measure != other_measure
+
+    def test_get_qubit_operands(self, measure: Measure) -> None:
+        assert measure.get_qubit_operands() == [Qubit(42)]
+
+
+class TestBlochSphereRotation:
+
+    @pytest.fixture(name="gate")
+    def gate_fixture(self) -> BlochSphereRotation:
+        return BlochSphereRotation(qubit=Qubit(42), axis=(1, 0, 0), angle=math.pi, phase=math.tau)
+
+    def test_identity(self) -> None:
+        expected_result = BlochSphereRotation(qubit=Qubit(42), axis=(1, 0, 0), angle=0, phase=0)
+        assert BlochSphereRotation.identity(Qubit(42)) == expected_result
+
+    @pytest.mark.parametrize(
+        "other_gate",
+        [
+            BlochSphereRotation(qubit=Qubit(42), axis=(1, 0, 0), angle=math.pi, phase=math.tau),
+            BlochSphereRotation(qubit=Qubit(42), axis=(1 + ATOL / 2, 0, 0), angle=math.pi, phase=math.tau),
+            BlochSphereRotation(qubit=Qubit(42), axis=(1, 0, 0), angle=math.pi + ATOL / 2, phase=math.tau),
+            BlochSphereRotation(qubit=Qubit(42), axis=(1, 0, 0), angle=math.pi, phase=math.tau + ATOL / 2),
+            BlochSphereRotation(qubit=Qubit(42), axis=(1, 0, 0), angle=math.pi + math.tau, phase=math.tau),
+        ],
+        ids=["all_equal", "close_axis", "close_angle", "close_phase", "angle+tau"],
+    )
+    def test_equality(self, gate: BlochSphereRotation, other_gate: BlochSphereRotation) -> None:
+        assert gate == other_gate
+
+    @pytest.mark.parametrize(
+        "other_gate",
+        [
+            BlochSphereRotation(qubit=Qubit(43), axis=(1, 0, 0), angle=math.pi, phase=math.tau),
+            BlochSphereRotation(qubit=Qubit(42), axis=(0, 1, 0), angle=math.pi, phase=math.tau),
+            BlochSphereRotation(qubit=Qubit(42), axis=(1, 0, 0), angle=0, phase=math.tau),
+            BlochSphereRotation(qubit=Qubit(42), axis=(1, 0, 0), angle=math.pi, phase=1),
+            "test",
+        ],
+        ids=["qubit", "axis", "angle", "phase", "type"],
+    )
+    def test_inequality(self, gate: BlochSphereRotation, other_gate: BlochSphereRotation | str) -> None:
+        assert gate != other_gate
+
+    def test_get_qubit_operands(self, gate: BlochSphereRotation) -> None:
+        assert gate.get_qubit_operands() == [Qubit(42)]
+
+    def test_is_identity(self, gate: BlochSphereRotation) -> bool:
+        assert BlochSphereRotation.identity(42).is_identity()
+        assert not gate.is_identity()
+
+
+class TestMatrixGate:
+    @pytest.fixture(name="gate")
+    def gate_fixture(self) -> MatrixGate:
+        cnot_matrix = np.array(
+            [
+                [1, 0, 0, 0],
+                [0, 1, 0, 0],
+                [0, 0, 0, 1],
+                [0, 0, 1, 0],
+            ]
+        )
+        cnot_matrix_gate = MatrixGate(cnot_matrix, operands=[Qubit(42), Qubit(100)])
+        return cnot_matrix_gate
+
+    def test_repr(self, gate: MatrixGate):
+        assert (
+            repr(gate)
+            == "MatrixGate(qubits=[Qubit[42], Qubit[100]], matrix=[[1 0 0 0]\n [0 1 0 0]\n [0 0 0 1]\n [0 0 1 0]])"
+        )
+
+    def test_get_qubit_operands(self, gate: MatrixGate) -> None:
+        assert gate.get_qubit_operands() == [Qubit(42), Qubit(100)]
+
+    def test_is_identity(self, gate: MatrixGate) -> None:
+        assert MatrixGate(np.eye(4), operands=[Qubit(42), Qubit(100)]).is_identity()
+        assert not gate.is_identity()
diff --git a/test/test_replacer.py b/test/test_replacer.py
index 9a01f2e6..3e0538a7 100644
--- a/test/test_replacer.py
+++ b/test/test_replacer.py
@@ -1,52 +1,54 @@
 import unittest
 
+from opensquirrel.circuit import Circuit
 from opensquirrel.decomposer import general_decomposer
-from opensquirrel.decomposer.general_decomposer import Decomposer, check_valid_replacement
+from opensquirrel.decomposer.general_decomposer import Decomposer, check_gate_replacement
 from opensquirrel.default_gates import *
-from opensquirrel.squirrel_ir import Comment, Qubit, SquirrelIR
+from opensquirrel.ir import IR, Comment, Qubit
+from opensquirrel.register_manager import RegisterManager
 
 
 class ReplacerTest(unittest.TestCase):
     @staticmethod
     def test_check_valid_replacement():
-        check_valid_replacement(BlochSphereRotation.identity(Qubit(0)), [BlochSphereRotation.identity(Qubit(0))])
+        check_gate_replacement(BlochSphereRotation.identity(Qubit(0)), [BlochSphereRotation.identity(Qubit(0))])
 
-        check_valid_replacement(
+        check_gate_replacement(
             BlochSphereRotation.identity(Qubit(0)),
             [BlochSphereRotation.identity(Qubit(0)), BlochSphereRotation.identity(Qubit(0))],
         )
 
-        check_valid_replacement(BlochSphereRotation.identity(Qubit(0)), [H(Qubit(0)), H(Qubit(0))])
+        check_gate_replacement(BlochSphereRotation.identity(Qubit(0)), [H(Qubit(0)), H(Qubit(0))])
 
-        check_valid_replacement(H(Qubit(0)), [H(Qubit(0)), H(Qubit(0)), H(Qubit(0))])
+        check_gate_replacement(H(Qubit(0)), [H(Qubit(0)), H(Qubit(0)), H(Qubit(0))])
 
-        check_valid_replacement(
+        check_gate_replacement(
             CNOT(Qubit(0), Qubit(1)), [CNOT(Qubit(0), Qubit(1)), BlochSphereRotation.identity(Qubit(0))]
         )
 
         # Arbitrary global phase change is not considered an issue.
-        check_valid_replacement(
+        check_gate_replacement(
             CNOT(Qubit(0), Qubit(1)),
             [CNOT(Qubit(0), Qubit(1)), BlochSphereRotation(Qubit(0), angle=0, axis=(1, 0, 0), phase=621.6546)],
         )
 
     def test_check_valid_replacement_wrong_qubit(self):
         with self.assertRaisesRegex(Exception, r"Replacement for gate H does not seem to operate on the right qubits"):
-            check_valid_replacement(H(Qubit(0)), [H(Qubit(1))])
+            check_gate_replacement(H(Qubit(0)), [H(Qubit(1))])
 
         with self.assertRaisesRegex(
             Exception, r"Replacement for gate CNOT does not seem to operate on the right qubits"
         ):
-            check_valid_replacement(CNOT(Qubit(0), Qubit(1)), [CNOT(Qubit(2), Qubit(1))])
+            check_gate_replacement(CNOT(Qubit(0), Qubit(1)), [CNOT(Qubit(2), Qubit(1))])
 
         with self.assertRaisesRegex(Exception, r"Replacement for gate CNOT does not preserve the quantum state"):
-            check_valid_replacement(CNOT(Qubit(0), Qubit(1)), [CNOT(Qubit(1), Qubit(0))])
+            check_gate_replacement(CNOT(Qubit(0), Qubit(1)), [CNOT(Qubit(1), Qubit(0))])
 
     def test_check_valid_replacement_cnot_as_sqrt_swap(self):
         # https://en.wikipedia.org/wiki/Quantum_logic_gate#/media/File:Qcircuit_CNOTsqrtSWAP2.svg
         c = Qubit(0)
         t = Qubit(1)
-        check_valid_replacement(
+        check_gate_replacement(
             CNOT(control=c, target=t),
             [
                 Ry(t, Float(math.pi / 2)),
@@ -60,7 +62,7 @@ def test_check_valid_replacement_cnot_as_sqrt_swap(self):
         )
 
         with self.assertRaisesRegex(Exception, r"Replacement for gate CNOT does not preserve the quantum state"):
-            check_valid_replacement(
+            check_gate_replacement(
                 CNOT(control=c, target=t),
                 [
                     Ry(t, Float(math.pi / 2)),
@@ -76,7 +78,7 @@ def test_check_valid_replacement_cnot_as_sqrt_swap(self):
         with self.assertRaisesRegex(
             Exception, r"Replacement for gate CNOT does not seem to operate on the right qubits"
         ):
-            check_valid_replacement(
+            check_gate_replacement(
                 CNOT(control=c, target=t),
                 [
                     Ry(t, Float(math.pi / 2)),
@@ -91,54 +93,55 @@ def test_check_valid_replacement_cnot_as_sqrt_swap(self):
 
     def test_check_valid_replacement_large_number_of_qubits(self):
         # If we were building the whole circuit matrix, this would run out of memory.
-        check_valid_replacement(H(Qubit(9234687)), [Y90(Qubit(9234687)), X(Qubit(9234687))])
+        check_gate_replacement(H(Qubit(9234687)), [Y90(Qubit(9234687)), X(Qubit(9234687))])
 
         with self.assertRaisesRegex(Exception, r"Replacement for gate H does not seem to operate on the right qubits"):
-            check_valid_replacement(H(Qubit(9234687)), [Y90(Qubit(698446519)), X(Qubit(9234687))])
+            check_gate_replacement(H(Qubit(9234687)), [Y90(Qubit(698446519)), X(Qubit(9234687))])
 
         with self.assertRaisesRegex(Exception, r"Replacement for gate H does not preserve the quantum state"):
-            check_valid_replacement(H(Qubit(9234687)), [Y90(Qubit(9234687)), X(Qubit(9234687)), X(Qubit(9234687))])
+            check_gate_replacement(H(Qubit(9234687)), [Y90(Qubit(9234687)), X(Qubit(9234687)), X(Qubit(9234687))])
 
     def test_replace_generic(self):
-        squirrel_ir = SquirrelIR(number_of_qubits=3, qubit_register_name="test")
-
-        squirrel_ir.add_gate(H(Qubit(0)))
-        squirrel_ir.add_gate(CNOT(Qubit(0), Qubit(1)))
+        register_manager = RegisterManager(qubit_register_size=3)
+        ir = IR()
+        ir.add_gate(H(Qubit(0)))
+        ir.add_gate(CNOT(Qubit(0), Qubit(1)))
+        circuit = Circuit(register_manager, ir)
 
         # A simple decomposer function that adds identities before and after single-qubit gates.
         class TestDecomposer(Decomposer):
             def decompose(self, g: Gate) -> [Gate]:
                 if isinstance(g, BlochSphereRotation):
                     return [BlochSphereRotation.identity(g.qubit), g, BlochSphereRotation.identity(g.qubit)]
-
                 return [g]
 
-        general_decomposer.decompose(squirrel_ir, decomposer=TestDecomposer())
-
-        expected_ir = SquirrelIR(number_of_qubits=3, qubit_register_name="test")
+        general_decomposer.decompose(ir, decomposer=TestDecomposer())
 
+        expected_ir = IR()
         expected_ir.add_gate(BlochSphereRotation.identity(Qubit(0)))
         expected_ir.add_gate(H(Qubit(0)))
         expected_ir.add_gate(BlochSphereRotation.identity(Qubit(0)))
         expected_ir.add_gate(CNOT(Qubit(0), Qubit(1)))
+        expected_circuit = Circuit(register_manager, expected_ir)
 
-        self.assertEqual(expected_ir, squirrel_ir)
+        self.assertEqual(expected_circuit, circuit)
 
     def test_replace(self):
-        squirrel_ir = SquirrelIR(number_of_qubits=3, qubit_register_name="test")
-
-        squirrel_ir.add_gate(H(Qubit(0)))
-        squirrel_ir.add_comment(Comment("Test comment."))
-
-        general_decomposer.replace(squirrel_ir, H, lambda q: [Y90(q), X(q)])
+        register_manager = RegisterManager(qubit_register_size=3)
+        ir = IR()
+        ir.add_gate(H(Qubit(0)))
+        ir.add_comment(Comment("Test comment."))
+        circuit = Circuit(register_manager, ir)
 
-        expected_ir = SquirrelIR(number_of_qubits=3, qubit_register_name="test")
+        general_decomposer.replace(ir, H, lambda q: [Y90(q), X(q)])
 
+        expected_ir = IR()
         expected_ir.add_gate(Y90(Qubit(0)))
         expected_ir.add_gate(X(Qubit(0)))
         expected_ir.add_comment(Comment("Test comment."))
+        expected_circuit = Circuit(register_manager, expected_ir)
 
-        self.assertEqual(expected_ir, squirrel_ir)
+        self.assertEqual(expected_circuit, circuit)
 
 
 if __name__ == "__main__":
diff --git a/test/test_writer.py b/test/test_writer.py
index d94c758e..736e46c9 100644
--- a/test/test_writer.py
+++ b/test/test_writer.py
@@ -1,53 +1,55 @@
 import unittest
 
+from opensquirrel.circuit import Circuit
 from opensquirrel.default_gates import *
 from opensquirrel.exporter import writer
-from opensquirrel.squirrel_ir import Comment, Float, Qubit, SquirrelIR
+from opensquirrel.ir import IR, Comment, Float, Qubit
+from opensquirrel.register_manager import RegisterManager
 
 
 class WriterTest(unittest.TestCase):
     def test_write(self):
-        squirrel_ir = SquirrelIR(number_of_qubits=3, qubit_register_name="myqubitsregister")
-
-        written = writer.squirrel_ir_to_string(squirrel_ir)
+        register_manager = RegisterManager(qubit_register_size=3)
+        ir = IR()
+        circuit = Circuit(register_manager, ir)
 
         self.assertEqual(
-            written,
+            writer.circuit_to_string(circuit),
             """version 3.0
 
-qubit[3] myqubitsregister
+qubit[3] q
 
 """,
         )
 
-        squirrel_ir.add_gate(H(Qubit(0)))
-        squirrel_ir.add_gate(CR(Qubit(0), Qubit(1), Float(1.234)))
-
-        written = writer.squirrel_ir_to_string(squirrel_ir)
+        ir.add_gate(H(Qubit(0)))
+        ir.add_gate(CR(Qubit(0), Qubit(1), Float(1.234)))
+        circuit = Circuit(register_manager, ir)
 
         self.assertEqual(
-            written,
+            writer.circuit_to_string(circuit),
             """version 3.0
 
-qubit[3] myqubitsregister
+qubit[3] q
 
-H myqubitsregister[0]
-CR(1.234) myqubitsregister[0], myqubitsregister[1]
+H q[0]
+CR(1.234) q[0], q[1]
 """,
         )
 
     def test_anonymous_gate(self):
-        squirrel_ir = SquirrelIR(number_of_qubits=1, qubit_register_name="q")
-
-        squirrel_ir.add_gate(CR(Qubit(0), Qubit(1), Float(1.234)))
-        squirrel_ir.add_gate(BlochSphereRotation(Qubit(0), axis=(1, 1, 1), angle=1.23))
-        squirrel_ir.add_gate(CR(Qubit(0), Qubit(1), Float(1.234)))
+        register_manager = RegisterManager(qubit_register_size=2)
+        ir = IR()
+        ir.add_gate(CR(Qubit(0), Qubit(1), Float(1.234)))
+        ir.add_gate(BlochSphereRotation(Qubit(0), axis=(1, 1, 1), angle=1.23))
+        ir.add_gate(CR(Qubit(0), Qubit(1), Float(1.234)))
+        circuit = Circuit(register_manager, ir)
 
         self.assertEqual(
-            writer.squirrel_ir_to_string(squirrel_ir),
+            writer.circuit_to_string(circuit),
             """version 3.0
 
-qubit[1] q
+qubit[2] q
 
 CR(1.234) q[0], q[1]
 <anonymous-gate>
@@ -56,14 +58,15 @@ def test_anonymous_gate(self):
         )
 
     def test_comment(self):
-        squirrel_ir = SquirrelIR(number_of_qubits=3, qubit_register_name="q")
-
-        squirrel_ir.add_gate(H(Qubit(0)))
-        squirrel_ir.add_comment(Comment("My comment"))
-        squirrel_ir.add_gate(CR(Qubit(0), Qubit(1), Float(1.234)))
+        register_manager = RegisterManager(qubit_register_size=3)
+        ir = IR()
+        ir.add_gate(H(Qubit(0)))
+        ir.add_comment(Comment("My comment"))
+        ir.add_gate(CR(Qubit(0), Qubit(1), Float(1.234)))
+        circuit = Circuit(register_manager, ir)
 
         self.assertEqual(
-            writer.squirrel_ir_to_string(squirrel_ir),
+            writer.circuit_to_string(circuit),
             """version 3.0
 
 qubit[3] q
@@ -77,12 +80,13 @@ def test_comment(self):
         )
 
     def test_cap_significant_digits(self):
-        squirrel_ir = SquirrelIR(number_of_qubits=3, qubit_register_name="q")
-
-        squirrel_ir.add_gate(CR(Qubit(0), Qubit(1), Float(1.6546514861321684321654)))
+        register_manager = RegisterManager(qubit_register_size=3)
+        ir = IR()
+        ir.add_gate(CR(Qubit(0), Qubit(1), Float(1.6546514861321684321654)))
+        circuit = Circuit(register_manager, ir)
 
         self.assertEqual(
-            writer.squirrel_ir_to_string(squirrel_ir),
+            writer.circuit_to_string(circuit),
             """version 3.0
 
 qubit[3] q
diff --git a/test/test_zyz_decomposer.py b/test/test_zyz_decomposer.py
index df11d66c..f9595cd0 100644
--- a/test/test_zyz_decomposer.py
+++ b/test/test_zyz_decomposer.py
@@ -3,7 +3,7 @@
 
 from opensquirrel.decomposer.zyz_decomposer import ZYZDecomposer
 from opensquirrel.default_gates import *
-from opensquirrel.squirrel_ir import Float, Qubit
+from opensquirrel.ir import Float, Qubit
 
 
 class ZYZDecomposerTest(IREqualityTestBase):
diff --git a/test/utils/test_matrix_expander.py b/test/utils/test_matrix_expander.py
index ccee9aa1..280947a3 100644
--- a/test/utils/test_matrix_expander.py
+++ b/test/utils/test_matrix_expander.py
@@ -3,7 +3,7 @@
 
 import numpy as np
 
-from opensquirrel.squirrel_ir import BlochSphereRotation, ControlledGate, MatrixGate, Qubit
+from opensquirrel.ir import BlochSphereRotation, ControlledGate, MatrixGate, Qubit
 from opensquirrel.utils import matrix_expander