2010-06-15 10:49:03 +02:00
|
|
|
(**************************************************************************)
|
|
|
|
(* *)
|
|
|
|
(* MiniLustre *)
|
|
|
|
(* *)
|
|
|
|
(* Author : Marc Pouzet *)
|
|
|
|
(* Organization : Demons, LRI, University of Paris-Sud, Orsay *)
|
|
|
|
(* *)
|
|
|
|
(**************************************************************************)
|
|
|
|
(* clock checking *)
|
2010-06-24 03:32:46 +02:00
|
|
|
|
2010-06-15 10:49:03 +02:00
|
|
|
open Misc
|
2010-07-23 19:45:19 +02:00
|
|
|
open Idents
|
2010-06-15 10:49:03 +02:00
|
|
|
open Minils
|
2010-06-22 10:08:30 +02:00
|
|
|
open Mls_printer
|
2010-06-17 16:09:32 +02:00
|
|
|
open Signature
|
2010-06-18 11:50:35 +02:00
|
|
|
open Types
|
2010-07-23 22:06:06 +02:00
|
|
|
open Clocks
|
2010-06-15 10:49:03 +02:00
|
|
|
open Location
|
2010-08-24 17:23:50 +02:00
|
|
|
open Format
|
2010-06-26 16:53:25 +02:00
|
|
|
|
2010-06-27 17:24:31 +02:00
|
|
|
(** Error Kind *)
|
2010-07-27 13:31:13 +02:00
|
|
|
type error_kind = | Etypeclash of ct * ct
|
2010-06-27 17:24:31 +02:00
|
|
|
|
2010-07-27 13:31:13 +02:00
|
|
|
let error_message loc = function
|
2010-06-27 17:24:31 +02:00
|
|
|
| Etypeclash (actual_ct, expected_ct) ->
|
2010-09-01 13:31:28 +02:00
|
|
|
Format.eprintf "%aClock Clash: this expression has clock %a,@\n\
|
2010-08-24 17:23:50 +02:00
|
|
|
but is expected to have clock %a.@."
|
|
|
|
print_location loc
|
2010-06-29 11:18:50 +02:00
|
|
|
print_clock actual_ct
|
|
|
|
print_clock expected_ct;
|
2010-09-15 09:38:52 +02:00
|
|
|
raise Errors.Error
|
2010-06-26 16:53:25 +02:00
|
|
|
|
2010-07-23 22:06:06 +02:00
|
|
|
|
2010-06-15 10:49:03 +02:00
|
|
|
let typ_of_name h x = Env.find x h
|
2010-06-26 16:53:25 +02:00
|
|
|
|
2010-06-15 10:49:03 +02:00
|
|
|
let rec typing h e =
|
2010-07-15 16:20:46 +02:00
|
|
|
let ct = match e.e_desc with
|
2010-11-01 01:04:35 +01:00
|
|
|
| Econst se -> skeleton (fresh_clock ()) se.se_ty
|
2010-07-15 16:20:46 +02:00
|
|
|
| Evar x -> Ck (typ_of_name h x)
|
2010-09-14 09:39:02 +02:00
|
|
|
| Efby (_, e) -> typing h e
|
2010-07-15 16:20:46 +02:00
|
|
|
| Eapp({a_op = op}, args, r) ->
|
|
|
|
let ck = match r with
|
2010-11-01 01:04:35 +01:00
|
|
|
| None -> fresh_clock ()
|
2010-07-23 22:06:06 +02:00
|
|
|
| Some(reset) -> typ_of_name h reset in
|
|
|
|
typing_op op args h e ck
|
|
|
|
| Eiterator (_, _, _, args, r) -> (* Typed exactly as a fun or a node... *)
|
|
|
|
let ck = match r with
|
2010-11-01 01:04:35 +01:00
|
|
|
| None -> fresh_clock()
|
2010-07-23 22:06:06 +02:00
|
|
|
| Some(reset) -> typ_of_name h reset
|
|
|
|
in (List.iter (expect h (Ck ck)) args; skeleton ck e.e_ty)
|
2010-07-15 16:20:46 +02:00
|
|
|
| Ewhen (e, c, n) ->
|
2010-07-23 22:06:06 +02:00
|
|
|
let ck_n = typ_of_name h n in
|
|
|
|
(expect h (skeleton ck_n e.e_ty) e; skeleton (Con (ck_n, c, n)) e.e_ty)
|
2010-07-15 16:20:46 +02:00
|
|
|
| Emerge (n, c_e_list) ->
|
2010-07-23 22:06:06 +02:00
|
|
|
let ck_c = typ_of_name h n in
|
|
|
|
(typing_c_e_list h ck_c n c_e_list; skeleton ck_c e.e_ty)
|
2010-07-15 16:20:46 +02:00
|
|
|
| Estruct l ->
|
2010-11-01 01:04:35 +01:00
|
|
|
let ck = fresh_clock () in
|
2010-07-15 16:20:46 +02:00
|
|
|
(List.iter
|
2010-09-14 09:39:02 +02:00
|
|
|
(fun (_, e) -> let ct = skeleton ck e.e_ty in expect h ct e) l;
|
2010-07-15 16:20:46 +02:00
|
|
|
Ck ck)
|
2010-06-18 11:50:35 +02:00
|
|
|
in (e.e_ck <- ckofct ct; ct)
|
|
|
|
|
2010-09-13 16:02:33 +02:00
|
|
|
and typing_op op e_list h e ck = match op with
|
2010-11-01 01:04:35 +01:00
|
|
|
| (Eequal | Efun _ | Enode _) -> (*LA*)
|
2010-09-27 18:16:00 +02:00
|
|
|
List.iter (fun e -> expect h (skeleton ck e.e_ty) e) e_list;
|
|
|
|
skeleton ck e.e_ty
|
2010-09-13 16:02:33 +02:00
|
|
|
| Etuple ->
|
2010-07-23 22:06:06 +02:00
|
|
|
Cprod (List.map (typing h) e_list)
|
2010-09-13 16:02:33 +02:00
|
|
|
| Eifthenelse ->
|
|
|
|
let e1, e2, e3 = assert_3 e_list in
|
2010-06-26 16:53:25 +02:00
|
|
|
let ct = skeleton ck e.e_ty
|
2010-07-15 16:20:46 +02:00
|
|
|
in (expect h (Ck ck) e1; expect h ct e2; expect h ct e3; ct)
|
2010-09-13 16:02:33 +02:00
|
|
|
| Efield ->
|
|
|
|
let e1 = assert_1 e_list in
|
2010-07-15 16:20:46 +02:00
|
|
|
let ct = skeleton ck e1.e_ty in (expect h (Ck ck) e1; ct)
|
2010-09-13 16:02:33 +02:00
|
|
|
| Efield_update ->
|
|
|
|
let e1, e2 = assert_2 e_list in
|
2010-06-26 16:53:25 +02:00
|
|
|
let ct = skeleton ck e.e_ty
|
|
|
|
in (expect h (Ck ck) e1; expect h ct e2; ct)
|
2010-09-13 16:02:33 +02:00
|
|
|
| Earray ->
|
2010-07-15 16:20:46 +02:00
|
|
|
(List.iter (expect h (Ck ck)) e_list; skeleton ck e.e_ty)
|
2010-09-13 16:02:33 +02:00
|
|
|
| Earray_fill -> let e = assert_1 e_list in typing h e
|
|
|
|
| Eselect -> let e = assert_1 e_list in typing h e
|
|
|
|
| Eselect_dyn -> (* TODO defe not treated ? *)
|
|
|
|
let e1, defe, idx = assert_2min e_list in
|
2010-07-15 16:20:46 +02:00
|
|
|
let ct = skeleton ck e1.e_ty
|
2010-09-13 01:18:45 +02:00
|
|
|
in (List.iter (expect h ct) (e1::defe::idx); ct)
|
2010-09-13 16:02:33 +02:00
|
|
|
| Eupdate ->
|
|
|
|
let e1, e2, idx = assert_2min e_list in
|
2010-06-26 16:53:25 +02:00
|
|
|
let ct = skeleton ck e.e_ty
|
2010-07-28 12:34:07 +02:00
|
|
|
in (expect h (Ck ck) e1; expect h ct e2; List.iter (expect h ct) idx; ct)
|
2010-09-13 16:02:33 +02:00
|
|
|
| Eselect_slice -> let e = assert_1 e_list in typing h e
|
|
|
|
| Econcat ->
|
|
|
|
let e1, e2 = assert_2 e_list in
|
2010-07-15 16:20:46 +02:00
|
|
|
let ct = skeleton ck e.e_ty
|
|
|
|
in (expect h (Ck ck) e1; expect h ct e2; ct)
|
2010-06-18 11:50:35 +02:00
|
|
|
|
2010-06-15 10:49:03 +02:00
|
|
|
and expect h expected_ty e =
|
2010-07-23 22:06:06 +02:00
|
|
|
let actual_ty = typing h e in
|
2010-06-29 11:18:50 +02:00
|
|
|
try unify actual_ty expected_ty
|
2010-07-27 13:31:13 +02:00
|
|
|
with
|
2010-08-03 22:38:42 +02:00
|
|
|
| Unify -> eprintf "%a : " print_exp e;
|
2010-07-27 13:31:13 +02:00
|
|
|
error_message e.e_loc (Etypeclash (actual_ty, expected_ty))
|
2010-06-18 11:50:35 +02:00
|
|
|
|
2010-06-15 10:49:03 +02:00
|
|
|
and typing_c_e_list h ck_c n c_e_list =
|
2010-06-18 11:50:35 +02:00
|
|
|
let rec typrec =
|
|
|
|
function
|
2010-06-29 11:18:50 +02:00
|
|
|
| [] -> ()
|
|
|
|
| (c, e) :: c_e_list ->
|
|
|
|
(expect h (skeleton (Con (ck_c, c, n)) e.e_ty) e; typrec c_e_list)
|
2010-06-18 11:50:35 +02:00
|
|
|
in typrec c_e_list
|
2010-06-26 16:53:25 +02:00
|
|
|
|
2010-06-18 11:50:35 +02:00
|
|
|
let rec typing_pat h =
|
|
|
|
function
|
2010-06-29 11:18:50 +02:00
|
|
|
| Evarpat x -> Ck (typ_of_name h x)
|
|
|
|
| Etuplepat pat_list -> Cprod (List.map (typing_pat h) pat_list)
|
|
|
|
|
2010-06-27 17:24:31 +02:00
|
|
|
let typing_eqs h eq_list = (*TODO FIXME*)
|
2010-07-27 13:31:13 +02:00
|
|
|
let typing_eq { eq_lhs = pat; eq_rhs = e } =
|
|
|
|
let ty_pat = typing_pat h pat in
|
|
|
|
(try expect h ty_pat e with
|
2010-09-15 09:38:52 +02:00
|
|
|
| Errors.Error -> (* DEBUG *)
|
2010-09-01 13:31:28 +02:00
|
|
|
Format.eprintf "Complete expression: %a@\nClock pattern: %a@."
|
2010-07-27 13:31:13 +02:00
|
|
|
Mls_printer.print_exp e
|
|
|
|
Mls_printer.print_clock ty_pat;
|
2010-09-15 09:38:52 +02:00
|
|
|
raise Errors.Error)
|
2010-07-27 13:31:13 +02:00
|
|
|
in List.iter typing_eq eq_list
|
2010-06-26 16:53:25 +02:00
|
|
|
|
2010-06-15 10:49:03 +02:00
|
|
|
let build h dec =
|
2010-11-01 01:04:35 +01:00
|
|
|
List.fold_left (fun h { v_ident = n } -> Env.add n (fresh_clock ()) h) h dec
|
2010-06-26 16:53:25 +02:00
|
|
|
|
2010-06-15 10:49:03 +02:00
|
|
|
let sbuild h dec base =
|
2010-06-27 17:24:31 +02:00
|
|
|
List.fold_left (fun h { v_ident = n } -> Env.add n base h) h dec
|
2010-06-26 16:53:25 +02:00
|
|
|
|
2010-06-15 10:49:03 +02:00
|
|
|
let typing_contract h contract base =
|
|
|
|
match contract with
|
2010-06-29 11:18:50 +02:00
|
|
|
| None -> h
|
|
|
|
| Some { c_local = l_list;
|
|
|
|
c_eq = eq_list;
|
|
|
|
c_assume = e_a;
|
2010-07-15 16:20:46 +02:00
|
|
|
c_enforce = e_g; } ->
|
2010-06-29 11:18:50 +02:00
|
|
|
let h' = build h l_list in
|
|
|
|
(* assumption *)
|
|
|
|
(* property *)
|
|
|
|
(typing_eqs h' eq_list;
|
|
|
|
expect h' (Ck base) e_a;
|
|
|
|
expect h' (Ck base) e_g;
|
|
|
|
h)
|
2010-06-27 17:24:31 +02:00
|
|
|
|
2010-09-14 09:39:02 +02:00
|
|
|
let typing_node ({ n_input = i_list;
|
2010-06-29 11:18:50 +02:00
|
|
|
n_output = o_list;
|
|
|
|
n_contract = contract;
|
|
|
|
n_local = l_list;
|
|
|
|
n_equs = eq_list
|
|
|
|
} as node) =
|
2010-06-15 10:49:03 +02:00
|
|
|
let base = Cbase in
|
|
|
|
let h = sbuild Env.empty i_list base in
|
|
|
|
let h = sbuild h o_list base in
|
|
|
|
let h = typing_contract h contract base in
|
2010-06-27 17:24:31 +02:00
|
|
|
let h = build h l_list in
|
2010-06-26 16:53:25 +02:00
|
|
|
(typing_eqs h eq_list;
|
2010-06-29 11:18:50 +02:00
|
|
|
(*update clock info in variables descriptions *)
|
2010-07-23 22:06:06 +02:00
|
|
|
let set_clock vd = { vd with v_clock = ck_repr (Env.find vd.v_ident h) } in
|
2010-06-29 11:18:50 +02:00
|
|
|
{ (node) with
|
|
|
|
n_input = List.map set_clock i_list;
|
|
|
|
n_output = List.map set_clock o_list;
|
|
|
|
n_local = List.map set_clock l_list })
|
|
|
|
|
2010-06-18 11:50:35 +02:00
|
|
|
let program (({ p_nodes = p_node_list } as p)) =
|
|
|
|
{ (p) with p_nodes = List.map typing_node p_node_list; }
|
2010-06-26 16:53:25 +02:00
|
|
|
|