fn compute_state_usage_for_exp(
        &mut self,
        mut visited_opt: Option<&mut BTreeSet<usize>>,
        exp: &Exp,
    ) -> (
        BTreeSet<QualifiedId<SpecVarId>>,
        BTreeSet<QualifiedId<StructId>>,
    ) {
        let mut used_spec_vars = BTreeSet::new();
        let mut used_memory = BTreeSet::new();
        exp.visit(&mut |e: &Exp| {
            match e {
                Exp::SpecVar(_, mid, vid) => {
                    used_spec_vars.insert(mid.qualified(*vid));
                }
                Exp::Call(_, Operation::Function(mid, fid), _) => {
                    if mid.to_usize() < self.parent.env.get_module_count() {
                        // This is calling a function from another module we already have
                        // translated.
                        let module_env = self.parent.env.get_module(*mid);
                        let fun_decl = module_env.get_spec_fun(*fid);
                        used_spec_vars.extend(&fun_decl.used_spec_vars);
                        used_memory.extend(&fun_decl.used_memory);
                    } else {
                        // This is calling a function from the module we are currently translating.
                        // Need to recursively ensure we have computed used_spec_vars because of
                        // arbitrary call graphs, including cyclic. If visted_opt is not set,
                        // we know we already computed this.
                        if let Some(visited) = &mut visited_opt {
                            self.compute_state_usage_for_fun(visited, fid.as_usize());
                        }
                        let fun_decl = &self.spec_funs[fid.as_usize()];
                        used_spec_vars.extend(&fun_decl.used_spec_vars);
                        used_memory.extend(&fun_decl.used_memory);
                    }
                }
                Exp::Call(node_id, Operation::Global, _)
                | Exp::Call(node_id, Operation::Exists, _) => {
                    if !self.parent.env.has_errors() {
                        // We would crash if the type is not valid, so only do this if no errors
                        // have been reported so far.
                        let ty = &self.instantiation_map.get(node_id).expect("type exists")[0];
                        let (mid, sid, _) = ty.require_struct();
                        used_memory.insert(mid.qualified(sid));
                    }
                }
                _ => {}
            }
        });
        (used_spec_vars, used_memory)
    }
/// Computes state usage for an expression. If the visited_opt is available, this recurses
/// to compute the usage for any functions called. Otherwise it assumes this information is
/// already computed.
Computes state usage for an expression. If the visited_opt is available, this recurses
to compute the usage for any functions called. Otherwise it assumes this information is
already computed.
Computes state usage for an expression . If the visited_opt is available this recurses to compute the usage for any functions called . Otherwise it assumes this information is already computed .
fn compute_state_usage_for_exp(
        &mut self,
        mut visited_opt: Option<&mut BTreeSet<usize>>,
        exp: &Exp,
    ) -> (
        BTreeSet<QualifiedId<SpecVarId>>,
        BTreeSet<QualifiedId<StructId>>,
    ) {
        let mut used_spec_vars = BTreeSet::new();
        let mut used_memory = BTreeSet::new();
        exp.visit(&mut |e: &Exp| {
            match e {
                Exp::SpecVar(_, mid, vid) => {
                    used_spec_vars.insert(mid.qualified(*vid));
                }
                Exp::Call(_, Operation::Function(mid, fid), _) => {
                    if mid.to_usize() < self.parent.env.get_module_count() {
                        // This is calling a function from another module we already have
                        // translated.
                        let module_env = self.parent.env.get_module(*mid);
                        let fun_decl = module_env.get_spec_fun(*fid);
                        used_spec_vars.extend(&fun_decl.used_spec_vars);
                        used_memory.extend(&fun_decl.used_memory);
                    } else {
                        // This is calling a function from the module we are currently translating.
                        // Need to recursively ensure we have computed used_spec_vars because of
                        // arbitrary call graphs, including cyclic. If visted_opt is not set,
                        // we know we already computed this.
                        if let Some(visited) = &mut visited_opt {
                            self.compute_state_usage_for_fun(visited, fid.as_usize());
                        }
                        let fun_decl = &self.spec_funs[fid.as_usize()];
                        used_spec_vars.extend(&fun_decl.used_spec_vars);
                        used_memory.extend(&fun_decl.used_memory);
                    }
                }
                Exp::Call(node_id, Operation::Global, _)
                | Exp::Call(node_id, Operation::Exists, _) => {
                    if !self.parent.env.has_errors() {
                        // We would crash if the type is not valid, so only do this if no errors
                        // have been reported so far.
                        let ty = &self.instantiation_map.get(node_id).expect("type exists")[0];
                        let (mid, sid, _) = ty.require_struct();
                        used_memory.insert(mid.qualified(sid));
                    }
                }
                _ => {}
            }
        });
        (used_spec_vars, used_memory)
    }
fn compute_state_usage_for_exp ( & mut self , mut visited_opt : Option < & mut BTreeSet < usize > > , exp : & Exp , ) -> ( BTreeSet < QualifiedId < SpecVarId > > , BTreeSet < QualifiedId < StructId > > , ) { let mut used_spec_vars = BTreeSet :: new ( ) ; let mut used_memory = BTreeSet :: new ( ) ; exp . visit ( & mut | e : & Exp | { match e { Exp :: SpecVar ( _ , mid , vid ) => { used_spec_vars . insert ( mid . qualified ( * vid ) ) ; } Exp :: Call ( _ , Operation :: Function ( mid , fid ) , _ ) => { if mid . to_usize ( ) < self . parent . env . get_module_count ( ) { // This is calling a function from another module we already have // translated. let module_env = self . parent . env . get_module ( * mid ) ; let fun_decl = module_env . get_spec_fun ( * fid ) ; used_spec_vars . extend ( & fun_decl . used_spec_vars ) ; used_memory . extend ( & fun_decl . used_memory ) ; } else { // This is calling a function from the module we are currently translating. // Need to recursively ensure we have computed used_spec_vars because of // arbitrary call graphs, including cyclic. If visted_opt is not set, // we know we already computed this. if let Some ( visited ) = & mut visited_opt { self . compute_state_usage_for_fun ( visited , fid . as_usize ( ) ) ; } let fun_decl = & self . spec_funs [ fid . as_usize ( ) ] ; used_spec_vars . extend ( & fun_decl . used_spec_vars ) ; used_memory . extend ( & fun_decl . used_memory ) ; } } Exp :: Call ( node_id , Operation :: Global , _ ) | Exp :: Call ( node_id , Operation :: Exists , _ ) => { if ! self . parent . env . has_errors ( ) { // We would crash if the type is not valid, so only do this if no errors // have been reported so far. let ty = & self . instantiation_map . get ( node_id ) . expect ( " " ) [ 0 ] ; let ( mid , sid , _ ) = ty . require_struct ( ) ; used_memory . insert ( mid . qualified ( sid ) ) ; } } _ => { } } } ) ; ( used_spec_vars , used_memory ) }
Computes state usage for an expression.
Computes state usage for an expression .
&mut self
visited_opt
Option<&mut BTreeSet<usize>>
exp
&Exp
&mut self
visited_opt
Option<&mut BTreeSet<usize>>
exp
&Exp