2010-06-27 17:24:31 +02:00
|
|
|
open Minils
|
|
|
|
open Mls_printer
|
|
|
|
open Location
|
|
|
|
open Names
|
|
|
|
open Ident
|
|
|
|
open Signature
|
|
|
|
open Static
|
|
|
|
open Types
|
|
|
|
open Misc
|
|
|
|
|
|
|
|
(** Error Kind *)
|
2010-06-30 17:20:56 +02:00
|
|
|
type err_kind = | Enot_static_exp
|
2010-06-27 17:24:31 +02:00
|
|
|
|
|
|
|
let err_message ?(exp=void) ?(loc=exp.e_loc) = function
|
2010-06-30 17:20:56 +02:00
|
|
|
| Enot_static_exp ->
|
|
|
|
Printf.eprintf "The expression %a should be a static_exp.@."
|
2010-07-01 20:00:46 +02:00
|
|
|
print_exp exp;
|
2010-06-29 11:18:50 +02:00
|
|
|
raise Error
|
2010-06-27 17:24:31 +02:00
|
|
|
|
2010-06-30 17:20:56 +02:00
|
|
|
let rec static_exp_of_exp e =
|
2010-06-29 11:18:50 +02:00
|
|
|
match e.e_desc with
|
2010-07-02 13:50:18 +02:00
|
|
|
| Econst se -> se
|
2010-06-30 17:20:56 +02:00
|
|
|
| _ -> err_message ~exp:e Enot_static_exp
|
2010-06-27 17:24:31 +02:00
|
|
|
|
|
|
|
(** @return the list of bounds of an array type*)
|
2010-06-29 11:18:50 +02:00
|
|
|
let rec bounds_list ty =
|
2010-06-27 17:24:31 +02:00
|
|
|
match ty with
|
|
|
|
| Tarray(ty, n) -> n::(bounds_list ty)
|
|
|
|
| _ -> []
|
|
|
|
|
|
|
|
(** @return the [var_dec] object corresponding to the name [n]
|
|
|
|
in a list of [var_dec]. *)
|
|
|
|
let rec vd_find n = function
|
|
|
|
| [] -> Format.printf "Not found var %s\n" (name n); raise Not_found
|
2010-06-29 11:18:50 +02:00
|
|
|
| vd::l ->
|
2010-06-27 17:24:31 +02:00
|
|
|
if vd.v_ident = n then vd else vd_find n l
|
|
|
|
|
2010-06-29 11:18:50 +02:00
|
|
|
(** @return whether an object of name [n] belongs to
|
2010-06-27 17:24:31 +02:00
|
|
|
a list of [var_dec]. *)
|
|
|
|
let rec vd_mem n = function
|
|
|
|
| [] -> false
|
|
|
|
| vd::l -> vd.v_ident = n or (vd_mem n l)
|
|
|
|
|
|
|
|
(** @return whether [ty] corresponds to a record type. *)
|
|
|
|
let is_record_type ty = match ty with
|
|
|
|
| Tid n ->
|
2010-06-29 11:18:50 +02:00
|
|
|
(try
|
|
|
|
ignore (Modules.find_struct n); true
|
|
|
|
with
|
|
|
|
Not_found -> false)
|
2010-06-27 17:24:31 +02:00
|
|
|
| _ -> false
|
|
|
|
|
2010-06-30 10:22:31 +02:00
|
|
|
let is_op = function
|
|
|
|
| Modname { qual = "Pervasives"; id = _ } -> true | _ -> false
|
|
|
|
|
2010-06-27 17:24:31 +02:00
|
|
|
module Vars =
|
|
|
|
struct
|
2010-06-29 11:18:50 +02:00
|
|
|
let add x acc =
|
2010-06-27 17:24:31 +02:00
|
|
|
if List.mem x acc then acc else x :: acc
|
|
|
|
|
|
|
|
let rec vars_pat acc = function
|
|
|
|
| Evarpat x -> x :: acc
|
|
|
|
| Etuplepat pat_list -> List.fold_left vars_pat acc pat_list
|
|
|
|
|
|
|
|
let rec vars_ck acc = function
|
|
|
|
| Con(ck, c, n) -> add n acc
|
|
|
|
| Cbase | Cvar { contents = Cindex _ } -> acc
|
|
|
|
| Cvar { contents = Clink ck } -> vars_ck acc ck
|
|
|
|
|
|
|
|
let rec read is_left acc e =
|
|
|
|
let acc =
|
|
|
|
match e.e_desc with
|
|
|
|
| Evar n -> add n acc
|
|
|
|
| Emerge(x, c_e_list) ->
|
|
|
|
let acc = add x acc in
|
2010-06-29 11:18:50 +02:00
|
|
|
List.fold_left (fun acc (_, e) -> read is_left acc e) acc c_e_list
|
2010-06-27 17:24:31 +02:00
|
|
|
| Eifthenelse(e1, e2, e3) ->
|
|
|
|
read is_left (read is_left (read is_left acc e1) e2) e3
|
|
|
|
| Ewhen(e, c, x) ->
|
|
|
|
let acc = add x acc in
|
2010-06-29 11:18:50 +02:00
|
|
|
read is_left acc e
|
2010-06-27 17:24:31 +02:00
|
|
|
| Etuple(e_list) -> List.fold_left (read is_left) acc e_list
|
2010-06-29 11:18:50 +02:00
|
|
|
| Ecall(_, e_list, None) ->
|
2010-06-27 17:24:31 +02:00
|
|
|
List.fold_left (read is_left) acc e_list
|
|
|
|
| Ecall(_, e_list, Some x) ->
|
|
|
|
let acc = add x acc in
|
2010-06-29 11:18:50 +02:00
|
|
|
List.fold_left (read is_left) acc e_list
|
2010-06-27 17:24:31 +02:00
|
|
|
| Efby(_, e) ->
|
|
|
|
if is_left then vars_ck acc e.e_ck else read is_left acc e
|
|
|
|
| Efield(e, _) -> read is_left acc e
|
|
|
|
| Estruct(f_e_list) ->
|
|
|
|
List.fold_left (fun acc (_, e) -> read is_left acc e) acc f_e_list
|
2010-06-29 11:18:50 +02:00
|
|
|
| Econst _ | Econstvar _ -> acc
|
|
|
|
| Efield_update (_, e1, e2) ->
|
|
|
|
read is_left (read is_left acc e1) e2
|
|
|
|
(*Array operators*)
|
|
|
|
| Earray e_list -> List.fold_left (read is_left) acc e_list
|
|
|
|
| Earray_op op -> read_array_op is_left acc op
|
2010-06-27 17:24:31 +02:00
|
|
|
in
|
2010-06-29 11:18:50 +02:00
|
|
|
vars_ck acc e.e_ck
|
2010-06-27 17:24:31 +02:00
|
|
|
|
2010-06-29 11:18:50 +02:00
|
|
|
and read_array_op is_left acc = function
|
2010-06-27 17:24:31 +02:00
|
|
|
| Erepeat (_,e) -> read is_left acc e
|
2010-06-29 11:18:50 +02:00
|
|
|
| Eselect (_,e) -> read is_left acc e
|
2010-06-30 13:46:46 +02:00
|
|
|
| Eselect_dyn (e_list, e1, e2) ->
|
2010-06-29 11:18:50 +02:00
|
|
|
let acc = List.fold_left (read is_left) acc e_list in
|
|
|
|
read is_left (read is_left acc e1) e2
|
|
|
|
| Eupdate (_, e1, e2) ->
|
|
|
|
read is_left (read is_left acc e1) e2
|
|
|
|
| Eselect_slice (_ , _, e) -> read is_left acc e
|
|
|
|
| Econcat (e1, e2) ->
|
|
|
|
read is_left (read is_left acc e1) e2
|
|
|
|
| Eiterator (_, _, _, e_list, None) ->
|
|
|
|
List.fold_left (read is_left) acc e_list
|
|
|
|
| Eiterator (_, _, _, e_list, Some x) ->
|
2010-06-27 17:24:31 +02:00
|
|
|
let acc = add x acc in
|
2010-06-29 11:18:50 +02:00
|
|
|
List.fold_left (read is_left) acc e_list
|
2010-06-27 17:24:31 +02:00
|
|
|
|
|
|
|
let rec remove x = function
|
|
|
|
| [] -> []
|
|
|
|
| y :: l -> if x = y then l else y :: remove x l
|
|
|
|
|
|
|
|
let def acc { eq_lhs = pat } = vars_pat acc pat
|
|
|
|
|
|
|
|
let read is_left { eq_lhs = pat; eq_rhs = e } =
|
|
|
|
match pat, e.e_desc with
|
|
|
|
| Evarpat(n), Efby(_, e1) ->
|
|
|
|
if is_left
|
|
|
|
then remove n (read is_left [] e1)
|
|
|
|
else read is_left [] e1
|
|
|
|
| _ -> read is_left [] e
|
|
|
|
|
|
|
|
let antidep { eq_rhs = e } =
|
|
|
|
match e.e_desc with Efby _ -> true | _ -> false
|
|
|
|
|
|
|
|
let clock { eq_rhs = e } =
|
|
|
|
match e.e_desc with
|
|
|
|
| Emerge(_, (_, e) :: _) -> e.e_ck
|
|
|
|
| _ -> e.e_ck
|
|
|
|
|
|
|
|
let head ck =
|
|
|
|
let rec headrec ck l =
|
|
|
|
match ck with
|
|
|
|
| Cbase | Cvar { contents = Cindex _ } -> l
|
|
|
|
| Con(ck, c, n) -> headrec ck (n :: l)
|
2010-06-29 11:18:50 +02:00
|
|
|
| Cvar { contents = Clink ck } -> headrec ck l
|
2010-06-27 17:24:31 +02:00
|
|
|
in
|
2010-06-29 11:18:50 +02:00
|
|
|
headrec ck []
|
2010-06-27 17:24:31 +02:00
|
|
|
|
2010-06-29 11:18:50 +02:00
|
|
|
(** Returns a list of memory vars (x in x = v fby e)
|
2010-06-27 17:24:31 +02:00
|
|
|
appearing in an equation. *)
|
|
|
|
let memory_vars ({ eq_lhs = _; eq_rhs = e } as eq) =
|
|
|
|
match e.e_desc with
|
|
|
|
| Efby(_, _) -> def [] eq
|
|
|
|
| _ -> []
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
(* data-flow dependences. pre-dependences are discarded *)
|
|
|
|
module DataFlowDep = Dep.Make
|
|
|
|
(struct
|
|
|
|
type equation = eq
|
|
|
|
let read eq = Vars.read true eq
|
|
|
|
let def = Vars.def
|
|
|
|
let antidep = Vars.antidep
|
|
|
|
end)
|
|
|
|
|
|
|
|
(* all dependences between variables *)
|
|
|
|
module AllDep = Dep.Make
|
|
|
|
(struct
|
|
|
|
type equation = eq
|
|
|
|
let read eq = Vars.read false eq
|
|
|
|
let def = Vars.def
|
|
|
|
let antidep eq = false
|
|
|
|
end)
|