summaryrefslogblamecommitdiff
path: root/abstract/abs_interp.ml
blob: feaf0378ca9ead6fbf99033a53ccf7730108ce69 (plain) (tree)
1
2
3
4
5
6
7
8
9
        
             






                                       

           
                                               


            

                           
                          








































                                                                                       
                                                                           











                                                                           
                                       










                                                                           
                                                     

                                                                             
                                                                         
 
                                                                                                              


                                       
                                                          
























                                                                          


       

                                        
                                                 
 
      


                                          













                                                                        

                        
                               











                                                    
      

                                               
 
                          
 
                                                       
 



                                                                           

                                     


                                              
                                               


                          
   
open Ast
open Ast_util
open Formula

open Util
open Environment_domain

module I (E : ENVIRONMENT_DOMAIN) : sig

    type st

    val do_prog     : int -> prog -> id -> unit

end = struct

    type st = {
        p           : prog;
        widen_delay : int;
        root_scope  : scope;
        all_vars    : var_def list;
        env         : E.t;
        f           : bool_expr;
        cl          : conslist;
    }


    let node_vars p f nid =
      let (n, _) = find_node_decl p f in
      List.map (fun (p, id, t) -> p, nid^"/"^id, t)
        (n.args @ n.ret @ n.var)

    (*
        extract_all_vars : prog -> scope -> var_decl list

        Extracts all variables with names given according to
        naming convention used here and in transform.ml :
        - pre variables are not prefixed by scope
        - next values for variables are prefixed by capital N
    *)
    let rec extract_all_vars p (node, prefix, eqs) =
        let vars_of_expr e =
          List.flatten
            (List.map
              (fun (f, id, eqs, args) ->
                node_vars p f (node^"/"^id) @
                extract_all_vars p (node^"/"^id, "", eqs))
              (extract_instances p e))
          @
          List.flatten
            (List.map
              (fun (id, _) -> [false, id, AST_TINT; false, "N"^id, AST_TINT])
                  (* TODO : type of pre value ? *)
              (extract_pre e))
        in
        let vars_of_eq e = match fst e with
          | AST_assign(_, e) | AST_assume(_, e) | AST_guarantee(_, e) -> vars_of_expr e
          | AST_activate (b, _) ->
            let rec do_branch = function
              | AST_activate_body b ->
                List.map (fun (p, id, t) -> p, node^"/"^id, t) b.act_locals
                @
                extract_all_vars p (node, b.act_id^".", b.body)
              | AST_activate_if(c, a, b) ->
                vars_of_expr c @ do_branch a @ do_branch b
            in do_branch b
          | AST_automaton _ -> not_implemented "extract_all vars automaton"
        in
        (false, node^"/"^prefix^"time", AST_TINT)::
        (false, "N"^node^"/"^prefix^"time", AST_TINT)::
        (List.flatten (List.map vars_of_eq eqs))

    (* init state *)
    let init_state widen_delay p root =
      let root_scope = get_root_scope p root in

      let f = Formula.eliminate_not (Transform.f_of_prog p root) in
      let cl = Formula.conslist_of_f f in
      let all_vars = node_vars p root "" @ extract_all_vars p root_scope in
      let env = List.fold_left
        (fun env (_, id, ty) ->
          E.addvar env id (ty = AST_TREAL))
        E.init
        all_vars
      in
      let init_f = Transform.init_f_of_prog p root in

      Format.printf "Init formula: %a@.@." Formula_printer.print_expr init_f;
      Format.printf "Cycle formula: %a@.@." Formula_printer.print_expr f;

      Format.printf "Vars: @[<hov>%a@]@.@." (Ast_printer.print_list Ast_printer.print_var_decl ", ") all_vars;

      let env = E.apply_f env init_f in

      { p; root_scope; widen_delay; f; cl; all_vars; env }

    (*
      pass_cycle : var_def list -> E.t -> E.t

      Does :
        - x <- Nx, for all x
        - ignore x for all x such that Nx does not exist
    *)
    let pass_cycle vars e =
      let tr_assigns = List.fold_left
        (fun q (_, id, _) ->
            if id.[0] = 'N' then
              (String.sub id 1 (String.length id - 1), NIdent id)::q
            else
              q)
        [] vars
      in
      let e = E.assign e tr_assigns in

      let forget_vars = List.map (fun (_, id, _) -> id)
          (List.filter
              (fun (_, id, _) ->
                 not (List.exists (fun (_, id2, _) -> id2 = "N"^id) vars))
              vars) in
      let e = List.fold_left E.forgetvar e forget_vars in
      e


    (* cycle : st -> cl -> env -> env *)
    let cycle st cl i =
      (pass_cycle st.all_vars (E.apply_cl i cl)) 

    (*
      loop : st -> cl -> env -> env -> env
    *)
    let loop st cycle_cl pnew stay =

      Format.printf "Loop @[<hv>%a@]@.New @[<hv>%a@]@.Stay @[<hv>%a@]@."
        Formula_printer.print_conslist cycle_cl
        E.print_all pnew E.print_all stay;

      let add_stay = cycle st cycle_cl pnew in
      let acc0 = E.join stay add_stay in

      let fsharp i = 
        Format.printf "Acc @[<hv>%a@]@." E.print_all i;
        let j = cycle st cycle_cl i in
        E.join acc0 j
      in

      let rec iter n i =
        let i' =
          if n < st.widen_delay
            then E.join i (fsharp i)
            else E.widen i (fsharp i)
        in
        if E.eq i i' then i else iter (n+1) i'
      in

      let x = iter 0 acc0 in
      fix E.eq fsharp x   (* decreasing iteration *)


    (*
      do_prog : prog -> id -> unit
    *)
    let do_prog widen_delay p root =
      let st = init_state widen_delay p root in

      let pnew = st.env in

      let stay = loop st st.cl pnew (E.vbottom pnew) in

      let final = E.join (E.apply_cl pnew st.cl) (E.apply_cl stay st.cl) in

      Format.printf "@[<hov>Final %a@]@."
        E.print_all final;

      Format.printf "Probes:@[<hov>";
      List.iter (fun (p, id, _) ->
        if p then Format.printf "@ %a ∊ %a,"
              Formula_printer.print_id id
              E.print_itv (E.var_itv final id))
        st.all_vars;
      Format.printf "@]@."

end