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