1#![warn(missing_docs)]
2
3pub use nargo_ir::*;
4use nargo_types::{Result, Span};
5use rayon::prelude::*;
6use serde::{Deserialize, Serialize};
7use std::{collections::VecDeque, path::Path};
8
9pub mod plugin;
11pub use plugin::*;
12
13#[derive(Debug, Clone, Serialize, Deserialize)]
15pub struct Transformation {
16 pub name: String,
17 pub description: String,
18 pub timestamp: u64,
19 pub affected_span: Option<Span>,
20 pub ir_before: Option<String>,
22 pub ir_after: Option<String>,
24}
25
26pub struct Transformer {
28 logs: VecDeque<Transformation>,
29 pub enable_snapshots: bool,
31 plugin_manager: PluginManager,
33}
34
35impl Default for Transformer {
36 fn default() -> Self {
37 Self::new()
38 }
39}
40
41impl Clone for Transformer {
42 fn clone(&self) -> Self {
43 Self {
44 logs: self.logs.clone(),
45 enable_snapshots: self.enable_snapshots,
46 plugin_manager: PluginManager::new(), }
48 }
49}
50
51impl Transformer {
52 pub fn new() -> Self {
53 Self { logs: VecDeque::new(), enable_snapshots: false, plugin_manager: PluginManager::new() }
54 }
55
56 pub fn log(&mut self, name: &str, description: &str, span: Option<Span>, ir_before: Option<String>, ir_after: Option<String>) {
58 let timestamp = std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH).unwrap_or_default().as_secs();
59
60 self.logs.push_back(Transformation { name: name.into(), description: description.into(), timestamp, affected_span: span, ir_before, ir_after });
61 }
62
63 pub fn get_logs(&self) -> Vec<Transformation> {
65 self.logs.iter().cloned().collect()
66 }
67
68 pub fn clear_logs(&mut self) {
70 self.logs.clear();
71 }
72
73 pub fn export_to_json(&self) -> Result<String> {
75 serde_json::to_string_pretty(&self.get_logs()).map_err(|e| nargo_types::Error::external_error("Transformer".to_string(), format!("Failed to export logs: {}", e), Span::unknown()))
76 }
77
78 pub fn load_plugin<P: Plugin + 'static>(&mut self, plugin: P, config: PluginConfig) -> Result<()> {
80 self.plugin_manager.load_plugin(plugin, config)
81 }
82
83 pub fn load_plugins_from_directory(&mut self, directory: &Path) -> Result<()> {
85 self.plugin_manager.load_plugins_from_directory(directory)
86 }
87
88 pub fn run_plugins(&mut self, ir: &mut IRModule, lifecycle: PluginLifecycle) -> Result<()> {
90 self.plugin_manager.run_plugins(ir, lifecycle)
91 }
92
93 pub fn cleanup_plugins(&mut self) -> Result<()> {
95 self.plugin_manager.cleanup_plugins()
96 }
97
98 pub fn get_plugins_info(&self) -> Vec<(String, PluginConfig)> {
100 self.plugin_manager.get_plugins_info()
101 }
102
103 pub fn set_plugin_enabled(&mut self, plugin_name: &str, enabled: bool) -> Result<()> {
105 self.plugin_manager.set_plugin_enabled(plugin_name, enabled)
106 }
107
108 pub fn apply<T: TransformPass>(&mut self, ir: &mut IRModule, pass: &mut T) -> Result<()> {
110 self.run_plugins(ir, PluginLifecycle::PreTransform)?;
112
113 let name = pass.name();
114 let description = pass.description();
115
116 let ir_before = if self.enable_snapshots { serde_json::to_string(ir).ok() } else { None };
117
118 pass.transform(ir)?;
120
121 self.run_plugins(ir, PluginLifecycle::Transform)?;
123
124 let ir_after = if self.enable_snapshots { serde_json::to_string(ir).ok() } else { None };
125
126 self.log(&name, &description, None, ir_before, ir_after);
128
129 self.run_plugins(ir, PluginLifecycle::PostTransform)?;
131
132 Ok(())
133 }
134
135 pub fn apply_parallel<T: TransformPass + Sync>(&mut self, ir: &mut IRModule, passes: &mut [&mut T]) -> Result<()> {
137 self.run_plugins(ir, PluginLifecycle::PreTransform)?;
139
140 for pass in passes {
142 pass.transform(ir)?;
143 }
144
145 self.run_plugins(ir, PluginLifecycle::Transform)?;
147
148 self.run_plugins(ir, PluginLifecycle::PostTransform)?;
150
151 Ok(())
152 }
153
154 pub fn with_span<T, F>(_span: Span, f: F) -> T
156 where
157 F: FnOnce() -> T,
158 {
159 f()
161 }
162}
163
164pub trait TransformPass {
166 fn name(&self) -> String;
167 fn description(&self) -> String;
168 fn transform(&mut self, ir: &mut IRModule) -> Result<()>;
169}
170
171pub mod passes;
173pub use passes::*;