2010-07-01 20:00:46 +02:00
|
|
|
(**************************************************************************)
|
|
|
|
(* *)
|
|
|
|
(* Heptagon *)
|
|
|
|
(* *)
|
|
|
|
(* Author : Marc Pouzet *)
|
|
|
|
(* Organization : Demons, LRI, University of Paris-Sud, Orsay *)
|
|
|
|
(* *)
|
|
|
|
(**************************************************************************)
|
|
|
|
|
|
|
|
(** This module defines static expressions, used in params and for constants.
|
2010-06-15 14:05:26 +02:00
|
|
|
|
|
|
|
const n: int = 3;
|
|
|
|
var x : int^n; var y : int^(n + 2);
|
|
|
|
x[n - 1], x[1 + 3],...
|
2010-06-15 10:49:03 +02:00
|
|
|
*)
|
2010-06-26 16:53:25 +02:00
|
|
|
|
2010-07-01 20:00:46 +02:00
|
|
|
open Names
|
2010-06-15 10:49:03 +02:00
|
|
|
open Format
|
2010-07-07 15:11:32 +02:00
|
|
|
open Types
|
2010-07-08 14:56:49 +02:00
|
|
|
open Signature
|
|
|
|
open Modules
|
2010-06-15 10:49:03 +02:00
|
|
|
|
2010-06-15 14:05:26 +02:00
|
|
|
(* unsatisfiable constraint *)
|
|
|
|
exception Instanciation_failed
|
2010-06-26 16:53:25 +02:00
|
|
|
|
2010-06-15 10:49:03 +02:00
|
|
|
exception Not_static
|
2010-06-26 16:53:25 +02:00
|
|
|
|
2010-06-15 10:49:03 +02:00
|
|
|
(** Returns the op from an operator full name. *)
|
2010-07-02 13:50:18 +02:00
|
|
|
let op_from_app_name ln =
|
|
|
|
match ln with
|
|
|
|
| Modname { qual = "Pervasives" } -> ln
|
2010-06-26 16:53:25 +02:00
|
|
|
| _ -> raise Not_static
|
|
|
|
|
2010-07-02 13:50:18 +02:00
|
|
|
(** Applies the operator [op] to the two integers [n1] and [n2]
|
|
|
|
and returns the reslt as a static exp. *)
|
|
|
|
let apply_int_op op n1 n2 =
|
|
|
|
match op with
|
|
|
|
| Modname { qual = "Pervasives"; id = "+" } -> Sint (n1 + n2)
|
|
|
|
| Modname { qual = "Pervasives"; id = "-" } -> Sint (n1 - n2)
|
|
|
|
| Modname { qual = "Pervasives"; id = "*" } -> Sint (n1 * n2)
|
|
|
|
| Modname { qual = "Pervasives"; id = "/" } ->
|
|
|
|
let n = if n2 = 0 then raise Instanciation_failed else n1 / n2 in
|
|
|
|
Sint n
|
|
|
|
| _ -> (* unknown operator, reconstrcut the op *)
|
2010-07-07 15:11:32 +02:00
|
|
|
Sop (op, [mk_static_exp (Sint n1); mk_static_exp (Sint n2)]) (*TODO CP*)
|
2010-07-02 13:50:18 +02:00
|
|
|
|
2010-06-15 10:49:03 +02:00
|
|
|
(** [simplify env e] returns e simplified with the
|
|
|
|
variables values taken from env (mapping vars to integers).
|
|
|
|
Variables are replaced with their values and every operator
|
|
|
|
that can be computed is replaced with the value of the result. *)
|
2010-07-02 13:50:18 +02:00
|
|
|
let rec simplify env se =
|
2010-07-07 15:11:32 +02:00
|
|
|
match se.se_desc with
|
|
|
|
| Sint _ | Sfloat _ | Sbool _ | Sconstructor _ -> se
|
2010-07-07 16:43:23 +02:00
|
|
|
| Svar ln ->
|
|
|
|
(try
|
|
|
|
let { info = cd } = find_const ln in
|
|
|
|
simplify env cd.c_value
|
|
|
|
with
|
|
|
|
Not_found ->
|
|
|
|
(match ln with
|
2010-07-08 14:56:49 +02:00
|
|
|
| Name n -> (try simplify env (NamesEnv.find n env) with | _ -> se)
|
2010-07-07 16:43:23 +02:00
|
|
|
| Modname _ -> se)
|
|
|
|
)
|
2010-07-02 13:50:18 +02:00
|
|
|
| Sop (op, [e1; e2]) ->
|
2010-07-07 12:15:02 +02:00
|
|
|
let e1 = simplify env e1 in
|
|
|
|
let e2 = simplify env e2 in
|
2010-07-07 15:11:32 +02:00
|
|
|
(match e1.se_desc, e2.se_desc with
|
2010-07-07 12:15:02 +02:00
|
|
|
| Sint n1, Sint n2 -> { se with se_desc = apply_int_op op n1 n2 }
|
|
|
|
| _, _ -> { se with se_desc = Sop (op, [e1; e2]) }
|
2010-07-02 13:50:18 +02:00
|
|
|
)
|
2010-07-07 12:15:02 +02:00
|
|
|
| Sop (op, se_list) ->
|
|
|
|
{ se with se_desc = Sop (op, List.map (simplify env) se_list) }
|
|
|
|
| Sarray se_list ->
|
|
|
|
{ se with se_desc = Sarray (List.map (simplify env) se_list) }
|
|
|
|
| Sarray_power (se, n) ->
|
|
|
|
{ se with se_desc = Sarray_power (simplify env se, simplify env n) }
|
|
|
|
| Stuple se_list ->
|
|
|
|
{ se with se_desc = Stuple (List.map (simplify env) se_list) }
|
2010-07-06 09:15:20 +02:00
|
|
|
| Srecord f_se_list ->
|
2010-07-07 12:15:02 +02:00
|
|
|
{ se with se_desc = Srecord
|
|
|
|
(List.map (fun (f,se) -> f, simplify env se) f_se_list) }
|
2010-06-26 16:53:25 +02:00
|
|
|
|
2010-06-30 17:20:56 +02:00
|
|
|
(** [int_of_static_exp env e] returns the value of the expression
|
2010-06-15 10:49:03 +02:00
|
|
|
[e] in the environment [env], mapping vars to integers. Raises
|
|
|
|
Instanciation_failed if it cannot be computed (if a var has no value).*)
|
2010-07-02 13:50:18 +02:00
|
|
|
let int_of_static_exp env e =
|
2010-07-07 12:15:02 +02:00
|
|
|
let e = simplify env e in
|
2010-07-07 15:11:32 +02:00
|
|
|
match e.se_desc with | Sint n -> n | _ -> raise Instanciation_failed
|
2010-06-26 16:53:25 +02:00
|
|
|
|
2010-06-15 10:49:03 +02:00
|
|
|
(** [is_true env constr] returns whether the constraint is satisfied
|
|
|
|
in the environment (or None if this can be decided)
|
|
|
|
and a simplified constraint. *)
|
2010-06-15 14:05:26 +02:00
|
|
|
let is_true env =
|
|
|
|
function
|
2010-07-07 15:11:32 +02:00
|
|
|
| Cequal (e1, e2) when e1 = e2 ->
|
2010-07-02 13:50:18 +02:00
|
|
|
Some true, Cequal (simplify env e1, simplify env e2)
|
2010-07-01 20:00:46 +02:00
|
|
|
| Cequal (e1, e2) ->
|
2010-06-26 16:53:25 +02:00
|
|
|
let e1 = simplify env e1 in
|
|
|
|
let e2 = simplify env e2
|
|
|
|
in
|
2010-07-07 15:11:32 +02:00
|
|
|
(match e1.se_desc, e2.se_desc with
|
2010-07-07 12:15:02 +02:00
|
|
|
| Sint n1, Sint n2 -> Some (n1 = n2), Cequal (e1, e2)
|
2010-07-02 13:50:18 +02:00
|
|
|
| (_, _) -> None, Cequal (e1, e2))
|
2010-07-01 20:00:46 +02:00
|
|
|
| Clequal (e1, e2) ->
|
2010-06-26 16:53:25 +02:00
|
|
|
let e1 = simplify env e1 in
|
|
|
|
let e2 = simplify env e2
|
|
|
|
in
|
2010-07-07 15:11:32 +02:00
|
|
|
(match e1.se_desc, e2.se_desc with
|
2010-07-07 12:15:02 +02:00
|
|
|
| Sint n1, Sint n2 -> Some (n1 <= n2), Clequal (e1, e2)
|
2010-07-02 13:50:18 +02:00
|
|
|
| _, _ -> None, Clequal (e1, e2))
|
|
|
|
| Cfalse -> None, Cfalse
|
2010-06-26 16:53:25 +02:00
|
|
|
|
2010-07-02 15:38:11 +02:00
|
|
|
exception Solve_failed of size_constraint
|
2010-06-26 16:53:25 +02:00
|
|
|
|
2010-06-15 10:49:03 +02:00
|
|
|
(** [solve env constr_list solves a list of constraints. It
|
2010-06-15 14:05:26 +02:00
|
|
|
removes equations that can be decided and simplify others.
|
2010-06-15 10:49:03 +02:00
|
|
|
If one equation cannot be satisfied, it raises Solve_failed. ]*)
|
2010-06-15 14:05:26 +02:00
|
|
|
let rec solve const_env =
|
|
|
|
function
|
2010-06-26 16:53:25 +02:00
|
|
|
| [] -> []
|
|
|
|
| c :: l ->
|
|
|
|
let l = solve const_env l in
|
|
|
|
let (res, c) = is_true const_env c
|
|
|
|
in
|
2010-06-15 14:05:26 +02:00
|
|
|
(match res with
|
2010-06-26 16:53:25 +02:00
|
|
|
| None -> c :: l
|
|
|
|
| Some v -> if not v then raise (Solve_failed c) else l)
|
|
|
|
|
2010-06-15 10:49:03 +02:00
|
|
|
(** Substitutes variables in the size exp with their value
|
|
|
|
in the map (mapping vars to size exps). *)
|
2010-07-07 12:15:02 +02:00
|
|
|
let rec static_exp_subst m se =
|
2010-07-08 14:56:49 +02:00
|
|
|
match se.se_desc with
|
2010-07-07 16:43:23 +02:00
|
|
|
| Svar ln ->
|
|
|
|
(match ln with
|
2010-07-13 14:03:39 +02:00
|
|
|
| Name n -> (try NamesEnv.find n m with | Not_found -> se)
|
2010-07-08 14:56:49 +02:00
|
|
|
| Modname _ -> se)
|
|
|
|
| Sop (op, se_list) ->
|
|
|
|
{ se with se_desc = Sop (op, List.map (static_exp_subst m) se_list) }
|
|
|
|
| Sarray_power (se, n) ->
|
|
|
|
{ se with se_desc = Sarray_power (static_exp_subst m se,
|
|
|
|
static_exp_subst m n) }
|
|
|
|
| Sarray se_list ->
|
|
|
|
{ se with se_desc = Sarray (List.map (static_exp_subst m) se_list) }
|
|
|
|
| Stuple se_list ->
|
|
|
|
{ se with se_desc = Stuple (List.map (static_exp_subst m) se_list) }
|
2010-07-07 12:15:02 +02:00
|
|
|
| Srecord f_se_list ->
|
2010-07-08 14:56:49 +02:00
|
|
|
{ se with se_desc =
|
|
|
|
Srecord (List.map
|
|
|
|
(fun (f,se) -> f, static_exp_subst m se) f_se_list) }
|
|
|
|
| _ -> se
|
2010-06-26 16:53:25 +02:00
|
|
|
|
2010-06-15 10:49:03 +02:00
|
|
|
(** Substitutes variables in the constraint list with their value
|
|
|
|
in the map (mapping vars to size exps). *)
|
|
|
|
let instanciate_constr m constr =
|
2010-07-01 20:00:46 +02:00
|
|
|
let replace_one m = function
|
2010-07-01 19:32:54 +02:00
|
|
|
| Cequal (e1, e2) -> Cequal (static_exp_subst m e1, static_exp_subst m e2)
|
|
|
|
| Clequal (e1, e2) -> Clequal (static_exp_subst m e1, static_exp_subst m e2)
|
|
|
|
| Cfalse -> Cfalse
|
2010-06-15 14:05:26 +02:00
|
|
|
in List.map (replace_one m) constr
|
2010-06-26 16:53:25 +02:00
|
|
|
|
2010-07-07 15:11:32 +02:00
|
|
|
|
|
|
|
open Format
|
2010-06-26 16:53:25 +02:00
|
|
|
|
2010-07-02 15:38:11 +02:00
|
|
|
let print_size_constraint ff = function
|
2010-07-01 20:00:46 +02:00
|
|
|
| Cequal (e1, e2) ->
|
2010-07-01 19:32:54 +02:00
|
|
|
fprintf ff "@[%a = %a@]" print_static_exp e1 print_static_exp e2
|
2010-07-01 20:00:46 +02:00
|
|
|
| Clequal (e1, e2) ->
|
2010-07-01 19:32:54 +02:00
|
|
|
fprintf ff "@[%a <= %a@]" print_static_exp e1 print_static_exp e2
|
|
|
|
| Cfalse -> fprintf ff "Cfalse"
|
2010-06-26 16:53:25 +02:00
|
|
|
|
2010-07-02 15:38:11 +02:00
|
|
|
let psize_constraint oc c =
|
2010-06-15 14:05:26 +02:00
|
|
|
let ff = formatter_of_out_channel oc
|
2010-07-02 15:38:11 +02:00
|
|
|
in (print_size_constraint ff c; fprintf ff "@?")
|
2010-06-26 16:53:25 +02:00
|
|
|
|