heptagon/compiler/global/static.ml

171 lines
6.4 KiB
OCaml
Raw Normal View History

(**************************************************************************)
(* *)
(* Heptagon *)
(* *)
(* Author : Marc Pouzet *)
(* Organization : Demons, LRI, University of Paris-Sud, Orsay *)
(* *)
(**************************************************************************)
(** This module defines static expressions, used in params and for constants.
const n: int = 3;
var x : int^n; var y : int^(n + 2);
x[n - 1], x[1 + 3],... *)
open Names
2010-06-15 10:49:03 +02:00
open Format
open Types
2010-07-08 14:56:49 +02:00
open Signature
open Modules
2010-06-15 10:49:03 +02:00
(* unsatisfiable constraint *)
exception Instanciation_failed
2010-08-24 17:24:22 +02:00
exception Partial_instanciation of static_exp
2010-06-15 10:49:03 +02:00
exception Not_static
2010-08-24 17:24:22 +02:00
let partial_apply_op op se_list =
match se_list with
| [{ se_desc = Sint n1 }; { se_desc = Sint n2 }] ->
(match op with
| { qual = "Pervasives"; name = "+" } ->
Sint (n1 + n2)
| { qual = "Pervasives"; name = "-" } ->
Sint (n1 - n2)
| { qual = "Pervasives"; name = "*" } ->
Sint (n1 * n2)
| { qual = "Pervasives"; name = "/" } ->
let n = if n2 = 0 then raise Instanciation_failed else n1 / n2 in
Sint n
| { qual = "Pervasives"; name = "=" } ->
2010-07-16 14:15:26 +02:00
Sbool (n1 = n2)
2010-07-16 14:16:31 +02:00
| _ -> assert false (*TODO: add missing operators*)
)
| [{ se_desc = Sint n }] ->
(match op with
| { qual = "Pervasives"; name = "~-" } -> Sint (-n)
| _ -> assert false (*TODO: add missing operators*)
)
| _ -> Sop(op, se_list)
2010-08-24 17:24:22 +02:00
let apply_op op se_list =
let se = partial_apply_op op se_list in
match se with
| Sop _ -> raise Not_found
| _ -> se
let eval_core eval apply_op env se = match se.se_desc with
| Sint _ | Sfloat _ | Sbool _ | Sconstructor _ | Sfield _ -> se
2010-08-24 17:24:22 +02:00
| Svar ln -> (
try (* first try to find in global const env *)
let cd = find_const ln in
2010-08-24 17:24:22 +02:00
eval env cd.c_value
with Not_found -> (* then try to find in local env *)
eval env (QualEnv.find ln env))
2010-08-24 17:24:22 +02:00
| Sop (op, se_list) ->
let se_list = List.map (eval env) se_list in
{ se with se_desc = apply_op op se_list }
| Sarray se_list ->
{ se with se_desc = Sarray (List.map (eval env) se_list) }
| Sarray_power (se, n) ->
{ se with se_desc = Sarray_power (eval env se, eval env n) }
| Stuple se_list ->
{ se with se_desc = Stuple (List.map (eval env) se_list) }
| Srecord f_se_list ->
{ se with se_desc = Srecord
(List.map (fun (f,se) -> f, eval env se) f_se_list) }
(** [simplify env e] returns e simplified with the
variables values taken from [env] or from the global env with [find_const].
Every operator that can be computed is.
It can return static_exp with uninstanciated variables.*)
let rec simplify env se =
try eval_core simplify partial_apply_op env se
with _ -> se
(** [eval env e] does the same as [simplify]
but if it returns, there are no variables nor op left.
@raise [Partial_instanciation] when it cannot fully evaluate *)
let rec eval env se =
try eval_core eval apply_op env se
with Not_found -> raise (Partial_instanciation se)
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).*)
let int_of_static_exp env se =
match (simplify env se).se_desc with
| Sint i -> i
| _ ->
(Format.eprintf "Internal compiler error, \
[eval_int] received the static_exp %a.@."
Global_printer.print_static_exp se;
assert false)
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. *)
let is_true env =
function
| Cequal (e1, e2) when e1 = e2 ->
Some true, Cequal (simplify env e1, simplify env e2)
| Cequal (e1, e2) ->
let e1 = simplify env e1 in
let e2 = simplify env e2 in
(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)
| (_, _) -> None, Cequal (e1, e2))
| Clequal (e1, e2) ->
let e1 = simplify env e1 in
let e2 = simplify env e2 in
(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)
| _, _ -> None, Clequal (e1, e2))
| Cfalse -> None, Cfalse
2010-07-02 15:38:11 +02:00
exception Solve_failed of size_constraint
2010-06-15 10:49:03 +02:00
(** [solve env constr_list solves a list of constraints. It
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. ]*)
let rec solve const_env =
function
| [] -> []
| c :: l ->
let l = solve const_env l in
let (res, c) = is_true const_env c in
(match res with
| 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
| Svar qn -> (try QualEnv.find qn m with | Not_found -> se)
2010-07-08 14:56:49 +02:00
| 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-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 =
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 in
List.map (replace_one m) constr