From 333e3a25e7862b51b01a590fd526c0a5dc7b18fa Mon Sep 17 00:00:00 2001 From: ploc <ploc@garoche.net> Date: Mon, 18 Dec 2017 09:57:21 +0100 Subject: [PATCH] [general] Refactor get_node_eqs to produce (eqs, auts) with automatons --- src/access.ml | 4 +- src/algebraicLoop.ml | 5 +- src/causality.ml | 43 ++++-- src/clock_calculus.ml | 16 +- src/clocks.ml | 32 +++- src/corelang.ml | 343 ++++++++++++++++++++++++++---------------- src/corelang.mli | 13 +- src/dimension.ml | 10 +- src/inliner.ml | 168 +++++++++++---------- src/machine_code.ml | 8 +- src/mpfr.ml | 6 +- src/mutation.ml | 6 +- src/normalization.ml | 4 +- src/printers.ml | 3 +- src/stateless.ml | 6 +- src/types.ml | 1 + src/typing.ml | 6 +- 17 files changed, 428 insertions(+), 246 deletions(-) diff --git a/src/access.ml b/src/access.ml index 0797d42e..a3754a08 100755 --- a/src/access.ml +++ b/src/access.ml @@ -80,7 +80,9 @@ let check_node nd = let checks = List.fold_left check_var_decl checks (get_node_vars nd) in let checks = - List.fold_left (fun checks eq -> check_expr checks eq.eq_rhs) checks (get_node_eqs nd) in + let eqs, auts = get_node_eqs nd in + assert (auts = []); (* Not checking automata yet . *) + List.fold_left (fun checks eq -> check_expr checks eq.eq_rhs) checks eqs in nd.node_checks <- CSet.elements checks let check_top_decl decl = diff --git a/src/algebraicLoop.ml b/src/algebraicLoop.ml index f863bb7e..36ca3590 100644 --- a/src/algebraicLoop.ml +++ b/src/algebraicLoop.ml @@ -43,8 +43,9 @@ struct let resolve node partition : call list = let partition = ISet.of_list partition in (* Preprocessing calls: associate to each of them the eq.lhs associated *) - let eqs = get_node_eqs node in - let calls_expr = Causality.NodeDep.get_calls (fun _ -> true) eqs in + let calls_expr = Causality.NodeDep.get_calls (fun _ -> true) node in + let eqs, auts = get_node_eqs node in + assert (auts = []); (* TODO voir si on peut acceder directement aux eqs qui font les calls *) let calls = List.map ( fun expr -> let eq = List.find (fun eq -> diff --git a/src/causality.ml b/src/causality.ml index 447b464e..7e7a42cc 100644 --- a/src/causality.ml +++ b/src/causality.ml @@ -88,8 +88,14 @@ let add_vertices vtc g = let new_graph () = IdentDepGraph.create () + module ExprDep = struct - + let get_node_eqs nd = + let eqs, auts = get_node_eqs nd in + if auts != [] then assert false (* No call on causality on a Lustre model + with automaton. They should be expanded by now. *); + eqs + let instance_var_cpt = ref 0 (* read vars represent input/mem read-only vars, @@ -317,12 +323,27 @@ module NodeDep = struct | Expr_appl (id, args, _) -> Some (id, expr_list_of_expr args) | _ -> None - let get_calls prednode eqs = - let deps = - List.fold_left - (fun accu eq -> ESet.union accu (get_expr_calls prednode eq.eq_rhs)) - ESet.empty - eqs in + let get_calls prednode nd = + let accu f init objl = List.fold_left (fun accu o -> ESet.union accu (f o)) init objl in + let get_eq_calls eq = get_expr_calls prednode eq.eq_rhs in + let rec get_stmt_calls s = + match s with Eq eq -> get_eq_calls eq | Aut aut -> get_aut_calls aut + and get_aut_calls aut = + let get_handler_calls h = + let get_cond_calls c = accu (fun (_,e,_,_) -> get_expr_calls prednode e) ESet.empty c in + let until = get_cond_calls h.hand_until in + let unless = get_cond_calls h.hand_unless in + let calls = ESet.union until unless in + let calls = accu get_stmt_calls calls h.hand_stmts in + let calls = accu (fun a -> get_expr_calls prednode a.assert_expr) calls h.hand_asserts in + (* let calls = accu xx calls h.hand_annots in *) (* TODO: search for calls in eexpr *) + calls + in + accu get_handler_calls ESet.empty aut.aut_handlers + in + let eqs, auts = get_node_eqs nd in + let deps = accu get_eq_calls ESet.empty eqs in + let deps = accu get_aut_calls deps auts in ESet.elements deps let dependence_graph prog = @@ -335,7 +356,7 @@ module NodeDep = struct let accu = add_vertices [nd.node_id] accu in let deps = List.map (fun e -> fst (desome (get_callee e))) - (get_calls (fun _ -> true) (get_node_eqs nd)) + (get_calls (fun _ -> true) nd) in (* Adding assert expressions deps *) let deps_asserts = @@ -378,7 +399,7 @@ module NodeDep = struct match td.top_decl_desc with | Node nd -> let prednode n = is_generic_node (Hashtbl.find node_table n) in - nd.node_gencalls <- get_calls prednode (get_node_eqs nd) + nd.node_gencalls <- get_calls prednode nd | _ -> () ) prog @@ -459,7 +480,9 @@ module CycleDetection = struct - a modified acyclic version of [g] *) let break_cycles node mems g = - let (mem_eqs, non_mem_eqs) = List.partition (fun eq -> List.exists (fun v -> ISet.mem v mems) eq.eq_lhs) (get_node_eqs node) in + let eqs , auts = get_node_eqs node in + assert (auts = []); (* TODO: check: For the moment we assume that auts are expanded by now *) + let (mem_eqs, non_mem_eqs) = List.partition (fun eq -> List.exists (fun v -> ISet.mem v mems) eq.eq_lhs) eqs in let rec break vdecls mem_eqs g = let scc_l = Cycles.scc_list g in let wrong = List.filter (wrong_partition g) scc_l in diff --git a/src/clock_calculus.ml b/src/clock_calculus.ml index 6c368487..e585db3b 100755 --- a/src/clock_calculus.ml +++ b/src/clock_calculus.ml @@ -681,7 +681,9 @@ let clock_node env loc nd = let new_env = clock_var_decl_list env false nd.node_inputs in let new_env = clock_var_decl_list new_env true nd.node_outputs in let new_env = clock_var_decl_list new_env true nd.node_locals in - List.iter (clock_eq new_env) (get_node_eqs nd); + let eqs, auts = get_node_eqs nd in (* TODO XXX: perform the clocking on auts. + For the moment, it is ignored *) + List.iter (clock_eq new_env) eqs; let ck_ins = clock_of_vlist nd.node_inputs in let ck_outs = clock_of_vlist nd.node_outputs in let ck_node = new_ck (Carrow (ck_ins,ck_outs)) false in @@ -690,14 +692,14 @@ let clock_node env loc nd = (* Local variables may contain first-order carrier variables that should be generalized. That's not the case for types. *) try_generalize ck_node loc; -(* - List.iter (fun vdecl -> try_generalize vdecl.var_clock vdecl.var_loc) nd.node_inputs; - List.iter (fun vdecl -> try_generalize vdecl.var_clock vdecl.var_loc) nd.node_outputs;*) + (* + List.iter (fun vdecl -> try_generalize vdecl.var_clock vdecl.var_loc) nd.node_inputs; + List.iter (fun vdecl -> try_generalize vdecl.var_clock vdecl.var_loc) nd.node_outputs;*) (*List.iter (fun vdecl -> try_generalize vdecl.var_clock vdecl.var_loc) nd.node_locals;*) (* TODO : Xavier pourquoi ai je cette erreur ? *) -(* if (is_main && is_polymorphic ck_node) then - raise (Error (loc,(Cannot_be_polymorphic ck_node))); -*) + (* if (is_main && is_polymorphic ck_node) then + raise (Error (loc,(Cannot_be_polymorphic ck_node))); + *) Log.report ~level:3 (fun fmt -> print_ck fmt ck_node); nd.node_clock <- ck_node; Env.add_value env nd.node_id ck_node diff --git a/src/clocks.ml b/src/clocks.ml index 8756e247..c148d482 100755 --- a/src/clocks.ml +++ b/src/clocks.ml @@ -33,7 +33,7 @@ and carrier_expr = {mutable carrier_desc: carrier_desc; mutable carrier_scoped: bool; carrier_id: int} - + type clock_expr = {mutable cdesc: clock_desc; mutable cscoped: bool; @@ -422,6 +422,36 @@ let uneval const cr = | Carry_name -> cr.carrier_desc <- Carry_const const | _ -> assert false + +(* Used in rename functions in Corelang. We have to propagate the renaming to + ids of variables clocking the signals *) + +(* Carrier are not renamed. They corresponds to enumerated type constants *) +(* +let rec rename_carrier f c = + { c with carrier_desc = rename_carrier_desc fvar c.carrier_desc } +and rename_carrier_desc f +let re = rename_carrier f + match cd with + | Carry_const id -> Carry_const (f id) + | Carry_link ce -> Carry_link (re ce) + | _ -> cd +*) + + +let rec rename_clock_expr fvar c = + { c with cdesc = rename_clock_desc fvar c.cdesc } +and rename_clock_desc fvar cd = + let re = rename_clock_expr fvar in + match cd with + | Carrow (c1, c2) -> Carrow (re c1, re c2) + | Ctuple cl -> Ctuple (List.map re cl) + | Con (c1, car, id) -> Con (re c1, car, fvar id) + | Cvar + | Cunivar -> cd + | Clink c -> Clink (re c) + | Ccarrying (car, c) -> Ccarrying (car, re c) + (* Local Variables: *) (* compile-command:"make -C .." *) (* End: *) diff --git a/src/corelang.ml b/src/corelang.ml index 3f335713..8446d910 100755 --- a/src/corelang.ml +++ b/src/corelang.ml @@ -130,7 +130,17 @@ let consts_of_enum_type top_decl = match top_decl.top_decl_desc with | TypeDef tdef -> (match tdef.tydef_desc with - | Tydec_enum tags -> List.map (fun tag -> let cdecl = { const_id = tag; const_loc = top_decl.top_decl_loc; const_value = Const_tag tag; const_type = Type_predef.type_const tdef.tydef_id } in { top_decl with top_decl_desc = Const cdecl }) tags + | Tydec_enum tags -> + List.map + (fun tag -> + let cdecl = { + const_id = tag; + const_loc = top_decl.top_decl_loc; + const_value = Const_tag tag; + const_type = Type_predef.type_const tdef.tydef_id + } in + { top_decl with top_decl_desc = Const cdecl }) + tags | _ -> []) | _ -> assert false @@ -538,16 +548,17 @@ let get_node_var id node = (* Format.eprintf "Unable to find variable %s in node %s@.@?" id node.node_id; *) raise Not_found end - + + let get_node_eqs = let get_eqs stmts = List.fold_right - (fun stmt res -> + (fun stmt (res_eq, res_aut) -> match stmt with - | Eq eq -> eq :: res - | Aut _ -> assert false) + | Eq eq -> eq :: res_eq, res_aut + | Aut aut -> res_eq, aut::res_aut) stmts - [] in + ([], []) in let table_eqs = Hashtbl.create 23 in (fun nd -> try @@ -561,8 +572,12 @@ let get_node_eqs = end) let get_node_eq id node = - List.find (fun eq -> List.mem id eq.eq_lhs) (get_node_eqs node) - + let eqs, auts = get_node_eqs node in + try + List.find (fun eq -> List.mem id eq.eq_lhs) eqs + with + Not_found -> (* Shall be defined in automata auts *) raise Not_found + let get_nodes prog = List.fold_left ( fun nodes decl -> @@ -630,70 +645,34 @@ let rec rename_carrier rename cck = | Ckdec_bool cl -> Ckdec_bool (List.map (fun (c, l) -> rename c, l) cl) | _ -> cck -(*Format.eprintf "Types.rename_static %a = %a@." print_ty ty print_ty res; res*) + (*Format.eprintf "Types.rename_static %a = %a@." print_ty ty print_ty res; res*) (* applies the renaming function [fvar] to all variables of expression [expr] *) - let rec expr_replace_var fvar expr = - { expr with expr_desc = expr_desc_replace_var fvar expr.expr_desc } - - and expr_desc_replace_var fvar expr_desc = - match expr_desc with - | Expr_const _ -> expr_desc - | Expr_ident i -> Expr_ident (fvar i) - | Expr_array el -> Expr_array (List.map (expr_replace_var fvar) el) - | Expr_access (e1, d) -> Expr_access (expr_replace_var fvar e1, d) - | Expr_power (e1, d) -> Expr_power (expr_replace_var fvar e1, d) - | Expr_tuple el -> Expr_tuple (List.map (expr_replace_var fvar) el) - | Expr_ite (c, t, e) -> Expr_ite (expr_replace_var fvar c, expr_replace_var fvar t, expr_replace_var fvar e) - | Expr_arrow (e1, e2)-> Expr_arrow (expr_replace_var fvar e1, expr_replace_var fvar e2) - | Expr_fby (e1, e2) -> Expr_fby (expr_replace_var fvar e1, expr_replace_var fvar e2) - | Expr_pre e' -> Expr_pre (expr_replace_var fvar e') - | Expr_when (e', i, l)-> Expr_when (expr_replace_var fvar e', fvar i, l) - | Expr_merge (i, hl) -> Expr_merge (fvar i, List.map (fun (t, h) -> (t, expr_replace_var fvar h)) hl) - | Expr_appl (i, e', i') -> Expr_appl (i, expr_replace_var fvar e', Utils.option_map (expr_replace_var fvar) i') - -(* Applies the renaming function [fvar] to every rhs - only when the corresponding lhs satisfies predicate [pvar] *) - let eq_replace_rhs_var pvar fvar eq = - let pvar l = List.exists pvar l in - let rec replace lhs rhs = - { rhs with expr_desc = - match lhs with - | [] -> assert false - | [_] -> if pvar lhs then expr_desc_replace_var fvar rhs.expr_desc else rhs.expr_desc - | _ -> - (match rhs.expr_desc with - | Expr_tuple tl -> - Expr_tuple (List.map2 (fun v e -> replace [v] e) lhs tl) - | Expr_appl (f, arg, None) when Basic_library.is_expr_internal_fun rhs -> - let args = expr_list_of_expr arg in - Expr_appl (f, expr_of_expr_list arg.expr_loc (List.map (replace lhs) args), None) - | Expr_array _ - | Expr_access _ - | Expr_power _ - | Expr_const _ - | Expr_ident _ - | Expr_appl _ -> - if pvar lhs - then expr_desc_replace_var fvar rhs.expr_desc - else rhs.expr_desc - | Expr_ite (c, t, e) -> Expr_ite (replace lhs c, replace lhs t, replace lhs e) - | Expr_arrow (e1, e2) -> Expr_arrow (replace lhs e1, replace lhs e2) - | Expr_fby (e1, e2) -> Expr_fby (replace lhs e1, replace lhs e2) - | Expr_pre e' -> Expr_pre (replace lhs e') - | Expr_when (e', i, l) -> let i' = if pvar lhs then fvar i else i - in Expr_when (replace lhs e', i', l) - | Expr_merge (i, hl) -> let i' = if pvar lhs then fvar i else i - in Expr_merge (i', List.map (fun (t, h) -> (t, replace lhs h)) hl) - ) - } - in { eq with eq_rhs = replace eq.eq_lhs eq.eq_rhs } + (* let rec expr_replace_var fvar expr = *) + (* { expr with expr_desc = expr_desc_replace_var fvar expr.expr_desc } *) - - let rec rename_expr f_node f_var f_const expr = - { expr with expr_desc = rename_expr_desc f_node f_var f_const expr.expr_desc } - and rename_expr_desc f_node f_var f_const expr_desc = - let re = rename_expr f_node f_var f_const in + (* and expr_desc_replace_var fvar expr_desc = *) + (* match expr_desc with *) + (* | Expr_const _ -> expr_desc *) + (* | Expr_ident i -> Expr_ident (fvar i) *) + (* | Expr_array el -> Expr_array (List.map (expr_replace_var fvar) el) *) + (* | Expr_access (e1, d) -> Expr_access (expr_replace_var fvar e1, d) *) + (* | Expr_power (e1, d) -> Expr_power (expr_replace_var fvar e1, d) *) + (* | Expr_tuple el -> Expr_tuple (List.map (expr_replace_var fvar) el) *) + (* | Expr_ite (c, t, e) -> Expr_ite (expr_replace_var fvar c, expr_replace_var fvar t, expr_replace_var fvar e) *) + (* | Expr_arrow (e1, e2)-> Expr_arrow (expr_replace_var fvar e1, expr_replace_var fvar e2) *) + (* | Expr_fby (e1, e2) -> Expr_fby (expr_replace_var fvar e1, expr_replace_var fvar e2) *) + (* | Expr_pre e' -> Expr_pre (expr_replace_var fvar e') *) + (* | Expr_when (e', i, l)-> Expr_when (expr_replace_var fvar e', fvar i, l) *) + (* | Expr_merge (i, hl) -> Expr_merge (fvar i, List.map (fun (t, h) -> (t, expr_replace_var fvar h)) hl) *) + (* | Expr_appl (i, e', i') -> Expr_appl (i, expr_replace_var fvar e', Utils.option_map (expr_replace_var fvar) i') *) + + + + let rec rename_expr f_node f_var expr = + { expr with expr_desc = rename_expr_desc f_node f_var expr.expr_desc } + and rename_expr_desc f_node f_var expr_desc = + let re = rename_expr f_node f_var in match expr_desc with | Expr_const _ -> expr_desc | Expr_ident i -> Expr_ident (f_var i) @@ -710,61 +689,114 @@ let rec rename_carrier rename cck = Expr_merge (f_var i, List.map (fun (t, h) -> (t, re h)) hl) | Expr_appl (i, e', i') -> Expr_appl (f_node i, re e', Utils.option_map re i') - - let rename_node_annot f_node f_var f_const expr = - expr - (* TODO assert false *) - - let rename_expr_annot f_node f_var f_const annot = - annot - (* TODO assert false *) - -let rename_node f_node f_var f_const nd = - let rename_var v = { v with var_id = f_var v.var_id } in - let rename_eq eq = { eq with - eq_lhs = List.map f_var eq.eq_lhs; - eq_rhs = rename_expr f_node f_var f_const eq.eq_rhs - } - in - let inputs = List.map rename_var nd.node_inputs in - let outputs = List.map rename_var nd.node_outputs in - let locals = List.map rename_var nd.node_locals in - let gen_calls = List.map (rename_expr f_node f_var f_const) nd.node_gencalls in - let node_checks = List.map (Dimension.expr_replace_var f_var) nd.node_checks in - let node_asserts = List.map - (fun a -> - {a with assert_expr = - let expr = a.assert_expr in - rename_expr f_node f_var f_const expr}) - nd.node_asserts - in - let node_stmts = List.map (fun eq -> Eq (rename_eq eq)) (get_node_eqs nd) in - let spec = - Utils.option_map - (fun s -> rename_node_annot f_node f_var f_const s) - nd.node_spec - in - let annot = - List.map - (fun s -> rename_expr_annot f_node f_var f_const s) - nd.node_annot - in - { - node_id = f_node nd.node_id; - node_type = nd.node_type; - node_clock = nd.node_clock; - node_inputs = inputs; - node_outputs = outputs; - node_locals = locals; - node_gencalls = gen_calls; - node_checks = node_checks; - node_asserts = node_asserts; - node_stmts = node_stmts; - node_dec_stateless = nd.node_dec_stateless; - node_stateless = nd.node_stateless; - node_spec = spec; - node_annot = annot; - } + + let rename_dec_type f_node f_var t = assert false (* + Types.rename_dim_type (Dimension.rename f_node f_var) t*) + + let rename_dec_clock f_node f_var c = assert false (* + Clocks.rename_clock_expr f_var c*) + + let rename_var f_node f_var v = { + v with + var_id = f_var v.var_id; + var_dec_type = rename_dec_type f_node f_var v.var_type; + var_dec_clock = rename_dec_clock f_node f_var v.var_clock + } + + let rename_vars f_node f_var = List.map (rename_var f_node f_var) + + let rec rename_eq f_node f_var eq = { eq with + eq_lhs = List.map f_var eq.eq_lhs; + eq_rhs = rename_expr f_node f_var eq.eq_rhs + } + and rename_handler f_node f_var h = {h with + hand_state = f_var h.hand_state; + hand_unless = List.map ( + fun (l,e,b,id) -> l, rename_expr f_node f_var e, b, f_var id + ) h.hand_unless; + hand_until = List.map ( + fun (l,e,b,id) -> l, rename_expr f_node f_var e, b, f_var id + ) h.hand_until; + hand_locals = rename_vars f_node f_var h.hand_locals; + hand_stmts = rename_stmts f_node f_var h.hand_stmts; + hand_annots = rename_annots f_node f_var h.hand_annots; + + } + and rename_aut f_node f_var aut = { aut with + aut_id = f_var aut.aut_id; + aut_handlers = List.map (rename_handler f_node f_var) aut.aut_handlers; + } + and rename_stmts f_node f_var stmts = List.map (fun stmt -> match stmt with + | Eq eq -> Eq (rename_eq f_node f_var eq) + | Aut at -> Aut (rename_aut f_node f_var at)) + stmts + and rename_annotl f_node f_var annots = + List.map + (fun (key, value) -> key, rename_eexpr f_node f_var value) + annots + and rename_annot f_node f_var annot = + { annot with annots = rename_annotl f_node f_var annot.annots } + and rename_annots f_node f_var annots = + List.map (rename_annot f_node f_var) annots +and rename_eexpr f_node f_var ee = + { ee with + eexpr_tag = Utils.new_tag (); + eexpr_qfexpr = rename_expr f_node f_var ee.eexpr_qfexpr; + eexpr_quantifiers = List.map (fun (typ,vdecls) -> typ, rename_vars f_node f_var vdecls) ee.eexpr_quantifiers; + eexpr_normalized = Utils.option_map + (fun (vdecl, eqs, vdecls) -> + rename_var f_node f_var vdecl, + List.map (rename_eq f_node f_var) eqs, + rename_vars f_node f_var vdecls + ) ee.eexpr_normalized; + + } + + + + + let rename_node f_node f_var nd = + let rename_var = rename_var f_node f_var in + let rename_expr = rename_expr f_node f_var in + let rename_stmts = rename_stmts f_node f_var in + let inputs = List.map rename_var nd.node_inputs in + let outputs = List.map rename_var nd.node_outputs in + let locals = List.map rename_var nd.node_locals in + let gen_calls = List.map rename_expr nd.node_gencalls in + let node_checks = List.map (Dimension.rename f_node f_var) nd.node_checks in + let node_asserts = List.map + (fun a -> + {a with assert_expr = + let expr = a.assert_expr in + rename_expr expr}) + nd.node_asserts + in + let node_stmts = rename_stmts nd.node_stmts + + + in + let spec = + Utils.option_map + (fun s -> assert false; (*rename_node_annot f_node f_var s*) ) (* TODO: implement! *) + nd.node_spec + in + let annot = rename_annots f_node f_var nd.node_annot in + { + node_id = f_node nd.node_id; + node_type = nd.node_type; + node_clock = nd.node_clock; + node_inputs = inputs; + node_outputs = outputs; + node_locals = locals; + node_gencalls = gen_calls; + node_checks = node_checks; + node_asserts = node_asserts; + node_stmts = node_stmts; + node_dec_stateless = nd.node_dec_stateless; + node_stateless = nd.node_stateless; + node_spec = spec; + node_annot = annot; + } let rename_const f_const c = @@ -780,7 +812,7 @@ let rename_prog f_node f_var f_const prog = List.fold_left (fun accu top -> (match top.top_decl_desc with | Node nd -> - { top with top_decl_desc = Node (rename_node f_node f_var f_const nd) } + { top with top_decl_desc = Node (rename_node f_node f_var nd) } | Const c -> { top with top_decl_desc = Const (rename_const f_const c) } | TypeDef tdef -> @@ -791,6 +823,44 @@ let rename_prog f_node f_var f_const prog = ) [] prog ) +(* Applies the renaming function [fvar] to every rhs + only when the corresponding lhs satisfies predicate [pvar] *) + let eq_replace_rhs_var pvar fvar eq = + let pvar l = List.exists pvar l in + let rec replace lhs rhs = + { rhs with expr_desc = + match lhs with + | [] -> assert false + | [_] -> if pvar lhs then rename_expr_desc (fun x -> x) fvar rhs.expr_desc else rhs.expr_desc + | _ -> + (match rhs.expr_desc with + | Expr_tuple tl -> + Expr_tuple (List.map2 (fun v e -> replace [v] e) lhs tl) + | Expr_appl (f, arg, None) when Basic_library.is_expr_internal_fun rhs -> + let args = expr_list_of_expr arg in + Expr_appl (f, expr_of_expr_list arg.expr_loc (List.map (replace lhs) args), None) + | Expr_array _ + | Expr_access _ + | Expr_power _ + | Expr_const _ + | Expr_ident _ + | Expr_appl _ -> + if pvar lhs + then rename_expr_desc (fun x -> x) fvar rhs.expr_desc + else rhs.expr_desc + | Expr_ite (c, t, e) -> Expr_ite (replace lhs c, replace lhs t, replace lhs e) + | Expr_arrow (e1, e2) -> Expr_arrow (replace lhs e1, replace lhs e2) + | Expr_fby (e1, e2) -> Expr_fby (replace lhs e1, replace lhs e2) + | Expr_pre e' -> Expr_pre (replace lhs e') + | Expr_when (e', i, l) -> let i' = if pvar lhs then fvar i else i + in Expr_when (replace lhs e', i', l) + | Expr_merge (i, hl) -> let i' = if pvar lhs then fvar i else i + in Expr_merge (i', List.map (fun (t, h) -> (t, replace lhs h)) hl) + ) + } + in { eq with eq_rhs = replace eq.eq_lhs eq.eq_rhs } + + (**********************************************************************) (* Pretty printers *) @@ -964,8 +1034,24 @@ let rec get_expr_calls nodes e = and get_eq_calls nodes eq = get_expr_calls nodes eq.eq_rhs +and get_aut_handler_calls nodes h = + List.fold_left (fun accu stmt -> match stmt with + | Eq eq -> Utils.ISet.union (get_eq_calls nodes eq) accu + | Aut aut' -> Utils.ISet.union (get_aut_calls nodes aut') accu + ) Utils.ISet.empty h.hand_stmts +and get_aut_calls nodes aut = + List.fold_left (fun accu h -> Utils.ISet.union (get_aut_handler_calls nodes h) accu) + Utils.ISet.empty aut.aut_handlers and get_node_calls nodes node = - List.fold_left (fun accu eq -> Utils.ISet.union (get_eq_calls nodes eq) accu) Utils.ISet.empty (get_node_eqs node) + let eqs, auts = get_node_eqs node in + let aut_calls = + List.fold_left + (fun accu aut -> Utils.ISet.union (get_aut_calls nodes aut) accu) + Utils.ISet.empty auts + in + List.fold_left + (fun accu eq -> Utils.ISet.union (get_eq_calls nodes eq) accu) + aut_calls eqs let get_expr_vars e = let rec get_expr_vars vars e = @@ -1010,8 +1096,11 @@ and expr_desc_has_arrows expr_desc = and eq_has_arrows eq = expr_has_arrows eq.eq_rhs +and aut_has_arrows aut = List.exists (fun h -> List.exists (fun stmt -> match stmt with Eq eq -> eq_has_arrows eq | Aut aut' -> aut_has_arrows aut') h.hand_stmts ) aut.aut_handlers and node_has_arrows node = - List.exists (fun eq -> eq_has_arrows eq) (get_node_eqs node) + let eqs, auts = get_node_eqs node in + List.exists (fun eq -> eq_has_arrows eq) eqs || List.exists (fun aut -> aut_has_arrows aut) auts + let copy_var_decl vdecl = diff --git a/src/corelang.mli b/src/corelang.mli index ea020ab9..17726b40 100755 --- a/src/corelang.mli +++ b/src/corelang.mli @@ -75,7 +75,7 @@ val const_impl: constant -> constant -> constant val get_node_vars: node_desc -> var_decl list val get_node_var: ident -> node_desc -> var_decl -val get_node_eqs: node_desc -> eq list +val get_node_eqs: node_desc -> eq list * automata_desc list val get_node_eq: ident -> node_desc -> eq val get_node_interface: node_desc -> imported_node_desc @@ -124,10 +124,17 @@ val rename_static: (ident -> Dimension.dim_expr) -> type_dec_desc -> type_dec_de val rename_carrier: (ident -> ident) -> clock_dec_desc -> clock_dec_desc val get_expr_vars: expr -> Utils.ISet.t -val expr_replace_var: (ident -> ident) -> expr -> expr +(*val expr_replace_var: (ident -> ident) -> expr -> expr*) + val eq_replace_rhs_var: (ident -> bool) -> (ident -> ident) -> eq -> eq -(** rename_prog f_node f_var f_const prog *) +(** val rename_expr f_node f_var expr *) +val rename_expr : (ident -> ident) -> (ident -> ident) -> expr -> expr +(** val rename_eq f_node f_var eq *) +val rename_eq : (ident -> ident) -> (ident -> ident) -> eq -> eq +(** val rename_aut f_node f_var aut *) +val rename_aut : (ident -> ident) -> (ident -> ident) -> automata_desc -> automata_desc +(** rename_prog f_node f_var prog *) val rename_prog: (ident -> ident) -> (ident -> ident) -> (ident -> ident) -> program -> program val substitute_expr: var_decl list -> eq list -> expr -> expr diff --git a/src/dimension.ml b/src/dimension.ml index ec0b2f26..4a46d85a 100644 --- a/src/dimension.ml +++ b/src/dimension.ml @@ -338,17 +338,17 @@ let unify ?(semi=false) dim1 dim2 = | _ -> raise (Unify (dim1, dim2)) in unif dim1 dim2 -let rec expr_replace_var fvar e = - { e with dim_desc = expr_replace_var_desc fvar e.dim_desc } -and expr_replace_var_desc fvar e = - let re = expr_replace_var fvar in +let rec rename fnode fvar e = + { e with dim_desc = expr_replace_var_desc fnode fvar e.dim_desc } +and expr_replace_var_desc fnode fvar e = + let re = rename fnode fvar in match e with | Dvar | Dunivar | Dbool _ | Dint _ -> e | Dident v -> Dident (fvar v) - | Dappl (id, el) -> Dappl (id, List.map re el) + | Dappl (id, el) -> Dappl (fnode id, List.map re el) | Dite (g,t,e) -> Dite (re g, re t, re e) | Dlink e -> Dlink (re e) diff --git a/src/inliner.ml b/src/inliner.ml index 0aab3f3d..33935a03 100644 --- a/src/inliner.ml +++ b/src/inliner.ml @@ -32,14 +32,15 @@ let is_node_var node v = ignore (Corelang.get_node_var v node); true with Not_found -> false -let rename_expr rename expr = expr_replace_var rename expr - +(* let rename_expr rename expr = expr_replace_var rename expr *) +(* let rename_eq rename eq = { eq with eq_lhs = List.map rename eq.eq_lhs; eq_rhs = rename_expr rename eq.eq_rhs } - +*) + let rec add_expr_reset_cond cond expr = let aux = add_expr_reset_cond cond in let new_desc = @@ -113,7 +114,9 @@ let inline_call node loc uid args reset locals caller = if v = tag_true || v = tag_false || not (is_node_var node v) then v else Corelang.mk_new_node_name caller (Format.sprintf "%s_%i_%s" node.node_id uid v) in - let eqs' = List.map (rename_eq rename) (get_node_eqs node) in + let eqs, auts = get_node_eqs node in + let eqs' = List.map (rename_eq (fun x -> x) rename) eqs in + let auts' = List.map (rename_aut (fun x -> x) rename) auts in let input_arg_list = List.combine node.node_inputs (Corelang.expr_list_of_expr args) in let static_inputs, dynamic_inputs = List.partition (fun (vdecl, arg) -> vdecl.var_dec_const) input_arg_list in let static_inputs = List.map (fun (vdecl, arg) -> vdecl, Corelang.dimension_of_expr arg) static_inputs in @@ -134,7 +137,7 @@ let inline_call node loc uid args reset locals caller = { v.var_dec_type with ty_dec_desc = Corelang.rename_static rename_static v.var_dec_type.ty_dec_desc }, { v.var_dec_clock with ck_dec_desc = Corelang.rename_carrier rename_carrier v.var_dec_clock.ck_dec_desc }, v.var_dec_const, - Utils.option_map (rename_expr rename) v.var_dec_value) in + Utils.option_map (rename_expr (fun x -> x) rename) v.var_dec_value) in begin (* (try @@ -162,13 +165,17 @@ in assert (node.node_gencalls = []); (* Expressing reset locally in equations *) - let eqs_r' = + let eqs_r' = + let all_eqs = (List.map (fun eq -> Eq eq) eqs') @ (List.map (fun aut -> Aut aut) auts') in match reset with - None -> eqs' - | Some cond -> List.map (add_eq_reset_cond cond) eqs' + None -> all_eqs + | Some cond -> ( + assert (auts' = []); (* TODO: we do not handle properly automaton in case of reset call *) + List.map (fun eq -> Eq (add_eq_reset_cond cond eq)) eqs' + ) in - let assign_inputs = mkeq loc (List.map (fun v -> v.var_id) inputs', - expr_of_expr_list args.expr_loc (List.map snd dynamic_inputs)) in + let assign_inputs = Eq (mkeq loc (List.map (fun v -> v.var_id) inputs', + expr_of_expr_list args.expr_loc (List.map snd dynamic_inputs))) in let expr = expr_of_expr_list loc (List.map expr_of_vdecl outputs') in let asserts' = (* We rename variables in assert expressions *) @@ -176,7 +183,7 @@ in (fun a -> {a with assert_expr = let expr = a.assert_expr in - rename_expr rename expr + rename_expr (fun x -> x) rename expr }) node.node_asserts in @@ -224,91 +231,94 @@ let rec inline_expr ?(selection_on_annotation=false) expr locals node nodes = match expr.expr_desc with | Expr_appl (id, args, reset) -> - let args', locals', eqs', asserts', annots' = inline_expr args locals node nodes in - if List.exists (check_node_name id) nodes && (* the current node call is provided - as arguments nodes *) - (not selection_on_annotation || is_inline_expr expr) (* and if selection on annotation is activated, - it is explicitely inlined here *) - then ( - (* Format.eprintf "Inlining call to %s in expression %a@." id Printers.pp_expr expr; *) - (* The node should be inlined *) - (* let _ = Format.eprintf "Inlining call to %s@." id in *) - let called = try List.find (check_node_name id) nodes - with Not_found -> (assert false) in - let called = node_of_top called in - let called' = inline_node called nodes in - let expr, locals', eqs'', asserts'', annots'' = - inline_call called' expr.expr_loc expr.expr_tag args' reset locals' node in - expr, locals', eqs'@eqs'', asserts'@asserts'', annots'@annots'' - ) - else - (* let _ = Format.eprintf "Not inlining call to %s@." id in *) - { expr with expr_desc = Expr_appl(id, args', reset)}, - locals', - eqs', - asserts', - annots' + let args', locals', eqs', asserts', annots' = inline_expr args locals node nodes in + if List.exists (check_node_name id) nodes && (* the current node call is provided + as arguments nodes *) + (not selection_on_annotation || is_inline_expr expr) (* and if selection on annotation is activated, + it is explicitely inlined here *) + then ( + (* Format.eprintf "Inlining call to %s in expression %a@." id Printers.pp_expr expr; *) + (* The node should be inlined *) + (* let _ = Format.eprintf "Inlining call to %s@." id in *) + let called = try List.find (check_node_name id) nodes + with Not_found -> (assert false) in + let called = node_of_top called in + let called' = inline_node called nodes in + let expr, locals', eqs'', asserts'', annots'' = + inline_call called' expr.expr_loc expr.expr_tag args' reset locals' node in + expr, locals', eqs'@eqs'', asserts'@asserts'', annots'@annots'' + ) + else + (* let _ = Format.eprintf "Not inlining call to %s@." id in *) + { expr with expr_desc = Expr_appl(id, args', reset)}, + locals', + eqs', + asserts', + annots' (* For other cases, we just keep the structure, but convert sub-expressions *) | Expr_const _ | Expr_ident _ -> expr, locals, [], [], [] | Expr_tuple el -> - let el', l', eqs', asserts', annots' = inline_tuple el in - { expr with expr_desc = Expr_tuple el' }, l', eqs', asserts', annots' + let el', l', eqs', asserts', annots' = inline_tuple el in + { expr with expr_desc = Expr_tuple el' }, l', eqs', asserts', annots' | Expr_ite (g, t, e) -> - let g', t', e', l', eqs', asserts', annots' = inline_triple g t e in - { expr with expr_desc = Expr_ite (g', t', e') }, l', eqs', asserts', annots' + let g', t', e', l', eqs', asserts', annots' = inline_triple g t e in + { expr with expr_desc = Expr_ite (g', t', e') }, l', eqs', asserts', annots' | Expr_arrow (e1, e2) -> - let e1', e2', l', eqs', asserts', annots' = inline_pair e1 e2 in - { expr with expr_desc = Expr_arrow (e1', e2') } , l', eqs', asserts', annots' + let e1', e2', l', eqs', asserts', annots' = inline_pair e1 e2 in + { expr with expr_desc = Expr_arrow (e1', e2') } , l', eqs', asserts', annots' | Expr_fby (e1, e2) -> - let e1', e2', l', eqs', asserts', annots' = inline_pair e1 e2 in - { expr with expr_desc = Expr_fby (e1', e2') }, l', eqs', asserts', annots' + let e1', e2', l', eqs', asserts', annots' = inline_pair e1 e2 in + { expr with expr_desc = Expr_fby (e1', e2') }, l', eqs', asserts', annots' | Expr_array el -> - let el', l', eqs', asserts', annots' = inline_tuple el in - { expr with expr_desc = Expr_array el' }, l', eqs', asserts', annots' + let el', l', eqs', asserts', annots' = inline_tuple el in + { expr with expr_desc = Expr_array el' }, l', eqs', asserts', annots' | Expr_access (e, dim) -> - let e', l', eqs', asserts', annots' = inline_expr e locals node nodes in - { expr with expr_desc = Expr_access (e', dim) }, l', eqs', asserts', annots' + let e', l', eqs', asserts', annots' = inline_expr e locals node nodes in + { expr with expr_desc = Expr_access (e', dim) }, l', eqs', asserts', annots' | Expr_power (e, dim) -> - let e', l', eqs', asserts', annots' = inline_expr e locals node nodes in - { expr with expr_desc = Expr_power (e', dim) }, l', eqs', asserts', annots' + let e', l', eqs', asserts', annots' = inline_expr e locals node nodes in + { expr with expr_desc = Expr_power (e', dim) }, l', eqs', asserts', annots' | Expr_pre e -> - let e', l', eqs', asserts', annots' = inline_expr e locals node nodes in - { expr with expr_desc = Expr_pre e' }, l', eqs', asserts', annots' + let e', l', eqs', asserts', annots' = inline_expr e locals node nodes in + { expr with expr_desc = Expr_pre e' }, l', eqs', asserts', annots' | Expr_when (e, id, label) -> - let e', l', eqs', asserts', annots' = inline_expr e locals node nodes in - { expr with expr_desc = Expr_when (e', id, label) }, l', eqs', asserts', annots' + let e', l', eqs', asserts', annots' = inline_expr e locals node nodes in + { expr with expr_desc = Expr_when (e', id, label) }, l', eqs', asserts', annots' | Expr_merge (id, branches) -> - let el, l', eqs', asserts', annots' = inline_tuple (List.map snd branches) in - let branches' = List.map2 (fun (label, _) v -> label, v) branches el in - { expr with expr_desc = Expr_merge (id, branches') }, l', eqs', asserts', annots' + let el, l', eqs', asserts', annots' = inline_tuple (List.map snd branches) in + let branches' = List.map2 (fun (label, _) v -> label, v) branches el in + { expr with expr_desc = Expr_merge (id, branches') }, l', eqs', asserts', annots' and inline_node ?(selection_on_annotation=false) node nodes = try copy_node (Hashtbl.find inline_table node.node_id) with Not_found -> - let inline_expr = inline_expr ~selection_on_annotation:selection_on_annotation in - let new_locals, eqs, asserts, annots = - List.fold_left (fun (locals, eqs, asserts, annots) eq -> - let eq_rhs', locals', new_eqs', asserts', annots' = - inline_expr eq.eq_rhs locals node nodes - in - locals', { eq with eq_rhs = eq_rhs' }::new_eqs'@eqs, asserts'@asserts, annots'@annots - ) (node.node_locals, [], node.node_asserts, node.node_annot) (get_node_eqs node) - in - let inlined = - { node with - node_locals = new_locals; - node_stmts = List.map (fun eq -> Eq eq) eqs; - node_asserts = asserts; - node_annot = annots; - } - in - begin - (*Format.eprintf "inline node:<< %a@.>>@." Printers.pp_node inlined;*) - Hashtbl.add inline_table node.node_id inlined; - inlined - end + let inline_expr = inline_expr ~selection_on_annotation:selection_on_annotation in + let eqs, auts = get_node_eqs node in + assert (auts = []); (* No inlining of automaton yet. One should visit each + handler eqs and perform similar computation *) + let new_locals, stmts, asserts, annots = + List.fold_left (fun (locals, stmts, asserts, annots) eq -> + let eq_rhs', locals', new_stmts', asserts', annots' = + inline_expr eq.eq_rhs locals node nodes + in + locals', Eq { eq with eq_rhs = eq_rhs' }::new_stmts'@stmts, asserts'@asserts, annots'@annots + ) (node.node_locals, [], node.node_asserts, node.node_annot) eqs + in + let inlined = + { node with + node_locals = new_locals; + node_stmts = stmts; + node_asserts = asserts; + node_annot = annots; + } + in + begin + (*Format.eprintf "inline node:<< %a@.>>@." Printers.pp_node inlined;*) + Hashtbl.add inline_table node.node_id inlined; + inlined + end let inline_all_calls node nodes = let nd = match node.top_decl_desc with Node nd -> nd | _ -> assert false in @@ -333,7 +343,7 @@ let witness filename main_name orig inlined type_env clock_env = let inlined_rename = rename_local_node inlined "inlined_" in let identity = (fun x -> x) in let is_node top = match top.top_decl_desc with Node _ -> true | _ -> false in - let orig = rename_prog orig_rename identity identity orig in + let orig = rename_prog orig_rename (* f_node *) identity (* f_var *) identity (* f_const *) orig in let inlined = rename_prog inlined_rename identity identity inlined in let nodes_origs, others = List.partition is_node orig in let nodes_inlined, _ = List.partition is_node inlined in diff --git a/src/machine_code.ml b/src/machine_code.ml index eca08aec..7288d6ac 100644 --- a/src/machine_code.ml +++ b/src/machine_code.ml @@ -555,7 +555,9 @@ let sort_equations_from_schedule nd sch = (* Format.eprintf "%s schedule: %a@." *) (* nd.node_id *) (* (Utils.fprintf_list ~sep:" ; " Scheduling.pp_eq_schedule) sch; *) - let split_eqs = Splitting.tuple_split_eq_list (get_node_eqs nd) in + let eqs, auts = get_node_eqs nd in + assert (auts = []); (* Automata should be expanded by now *) + let split_eqs = Splitting.tuple_split_eq_list eqs in let eqs_rev, remainder = List.fold_left (fun (accu, node_eqs_remainder) vl -> @@ -571,9 +573,11 @@ let sort_equations_from_schedule nd sch = in begin if List.length remainder > 0 then ( + let eqs, auts = get_node_eqs nd in + assert (auts = []); (* Automata should be expanded by now *) Format.eprintf "Equations not used are@.%a@.Full equation set is:@.%a@.@?" Printers.pp_node_eqs remainder - Printers.pp_node_eqs (get_node_eqs nd); + Printers.pp_node_eqs eqs; assert false); List.rev eqs_rev end diff --git a/src/mpfr.ml b/src/mpfr.ml index d310936c..ddf1dec5 100755 --- a/src/mpfr.ml +++ b/src/mpfr.ml @@ -221,8 +221,10 @@ let inject_node node = let is_local v = List.for_all ((!=) v) inputs_outputs in let orig_vars = inputs_outputs@node.node_locals in - let defs, vars = - List.fold_left (inject_eq node) ([], orig_vars) (get_node_eqs node) in + let defs, vars = + let eqs, auts = get_node_eqs node in + if auts != [] then assert false; (* Automata should be expanded by now. *) + List.fold_left (inject_eq node) ([], orig_vars) eqs in (* Normalize the asserts *) let vars, assert_defs, asserts = List.fold_left ( diff --git a/src/mutation.ml b/src/mutation.ml index a907de23..f5a94911 100644 --- a/src/mutation.ml +++ b/src/mutation.ml @@ -103,8 +103,10 @@ let rec compute_records_expr expr = let compute_records_eq eq = compute_records_expr eq.eq_rhs -let compute_records_node nd = - merge_records (List.map compute_records_eq (get_node_eqs nd)) +let compute_records_node nd = + let eqs, auts = get_node_eqs nd in + assert (auts=[]); (* Automaton should be expanded by now *) + merge_records (List.map compute_records_eq eqs) let compute_records_top_decl td = match td.top_decl_desc with diff --git a/src/normalization.ml b/src/normalization.ml index 7cdb1a6a..ccc8d8d5 100644 --- a/src/normalization.ml +++ b/src/normalization.ml @@ -399,7 +399,9 @@ let normalize_node node = List.for_all ((!=) v) inputs_outputs in let orig_vars = inputs_outputs@node.node_locals in let defs, vars = - List.fold_left (normalize_eq node) ([], orig_vars) (get_node_eqs node) in + let eqs, auts = get_node_eqs node in + if auts != [] then assert false; (* Automata should be expanded by now. *) + List.fold_left (normalize_eq node) ([], orig_vars) eqs in (* Normalize the asserts *) let vars, assert_defs, asserts = List.fold_left ( diff --git a/src/printers.ml b/src/printers.ml index 3b02fb91..5c1282fb 100644 --- a/src/printers.ml +++ b/src/printers.ml @@ -332,7 +332,8 @@ let pp_decl fmt decl = | TypeDef tdef -> fprintf fmt "%a@ " pp_typedef tdef let pp_prog fmt prog = - (* we first print types *) + (* we first print types: the function SortProg.sort could do the job but ut + introduces a cyclic dependance *) let type_decl, others = List.partition (fun decl -> match decl.top_decl_desc with TypeDef _ -> true | _ -> false) prog in diff --git a/src/stateless.ml b/src/stateless.ml index 10acf40c..eee1401b 100755 --- a/src/stateless.ml +++ b/src/stateless.ml @@ -36,8 +36,10 @@ let rec check_expr expr = | Expr_appl (i, e', i') -> check_expr e' && (Basic_library.is_stateless_fun i || check_node (node_from_name i)) -and compute_node nd = - List.for_all (fun eq -> check_expr eq.eq_rhs) (get_node_eqs nd) +and compute_node nd = (* returns true iff the node is stateless.*) + let eqs, aut = get_node_eqs nd in + aut = [] && (* A node containinig an automaton will be stateful *) + List.for_all (fun eq -> check_expr eq.eq_rhs) eqs and check_node td = match td.top_decl_desc with | Node nd -> ( diff --git a/src/types.ml b/src/types.ml index 8c4bf2de..b7f0374a 100755 --- a/src/types.ml +++ b/src/types.ml @@ -355,6 +355,7 @@ let rec is_polymorphic ty = let mktyptuple nb typ = let array = Array.make nb typ in Ttuple (Array.to_list array) + (* Local Variables: *) diff --git a/src/typing.ml b/src/typing.ml index 283f41f0..0aed94cb 100755 --- a/src/typing.ml +++ b/src/typing.ml @@ -562,6 +562,8 @@ let rec check_type_declaration loc cty = | Tydec_clock ty | Tydec_array (_, ty) -> check_type_declaration loc ty | Tydec_const tname -> + Format.printf "TABLE: %a@." print_type_table (); + (* TODO REMOVE *) if not (Hashtbl.mem type_table cty) then raise (Error (loc, Unbound_type tname)); | _ -> () @@ -622,7 +624,9 @@ let type_node env nd loc = (fun uvs v -> ISet.add v.var_id uvs) ISet.empty vd_env_ol in let undefined_vars = - List.fold_left (type_eq (new_env, vd_env) is_main) undefined_vars_init (get_node_eqs nd) + let eqs, auts = get_node_eqs nd in + (* TODO XXX: il faut typer les handlers de l'automate *) + List.fold_left (type_eq (new_env, vd_env) is_main) undefined_vars_init eqs in (* Typing asserts *) List.iter (fun assert_ -> -- GitLab