1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
use std::rc::Rc;
use std::cell::RefCell;

use crate::module::ParsedModule;
use crate::analysis::{ check_program, Program as AnalyzedProgram, Function, CFG, FnId, AnonymousFunction, TypingContext };
use crate::analysis::error::AnalysisError;

pub struct Program {
    program: AnalyzedProgram
}

impl Program {
    pub fn create(modules: Vec<ParsedModule>) -> Result<Program, AnalysisError> {
        Ok(Program {
            program: check_program(modules)?
        })
    }

    pub fn metadata(&self) -> &crate::metadata::Metadata {
        &self.program.metadata()
    }

    pub fn compilable_fns<'a>(&'a self) 
        -> impl Iterator<Item=(FnId, CompilableFn)> + 'a {

        self.program
            .all_fns()
            .filter(|(_, f)| {
                match f {
                    Function::SMPL(_) => true,
                    Function::Anonymous(_) => true,
                    _ => false
                }
            })
            .map(|(f_id, f)| {
                match f {
                    Function::SMPL(f) => {
                        let c_fn = CompilableFn {
                            cfg: f.cfg(),
                            typing_context: f.analysis_context().typing_context(),
                        };
                        (f_id, c_fn)
                    },

                    Function::Anonymous(AnonymousFunction::Reserved(_)) => {
                        panic!("All anonymous functions should be resolved after analysis");
                    }

                    Function::Anonymous(AnonymousFunction::Resolved {
                        ref cfg,
                        ref analysis_context,
                        ..
                    }) => {
                        let c_fn = CompilableFn {
                            cfg: cfg.clone(),
                            typing_context: analysis_context.typing_context()
                        };

                        (f_id, c_fn)
                    },

                    _ => unreachable!(),
                }
            })
    }
}

pub struct CompilableFn<'a> {
    cfg: Rc<RefCell<CFG>>,
    typing_context: &'a TypingContext,
}

impl<'a> CompilableFn<'a> {
    pub(crate) fn cfg(&self) -> &Rc<RefCell<CFG>> {
        &self.cfg
    }

    pub(crate) fn typing_context(&self) -> &TypingContext {
        self.typing_context
    }
}