First try at a normalization in Heptagon
I can't see if it compiles yet
This commit is contained in:
		
							parent
							
								
									2c7b609d2e
								
							
						
					
					
						commit
						cbf92beba2
					
				
					 4 changed files with 257 additions and 363 deletions
				
			
		|  | @ -53,6 +53,9 @@ let compile_program p = | |||
|   (* Every *) | ||||
|   let p = pass "Every" true Every.program p pp in | ||||
| 
 | ||||
|   (* Normalization *) | ||||
|   let p = pass "Normalization" true Normalize.program p pp in | ||||
| 
 | ||||
|   (* Block flatten *) | ||||
|   let p = pass "Block" true Block.program p pp in | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										253
									
								
								compiler/heptagon/transformations/normalize.ml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										253
									
								
								compiler/heptagon/transformations/normalize.ml
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,253 @@ | |||
| (**************************************************************************) | ||||
| (*                                                                        *) | ||||
| (*  Heptagon                                                              *) | ||||
| (*                                                                        *) | ||||
| (*  Author : Marc Pouzet                                                  *) | ||||
| (*  Organization : Demons, LRI, University of Paris-Sud, Orsay            *) | ||||
| (*                                                                        *) | ||||
| (**************************************************************************) | ||||
| open Misc | ||||
| open Initial | ||||
| open Names | ||||
| open Idents | ||||
| open Signature | ||||
| open Heptagon | ||||
| open Types | ||||
| open Clocks | ||||
| 
 | ||||
| 
 | ||||
| (** Normalization pass | ||||
|     The normal form of the language is given in the manual *) | ||||
| 
 | ||||
| module Error = | ||||
| struct | ||||
|   type error = | ||||
|     | Eunsupported_language_construct | ||||
| 
 | ||||
|   let message loc kind = | ||||
|     begin match kind with | ||||
|       | Eunsupported_language_construct -> | ||||
|           eprintf "%aThis construct is not supported by MiniLS.@." | ||||
|             print_location loc | ||||
|     end; | ||||
|     raise Errors.Error | ||||
| end | ||||
| 
 | ||||
| let is_list e = match e.e_desc with  | ||||
|  | Eapp({ a_op = Etuple }, e_list, _)  | ||||
|  | Econst { se_desc = Stuple se_list } -> true | ||||
|  | _ -> false | ||||
| 
 | ||||
| let e_to_e_list e = match e.e_desc with | ||||
|   | Eapp({ a_op = Etuple }, e_list, _) -> e_list | ||||
|   | Econst { se_desc = Stuple se_list } -> | ||||
|       exp_list_of_static_exp_list se_list | ||||
| 
 | ||||
| let flatten_e_list l = | ||||
|   let flatten = function | ||||
|     | { e_desc = Eapp({ a_op =  Etuple }, l, _) } -> l | ||||
|     | e -> [e] | ||||
|   in | ||||
|     List.flatten (List.map flatten l) | ||||
| 
 | ||||
| let equation (d_list, eq_list) e = | ||||
|   let add_one_var ty d_list = | ||||
|     let n = Idents.gen_var "normalize" "v" in | ||||
|     let d_list = (mk_var_dec ~clock:e.e_ck n ty) :: d_list in | ||||
|       n, d_list | ||||
|   in | ||||
|     match e.e_ty with | ||||
|       | Tprod ty_list -> | ||||
|           let var_list, d_list = | ||||
|             mapfold (fun d_list ty -> add_one_var ty d_list) d_list ty_list in | ||||
|           let pat_list = List.map (fun n -> Evarpat n) var_list in | ||||
|           let eq_list = (mk_equation (Etuplepat pat_list) e) :: eq_list in | ||||
|           let e_list = List.map2 | ||||
|             (fun n ty -> mk_exp ~ty:ty (Evar n)) var_list ty_list in | ||||
|           let e = Eapp(mk_app Etuple, e_list, None) in | ||||
|             (d_list, eq_list), e | ||||
|       | _ -> | ||||
|           let n, d_list = add_one_var e.e_ty d_list in | ||||
|           let eq_list = (mk_equation (Evarpat n) e) :: eq_list in | ||||
|             (d_list, eq_list), Evar n | ||||
| 
 | ||||
| (* [(e1,...,ek) when C(n) = (e1 when C(n),...,ek when C(n))] *) | ||||
| let rec whenc context e c n = | ||||
|   let when_on_c c n e = | ||||
|     { e with e_desc = Ewhen(e, c, n); e_ck = Con(e.e_ck, c, n) } | ||||
|   in | ||||
|     if is_list e then ( | ||||
|       let e_list = List.map (when_on_c c n) (e_to_e_list e) in | ||||
|           context, { e with e_desc = Eapp (app, e_list, r); | ||||
|                             e_ck = Con(e.e_ck, c, n) } | ||||
|     ) else | ||||
|       context, when_on_c c n e | ||||
| 
 | ||||
| let const e c = | ||||
|   let rec const = function | ||||
|     | Cbase | Cvar { contents = Cindex _ } -> c | ||||
|     | Con(ck_on, tag, x) -> | ||||
|         Ewhen({ e with e_desc = const ck_on; e_ck = ck_on }, tag, x) | ||||
|     | Cvar { contents = Clink ck } -> const ck in | ||||
|   const e.e_ck | ||||
| 
 | ||||
| type kind = ExtValue | Any | ||||
| 
 | ||||
| let add context expected_kind ({ e_desc = de } as e) = | ||||
|   let up = match de, expected_kind with | ||||
|     | (Evar _ | Eapp ({ a_op = Efield }, _, _) | Ewhen _ | ||||
|       | Eapp ({ a_op = Etuple }, _, _) | Econst) , ExtValue -> false | ||||
|     | _ , ExtValue -> true | ||||
|     | _ -> false in | ||||
|   if up then | ||||
|     let context, n = equation context e in | ||||
|       context, { e with e_desc = n } | ||||
|   else  | ||||
|     context, e | ||||
| 
 | ||||
| let rec translate kind context e = | ||||
|   let context, e = match e.e_desc with | ||||
|     | Econst c -> context, { e with e_desc = const e (Econst c) } | ||||
|     | Evar _ -> context, e | ||||
|     | Epre(v, e1) -> fby kind context e v e1 | ||||
|     | Efby({ e_desc = Econst v }, e1) -> fby kind context e (Some v) e1 | ||||
|     | Estruct l -> | ||||
| 	let translate_field (f, e) context = | ||||
| 	  let context, e = translate ExtValue context e in | ||||
|             context, (f, e) | ||||
| 	in | ||||
|         let context, l = mapfold translate_field context l in | ||||
|           context, { e with e_desc = Estruct l } | ||||
|     | Ewhen(e1, c, n) -> | ||||
|         let context, e1 = translate kind context e1 in | ||||
|           whenc context e1 c n | ||||
|     | Emerge(n, tag_e_list) -> | ||||
| 	merge context n tag_e_list | ||||
|     | Eapp({ a_op = Eifthenelse }, [e1; e2; e3], _) -> | ||||
|         ifthenelse context e1 e2 e3 | ||||
|     | Eapp(app, e_list, r) -> | ||||
|         let context, e_list = translate_list ExtValue context e_list in | ||||
|           context, { e with e_desc = Eapp(app, flatten_e_list e_list, r) } | ||||
|     | Eiterator (it, app, n, pe_list, e_list, reset) -> | ||||
|       (* normalize anonymous nodes *) | ||||
|       (match app.a_op with | ||||
|         | Enode f when Itfusion.is_anon_node f -> | ||||
| 	    let nd = Itfusion.find_anon_node f in | ||||
|             let d_list, eq_list = translate_eq_list nd.n_local nd.n_equs in | ||||
| 	    let nd = { nd with n_equs = eq_list; n_local = d_list } in | ||||
| 	      Itfusion.replace_anon_node f nd | ||||
|         | _ -> () ); | ||||
|         let context, pe_list = translate_list ExtValue context pe_list in | ||||
|         let context, e_list = translate_list ExtValue context e_list in | ||||
|         context, { e with e_desc = Eiterator(it, app, n, flatten_e_list pe_list, | ||||
|                                              flatten_e_list e_list, reset) } | ||||
|     | Elast _ | Efby _ -> message e.e_loc Eunsupported_language_construct | ||||
|   in add context kind e | ||||
| 
 | ||||
| and translate_list kind context e_list = | ||||
|   match e_list with | ||||
|     | [] -> context, [] | ||||
|     | e :: e_list -> | ||||
|         let context, e = translate kind context e in | ||||
|         let context, e_list = translate_list kind context e_list in | ||||
|           context, e :: e_list | ||||
| 
 | ||||
| and fby kind context e v e1 = | ||||
|   let mk_fby c e = | ||||
|     mk_exp ~ty:e.e_ty ~loc:e.e_loc (Efby(Some c, e)) in | ||||
|   let mk_pre e = | ||||
|     mk_exp ~ty:e.e_ty ~loc:e.e_loc (Efby(None, e)) in | ||||
|   let e1 = translate ExtValue context e1 in | ||||
|   match e1.e_desc, v with | ||||
|     | Eapp({ a_op = Etuple } as app, e_list, r), | ||||
|       Some { se_desc = Stuple se_list } -> | ||||
|         let e_list = List.map2 mk_fby se_list e_list in | ||||
|         let e = { e with e_desc = Eapp(app, e_list, r) } in | ||||
|           translate kind context e | ||||
|     | Econst { se_desc = Stuple se_list }, | ||||
|       Some { se_desc = Stuple v_list } -> | ||||
|         let e_list = List.map2 mk_fby v_list | ||||
|           (exp_list_of_static_exp_list se_list) in | ||||
|         let e = { e with e_desc = Eapp(mk_app Etuple, e_list, None) } in | ||||
|           translate kind context e | ||||
|     | Eapp({ a_op = Etuple } as app, e_list, r), None -> | ||||
|         let e_list = List.map mk_pre e_list in | ||||
|         let e = { e with e_desc = Eapp(app, e_list, r) } in | ||||
|           translate kind context e | ||||
|     | Econst { se_desc = Stuple se_list }, None -> | ||||
|         let e_list = List.map mk_pre (exp_list_of_static_exp_list se_list) in | ||||
|         let e = { e with e_desc = Eapp(app, e_list, r) } in | ||||
|           translate kind context e | ||||
|     | _ -> context, { e with e_desc = Efby(v, e1) } | ||||
| 
 | ||||
| (** transforms [if x then e1, ..., en else e'1,..., e'n]  | ||||
|     into [if x then e1 else e'1, ..., if x then en else e'n]  *) | ||||
| and ifthenelse context e e1 e2 e3 = | ||||
|   let context, e1 = translate ExtValue context e1 in | ||||
|   let context, e2 = translate ExtValue context e2 in | ||||
|   let context, e3 = translate ExtValue context e3 in | ||||
|   let mk_ite_list e2_list e3_list = | ||||
|     let mk_ite e2 e3 =  | ||||
|       mk_exp ~ty:e2.e_ty ~loc:e.e_loc (Eifthenelse(e1, e2, e3))  | ||||
|     in | ||||
|     let e_list = List.map2 mk_ite e2_list e3_list in | ||||
|       { e with e_desc = Eapp(mk_app Etuple, e_list, None) } | ||||
|   in | ||||
|     if is_list e2 then  | ||||
|       context, mk_ite_list context (e_to_e_list e2) (e_to_e_list e2) | ||||
|     else | ||||
|       context, { e with e_desc = Eifthenelse(e1, e2, e3)} | ||||
| 
 | ||||
| (** transforms [merge x (c1, (e11,...,e1n));...;(ck, (ek1,...,ekn))] into | ||||
|     [merge x (c1, e11)...(ck, ek1),..., merge x (c1, e1n)...(ck, ekn)]    *) | ||||
| and merge context e x c_e_list = | ||||
|     let translate_tag (tag, e) context = | ||||
|       let context, e = translate ExtValue context e in | ||||
|         context, (tag, e) | ||||
|     in | ||||
|     let mk_merge x c_list e_list = | ||||
|       let ty = (hd e_list).e_e_ty in | ||||
|       let t_e_list = List.map2 (fun t e -> (t,e)) c_list e_list in | ||||
| 	mk_exp ~ty:ty ~loc:e.e_loc (Emerge(x, t_e_list)) | ||||
|     in | ||||
|     let context, x = translate ExtValue context x in | ||||
|     let context, c_e_list = mapfold translate_tag context ta_list in | ||||
|       match c_e_list with | ||||
| 	| [] -> assert false | ||||
| 	| (_,e)::_ -> | ||||
| 	    if is_list e then  | ||||
| 	      let c_list = List.map (fun (t,_) -> t) c_e_list in | ||||
| 	      let e_lists = List.map (fun (_,e) -> e_to_e_list e) c_e_list in | ||||
| 	      let e_list = List.map (mk_merge x c_list) e_lists in | ||||
| 		context, { e with e_desc = Eapp(mk_app Etuple, e_list, None) } | ||||
| 	    else | ||||
| 	      context, { e with e_desc = Emerge(x, c_e_list) } | ||||
| 
 | ||||
| (* applies distribution rules *) | ||||
| (* [x = v fby e] should verifies that x is local *) | ||||
| (* [(p1,...,pn) = (e1,...,en)] into [p1 = e1;...;pn = en] *) | ||||
| and distribute ((d_list, eq_list) as context) pat e = | ||||
|   match pat, e.e_desc with | ||||
|     | Evarpat(x), Efby _ when not (vd_mem x d_list) -> | ||||
|         let (d_list, eq_list), n = equation context e in | ||||
|           d_list, | ||||
|         { eq with eq_rhs = { e with e_desc = n } } :: eq_list | ||||
|     | Etuplepat(pat_list), Eapp({ a_op = Etuple }, e_list, _) -> | ||||
|         let eqs = List.map2 mk_equation pat_list e_list in | ||||
|           List.fold_left distribute context eqs | ||||
|     | _ -> d_list, Eeq(pat, e) :: eq_list  | ||||
| 
 | ||||
| and translate_eq context eq = match eq with | ||||
|   | Eeq (pat, e) ->  | ||||
|       let context, e = translate Any context e in | ||||
| 	distribute context pat e | ||||
|   | _ -> raise Fallback | ||||
| 
 | ||||
| let block funs _ b = | ||||
|   let _, (v_acc, eq_acc) = Hept_mapfold.block funs ([],[]) b in | ||||
|     { b with b_local = v_acc@b.b_local; b_equs = eq_acc}, ([], []) | ||||
| 
 | ||||
| let program p = | ||||
|   let funs = { defaults with eq = translate_eq; } in | ||||
|   let p, _ = Hept_mapfold.program funs ([], []) p in | ||||
|     p | ||||
|  | @ -48,7 +48,7 @@ and extvalue = { | |||
| and extvalue_desc = | ||||
|   | Wconst of static_exp | ||||
|   | Wvar of var_ident | ||||
|   | Wfield of ext_value * field_name | ||||
|   | Wfield of extvalue * field_name | ||||
|   | Wwhen of extvalue * constructor_name * var_ident | ||||
|                        (** extvalue when Constructor(ident) *) | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,362 +0,0 @@ | |||
| (**************************************************************************) | ||||
| (*                                                                        *) | ||||
| (*  Heptagon                                                              *) | ||||
| (*                                                                        *) | ||||
| (*  Author : Marc Pouzet                                                  *) | ||||
| (*  Organization : Demons, LRI, University of Paris-Sud, Orsay            *) | ||||
| (*                                                                        *) | ||||
| (**************************************************************************) | ||||
| open Misc | ||||
| open Initial | ||||
| open Names | ||||
| open Idents | ||||
| open Signature | ||||
| open Minils | ||||
| open Mls_utils | ||||
| open Types | ||||
| open Clocks | ||||
| 
 | ||||
| let flatten_e_list l = | ||||
|   let flatten = function | ||||
|     | { e_desc = Eapp({ a_op =  Etuple }, l, _) } -> l | ||||
|     | e -> [e] | ||||
|   in | ||||
|     List.flatten (List.map flatten l) | ||||
| 
 | ||||
| let equation (d_list, eq_list) e = | ||||
|   let add_one_var ty d_list = | ||||
|     let n = Idents.gen_var "normalize" "v" in | ||||
|     let d_list = (mk_var_dec ~clock:e.e_ck n ty) :: d_list in | ||||
|       n, d_list | ||||
|   in | ||||
|     match e.e_ty with | ||||
|       | Tprod ty_list -> | ||||
|           let var_list, d_list = | ||||
|             mapfold (fun d_list ty -> add_one_var ty d_list) d_list ty_list in | ||||
|           let pat_list = List.map (fun n -> Evarpat n) var_list in | ||||
|           let eq_list = (mk_equation (Etuplepat pat_list) e) :: eq_list in | ||||
|           let e_list = List.map2 | ||||
|             (fun n ty -> mk_exp ~ty:ty (Evar n)) var_list ty_list in | ||||
|           let e = Eapp(mk_app Etuple, e_list, None) in | ||||
|             (d_list, eq_list), e | ||||
|       | _ -> | ||||
|           let n, d_list = add_one_var e.e_ty d_list in | ||||
|           let eq_list = (mk_equation (Evarpat n) e) :: eq_list in | ||||
|             (d_list, eq_list), Evar n | ||||
| 
 | ||||
| let intro context e = | ||||
|   match e.e_desc with | ||||
|     | Evar n -> context, Evar n | ||||
|     | _ -> equation context e | ||||
| 
 | ||||
| (* distribution: [(e1,...,ek) when C(n) = (e1 when C(n),...,ek when C(n))] *) | ||||
| let rec whenc context e c n = | ||||
|   let when_on_c c n e = | ||||
|     { e with e_desc = Ewhen(e, c, n); e_ck = Con(e.e_ck, c, n) } in | ||||
| 
 | ||||
|   match e.e_desc with | ||||
|     | Eapp({ a_op = Etuple } as app, e_list, r) -> | ||||
|         let context, e_list = | ||||
|           List.fold_right | ||||
|             (fun e (context, e_list) -> let context, e = whenc context e c n in | ||||
|              (context, e :: e_list)) | ||||
|             e_list (context, []) in | ||||
|         context, { e with e_desc = Eapp (app, e_list, r); | ||||
|                      e_ck = Con(e.e_ck, c, n) } | ||||
|     | Econst { se_desc = Stuple se_list } -> | ||||
|         let e_list = exp_list_of_static_exp_list se_list in | ||||
|         let context, e_list = | ||||
|           List.fold_right | ||||
|             (fun e (context, e_list) -> let context, e = whenc context e c n in | ||||
|                (context, e :: e_list)) | ||||
|             e_list (context, []) in | ||||
|         context, { e with e_desc = Eapp (mk_app Etuple, e_list, None); | ||||
|                      e_ck = Con(e.e_ck, c, n) } | ||||
| 
 | ||||
|           (* | Emerge _ -> let context, x = equation context e in | ||||
|              context, when_on_c c n { e with e_desc = Evar(x) } *) | ||||
|     | _ -> context, when_on_c c n e | ||||
| 
 | ||||
| (* transforms [merge x (c1, (e11,...,e1n));...;(ck, (ek1,...,ekn))] into *) | ||||
| (* [merge x (c1, e11)...(ck, ek1),..., merge x (c1, e1n)...(ck, ekn)]    *) | ||||
| let rec merge e x ci_a_list = | ||||
|   let rec split ci_tas_list = | ||||
|     match ci_tas_list with | ||||
|       | [] | (_, _, []) :: _ -> [], [] | ||||
|       | (ci, b, a :: tas) :: ci_tas_list -> | ||||
|           let ci_ta_list, ci_tas_list = split ci_tas_list in | ||||
|           (ci, a) :: ci_ta_list, (ci, b, tas) :: ci_tas_list in | ||||
|   let rec distribute ci_tas_list = | ||||
|     match ci_tas_list with | ||||
|       | [] | (_, _, []) :: _ -> [] | ||||
|       | (_, b, (eo :: _)) :: _ -> | ||||
|           let ci_ta_list, ci_tas_list = split ci_tas_list in | ||||
|           let ci_tas_list = distribute ci_tas_list in | ||||
|           (if b then | ||||
|              { eo with e_desc = Emerge(x, ci_ta_list); | ||||
|                  e_ck = e.e_ck; e_loc = e.e_loc } | ||||
|            else | ||||
|              merge e x ci_ta_list) | ||||
|           :: ci_tas_list in | ||||
|   let rec erasetuple ci_a_list = | ||||
|     match ci_a_list with | ||||
|       | [] -> [] | ||||
|       | (ci, { e_desc = Eapp({ a_op =  Etuple }, l, _) }) :: ci_a_list -> | ||||
|           (ci, false, l) :: erasetuple ci_a_list | ||||
|       | (ci, { e_desc = Econst { se_desc = Stuple se_list } }) :: ci_a_list -> | ||||
|           let l = exp_list_of_static_exp_list se_list in | ||||
|             (ci, false, l) :: erasetuple ci_a_list | ||||
|       | (ci, e) :: ci_a_list -> | ||||
|           (ci, true, [e]) :: erasetuple ci_a_list in | ||||
|   let ci_tas_list = erasetuple ci_a_list in | ||||
|   let ci_tas_list = distribute ci_tas_list in | ||||
|   match ci_tas_list with | ||||
|     | [e] -> e | ||||
|     | l -> { e with e_desc = Eapp(mk_app Etuple, l, None) } | ||||
| 
 | ||||
| let ifthenelse context e1 e2 e3 = | ||||
|   let context, n = intro context e1 in | ||||
|   let n = (match n with Evar n -> n | _ -> assert false) in | ||||
|   let context, e2 = whenc context e2 ptrue n in | ||||
|   let context, e3 = whenc context e3 pfalse n in | ||||
|     context, merge e1 n [ptrue, e2; pfalse, e3] | ||||
| 
 | ||||
| let const e c = | ||||
|   let rec const = function | ||||
|     | Cbase | Cvar { contents = Cindex _ } -> c | ||||
|     | Con(ck_on, tag, x) -> | ||||
|         Ewhen({ e with e_desc = const ck_on; e_ck = ck_on }, tag, x) | ||||
|     | Cvar { contents = Clink ck } -> const ck in | ||||
|   const e.e_ck | ||||
| 
 | ||||
| (* normal form for expressions and equations:                              *) | ||||
| (* - e ::= op(e,...,e) | x | C | e when C(x)                               *) | ||||
| (* - act ::= e | merge x (C1 -> act) ... (Cn -> act) | (act,...,act)       *) | ||||
| (* - eq ::= [x = v fby e] | [pat = act] | [pat = f(e1,...,en) every n     *) | ||||
| (* - A-normal form: (e1,...,en) when c(x) = (e1 when c(x),...,en when c(x) *) | ||||
| type kind = VRef | Exp | Act | Any | ||||
| 
 | ||||
| let function_args_kind = Exp | ||||
| let merge_kind = Act | ||||
| 
 | ||||
| let rec constant e = match e.e_desc with | ||||
|   | Econst _ -> true | ||||
|   | Ewhen(e, _, _) -> constant e | ||||
|   | Evar _ -> true | ||||
|   | _ -> false | ||||
| 
 | ||||
| let add context expected_kind ({ e_desc = de } as e) = | ||||
|   let up = match de, expected_kind with | ||||
|     | (Evar _ | Eapp ({ a_op = Efield }, _, _)) , VRef -> false | ||||
|     | _ , VRef -> true | ||||
|     | Eapp ({ a_op = Efun n }, _, _), | ||||
|         (Exp|Act) when is_op n -> false | ||||
|     | Eapp ({ a_op = Eequal }, _, _), (Exp|Act) -> false | ||||
|     | ( Emerge _ | Eapp _ | Eiterator _ | Efby _ ), Exp -> true | ||||
|     | ( Eapp({ a_op = Efun _ | Enode _ }, _, _) | ||||
|       | Eiterator _ | Efby _ ), Act -> true | ||||
|     | _ -> false in | ||||
|   if up then | ||||
|     let context, n = equation context e in | ||||
|     context, { e with e_desc = n } | ||||
|   else context, e | ||||
| 
 | ||||
| let rec translate kind context e = | ||||
|   let context, e = match e.e_desc with | ||||
|     | Emerge(n, tag_e_list) -> | ||||
|         let context, ta_list = | ||||
|           List.fold_right | ||||
|             (fun (tag, e) (context, ta_list) -> | ||||
|                let context, act = translate merge_kind context e in | ||||
|                context, ((tag, act) :: ta_list)) | ||||
|             tag_e_list (context, []) in | ||||
|         context, merge e n ta_list | ||||
|     | Ewhen(e1, c, n) -> | ||||
|         let context, e1 = translate kind context e1 in | ||||
|         whenc context e1 c n | ||||
|     | Efby(v, e1) -> | ||||
|         let context, e1 = translate Act context e1 in | ||||
|           fby kind context e v e1 | ||||
|     | Evar _ -> context, e | ||||
|     | Econst c -> context, { e with e_desc = const e (Econst c) } | ||||
|     | Estruct(l) -> | ||||
|         let context, l = | ||||
|           List.fold_right | ||||
|             (fun (field, e) (context, field_desc_list) -> | ||||
|                let context, e = translate Exp context e in | ||||
|                context, ((field, e) :: field_desc_list)) | ||||
|             l (context, []) in | ||||
|         context, { e with e_desc = Estruct l } | ||||
|     | Eapp({ a_op = Eifthenelse }, [e1; e2; e3], _) -> | ||||
|         let context, e1 = translate Any context e1 in | ||||
|         let context, e2 = translate Act context e2 in | ||||
|         let context, e3 = translate Act context e3 in | ||||
|           ifthenelse context e1 e2 e3 | ||||
|     | Eapp({ a_op = Efun _ | Enode _ } as app, e_list, r) -> | ||||
|         let context, e_list = | ||||
|           translate_list function_args_kind context e_list in | ||||
|           context, { e with e_desc = Eapp(app, flatten_e_list e_list, r) } | ||||
|     | Eapp(app, e_list, r) -> | ||||
|         let context, e_list = translate_app kind context app.a_op e_list in | ||||
|           context, { e with e_desc = Eapp(app, e_list, r) } | ||||
|     | Eiterator (it, app, n, pe_list, e_list, reset) -> | ||||
|       (* normalize anonymous nodes *) | ||||
|       (match app.a_op with | ||||
|         | Enode f when Itfusion.is_anon_node f -> | ||||
|     let nd = Itfusion.find_anon_node f in | ||||
|           let d_list, eq_list = translate_eq_list nd.n_local nd.n_equs in | ||||
|     let nd = { nd with n_equs = eq_list; n_local = d_list } in | ||||
|       Itfusion.replace_anon_node f nd | ||||
|         | _ -> () ); | ||||
| 
 | ||||
|         (* Add an intermediate equation for each array lit argument. *) | ||||
|         let translate_iterator_arg_list context e_list = | ||||
|           let add e context = | ||||
|             let kind = match e.e_desc with | ||||
|               | Econst { se_desc = Sarray _; } -> VRef | ||||
|               | _ -> function_args_kind in | ||||
|             translate kind context e in | ||||
|           Misc.mapfold_right add e_list context in | ||||
| 
 | ||||
|         let context, pe_list = | ||||
|           translate_list function_args_kind context pe_list in | ||||
|         let context, e_list = | ||||
|           translate_iterator_arg_list context e_list in | ||||
|         context, { e with e_desc = Eiterator(it, app, n, flatten_e_list pe_list, | ||||
|                                              flatten_e_list e_list, reset) } | ||||
|   in add context kind e | ||||
| 
 | ||||
| and translate_app kind context op e_list = | ||||
|   match op with | ||||
|     | Eequal -> | ||||
|         let context, e_list = | ||||
|           translate_list function_args_kind context e_list in | ||||
|         context, e_list | ||||
|     | Etuple -> | ||||
|         let context, e_list = translate_list kind context e_list in | ||||
|           context, e_list | ||||
|     | Efield -> | ||||
|         let e' = assert_1 e_list in | ||||
|         let context, e' = translate Exp context e' in | ||||
|           context, [e'] | ||||
|     | Efield_update -> | ||||
|         let e1, e2 = assert_2 e_list in | ||||
|         let context, e1 = translate VRef context e1 in | ||||
|         let context, e2 = translate Exp context e2 in | ||||
|           context, [e1; e2] | ||||
|     | Earray -> | ||||
|         let context, e_list = translate_list kind context e_list in | ||||
|           context, e_list | ||||
|     | Earray_fill -> | ||||
|         let e = assert_1 e_list in | ||||
|         let context, e = translate Exp context e in | ||||
|           context, [e] | ||||
|     | Eselect -> | ||||
|         let e' = assert_1 e_list in | ||||
|         let context, e' = translate VRef context e' in | ||||
|           context, [e'] | ||||
|     | Eselect_dyn -> | ||||
|         let e1, e2, idx = assert_2min e_list in | ||||
|         let context, e1 = translate VRef context e1 in | ||||
|         let context, idx = translate_list Exp context idx in | ||||
|         let context, e2 = translate Exp context e2 in | ||||
|         context, e1::e2::idx | ||||
|     | Eselect_trunc -> | ||||
|         let e1, idx = assert_1min e_list in | ||||
|         let context, e1 = translate VRef context e1 in | ||||
|         let context, idx = translate_list Exp context idx in | ||||
|         context, e1::idx | ||||
|     | Eupdate -> | ||||
|         let e1, e2, idx = assert_2min e_list in | ||||
|         let context, e1 = translate VRef context e1 in | ||||
|         let context, idx = translate_list Exp context idx in | ||||
|         let context, e2 = translate Exp context e2 in | ||||
|           context, e1::e2::idx | ||||
|     | Eselect_slice -> | ||||
|         let e' = assert_1 e_list in | ||||
|         let context, e' = translate VRef context e' in | ||||
|         context, [e'] | ||||
|     | Econcat -> | ||||
|         let e1, e2 = assert_2 e_list in | ||||
|         let context, e1 = translate VRef context e1 in | ||||
|         let context, e2 = translate VRef context e2 in | ||||
|         context, [e1; e2] | ||||
|     | Enode _ | Efun _ | Eifthenelse _ -> | ||||
|       assert false (*already done in translate*) | ||||
| 
 | ||||
| and translate_list kind context e_list = | ||||
|   match e_list with | ||||
|       [] -> context, [] | ||||
|     | e :: e_list -> | ||||
|         let context, e = translate kind context e in | ||||
|         let context, e_list = translate_list kind context e_list in | ||||
|         context, e :: e_list | ||||
| 
 | ||||
| and fby kind context e v e1 = | ||||
|   let mk_fby c e = | ||||
|     mk_exp ~ty:e.e_ty ~loc:e.e_loc (Efby(Some c, e)) in | ||||
|   let mk_pre e = | ||||
|     mk_exp ~ty:e.e_ty ~loc:e.e_loc (Efby(None, e)) in | ||||
|   match e1.e_desc, v with | ||||
|     | Eapp({ a_op = Etuple } as app, e_list, r), | ||||
|       Some { se_desc = Stuple se_list } -> | ||||
|         let e_list = List.map2 mk_fby se_list e_list in | ||||
|         let e = { e with e_desc = Eapp(app, e_list, r) } in | ||||
|           translate kind context e | ||||
|     | Econst { se_desc = Stuple se_list }, | ||||
|       Some { se_desc = Stuple v_list } -> | ||||
|         let e_list = List.map2 mk_fby v_list | ||||
|           (exp_list_of_static_exp_list se_list) in | ||||
|         let e = { e with e_desc = Eapp(mk_app Etuple, e_list, None) } in | ||||
|           translate kind context e | ||||
|     | Eapp({ a_op = Etuple } as app, e_list, r), None -> | ||||
|         let e_list = List.map mk_pre e_list in | ||||
|         let e = { e with e_desc = Eapp(app, e_list, r) } in | ||||
|           translate kind context e | ||||
|     | Econst { se_desc = Stuple _ }, None -> | ||||
|         context, e1 | ||||
|     | _ -> | ||||
|         let context, e1' = | ||||
|           if constant e1 then context, e1 | ||||
|           else let context, n = equation context e1 in | ||||
|           context, { e1 with e_desc = n } in | ||||
|         context, { e with e_desc = Efby(v, e1') } | ||||
| 
 | ||||
| and translate_eq context eq = | ||||
|   (* applies distribution rules *) | ||||
|   (* [x = v fby e] should verifies that x is local *) | ||||
|   (* [(p1,...,pn) = (e1,...,en)] into [p1 = e1;...;pn = en] *) | ||||
|   let rec distribute ((d_list, eq_list) as context) | ||||
|       ({ eq_lhs = pat; eq_rhs = e } as eq) = | ||||
|     match pat, e.e_desc with | ||||
|       | Evarpat(x), Efby _ when not (vd_mem x d_list) -> | ||||
|           let (d_list, eq_list), n = equation context e in | ||||
|           d_list, | ||||
|           { eq with eq_rhs = { e with e_desc = n } } :: eq_list | ||||
|       | Etuplepat(pat_list), Eapp({ a_op = Etuple }, e_list, _) -> | ||||
|           let eqs = List.map2 mk_equation pat_list e_list in | ||||
|           List.fold_left distribute context eqs | ||||
|       | _ -> d_list, eq :: eq_list in | ||||
| 
 | ||||
|   let context, e = translate Any context eq.eq_rhs in | ||||
|   distribute context { eq with eq_rhs = e } | ||||
| 
 | ||||
| and translate_eq_list d_list eq_list = | ||||
|   List.fold_left | ||||
|     (fun context eq -> translate_eq context eq) | ||||
|     (d_list, []) eq_list | ||||
| 
 | ||||
| let translate_contract ({ c_eq = eq_list; c_local = d_list } as c) = | ||||
|   let d_list,eq_list = translate_eq_list d_list eq_list in | ||||
|   { c with | ||||
|       c_local = d_list; | ||||
|       c_eq = eq_list } | ||||
| 
 | ||||
| let translate_node ({ n_contract = contract; | ||||
|                       n_local = d_list; n_equs = eq_list } as node) = | ||||
|   let contract = optional translate_contract contract in | ||||
|   let d_list, eq_list = translate_eq_list d_list eq_list in | ||||
|   { node with n_contract = contract; n_local = d_list; n_equs = eq_list } | ||||
| 
 | ||||
| let program ({ p_nodes = p_node_list } as p) = | ||||
|   { p with p_nodes = List.map translate_node p_node_list } | ||||
		Loading…
	
		Reference in a new issue
	
	 Cédric Pasteur
						Cédric Pasteur