charon_lib/ast/
gast_utils.rs

1//! Implementations for [crate::gast]
2
3use crate::ast::*;
4use crate::llbc_ast;
5use crate::ullbc_ast;
6
7impl FnPtrKind {
8    pub fn mk_builtin(aid: BuiltinFunId) -> Self {
9        Self::Fun(FunId::Builtin(aid))
10    }
11}
12
13impl Body {
14    pub fn as_unstructured(&self) -> Option<&ullbc_ast::ExprBody> {
15        if let Self::Unstructured(v) = self {
16            Some(v)
17        } else {
18            None
19        }
20    }
21    pub fn as_unstructured_mut(&mut self) -> Option<&mut ullbc_ast::ExprBody> {
22        if let Self::Unstructured(v) = self {
23            Some(v)
24        } else {
25            None
26        }
27    }
28
29    pub fn as_structured(&self) -> Option<&llbc_ast::ExprBody> {
30        if let Self::Structured(v) = self {
31            Some(v)
32        } else {
33            None
34        }
35    }
36    pub fn as_structured_mut(&mut self) -> Option<&mut llbc_ast::ExprBody> {
37        if let Self::Structured(v) = self {
38            Some(v)
39        } else {
40            None
41        }
42    }
43
44    pub fn locals(&self) -> &Locals {
45        match self {
46            Body::Structured(body) => &body.locals,
47            Body::Unstructured(body) => &body.locals,
48        }
49    }
50}
51
52impl Locals {
53    pub fn new(arg_count: usize) -> Self {
54        Self {
55            arg_count,
56            locals: Default::default(),
57        }
58    }
59
60    /// Creates a new variable and returns a place pointing to it.
61    /// Warning: don't forget to `StorageLive` it before using it.
62    pub fn new_var(&mut self, name: Option<String>, ty: Ty) -> Place {
63        let local_id = self.locals.push_with(|index| Local {
64            index,
65            name,
66            ty: ty.clone(),
67        });
68        Place::new(local_id, ty)
69    }
70
71    /// Gets a place pointing to the corresponding variable.
72    pub fn place_for_var(&self, local_id: LocalId) -> Place {
73        let ty = self.locals[local_id].ty.clone();
74        Place::new(local_id, ty)
75    }
76
77    /// Returns whether this local is the special return local or one of the input argument locals.
78    pub fn is_return_or_arg(&self, lid: LocalId) -> bool {
79        lid.index() <= self.arg_count
80    }
81
82    /// The place where we write the return value.
83    pub fn return_place(&self) -> Place {
84        self.place_for_var(LocalId::new(0))
85    }
86
87    /// Locals that aren't arguments or return values.
88    pub fn non_argument_locals(&self) -> impl Iterator<Item = (LocalId, &Local)> {
89        self.locals.iter_indexed().skip(1 + self.arg_count)
90    }
91}
92
93impl std::ops::Index<LocalId> for Locals {
94    type Output = Local;
95    fn index(&self, local_id: LocalId) -> &Self::Output {
96        &self.locals[local_id]
97    }
98}
99impl std::ops::IndexMut<LocalId> for Locals {
100    fn index_mut(&mut self, local_id: LocalId) -> &mut Self::Output {
101        &mut self.locals[local_id]
102    }
103}
104
105impl FunDecl {
106    /// Replace the generic parameters of this function with the ones given by the binder.
107    pub fn substitute_params(self, subst: Binder<GenericArgs>) -> Self {
108        let FunDecl {
109            def_id,
110            item_meta,
111            signature,
112            src: kind,
113            is_global_initializer,
114            body,
115        } = self;
116        let signature = FunSig {
117            generics: subst.params,
118            inputs: signature.inputs.substitute(&subst.skip_binder),
119            output: signature.output.substitute(&subst.skip_binder),
120            ..signature
121        };
122        let src = kind.substitute(&subst.skip_binder);
123        let body = body.substitute(&subst.skip_binder);
124        FunDecl {
125            def_id,
126            item_meta,
127            signature,
128            src,
129            is_global_initializer,
130            body,
131        }
132    }
133}
134impl TraitDecl {
135    pub fn methods(&self) -> impl Iterator<Item = &Binder<TraitMethod>> {
136        self.methods.iter()
137    }
138}
139impl TraitImpl {
140    pub fn methods(&self) -> impl Iterator<Item = &(TraitItemName, Binder<FunDeclRef>)> {
141        self.methods.iter()
142    }
143}
144
145impl Binder<TraitAssocTy> {
146    pub fn name(&self) -> &TraitItemName {
147        &self.skip_binder.name
148    }
149}
150impl Binder<TraitMethod> {
151    pub fn name(&self) -> TraitItemName {
152        self.skip_binder.name
153    }
154}