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
82
83
84
85
86
87
88
89
90
91
92
93
94
use std::rc::Rc;

use arret_syntax::datum::DataStr;

use crate::context::ModuleId;
use crate::hir;
use crate::mir::env_values::EnvValues;
use crate::ty;
use crate::ty::ty_args::TyArgs;

new_global_id_type!(ArretFunId);

#[derive(Clone, Debug)]
struct ArretFunConsts {
    id: ArretFunId,
    module_id: Option<ModuleId>,
    source_name: Option<DataStr>,
    env_ty_args: TyArgs<ty::Mono>,
    fun_expr: hir::Fun<hir::Inferred>,
}

#[derive(Clone, Debug)]
pub struct ArretFun {
    consts: Rc<ArretFunConsts>,
    env_values: EnvValues,
}

impl ArretFun {
    pub fn new(
        module_id: Option<ModuleId>,
        source_name: Option<DataStr>,
        env_ty_args: TyArgs<ty::Mono>,
        env_values: EnvValues,
        fun_expr: hir::Fun<hir::Inferred>,
    ) -> Self {
        Self {
            consts: Rc::new(ArretFunConsts {
                id: ArretFunId::alloc(),
                module_id,
                source_name,
                env_ty_args,
                fun_expr,
            }),
            env_values,
        }
    }

    pub fn id(&self) -> ArretFunId {
        self.consts.id
    }

    /// Returns the optional module ID this function occurs in
    ///
    /// This is used to look up local variables from other definitions in the same module.
    pub fn module_id(&self) -> Option<ModuleId> {
        self.consts.module_id
    }

    pub fn source_name(&self) -> &Option<DataStr> {
        &self.consts.source_name
    }

    pub fn env_ty_args(&self) -> &TyArgs<ty::Mono> {
        &self.consts.env_ty_args
    }

    pub fn env_values(&self) -> &EnvValues {
        &self.env_values
    }

    pub fn env_values_mut(&mut self) -> &mut EnvValues {
        &mut self.env_values
    }

    pub fn fun_expr(&self) -> &hir::Fun<hir::Inferred> {
        &self.consts.fun_expr
    }

    pub fn with_env_values(&self, env_values: EnvValues) -> ArretFun {
        ArretFun {
            consts: self.consts.clone(),
            env_values,
        }
    }

    /// Indicates if this `ArretFun` is used in multiple places
    ///
    /// This is a heuristic; if a `Fun` is bound to a variable this will return true regardless
    /// of the number of usages.
    pub fn has_multiple_usages(&self) -> bool {
        // This is a hack but has the benefit of not requiring a separate analysis pass
        Rc::strong_count(&self.consts) > 1
    }
}