ryna/
serialization.rs

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        // Reconstruct original context
123        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}