summaryrefslogtreecommitdiff
path: root/src/SymbolicAstUtils.ml
blob: f781ed657b239f9fa8687970dd8e9c46b62b4eab (plain)
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
open Errors
module T = Types
module V = Values
module E = Expressions
module A = CfimAst
open SymbolicAst
open ValuesUtils
open InterpreterUtils

type ('c, 's) ended = EndedConcrete of 'c | EndedSymbolic of 's

type ended_loan = (V.mvalue, V.mvalue list) ended

type ended_borrow = (V.mvalue, V.mvalue) ended

type ended_loan_or_borrow =
  | EndedLoan of ended_loan
  | EndedBorrow of ended_borrow

(** Return the list of the meta-values given to the top owned ended mutable
    loans/borrows of an abstraction
    
    We expect an abstraction where all the loans/borrows have ended.
 *)
let get_top_owned_ended_loans_borrows (abs : V.abs) : ended_loan_or_borrow list
    =
  (* The accumulator *)
  let acc = ref [] in
  let add x = acc := x :: !acc in
  let add_loan x = add (EndedLoan x) in
  let add_borrow x = add (EndedBorrow x) in
  let add_sloan x = add_loan (EndedSymbolic x) in
  let add_cloan x = add_loan (EndedConcrete x) in
  let add_sborrow x = add_borrow (EndedSymbolic x) in
  let add_cborrow x = add_borrow (EndedConcrete x) in

  (* The visitor *)
  let obj =
    object
      inherit [_] V.iter_abs as super

      method! visit_aproj env aproj =
        match aproj with
        | AEndedProjLoans (msv, []) ->
            (* The symbolic value was left unchanged *)
            add_sloan [ mk_typed_value_from_symbolic_value msv ]
        | AEndedProjLoans (_, mvl) -> add_sloan (List.map fst mvl)
        | AEndedProjBorrows mv -> add_sborrow mv
        | AIgnoredProjBorrows | AProjLoans (_, _) | AProjBorrows (_, _) ->
            failwith "Unreachable"

      method! visit_aloan_content env lc =
        match lc with
        | AMutLoan (_, _) | ASharedLoan (_, _, _) -> failwith "Unreachable"
        | AEndedMutLoan { child = _; given_back = _; given_back_meta } ->
            (* Add the meta-value and stop the exploration *)
            add_cloan given_back_meta
        | AEndedSharedLoan (_, _) ->
            (* We don't dive into shared loans: there is nothing to give back
             * inside (note that there could be a mutable borrow in the shared
             * value, pointing to a mutable loan in the child avalue, but this
             * borrow is in practice immutable *)
            ()
        | AIgnoredMutLoan (_, _) ->
            (* There can be *inner* mutable loans, but not outer ones *)
            failwith "Unreachable"
        | AEndedIgnoredMutLoan _ ->
            (* Dive in *)
            super#visit_aloan_content env lc
        | AIgnoredSharedLoan _ ->
            (* Ignore *)
            ()

      method! visit_aborrow_content env bc =
        match bc with
        | AMutBorrow (_, _, _) | ASharedBorrow _ | AIgnoredMutBorrow (_, _) ->
            failwith "Unreachable"
        | AEndedMutBorrow (mv, _) ->
            (* Add the meta-value and stop the exploration *)
            add_cborrow mv
        | AEndedIgnoredMutBorrow _ ->
            (* Dive in *)
            super#visit_aborrow_content env bc
        | AProjSharedBorrow _ ->
            (* Ignore *)
            ()
    end
  in
  (* Apply *)
  obj#visit_abs () abs;
  (* Return the accumulated values *)
  List.rev !acc