ryna/
compilation.rs

1use std::cell::RefCell;
2use std::collections::HashMap;
3use std::fmt::Debug;
4use std::sync::Arc;
5
6use colored::Colorize;
7use levenshtein::levenshtein;
8use nom::error::{VerboseErrorKind, VerboseError};
9use rustc_hash::FxHashSet;
10use serde::{Serialize, Deserialize};
11use malachite::Integer;
12
13use crate::cache::needs_import;
14use crate::cache::needs_line_import;
15use crate::config::ImportMap;
16use crate::config::Imports;
17use crate::config::RynaModule;
18use crate::context::RynaContext;
19use crate::debug::DebugInfo;
20use crate::debug::DebugInfoBuilder;
21use crate::graph::DirectedGraph;
22use crate::id_mapper::IdMapper;
23use crate::interfaces::ITERABLE_ID;
24use crate::macros::RynaMacro;
25use crate::object::TypeInstance;
26use crate::parser::*;
27use crate::object::RynaArray;
28use crate::types::*;
29use crate::object::Object;
30use crate::functions::*;
31use crate::operations::*;
32use crate::variable_map::VariableMap;
33use crate::ARR_IT_OF;
34use crate::ARR_OF;
35
36/*
37                                                  ╒══════════════════╕
38    ============================================= │  IMPLEMENTATION  │ =============================================
39                                                  ╘══════════════════╛
40*/
41
42/*
43    ╒══════════════════════════════╕
44    │ Compilation error management │
45    ╘══════════════════════════════╛
46*/
47
48#[derive(Debug, Clone)]
49pub struct RynaError {
50    pub err_type: String,
51    pub message: String,
52
53    pub has_location: bool,
54    pub line: usize,
55    pub column: usize,
56    pub module: Arc<String>,
57    pub fragment: String,
58
59    pub suggestions: Vec<String>
60}
61
62impl RynaError {
63    pub fn in_module(mut self, module: Arc<String>) -> Self {
64        self.module = module;
65        self
66    } 
67
68    pub fn syntax_error(message: String, line: usize, column: usize, module: Arc<String>, fragment: String, suggestions: Vec<String>) -> Self {
69        RynaError { err_type: "Syntax error".into(), has_location: true, message, line, column, module, fragment, suggestions }
70    }
71
72    #[cold]
73    pub fn compiler_error(message: String, location: &Location, suggestions: Vec<String>) -> Self {
74        RynaError { 
75            err_type: "Compilation error".into(), 
76            has_location: true,
77            message, 
78            line: location.line, 
79            column: location.column, 
80            module: location.module.clone(),
81            fragment: location.span.clone(), 
82            suggestions 
83        }
84    }
85
86    #[cold]
87    pub fn execution_error(message: String) -> Self {
88        RynaError { 
89            err_type: "Execution error".into(), 
90            has_location: false,
91            message, 
92            line: 0, 
93            column: 0, 
94            module: Arc::default(),
95            fragment: "".into(), 
96            suggestions: vec!()
97        }
98    }
99
100    #[cold]
101    pub fn module_error(message: String) -> Self {
102        RynaError { 
103            err_type: "Module error".into(), 
104            has_location: false,
105            message, 
106            line: 0, 
107            column: 0, 
108            module: Arc::default(),
109            fragment: "".into(), 
110            suggestions: vec!()
111        }
112    }
113
114    #[cold]
115    pub fn emit(&self) -> ! {
116        if self.has_location {
117            let mut frag = self.fragment.as_str();
118            
119            if let Some(pos) = frag.find('\n') {
120                frag = &frag[..pos];
121            }
122    
123            if frag.len() > 50 {
124                frag = &frag[..50];
125            }
126    
127            frag = frag.trim();
128    
129            eprintln!(
130                "\n[{} in module {}, line {}, column {}]\n\n • {}:\n\n\t[...] {} [...]\n\t      {}\n", 
131                self.err_type.red().bold(), 
132                self.module.green(),
133                self.line.to_string().yellow(), self.column.to_string().yellow(), 
134                self.message, frag,
135                "^".repeat(frag.len()).red()
136            );
137
138            if !self.suggestions.is_empty() {
139                eprintln!("[{}]\n", "Suggestions".blue().bold());
140
141                for s in &self.suggestions {
142                    eprintln!(" • {}", s);                    
143                }
144
145                eprintln!();
146            }
147
148        } else {
149            eprintln!(
150                "\n[{}] {}\n", 
151                self.err_type.red().bold(),
152                self.message
153            );
154        }
155        
156        exit_process();
157    }
158}
159
160impl<'a> From<VerboseError<Span<'a>>> for RynaError {
161    fn from(error: VerboseError<Span<'a>>) -> Self {
162        let err = error.errors.last().unwrap();
163
164        let fragment = err.0;
165        let error_msg = match &err.1 {
166            VerboseErrorKind::Context(ctx) => ctx,
167            _ => "Unable to parse"
168        };
169
170        RynaError::syntax_error(
171            error_msg.into(), 
172            fragment.location_line() as usize, fragment.get_column(), Arc::default(),
173            fragment.to_string(), 
174            vec!()
175        )
176    }
177}
178
179impl<'a> From<nom::Err<VerboseError<Span<'a>>>> for RynaError {
180    fn from(error: nom::Err<VerboseError<Span<'a>>>) -> Self {
181        match error {
182            nom::Err::Error(err) |
183            nom::Err::Failure(err) => RynaError::from(err),
184
185            _ => unreachable!()
186        }
187    }
188}
189
190/*
191    ╒═════════════════════════════════╕
192    │ Expression tree transformations │
193    ╘═════════════════════════════════╛
194*/
195
196pub fn exit_process() -> ! {
197    if cfg!(test) {
198        panic!();
199
200    } else {
201        std::process::exit(1);
202    }
203}
204
205pub fn message_and_exit(msg: String) -> ! {
206    if cfg!(test) {
207        panic!("{}", msg);
208
209    } else {
210        RynaError::execution_error(msg).emit();
211    }
212}
213
214#[macro_export]
215macro_rules! ryna_warning {
216    ($pat: expr $( , $more: expr)*) => {
217        println!(
218            "[{}] {}",
219            "Warning".yellow(),
220            format!($pat, $($more,)*)
221        );
222    };
223}
224
225#[macro_export]
226macro_rules! located_ryna_warning {
227    ($l: expr, $pat: expr $( , $more: expr)*) => {
228        use colored::Colorize;
229        
230        let loc = $l;
231
232        println!(
233            "[{} in module {}, line {}, column {}] {}",
234            "Warning".yellow(),
235            loc.module.green(),
236            loc.line.to_string().yellow(), loc.column.to_string().yellow(),
237            format!($pat, $($more,)*)
238        );
239    };
240}
241
242#[macro_export]
243macro_rules! ryna_error {
244    ($pat: expr $( , $more: expr)*) => {
245        {
246            use colored::Colorize;
247            use $crate::compilation::exit_process;
248
249            eprintln!(
250                "[{}] {}",
251                "Error".red(),
252                format!($pat, $($more,)*)
253            );
254    
255            exit_process();
256        }
257    };
258}
259
260impl RynaContext {
261    /*
262        ╒══════════════════════╕
263        │ Function compilation │
264        ╘══════════════════════╛
265    */
266
267    fn infer_lambda_return_type(&mut self, lines: &mut Vec<RynaExpr>) -> Result<Option<Type>, RynaError> {
268        let merge_types = |a: Option<Type>, b: Option<Type>, ctx: &mut RynaContext| -> Option<Type> {
269            if b.is_none() {
270                return a;
271            }
272            
273            match &a {
274                Some(na) => {
275                    if na.bindable_to(b.as_ref().unwrap(), ctx) {
276                        b
277                    
278                    } else if b.as_ref().unwrap().bindable_to(na, ctx) {
279                        return a;
280
281                    } else {
282                        return Some(Type::Or(vec!(na.clone(), b.unwrap())));
283                    }
284                },
285
286                None => b,
287            }
288        };
289
290        let mut res = None;
291
292        for expr in lines {
293            match expr {
294                RynaExpr::While(_, _, b) |
295                RynaExpr::CompiledFor(_, _, _, _, _, b) => res = merge_types(res, self.infer_lambda_return_type(b)?, self),
296
297                RynaExpr::If(_, _, ib, ei, eb) => {
298                    res = merge_types(res, self.infer_lambda_return_type(ib)?, self);
299
300                    for (_, eib) in ei {
301                        res = merge_types(res, self.infer_lambda_return_type(eib)?, self);
302                    }
303
304                    if let Some(eb_inner) = eb {
305                        res = merge_types(res, self.infer_lambda_return_type(eb_inner)?, self);
306                    }
307                },
308
309                RynaExpr::Return(_, expr) => res = merge_types(res, Some(self.infer_type(expr)?), self),
310
311                _ => {}
312            }
313        }
314
315        Ok(res)
316    }
317
318    /*
319        ╒══════════════════╕
320        │ Full compilation │
321        ╘══════════════════╛
322    */
323
324    fn compile_expr_variables(&mut self, expr: &mut RynaExpr, is_dtor: bool, needs_dtor: bool) -> Result<(), RynaError> {
325        match expr {
326            // Compile variable references
327            RynaExpr::NameReference(l, n) if self.var_map.is_var_defined(n) => {
328                let (d, (idx, t)) = self.var_map.get_var(n).unwrap();
329                *expr = RynaExpr::Variable(l.clone(), *idx, n.clone(), t.clone(), d == 0);
330            },
331
332            RynaExpr::NameReference(l, n) => {
333                if n == "destroy" || n == "destroy_or" {
334                    return Err(
335                        RynaError::compiler_error(format!("Function {} cannot be called directly", n.green()), l, vec!())
336                    );
337                }
338
339                let func = self.get_function_id(n.clone()).ok();
340                *expr = RynaExpr::QualifiedName(l.clone(), n.clone(), func);
341            },
342
343            RynaExpr::VariableAssignment(l, n, e) => {
344                let n_cpy = n.clone();
345                
346                if self.var_map.is_var_defined(n) {
347                    self.compile_expr_variables(e, is_dtor, false)?;
348                    
349                    let (d, (idx, t)) = self.var_map.get_var(n).unwrap();
350
351                    *expr = RynaExpr::CompiledVariableAssignment(l.clone(), *idx, n.clone(), t.clone(), e.clone(), d == 0);
352
353                    // Destroy previous value
354                    if t.needs_destructor(&self) {
355                        *expr = RynaExpr::DoBlock(Location::none(), vec!(
356                            self.get_destructor_call(*idx, None, None, None, &n_cpy, &t),
357                            expr.clone(),
358                            RynaExpr::Return(Location::none(), Box::new(RynaExpr::Literal(Location::none(), Object::empty())))
359                        ), Type::Empty);
360                    }
361                
362                } else {
363                    return Err(RynaError::compiler_error(format!("Variable with name {} is not defined", n.green()), l, vec!()));
364                }
365            },
366
367            // Compile variable definitions
368            RynaExpr::VariableDefinition(l, n, t, e) => {
369                if self.var_map.is_var_defined_in_last_ctx(n) {
370                    return Err(RynaError::compiler_error(format!("Variable with name {} is already defined", n.green()), l, vec!()));
371                }
372
373                let idx = self.registers.pop().unwrap();
374
375                self.compile_expr_variables(e, is_dtor, false)?;
376
377                if let Type::InferenceMarker = t {
378                    *t = self.infer_type(e)?;
379                }
380
381                let d = self.var_map.define_var(n.clone(), idx, t.clone());
382
383                *expr = RynaExpr::CompiledVariableDefinition(l.clone(), idx, n.clone(), t.clone(), e.clone(), d == 0);
384            },
385            
386            // Compile operations
387            RynaExpr::UnaryOperation(l, id, t, e) => {
388                self.compile_expr_variables(e, is_dtor, false)?;
389
390                if t.is_empty() {
391                    let arg_type = self.infer_type(e)?;
392
393                    if self.is_unary_op_ambiguous(*id, arg_type.clone()).is_none() {
394                        if let Ok((_, _, _, it_args)) = self.get_first_unary_op(*id, arg_type.clone(), None, true, l) {
395                            if !it_args.is_empty() {
396                                *t = it_args;
397                            }
398                        }
399                    }
400                }
401            }
402
403            RynaExpr::BinaryOperation(l, id, t, a, b) => {
404                self.compile_expr_variables(a, is_dtor, false)?;
405                self.compile_expr_variables(b, is_dtor, false)?;
406
407                let is_func = matches!(b.as_ref(), RynaExpr::FunctionCall(..));
408                let is_name = matches!(b.as_ref(), RynaExpr::QualifiedName(..) | RynaExpr::Variable(.., true));
409                let is_attr = matches!(a.as_ref(), RynaExpr::AttributeAccess(..));
410                                
411                // Attribute assignments
412                if *id == DEFINE_BINOP_ID && is_attr {
413                    if let RynaExpr::AttributeAccess(_, e, att_idx) = a.as_ref() {
414                        *expr = RynaExpr::AttributeAssignment(l.clone(), e.clone(), b.clone(), *att_idx);
415                        
416                        return Ok(());
417                    }
418                }
419
420                // Member function calls
421                if *id == DOT_BINOP_ID && is_func {
422                    if let RynaExpr::FunctionCall(_, f_id, t, args) = b.as_ref() {
423                        // Append first operand to the function's arguments 
424                        let mut new_args = vec!(a.as_ref().clone());
425                        new_args.extend(args.iter().cloned());
426
427                        *expr = RynaExpr::FunctionCall(l.clone(), *f_id, t.clone(), new_args);
428    
429                        // Recompile after transformation
430                        self.compile_expr_variables(expr, is_dtor, false)?;
431                    }
432
433                } else if *id == DOT_BINOP_ID && is_name {
434                    if let RynaExpr::QualifiedName(_, n, _) | RynaExpr::Variable(_, _, n, _, true) = b.as_ref() {
435                        let arg_type = self.infer_type(a)?;
436                        let mut changed = false;
437                        let l_cpy = l.clone();
438                        let n_cpy = n.clone();
439
440                        if let Type::Basic(id) | Type::Template(id, _) = arg_type.deref_type() {
441                            let attrs = &self.type_templates[*id].attributes;
442    
443                            for (i, att) in attrs.iter().enumerate() {
444                                if &att.0 == n {
445                                    *expr = RynaExpr::AttributeAccess(l.clone(), a.clone(), i);
446                                    changed = true;
447                                    break;
448                                }
449                            } 
450                        
451                        } else {
452                            return Err(RynaError::compiler_error(
453                                format!("Type {} has no attributes", arg_type.get_name(self)), 
454                                &l_cpy, vec!()
455                            ));
456                        }
457
458                        if !changed {
459                            return Err(RynaError::compiler_error(
460                                format!("Attribute with name {} was not found in class {}", n_cpy.cyan(), arg_type.deref_type().get_name(self)), 
461                                &l_cpy, vec!()
462                            ));
463                        }                
464                    }
465                    
466                } else if t.is_empty() {
467                    let arg_type_1 = self.infer_type(a)?;
468                    let arg_type_2 = self.infer_type(b)?;
469
470                    if self.is_binary_op_ambiguous(*id, arg_type_1.clone(), arg_type_2.clone()).is_none() {
471                        if let Ok((_, _, _, it_args)) = self.get_first_binary_op(*id, arg_type_1.clone(), arg_type_2.clone(), None, true, l) {
472                            if !it_args.is_empty() {
473                                *t = it_args;
474                            }
475                        }
476                    }
477                }
478            }
479            
480            RynaExpr::NaryOperation(l, id, t, a, b) => {
481                self.compile_expr_variables(a, is_dtor, false)?;
482
483                for i in b.iter_mut() {
484                    self.compile_expr_variables(i, is_dtor, false)?;
485                }
486
487                let is_func = matches!(a.as_ref(), RynaExpr::QualifiedName(_, _, Some(_)));
488
489                if *id == CALL_OP && is_func {
490                    if let RynaExpr::QualifiedName(_, _, Some(id)) = a.as_ref() {                    
491                        *expr = RynaExpr::FunctionCall(l.clone(), *id, t.clone(), b.clone());
492    
493                        // Recompile after transformation
494                        self.compile_expr_variables(expr, is_dtor, false)?;
495                    }
496                
497                } else if t.is_empty() {
498                    let arg_type = self.infer_type(a)?;
499                    let arg_types: Vec<_> = b.iter().map(|a| self.infer_type(a)).collect::<Result<_, _>>()?;
500                    
501                    if self.is_nary_op_ambiguous(*id, arg_type.clone(), arg_types.clone()).is_none() {
502                        if let Ok((_, _, _, it_args)) = self.get_first_nary_op(*id, arg_type.clone(), arg_types, None, true, l) {
503                            if !it_args.is_empty() {
504                                *t = it_args;
505                            }
506                        }
507                    }
508                }
509            }
510
511            RynaExpr::Tuple(_, args) => {
512                if args.len() == 1 {
513                    *expr = args.pop().unwrap();
514                    self.compile_expr_variables(expr, is_dtor, false)?;                    
515                    
516                } else {
517                    for i in args {
518                        self.compile_expr_variables(i, is_dtor, false)?;                    
519                    }
520                }
521            }
522
523            RynaExpr::FunctionCall(l, id, t, args) => {
524                for i in args.iter_mut() {
525                    self.compile_expr_variables(i, is_dtor, false)?;                    
526                }
527
528                if t.is_empty() {
529                    let arg_types: Vec<_> = args.iter().map(|a| self.infer_type(a)).collect::<Result<_, _>>()?;
530
531                    if self.is_function_overload_ambiguous(*id, arg_types.clone()).is_none() {
532                        if let Ok((_, _, _, it_args)) = self.get_first_function_overload(*id, arg_types.clone(), None, true, l) {
533                            if !it_args.is_empty() {
534                                *t = it_args;
535                            }
536                        }
537                    }
538                }
539            }
540
541            // Compile flow control
542            RynaExpr::If(_, h, ib, ei, eb) => {
543                self.compile_expr_variables(h, is_dtor, false)?;
544                self.compile_vars_and_infer_ctx(ib, &vec!(), false, false)?;
545
546                for (ei_h, ei_b) in ei {
547                    self.compile_expr_variables(ei_h, is_dtor, false)?;
548                    self.compile_vars_and_infer_ctx(ei_b, &vec!(), false, false)?;
549                }
550
551                if let Some(eb_inner) = eb {
552                    self.compile_vars_and_infer_ctx(eb_inner, &vec!(), false, false)?;
553                }
554            }
555
556            RynaExpr::While(_, c, b) => {
557                self.compile_expr_variables(c, is_dtor, false)?;
558                self.compile_vars_and_infer_ctx(b, &vec!(), false, false)?;
559            }
560
561            RynaExpr::For(l, i, c, b) => {
562                self.compile_expr_variables(c, is_dtor, false)?;
563
564                let container_type = self.infer_type(c)?;
565
566                if !self.implements_iterable(&container_type) {
567                    return Err(RynaError::compiler_error(
568                        format!("type {} does not implement {} interface", container_type.get_name(self), self.interfaces[ITERABLE_ID].name.green()), 
569                        l, vec!()
570                    ));
571                }
572
573                let (it_ov_id, iterator_type, _, it_args) = self.get_iterator_type(&container_type, l)?;
574                let (next_ov_id, element_type, _, next_args) = self.get_iterator_output_type(&iterator_type, l)?;
575
576                let iterator_idx = *self.registers.last().unwrap();
577                let element_idx = *self.registers.get(self.registers.len() - 2).unwrap();
578
579                let it_mut = iterator_type.clone().to_mut();
580
581                let (consumed_ov_id, _, _, consumed_args) = self.get_first_function_overload(IS_CONSUMED_FUNC_ID, vec!(it_mut.clone()), None, true, l)?;
582
583                self.cache.usages.functions.add_new(ITERATOR_FUNC_ID, vec!(container_type.clone()), it_args.clone());
584                self.cache.usages.functions.add_new(NEXT_FUNC_ID, vec!(it_mut.clone()), next_args.clone());
585                self.cache.usages.functions.add_new(IS_CONSUMED_FUNC_ID, vec!(it_mut.clone()), consumed_args.clone());
586
587                self.cache.overloads.functions.insert((ITERATOR_FUNC_ID, vec!(container_type.clone()), it_args.clone()), it_ov_id);
588                self.cache.overloads.functions.insert((NEXT_FUNC_ID, vec!(it_mut.clone()), next_args.clone()), next_ov_id);            
589                self.cache.overloads.functions.insert((IS_CONSUMED_FUNC_ID, vec!(it_mut.clone()), consumed_args.clone()), consumed_ov_id);
590
591                // Define iterator and container
592                let temp_idx = self.var_map.count_up();
593                self.var_map.define_var(format!("$it_{temp_idx}"), self.registers.pop().unwrap(), iterator_type.clone());    
594
595                // Add container
596                self.compile_vars_and_infer_ctx(b, &vec!((i.clone(), element_type.clone())), false, false)?;
597
598                *expr = RynaExpr::CompiledFor(l.clone(), iterator_idx, element_idx, i.clone(), c.clone(), b.clone());
599            }
600
601            RynaExpr::Return(_, e) => {
602                self.compile_expr_variables(e, is_dtor, false)?;
603                
604                if !is_dtor {
605                    // Get variables that need to be destroyed
606                    let mut vars_dtor = vec!();
607
608                    self.var_map.for_each_until_base(|i, n, t| {
609                        if t.needs_destructor(self) {
610                            vars_dtor.push((i, n.clone(), t.clone()));
611                        }
612                    });
613
614                    // Add destructors if needed
615                    if vars_dtor.len() > 0 {
616                        // Define temporary variable
617                        let ret = self.infer_type(e).unwrap();
618
619                        let idx = self.registers.pop().unwrap();
620                        let var_name = format!("$temp_{idx}");
621                        let d = self.var_map.define_var(var_name.clone(), idx, ret.clone());    
622
623                        // Add variable definition
624                        let mut exprs = vec!(
625                            RynaExpr::CompiledVariableDefinition(Location::none(), idx, var_name.clone(), ret.clone(), e.clone(), d == 0)
626                        );
627
628                        // Add destructors
629                        for (i, n, t) in vars_dtor {
630                            exprs.push(self.get_destructor_call(i, None, None, None, &n, &t));
631                        }
632
633                        // Add return
634                        if ret.is_ref() {
635                            exprs.push(
636                                RynaExpr::Return(
637                                    Location::none(),
638                                    Box::new(RynaExpr::Variable(Location::none(), idx, var_name, ret.clone(), d == 0))
639                                )
640                            );
641                        
642                        } else {
643                            let move_idx = self.get_function_id("move".into()).unwrap();
644
645                            exprs.push(
646                                RynaExpr::Return(
647                                    Location::none(),
648                                    Box::new(RynaExpr::FunctionCall(Location::none(), move_idx, vec!(ret.clone()), vec!(
649                                        RynaExpr::Variable(Location::none(), idx, var_name, ret.clone(), d == 0)
650                                    )))
651                                )
652                            );
653                        }
654
655                        *expr = RynaExpr::Return(
656                            Location::none(),
657                            Box::new(RynaExpr::DoBlock(Location::none(), exprs, ret))
658                        );
659                    }
660                }
661            }
662
663            RynaExpr::DoBlock(_, b, r) => {
664                self.compile_vars_and_infer_ctx(b, &vec!(), true, false)?;
665
666                // Infer further
667                if *r == Type::InferenceMarker {
668                    *r = self.infer_lambda_return_type(b)?.unwrap_or(Type::Empty);
669                }
670            }
671
672            RynaExpr::Lambda(l, c, a, r, b) => {
673                let mut captures = vec!();
674                let mut capture_args = vec!();
675
676                // Compile lambda captures
677                for n in c {
678                    if self.var_map.is_var_defined(n) {
679                        let (_, (idx, t)) = self.var_map.get_var(n).unwrap();
680                        captures.push((n.clone(), RynaExpr::Variable(l.clone(), *idx, n.clone(), t.clone(), false)));
681                        capture_args.push((n.clone(), t.clone()));
682                    
683                    } else {
684                        return Err(RynaError::compiler_error(format!("Variable with name {} is not defined", n.green()), l, vec!()));
685                    }
686                }
687
688                self.compile_isolated(b, &capture_args.iter().chain(a.iter()).cloned().collect(), false)?;
689
690                // Infer further
691                if *r == Type::InferenceMarker {
692                    *r = self.infer_lambda_return_type(b)?.unwrap_or(Type::Empty);
693                }
694
695                *expr = RynaExpr::CompiledLambda(l.clone(), self.lambdas, captures, a.clone(), r.clone(), b.clone());
696                self.lambdas += 1;
697            },
698
699            RynaExpr::FunctionDefinition(l, _, idx, tm, a, r, b) => {
700                if tm.is_empty() {
701                    self.compile(b, a, self.is_dtor_id(*idx))?;
702                }
703                    
704                if let Type::Empty = r {
705                    if RynaContext::ensured_return_check_body(b, l, "Function").is_err() {
706                        b.push(RynaExpr::Return(l.clone(), Box::new(RynaExpr::Literal(l.clone(), Object::empty()))));
707                    }
708                }
709            },
710
711            RynaExpr::PrefixOperationDefinition(l, _, _, tm, n, t, r, b) => {
712                if tm.is_empty() {
713                    self.compile(b, &vec!((n.clone(), t.clone())), false)?;
714                }
715                
716                if let Type::Empty = r {
717                    if RynaContext::ensured_return_check_body(b, l, "Operation").is_err() {
718                        b.push(RynaExpr::Return(l.clone(), Box::new(RynaExpr::Literal(l.clone(), Object::empty()))));
719                    }
720                }
721            },
722
723            RynaExpr::PostfixOperationDefinition(l, _, _, tm, n, t, r, b) => {
724                if tm.is_empty() {
725                    self.compile(b, &vec!((n.clone(), t.clone())), false)?;
726                }
727
728                if let Type::Empty = r {
729                    if RynaContext::ensured_return_check_body(b, l, "Operation").is_err() {
730                        b.push(RynaExpr::Return(l.clone(), Box::new(RynaExpr::Literal(l.clone(), Object::empty()))));
731                    }
732                }
733            },
734
735            RynaExpr::BinaryOperationDefinition(l, _, _, tm, a1, a2, r, b) => {
736                if tm.is_empty() {
737                    self.compile(b, &vec!(a1.clone(), a2.clone()), false)?;
738                }
739
740                if let Type::Empty = r {
741                    if RynaContext::ensured_return_check_body(b, l, "Operation").is_err() {
742                        b.push(RynaExpr::Return(l.clone(), Box::new(RynaExpr::Literal(l.clone(), Object::empty()))));
743                    }
744                }
745            },
746
747            RynaExpr::NaryOperationDefinition(l, _, _, tm, a, args, r, b) => {
748                let mut all_args = vec!(a.clone());
749                all_args.extend(args.iter().cloned());
750
751                if tm.is_empty() {
752                    self.compile(b, &all_args, false)?;
753                }
754
755                if let Type::Empty = r {
756                    if RynaContext::ensured_return_check_body(b, l, "Operation").is_err() {
757                        b.push(RynaExpr::Return(l.clone(), Box::new(RynaExpr::Literal(l.clone(), Object::empty()))));
758                    }
759                }
760            }
761
762            _ => {}
763        }
764
765        // Add destructors to expressions if needed. Variables do not get destroyed
766        if needs_dtor && expr.is_expr() && self.expr_needs_dtor(expr) {
767            let t = self.infer_type(expr)?;
768
769            if t.needs_destructor(self) {
770                let dtor_expr;
771
772                if t.is_ref() {
773                    dtor_expr = expr.clone();
774
775                } else {
776                    let ref_idx = self.get_function_id("ref".into()).unwrap();
777
778                    dtor_expr = RynaExpr::FunctionCall(Location::none(), ref_idx, vec!(t.clone()), vec!(expr.clone()));
779                }
780
781                *expr = self.get_destructor_call(0, Some(dtor_expr), None, None, &"".into(), &t);
782            }
783        }
784
785        Ok(())
786    }
787
788    fn get_destructor_id(&self, t: &Type) -> usize {
789        if matches!(t.deref_type(), Type::Or(..)) {
790            self.get_function_id("destroy_or".into()).unwrap()
791
792        } else {
793            self.get_function_id("destroy".into()).unwrap()
794        }
795    }
796
797    fn get_destructor_template_args(&self, t: Type) -> Vec<Type> {
798        let destroy_idx = self.get_destructor_id(&t);
799
800        match self.get_first_function_overload(destroy_idx, vec!(t), None, true, &Location::none()) {
801            Ok((_, _, _, t)) => t,
802            Err(_) => vec!(),
803        }
804    }
805
806    fn add_destructor_usage(&self, t: Type) {
807        let destroy_idx = self.get_destructor_id(&t);
808        let t_args = self.get_destructor_template_args(t.clone());
809        self.cache.usages.functions.add_new(destroy_idx, vec!(t), t_args);
810    }
811
812    fn get_destructor_call(&self, id: usize, expr: Option<RynaExpr>, attr_id: Option<usize>, index: Option<RynaExpr>, name: &String, t: &Type) -> RynaExpr {
813        let mut destroy_idx = self.get_function_id("destroy".into()).unwrap();
814        let deref_idx = self.get_function_id("deref".into()).unwrap();
815        let demut_idx = self.get_function_id("demut".into()).unwrap();
816
817        let mut var_t = t.clone();
818        let mut var = RynaExpr::Variable(Location::none(), id, name.clone(), t.clone(), false);
819
820        if let Some(inner_expr) = &expr {
821            var = inner_expr.clone();
822            var_t = self.infer_type(&var).unwrap();            
823        }
824        
825        // Deref double references
826        while var_t.is_ref() && var_t.deref_type().is_ref() {
827            var_t = var_t.deref_type().clone();
828            var = RynaExpr::FunctionCall(Location::none(), deref_idx, vec!(var_t.clone()), vec!(var));
829        }
830
831        if let Some(attr) = attr_id {
832            var = RynaExpr::AttributeAccess(Location::none(), Box::new(var), attr);
833            var_t = self.infer_type(&var).unwrap();
834        }
835
836        if let Some(idx) = index {
837            if let Type::Template(_, tm) = var_t.deref_type() {
838                var = RynaExpr::NaryOperation(Location::none(), IDX_NARYOP_ID, tm.clone(), Box::new(var), vec!(idx));
839                var_t = self.infer_type(&var).unwrap();    
840            }
841        }
842
843        if matches!(var_t.deref_type(), Type::Or(..)) {
844            destroy_idx = self.get_function_id("destroy_or".into()).unwrap()
845        }
846
847        match &var_t {
848            Type::MutRef(inner) => { 
849                let t_args = self.get_destructor_template_args(inner.clone().to_ref());
850                self.add_destructor_usage(inner.clone().to_ref());
851                
852                // Add destructor dependencies
853                for t in inner.destructor_dependencies(self) {
854                    self.add_destructor_usage(t.clone().to_ref());
855                }
856
857                RynaExpr::FunctionCall(Location::none(), destroy_idx, t_args, vec!(
858                    RynaExpr::FunctionCall(Location::none(), demut_idx, vec!(*inner.clone()), vec!(var))
859                ))
860            }
861
862            Type::Ref(inner) => { 
863                let t_args = self.get_destructor_template_args(var_t.clone());
864                self.add_destructor_usage(var_t.clone());
865
866                // Add destructor dependencies
867                for t in inner.destructor_dependencies(self) {
868                    self.add_destructor_usage(t.clone().to_ref());
869                }
870
871                RynaExpr::FunctionCall(Location::none(), destroy_idx, t_args, vec!(var))
872            }
873
874            // This will never happen when expr is Some(...)
875            _ => {                
876                let t_args = self.get_destructor_template_args(var_t.clone().to_ref());
877                self.add_destructor_usage(var_t.clone().to_ref());
878
879                // Add destructor dependencies
880                for t in var_t.destructor_dependencies(self) {
881                    self.add_destructor_usage(t.clone().to_ref());
882                }
883
884                RynaExpr::FunctionCall(Location::none(), destroy_idx, t_args, vec!(
885                    RynaExpr::FunctionCall(Location::none(), demut_idx, vec!(t.clone()), vec!(var))    
886                ))
887            }
888        }
889    }
890
891    fn expr_needs_dtor(&self, expr: &RynaExpr) -> bool {
892        let ref_idx = self.get_function_id("ref".into()).unwrap();
893        let mut_idx = self.get_function_id("mut".into()).unwrap();
894        let deref_idx = self.get_function_id("deref".into()).unwrap();
895        let demut_idx = self.get_function_id("demut".into()).unwrap();
896        let fwd_idx = self.get_function_id("fwd".into()).unwrap();
897        let cfwd_idx = self.get_function_id("cfwd".into()).unwrap();
898        let move_idx = self.get_function_id("move".into()).unwrap();
899
900        match expr {
901            RynaExpr::FunctionCall(_, id, _, a) if *id == deref_idx => {
902                let t = self.infer_type(&a[0]).unwrap();
903
904                // If you are cloning the value
905                if !t.deref_type().is_ref() {
906                    return true;
907                }
908
909                self.expr_needs_dtor(&a[0])
910            },
911
912            RynaExpr::FunctionCall(_, id, t, a) if *id == fwd_idx || *id == cfwd_idx || *id == move_idx => {
913                // If you are cloning the value (i.e. forwarding to a non-reference)
914                if !t[0].is_ref() {
915                    return true;
916                }
917
918                self.expr_needs_dtor(&a[0])
919            }
920
921            RynaExpr::FunctionCall(_, id, _, a) if *id == ref_idx || *id == mut_idx || *id == demut_idx => {
922                self.expr_needs_dtor(&a[0])
923            },
924
925            RynaExpr::Variable(..) => false,
926
927            _ => true
928        }
929    }
930
931    fn get_destructor_variable(&self, expr: &RynaExpr) -> Option<usize> {
932        let deref_idx = self.get_function_id("deref".into()).unwrap();
933        let demut_idx = self.get_function_id("demut".into()).unwrap();
934
935        match expr {
936            RynaExpr::Variable(_, id, _, _, _) => Some(*id),
937            RynaExpr::FunctionCall(_, id, _, a) if *id == deref_idx || *id == demut_idx => {
938                self.get_destructor_variable(&a[0])
939            },
940
941            _ => None
942        }
943    }
944    
945    fn compile_vars_and_infer_ctx(&mut self, body: &mut Vec<RynaExpr>, args: &Vec<(String, Type)>, is_base: bool, is_dtor: bool) -> Result<usize, RynaError> {
946        self.var_map.add_context(is_base);
947
948        for (n, t) in args {
949            let idx = self.registers.pop().unwrap();
950            self.var_map.define_var(n.clone(), idx, t.clone());
951        }
952
953        // Compile each expression sequentially
954        for e in body.iter_mut() {
955            self.compile_expr_variables(e, is_dtor, true)?;
956        }
957
958        // Add destructors
959        if !is_dtor {
960            match body.last() {
961                None |
962                Some(RynaExpr::Return(..)) => { } // Do not modify return statements, those are handled differently
963    
964                Some(_) => {
965                    self.var_map.for_each_last_ctx(|i, n, t| {
966                        if t.needs_destructor(self) {
967                            body.push(self.get_destructor_call(i, None, None, None, n, t));
968                        }             
969                    });
970                }
971            }
972        }
973
974        let mut max_var = 0;
975
976        // Free the registers inside the context
977        if self.var_map.depth() > 1 {
978            let mut freed_vars = vec!();
979    
980            self.var_map.for_each_last_ctx(|i, _, _| {
981                freed_vars.push(i);
982                max_var = max_var.max(i + 1); // Maximum register
983            });
984    
985            self.registers.append(&mut freed_vars);
986            self.var_map.remove_context();
987        }
988
989        Ok(max_var)
990    }
991
992    pub fn transform_term(&mut self, expr: &mut RynaExpr) -> Result<(), RynaError> {
993        match expr {
994            RynaExpr::QualifiedName(l, _, Some(id)) => {
995                let func = &self.functions[*id];
996
997                if func.overloads.len() > 1 {
998                    return Err(RynaError::compiler_error(
999                        format!(
1000                            "Implicit lambda for function with name {} is ambiguous (found {} overloads)",
1001                            func.name.green(),
1002                            func.overloads.len()
1003                        ), 
1004                        l, vec!()
1005                    ));
1006                }
1007
1008                if func.overloads[0].templates != 0 {
1009                    return Err(RynaError::compiler_error(
1010                        format!(
1011                            "Implicit lambda for function with name {} cannot be formed from generic overload",
1012                            func.name.green()
1013                        ), 
1014                        l, vec!()
1015                    ));
1016                }
1017
1018                let ov = &func.overloads[0];
1019                let mut args = vec!();
1020
1021                if let Type::And(a) = &ov.args {
1022                    if a.len() == 1 {
1023                        args.push(a[0].clone());
1024
1025                    } else {
1026                        args.extend(a.iter().cloned());
1027                    }
1028
1029                } else {
1030                    args.push(ov.args.clone());
1031                }
1032
1033                let move_id = self.get_function_id("move".into()).unwrap();
1034
1035                // Generate implicit function call
1036                let fn_call = RynaExpr::FunctionCall(
1037                    Location::none(), *id, vec!(), 
1038                    args.iter().enumerate()
1039                        .map(|(i, t)| {
1040                            let v = RynaExpr::Variable(Location::none(), i, format!("arg_{i}"), t.clone(), false);
1041
1042                            // Move if it is a direct value
1043                            if t.is_ref() {
1044                                v
1045                            
1046                            } else {
1047                                RynaExpr::FunctionCall(
1048                                    Location::none(), move_id, vec!(t.clone()), vec!(v) 
1049                                )
1050                            }
1051                        })
1052                        .collect()
1053                );
1054
1055                // Generate implicit lambda
1056                *expr = RynaExpr::CompiledLambda(
1057                    l.clone(), self.lambdas, vec!(), 
1058                    args.into_iter().enumerate().map(|(i, t)| (format!("arg_{i}"), t)).collect(), 
1059                    ov.ret.clone(), 
1060                    vec!(RynaExpr::Return(Location::none(), Box::new(fn_call)))
1061                );
1062
1063                self.lambdas += 1;
1064
1065                Ok(())
1066            } 
1067
1068            RynaExpr::QualifiedName(l, n, func) => {
1069                if func.is_none() {
1070                    let similar_func = self.functions.iter().map(|f| &f.name)
1071                                                     .filter(|name| levenshtein(n, name) < 3)
1072                                                     .map(|i| format!("{} (Function)", i.green()))
1073                                                     .collect::<Vec<_>>();
1074
1075                    return Err(RynaError::compiler_error(
1076                        format!("Identifier with name {} is not defined", n), l, 
1077                        similar_func.iter().map(|i| format!("Similar: {}", i)).collect()
1078                    ));
1079                }
1080
1081                Ok(())
1082            }
1083
1084            RynaExpr::AttributeAccess(_, e, _) |
1085            RynaExpr::UnaryOperation(_, _, _, e) |
1086            RynaExpr::Return(_, e) |
1087            RynaExpr::CompiledVariableDefinition(_, _, _, _, e, _) |
1088            RynaExpr::CompiledVariableAssignment(_, _, _, _, e, _) => self.transform_term(e),
1089
1090            RynaExpr::CompiledLambda(_, _, c, _, _, _) => {
1091                for (_, e) in c {
1092                    self.transform_term(e)?;
1093                }
1094
1095                Ok(())
1096            }
1097
1098            RynaExpr::DoBlock(_, exprs, _) |
1099            RynaExpr::FunctionCall(_, _, _, exprs) |
1100            RynaExpr::Tuple(_, exprs) => {
1101                for e in exprs {
1102                    self.transform_term(e)?;
1103                }
1104
1105                Ok(())
1106            },
1107
1108            RynaExpr::CompiledFor(_, _, _, _, c, exprs) |
1109            RynaExpr::While(_, c, exprs) => {
1110                self.transform_term(c)?;
1111
1112                for e in exprs {
1113                    self.transform_term(e)?;
1114                }
1115
1116                Ok(())
1117            },
1118
1119            RynaExpr::NaryOperation(_, _, _, c, exprs) => {
1120                self.transform_term(c)?;
1121
1122                for e in exprs {
1123                    self.transform_term(e)?;
1124                }
1125
1126                Ok(())
1127            },
1128
1129            RynaExpr::AttributeAssignment(_, a, b, _) |
1130            RynaExpr::BinaryOperation(_, _, _, a, b) => {
1131                self.transform_term(a)?;
1132                self.transform_term(b)?;
1133
1134                Ok(())
1135            },
1136
1137            RynaExpr::If(_, ic, ib, ei, eb) => {
1138                self.transform_term(ic)?;
1139                
1140                for e in ib {
1141                    self.transform_term(e)?;
1142                }
1143
1144                for (ei_h, ei_b) in ei {
1145                    self.transform_term(ei_h)?;
1146                    
1147                    for e in ei_b {
1148                        self.transform_term(e)?;
1149                    }
1150                }
1151
1152                if let Some(inner) = eb {
1153                    for e in inner {
1154                        self.transform_term(e)?;
1155                    }
1156                }
1157
1158                Ok(())
1159            },
1160            
1161            RynaExpr::Variable(_, _, _, _, _) |
1162            RynaExpr::Break(_) |
1163            RynaExpr::Continue(_) |
1164            RynaExpr::Literal(_, _) |
1165            RynaExpr::Macro(_, _, _, _, _, _) |
1166            RynaExpr::FunctionDefinition(_, _, _, _, _, _, _) |
1167            RynaExpr::PrefixOperatorDefinition(_, _, _) |
1168            RynaExpr::PostfixOperatorDefinition(_, _, _) |
1169            RynaExpr::BinaryOperatorDefinition(_, _, _, _) |
1170            RynaExpr::NaryOperatorDefinition(_, _, _, _) |
1171            RynaExpr::ClassDefinition(_, _, _, _, _, _, _) |
1172            RynaExpr::InterfaceDefinition(_, _, _, _, _, _, _, _) |
1173            RynaExpr::InterfaceImplementation(_, _, _, _, _) |
1174            RynaExpr::PrefixOperationDefinition(_, _, _, _, _, _, _, _) |
1175            RynaExpr::PostfixOperationDefinition(_, _, _, _, _, _, _, _) |
1176            RynaExpr::BinaryOperationDefinition(_, _, _, _, _, _, _, _) |
1177            RynaExpr::NaryOperationDefinition(_, _, _, _, _, _, _, _) => { Ok(()) },
1178
1179            e => unreachable!("{:?}", e)
1180        }
1181    }
1182
1183    pub fn compile_vars_and_infer(&mut self, body: &mut Vec<RynaExpr>, args: &Vec<(String, Type)>, is_dtor: bool) -> Result<usize, RynaError> {
1184        self.compile_vars_and_infer_ctx(body, args, true, is_dtor)
1185    }
1186
1187    pub fn compile(&mut self, body: &mut Vec<RynaExpr>, args: &Vec<(String, Type)>, is_dtor: bool) -> Result<(), RynaError> {
1188        // Backup registers
1189        let registers_cpy = self.registers.clone();
1190        self.reset_registers();
1191
1192        // First pass
1193        self.compile_vars_and_infer(body, args, is_dtor)?;
1194
1195        // Second pass to transform some terms if needed
1196        for expr in body.iter_mut() {
1197            self.transform_term(expr)?;
1198        }
1199
1200        // Recover previous registers
1201        self.registers = registers_cpy;
1202
1203        Ok(())
1204    }
1205
1206    // Compile without access to globals
1207    pub fn compile_isolated(&mut self, body: &mut Vec<RynaExpr>, args: &Vec<(String, Type)>, is_dtor: bool) -> Result<(), RynaError> {
1208        // Backup globals
1209        let var_map_cpy = self.var_map.clone();
1210
1211        // Create a variable map with an empty global context
1212        self.var_map = VariableMap::new();
1213        self.var_map.add_context(true);
1214
1215        // Compile normally
1216        self.compile(body, args, is_dtor)?;
1217
1218        // Restore globals
1219        self.var_map = var_map_cpy;
1220
1221        Ok(())
1222    }
1223}
1224
1225/*
1226    ╒══════════════════════╕
1227    │ Compiled Ryna struct │
1228    ╘══════════════════════╛
1229*/
1230
1231#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1232pub enum PlaceholderType {
1233    Break, Continue
1234}
1235
1236#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1237pub enum CompiledRynaExpr {
1238    Empty,
1239    Bool(bool),
1240    Int(Integer),
1241    Float(f64),
1242    Str(String),
1243    Array(usize, Type),
1244    Lambda(usize, usize, Type, Type),
1245
1246    Construct(usize, usize, Vec<Type>),
1247    AttributeAssign(usize),
1248    AttributeMove(usize),
1249    AttributeRef(usize),
1250    AttributeMut(usize),
1251    AttributeCopy(usize),
1252    AttributeDeref(usize),
1253
1254    Tuple(usize),
1255    TupleElemMove(usize),
1256    TupleElemRef(usize),
1257    TupleElemMut(usize),
1258    TupleElemCopy(usize),
1259    TupleElemDeref(usize),
1260
1261    IdxMove, IdxRef, IdxMut, IdxMoveRef,
1262
1263    StoreIntVariable(usize, bool, Integer),
1264    StoreBoolVariable(usize, bool, bool),
1265    StoreFloatVariable(usize, bool, f64),
1266    StoreStringVariable(usize, bool, String),
1267
1268    StoreVariable(usize, bool),
1269    GetVariable(usize, bool),
1270    CloneVariable(usize, bool),
1271    RefVariable(usize, bool),
1272    DerefVariable(usize, bool),
1273    CopyVariable(usize, bool),
1274    MoveVariable(usize, bool),
1275    Assign,
1276    AssignToVar(usize, bool), AssignToVarDirect(usize, bool),
1277    Drop,
1278
1279    Jump(usize),
1280    RelativeJump(i32),
1281    RelativeJumpIfFalse(usize, bool),
1282    RelativeJumpIfTrue(usize, bool),
1283    Call(usize),
1284    CallDestructor(usize),
1285    DeleteVar(usize, bool),
1286    LambdaCall, LambdaCallRef,
1287    Return,
1288
1289    NativeFunctionCall(usize, usize, Vec<Type>),
1290    UnaryOperatorCall(usize, usize, Vec<Type>),
1291    BinaryOperatorCall(usize, usize, Vec<Type>),
1292    NaryOperatorCall(usize, usize, Vec<Type>),
1293
1294    NativeFunctionCallNoRet(usize, usize, Vec<Type>), // No return variants
1295    UnaryOperatorCallNoRet(usize, usize, Vec<Type>),
1296    BinaryOperatorCallNoRet(usize, usize, Vec<Type>),
1297
1298    // Conversions
1299    Ref, Mut, Copy, Deref, Demut, Move, ToFloat,
1300
1301    // Arithmetic opcodes
1302    Inc, Dec,
1303    Addi, Addf,
1304    Subi, Subf,
1305    Muli, Mulf,
1306    Divi, Divf,
1307    Modi, Modf,
1308    Negi, Negf,
1309
1310    AddStr,
1311
1312    // Bitwise opcodes
1313    NotB, AndB, OrB, XorB, Shr, Shl,
1314
1315    // Comparison opcodes
1316    Lti, Ltf,
1317    Gti, Gtf,
1318    Lteqi, Lteqf,
1319    Gteqi, Gteqf,
1320    Eqi, Eqf,
1321    Neqi, Neqf,
1322    EqBool, NeqBool,
1323    EqStr, NeqStr,
1324
1325    // Logical opcodes
1326    Not, Or, And, Xor,
1327    
1328    Nand, Nor, // Only via peephole optimization
1329
1330    Placeholder(PlaceholderType),
1331
1332    Halt
1333}
1334
1335impl CompiledRynaExpr {
1336    pub fn needs_float(&self) -> bool {
1337        use CompiledRynaExpr::*;
1338
1339        matches!(
1340            self,
1341            Addf | Subf | Mulf | Divf | Modf |
1342            Ltf | Gtf | Lteqf | Gteqf | Eqf | Neqf |
1343            Negf
1344        )
1345    }
1346
1347    pub fn needs_deref(&self) -> bool {
1348        use CompiledRynaExpr::*;
1349
1350        matches!(
1351            self, 
1352            Addf | Subf | Mulf | Divf | Modf |
1353            Ltf | Gtf | Lteqf | Gteqf | Eqf | Neqf | Negf |
1354            Addi | Subi | Muli | Divi | Modi |
1355            Lti | Gti | Lteqi | Gteqi | Eqi | Neqi | Negi |
1356            Not | Or | And | Xor |
1357            NotB | AndB | OrB | XorB | Shr | Shl |
1358            EqStr | NeqStr | EqBool | NeqBool | AddStr
1359        )
1360    }
1361
1362    pub fn needs_no_drop(&self) -> bool {
1363        use CompiledRynaExpr::*;
1364
1365        matches!(
1366            self, 
1367            Assign |
1368            Inc | Dec
1369        )
1370    }
1371
1372    pub fn to_string(&self, ctx: &RynaContext) -> String {
1373        use CompiledRynaExpr::*;
1374
1375        match self {
1376            Bool(obj) => format!("{}({})", "Bool".green(), obj.to_string().blue()),
1377            Int(obj) => format!("{}({})", "Int".green(), obj.to_string().blue()),
1378            Float(obj) => format!("{}({})", "Float".green(), obj.to_string().blue()),
1379            Str(obj) => format!("{}(\"{}\")", "Str".green(), obj.to_string().blue()),
1380
1381            Array(length, t) => format!(
1382                "{}({}, {})", "Array".green(), 
1383                length.to_string().magenta(), 
1384                t.get_name(ctx)
1385            ),
1386
1387            Lambda(pos, cap, args, ret) => format!(
1388                "{}({}, {}, {}, {})", "Lambda".green(), 
1389                pos.to_string().magenta(), 
1390                cap.to_string().magenta(), 
1391                args.get_name(ctx),
1392                ret.get_name(ctx)
1393            ),
1394            
1395            Tuple(to) => format!("{}({})", "Tuple".green(), to.to_string().blue()),
1396
1397            StoreVariable(to, g) => format!("{}({}, {})", "StoreVariable".green(), to.to_string().blue(), g.to_string().blue()),
1398            GetVariable(to, g) => format!("{}({}, {})", "GetVariable".green(), to.to_string().blue(), g.to_string().blue()),
1399            CopyVariable(to, g) => format!("{}({}, {})", "CopyVariable".green(), to.to_string().blue(), g.to_string().blue()),
1400            DerefVariable(to, g) => format!("{}({}, {})", "DerefVariable".green(), to.to_string().blue(), g.to_string().blue()),
1401            MoveVariable(to, g) => format!("{}({}, {})", "MoveVariable".green(), to.to_string().blue(), g.to_string().blue()),
1402
1403            Call(to) => format!("{}({})", "Call".green(), to.to_string().blue()),
1404
1405            Jump(to) => format!("{}({})", "Jump".green(), to.to_string().blue()),
1406            RelativeJump(to) => format!("{}({})", "RelativeJump".green(), to.to_string().blue()),
1407            RelativeJumpIfTrue(to, p) => format!("{}({}, {})", "RelativeJumpIfTrue".green(), to.to_string().blue(), p.to_string().blue()),
1408            RelativeJumpIfFalse(to, p) => format!("{}({}, {})", "RelativeJumpIfFalse".green(), to.to_string().blue(), p.to_string().blue()),
1409
1410            Construct(id, length, args) => format!(
1411                "{}({}, {}, {{{}}})", "Construct".green(), 
1412                ctx.type_templates[*id].name.magenta(), 
1413                length.to_string().magenta(), 
1414                args.iter().map(|i| i.get_name(ctx)).collect::<Vec<_>>().join(", ")
1415            ),
1416
1417            AttributeMove(to) => format!("{}({})", "Attribute".green(), to.to_string().blue()),
1418            AttributeRef(to) => format!("{}({})", "AttributeRef".green(), to.to_string().blue()),
1419            AttributeMut(to) => format!("{}({})", "AttributeMut".green(), to.to_string().blue()),
1420            AttributeCopy(to) => format!("{}({})", "AttributeCopy".green(), to.to_string().blue()),
1421            AttributeDeref(to) => format!("{}({})", "AttributeDeref".green(), to.to_string().blue()),
1422
1423            TupleElemMove(to) => format!("{}({})", "TupleElem".green(), to.to_string().blue()),
1424            TupleElemRef(to) => format!("{}({})", "TupleElemRef".green(), to.to_string().blue()),
1425            TupleElemMut(to) => format!("{}({})", "TupleElemMut".green(), to.to_string().blue()),
1426            TupleElemCopy(to) => format!("{}({})", "TupleElemCopy".green(), to.to_string().blue()),
1427            TupleElemDeref(to) => format!("{}({})", "TupleElemDeref".green(), to.to_string().blue()),
1428
1429            NativeFunctionCall(id, ov, args) => format!(
1430                "{}({}, {}, {{{}}})", "FunctionCall".green(), 
1431                ctx.functions[*id].name.magenta(), 
1432                ov.to_string().blue(), 
1433                args.iter().map(|i| i.get_name(ctx)).collect::<Vec<_>>().join(", ")
1434            ),
1435
1436            NativeFunctionCallNoRet(id, ov, args) => format!(
1437                "{}({}, {}, {{{}}})", "FunctionCallNoRet".green(), 
1438                ctx.functions[*id].name.magenta(), 
1439                ov.to_string().blue(), 
1440                args.iter().map(|i| i.get_name(ctx)).collect::<Vec<_>>().join(", ")
1441            ),
1442
1443            UnaryOperatorCall(id, ov, args) => format!(
1444                "{}({}, {}, {{{}}})", "UnOpCall".green(), 
1445                ctx.unary_ops[*id].get_repr().magenta(), 
1446                ov.to_string().blue(), 
1447                args.iter().map(|i| i.get_name(ctx)).collect::<Vec<_>>().join(", ")
1448            ),
1449
1450            UnaryOperatorCallNoRet(id, ov, args) => format!(
1451                "{}({}, {}, {{{}}})", "UnOpCallNoRet".green(), 
1452                ctx.unary_ops[*id].get_repr().magenta(), 
1453                ov.to_string().blue(), 
1454                args.iter().map(|i| i.get_name(ctx)).collect::<Vec<_>>().join(", ")
1455            ),
1456
1457            BinaryOperatorCall(id, ov, args) => format!(
1458                "{}({}, {}, {{{}}})", "BinOpCall".green(), 
1459                ctx.binary_ops[*id].get_repr().magenta(), 
1460                ov.to_string().blue(), 
1461                args.iter().map(|i| i.get_name(ctx)).collect::<Vec<_>>().join(", ")
1462            ),
1463
1464            BinaryOperatorCallNoRet(id, ov, args) => format!(
1465                "{}({}, {}, {{{}}})", "BinOpCallNoRet".green(), 
1466                ctx.binary_ops[*id].get_repr().magenta(), 
1467                ov.to_string().blue(), 
1468                args.iter().map(|i| i.get_name(ctx)).collect::<Vec<_>>().join(", ")
1469            ),
1470
1471            NaryOperatorCall(id, ov, args) => format!(
1472                "{}({}, {}, {{{}}})", "NaryOpCall".green(), 
1473                ctx.nary_ops[*id].get_repr().magenta(), 
1474                ov.to_string().blue(), 
1475                args.iter().map(|i| i.get_name(ctx)).collect::<Vec<_>>().join(", ")
1476            ),
1477
1478            _ => format!("{:?}", self).green().to_string()
1479        }
1480    }
1481}
1482
1483#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1484pub struct RynaInstruction {
1485    pub instruction: CompiledRynaExpr,
1486    pub debug_info: DebugInfo
1487}
1488
1489impl RynaInstruction {
1490    pub fn to_string(&self, ctx: &RynaContext) -> String {
1491        format!("{:<30}{}{}", self.instruction.to_string(ctx), if self.debug_info.comment.is_empty() { "" } else { " # " }, self.debug_info.comment)
1492    }
1493}
1494
1495impl From<CompiledRynaExpr> for RynaInstruction {
1496    fn from(obj: CompiledRynaExpr) -> RynaInstruction {
1497        RynaInstruction {
1498            instruction: obj,
1499            debug_info: DebugInfo::default()
1500        }
1501    }
1502}
1503
1504impl RynaInstruction {
1505    pub fn new(instruction: CompiledRynaExpr, comment: String) -> RynaInstruction {
1506        RynaInstruction {
1507            instruction,
1508            debug_info: DebugInfoBuilder::default().comment(comment).build().unwrap()
1509        }
1510    }
1511
1512    pub fn new_with_type(instruction: CompiledRynaExpr, comment: String, var_type: Type) -> RynaInstruction {
1513        RynaInstruction {
1514            instruction,
1515            debug_info: DebugInfoBuilder::default().comment(comment).var_type(Some(var_type)).build().unwrap()
1516        }
1517    }
1518
1519    pub fn set_loc(mut self, loc: &Location) -> Self {
1520        self.debug_info.set_line(loc.module.clone(), loc.line);
1521        self
1522    }
1523}
1524
1525impl RynaContext{
1526    pub fn get_inner_dep_graph(&mut self, lines: &[RynaExpr]) -> Result<DirectedGraph<(ImportType, usize), ()>, RynaError> {
1527        let mut res = DirectedGraph::new();
1528        let mut compiled = lines.to_owned();
1529
1530        self.compile(&mut compiled, &vec!(), false)?; // TODO: this seems costly...
1531
1532        for (line_idx, e) in compiled.iter().enumerate() {
1533            self.get_inner_dep_graph_expr(e, &(ImportType::Line(line_idx), 0), &mut res);
1534        }
1535
1536        self.reset_registers();
1537        self.var_map = VariableMap::new();
1538
1539        Ok(res)
1540    }
1541
1542    pub fn get_inner_dep_graph_body(&self, lines: &Vec<RynaExpr>, parent: &(ImportType, usize), deps: &mut DirectedGraph<(ImportType, usize), ()>) {
1543        for line in lines {
1544            self.get_inner_dep_graph_expr(line, parent, deps);
1545        }
1546    }
1547
1548    pub fn get_inner_dep_graph_expr(&self, expr: &RynaExpr, parent: &(ImportType, usize), deps: &mut DirectedGraph<(ImportType, usize), ()>) {
1549        match expr {
1550            RynaExpr::Literal(_, obj) => {
1551                deps.connect(parent.clone(), (ImportType::Class, obj.get_type_id()), ());
1552            }
1553
1554            RynaExpr::Return(_, e) => self.get_inner_dep_graph_expr(e, parent, deps),
1555
1556            RynaExpr::CompiledVariableAssignment(_, _, _, t, e, _) |
1557            RynaExpr::CompiledVariableDefinition(_, _, _, t, e, _) => {
1558                self.get_inner_dep_graph_expr(e, parent, deps);
1559
1560                for td in t.type_dependencies() {
1561                    deps.connect(parent.clone(), (ImportType::Class, td), ());
1562                }
1563
1564                for id in t.interface_dependencies() {
1565                    deps.connect(parent.clone(), (ImportType::Interface, id), ());
1566                }
1567            }
1568
1569            RynaExpr::Tuple(_, b) => {
1570                self.get_inner_dep_graph_body(b, parent, deps);
1571            }
1572
1573            RynaExpr::FunctionCall(_, id, ts, args) => {
1574                deps.connect(parent.clone(), (ImportType::Fn, *id), ());
1575
1576                self.get_inner_dep_graph_body(args, parent, deps);
1577
1578                for t in ts {
1579                    for td in t.type_dependencies() {
1580                        deps.connect(parent.clone(), (ImportType::Class, td), ());
1581                    }
1582
1583                    for id in t.interface_dependencies() {
1584                        deps.connect(parent.clone(), (ImportType::Interface, id), ());
1585                    }
1586                }
1587            }
1588
1589            RynaExpr::UnaryOperation(_, id, ts, a) => {
1590                if let Operator::Unary { id, prefix, .. } = &self.unary_ops[*id] {
1591                    if *prefix {
1592                        deps.connect(parent.clone(), (ImportType::Prefix, *id), ());
1593                    
1594                    } else {
1595                        deps.connect(parent.clone(), (ImportType::Postfix, *id), ());
1596                    }
1597
1598                    self.get_inner_dep_graph_expr(a, parent, deps);
1599
1600                    for t in ts {
1601                        for td in t.type_dependencies() {
1602                            deps.connect(parent.clone(), (ImportType::Class, td), ());
1603                        }
1604
1605                        for id in t.interface_dependencies() {
1606                            deps.connect(parent.clone(), (ImportType::Interface, id), ());
1607                        }
1608                    }
1609                }
1610            }
1611
1612            RynaExpr::BinaryOperation(_, id, ts, a, b) => {
1613                if let Operator::Binary { id, .. } = &self.binary_ops[*id] {
1614                    deps.connect(parent.clone(), (ImportType::Binary, *id), ());
1615
1616                    self.get_inner_dep_graph_expr(a, parent, deps);
1617                    self.get_inner_dep_graph_expr(b, parent, deps);
1618
1619                    for t in ts {
1620                        for td in t.type_dependencies() {
1621                            deps.connect(parent.clone(), (ImportType::Class, td), ());
1622                        }
1623
1624                        for id in t.interface_dependencies() {
1625                            deps.connect(parent.clone(), (ImportType::Interface, id), ());
1626                        }
1627                    }
1628                }
1629            }
1630
1631            RynaExpr::NaryOperation(_, id, ts, a, b) => {
1632                if let Operator::Nary { id, .. } = &self.nary_ops[*id] {
1633                    deps.connect(parent.clone(), (ImportType::Nary, *id), ());
1634
1635                    self.get_inner_dep_graph_expr(a, parent, deps);
1636                    self.get_inner_dep_graph_body(b, parent, deps);
1637
1638                    for t in ts {
1639                        for td in t.type_dependencies() {
1640                            deps.connect(parent.clone(), (ImportType::Class, td), ());
1641                        }
1642
1643                        for id in t.interface_dependencies() {
1644                            deps.connect(parent.clone(), (ImportType::Interface, id), ());
1645                        }
1646                    }
1647                }
1648            }
1649
1650            RynaExpr::DoBlock(_, b, _) => {
1651                self.get_inner_dep_graph_body(b, parent, deps);
1652            }
1653
1654            RynaExpr::While(_, c, b) => {
1655                self.get_inner_dep_graph_expr(c, parent, deps);
1656                self.get_inner_dep_graph_body(b, parent, deps);
1657            }
1658
1659            RynaExpr::CompiledFor(_, _, _, _, c, b) => {
1660                self.get_inner_dep_graph_expr(c, parent, deps);
1661                self.get_inner_dep_graph_body(b, parent, deps);
1662
1663                // Iteration functions, since they are used implicitly
1664                deps.connect(parent.clone(), (ImportType::Interface, ITERABLE_ID), ());
1665                deps.connect(parent.clone(), (ImportType::Fn, ITERATOR_FUNC_ID), ());
1666                deps.connect(parent.clone(), (ImportType::Fn, NEXT_FUNC_ID), ());
1667                deps.connect(parent.clone(), (ImportType::Fn, IS_CONSUMED_FUNC_ID), ());
1668            }
1669
1670            RynaExpr::If(_, ic, ib, ie, eb) => {
1671                self.get_inner_dep_graph_expr(ic, parent, deps);
1672                self.get_inner_dep_graph_body(ib, parent, deps);
1673
1674                for (ie_c, ie_b) in ie {
1675                    self.get_inner_dep_graph_expr(ie_c, parent, deps);
1676                    self.get_inner_dep_graph_body(ie_b, parent, deps);
1677                }
1678
1679                if let Some(b) = eb {
1680                    self.get_inner_dep_graph_body(b, parent, deps);
1681                }
1682            }
1683
1684            RynaExpr::CompiledLambda(_, _, c, args, ret, b) => {
1685                self.get_inner_dep_graph_body(b, parent, deps);
1686
1687                for (_, a) in c {
1688                    self.get_inner_dep_graph_expr(a, parent, deps);
1689                }
1690
1691                for (_, t) in args {
1692                    for td in t.type_dependencies() {
1693                        deps.connect(parent.clone(), (ImportType::Class, td), ());
1694                    }
1695
1696                    for id in t.interface_dependencies() {
1697                        deps.connect(parent.clone(), (ImportType::Interface, id), ());
1698                    }
1699                }
1700
1701                for td in ret.type_dependencies() {
1702                    deps.connect(parent.clone(), (ImportType::Class, td), ());
1703                }
1704
1705                for id in ret.interface_dependencies() {
1706                    deps.connect(parent.clone(), (ImportType::Interface, id), ());
1707                }
1708            }
1709
1710            RynaExpr::FunctionDefinition(_, _, id, _, args, ret, b) => {
1711                self.get_inner_dep_graph_body(b, &(ImportType::Fn, *id), deps);
1712
1713                for (_, t) in args {
1714                    for td in t.type_dependencies() {
1715                        deps.connect(parent.clone(), (ImportType::Class, td), ());
1716                    }
1717
1718                    for id in t.interface_dependencies() {
1719                        deps.connect(parent.clone(), (ImportType::Interface, id), ());
1720                    }
1721                }
1722
1723                for td in ret.type_dependencies() {
1724                    deps.connect(parent.clone(), (ImportType::Class, td), ());
1725                }
1726
1727                for id in ret.interface_dependencies() {
1728                    deps.connect(parent.clone(), (ImportType::Interface, id), ());
1729                }
1730            }
1731
1732            RynaExpr::PrefixOperationDefinition(_, _, id, _, _, t1, t2, b) => {
1733                self.get_inner_dep_graph_body(b, &(ImportType::Prefix, *id), deps);
1734
1735                for td in t1.type_dependencies() {
1736                    deps.connect(parent.clone(), (ImportType::Class, td), ());
1737                }
1738
1739                for id in t1.interface_dependencies() {
1740                    deps.connect(parent.clone(), (ImportType::Interface, id), ());
1741                }
1742
1743                for td in t2.type_dependencies() {
1744                    deps.connect(parent.clone(), (ImportType::Class, td), ());
1745                }
1746
1747                for id in t2.interface_dependencies() {
1748                    deps.connect(parent.clone(), (ImportType::Interface, id), ());
1749                }
1750            }
1751
1752            RynaExpr::PostfixOperationDefinition(_, _, id, _, _, t1, t2, b) => {
1753                self.get_inner_dep_graph_body(b, &(ImportType::Postfix, *id), deps);
1754
1755                for td in t1.type_dependencies() {
1756                    deps.connect(parent.clone(), (ImportType::Class, td), ());
1757                }
1758
1759                for id in t1.interface_dependencies() {
1760                    deps.connect(parent.clone(), (ImportType::Interface, id), ());
1761                }
1762
1763                for td in t2.type_dependencies() {
1764                    deps.connect(parent.clone(), (ImportType::Class, td), ());
1765                }
1766
1767                for id in t2.interface_dependencies() {
1768                    deps.connect(parent.clone(), (ImportType::Interface, id), ());
1769                }
1770            }
1771
1772            RynaExpr::BinaryOperationDefinition(_, _, id, _, (_, t1), (_, t2), ret, b) => {
1773                self.get_inner_dep_graph_body(b, &(ImportType::Binary, *id), deps);
1774
1775                for td in t1.type_dependencies() {
1776                    deps.connect(parent.clone(), (ImportType::Class, td), ());
1777                }
1778
1779                for id in t1.interface_dependencies() {
1780                    deps.connect(parent.clone(), (ImportType::Interface, id), ());
1781                }
1782
1783                for td in t2.type_dependencies() {
1784                    deps.connect(parent.clone(), (ImportType::Class, td), ());
1785                }
1786
1787                for id in t2.interface_dependencies() {
1788                    deps.connect(parent.clone(), (ImportType::Interface, id), ());
1789                }
1790
1791                for td in ret.type_dependencies() {
1792                    deps.connect(parent.clone(), (ImportType::Class, td), ());
1793                }
1794
1795                for id in ret.interface_dependencies() {
1796                    deps.connect(parent.clone(), (ImportType::Interface, id), ());
1797                }
1798            }
1799
1800            RynaExpr::NaryOperationDefinition(_, _, id, _, (_, t1), args, ret, b) => {
1801                self.get_inner_dep_graph_body(b, &(ImportType::Nary, *id), deps);
1802
1803                for (_, t) in args {
1804                    for td in t.type_dependencies() {
1805                        deps.connect(parent.clone(), (ImportType::Class, td), ());
1806                    }
1807
1808                    for id in t.interface_dependencies() {
1809                        deps.connect(parent.clone(), (ImportType::Interface, id), ());
1810                    }
1811                }
1812
1813                for td in t1.type_dependencies() {
1814                    deps.connect(parent.clone(), (ImportType::Class, td), ());
1815                }
1816
1817                for id in t1.interface_dependencies() {
1818                    deps.connect(parent.clone(), (ImportType::Interface, id), ());
1819                }
1820
1821                for td in ret.type_dependencies() {
1822                    deps.connect(parent.clone(), (ImportType::Class, td), ());
1823                }
1824
1825                for id in ret.interface_dependencies() {
1826                    deps.connect(parent.clone(), (ImportType::Interface, id), ());
1827                }
1828            }
1829
1830            RynaExpr::InterfaceImplementation(_, _, t_i, n, a) => {
1831                if let Some(t) = self.get_interface(n) {
1832                    match t_i {
1833                        Type::Basic(id) | Type::Template(id, _) => {
1834                            deps.connect((ImportType::Class, *id), (ImportType::Interface, t.id), ());
1835                        }
1836                        
1837                        _ => {}
1838                    }
1839
1840                    for tp in a {
1841                        for t_dep in tp.type_dependencies() {
1842                            deps.connect((ImportType::Interface, t.id), (ImportType::Class, t_dep), ());
1843                        }
1844    
1845                        for id in tp.interface_dependencies() {
1846                            deps.connect((ImportType::Interface, t.id), (ImportType::Interface, id), ());
1847                        }
1848                    }
1849    
1850                    for t_dep in t_i.type_dependencies() {
1851                        deps.connect((ImportType::Interface, t.id), (ImportType::Class, t_dep), ());
1852                    }
1853
1854                    for id in t_i.interface_dependencies() {
1855                        deps.connect((ImportType::Interface, t.id), (ImportType::Interface, id), ());
1856                    }
1857                }
1858            }
1859
1860            RynaExpr::InterfaceDefinition(_, _, n, _, fns, uns, bin, nary) => {
1861                if let Some(t) = self.get_interface(n) {
1862                    for (_, f_n, _, a, r) in fns {
1863                        if let Some(f) = self.get_function(f_n) {
1864                            deps.connect((ImportType::Interface, t.id), (ImportType::Fn, f.id), ());                        
1865                        }
1866
1867                        for (_, tp) in a {
1868                            for t_dep in tp.type_dependencies() {
1869                                deps.connect((ImportType::Interface, t.id), (ImportType::Class, t_dep), ());
1870                            }
1871    
1872                            for id in tp.interface_dependencies() {
1873                                deps.connect((ImportType::Interface, t.id), (ImportType::Interface, id), ());
1874                            }
1875                        }
1876    
1877                        for t_dep in r.type_dependencies() {
1878                            deps.connect((ImportType::Interface, t.id), (ImportType::Class, t_dep), ());
1879                        }
1880    
1881                        for id in r.interface_dependencies() {
1882                            deps.connect((ImportType::Interface, t.id), (ImportType::Interface, id), ());
1883                        }
1884                    }
1885
1886                    for (_, op_id, _, _, at, r) in uns {
1887                        if let Operator::Unary { prefix, .. } = &self.unary_ops[*op_id] {
1888                            if *prefix {
1889                                deps.connect((ImportType::Interface, t.id), (ImportType::Prefix, *op_id), ());
1890                                
1891                            } else {
1892                                deps.connect((ImportType::Interface, t.id), (ImportType::Postfix, *op_id), ());
1893                            }
1894                        }
1895
1896                        for t_dep in at.type_dependencies() {
1897                            deps.connect((ImportType::Interface, t.id), (ImportType::Class, t_dep), ());
1898                        }
1899    
1900                        for id in at.interface_dependencies() {
1901                            deps.connect((ImportType::Interface, t.id), (ImportType::Interface, id), ());
1902                        }
1903
1904                        for t_dep in r.type_dependencies() {
1905                            deps.connect((ImportType::Interface, t.id), (ImportType::Class, t_dep), ());
1906                        }
1907    
1908                        for id in r.interface_dependencies() {
1909                            deps.connect((ImportType::Interface, t.id), (ImportType::Interface, id), ());
1910                        }
1911                    }
1912
1913                    for (_, op_id, _, (_, a0t), (_, a1t), r) in bin {
1914                        deps.connect((ImportType::Interface, t.id), (ImportType::Binary, *op_id), ());
1915
1916                        for t_dep in a0t.type_dependencies() {
1917                            deps.connect((ImportType::Interface, t.id), (ImportType::Class, t_dep), ());
1918                        }
1919    
1920                        for id in a0t.interface_dependencies() {
1921                            deps.connect((ImportType::Interface, t.id), (ImportType::Interface, id), ());
1922                        }
1923
1924                        for t_dep in a1t.type_dependencies() {
1925                            deps.connect((ImportType::Interface, t.id), (ImportType::Class, t_dep), ());
1926                        }
1927    
1928                        for id in a1t.interface_dependencies() {
1929                            deps.connect((ImportType::Interface, t.id), (ImportType::Interface, id), ());
1930                        }
1931
1932                        for t_dep in r.type_dependencies() {
1933                            deps.connect((ImportType::Interface, t.id), (ImportType::Class, t_dep), ());
1934                        }
1935    
1936                        for id in r.interface_dependencies() {
1937                            deps.connect((ImportType::Interface, t.id), (ImportType::Interface, id), ());
1938                        }
1939                    }
1940
1941                    for (_, op_id, _, (_, a0t), a, r) in nary {
1942                        deps.connect((ImportType::Interface, t.id), (ImportType::Nary, *op_id), ());
1943
1944                        for t_dep in a0t.type_dependencies() {
1945                            deps.connect((ImportType::Interface, t.id), (ImportType::Class, t_dep), ());
1946                        }
1947    
1948                        for id in a0t.interface_dependencies() {
1949                            deps.connect((ImportType::Interface, t.id), (ImportType::Interface, id), ());
1950                        }
1951
1952                        for (_, tp) in a {
1953                            for t_dep in tp.type_dependencies() {
1954                                deps.connect((ImportType::Interface, t.id), (ImportType::Class, t_dep), ());
1955                            }
1956    
1957                            for id in tp.interface_dependencies() {
1958                                deps.connect((ImportType::Interface, t.id), (ImportType::Interface, id), ());
1959                            }
1960                        }
1961    
1962                        for t_dep in r.type_dependencies() {
1963                            deps.connect((ImportType::Interface, t.id), (ImportType::Class, t_dep), ());
1964                        }
1965    
1966                        for id in r.interface_dependencies() {
1967                            deps.connect((ImportType::Interface, t.id), (ImportType::Interface, id), ());
1968                        }
1969                    }
1970                }
1971            }
1972
1973            RynaExpr::ClassDefinition(_, _, n, _, _, _, _) => {
1974                if let Some(t) = self.get_type_template(n) {
1975                    deps.connect(parent.clone(), (ImportType::Class, t.id), ());
1976
1977                    // Dependencies from the attributes
1978                    for (_, tp) in &t.attributes {
1979                        for t_dep in tp.type_dependencies() {
1980                            deps.connect((ImportType::Class, t.id), (ImportType::Class, t_dep), ());
1981                        }
1982
1983                        for id in tp.interface_dependencies() {
1984                            deps.connect(parent.clone(), (ImportType::Interface, id), ());
1985                        }
1986                    }
1987                }
1988            },
1989
1990            _ => {}
1991        }
1992    }
1993
1994    pub fn get_template_calls_body(
1995        &mut self, 
1996        lines: &Vec<RynaExpr>
1997    ) -> Result<(), RynaError> {
1998        let mut changed = true;
1999        
2000        while changed {
2001            changed = false;
2002            self.get_template_calls_body_pass(lines, &mut changed)?;
2003        }
2004
2005        Ok(())
2006    }
2007
2008    pub fn get_template_calls_pass(
2009        &mut self, 
2010        expr: &RynaExpr,
2011        changed: &mut bool
2012    ) -> Result<(), RynaError> {
2013        return match expr {
2014            RynaExpr::FunctionDefinition(_, _, id, _, a, r, b) => {
2015                let arg_types = a.iter().map(|(_, t)| t.clone()).collect::<Vec<_>>();
2016                let and = Type::And(arg_types.clone());
2017
2018                if let Some(usages) = self.cache.usages.functions.get_checked(id) {                    
2019                    for (args, ov) in usages {
2020                        if Type::And(args).bindable_to(&and, self) {
2021                            let mut body = b.clone();
2022                            let key = (*id, ov.clone(), arg_types.clone());
2023    
2024                            if !self.cache.templates.functions.contains(&key) {
2025                                if !ov.is_empty() {
2026                                    let templates = ov.iter().cloned().enumerate().collect();
2027
2028                                    // Create new instance
2029                                    body.iter_mut().for_each(|i| RynaContext::subtitute_type_params_expr(i, &templates));
2030                                    self.compile(&mut body, &a.iter().map(|(n, t)| (n.clone(), t.sub_templates(&templates))).collect(), self.is_dtor_id(*id))?;    
2031    
2032                                    // Statically check the newly instantiated functions
2033                                    for line in &body {
2034                                        self.static_check_expected(line, &Some(r.sub_templates(&templates)))?;
2035                                    }    
2036                                }
2037
2038                                self.cache.templates.functions.insert(key, body.clone());
2039
2040                                // Search instance recursively
2041                                self.get_template_calls_body_pass(&body, changed)?;
2042
2043                                *changed = true;
2044                            }
2045                        }
2046                    }
2047                }
2048
2049                Ok(())
2050            }
2051
2052            RynaExpr::PostfixOperationDefinition(_, _, id, _, n, tp, r, b) |
2053            RynaExpr::PrefixOperationDefinition(_, _, id, _, n, tp, r, b) => {
2054                if let Some(usages) = self.cache.usages.unary.get_checked(id) {
2055                    for (arg, ov) in usages {
2056                        if arg[0].bindable_to(tp, self) {
2057                            let mut body = b.clone();
2058                            let key = (*id, ov.clone(), vec!(tp.clone()));
2059        
2060                            if !self.cache.templates.unary.contains(&key) {
2061                                if !ov.is_empty() {
2062                                    let templates = ov.iter().cloned().enumerate().collect();
2063
2064                                    // Create new instance
2065                                    body.iter_mut().for_each(|i| RynaContext::subtitute_type_params_expr(i, &templates));
2066                                    self.compile(&mut body, &vec!((n.clone(), tp.sub_templates(&templates))), false)?;    
2067    
2068                                    // Statically check the newly instantiated functions
2069                                    for line in &body {
2070                                        self.static_check_expected(line, &Some(r.sub_templates(&templates)))?;
2071                                    }
2072                                }
2073
2074                                self.cache.templates.unary.insert(key, body.clone());
2075
2076                                // Search instance recursively
2077                                self.get_template_calls_body_pass(&body, changed)?;
2078
2079                                *changed = true;
2080                            }
2081                        }
2082                    }
2083                }
2084
2085                Ok(())
2086            }
2087
2088            RynaExpr::BinaryOperationDefinition(_, _, id, _, (n1, t1), (n2, t2), r, b) => {
2089                if let Some(usages) = self.cache.usages.binary.get_checked(id) {
2090                    for (arg, ov) in usages {
2091                        if arg[0].bindable_to(t1, self) && arg[1].bindable_to(t2, self) {
2092                            let mut body = b.clone();
2093                            let key = (*id, ov.clone(), vec!(t1.clone(), t2.clone()));
2094    
2095                            if !self.cache.templates.binary.contains(&key) {
2096                                if !ov.is_empty() {
2097                                    let templates = ov.iter().cloned().enumerate().collect();
2098                                    
2099                                    // Create new instance
2100                                    body.iter_mut().for_each(|i| RynaContext::subtitute_type_params_expr(i, &templates));
2101                                    self.compile(&mut body, &vec!((n1.clone(), t1.sub_templates(&templates)), (n2.clone(), t2.sub_templates(&templates))), false)?;    
2102    
2103                                    // Statically check the newly instantiated functions
2104                                    for line in &body {
2105                                        self.static_check_expected(line, &Some(r.sub_templates(&templates)))?;
2106                                    }
2107                                }
2108
2109                                self.cache.templates.binary.insert(key, body.clone());
2110
2111                                // Search instance recursively
2112                                self.get_template_calls_body_pass(&body, changed)?;
2113
2114                                *changed = true;
2115                            }
2116                        }
2117                    }
2118                }
2119
2120                Ok(())
2121            }
2122
2123            RynaExpr::NaryOperationDefinition(_, _, id, _, (n, t), a, r, b) => {
2124                let mut all_args = vec!(t.clone());
2125                all_args.extend(a.iter().map(|(_, t)| t).cloned());
2126                let and = Type::And(all_args.clone());
2127
2128                if let Some(usages) = self.cache.usages.nary.get_checked(id) {
2129                    for (args, ov) in usages {
2130                        if Type::And(args.clone()).bindable_to(&and, self) {
2131                            let mut body = b.clone();
2132                            let key = (*id, ov.clone(), all_args.clone());
2133    
2134                            if !self.cache.templates.nary.contains(&key) {
2135                                if !ov.is_empty() {
2136                                    let templates = ov.iter().cloned().enumerate().collect();
2137                                    
2138                                    // Create new instance
2139                                    body.iter_mut().for_each(|i| RynaContext::subtitute_type_params_expr(i, &templates));
2140
2141                                    let named_args = [(n.clone(), t.clone())].iter().chain(a).map(|(n, t)| (n.clone(), t.sub_templates(&templates))).collect();
2142                                    self.compile(&mut body, &named_args, false)?;    
2143
2144                                    // Statically check the newly instantiated functions
2145                                    for line in &body {
2146                                        self.static_check_expected(line, &Some(r.sub_templates(&templates)))?;
2147                                    }
2148                                }
2149
2150                                self.cache.templates.nary.insert(key, body.clone());
2151
2152                                // Search instance recursively
2153                                self.get_template_calls_body_pass(&body, changed)?;
2154
2155                                *changed = true;
2156                            }
2157                        }
2158                    }
2159                }
2160
2161                Ok(())
2162            }
2163
2164            _ => Ok(())
2165        }
2166    }
2167
2168    pub fn get_template_calls_body_pass(
2169        &mut self, 
2170        lines: &Vec<RynaExpr>,
2171        changed: &mut bool
2172    ) -> Result<(), RynaError> {
2173        for line in lines {
2174            self.get_template_calls_pass(line, changed)?;
2175        }
2176
2177        Ok(())
2178    }
2179
2180    pub fn subtitute_type_params_expr(expr: &mut RynaExpr, templates: &HashMap<usize, Type>) {
2181        match expr {
2182            RynaExpr::Continue(..) |
2183            RynaExpr::Break(..) |
2184            RynaExpr::Literal(..) |
2185            RynaExpr::NameReference(..) => {},
2186
2187            RynaExpr::Tuple(_, e) => e.iter_mut().for_each(|i| RynaContext::subtitute_type_params_expr(i, templates)),
2188
2189            RynaExpr::DoBlock(_, e, t) => {
2190                *t = t.sub_templates(templates);
2191                
2192                e.iter_mut().for_each(|i| RynaContext::subtitute_type_params_expr(i, templates))
2193            },
2194
2195            RynaExpr::Variable(_, _, _, t, _) => *t = t.sub_templates(templates),
2196
2197            RynaExpr::Lambda(_, _, args, r, lines) => {
2198                for (_, tp) in args {
2199                    *tp = tp.sub_templates(templates);
2200                }
2201                
2202                if *r != Type::InferenceMarker {
2203                    *r = r.sub_templates(templates);
2204                }
2205
2206                lines.iter_mut().for_each(|i| RynaContext::subtitute_type_params_expr(i, templates));
2207            },
2208
2209            RynaExpr::VariableAssignment(_, _, e) |
2210            RynaExpr::AttributeAccess(_, e, _) |
2211            RynaExpr::Return(_, e) => RynaContext::subtitute_type_params_expr(e, templates),
2212
2213            RynaExpr::VariableDefinition(_, _, t, e) |
2214            RynaExpr::CompiledVariableAssignment(_, _, _, t, e, _) |
2215            RynaExpr::CompiledVariableDefinition(_, _, _, t, e, _) => {
2216                *t = t.sub_templates(templates);
2217
2218                RynaContext::subtitute_type_params_expr(e, templates);
2219            },
2220            
2221            RynaExpr::UnaryOperation(_, _, t, a) => {
2222                t.iter_mut().for_each(|i| *i = i.sub_templates(templates));
2223
2224                RynaContext::subtitute_type_params_expr(a, templates);
2225            },
2226
2227            RynaExpr::AttributeAssignment(_, a, b, _) => {
2228                RynaContext::subtitute_type_params_expr(a, templates);
2229                RynaContext::subtitute_type_params_expr(b, templates);
2230            }
2231
2232            RynaExpr::BinaryOperation(_, _, t, a, b) => {
2233                t.iter_mut().for_each(|i| *i = i.sub_templates(templates));
2234
2235                RynaContext::subtitute_type_params_expr(a, templates);
2236                RynaContext::subtitute_type_params_expr(b, templates);
2237            }
2238
2239            RynaExpr::NaryOperation(_, _, t, first, args) => {
2240                t.iter_mut().for_each(|i| *i = i.sub_templates(templates));
2241
2242                RynaContext::subtitute_type_params_expr(first, templates);
2243                args.iter_mut().for_each(|i| RynaContext::subtitute_type_params_expr(i, templates));
2244            },
2245            
2246            RynaExpr::FunctionCall(_, _, t, args) => {
2247                t.iter_mut().for_each(|i| *i = i.sub_templates(templates));
2248
2249                args.iter_mut().for_each(|i| RynaContext::subtitute_type_params_expr(i, templates));
2250            },
2251            
2252            RynaExpr::For(_, _, container, body) |
2253            RynaExpr::CompiledFor(_, _, _, _, container, body) |
2254            RynaExpr::While(_, container, body) => {
2255                RynaContext::subtitute_type_params_expr(container, templates);
2256                body.iter_mut().for_each(|i| RynaContext::subtitute_type_params_expr(i, templates));
2257            },
2258
2259            RynaExpr::If(_, ih, ib, ei, eb) => {
2260                RynaContext::subtitute_type_params_expr(ih, templates);
2261                ib.iter_mut().for_each(|i| RynaContext::subtitute_type_params_expr(i, templates));
2262
2263                for (ei_h, ei_b) in ei {
2264                    RynaContext::subtitute_type_params_expr(ei_h, templates);
2265                    ei_b.iter_mut().for_each(|i| RynaContext::subtitute_type_params_expr(i, templates));
2266                }
2267
2268                if let Some(b) = eb {
2269                    b.iter_mut().for_each(|i| RynaContext::subtitute_type_params_expr(i, templates));
2270                }
2271            }
2272            
2273            _ => unimplemented!("{:?}", expr)
2274        };
2275    }
2276
2277    pub fn compile_lambda_expr(
2278        &mut self, 
2279        line: &RynaExpr,
2280        only_length: bool
2281    ) -> Result<(), RynaError> {
2282        return match line {
2283            RynaExpr::Break(..) |
2284            RynaExpr::Continue(..) |
2285            RynaExpr::Literal(..) |
2286            RynaExpr::Variable(..) |
2287            RynaExpr::ClassDefinition(..) |
2288            RynaExpr::InterfaceDefinition(..) |
2289            RynaExpr::InterfaceImplementation(..) |
2290            RynaExpr::PrefixOperatorDefinition(..) |
2291            RynaExpr::PostfixOperatorDefinition(..) |
2292            RynaExpr::BinaryOperatorDefinition(..) |
2293            RynaExpr::NaryOperatorDefinition(..) => Ok(()),
2294
2295            RynaExpr::CompiledLambda(_, i, c, a, _, b) => {
2296                self.compile_lambdas(b, only_length)?;
2297
2298                if only_length {
2299                    self.lambda_positions.entry(*i).or_insert(1 + self.lambda_code_length);
2300                    
2301                    self.lambda_code_length += self.compiled_form_body_size(b, true)? + a.len() + c.len();
2302
2303                } else {
2304                    for (i, e) in c.iter().enumerate() {
2305                        if i == 0 {
2306                            self.lambda_code.push(RynaInstruction::new_with_type(
2307                                CompiledRynaExpr::StoreVariable(i, false), 
2308                                "Lambda expression start".into(),
2309                                self.infer_type(&e.1).unwrap()
2310                            ));
2311    
2312                        } else {
2313                            self.lambda_code.push(RynaInstruction::new_with_type(
2314                                CompiledRynaExpr::StoreVariable(i, false), 
2315                                String::new(),
2316                                self.infer_type(&e.1).unwrap()
2317                            ));
2318                        }
2319                    }
2320    
2321                    for (i, arg) in a.iter().enumerate() {
2322                        self.lambda_code.push(RynaInstruction::new_with_type(
2323                            CompiledRynaExpr::StoreVariable(i + c.len(), false), 
2324                            String::new(),
2325                            arg.1.clone()
2326                        ));
2327                    }
2328    
2329                    self.lambda_code.extend(self.compiled_form_body(b)?);
2330                }
2331                
2332                Ok(())
2333            }
2334
2335            RynaExpr::CompiledVariableDefinition(_, _, _, _, e, _) |
2336            RynaExpr::CompiledVariableAssignment(_, _, _, _, e, _) |
2337            RynaExpr::Return(_, e) |
2338            RynaExpr::AttributeAccess(_, e, _) |
2339            RynaExpr::UnaryOperation(_, _, _, e) => self.compile_lambda_expr(e, only_length),
2340
2341            RynaExpr::AttributeAssignment(_, a, b, _) |
2342            RynaExpr::BinaryOperation(_, _, _, a, b) => {
2343                self.compile_lambda_expr(a, only_length)?;
2344                self.compile_lambda_expr(b, only_length)?;
2345
2346                Ok(())
2347            }
2348
2349            RynaExpr::CompiledFor(_, _, _, _, a, b) |
2350            RynaExpr::While(_, a, b) |
2351            RynaExpr::NaryOperation(_, _, _, a, b) => {
2352                self.compile_lambda_expr(a, only_length)?;
2353                self.compile_lambdas(b, only_length)?;
2354
2355                Ok(())
2356            }
2357
2358            RynaExpr::If(_, ih, ib, ei, eb) => {
2359                self.compile_lambda_expr(ih, only_length)?;
2360                self.compile_lambdas(ib, only_length)?;
2361
2362                for (ei_h, ei_b) in ei {
2363                    self.compile_lambda_expr(ei_h, only_length)?;
2364                    self.compile_lambdas(ei_b, only_length)?;
2365                }
2366
2367                if let Some(eb_inner) = eb {
2368                    self.compile_lambdas(eb_inner, only_length)?;                    
2369                }
2370
2371                Ok(())
2372            }
2373
2374            RynaExpr::DoBlock(_, args, _) |
2375            RynaExpr::Tuple(_, args) |
2376            RynaExpr::FunctionCall(_, _, _, args) => self.compile_lambdas(args, only_length),
2377
2378            RynaExpr::PrefixOperationDefinition(..) |
2379            RynaExpr::PostfixOperationDefinition(..) |
2380            RynaExpr::BinaryOperationDefinition(..) |
2381            RynaExpr::NaryOperationDefinition(..) |
2382            RynaExpr::FunctionDefinition(..) => Ok(()),
2383
2384            RynaExpr::Macro(..) => { Ok(()) },
2385
2386            _ => unimplemented!("{:?}", line)
2387        };
2388    }
2389
2390    pub fn compile_lambdas(
2391        &mut self, 
2392        lines: &Vec<RynaExpr>,
2393        only_length: bool
2394    ) -> Result<(), RynaError> {
2395        for line in lines {
2396            self.compile_lambda_expr(line, only_length)?;
2397        }
2398
2399        Ok(())
2400    }
2401
2402    pub fn compile_function_lambdas(&mut self, lines: &Vec<RynaExpr>, only_length: bool) -> Result<(), RynaError> {
2403        for expr in lines {
2404            match expr {
2405                RynaExpr::FunctionDefinition(_, _, id, _, a, _, _) => {
2406                    let arg_types = a.iter().map(|(_, t)| t.clone()).collect::<Vec<_>>();
2407                    let and = Type::And(arg_types.clone());
2408
2409                    if let Some(usages) = self.cache.usages.functions.get_checked(id) {
2410                        for (args, ov) in usages {
2411                            if Type::And(args.clone()).bindable_to(&and, self) {
2412                                let sub_b = self.cache.templates.functions.get_checked(&(*id, ov.clone(), arg_types.clone())).unwrap();
2413                                self.compile_lambdas(&sub_b, only_length)?;
2414                            }
2415                        }
2416                    }
2417                },
2418
2419                RynaExpr::PrefixOperationDefinition(_, _, id, _, _, tp, _, _) |
2420                RynaExpr::PostfixOperationDefinition(_, _, id, _, _, tp, _, _) => {
2421                    if let Some(usages) = self.cache.usages.unary.get_checked(id) {
2422                        for (args, ov) in usages {
2423                            if Type::And(args.clone()).bindable_to(tp, self) {
2424                                let sub_b = self.cache.templates.unary.get_checked(&(*id, ov.clone(), vec!(tp.clone()))).unwrap();
2425                                self.compile_lambdas(&sub_b, only_length)?;
2426                            }
2427                        }
2428                    }
2429                },
2430
2431                RynaExpr::BinaryOperationDefinition(_, _, id, _, (_, t1), (_, t2), _, _) => {
2432                    let and = Type::And(vec!(t1.clone(), t2.clone()));
2433
2434                    if let Some(usages) = self.cache.usages.binary.get_checked(id) {
2435                        for (args, ov) in usages {
2436                            if Type::And(args.clone()).bindable_to(&and, self) {    
2437                                let sub_b = self.cache.templates.binary.get_checked(&(*id, ov.clone(), vec!(t1.clone(), t2.clone()))).unwrap();
2438                                self.compile_lambdas(&sub_b, only_length)?;
2439                            }
2440                        }
2441                    }
2442                },
2443
2444                RynaExpr::NaryOperationDefinition(_, _, id, _, (_, a_t), a, _, _) => {
2445                    let mut arg_types = vec!(a_t.clone());
2446                    arg_types.extend(a.iter().map(|(_, t)| t).cloned());
2447
2448                    let and = Type::And(arg_types.clone());
2449
2450                    if let Some(usages) = self.cache.usages.nary.get_checked(id) {
2451                        for (args, ov) in usages {
2452                            if Type::And(args.clone()).bindable_to(&and, self) {
2453                                let sub_b = self.cache.templates.nary.get_checked(&(*id, ov.clone(), arg_types.clone())).unwrap();
2454                                self.compile_lambdas(&sub_b, only_length)?;
2455                            }
2456                        }
2457                    }
2458                },
2459
2460                _ => {}
2461            }
2462        }
2463
2464        Ok(())
2465    }
2466
2467    pub fn generate_array_destructor(&self, tm: &Type) -> Result<Vec<RynaExpr>, RynaError> {
2468        use RynaExpr::*;
2469
2470        let inc_idx = self.get_function_id("inc".into()).unwrap();
2471        let len_idx = self.get_function_id("len".into()).unwrap();
2472        let drop_idx = self.get_function_id("$drop_unsafe".into()).unwrap();
2473        let deref_idx = self.get_function_id("deref".into()).unwrap();
2474        
2475        let container = Variable(Location::none(), 0, "$c".into(), ARR_OF!(tm.clone()).to_ref(), false);
2476        let index = Variable(Location::none(), 1, "$idx".into(), INT, false);
2477        let deref_index = FunctionCall(Location::none(), deref_idx, vec!(INT), vec!(index.clone()));
2478
2479        let body = vec!(
2480            // Init idx variable
2481            CompiledVariableDefinition(Location::none(), 1, "$idx".into(), INT, Box::new(Literal(Location::none(), Object::new(Integer::from(0)))), false),
2482
2483            // While loop
2484            While(
2485                Location::none(), 
2486                Box::new(BinaryOperation(Location::none(), LT_BINOP_ID, vec!(),
2487                    Box::new(index.clone()),
2488                    Box::new(FunctionCall(Location::none(), len_idx, vec!(), vec!(container.clone())))
2489                )),
2490                vec!(
2491                    // Call destructor on element
2492                    self.get_destructor_call(0, None, None, Some(deref_index.clone()), &"$c".into(), &ARR_OF!(tm.clone())),
2493
2494                    // Delete element from array
2495                    FunctionCall(Location::none(), drop_idx, vec!(), vec!(container, deref_index.clone())),
2496
2497                    // Increment index
2498                    FunctionCall(Location::none(), inc_idx, vec!(), vec!(index))
2499                )
2500            ),
2501
2502            Return(Location::none(), Box::new(Literal(Location::none(), Object::empty())))
2503        );
2504
2505        Ok(body)
2506    }
2507
2508    fn generate_type_destructor(&self, id: usize, templates: &Vec<Type>) -> Result<Vec<RynaExpr>, RynaError> {
2509        use RynaExpr::*;
2510
2511        let drop_idx = self.get_function_id("$drop_attr_unsafe".into()).unwrap();
2512
2513        let subs = templates.iter().cloned().enumerate().collect::<HashMap<_, _>>();
2514
2515        let obj_type = Type::Template(id, templates.clone()).to_ref();
2516        let obj = Variable(Location::none(), 0, "$obj".into(), obj_type.clone(), false);
2517
2518        let mut body = vec!();
2519
2520        for (i, (_, attr)) in self.type_templates[id].attributes.iter().enumerate() {
2521            let sub_attr = attr.sub_templates(&subs);
2522
2523            if sub_attr.needs_destructor(self) {
2524                // Add attribute destructor
2525                let dtor = self.get_destructor_call(0, None, Some(i), None, &"$obj".into(), &obj_type.clone());
2526                body.push(dtor);
2527
2528                // Remove attribute
2529                let rm = FunctionCall(Location::none(), drop_idx, vec!(), vec!(
2530                    obj.clone(),
2531                    Literal(Location::none(), Object::new(Integer::from(i)))
2532                ));
2533                body.push(rm);
2534            }
2535        }
2536
2537        body.push(Return(Location::none(), Box::new(Literal(Location::none(), Object::empty()))));
2538
2539        Ok(body)
2540    }
2541
2542    fn generate_iterator_destructor(&self, c: &Type, it: &Type) -> Result<Vec<RynaExpr>, RynaError> {
2543        use RynaExpr::*;
2544
2545        let destroy_idx = self.get_function_id("destroy".into()).unwrap();
2546        let container_idx = self.get_function_id("$container".into()).unwrap();
2547
2548        let iterator = Variable(Location::none(), 0, "$it".into(), ARR_IT_OF!(c.clone(), it.clone()).to_ref(), false);
2549        let container = FunctionCall(Location::none(), container_idx, vec!(c.clone()), vec!(iterator));
2550
2551        let t_args = self.get_destructor_template_args(ARR_OF!(c.clone()));
2552        let dtor = FunctionCall(Location::none(), destroy_idx, t_args, vec!(container));
2553
2554        // Add destructor dependencies
2555        for t in ARR_IT_OF!(c.clone(), it.clone()).destructor_dependencies(self) {
2556            self.add_destructor_usage(t.clone().to_ref());
2557        }
2558
2559        let body = vec!(
2560            dtor,
2561            Return(Location::none(), Box::new(Literal(Location::none(), Object::empty())))
2562        );
2563
2564        Ok(body)
2565    }
2566
2567    fn generate_tuple_destructor(&self, elems: &Vec<Type>) -> Result<Vec<RynaExpr>, RynaError> {
2568        use RynaExpr::*;
2569
2570        let tuple = Variable(Location::none(), 0, "$obj".into(), Type::And(elems.clone()).to_ref(), false);
2571
2572        let mut body = vec!();
2573
2574        for (i, t) in elems.iter().enumerate() {
2575            if t.needs_destructor(self) {
2576                let get_idx = self.get_function_id(format!("get_{i}")).unwrap();
2577                let drop_idx = self.get_function_id(format!("$drop_{i}_unsafe")).unwrap();
2578
2579                let tuple_elem = FunctionCall(Location::none(), get_idx, elems.clone(), vec!(tuple.clone()));
2580                let dtor = self.get_destructor_call(0, Some(tuple_elem), None, None, &"".into(), t);
2581
2582                body.push(dtor);
2583
2584                let drop = FunctionCall(Location::none(), drop_idx, elems.clone(), vec!(tuple.clone()));
2585
2586                body.push(drop);
2587            }
2588        }
2589
2590        body.push(Return(Location::none(), Box::new(Literal(Location::none(), Object::empty()))));
2591
2592        Ok(body)
2593    }
2594
2595    fn generate_or_destructor(&self, elems: &Vec<Type>) -> Result<Vec<RynaExpr>, RynaError> {
2596        use RynaExpr::*;
2597
2598        let is_idx = self.get_function_id("is".into()).unwrap();
2599        let as_idx = self.get_function_id("$unsafe_as".into()).unwrap();
2600
2601        let or = Variable(Location::none(), 0, "$obj".into(), Type::Or(elems.clone()).to_ref(), false);
2602
2603        let mut body = vec!();
2604
2605        for t in elems.iter() {
2606            if t.needs_destructor(self) {
2607                let variant = t.deref_type().clone().to_ref();
2608
2609                let cond = FunctionCall(Location::none(), is_idx, vec!(variant.clone()), vec!(or.clone()));
2610                let casted = FunctionCall(Location::none(), as_idx, vec!(variant), vec!(or.clone()));
2611                let dtor = self.get_destructor_call(0, Some(casted), None, None, &"".into(), t);
2612
2613                body.push(If(
2614                    Location::none(),
2615                    Box::new(cond),
2616                    vec!(
2617                        dtor,
2618                        Return(Location::none(), Box::new(Literal(Location::none(), Object::empty())))
2619                    ),
2620                    vec!(),
2621                    None
2622                ));
2623            }
2624        }
2625
2626        body.push(Return(Location::none(), Box::new(Literal(Location::none(), Object::empty()))));
2627
2628        Ok(body)
2629    }
2630
2631    pub fn generate_destructor_for_type(&self, t: &Type) -> Result<Vec<RynaExpr>, RynaError> {
2632        match t.deref_type() {
2633            Type::And(t) => self.generate_tuple_destructor(t),
2634            Type::Or(t) => self.generate_or_destructor(t),
2635
2636            Type::Template(ARR_ID, tm) => self.generate_array_destructor(&tm[0]),
2637            Type::Template(ARR_IT_ID, tm) => self.generate_iterator_destructor(&tm[0], &tm[1]),
2638
2639            Type::Template(id, tm) => self.generate_type_destructor(*id, tm), 
2640            Type::Basic(id) => self.generate_type_destructor(*id, &vec!()),
2641
2642            _ => Err(
2643                RynaError::compiler_error(
2644                    format!("Unable to generate destructor for type {}", t.get_name(self)),
2645                    &Location::none(), vec!()
2646                )
2647            )
2648        }
2649    }
2650
2651    pub fn generate_destructors(&mut self, lines: &mut Vec<RynaExpr>) -> Result<(), RynaError> {
2652        let destroy_id = self.get_function_id("destroy".into()).unwrap();
2653        let destroy_or_id = self.get_function_id("destroy_or".into()).unwrap();
2654
2655        for id in [destroy_id, destroy_or_id] {
2656            if let Some(usages) = self.cache.usages.functions.get_checked(&id) {
2657                for (args, ov) in usages {
2658                    // If there is no overload, we need to generate it
2659                    if self.get_first_function_overload(id, args.clone(), Some(ov.clone()), true, &Location::none()).is_err() {
2660                        let body = self.generate_destructor_for_type(&args[0])?;
2661    
2662                        // Define function overload
2663                        match self.define_function_overload(Location::none(), vec!(), id, ov.len(), &args, Type::Empty, None) {
2664                            Ok(_) => { },
2665                            Err(err) => return Err(RynaError::compiler_error(err, &Location::none(), vec!())),
2666                        }
2667    
2668                        // Add line at the end
2669                        lines.push(
2670                            RynaExpr::FunctionDefinition(
2671                                Location::none(), 
2672                                vec!(), id, vec!(), 
2673                                vec!(("$obj".into(), args[0].clone())), 
2674                                Type::Empty,
2675                                body
2676                            )
2677                        );
2678                    }
2679                }
2680            }
2681        }
2682
2683        Ok(())
2684    }
2685
2686    pub fn compiled_form(&mut self, lines: &Vec<RynaExpr>) -> Result<Vec<RynaInstruction>, RynaError> {
2687        self.compile_function_lambdas(lines, true)?;
2688        self.compile_lambdas(lines, true)?;
2689
2690        let mut program_size = 1 + self.lambda_code_length;
2691
2692        // Define function indexes
2693        for expr in lines {
2694            match expr {
2695                RynaExpr::FunctionDefinition(_, _, id, t, a, ret, _) => {
2696                    let arg_types = a.iter().map(|(_, t)| t.clone()).collect::<Vec<_>>();
2697                    let and = Type::And(arg_types.clone());
2698
2699                    if let Some(usages) = self.cache.usages.functions.get_checked(id) {
2700                        for (args, ov) in usages {
2701                            if Type::And(args.clone()).bindable_to(&and, self) {
2702                                // Find function overload id    
2703                                if self.cache.overloads.functions.get_checked(&(*id, args.clone(), ov.clone())).is_some() {
2704                                    let init_loc = program_size;
2705                                    self.cache.locations.functions.insert((*id, args.clone(), ov.clone()), program_size);
2706
2707                                    let arg_types = a.iter().map(|(_, t)| t.clone()).collect();
2708                                    let sub_b = self.cache.templates.functions.get_checked(&(*id, ov.clone(), arg_types)).unwrap(); 
2709
2710                                    program_size += self.compiled_form_body_size(&sub_b, true)? + a.len();
2711
2712                                    if t.is_empty() {
2713                                        let signature = format!(
2714                                            "fn {}({}) -> {}",
2715                                            self.functions[*id].name,
2716                                            a.iter().map(|(_, at)| {
2717                                                at.get_name_plain(self)
2718                                            }).collect::<Vec<_>>().join(", "),
2719                                            ret.get_name_plain(self)
2720                                        );
2721
2722                                        self.cache.ranges.insert(signature, (init_loc, program_size));
2723        
2724                                    } else {                                
2725                                        let signature = format!(
2726                                            "fn<{}> {}({}) -> {}",
2727                                            ov.iter().map(|i| {
2728                                                i.get_name_plain(self)
2729                                            }).collect::<Vec<_>>().join(", "),
2730                                            self.functions[*id].name,
2731                                            a.iter().map(|(_, at)| {
2732                                                at.get_name_plain(self)
2733                                            }).collect::<Vec<_>>().join(", "),
2734                                            ret.get_name_plain(self)
2735                                        );
2736
2737                                        self.cache.ranges.insert(signature, (init_loc, program_size));
2738                                    }    
2739                                }
2740                            }
2741                        }
2742                    }
2743                },
2744                
2745                RynaExpr::PrefixOperationDefinition(_, _, id, t, _, tp, ret, _) |
2746                RynaExpr::PostfixOperationDefinition(_, _, id, t, _, tp, ret, _) => {
2747                    if let Some(usages) = self.cache.usages.unary.get_checked(id) {
2748                        for (args, ov) in usages {
2749                            if Type::And(args.clone()).bindable_to(tp, self) {                                
2750                                // Find overload id    
2751                                if self.cache.overloads.unary.get_checked(&(*id, args.clone(), ov.clone())).is_some() {
2752                                    let init_loc = program_size;
2753                                    self.cache.locations.unary.insert((*id, args.clone(), ov.clone()), program_size);
2754
2755                                    let prefix = if let Operator::Unary { prefix, .. } = self.unary_ops[*id] {
2756                                        prefix   
2757                                    } else {
2758                                        false
2759                                    };
2760
2761                                    let sub_b = self.cache.templates.unary.get_checked(&(*id, ov.clone(), vec!(tp.clone()))).unwrap(); 
2762                                    program_size += self.compiled_form_body_size(&sub_b, true)? + 1;
2763                                    
2764                                    if t.is_empty() {        
2765                                        let signature = format!(
2766                                            "op {}({}){} -> {}",
2767                                            if prefix { self.unary_ops[*id].get_repr() } else { "".into() },
2768                                            tp.get_name_plain(self),
2769                                            if prefix { "".into() } else { self.unary_ops[*id].get_repr() },
2770                                            ret.get_name_plain(self)
2771                                        );
2772
2773                                        self.cache.ranges.insert(signature, (init_loc, program_size));
2774
2775                                    } else {                                
2776                                        let signature = format!(
2777                                            "op<{}> {}({}){} -> {}",
2778                                            ov.iter().map(|i| {
2779                                                i.get_name_plain(self)
2780                                            }).collect::<Vec<_>>().join(", "),
2781                                            if prefix { self.unary_ops[*id].get_repr() } else { "".into() },
2782                                            tp.get_name_plain(self),
2783                                            if prefix { "".into() } else { self.unary_ops[*id].get_repr() },
2784                                            ret.get_name_plain(self)
2785                                        );
2786
2787                                        self.cache.ranges.insert(signature, (init_loc, program_size));
2788                                    }    
2789                                }
2790                            }
2791                        }
2792                    }
2793                }
2794                
2795                RynaExpr::BinaryOperationDefinition(_, _, id, t, (_, t1), (_, t2), ret, _) => {
2796                    let and = Type::And(vec!(t1.clone(), t2.clone()));
2797
2798                    if let Some(usages) = self.cache.usages.binary.get_checked(id) {
2799                        for (args, ov) in usages {
2800                            if Type::And(args.clone()).bindable_to(&and, self) {                                
2801                                // Find overload id    
2802                                if self.cache.overloads.binary.get_checked(&(*id, args.clone(), ov.clone())).is_some() {
2803                                    let init_loc = program_size;
2804                                    self.cache.locations.binary.insert((*id, args.clone(), ov.clone()), program_size);
2805
2806                                    let sub_b = self.cache.templates.binary.get_checked(&(*id, ov.clone(), vec!(t1.clone(), t2.clone()))).unwrap(); 
2807                                    program_size += self.compiled_form_body_size(&sub_b, true)? + 2;
2808
2809                                    if t.is_empty() {
2810                                        let signature = format!(
2811                                            "op ({}){}({}) -> {}",
2812                                            t1.get_name_plain(self),
2813                                            self.binary_ops[*id].get_repr(),
2814                                            t2.get_name_plain(self),
2815                                            ret.get_name_plain(self)
2816                                        );
2817
2818                                        self.cache.ranges.insert(signature, (init_loc, program_size));
2819
2820                                    } else {                                
2821                                        let signature = format!(
2822                                            "op<{}> ({}){}({}) -> {}",
2823                                            ov.iter().map(|i| {
2824                                                i.get_name_plain(self)
2825                                            }).collect::<Vec<_>>().join(", "),
2826                                            t1.get_name_plain(self),
2827                                            self.binary_ops[*id].get_repr(),
2828                                            t2.get_name_plain(self),
2829                                            ret.get_name_plain(self)
2830                                        );
2831
2832                                        self.cache.ranges.insert(signature, (init_loc, program_size));
2833                                    }    
2834                                }
2835                            }
2836                        }
2837                    }
2838                }
2839                
2840                RynaExpr::NaryOperationDefinition(_, _, id, t, (_, a_t), a, ret, _) => {
2841                    let mut arg_types = vec!(a_t.clone());
2842                    arg_types.extend(a.iter().map(|(_, t)| t).cloned());
2843
2844                    let and = Type::And(arg_types.clone());
2845
2846                    if let Some(usages) = self.cache.usages.nary.get_checked(id) {
2847                        for (args, ov) in usages {
2848                            if Type::And(args.clone()).bindable_to(&and, self) {
2849                                // Find overload id    
2850                                if self.cache.overloads.nary.get_checked(&(*id, args.clone(), ov.clone())).is_some() {
2851                                    let init_loc = program_size;
2852                                    self.cache.locations.nary.insert((*id, args.clone(), ov.clone()), program_size);
2853
2854                                    let mut o_rep = "".to_string();
2855                                    let mut c_rep = "".to_string();
2856
2857                                    if let Operator::Nary { open_rep, close_rep, .. } = &self.nary_ops[*id] {
2858                                        o_rep = open_rep.clone();
2859                                        c_rep = close_rep.clone();
2860                                    }
2861
2862                                    let sub_b = self.cache.templates.nary.get_checked(&(*id, ov.clone(), arg_types.clone())).unwrap(); 
2863                                    program_size += self.compiled_form_body_size(&sub_b, true)? + a.len() + 1;
2864                                    
2865                                    if t.is_empty() {                                            
2866                                        let signature = format!(
2867                                            "op ({}){}({}){} -> {}",
2868                                            a_t.get_name_plain(self),
2869                                            o_rep,
2870                                            a.iter().map(|(_, at)| {
2871                                                at.get_name_plain(self)
2872                                            }).collect::<Vec<_>>().join(", "),
2873                                            c_rep,
2874                                            ret.get_name_plain(self)
2875                                        );
2876
2877                                        self.cache.ranges.insert(signature, (init_loc, program_size));
2878        
2879                                    } else {
2880                                        let signature = format!(
2881                                            "op<{}> ({}){}({}){} -> {}",
2882                                            ov.iter().map(|i| {
2883                                                i.get_name_plain(self)
2884                                            }).collect::<Vec<_>>().join(", "),
2885                                            a_t.get_name_plain(self),
2886                                            o_rep,
2887                                            a.iter().map(|(_, at)| {
2888                                                at.get_name_plain(self)
2889                                            }).collect::<Vec<_>>().join(", "),
2890                                            c_rep,
2891                                            ret.get_name_plain(self)
2892                                        );
2893
2894                                        self.cache.ranges.insert(signature, (init_loc, program_size));
2895                                    }    
2896                                }
2897                            }
2898                        }
2899                    }
2900                }
2901
2902                _ => {}
2903            }
2904        }
2905
2906        let mut res = vec!(RynaInstruction::from(CompiledRynaExpr::Jump(program_size + self.lambda_code.len())));
2907
2908        self.compile_function_lambdas(lines, false)?;
2909        self.compile_lambdas(lines, false)?;
2910
2911        res.append(&mut self.lambda_code);
2912
2913        // Define functions
2914        for expr in lines {
2915            match expr {
2916                RynaExpr::FunctionDefinition(_, _, id, _, a, r, _) => {
2917                    let arg_types = a.iter().map(|(_, t)| t.clone()).collect::<Vec<_>>();
2918                    let and = Type::And(arg_types.clone());
2919
2920                    if let Some(usages) = self.cache.usages.functions.get_checked(id) {
2921                        for (args, ov) in usages {
2922                            if Type::And(args.clone()).bindable_to(&and, self) {
2923                                // Store parameters
2924                                for (i, arg) in args.iter().enumerate() {
2925                                    if i == 0 {
2926                                        let comment = format!(
2927                                            "fn {}{}({}) -> {}",
2928                                            self.functions[*id].name.green(),
2929                                            if ov.is_empty() { "".into() } else { format!("<{}>", ov.iter().map(|i| i.get_name(self)).collect::<Vec<_>>().join(", ")) },
2930                                            a.iter().map(|(_, t)| t.get_name(self)).collect::<Vec<_>>().join(", "),
2931                                            r.get_name(self)
2932                                        );
2933
2934                                        res.push(RynaInstruction::new_with_type(
2935                                            CompiledRynaExpr::StoreVariable(i, false), 
2936                                            comment,
2937                                            arg.clone()
2938                                        ));
2939
2940                                    } else {
2941                                        res.push(RynaInstruction::new_with_type(
2942                                            CompiledRynaExpr::StoreVariable(i, false),
2943                                            String::new(),
2944                                            arg.clone()
2945                                        ));
2946                                    }
2947                                }
2948
2949                                let sub_b = self.cache.templates.functions.get_checked(&(*id, ov.clone(), arg_types.clone())).unwrap();
2950                                res.extend(self.compiled_form_body(&sub_b)?);
2951                            }
2952                        }
2953                    }
2954                },
2955
2956                RynaExpr::PrefixOperationDefinition(_, _, id, _, _, tp, r, _) |
2957                RynaExpr::PostfixOperationDefinition(_, _, id, _, _, tp, r, _) => {
2958                    if let Some(usages) = self.cache.usages.unary.get_checked(id) {
2959                        for (args, ov) in usages {
2960                            if Type::And(args.clone()).bindable_to(tp, self) {
2961                                let mut rep = String::new();
2962                                let mut is_prefix = false;
2963            
2964                                if let Operator::Unary{representation, prefix, ..} = &self.unary_ops[*id] {
2965                                    rep = representation.clone();
2966                                    is_prefix = *prefix;
2967                                }
2968            
2969                                // Store parameter
2970                                let comment = if is_prefix {
2971                                    format!("op {}({}) -> {}", rep, tp.get_name(self), r.get_name(self))
2972            
2973                                } else {
2974                                    format!("op ({}){} -> {}", tp.get_name(self), rep, r.get_name(self))
2975                                };
2976                                
2977                                res.push(RynaInstruction::new_with_type(
2978                                    CompiledRynaExpr::StoreVariable(0, false), 
2979                                    comment,
2980                                    args[0].clone()
2981                                ));
2982    
2983                                let sub_b = self.cache.templates.unary.get_checked(&(*id, ov.clone(), vec!(tp.clone()))).unwrap();
2984                                res.extend(self.compiled_form_body(&sub_b)?);
2985                            }
2986                        }
2987                    }
2988                },
2989
2990                RynaExpr::BinaryOperationDefinition(_, _, id, _, (_, t1), (_, t2), r, _) => {
2991                    let and = Type::And(vec!(t1.clone(), t2.clone()));
2992
2993                    if let Some(usages) = self.cache.usages.binary.get_checked(id) {
2994                        for (args, ov) in usages {
2995                            if Type::And(args.clone()).bindable_to(&and, self) {    
2996                                // Store parameters
2997                                let mut rep = String::new();
2998
2999                                if let Operator::Binary{representation, ..} = &self.binary_ops[*id] {
3000                                    rep = representation.clone();
3001                                }
3002
3003                                let comment = format!("op ({}) {} ({}) -> {}", t1.get_name(self), rep, t2.get_name(self), r.get_name(self));
3004
3005                                res.push(RynaInstruction::new_with_type(
3006                                    CompiledRynaExpr::StoreVariable(0, false), 
3007                                    comment,
3008                                    args[0].clone()
3009                                ));
3010
3011                                res.push(RynaInstruction::new_with_type(
3012                                    CompiledRynaExpr::StoreVariable(1, false),
3013                                    String::new(),
3014                                    args[1].clone()
3015                                ));
3016    
3017                                let sub_b = self.cache.templates.binary.get_checked(&(*id, ov.clone(), vec!(t1.clone(), t2.clone()))).unwrap();
3018                                res.extend(self.compiled_form_body(&sub_b)?);
3019                            }
3020                        }
3021                    }
3022                },
3023
3024                RynaExpr::NaryOperationDefinition(_, _, id, _, (_, a_t), a, r, _) => {
3025                    let mut arg_types = vec!(a_t.clone());
3026                    arg_types.extend(a.iter().map(|(_, t)| t).cloned());
3027
3028                    let and = Type::And(arg_types.clone());
3029
3030                    if let Some(usages) = self.cache.usages.nary.get_checked(id) {
3031                        for (args, ov) in usages {
3032                            if Type::And(args.clone()).bindable_to(&and, self) {
3033                                // Store parameters
3034                                let mut o_rep = String::new();
3035                                let mut c_rep = String::new();
3036    
3037                                if let Operator::Nary{open_rep, close_rep, ..} = &self.nary_ops[*id] {
3038                                    o_rep = open_rep.clone();
3039                                    c_rep = close_rep.clone();
3040                                }
3041    
3042                                for (i, arg) in args.iter().enumerate() {
3043                                    if i == 0 {
3044                                        let comment = format!(
3045                                            "op ({}){}{}{} -> {}", 
3046                                            a_t.get_name(self),
3047                                            o_rep, 
3048                                            a.iter().map(|(_, t)| t.get_name(self)).collect::<Vec<_>>().join(", "), 
3049                                            c_rep,
3050                                            r.get_name(self)
3051                                        );
3052    
3053                                        res.push(RynaInstruction::new_with_type(
3054                                            CompiledRynaExpr::StoreVariable(i, false), 
3055                                            comment,
3056                                            arg.clone()
3057                                        ));
3058    
3059                                    } else {
3060                                        res.push(RynaInstruction::new_with_type(
3061                                            CompiledRynaExpr::StoreVariable(i, false),
3062                                            String::new(),
3063                                            arg.clone()
3064                                        ));
3065                                    }
3066                                }
3067    
3068                                let sub_b = self.cache.templates.nary.get_checked(&(*id, ov.clone(), arg_types.clone())).unwrap();
3069                                res.extend(self.compiled_form_body(&sub_b)?);
3070                            }
3071                        }
3072                    }
3073                },
3074
3075                _ => {}
3076            }
3077        }
3078
3079        // Update first jump
3080        res[0] = RynaInstruction::from(CompiledRynaExpr::Jump(program_size));
3081
3082        // Define everything else
3083        for expr in lines {
3084            match expr {
3085                RynaExpr::FunctionDefinition(..) | 
3086                RynaExpr::PrefixOperationDefinition(..) |
3087                RynaExpr::PostfixOperationDefinition(..) |
3088                RynaExpr::BinaryOperationDefinition(..) |
3089                RynaExpr::NaryOperationDefinition(..) => {},
3090
3091                _ => res.extend(self.compiled_form_expr(expr, true)?)
3092            }
3093        }
3094
3095        res.push(RynaInstruction::new(CompiledRynaExpr::Halt, "End of the program".into()));
3096
3097        Ok(res)
3098    }
3099
3100    pub fn is_dtor_id(&self, id: usize) -> bool {
3101        id == self.get_function_id("destroy".into()).unwrap() ||
3102        id == self.get_function_id("destroy_or".into()).unwrap()
3103    }
3104
3105    pub fn compiled_form_size(&self, expr: &RynaExpr, root: bool, root_counter: &mut usize) -> Result<usize, RynaError> {
3106        use RynaExpr::*;
3107
3108        match expr {
3109            Break(..) |
3110            Continue(..) => Ok(1),
3111
3112            Variable(..) => {
3113                *root_counter += root as usize; // Add drop instruction
3114
3115                Ok(1)
3116            }, 
3117            
3118            Literal(_, obj) => {
3119                *root_counter += root as usize; // Add drop instruction
3120                
3121                Ok(RynaContext::compiled_literal_size(obj))
3122            },
3123
3124            AttributeAccess(_, e, _) => {
3125                *root_counter += root as usize; // Add drop instruction
3126                
3127                Ok(self.compiled_form_size(e, false, root_counter)? + 1)
3128            }
3129
3130            AttributeAssignment(_, a, b, _) => {                
3131                Ok(self.compiled_form_size(a, false, root_counter)? + self.compiled_form_size(b, false, root_counter)? + 1)
3132            }
3133            
3134            CompiledLambda(_, _, c, ..) => {
3135                *root_counter += root as usize; // Add drop instruction
3136                
3137                Ok(1 + c.len())
3138            }
3139
3140            UnaryOperation(_, id, t, arg) => {
3141                *root_counter += root as usize; // Add drop instruction
3142
3143                let a_t = self.infer_type(arg)?;
3144
3145                let ov_id = self.cache.overloads.unary.get_checked(&(*id, vec!(a_t.clone()), t.clone())).unwrap();
3146                let offset = self.cache.opcodes.unary.get_checked(&(*id, ov_id)).map(|i| i.1).unwrap_or(0);
3147
3148                Ok(self.compiled_form_size(arg, false, root_counter)? + 1 + offset)
3149            }
3150
3151            BinaryOperation(_, id, t, a, b) => {
3152                *root_counter += root as usize; // Add drop instruction
3153
3154                let a_t = self.infer_type(a)?;
3155                let b_t = self.infer_type(b)?;
3156
3157                let ov_id = self.cache.overloads.binary.get_checked(&(*id, vec!(a_t.clone(), b_t.clone()), t.clone())).unwrap();
3158                let (opcode, mut offset) = self.cache.opcodes.binary.get_checked(&(*id, ov_id)).unwrap_or((CompiledRynaExpr::Halt, 0));
3159
3160                if (*id == AND_BINOP_ID || *id == OR_BINOP_ID) && *a_t.deref_type() == BOOL && *b_t.deref_type() == BOOL {
3161                    offset += 1;
3162                }
3163
3164                if root && opcode.needs_no_drop() {
3165                    *root_counter -= 1; // No drop for Assign
3166                }
3167
3168                Ok(self.compiled_form_size(a, false, root_counter)? + self.compiled_form_size(b, false, root_counter)? + 1 + offset)
3169            },
3170
3171            NaryOperation(_, _, _, a, b) => {
3172                *root_counter += root as usize; // Add drop instruction
3173
3174                Ok(self.compiled_form_size(a, false, root_counter)? + self.compiled_form_body_size(b, false)? + 1)
3175            },
3176
3177            Return(_, e) | CompiledVariableDefinition(_, _, _, _, e, _) | CompiledVariableAssignment(_, _, _, _, e, _) => Ok(self.compiled_form_size(e, false, root_counter)? + 1),
3178            
3179            If(_, ih, ib, ei, e) => {
3180                let needs_deref = self.infer_type(ih).unwrap().is_ref();
3181                let mut res = self.compiled_form_size(ih, false, root_counter)? + self.compiled_form_body_size(ib, true)? + 2 + needs_deref as usize;
3182
3183                for (h, b) in ei {
3184                    let needs_deref = self.infer_type(h).unwrap().is_ref();
3185                    res += self.compiled_form_size(h, false, root_counter)? + self.compiled_form_body_size(b, true)? + 2 + needs_deref as usize;
3186                }
3187
3188                if let Some(b) = e {
3189                    res += self.compiled_form_body_size(b, true)?;
3190                }
3191                
3192                Ok(res)
3193            },
3194
3195            CompiledFor(_, _, _, _, c, b) => Ok(self.compiled_form_size(c, false, root_counter)? + self.compiled_form_body_size(b, true)? + 9),
3196
3197            While(_, c, b) => {
3198                let needs_deref = self.infer_type(c).unwrap().is_ref();
3199
3200                Ok(self.compiled_form_size(c, false, root_counter)? + self.compiled_form_body_size(b, true)? + 2 + needs_deref as usize)
3201            },
3202
3203            DoBlock(_, b, _) => {
3204                *root_counter += root as usize; // Add drop instruction
3205
3206                Ok(self.compiled_form_body_size(b, true)?)
3207            }
3208
3209            Tuple(_, b) => {            
3210                *root_counter += root as usize; // Add drop instruction
3211
3212                Ok(1 + self.compiled_form_body_size(b, false)?)
3213            },
3214
3215            FunctionCall(_, id, t, a) => {
3216                *root_counter += root as usize; // Add drop instruction
3217
3218                let args_types = a.iter().map(|i| self.infer_type(i)).collect::<Result<Vec<_>, _>>()?;
3219                
3220                let ov_id = self.cache.overloads.functions.get_checked(&(*id, args_types.clone(), t.clone())).unwrap();
3221                let (opcode, offset) = self.cache.opcodes.functions.get_checked(&(*id, ov_id)).unwrap_or((CompiledRynaExpr::Halt, 0));
3222
3223                if root && opcode.needs_no_drop() {
3224                    *root_counter -= 1; // No drop for Inc
3225                }
3226
3227                let mut dtor_offset = 0;
3228
3229                if self.is_dtor_id(*id) {
3230                    if let Some(_) = self.get_destructor_variable(&a[0]) {
3231                        dtor_offset += 1;
3232                    }
3233                }
3234
3235                Ok(self.compiled_form_body_size(a, false)? + 1 + offset + dtor_offset)
3236            }, 
3237
3238            _ => unreachable!("{:?}", expr)
3239        }
3240    }
3241
3242    pub fn compiled_form_body_size(&self, lines: &Vec<RynaExpr>, root: bool) -> Result<usize, RynaError> {
3243        let mut counter = 0;
3244        let mut res = 0;
3245
3246        for i in lines {
3247            res += self.compiled_form_size(i, root, &mut counter)?;
3248        }
3249
3250        Ok(res + counter)
3251    }
3252
3253    pub fn compiled_literal_size(obj: &Object) -> usize {
3254        match obj.get_type() {
3255            Type::Empty |
3256            Type::Basic(INT_ID) |
3257            Type::Basic(FLOAT_ID) |
3258            Type::Basic(BOOL_ID) |
3259            Type::Basic(STR_ID) => 1,
3260
3261            Type::Basic(_) => {
3262                let obj_t = obj.get::<TypeInstance>();
3263                let mut res = 1;
3264
3265                for i in obj_t.attributes.iter().rev() {
3266                    res += RynaContext::compiled_literal_size(i);
3267                }
3268
3269                res
3270            },
3271
3272            Type::Template(ARR_ID, _) => {
3273                let obj_t = obj.get::<RynaArray>();
3274                let mut res = 1;
3275
3276                for i in obj_t.elements.iter().rev() {
3277                    res += RynaContext::compiled_literal_size(i);
3278                }
3279
3280                res
3281            },
3282
3283            _ => 1
3284        }
3285    }
3286
3287    pub fn compile_literal(obj: &Object) -> Vec<RynaInstruction> {
3288        match obj.get_type() {
3289            Type::Empty => vec!(RynaInstruction::from(CompiledRynaExpr::Empty)),
3290            
3291            Type::Basic(INT_ID) => vec!(RynaInstruction::from(CompiledRynaExpr::Int(obj.get::<Integer>().clone()))),
3292            Type::Basic(FLOAT_ID) => vec!(RynaInstruction::from(CompiledRynaExpr::Float(*obj.get::<f64>()))),
3293            Type::Basic(BOOL_ID) => vec!(RynaInstruction::from(CompiledRynaExpr::Bool(*obj.get::<bool>()))),
3294            Type::Basic(STR_ID) => vec!(RynaInstruction::from(CompiledRynaExpr::Str(obj.get::<String>().clone()))),
3295
3296            Type::Basic(id) => {
3297                let obj_t = obj.get::<TypeInstance>();
3298                let mut res = vec!();
3299
3300                for i in obj_t.attributes.iter().rev() {
3301                    res.extend(RynaContext::compile_literal(i));
3302                }
3303
3304                res.push(RynaInstruction::from(CompiledRynaExpr::Construct(id, obj_t.attributes.len(), obj_t.params.clone())));
3305
3306                res
3307            },
3308
3309            Type::Template(ARR_ID, _) => {
3310                let obj_t = obj.get::<RynaArray>();
3311                let mut res = vec!();
3312
3313                for i in obj_t.elements.iter().rev() {
3314                    res.extend(RynaContext::compile_literal(i));
3315                }
3316
3317                res.push(RynaInstruction::from(CompiledRynaExpr::Array(obj_t.elements.len(), *obj_t.elem_type.clone())));
3318
3319                res
3320            },
3321
3322            _ => unreachable!()
3323        }
3324    }
3325
3326    pub fn compiled_form_expr(
3327        &self, expr: &RynaExpr,
3328        root: bool
3329    ) -> Result<Vec<RynaInstruction>, RynaError> {
3330        return match expr {
3331            RynaExpr::Break(l) => {
3332                Ok(vec!(
3333                    RynaInstruction::from(CompiledRynaExpr::Placeholder(PlaceholderType::Break)).set_loc(l) // Placeholder
3334                ))
3335            }
3336            
3337            RynaExpr::Continue(l) => {
3338                Ok(vec!(
3339                    RynaInstruction::from(CompiledRynaExpr::Placeholder(PlaceholderType::Continue)).set_loc(l) // Placeholder
3340                ))
3341            }
3342
3343            RynaExpr::Literal(l, obj) => {
3344                let mut res = RynaContext::compile_literal(obj);
3345                
3346                if root { // Drop if the return value is unused
3347                    res.push(RynaInstruction::from(CompiledRynaExpr::Drop));
3348                }
3349
3350                Ok(res.into_iter().map(|i| i.set_loc(l)).collect())
3351            },
3352
3353            RynaExpr::AttributeAccess(l, e, att_idx) => {
3354                let mut res = self.compiled_form_expr(e, root)?;
3355                let arg_type = self.infer_type(e)?;
3356
3357                if let Type::Basic(id) | Type::Template(id, _) = arg_type.deref_type() {
3358                    let mut att_type = self.type_templates[*id].attributes[*att_idx].1.clone();
3359
3360                    // Subtitute template parameters if needed
3361                    if let Type::Template(_, ts) = arg_type.deref_type() {
3362                        att_type = att_type.sub_templates(&ts.iter().cloned().enumerate().collect());
3363                    }
3364                    
3365                    let opcode = match (&arg_type, &att_type) {
3366                        (Type::MutRef(_), Type::Ref(_)) => CompiledRynaExpr::AttributeRef(*att_idx),
3367                        (Type::MutRef(_), _) => CompiledRynaExpr::AttributeMut(*att_idx),
3368                        (Type::Ref(_), _) => CompiledRynaExpr::AttributeRef(*att_idx),
3369                        (_, _) => CompiledRynaExpr::AttributeMove(*att_idx)
3370                    };
3371
3372                    res.push(RynaInstruction::from(opcode).set_loc(l));
3373                
3374                    if root { // Drop if the return value is unused
3375                        res.push(RynaInstruction::from(CompiledRynaExpr::Drop).set_loc(l));
3376                    }
3377
3378                    Ok(res)
3379
3380                } else {
3381                    unreachable!()
3382                }
3383            }
3384
3385            RynaExpr::CompiledLambda(l, i, c, a, r, _) => {
3386                let mut res = vec!();
3387
3388                for (_, i) in c.iter().rev() {
3389                    res.extend(self.compiled_form_expr(i, false)?);
3390                }
3391
3392                res.push(RynaInstruction::from(CompiledRynaExpr::Lambda(
3393                    *self.lambda_positions.get(i).unwrap(),
3394                    c.len(),
3395                    if a.len() == 1 && !matches!(a[0].1, Type::And(..)) {
3396                        a[0].1.clone()
3397
3398                    } else {
3399                        Type::And(a.iter().map(|(_, t)| t).cloned().collect())
3400                    },
3401                    r.clone()
3402                )).set_loc(l));
3403                
3404                if root { // Drop if the return value is unused
3405                    res.push(RynaInstruction::from(CompiledRynaExpr::Drop).set_loc(l));
3406                }
3407
3408                Ok(res)
3409            },
3410
3411            RynaExpr::DoBlock(l, lines, _) => {
3412                let mut res = self.compiled_form_body(lines)?;
3413                let length = res.len();
3414
3415                // Transform returns into relative jumps
3416                for (idx, i) in res.iter_mut().enumerate() {
3417                    if let CompiledRynaExpr::Return = i.instruction {
3418                        i.instruction = CompiledRynaExpr::RelativeJump((length - idx) as i32);
3419                    }
3420                }
3421                
3422                if root { // Drop if the return value is unused
3423                    res.push(RynaInstruction::from(CompiledRynaExpr::Drop).set_loc(l));
3424                }
3425
3426                Ok(res)
3427            }
3428
3429            RynaExpr::Tuple(l, e) => {
3430                let mut res = vec!();
3431
3432                for i in e.iter().rev() {
3433                    res.extend(self.compiled_form_expr(i, false)?);
3434                }
3435
3436                res.push(RynaInstruction::from(CompiledRynaExpr::Tuple(e.len())).set_loc(l));
3437                
3438                if root { // Drop if the return value is unused
3439                    res.push(RynaInstruction::from(CompiledRynaExpr::Drop).set_loc(l));
3440                }
3441
3442                Ok(res)
3443            }
3444
3445            RynaExpr::Variable(l, id, _, t, g) => {
3446                let mut res = vec!(
3447                    if t.is_ref() {
3448                        RynaInstruction::new_with_type(
3449                            CompiledRynaExpr::CloneVariable(*id, *g), "".into(), t.clone()
3450                        ).set_loc(l)
3451    
3452                    } else {
3453                        RynaInstruction::new_with_type(
3454                            CompiledRynaExpr::GetVariable(*id, *g), "".into(), t.clone()
3455                        ).set_loc(l)    
3456                    }
3457                );
3458                
3459                if root { // Drop if the return value is unused
3460                    res.push(RynaInstruction::from(CompiledRynaExpr::Drop).set_loc(l));
3461                }
3462
3463                Ok(res)
3464            }, 
3465
3466            RynaExpr::AttributeAssignment(l, a, b, att_idx) => {
3467                let mut res = self.compiled_form_expr(a, false)?;
3468                res.append(&mut self.compiled_form_expr(b, false)?);
3469
3470                res.push(RynaInstruction::from(CompiledRynaExpr::AttributeAssign(*att_idx)).set_loc(l));
3471
3472                Ok(res)
3473            }
3474
3475            RynaExpr::CompiledVariableDefinition(l, id, _, t, e, g) | RynaExpr::CompiledVariableAssignment(l, id, _, t, e, g) => {
3476                let mut res = self.compiled_form_expr(e, false)?;
3477                res.push(RynaInstruction::new_with_type(
3478                    CompiledRynaExpr::StoreVariable(*id, *g),
3479                    String::new(),
3480                    t.clone()
3481                ).set_loc(l));
3482
3483                Ok(res)
3484            },
3485
3486            RynaExpr::UnaryOperation(l, id, t, e) => {
3487                let mut res = self.compiled_form_expr(e, false)?;
3488
3489                let i_t = self.infer_type(e)?;
3490
3491                let ov_id = self.cache.overloads.unary.get_checked(&(*id, vec!(i_t.clone()), t.clone())).unwrap();
3492
3493                if let Some(pos) = self.cache.locations.unary.get_checked(&(*id, vec!(i_t.clone()), t.clone())) {
3494                    res.push(RynaInstruction::from(CompiledRynaExpr::Call(pos)).set_loc(l));
3495
3496                } else if let Some((opcode, _)) = self.cache.opcodes.unary.get_checked(&(*id, ov_id)) {                    
3497                    // Deref if necessary
3498                    if opcode.needs_deref() && i_t.is_ref() {
3499                        res.push(RynaInstruction::from(CompiledRynaExpr::Deref).set_loc(l));
3500                    }
3501
3502                    // Convert to float if necessary
3503                    if opcode.needs_float() {
3504                        if let Type::Basic(INT_ID) = i_t.deref_type() {
3505                            res.push(RynaInstruction::from(CompiledRynaExpr::ToFloat).set_loc(l));
3506                        }
3507                    }
3508
3509                    res.push(RynaInstruction::from(opcode).set_loc(l));
3510
3511                } else {
3512                    res.push(RynaInstruction::from(CompiledRynaExpr::UnaryOperatorCall(*id, ov_id, t.clone())).set_loc(l));
3513                }   
3514
3515                if root { // Drop if the return value is unused
3516                    res.push(RynaInstruction::from(CompiledRynaExpr::Drop).set_loc(l));
3517                }
3518
3519                Ok(res)
3520            },
3521
3522            RynaExpr::BinaryOperation(l, id, t, a, b) => {
3523                let mut res_a = self.compiled_form_expr(b, false)?;
3524                let mut res_b = self.compiled_form_expr(a, false)?;
3525                
3526                let a_t = self.infer_type(a)?;
3527                let b_t = self.infer_type(b)?;
3528
3529                let ov_id = self.cache.overloads.binary.get_checked(&(*id, vec!(a_t.clone(), b_t.clone()), t.clone())).unwrap();
3530
3531                let res_op;
3532
3533                // Short circuit
3534                let mut short_circuit = false;
3535                let mut short_circuit_on = true;
3536                let mut translated_opcode = CompiledRynaExpr::Halt; // Invalid opcode for now
3537
3538                if let Some(pos) = self.cache.locations.binary.get_checked(&(*id, vec!(a_t.clone(), b_t.clone()), t.clone())) {
3539                    res_op = RynaInstruction::from(CompiledRynaExpr::Call(pos)).set_loc(l);
3540
3541                } else {
3542                    if (*id == AND_BINOP_ID || *id == OR_BINOP_ID) && *a_t.deref_type() == BOOL && *b_t.deref_type() == BOOL {
3543                        short_circuit = true;
3544                        short_circuit_on = *id == OR_BINOP_ID; // True on OR and false on AND
3545                    }
3546
3547                    if let Some((opcode, _)) = self.cache.opcodes.binary.get_checked(&(*id, ov_id)) {
3548                        translated_opcode = opcode.clone();
3549
3550                        // Deref if necessary
3551                        if opcode.needs_deref() {
3552                            if a_t.is_ref() {
3553                                res_b.push(RynaInstruction::from(CompiledRynaExpr::Deref).set_loc(l));
3554                            }
3555        
3556                            if b_t.is_ref() {
3557                                res_a.push(RynaInstruction::from(CompiledRynaExpr::Deref).set_loc(l));
3558                            }
3559                        }
3560    
3561                        // Convert to float if necessary
3562                        if opcode.needs_float() {
3563                            if let Type::Basic(INT_ID) = a_t.deref_type() {
3564                                res_b.push(RynaInstruction::from(CompiledRynaExpr::ToFloat).set_loc(l));
3565                            }
3566    
3567                            if let Type::Basic(INT_ID) = b_t.deref_type() {
3568                                res_a.push(RynaInstruction::from(CompiledRynaExpr::ToFloat).set_loc(l));
3569                            }
3570                        }
3571
3572                        res_op = RynaInstruction::from(opcode).set_loc(l);
3573
3574                    } else {
3575                        res_op = RynaInstruction::from(CompiledRynaExpr::BinaryOperatorCall(*id, ov_id, t.clone())).set_loc(l);
3576                    }
3577                }
3578                
3579                let mut res;
3580
3581                if short_circuit {
3582                    res = res_b;
3583
3584                    if short_circuit_on {
3585                        res.push(RynaInstruction::from(CompiledRynaExpr::RelativeJumpIfTrue(res_a.len() + 2, true)).set_loc(l));
3586
3587                    } else {
3588                        res.push(RynaInstruction::from(CompiledRynaExpr::RelativeJumpIfFalse(res_a.len() + 2, true)).set_loc(l));
3589                    }
3590
3591                    res.append(&mut res_a);
3592    
3593                } else {
3594                    res = res_a;
3595                    res.append(&mut res_b);
3596                }
3597
3598                res.push(res_op);    
3599
3600                if root && !translated_opcode.needs_no_drop() { // Drop if the return value is unused
3601                    res.push(RynaInstruction::from(CompiledRynaExpr::Drop).set_loc(l));
3602                }
3603
3604                Ok(res)
3605            },
3606
3607            RynaExpr::NaryOperation(l, id, t, a, b) => {
3608                let mut res = vec!();
3609
3610                for i in b.iter().rev() {
3611                    res.extend(self.compiled_form_expr(i, false)?);
3612                }
3613                
3614                res.extend(self.compiled_form_expr(a, false)?);
3615
3616                let a_t = self.infer_type(a)?;
3617                let b_t = b.iter().map(|i| self.infer_type(i)).collect::<Result<Vec<_>, _>>()?;
3618
3619                let mut arg_types = vec!(a_t.clone());
3620                arg_types.extend(b_t.iter().cloned());
3621
3622                let ov_id = self.cache.overloads.nary.get_checked(&(*id, arg_types.clone(), t.clone())).unwrap();
3623
3624                if let Some(pos) = self.cache.locations.nary.get_checked(&(*id, arg_types, t.clone())) {
3625                    res.push(RynaInstruction::from(CompiledRynaExpr::Call(pos)).set_loc(l));
3626
3627                } else if let Some((opcode, _)) = self.cache.opcodes.nary.get_checked(&(*id, ov_id)) {
3628                    res.push(RynaInstruction::from(opcode).set_loc(l));
3629                
3630                } else {                    
3631                    res.push(RynaInstruction::from(CompiledRynaExpr::NaryOperatorCall(*id, ov_id, t.clone())).set_loc(l));
3632                }   
3633
3634                if root { // Drop if the return value is unused
3635                    res.push(RynaInstruction::from(CompiledRynaExpr::Drop).set_loc(l));
3636                }
3637
3638                Ok(res)
3639            },
3640
3641            RynaExpr::If(l, ih, ib, ei, e) => {
3642                let mut res = self.compiled_form_expr(ih, false)?;
3643                let if_body = self.compiled_form_body(ib)?;
3644
3645                if self.infer_type(ih).unwrap().is_ref() {
3646                    res.push(RynaInstruction::from(CompiledRynaExpr::Deref).set_loc(l));
3647                }
3648
3649                res.push(RynaInstruction::from(CompiledRynaExpr::RelativeJumpIfFalse(if_body.len() + 2, false)));
3650                res.extend(if_body);
3651
3652                let mut elif = vec!();
3653                let mut else_body = vec!();
3654                let mut complete_size = 1;
3655
3656                for (h, b) in ei {
3657                    let cond = self.compiled_form_expr(h, false)?;
3658                    let body = self.compiled_form_body(b)?;
3659                    let needs_deref = self.infer_type(h).unwrap().is_ref();
3660                    
3661                    complete_size += cond.len() + body.len() + 2 + needs_deref as usize;
3662
3663                    elif.push((cond, body, needs_deref));
3664                }
3665
3666                if let Some(b) = e {
3667                    else_body = self.compiled_form_body(b)?;
3668                    complete_size += else_body.len();
3669                }
3670
3671                res.push(RynaInstruction::from(CompiledRynaExpr::RelativeJump(complete_size as i32)));
3672
3673                for (cond, body, needs_deref) in elif {
3674                    complete_size -= cond.len() + body.len() + 2;
3675
3676                    res.extend(cond);
3677                    
3678                    if needs_deref {
3679                        res.push(RynaInstruction::from(CompiledRynaExpr::Deref));
3680                    }
3681
3682                    res.push(RynaInstruction::from(CompiledRynaExpr::RelativeJumpIfFalse(body.len() + 2, false)));
3683                    res.extend(body);
3684                    res.push(RynaInstruction::from(CompiledRynaExpr::RelativeJump(complete_size as i32)));
3685                }
3686
3687                res.extend(else_body);
3688
3689                Ok(res)
3690            },
3691
3692            RynaExpr::While(l, c, b) => {
3693                // Start with the condition
3694                let mut res = self.compiled_form_expr(c, false)?;
3695                let while_body = self.compiled_form_body(b)?;
3696
3697                if self.infer_type(c).unwrap().is_ref() {
3698                    res.push(RynaInstruction::from(CompiledRynaExpr::Deref).set_loc(l));
3699                }
3700                
3701                // Add while body
3702                let beginning_jmp = CompiledRynaExpr::RelativeJump(-(while_body.len() as i32 + res.len() as i32 + 1));
3703
3704                res.push(RynaInstruction::from(CompiledRynaExpr::RelativeJumpIfFalse(while_body.len() + 2, false)));
3705                res.extend(while_body);
3706
3707                // Jump to the beginning of the loop
3708                res.push(RynaInstruction::from(beginning_jmp));
3709
3710                // Transform breaks and continues into relative jumps
3711                let length = res.len();
3712
3713                for (idx, i) in res.iter_mut().enumerate() {
3714                    if let CompiledRynaExpr::Placeholder(PlaceholderType::Break) = i.instruction {
3715                        i.instruction = CompiledRynaExpr::RelativeJump((length - idx) as i32);
3716                    
3717                    } else if let CompiledRynaExpr::Placeholder(PlaceholderType::Continue) = i.instruction {
3718                        i.instruction = CompiledRynaExpr::RelativeJump(-(idx as i32));
3719                    }
3720                }
3721
3722                Ok(res)
3723            },
3724
3725            RynaExpr::CompiledFor(l, it_var_id, elem_var_id, _, c, b) => {
3726                let t = self.infer_type(c)?;
3727
3728                let mut res = self.compiled_form_expr(c, false)?;
3729
3730                // Get "iterator", "next" and "is_consumed" function overloads and check them
3731                let (it_ov_id, it_type, it_native, it_args) = self.get_first_function_overload(ITERATOR_FUNC_ID, vec!(t.clone()), None, true, l)?;
3732
3733                let it_mut = Type::MutRef(Box::new(it_type.clone()));
3734
3735                let (next_ov_id, _, next_native, next_args) = self.get_first_function_overload(NEXT_FUNC_ID, vec!(it_mut.clone()), None, true, l)?;
3736                let (consumed_ov_id, consumed_res, consumed_native, consumed_args) = self.get_first_function_overload(IS_CONSUMED_FUNC_ID, vec!(it_mut.clone()), None, true, l)?;
3737
3738                if let Type::Basic(BOOL_ID) = consumed_res {
3739                    let for_body = self.compiled_form_body(b)?;
3740                    let for_body_len = for_body.len();
3741
3742                    // Convert the iterable into an iterator
3743                    if it_native {
3744                        res.push(RynaInstruction::from(CompiledRynaExpr::NativeFunctionCall(ITERATOR_FUNC_ID, it_ov_id, it_args)).set_loc(l));
3745
3746                    } else {
3747                        let pos = self.cache.locations.functions.get_checked(&(ITERATOR_FUNC_ID, vec!(t.clone()), it_args.clone())).unwrap();
3748                        res.push(RynaInstruction::from(CompiledRynaExpr::Call(pos)).set_loc(l));
3749                    }
3750
3751                    // Store the iterator
3752                    res.push(RynaInstruction::from(CompiledRynaExpr::StoreVariable(*it_var_id, false)).set_loc(l));
3753
3754                    // Check end of iterator
3755                    res.push(RynaInstruction::from(CompiledRynaExpr::GetVariable(*it_var_id, false)).set_loc(l));
3756
3757                    if consumed_native {
3758                        res.push(RynaInstruction::from(CompiledRynaExpr::NativeFunctionCall(IS_CONSUMED_FUNC_ID, consumed_ov_id, consumed_args)).set_loc(l));
3759
3760                    } else {
3761                        let pos = self.cache.locations.functions.get_checked(&(IS_CONSUMED_FUNC_ID, vec!(it_mut.clone()), consumed_args.clone())).unwrap();
3762                        res.push(RynaInstruction::from(CompiledRynaExpr::Call(pos)).set_loc(l));
3763                    }                                    
3764
3765                    // Jump to end of loop
3766                    res.push(RynaInstruction::from(CompiledRynaExpr::RelativeJumpIfTrue(for_body_len + 5, false)));
3767
3768                    // Get next value
3769                    res.push(RynaInstruction::from(CompiledRynaExpr::GetVariable(*it_var_id, false)).set_loc(l));
3770
3771                    if next_native {
3772                        res.push(RynaInstruction::from(CompiledRynaExpr::NativeFunctionCall(NEXT_FUNC_ID, next_ov_id, next_args)).set_loc(l));
3773
3774                    } else {
3775                        let pos = self.cache.locations.functions.get_checked(&(NEXT_FUNC_ID, vec!(it_mut.clone()), next_args.clone())).unwrap();
3776                        res.push(RynaInstruction::from(CompiledRynaExpr::Call(pos)).set_loc(l));
3777                    }
3778
3779                    // Store next value
3780                    res.push(RynaInstruction::from(CompiledRynaExpr::StoreVariable(*elem_var_id, false)).set_loc(l));
3781
3782                    // Add for body
3783                    let beginning_jmp = CompiledRynaExpr::RelativeJump(-(for_body_len as i32 + 6));
3784
3785                    res.extend(for_body);
3786
3787                    // Jump to the beginning of the loop
3788                    res.push(RynaInstruction::from(beginning_jmp));
3789
3790                    // Transform breaks and continues into relative jumps
3791                    let length = res.len();
3792
3793                    for (idx, i) in res.iter_mut().enumerate() {
3794                        if let CompiledRynaExpr::Placeholder(PlaceholderType::Break) = i.instruction {
3795                            i.instruction = CompiledRynaExpr::RelativeJump((length - idx) as i32);
3796                        
3797                        } else if let CompiledRynaExpr::Placeholder(PlaceholderType::Continue) = i.instruction {
3798                            i.instruction = CompiledRynaExpr::RelativeJump((length - idx) as i32 - 1);
3799                        }
3800                    }
3801
3802                    Ok(res)
3803
3804                } else {
3805                    Err(RynaError::compiler_error(format!("Funtion overload is_consumed({}) returns {} (expected Bool)", it_mut.get_name(self), consumed_res.get_name(self)), l, vec!()))
3806                }
3807            },
3808
3809            RynaExpr::Return(l, e) => {
3810                let mut res = self.compiled_form_expr(e, false)?;
3811                res.push(RynaInstruction::from(CompiledRynaExpr::Return).set_loc(l));
3812
3813                Ok(res)
3814            },
3815
3816            RynaExpr::FunctionCall(l, id, t, a) => {
3817                let mut res = vec!();
3818
3819                for i in a.iter().rev() {
3820                    res.extend(self.compiled_form_expr(i, false)?);
3821                }
3822                
3823                let args_types = a.iter().map(|i| self.infer_type(i)).collect::<Result<Vec<_>, _>>()?;
3824                
3825                let ov_id = self.cache.overloads.functions.get_checked(&(*id, args_types.clone(), t.clone())).unwrap();
3826                let mut translated_opcode = CompiledRynaExpr::Halt; // Invalid opcode for now
3827
3828                if let Some(pos) = self.cache.locations.functions.get_checked(&(*id, args_types, t.clone())) {
3829                    if self.is_dtor_id(*id) {
3830                        res.push(RynaInstruction::from(CompiledRynaExpr::CallDestructor(pos)).set_loc(l));
3831
3832                        // Add variable drop
3833                        if let Some(var_idx) = self.get_destructor_variable(&a[0]) {
3834                            res.push(RynaInstruction::from(CompiledRynaExpr::DeleteVar(var_idx, false)).set_loc(l));
3835                        }
3836
3837                    } else {
3838                        res.push(RynaInstruction::from(CompiledRynaExpr::Call(pos)).set_loc(l));
3839                    }
3840
3841                } else if let Some((mut opcode, _)) = self.cache.opcodes.functions.get_checked(&(*id, ov_id)) {
3842                    // TODO: add conversions and derefs if necessary 
3843                    opcode = match opcode {
3844                        // Add type parameters to Construct opcodes
3845                        CompiledRynaExpr::Construct(id, length, _) => CompiledRynaExpr::Construct(id, length, t.clone()),
3846                        _ => opcode
3847                    };
3848
3849                    translated_opcode = opcode.clone();
3850
3851                    res.push(RynaInstruction::new_with_type(
3852                        opcode,
3853                        "".into(),
3854                        self.functions[*id].overloads[ov_id].ret.clone()
3855                    ).set_loc(l));
3856
3857                } else {
3858                    res.push(RynaInstruction::from(CompiledRynaExpr::NativeFunctionCall(*id, ov_id, t.clone())).set_loc(l));
3859                }
3860
3861                if root && !translated_opcode.needs_no_drop() { // Drop if the return value is unused
3862                    res.push(RynaInstruction::from(CompiledRynaExpr::Drop).set_loc(l));
3863                }
3864
3865                Ok(res)
3866            }
3867            
3868            _ => { Ok(vec!()) }
3869        };
3870    }
3871
3872    pub fn compiled_form_body(
3873        &self, lines: &[RynaExpr]
3874    ) -> Result<Vec<RynaInstruction>, RynaError> {
3875        return Ok(lines.iter().map(|i| self.compiled_form_expr(i, true)).flat_map(|i| i.unwrap()).collect());
3876    }
3877
3878    pub fn define_module_macro(&mut self, definition: RynaExpr, defined_macros: &mut FxHashSet<Location>) -> Result<bool, RynaError> {
3879        if let RynaExpr::Macro(l, an, n, t, p, m) = definition {
3880            if !defined_macros.contains(&l) {
3881                if self.macros.iter().any(|i| i.name == n) {
3882                    return Err(RynaError::compiler_error(format!("Syntax with name '{n}' is already defined"), &l, vec!()));
3883                }
3884    
3885                self.macros.push(RynaMacro {
3886                    location: l.clone(),
3887                    annotations: an,
3888                    name: n,
3889                    m_type: t,
3890                    pattern: p,
3891                    generator: m,
3892                });
3893
3894                defined_macros.insert(l.clone());
3895
3896                return Ok(true);
3897            }
3898        }
3899
3900        Ok(false)
3901    }
3902
3903    pub fn define_module_class(&mut self, definition: RynaExpr) -> Result<(), RynaError> {
3904        match definition {
3905            RynaExpr::ClassDefinition(l, an, n, t, a, al, p) => {
3906                let err = self.implicit_syntax_check(&n, &t, &a, &p);
3907
3908                if let Err(msg) = err {
3909                    return Err(RynaError::compiler_error(msg, &l, vec!()));
3910                }
3911
3912                let n_templates = t.len();
3913                let arg_types = a.iter().map(|(_, t)| t.clone()).collect::<Vec<_>>();
3914
3915                let err = if self.get_type_template(&n).is_some() {
3916                    self.redefine_type(l.clone(), an.clone(), n.clone(), t, a.clone(), al, p, Some(
3917                        |ctx, c_type, s| {
3918                            if let Ok((_, o)) = ctx.parse_literal_type(c_type, Span::new(s.as_str()), &RefCell::default()) {
3919                                return Ok(o);
3920                            }
3921    
3922                            Err(format!("Unable to parse {} from {}", c_type.name, s))
3923                        }
3924                    ))
3925
3926                } else {
3927                    self.define_type(l.clone(), an.clone(), n.clone(), t, a.clone(), al, p, Some(
3928                        |ctx, c_type, s| {
3929                            if let Ok((_, o)) = ctx.parse_literal_type(c_type, Span::new(s.as_str()), &RefCell::default()) {
3930                                return Ok(o);
3931                            }
3932    
3933                            Err(format!("Unable to parse {} from {}", c_type.name, s))
3934                        }
3935                    ))
3936                };
3937
3938                if let Err(msg) = err {
3939                    return Err(RynaError::compiler_error(msg, &l, vec!()));
3940                }
3941
3942                let func_id = self.define_function(n.clone()).unwrap_or_default(); // Define constructor function
3943                let class_id = self.get_type_id(n).unwrap();
3944
3945                if n_templates == 0 {
3946                    // Define constructor instance
3947                    let res = self.define_native_function_overload(func_id, 0, &arg_types, Type::Basic(class_id), |_, r, a, _| {
3948                        if let Type::Basic(id) = r {
3949                            return Ok(Object::new(TypeInstance {
3950                                id: *id,
3951                                params: vec!(),
3952                                attributes: a
3953                            }))
3954                        }
3955
3956                        unreachable!();
3957                    });
3958
3959                    if let Err(msg) = res {
3960                        return Err(RynaError::compiler_error(msg, &l, vec!()));
3961                    
3962                    } else {
3963                        self.cache.opcodes.functions.insert((func_id, res.unwrap()), (CompiledRynaExpr::Construct(class_id, a.len(), vec!()), 0));
3964                    }
3965
3966                } else {
3967                    let templ = (0..n_templates).map(|i| Type::TemplateParam(i, vec!())).collect::<Vec<_>>();
3968
3969                    // Define constructor instance
3970                    let res = self.define_native_function_overload(func_id, n_templates, &arg_types, Type::Template(class_id, templ.clone()), |t, r, a, _| {
3971                        if let Type::Template(id, _) = r {
3972                            return Ok(Object::new(TypeInstance {
3973                                id: *id,
3974                                params: t.clone(),
3975                                attributes: a
3976                            }))
3977                        }
3978
3979                        unreachable!();
3980                    });
3981
3982                    if let Err(msg) = res {
3983                        return Err(RynaError::compiler_error(msg, &l, vec!()));
3984
3985                    } else {
3986                        self.cache.opcodes.functions.insert((func_id, res.unwrap()), (CompiledRynaExpr::Construct(class_id, a.len(), vec!()), 0));
3987                    }
3988                }
3989            },
3990
3991            _ => unreachable!()
3992        }
3993
3994        Ok(())
3995    }
3996
3997    pub fn define_module_macros(&mut self, code: &String) -> Result<(), RynaError> {
3998        let mut defined_macros = FxHashSet::default();
3999        let mut changed = true;
4000
4001        while changed {
4002            changed = false;
4003
4004            let ops = self.ryna_macros_parser(Span::new(code));
4005        
4006            if let Err(err) = ops {
4007                return Err(RynaError::from(err).in_module(self.module_name.clone()));
4008            }
4009            
4010            for i in ops.unwrap().1 {
4011                changed |= self.define_module_macro(i, &mut defined_macros)?;
4012            }
4013        }
4014
4015        Ok(())
4016    }
4017
4018    pub fn define_module_classes(&mut self, code: &String) -> Result<(), RynaError> {
4019        if let Ok((_, i_names)) = self.ryna_interface_definition_names_parser(Span::new(code)) {
4020            for i_name in i_names {
4021                self.define_interface(Location::none(), vec!(), i_name, vec!(), vec!(), vec!(), vec!(), vec!()).unwrap();
4022            }
4023
4024            if let Ok((_, names)) = self.ryna_class_names_parser(Span::new(code)) {
4025                for name in names {
4026                    self.define_type(Location::none(), vec!(), name, vec!(), vec!(), None, vec!(), None).unwrap();
4027                }
4028    
4029                let interfaces = self.ryna_interface_definition_parser(Span::new(code))?;
4030
4031                for i in interfaces.1 {
4032                    if let RynaExpr::InterfaceDefinition(l, an, n, t, v, u, b, nr) = i {
4033                        self.redefine_interface(l, an, n, t, v, u, b, nr).unwrap();
4034                    }
4035                }
4036
4037                let interfaces_impl = self.ryna_interface_implementation_parser(Span::new(code))?;
4038
4039                for i in interfaces_impl.1 {
4040                    if let RynaExpr::InterfaceImplementation(_, tm, t, n, i_tm) = i {
4041                        self.define_interface_impl(n, tm, t, i_tm).unwrap();
4042                    }
4043                }
4044
4045                let ops = self.ryna_class_parser(Span::new(code))?;
4046                
4047                for i in ops.1 {
4048                    self.define_module_class(i)?;
4049                }
4050            }
4051        }
4052
4053        Ok(())
4054    }
4055    
4056    pub fn define_module_operators(&mut self, code: &String) -> Result<(), RynaError> {
4057        let ops = self.ryna_operators_parser(Span::new(code));
4058
4059        if let Err(err) = ops {
4060            return Err(RynaError::from(err).in_module(self.module_name.clone()));
4061        }
4062
4063        for i in ops.unwrap().1 {
4064            let (l, err) = match &i {
4065                RynaExpr::PrefixOperatorDefinition(l, n, p) => (l, self.define_unary_operator(n.clone(), true, *p)),
4066                RynaExpr::PostfixOperatorDefinition(l, n, p) => (l, self.define_unary_operator(n.clone(), false, *p)),
4067                RynaExpr::BinaryOperatorDefinition(l, n, f, p) => (l, self.define_binary_operator(n.clone(), *f, *p)),
4068                RynaExpr::NaryOperatorDefinition(l, o, c, p) => (l, self.define_nary_operator(o.clone(), c.clone(), *p)),
4069
4070                _ => unreachable!()
4071            };
4072
4073            if let Err(msg) = err {
4074                return Err(RynaError::compiler_error(msg, l, vec!()));
4075            }
4076        }
4077
4078        Ok(())
4079    }
4080    
4081    pub fn define_module_functions(&mut self, code: &String) -> Result<(), RynaError> {
4082        let ops = self.ryna_function_headers_parser(Span::new(code));
4083
4084        if let Err(err) = ops {
4085            return Err(RynaError::from(err).in_module(self.module_name.clone()));
4086        }
4087
4088        for i in ops.unwrap().1 {
4089            self.define_function(i.0).unwrap_or_default();
4090        }
4091
4092        Ok(())
4093    }
4094    
4095    pub fn define_module_operations(&mut self, code: &String) -> Result<(), RynaError> {
4096        let ops = self.ryna_operations_parser(Span::new(code));
4097
4098        if let Err(err) = ops {
4099            return Err(RynaError::from(err).in_module(self.module_name.clone()));
4100        }
4101
4102        for i in ops.unwrap().1 {
4103            let (l, err) = match &i {
4104                RynaExpr::PrefixOperationDefinition(l, an, id, tm, _a, t, r, _) |
4105                RynaExpr::PostfixOperationDefinition(l, an, id, tm, _a, t, r, _) => (l, self.define_unary_operation(l.clone(), an.clone(), *id, tm.len(), t.clone(), r.clone(), None)),
4106                RynaExpr::BinaryOperationDefinition(l, an, id, tm, (_a, ta), (_b, tb), r, _) => (l, self.define_binary_operation(l.clone(), an.clone(), *id, tm.len(), ta.clone(), tb.clone(), r.clone(), None)),
4107                RynaExpr::NaryOperationDefinition(l, an, id, tm, (_a, ta), v, r, _) => (l, self.define_nary_operation(l.clone(), an.clone(), *id, tm.len(), ta.clone(), &v.iter().map(|(_, t)| t.clone()).collect::<Vec<_>>(), r.clone(), None)),
4108
4109                _ => unreachable!()
4110            };
4111
4112            if let Err(msg) = err {
4113                return Err(RynaError::compiler_error(msg, l, vec!()));
4114            }
4115        }
4116
4117        Ok(())
4118    }
4119
4120    pub fn define_module_function_overloads(&mut self, lines: &Vec<RynaExpr>) -> Result<(), RynaError> {
4121        for i in lines {
4122            if let RynaExpr::FunctionDefinition(l, an, id, t, a, r, _)  = i {
4123                let arg_types = a.iter().map(|(_, t)| t.clone()).collect::<Vec<_>>();
4124                let err = self.define_function_overload(l.clone(), an.clone(), *id, t.len(), &arg_types, r.clone(), None);
4125
4126                if let Err(msg) = err {
4127                    return Err(RynaError::compiler_error(msg, l, vec!()));
4128                }
4129            }
4130        }
4131
4132        Ok(())
4133    }
4134
4135    pub fn parse_ryna_module(&mut self, code: &String) -> Result<Vec<RynaExpr>, RynaError> {
4136        return match self.ryna_parser(Span::new(code)) {
4137            Ok((_, lines)) => Ok(lines),
4138
4139            Err(nom::Err::Error(error)) |
4140            Err(nom::Err::Failure(error)) => Err(RynaError::from(error).in_module(self.module_name.clone())),
4141
4142            _ => unreachable!()
4143        };
4144    }
4145
4146    pub fn map_ryna_interface(&mut self, other: &RynaContext, id: usize, id_mapper: &mut IdMapper, l: &Location) -> Result<usize, String> {
4147        let other_i = &other.interfaces[id];
4148        let i_name = &other_i.name;
4149
4150        if !id_mapper.interfaces.contains_key(&id) {
4151            let interface_id;
4152
4153            // If the function has another id in the target context
4154            if let Some(f) = self.get_interface(i_name) {
4155                interface_id = f.id;
4156
4157            } else { // Else the function needs to be defined
4158                interface_id = self.interfaces.len();
4159                id_mapper.interfaces.entry(id).or_insert(interface_id);
4160
4161                let mapped_fns = other_i.fns.iter().map(|(an, n, t, a, r)| {
4162                    (
4163                        an.clone(),
4164                        n.clone(),
4165                        t.clone(),
4166                        a.iter().map(|(n, t)| (n.clone(), t.map_type(self, other, id_mapper, l))).collect(),
4167                        r.map_type(self, other, id_mapper, l)
4168                    )
4169                }).collect::<Vec<_>>();
4170
4171                let mapped_uns = other_i.uns.iter().map(|(an, id, tm, a, at, ret)| {
4172                    Result::<_, RynaError>::Ok((
4173                        an.clone(),
4174                        self.map_ryna_unary_operator(other, *id, id_mapper, l)?,
4175                        tm.clone(),
4176                        a.clone(),
4177                        at.map_type(self, other, id_mapper, l),
4178                        ret.map_type(self, other, id_mapper, l)
4179                    ))
4180                }).collect::<Result<Vec<_>, _>>().unwrap();
4181
4182                let mapped_bin = other_i.bin.iter().map(|(an, id, tm, (a0, a0t), (a1, a1t), ret)| {
4183                    Result::<_, RynaError>::Ok((
4184                        an.clone(),
4185                        self.map_ryna_binary_operator(other, *id, id_mapper, l)?,
4186                        tm.clone(),
4187                        (a0.clone(), a0t.map_type(self, other, id_mapper, l)),
4188                        (a1.clone(), a1t.map_type(self, other, id_mapper, l)),
4189                        ret.map_type(self, other, id_mapper, l)
4190                    ))
4191                }).collect::<Result<Vec<_>, _>>().unwrap();
4192
4193                let mapped_nary = other_i.nary.iter().map(|(an, id, tm, (a0, a0t), a, ret)| {
4194                    Result::<_, RynaError>::Ok((
4195                        an.clone(),
4196                        self.map_ryna_binary_operator(other, *id, id_mapper, l)?,
4197                        tm.clone(),
4198                        (a0.clone(), a0t.map_type(self, other, id_mapper, l)),
4199                        a.iter().map(|(n, t)| (n.clone(), t.map_type(self, other, id_mapper, l))).collect(),
4200                        ret.map_type(self, other, id_mapper, l)
4201                    ))
4202                }).collect::<Result<Vec<_>, _>>().unwrap();
4203
4204                self.define_interface(other_i.location.clone(), other_i.annotations.clone(), i_name.clone(), other_i.params.clone(), mapped_fns, mapped_uns, mapped_bin, mapped_nary)?;
4205            }
4206
4207            return Ok(interface_id);
4208        }
4209
4210        Ok(id_mapper.interfaces[&id])
4211    }
4212
4213    pub fn map_ryna_class(&mut self, other: &RynaContext, id: usize, id_mapper: &mut IdMapper, l: &Location) -> Result<usize, String> {
4214        let other_cl = &other.type_templates[id];
4215        let c_name = &other_cl.name;
4216
4217        if !id_mapper.classes.contains_key(&id) {
4218            let class_id;
4219
4220            // If the function has another id in the target context
4221            if let Some(f) = self.get_type_template(c_name) {
4222                class_id = f.id;
4223
4224            } else { // Else the function needs to be defined
4225                class_id = self.type_templates.len();
4226                id_mapper.classes.entry(id).or_insert(class_id);
4227
4228                let mapped_attrs = other_cl.attributes.iter().map(|(n, t)| (n.clone(), t.map_type(self, other, id_mapper, l))).collect();
4229                let mapped_alias = other_cl.alias.as_ref().map(|i| i.map_type(self, other, id_mapper, l));
4230
4231                self.define_type(other_cl.location.clone(), other_cl.annotations.clone(), c_name.clone(), other_cl.params.clone(), mapped_attrs, mapped_alias, other_cl.patterns.clone(), other_cl.parser)?;
4232            }
4233
4234            return Ok(class_id);
4235        }
4236
4237        Ok(id_mapper.classes[&id])
4238    }
4239
4240    fn map_ryna_function(&mut self, other: &RynaContext, id: usize, id_mapper: &mut IdMapper, l: &Location) -> Result<usize, RynaError> {
4241        let f_name = &other.functions[id].name;
4242
4243        if !id_mapper.functions.contains_key(&id) {
4244            let fn_id;
4245
4246            // If the function has another id in the target context
4247            if let Some(f) = self.get_function(f_name) {
4248                fn_id = f.id;
4249
4250            } else { // Else the function needs to be defined
4251                fn_id = self.functions.len();
4252
4253                if let Err(err) = self.define_function(f_name.clone()) {
4254                    return Err(RynaError::compiler_error(err, l, vec!()));
4255                }
4256            }
4257
4258            return Ok(*id_mapper.functions.entry(id).or_insert(fn_id));
4259        }
4260
4261        Ok(id_mapper.functions[&id])
4262    }
4263
4264    fn map_ryna_unary_operator(&mut self, other: &RynaContext, id: usize, id_mapper: &mut IdMapper, l: &Location) -> Result<usize, RynaError> {
4265        if let Operator::Unary{representation: r, prefix, precedence, ..} = &other.unary_ops[id] {
4266            if !id_mapper.unary_operators.contains_key(&id) {
4267                let mapped_op_id;
4268    
4269                // If the function has another id in the target context
4270                if let Some((op_id, _)) = self.unary_ops.iter()
4271                                     .map(|op| if let Operator::Unary{id: op_id, representation: op_rep, ..} = op { (op_id, op_rep) } else { unreachable!() }).find(|(_, op_rep)| *op_rep == r) {
4272                    mapped_op_id = *op_id;
4273    
4274                } else { // Else the function needs to be defined
4275                    mapped_op_id = self.unary_ops.len();
4276
4277                    if let Err(err) = self.define_unary_operator(r.clone(), *prefix, *precedence) {
4278                        return Err(RynaError::compiler_error(err, l, vec!()));
4279                    }
4280                }
4281    
4282                return Ok(*id_mapper.unary_operators.entry(id).or_insert(mapped_op_id));
4283            }
4284        
4285        } else {
4286            return Err(RynaError::compiler_error(format!("Unable to find unary operator with id = {}", id), l, vec!()));
4287        }
4288
4289        Ok(id_mapper.unary_operators[&id])
4290    }
4291
4292    fn map_ryna_binary_operator(&mut self, other: &RynaContext, id: usize, id_mapper: &mut IdMapper, l: &Location) -> Result<usize, RynaError> {
4293        if let Operator::Binary{representation: r, right_associative, precedence, ..} = &other.binary_ops[id] {
4294            if !id_mapper.binary_operators.contains_key(&id) {
4295                let mapped_op_id;
4296    
4297                // If the function has another id in the target context
4298                if let Some((op_id, _)) = self.binary_ops.iter()
4299                                     .map(|op| if let Operator::Binary{id: op_id, representation: op_rep, ..} = op { (op_id, op_rep) } else { unreachable!() }).find(|(_, op_rep)| *op_rep == r) {
4300                    mapped_op_id = *op_id;
4301    
4302                } else { // Else the function needs to be defined
4303                    mapped_op_id = self.binary_ops.len();
4304
4305                    if let Err(err) = self.define_binary_operator(r.clone(), *right_associative, *precedence) {
4306                        return Err(RynaError::compiler_error(err, l, vec!()));
4307                    }
4308                }
4309    
4310                return Ok(*id_mapper.binary_operators.entry(id).or_insert(mapped_op_id));
4311            }
4312        
4313        } else {
4314            return Err(RynaError::compiler_error(format!("Unable to find binary operator with id = {}", id), l, vec!()));
4315        }
4316
4317        Ok(id_mapper.binary_operators[&id])
4318    }
4319
4320    fn map_ryna_nary_operator(&mut self, other: &RynaContext, id: usize, id_mapper: &mut IdMapper, l: &Location) -> Result<usize, RynaError> {
4321        if let Operator::Nary{open_rep: or, close_rep: cr, precedence, ..} = &other.nary_ops[id] {
4322            if !id_mapper.nary_operators.contains_key(&id) {
4323                let mapped_op_id;
4324    
4325                // If the function has another id in the target context
4326                if let Some((op_id, _, _)) = self.nary_ops.iter()
4327                                     .map(|op| if let Operator::Nary{id: op_id, open_rep: op_or, close_rep: op_cr, ..} = op { (op_id, op_or, op_cr) } else { unreachable!() }).find(|(_, op_or, op_cr)| *op_or == or && *op_cr == cr) {
4328                    mapped_op_id = *op_id;
4329    
4330                } else { // Else the function needs to be defined
4331                    mapped_op_id = self.binary_ops.len();
4332
4333                    if let Err(err) = self.define_nary_operator(or.clone(), cr.clone(), *precedence) {
4334                        return Err(RynaError::compiler_error(err, l, vec!()));
4335                    }
4336                }
4337    
4338                return Ok(*id_mapper.nary_operators.entry(id).or_insert(mapped_op_id));
4339            }
4340        
4341        } else {
4342            return Err(RynaError::compiler_error(format!("Unable to find binary operator with id = {}", id), l, vec!()));
4343        }
4344
4345        Ok(id_mapper.nary_operators[&id])
4346    }
4347
4348    pub fn map_ryna_expression(
4349        &mut self, expr: &mut RynaExpr, ctx: &RynaContext,
4350        id_mapper: &mut IdMapper
4351    ) -> Result<(), RynaError> {
4352        match expr {
4353            RynaExpr::Break(..) |
4354            RynaExpr::Continue(..) |
4355            RynaExpr::Literal(..) |
4356            RynaExpr::NameReference(..) |
4357            RynaExpr::PostfixOperatorDefinition(_, _, _) |
4358            RynaExpr::PrefixOperatorDefinition(_, _, _) |
4359            RynaExpr::BinaryOperatorDefinition(_, _, _, _) |
4360            RynaExpr::NaryOperatorDefinition(_, _, _, _) => {}
4361
4362            RynaExpr::VariableDefinition(l, _, t, e) => {
4363                *t = t.map_type(self, ctx, id_mapper, l);
4364
4365                self.map_ryna_expression(e, ctx, id_mapper)?;
4366            }
4367
4368            RynaExpr::VariableAssignment(_, _, e) => {
4369                self.map_ryna_expression(e, ctx, id_mapper)?;
4370            }
4371
4372            RynaExpr::Tuple(_, b) => {
4373                for arg in b {
4374                    self.map_ryna_expression(arg, ctx, id_mapper)?;
4375                }
4376            }
4377
4378            RynaExpr::DoBlock(l, b, t) => {
4379                *t = t.map_type(self, ctx, id_mapper, l);
4380
4381                for arg in b {
4382                    self.map_ryna_expression(arg, ctx, id_mapper)?;
4383                }
4384            }
4385
4386            RynaExpr::UnaryOperation(l, id, t, a) => {
4387                *id = self.map_ryna_unary_operator(ctx, *id, id_mapper, l)?;
4388
4389                *t = t.iter().map(|t| t.map_type(self, ctx, id_mapper, l)).collect();
4390
4391                self.map_ryna_expression(a, ctx, id_mapper)?;
4392            }
4393
4394            RynaExpr::BinaryOperation(l, id, t, a, b) => {
4395                *id = self.map_ryna_binary_operator(ctx, *id, id_mapper, l)?;
4396
4397                *t = t.iter().map(|t| t.map_type(self, ctx, id_mapper, l)).collect();
4398
4399                self.map_ryna_expression(a, ctx, id_mapper)?;
4400                self.map_ryna_expression(b, ctx, id_mapper)?;
4401            }
4402
4403            RynaExpr::NaryOperation(l, id, t, a, b) => {
4404                *id = self.map_ryna_nary_operator(ctx, *id, id_mapper, l)?;
4405
4406                *t = t.iter().map(|t| t.map_type(self, ctx, id_mapper, l)).collect();
4407
4408                self.map_ryna_expression(a, ctx, id_mapper)?;
4409
4410                for arg in b {
4411                    self.map_ryna_expression(arg, ctx, id_mapper)?;
4412                }
4413            }
4414
4415            RynaExpr::FunctionCall(l, id, t, args) => {
4416                *id = self.map_ryna_function(ctx, *id, id_mapper, l)?;
4417
4418                *t = t.iter().map(|t| t.map_type(self, ctx, id_mapper, l)).collect();
4419
4420                for arg in args {
4421                    self.map_ryna_expression(arg, ctx, id_mapper)?;
4422                }
4423            }
4424
4425            RynaExpr::If(_, ih, ib, ei, eb) => {
4426                self.map_ryna_expression(ih, ctx, id_mapper)?;
4427
4428                for line in ib {
4429                    self.map_ryna_expression(line, ctx, id_mapper)?;
4430                }
4431
4432                for (ei_h, ei_b) in ei {
4433                    self.map_ryna_expression(ei_h, ctx, id_mapper)?;
4434
4435                    for line in ei_b {
4436                        self.map_ryna_expression(line, ctx, id_mapper)?;
4437                    }
4438                }
4439
4440                if let Some(eb_inner) = eb {
4441                    for line in eb_inner {
4442                        self.map_ryna_expression(line, ctx, id_mapper)?;
4443                    }
4444                }
4445            }
4446
4447            RynaExpr::While(_, c, lines) |
4448            RynaExpr::For(_, _, c, lines) => {
4449                self.map_ryna_expression(c, ctx, id_mapper)?;
4450                
4451                for line in lines {
4452                    self.map_ryna_expression(line, ctx, id_mapper)?;
4453                }
4454            }
4455
4456            RynaExpr::Return(_, e) => {
4457                self.map_ryna_expression(e, ctx, id_mapper)?;
4458            }
4459
4460            RynaExpr::Lambda(l, _, a, ret, lines) => {
4461                for (_, t) in a {
4462                    *t = t.map_type(self, ctx, id_mapper, l)
4463                }
4464
4465                *ret = ret.map_type(self, ctx, id_mapper, l);
4466
4467                for line in lines {
4468                    self.map_ryna_expression(line, ctx, id_mapper)?;
4469                }
4470            },
4471
4472            e => unreachable!("{:?}", e)
4473        }
4474
4475        Ok(())
4476    }
4477
4478    pub fn import_code(
4479        &mut self, 
4480        code: &[RynaExpr], 
4481        source: &Vec<(String, usize)>, 
4482        ctx: &RynaContext, 
4483        imports: &Imports
4484    ) -> Result<(Vec<RynaExpr>, Vec<(String, usize)>), RynaError> {
4485        let mut res = vec!();
4486        let mut new_source = vec!();
4487        let mut id_mapper = IdMapper::default();
4488
4489        for (line, (module, module_line)) in code.iter().zip(source) {
4490            match line {
4491                RynaExpr::Macro(_, _, n, _, p, _) => {
4492                    if needs_import(module, ImportType::Syntax, n, imports, &mut self.cache.imports.macros, (n.clone(), p.clone())) {
4493                        self.define_module_macro(line.clone(), &mut FxHashSet::default()).map(|_| ())?;
4494                    }
4495                }
4496
4497                RynaExpr::InterfaceImplementation(l, t, tp, n, ts) => {
4498                    if needs_import(module, ImportType::Interface, n, imports, &mut self.cache.imports.interface_impl, (t.clone(), tp.clone(), n.clone(), ts.clone())) {
4499                        let mapped_type = tp.map_type(self, ctx, &mut id_mapper, l);
4500                        let mapped_args = ts.iter().map(|i| i.map_type(self, ctx, &mut id_mapper, l)).collect::<Vec<_>>();
4501
4502                        self.define_interface_impl(n.clone(), t.clone(), mapped_type.clone(), mapped_args.clone()).unwrap();
4503
4504                        let mapped_expr = RynaExpr::InterfaceImplementation(l.clone(), t.clone(), mapped_type, n.clone(), mapped_args);
4505
4506                        res.push(mapped_expr);
4507                        new_source.push((module.clone(), *module_line));
4508                    }
4509                }
4510
4511                RynaExpr::InterfaceDefinition(l, an, n, t, fns, uns, bin, nary) => {
4512                    if needs_import(module, ImportType::Interface, n, imports, &mut self.cache.imports.interface_def, (n.clone(), t.clone())) {
4513                        self.map_ryna_interface(ctx, ctx.get_interface_id(n.clone()).unwrap(), &mut id_mapper, l).unwrap();
4514
4515                        let mapped_fns = fns.iter().map(|(an, n, t, a, r)| {
4516                            (
4517                                an.clone(),
4518                                n.clone(),
4519                                t.clone(),
4520                                a.iter().map(|(n, t)| (n.clone(), t.map_type(self, ctx, &mut id_mapper, l))).collect(),
4521                                r.map_type(self, ctx, &mut id_mapper, l)
4522                            )
4523                        }).collect();
4524
4525                        let mapped_uns = uns.iter().map(|(an, id, tm, a, at, ret)| {
4526                            Result::<_, RynaError>::Ok((
4527                                an.clone(),
4528                                self.map_ryna_unary_operator(ctx, *id, &mut id_mapper, l)?,
4529                                tm.clone(),
4530                                a.clone(),
4531                                at.map_type(self, ctx, &mut id_mapper, l),
4532                                ret.map_type(self, ctx, &mut id_mapper, l)
4533                            ))
4534                        }).collect::<Result<Vec<_>, _>>()?;
4535
4536                        let mapped_bin = bin.iter().map(|(an, id, tm, (a0, a0t), (a1, a1t), ret)| {
4537                            Result::<_, RynaError>::Ok((
4538                                an.clone(),
4539                                self.map_ryna_binary_operator(ctx, *id, &mut id_mapper, l)?,
4540                                tm.clone(),
4541                                (a0.clone(), a0t.map_type(self, ctx, &mut id_mapper, l)),
4542                                (a1.clone(), a1t.map_type(self, ctx, &mut id_mapper, l)),
4543                                ret.map_type(self, ctx, &mut id_mapper, l)
4544                            ))
4545                        }).collect::<Result<Vec<_>, _>>().unwrap();
4546
4547                        let mapped_nary = nary.iter().map(|(an, id, tm, (a0, a0t), a, ret)| {
4548                            Result::<_, RynaError>::Ok((
4549                                an.clone(),
4550                                self.map_ryna_binary_operator(ctx, *id, &mut id_mapper, l)?,
4551                                tm.clone(),
4552                                (a0.clone(), a0t.map_type(self, ctx, &mut id_mapper, l)),
4553                                a.iter().map(|(n, t)| (n.clone(), t.map_type(self, ctx, &mut id_mapper, l))).collect(),
4554                                ret.map_type(self, ctx, &mut id_mapper, l)
4555                            ))
4556                        }).collect::<Result<Vec<_>, _>>().unwrap();
4557
4558                        let mapped_expr = RynaExpr::InterfaceDefinition(l.clone(), an.clone(), n.clone(), t.clone(), mapped_fns, mapped_uns, mapped_bin, mapped_nary);
4559
4560                        res.push(mapped_expr);
4561                        new_source.push((module.clone(), *module_line));
4562                    }
4563                }
4564
4565                RynaExpr::ClassDefinition(l, an, n, t, atts, al, p) => {
4566                    if needs_import(module, ImportType::Class, n, imports, &mut self.cache.imports.classes, (n.clone(), t.clone())) {
4567                        let mapped_atts = atts.iter().map(|(n, t)| (n.clone(), t.map_type(self, ctx, &mut id_mapper, l))).collect();
4568                        let mapped_al = al.clone().map(|i| i.map_type(self, ctx, &mut id_mapper, l));
4569                        let mapped_expr = RynaExpr::ClassDefinition(l.clone(), an.clone(), n.clone(), t.clone(), mapped_atts, mapped_al, p.clone());
4570
4571                        self.define_module_class(mapped_expr.clone())?;
4572                        
4573                        res.push(mapped_expr);
4574                        new_source.push((module.clone(), *module_line));
4575                    }
4576                }
4577
4578                RynaExpr::FunctionDefinition(l, an, id, t, a, r, b) => {
4579                    let f_name = &ctx.functions[*id].name;
4580                    let fn_id = self.map_ryna_function(ctx, *id, &mut id_mapper, l)?;
4581
4582                    let mapped_args = a.iter().map(|(n, t)| (n.clone(), t.map_type(self, ctx, &mut id_mapper, l))).collect::<Vec<_>>();
4583                    let mapped_return = r.map_type(self, ctx, &mut id_mapper, l);
4584
4585                    if needs_import(module, ImportType::Fn, f_name, imports, &mut self.cache.imports.functions, (fn_id, t.clone(), mapped_args.clone(), mapped_return.clone())) {
4586                        let mut mapped_body = b.clone();
4587
4588                        // Map each line of the definition to the target context
4589                        for line in mapped_body.iter_mut() {
4590                            self.map_ryna_expression(line, ctx, &mut id_mapper)?;
4591                        }
4592
4593                        let arg_types = mapped_args.iter().map(|(_, t)| t.clone()).collect::<Vec<_>>();
4594
4595                        if let Err(err) = self.define_function_overload(l.clone(), an.clone(), fn_id, t.len(), &arg_types, mapped_return.clone(), None) {
4596                            return Err(RynaError::compiler_error(err, l, vec!()));
4597                        }
4598
4599                        // Add the mapped function to the list of new expressions
4600                        res.push(RynaExpr::FunctionDefinition(l.clone(), an.clone(), fn_id, t.clone(), mapped_args.clone(), mapped_return, mapped_body));
4601                        new_source.push((module.clone(), *module_line));
4602                    }
4603                }
4604
4605                RynaExpr::PrefixOperationDefinition(l, an, id, t, arg, arg_t, r, body) |
4606                RynaExpr::PostfixOperationDefinition(l, an, id, t, arg, arg_t, r, body) => {
4607                    let rep;
4608                    let op_prefix;
4609                    let op_import_type;
4610
4611                    if let Operator::Unary { representation, prefix, .. } = &ctx.unary_ops[*id] {
4612                        rep = representation;
4613                        op_prefix = prefix;
4614                        op_import_type = if *prefix { ImportType::Prefix } else { ImportType::Postfix };
4615                    
4616                    } else {
4617                        unreachable!();
4618                    }
4619
4620                    let op_id = self.map_ryna_unary_operator(ctx, *id, &mut id_mapper, l)?;
4621
4622                    let mapped_arg_t = arg_t.map_type(self, ctx, &mut id_mapper, l);
4623                    let mapped_return = r.map_type(self, ctx, &mut id_mapper, l);
4624
4625                    if needs_import(module, op_import_type, rep, imports, &mut self.cache.imports.unary, (op_id, t.clone(), mapped_arg_t.clone(), mapped_return.clone())) {
4626                        let mut mapped_body = body.clone();
4627
4628                        // Map each line of the definition to the target context
4629                        for line in mapped_body.iter_mut() {
4630                            self.map_ryna_expression(line, ctx, &mut id_mapper)?;
4631                        }
4632
4633                        if let Err(err) = self.define_unary_operation(l.clone(), an.clone(), *id, t.len(), mapped_arg_t.clone(), mapped_return.clone(), None) {
4634                            return Err(RynaError::compiler_error(err, l, vec!()));
4635                        }
4636
4637                        // Add the mapped function to the list of new expressions
4638                        if *op_prefix {
4639                            res.push(RynaExpr::PrefixOperationDefinition(l.clone(), an.clone(), op_id, t.clone(), arg.clone(), mapped_arg_t, mapped_return, mapped_body));
4640
4641                        } else {
4642                            res.push(RynaExpr::PostfixOperationDefinition(l.clone(), an.clone(), op_id, t.clone(), arg.clone(), mapped_arg_t, mapped_return, mapped_body));
4643                        }
4644
4645                        new_source.push((module.clone(), *module_line));
4646                    }
4647                },
4648
4649                RynaExpr::BinaryOperationDefinition(l, an, id, t, a, b, r, body) => {
4650                    let rep = ctx.binary_ops[*id].get_repr();
4651
4652                    let op_id = self.map_ryna_binary_operator(ctx, *id, &mut id_mapper, l)?;
4653
4654                    let mapped_arg1 = (a.0.clone(), a.1.map_type(self, ctx, &mut id_mapper, l));
4655                    let mapped_arg2 = (b.0.clone(), b.1.map_type(self, ctx, &mut id_mapper, l));
4656                    let mapped_return = r.map_type(self, ctx, &mut id_mapper, l);
4657
4658                    if needs_import(module, ImportType::Binary, &rep, imports, &mut self.cache.imports.binary, (op_id, t.clone(), mapped_arg1.1.clone(), mapped_arg2.1.clone(), mapped_return.clone())) {
4659                        let mut mapped_body = body.clone();
4660
4661                        // Map each line of the definition to the target context
4662                        for line in mapped_body.iter_mut() {
4663                            self.map_ryna_expression(line, ctx, &mut id_mapper)?;
4664                        }
4665
4666                        if let Err(err) = self.define_binary_operation(l.clone(), an.clone(), *id, t.len(), mapped_arg1.1.clone(), mapped_arg2.1.clone(), mapped_return.clone(), None) {
4667                            return Err(RynaError::compiler_error(err, l, vec!()));
4668                        }
4669
4670                        // Add the mapped function to the list of new expressions
4671                        res.push(RynaExpr::BinaryOperationDefinition(l.clone(), an.clone(), op_id, t.clone(), mapped_arg1, mapped_arg2, mapped_return, mapped_body));
4672                        new_source.push((module.clone(), *module_line));
4673                    }
4674                },
4675
4676                RynaExpr::NaryOperationDefinition(l, an, id, t, arg, args, r, body) => {
4677                    let rep = ctx.nary_ops[*id].get_repr();
4678
4679                    let op_id = self.map_ryna_nary_operator(ctx, *id, &mut id_mapper, l)?;
4680
4681                    let mapped_arg = (arg.0.clone(), arg.1.map_type(self, ctx, &mut id_mapper, l));
4682                    let mapped_args = args.iter().map(|(n, t)| (n.clone(), t.map_type(self, ctx, &mut id_mapper, l))).collect::<Vec<_>>();
4683                    let mapped_return = r.map_type(self, ctx, &mut id_mapper, l);
4684
4685                    if needs_import(module, ImportType::Binary, &rep, imports, &mut self.cache.imports.nary, (*id, t.clone(), mapped_arg.1.clone(), mapped_args.clone(), mapped_return.clone())) {
4686                        let mut mapped_body = body.clone();
4687
4688                        // Map each line of the definition to the target context
4689                        for line in mapped_body.iter_mut() {
4690                            self.map_ryna_expression(line, ctx, &mut id_mapper)?;
4691                        }
4692
4693                        let arg_types = mapped_args.iter().map(|(_, t)| t.clone()).collect::<Vec<_>>();
4694
4695                        if let Err(err) = self.define_nary_operation(l.clone(), an.clone(), *id, t.len(), mapped_arg.1.clone(), &arg_types, mapped_return.clone(), None) {
4696                            return Err(RynaError::compiler_error(err, l, vec!()));
4697                        }
4698
4699                        // Add the mapped function to the list of new expressions
4700                        res.push(RynaExpr::NaryOperationDefinition(l.clone(), an.clone(), op_id, t.clone(), mapped_arg, mapped_args, mapped_return, mapped_body));
4701                        new_source.push((module.clone(), *module_line));
4702                    }
4703                },
4704
4705                expr => {
4706                    if needs_line_import(module, *module_line, &mut self.cache.imports.lines) {
4707                        let mut mapped_expr = expr.clone();
4708                        self.map_ryna_expression(&mut mapped_expr, ctx, &mut id_mapper)?;
4709    
4710                        res.push(mapped_expr);
4711                        new_source.push((module.clone(), *module_line));    
4712                    }
4713                }
4714            }
4715        }
4716
4717        Ok((res, new_source))
4718    }
4719
4720    // BFS on imports
4721    fn cascade_imports(
4722        imports: &mut ImportMap,
4723        modules: &HashMap<String, &RynaModule>
4724    )
4725    {
4726        let mut res = HashMap::new();
4727        
4728        while res != *imports {
4729            res = imports.clone();
4730
4731            for (name, _) in imports.iter() {
4732                for (d_name, d_deps) in &modules.get(name).unwrap().imports {
4733                    for (t, n) in d_deps {
4734                        res.entry(d_name.clone()).or_default().entry(t.clone()).or_default().extend(n.iter().cloned());
4735                    }
4736                }
4737            }
4738    
4739            *imports = res.clone();
4740        }
4741    }
4742
4743    fn map_import(&self, import: &ImportType, name: &String) -> usize {
4744        return match import {
4745            ImportType::Interface => self.get_interface_id(name.clone()).unwrap(),
4746            ImportType::Class => self.get_type_id(name.clone()).unwrap(),
4747            ImportType::Fn => self.get_function_id(name.clone()).unwrap(),
4748
4749            ImportType::Prefix |
4750            ImportType::Postfix => self.unary_ops.iter().find(|i| i.get_repr() == *name).unwrap().get_id(),
4751            
4752            ImportType::Binary => self.binary_ops.iter().find(|i| i.get_repr() == *name).unwrap().get_id(),
4753            ImportType::Nary => self.nary_ops.iter().find(|i| i.get_repr() == *name).unwrap().get_id(),
4754
4755            _ => unimplemented!()
4756        };
4757    }
4758
4759    fn rev_map_import(&self, import: &ImportType, id: usize) -> String {
4760        match import {
4761            ImportType::Interface => self.interfaces[id].name.clone(),
4762            ImportType::Class => self.type_templates[id].name.clone(),
4763            ImportType::Fn => self.functions[id].name.clone(),
4764
4765            ImportType::Prefix |
4766            ImportType::Postfix => self.unary_ops[id].get_repr(),
4767            
4768            ImportType::Binary => self.binary_ops[id].get_repr(),
4769            ImportType::Nary => self.nary_ops[id].get_repr(),
4770
4771            _ => unimplemented!()
4772        }
4773    }
4774
4775    // BFS on imports (inner dependencies)
4776    fn cascade_imports_inner(
4777        imports: &mut ImportMap,
4778        modules: &HashMap<String, &RynaModule>
4779    )
4780    {
4781        for (m, imps) in imports {
4782            let mut new_imports = Imports::new();
4783            let module = &modules.get(m).unwrap();
4784
4785            for (t, names) in imps.iter() {
4786                if let ImportType::Syntax | ImportType::All = t { // Syntaxes do not have to be mapped
4787                    new_imports.entry(t.clone()).or_default().extend(names.iter().cloned());                    
4788
4789                } else {
4790                    for name in names.iter() {
4791                        // Import all
4792                        if name == "*" {
4793                            new_imports.entry(t.clone()).or_default().insert(name.clone());
4794
4795                        } else {
4796                            let id = module.ctx.map_import(t, name);
4797    
4798                            module.inner_dependencies.dfs(&(t.clone(), id), |(tp, id)| {
4799                                let mapped_name = module.ctx.rev_map_import(tp, *id);
4800                                new_imports.entry(tp.clone()).or_default().insert(mapped_name);
4801                            }); 
4802                        }
4803                    }
4804                }
4805            }
4806
4807            for (t, names) in new_imports {
4808                imps.entry(t.clone()).or_default().extend(names);
4809            }
4810        }
4811    }
4812
4813    pub fn parse_with_dependencies(
4814        &mut self, 
4815        name: &str,
4816        code: &String, 
4817        modules: &HashMap<String, &RynaModule>
4818    ) -> Result<(Vec<RynaExpr>, Vec<(String, usize)>), RynaError> {
4819        let mut res = vec!();
4820        let mut source = vec!();
4821        let mut imports = ryna_module_imports_parser(Span::new(code), self.module_name.clone()).unwrap().1; // TODO: should cache this
4822
4823        Self::cascade_imports(&mut imports, modules);
4824        Self::cascade_imports_inner(&mut imports, modules);
4825
4826        // Import code from dependencies
4827        for (m, i) in imports {
4828            let other = modules.get(&m).unwrap();
4829
4830            let (mut new_code, mut new_source) = self.import_code(&other.code, &other.source, &other.ctx, &i)?;
4831            source.append(&mut new_source);
4832            res.append(&mut new_code);
4833        }
4834
4835        let mut main_code = self.parse_without_precompiling(code)?;
4836        source.extend(std::iter::repeat(name.to_owned()).take(main_code.len()).enumerate().map(|(a, b)| (b, a)));
4837        res.append(&mut main_code);
4838
4839        Ok((res, source))
4840    }
4841
4842    pub fn parse_without_precompiling(&mut self, code: &String) -> Result<Vec<RynaExpr>, RynaError> {
4843        self.define_module_macros(code)?;
4844        self.define_module_operators(code)?;
4845        self.define_module_classes(code)?;
4846        self.define_module_functions(code)?;
4847        self.define_module_operations(code)?;
4848
4849        let lines = self.parse_ryna_module(code)?;
4850
4851        self.define_module_function_overloads(&lines)?;
4852
4853        Ok(lines)
4854    }
4855
4856    pub fn compile_globals(&mut self, lines: &mut Vec<RynaExpr>) -> Result<(), RynaError> {
4857        for line in lines.iter_mut() {
4858            match line {
4859                RynaExpr::VariableDefinition(..) => self.compile_expr_variables(line, false, false)?,
4860                _ => {}
4861            }
4862        }
4863
4864        self.reset_registers();
4865        
4866        Ok(())
4867    }
4868
4869    pub fn precompile_module(&mut self, lines: &mut Vec<RynaExpr>) -> Result<(), RynaError> {        
4870        self.compile(lines, &vec!(), false)?;
4871        self.compute_num_globals();
4872
4873        // Generate automatic destructors
4874        self.generate_destructors(lines)?;
4875
4876        // Static checks before doing anything else
4877        for expr in lines.iter_mut() {
4878            self.static_check(expr)?;
4879        }
4880
4881        // Get every function and operation call in the program
4882        self.get_template_calls_body(lines)?;
4883
4884        // Optimize the program
4885        if self.optimize {
4886            // Early optimization
4887            self.optimize(lines);
4888
4889            for body in self.cache.templates.functions.inner_borrow_mut().values_mut() {
4890                self.optimize(body);
4891            }
4892
4893            for body in self.cache.templates.unary.inner_borrow_mut().values_mut() {
4894                self.optimize(body);
4895            }
4896
4897            for body in self.cache.templates.binary.inner_borrow_mut().values_mut() {
4898                self.optimize(body);
4899            }
4900
4901            for body in self.cache.templates.nary.inner_borrow_mut().values_mut() {
4902                self.optimize(body);
4903            }
4904
4905            // Late optimization
4906            macro_rules! optimize_cache {
4907                ($cache: expr) => {
4908                    let keys = $cache.inner_borrow_mut().keys().cloned().collect::<Vec<_>>();
4909
4910                    for key in keys {
4911                        let mut body = $cache.get_checked(&key).unwrap().clone();
4912                        
4913                        self.late_optimize(&mut body);
4914        
4915                        $cache.insert(key, body);
4916                    }          
4917                };
4918            }
4919
4920            optimize_cache!(self.cache.templates.functions);
4921            optimize_cache!(self.cache.templates.unary);
4922            optimize_cache!(self.cache.templates.binary);
4923            optimize_cache!(self.cache.templates.nary);
4924
4925            self.late_optimize(lines);
4926        }
4927
4928        Ok(())
4929    }
4930
4931    pub fn parse_and_precompile(&mut self, code: &String) -> Result<Vec<RynaExpr>, RynaError> {
4932        let mut lines = self.parse_without_precompiling(code)?;
4933        self.precompile_module(&mut lines)?;
4934
4935        Ok(lines)
4936    }
4937
4938    pub fn parse_and_compile(&mut self, code: &String) -> Result<Vec<RynaInstruction>, RynaError> {
4939        let lines = self.parse_and_precompile(code)?;
4940
4941        self.compiled_form(&lines)
4942    }
4943}
4944
4945/*
4946                                                  ╒═════════╕
4947    ============================================= │  TESTS  │ =============================================
4948                                                  ╘═════════╛
4949*/
4950
4951#[cfg(test)]
4952mod tests {
4953    use malachite::Integer;
4954
4955    use crate::object::*;
4956    use crate::parser::*;
4957    use crate::context::*;
4958    use crate::types::INT;
4959
4960    #[test]
4961    fn function_names_and_calls() {
4962        let mut ctx = standard_ctx();
4963        
4964        let code_1_str = "
4965        inc(5.mut());
4966        ";
4967        
4968        let code_str = "
4969        inc<Int>(5.mut());
4970        ";
4971
4972        let inc_idx = ctx.get_function_id("inc".into()).unwrap();
4973        let mut_idx = ctx.get_function_id("mut".into()).unwrap();
4974        
4975        let (_, mut code) = ctx.ryna_parser(Span::new(code_1_str)).unwrap();
4976        ctx.compile(&mut code, &vec!(), false).unwrap();
4977
4978        assert_eq!(code, vec!(
4979            RynaExpr::FunctionCall(Location::none(), inc_idx, vec!(), vec!(
4980                RynaExpr::FunctionCall(Location::none(), mut_idx, vec!(INT), vec!(
4981                    RynaExpr::Literal(Location::none(), Object::new(Integer::from(5)))
4982                ))    
4983            ))
4984        ));
4985        
4986        let (_, mut code) = ctx.ryna_parser(Span::new(code_str)).unwrap();
4987
4988        assert!(ctx.compile(&mut code, &vec!(), false).is_ok());
4989    }
4990
4991    #[test]
4992    fn compiled_form() {
4993        let mut ctx = standard_ctx();
4994
4995        let code_str = "
4996            fn test(a: Int) -> Int {
4997                if 0 < a {
4998                    return test(a - 1) + a;
4999                }
5000
5001                return 0;
5002            }
5003
5004            let a = test(10);
5005        ";
5006
5007        let compiled_code = ctx.parse_and_compile(&code_str.into());
5008
5009        assert!(compiled_code.is_ok());
5010    }
5011}