1use std::{cell::RefCell, fs, path::Path};
2
3use crate::{cache::RynaCache, compilation::{CompiledRynaExpr, RynaError, RynaInstruction}, config::{ImportMap, InnerDepGraph, RynaModule}, context::{standard_ctx, RynaContext, NUM_STD_BINOPS, NUM_STD_FNS, NUM_STD_INTS, NUM_STD_INT_IMPL, NUM_STD_MACROS, NUM_STD_NARYOPS, NUM_STD_TYPES, NUM_STD_UNOPS}, execution::ExecutionInfo, functions::Function, interfaces::{Interface, InterfaceImpl}, macros::RynaMacro, operations::Operator, parser::{RynaExpr, Span}, types::TypeTemplate};
4
5use serde::{Serialize, Deserialize};
6use bitcode;
7
8#[derive(Clone, Serialize, Deserialize)]
9pub struct ReducedRynaModule {
10 pub name: String,
11 pub hash: String,
12
13 pub code: Vec<RynaExpr>,
14 pub source: Vec<(String, usize)>,
15 pub imports: ImportMap,
16 pub inner_dependencies: InnerDepGraph,
17
18 pub type_templates: Vec<TypeTemplate>,
19 pub interfaces: Vec<Interface>,
20 pub interface_impls: Vec<InterfaceImpl>,
21
22 pub unary_ops: Vec<Operator>,
23 pub binary_ops: Vec<Operator>,
24 pub nary_ops: Vec<Operator>,
25
26 pub functions: Vec<Function>,
27
28 pub macros: Vec<RynaMacro>,
29
30 pub cache: RynaCache
31}
32
33impl RynaModule {
34 pub fn get_reduced_module(&self) -> ReducedRynaModule {
35 let reduced_types = self.ctx.type_templates[*NUM_STD_TYPES.lock().unwrap().borrow()..].to_vec();
36 let reduced_ints = self.ctx.interfaces[*NUM_STD_INTS.lock().unwrap().borrow()..].to_vec();
37 let reduced_int_impls = self.ctx.interface_impls[*NUM_STD_INT_IMPL.lock().unwrap().borrow()..].to_vec();
38 let reduced_macros = self.ctx.macros[*NUM_STD_MACROS.lock().unwrap().borrow()..].to_vec();
39
40 let func_map = NUM_STD_FNS.lock().unwrap();
41 let unop_map = NUM_STD_UNOPS.lock().unwrap();
42 let binop_map = NUM_STD_BINOPS.lock().unwrap();
43 let naryop_map = NUM_STD_NARYOPS.lock().unwrap();
44
45 let reduced_functions = self.ctx.functions.iter().map(|f| {
46 let mut f_cpy = f.clone();
47
48 if let Some(inner) = func_map.borrow().get(&f_cpy.id) {
49 f_cpy.overloads = f_cpy.overloads[*inner..].to_vec();
50 }
51
52 f_cpy
53 })
54 .collect();
55
56 let reduced_unops = self.ctx.unary_ops.iter().filter_map(|o| {
57 let mut o_cpy = o.clone();
58
59 if let Operator::Unary { id, operations, .. } = &mut o_cpy {
60 if let Some(inner) = unop_map.borrow().get(id) {
61 *operations = operations[*inner..].to_vec();
62 }
63
64 return Some(o_cpy);
65 }
66
67 unreachable!();
68 }).collect();
69
70 let reduced_binops = self.ctx.binary_ops.iter().filter_map(|o| {
71 let mut o_cpy = o.clone();
72
73 if let Operator::Binary { id, operations, .. } = &mut o_cpy {
74 if let Some(inner) = binop_map.borrow().get(id) {
75 *operations = operations[*inner..].to_vec();
76 }
77
78 return Some(o_cpy);
79 }
80
81 unreachable!();
82 }).collect();
83
84 let reduced_naryops = self.ctx.nary_ops.iter().filter_map(|o| {
85 let mut o_cpy = o.clone();
86
87 if let Operator::Nary { id, operations, .. } = &mut o_cpy {
88 if let Some(inner) = naryop_map.borrow().get(id) {
89 *operations = operations[*inner..].to_vec();
90 }
91
92 return Some(o_cpy);
93 }
94
95 unreachable!();
96 }).collect();
97
98 ReducedRynaModule {
99 name: self.name.clone(),
100 hash: self.hash.clone(),
101 code: self.code.clone(),
102 source: self.source.clone(),
103 imports: self.imports.clone(),
104 inner_dependencies: self.inner_dependencies.clone(),
105 type_templates: reduced_types,
106 interfaces: reduced_ints,
107 interface_impls: reduced_int_impls,
108 unary_ops: reduced_unops,
109 binary_ops: reduced_binops,
110 nary_ops: reduced_naryops,
111 functions: reduced_functions,
112 macros: reduced_macros,
113 cache: self.ctx.cache.clone(),
114 }
115 }
116}
117
118impl ReducedRynaModule {
119 pub fn recover_module(mut self) -> RynaModule {
120 let mut std_ctx = standard_ctx();
121
122 std_ctx.cache = self.cache;
124
125 self.type_templates.iter_mut().for_each(|t| {
126 t.parser = Some(|ctx: &RynaContext, c_type, s: &String| {
127 if let Ok((_, o)) = ctx.parse_literal_type(c_type, Span::new(s.as_str()), &RefCell::default()) {
128 return Ok(o);
129 }
130
131 Err(format!("Unable to parse {} from {}", c_type.name, s))
132 });
133 });
134
135 std_ctx.type_templates.append(&mut self.type_templates);
136 std_ctx.interfaces.append(&mut self.interfaces);
137 std_ctx.interface_impls.append(&mut self.interface_impls);
138 std_ctx.macros.append(&mut self.macros);
139
140 for mut f in self.functions {
141 if f.id < std_ctx.functions.len() {
142 std_ctx.functions[f.id].overloads.append(&mut f.overloads);
143
144 } else {
145 std_ctx.functions.push(f);
146 }
147 }
148
149 for mut o in self.unary_ops {
150 if let Operator::Unary { id, operations, .. } = &mut o {
151 if *id < std_ctx.unary_ops.len() {
152 if let Operator::Unary { operations: operations_std, .. } = &mut std_ctx.unary_ops[*id] {
153 operations_std.append(operations);
154 }
155
156 } else {
157 std_ctx.unary_ops.push(o);
158 }
159
160 } else {
161 unreachable!();
162 }
163 }
164
165 for mut o in self.binary_ops {
166 if let Operator::Binary { id, operations, .. } = &mut o {
167 if *id < std_ctx.binary_ops.len() {
168 if let Operator::Binary { operations: operations_std, .. } = &mut std_ctx.binary_ops[*id] {
169 operations_std.append(operations);
170 }
171
172 } else {
173 std_ctx.binary_ops.push(o);
174 }
175
176 } else {
177 unreachable!();
178 }
179 }
180
181 for mut o in self.nary_ops {
182 if let Operator::Nary { id, operations, .. } = &mut o {
183 if *id < std_ctx.nary_ops.len() {
184 if let Operator::Nary { operations: operations_std, .. } = &mut std_ctx.nary_ops[*id] {
185 operations_std.append(operations);
186 }
187
188 } else {
189 std_ctx.nary_ops.push(o);
190 }
191
192 } else {
193 unreachable!();
194 }
195 }
196
197 RynaModule {
198 name: self.name.clone(),
199 hash: self.hash.clone(),
200 ctx: std_ctx,
201 code: self.code,
202 source: self.source,
203 imports: self.imports,
204 inner_dependencies: self.inner_dependencies,
205 }
206 }
207
208 pub fn deserialize(data: &[u8]) -> Self {
209 bitcode::deserialize(data).expect("Unable to deserialize module")
210 }
211
212 pub fn serialize(&self) -> Vec<u8> {
213 bitcode::serialize(self).expect("Unable to serialize module")
214 }
215
216 pub fn from_file(path: &Path) -> Self {
217 let data = fs::read(path).expect("Unable to read serialized module from file");
218 ReducedRynaModule::deserialize(&data)
219 }
220
221 pub fn write_to_file(&self, path: &Path) {
222 fs::write(path, self.serialize()).expect("Unable to write serialized module to file");
223 }
224}
225
226#[derive(Clone, Serialize, Deserialize)]
227pub struct CompiledRynaModule {
228 pub hash: String,
229 num_globals: usize,
230 type_templates: Vec<TypeTemplate>,
231 interface_impls: Vec<InterfaceImpl>,
232 instructions: Vec<CompiledRynaExpr>
233}
234
235impl RynaContext {
236 pub fn get_serializable_module(&self, hash: String, instructions: &[RynaInstruction]) -> CompiledRynaModule {
237 let mut reduced_types = self.type_templates[*NUM_STD_TYPES.lock().unwrap().borrow()..].to_vec();
238
239 reduced_types.iter_mut().for_each(|t| {
240 t.attributes.clear();
241 t.annotations.clear();
242 t.patterns.clear();
243 });
244
245 return CompiledRynaModule {
246 hash,
247 num_globals: self.num_globals,
248 type_templates: reduced_types,
249 interface_impls: self.interface_impls[*NUM_STD_INT_IMPL.lock().unwrap().borrow()..].to_vec(),
250 instructions: instructions.iter().map(|i| i.instruction.clone()).collect()
251 };
252 }
253}
254
255impl CompiledRynaModule {
256 pub fn deserialize(data: &[u8]) -> Self {
257 bitcode::deserialize(data).expect("Unable to deserialize code")
258 }
259
260 pub fn serialize(&self) -> Vec<u8> {
261 bitcode::serialize(self).expect("Unable to serialize code")
262 }
263
264 pub fn from_file(path: &Path) -> Self {
265 let data = fs::read(path).expect("Unable to read serialized code from file");
266 CompiledRynaModule::deserialize(&data)
267 }
268
269 pub fn write_to_file(&self, path: &Path) {
270 fs::write(path, self.serialize()).expect("Unable to write serialized code to file");
271 }
272
273 pub fn execute<const DEBUG: bool>(&mut self, program_input: &[String]) -> Result<ExecutionInfo, RynaError> {
274 let mut ctx = standard_ctx();
275
276 ctx.num_globals = self.num_globals;
277 ctx.type_templates.append(&mut self.type_templates);
278 ctx.interface_impls.append(&mut self.interface_impls);
279
280 ctx.program_input = program_input.to_vec();
281
282 ctx.execute_compiled_code::<DEBUG>(&self.instructions, &[])
283 }
284}