From 86c5e03fd7a31965c1518ea5492c7feab469bea5 Mon Sep 17 00:00:00 2001 From: Erwan Jahier <jahier@imag.fr> Date: Wed, 18 Jun 2008 17:49:15 +0200 Subject: [PATCH] Add a New module that checks that all variables (outputs and locals) are defined exactly once. This algo is naive and does not work with slices of slices with negative steps. I commit it before trying a new one to get better non-reg test. Fix some non-reg test in the should_work dir that this new check revealed. --- src/Makefile | 1 + src/TODO | 1 - src/compiledData.ml | 28 +- src/evalClock.ml | 19 +- src/getEff.ml | 9 +- src/lazyCompiler.ml | 14 +- src/test/should_work/Pascal/left.lus | 4 +- src/test/should_work/clock/clock.lus | 40 +++ src/test/should_work/demo/declaration.lus | 2 + src/test/should_work/fab_test/morel.lus | 2 +- src/test/should_work/lionel/Gyroscope.lus | 4 + .../lionel/ProduitBool/produitBool.lus | 3 + .../packageTableau.lus | 1 + src/test/test.res.exp | 46 ++- src/uniqueOutput.ml | 334 ++++++++++++++++++ 15 files changed, 456 insertions(+), 52 deletions(-) create mode 100644 src/test/should_work/clock/clock.lus create mode 100644 src/uniqueOutput.ml diff --git a/src/Makefile b/src/Makefile index ff93d3dc..982f1974 100644 --- a/src/Makefile +++ b/src/Makefile @@ -50,6 +50,7 @@ SOURCES = \ ./evalClock.ml \ ./getEff.mli \ ./getEff.ml \ + ./uniqueOutput.ml \ ./lazyCompiler.ml \ ./lazyCompiler.mli \ ./compile.ml \ diff --git a/src/TODO b/src/TODO index 5291493a..9513cb9a 100644 --- a/src/TODO +++ b/src/TODO @@ -138,7 +138,6 @@ n'est pas le cas pour l'instant... *** facile - * Pb des noms de modules ../lus2lic should_work/NONREG/dependeur_struct.lus -> diff --git a/src/compiledData.ml b/src/compiledData.ml index 20cc272f..1bddaca7 100644 --- a/src/compiledData.ml +++ b/src/compiledData.ml @@ -1,4 +1,4 @@ -(** Time-stamp: <modified the 12/06/2008 (at 17:07) by Erwan Jahier> *) +(** Time-stamp: <modified the 17/06/2008 (at 10:10) by Erwan Jahier> *) (** @@ -286,24 +286,6 @@ and static_arg_eff = | NodeStaticArgEff of (Ident.t * node_exp_eff) -(* XXX rm: just for test *) -let (make_dummy_var: Ident.idref -> var_info_eff) = - fun idref -> - let id = Ident.of_idref idref in - let str = Ident.string_of_idref idref in - let teff = - try ignore (int_of_string str); Int_type_eff - with _ -> - try ignore (float_of_string str); Real_type_eff - with _ -> Bool_type_eff - in - { - var_name_eff = id; - var_nature_eff = VarLocal; - var_number_eff = 0; - var_type_eff = teff; - var_clock_eff = BaseEff; - } (****************************************************************************) (** Type check_flag @@ -465,6 +447,14 @@ let rec (clock_of_left_eff: left_eff -> clock_eff) = | LeftArrayEff (left_eff,_,_) -> clock_of_left_eff left_eff | LeftSliceEff (left_eff,_,_) -> clock_of_left_eff left_eff +let rec (var_info_of_left_eff: left_eff -> var_info_eff) = + function + | LeftVarEff (v, _) -> v + | LeftFieldEff (left_eff,_,_) -> var_info_of_left_eff left_eff + | LeftArrayEff (left_eff,_,_) -> var_info_of_left_eff left_eff + | LeftSliceEff (left_eff,_,_) -> var_info_of_left_eff left_eff + + (*--------------------------------------------------------------------- Une erreur associée à un noeud + 1 lexeme dans le fichier source diff --git a/src/evalClock.ml b/src/evalClock.ml index fb1c68b4..40d80c63 100644 --- a/src/evalClock.ml +++ b/src/evalClock.ml @@ -1,4 +1,4 @@ -(** Time-stamp: <modified the 12/06/2008 (at 11:10) by Erwan Jahier> *) +(** Time-stamp: <modified the 16/06/2008 (at 15:26) by Erwan Jahier> *) open Predef @@ -284,8 +284,22 @@ let (check_res : Lxm.t -> clock_info_res list -> clock_eff list -> unit) = (******************************************************************************) +let cpt_var_name = ref 0 +let (make_dummy_var: string -> var_info_eff) = + fun str -> + let id = Ident.of_string (str ^ (string_of_int !cpt_var_name)) in + { + var_name_eff = id; + var_nature_eff = VarLocal; + var_number_eff = -1; + var_type_eff = Bool_type_eff; + var_clock_eff = BaseEff; + } + + let rec (f : id_solver -> val_exp_eff -> clock_info_res list) = fun id_solver ve -> + cpt_var_name := 0; match ve with | CallByPosEff ({it=posop; src=lxm}, OperEff args) -> ( eval_by_pos_clock id_solver posop lxm args @@ -361,7 +375,8 @@ and (eval_by_pos_clock : id_solver -> by_pos_op_eff -> Lxm.t -> val_exp_eff list | TUPLE_eff -> List.flatten (List.map (f id_solver) args) - | IDENT_eff idref -> [Base_res(make_dummy_var idref)] (* all constants are on the base clock *) + | IDENT_eff idref -> [Base_res(make_dummy_var (Ident.string_of_idref idref))] + (* all constants are on the base clock *) and (eval_by_name_clock : id_solver -> by_name_op_eff -> Lxm.t -> diff --git a/src/getEff.ml b/src/getEff.ml index 965583f1..6b1270ef 100644 --- a/src/getEff.ml +++ b/src/getEff.ml @@ -1,4 +1,4 @@ -(** Time-stamp: <modified the 12/06/2008 (at 16:29) by Erwan Jahier> *) +(** Time-stamp: <modified the 16/06/2008 (at 15:44) by Erwan Jahier> *) open Lxm @@ -73,10 +73,9 @@ and (type_check_equation: id_solver -> eq_info srcflagged -> left_eff list -> and (clock_check_equation:id_solver -> eq_info srcflagged -> left_eff list -> val_exp_eff -> unit) = fun id_solver eq_info lpl_eff ve_eff -> - let lpl_clk = List.map (clock_of_left_eff) lpl_eff in - let right_part = EvalClock.f id_solver ve_eff in - EvalClock.check_res eq_info.src right_part lpl_clk - +(* let right_part,s = EvalClock.f id_solver EvalClock.empty_subst ve_eff in *) +(* EvalClock.check_res eq_info.src s lpl_eff right_part *) + assert false (******************************************************************************) let (get_static_params_from_idref : SymbolTab.t -> Lxm.t -> Ident.idref -> diff --git a/src/lazyCompiler.ml b/src/lazyCompiler.ml index c7b2a2e9..6844c872 100644 --- a/src/lazyCompiler.ml +++ b/src/lazyCompiler.ml @@ -1,4 +1,4 @@ -(** Time-stamp: <modified the 12/06/2008 (at 18:02) by Erwan Jahier> *) +(** Time-stamp: <modified the 17/06/2008 (at 15:22) by Erwan Jahier> *) open Lxm @@ -688,11 +688,12 @@ and (node_check_do: t -> CompiledData.node_key -> Lxm.t -> SymbolTab.t -> after the local_env.lenv_vars has been filled *) - BodyEff { - asserts_eff = - List.map (GetEff.assertion node_id_solver) nb.asserts; - eqs_eff = List.map (GetEff.eq node_id_solver) nb.eqs; - } + let eq_eff = List.map (GetEff.eq node_id_solver) nb.eqs in + BodyEff { + asserts_eff = + List.map (GetEff.assertion node_id_solver) nb.asserts; + eqs_eff = eq_eff; + } ) ) @@ -753,6 +754,7 @@ and (node_check_do: t -> CompiledData.node_key -> Lxm.t -> SymbolTab.t -> in if not provide_flag then output_string !Global.oc (CompiledDataDump.node_of_node_exp_eff res); + UniqueOutput.check res node_def.src; res diff --git a/src/test/should_work/Pascal/left.lus b/src/test/should_work/Pascal/left.lus index 18f444c3..aa21f4f5 100644 --- a/src/test/should_work/Pascal/left.lus +++ b/src/test/should_work/Pascal/left.lus @@ -5,10 +5,10 @@ type truc = struct { }; -(* XXX TODO 0..98 should work !!! *) node toto(x : bool) returns (t : truc^3); let - t[0].a[0..98 step 2][48..0 step -2] = true^25; +-- t[0].a[0..98 step 2][48..0 step -2] = true^25; + t[0].a[0..98 step 2][0..48 step 2] = true^25; t[0].a[0..98 step 2][1..49 step 2] = false^25; t[0].a[1..99 step 2][0] = true; t[0].a[1..99 step 2][1] = true; diff --git a/src/test/should_work/clock/clock.lus b/src/test/should_work/clock/clock.lus new file mode 100644 index 00000000..19628523 --- /dev/null +++ b/src/test/should_work/clock/clock.lus @@ -0,0 +1,40 @@ + +-- Entree sur entree: ok +extern node clock2(clock2_u: bool; clock2_v: bool when clock2_u) returns (clock2_y: bool ); + +-- Sortie sur sortie: ok +extern node clock3(clock3_u: bool) returns (clock3_toto: bool; clock3_y: bool when clock3_toto); + + +-- Entree sur entree et sortie sur sortie: ok +extern node clock4(clock4_u: bool; clock4_v: bool when clock4_u) returns (clock4_x: bool; clock4_y: bool when clock4_x); + +type s = struct {x: bool^10; y: bool}; + +-- Noeud principal. +node clock(a: bool; b: bool) returns (c: bool; d: bool when c); +var + z: bool; +-- z2: bool; + x: bool when z; +-- y: bool when x; +-- e : bool when b; + +let +-- c = clock2(a, (b or b) when a) or (true->a); +-- d = clock2(a, b when a) when c; + +-- y = clock2(a, b when a) when x; -- ko ? + +-- (z, x) = clock3(current(z)); +-- (z, x) = clock3(current(z when z2)); + (z, x) = clock3(z);-- ok + + + (c, d) = clock4(a, b when a); +-- z = clock5(a, b when a, e when a); +-- z2 = clock5(a, b when a, e when b when c); +tel + + +extern node clock5(x : bool; y: bool when x; z: bool when y) returns (a: bool); diff --git a/src/test/should_work/demo/declaration.lus b/src/test/should_work/demo/declaration.lus index ebeeb1cb..a44568be 100644 --- a/src/test/should_work/demo/declaration.lus +++ b/src/test/should_work/demo/declaration.lus @@ -44,4 +44,6 @@ var c1: real; let b1 = a1 / c1; +-- R1: fix that non-def local + c1 = 1.0; tel; diff --git a/src/test/should_work/fab_test/morel.lus b/src/test/should_work/fab_test/morel.lus index b6cb570d..eb65e9fe 100644 --- a/src/test/should_work/fab_test/morel.lus +++ b/src/test/should_work/fab_test/morel.lus @@ -16,7 +16,7 @@ let b1, b2, b3 = (tabb[0], tabb[1], tabb[2]) ; i1, i2, i3 = (tabi[0][0]+tabi[0][1], tabi[1][0]+tabi[1][1], tabi[2][0]+tabi[2][1]); --- tabb[0] = b; + tabb[0] = b; tabb[1..2] = [true, false] ; tabi[2] = mcmorel(i) ; diff --git a/src/test/should_work/lionel/Gyroscope.lus b/src/test/should_work/lionel/Gyroscope.lus index 8d76b4b5..555f1e68 100644 --- a/src/test/should_work/lionel/Gyroscope.lus +++ b/src/test/should_work/lionel/Gyroscope.lus @@ -33,12 +33,16 @@ tel node assumeSum (accu_in : real; elt_in : real) returns (assumeOK : bool); var varBidon : real; let +-- R1: fix that non-def local + varBidon = 1.0; assumeOK = varBidon < elt_in; tel node guaranteeSum (accu_in : real; elt_in : real; accu_out : real) returns (guaranteeOK : bool); var otherVarBidon : real; let +-- R1: fix that non-def local + otherVarBidon = 1.0; guaranteeOK = elt_in + otherVarBidon < accu_out; tel diff --git a/src/test/should_work/lionel/ProduitBool/produitBool.lus b/src/test/should_work/lionel/ProduitBool/produitBool.lus index 08b24096..1c63ba59 100644 --- a/src/test/should_work/lionel/ProduitBool/produitBool.lus +++ b/src/test/should_work/lionel/ProduitBool/produitBool.lus @@ -104,6 +104,9 @@ let ligne = if multiplicande=false then multiplicande ^ (2*size) else shift(acc_in); + +-- R1: fix that non-def output + acc_out= acc_in; tel diff --git a/src/test/should_work/packEnvTest/contractForElementSelectionInArray/packageTableau.lus b/src/test/should_work/packEnvTest/contractForElementSelectionInArray/packageTableau.lus index 84730f71..1fad9fe2 100644 --- a/src/test/should_work/packEnvTest/contractForElementSelectionInArray/packageTableau.lus +++ b/src/test/should_work/packEnvTest/contractForElementSelectionInArray/packageTableau.lus @@ -74,6 +74,7 @@ node _isElementOf_(e : elementType; t : arrayType) returns (iselementof : bool); var acc_out : T_isElementOf_; let acc_out = red<<iterated_isElementOf_, size>>(T_isElementOf_{eltToSearch = e; iselementof = false}, t); + iselementof = acc_out.iselementof; tel diff --git a/src/test/test.res.exp b/src/test/test.res.exp index 8fa143a9..3f22b15b 100644 --- a/src/test/test.res.exp +++ b/src/test/test.res.exp @@ -2960,7 +2960,7 @@ Opening file /home/jahier/lus2lic/src/test/should_work/Pascal/left.lus type left::truc = left::truc {a : bool^100; b : int}; node left::toto(x:bool) returns (t:left::truc^3); let - t[0].a[0..98 step 2][48..0 step -2] = true^25; + t[0].a[0..98 step 2][0..48 step 2] = true^25; t[0].a[0..98 step 2][1..49 step 2] = false^25; t[0].a[1..99 step 2][0] = true; t[0].a[1..99 step 2][1] = true; @@ -3772,34 +3772,42 @@ tel ---------------------------------------------------------------------- ====> ../lus2lic -vl 2 --compile-all-items should_work/clock/clock.lus Opening file /home/jahier/lus2lic/src/test/should_work/clock/clock.lus -extern node clock::clock3(u:bool) returns (toto:bool; y:bool when toto); +type clock::s = clock::s {x : bool^10; y : bool}; -extern node clock::clock4( - u:bool; - v:bool when u) +extern node clock::clock3( + clock3_u:bool) returns ( - x:bool; - y:bool when x); + clock3_toto:bool; + clock3_y:bool when clock3_toto); -extern node clock::clock5( - x:bool; - y:bool when x; - z:bool when y) +extern node clock::clock4( + clock4_u:bool; + clock4_v:bool when clock4_u) returns ( - a:bool); + clock4_x:bool; + clock4_y:bool when clock4_x); node clock::clock(a:bool; b:bool) returns (c:bool; d:bool when c); var z:bool; x:bool when z; - y:bool when x; - e:bool when b; let (z, x) = clock::clock3(z); (c, d) = clock::clock4(a, b when a); - z = clock::clock5(a, b when a, e when b when a); tel -- end of node clock::clock -extern node clock::clock2(u:bool; v:bool when u) returns (y:bool); + +extern node clock::clock2( + clock2_u:bool; + clock2_v:bool when clock2_u) +returns ( + clock2_y:bool); + +extern node clock::clock5( + x:bool; + y:bool when x; + z:bool when y) +returns ( + a:bool); ---------------------------------------------------------------------- ====> ../lus2lic -vl 2 --compile-all-items should_work/demo/Gyroscope2.lus @@ -4412,6 +4420,7 @@ var c1:real; let b1 = (a1 / c1); + c1 = 1.0; tel -- end of node declaration::n5 @@ -5141,6 +5150,7 @@ let (b1, b2, b3) = (tabb[0], tabb[1], tabb[2]); (i1, i2, i3) = ((tabi[0][0] + tabi[0][1]), (tabi[1][0] + tabi[1][1]), (tabi[2][0] + tabi[2][1])); + tabb[0] = b; tabb[1..2] = [true, false]; tabi[2] = morel::mcmorel(i); tabi[0..1] = [[10, 100], [1000, 10000]]; @@ -6593,6 +6603,7 @@ returns ( var varBidon:real; let + varBidon = 1.0; assumeOK = (varBidon < elt_in); tel -- end of node Gyroscope::assumeSum @@ -6808,6 +6819,7 @@ returns ( var otherVarBidon:real; let + otherVarBidon = 1.0; guaranteeOK = ((elt_in + otherVarBidon) < accu_out); tel -- end of node Gyroscope::guaranteeSum @@ -6936,6 +6948,7 @@ returns ( let ligne = if ((multiplicande = false)) then (multiplicande^20) else (produitBool::shift(acc_in)); + acc_out = acc_in; tel -- end of node produitBool::PLC @@ -8419,6 +8432,7 @@ var let acc_out = red<<node intArray::iterated_isElementOf_, const 10>>(T_isElementOf_{eltToSearch=e;iselementof=false}, t); + iselementof = acc_out.iselementof; tel -- end of node intArray::_isElementOf_ type intArray::forSortingAlgo = intArray::forSortingAlgo {previousElement : int; sortedUpToHere : bool}; diff --git a/src/uniqueOutput.ml b/src/uniqueOutput.ml new file mode 100644 index 00000000..8c322759 --- /dev/null +++ b/src/uniqueOutput.ml @@ -0,0 +1,334 @@ + + +open CompiledData +open Lxm +open Errors + +(* given a list of (output) [var_info_eff] [vl], and a list of + [left_eff] [lel], we want to check that each variable is defined + exactly once by the [left_eff]. To do that, we first transform + [vl] into a list of variable atoms. +*) +type atom = string +(* | Var of (var_info_eff) *) +(* | Field of (atom * Ident.t) *) +(* | Array of (atom * int) *) + +let rec (var_info_eff_to_atoms: var_info_eff -> atom list) = + fun v -> + type_eff_to_atoms (Ident.to_string v.var_name_eff) v.var_type_eff + +and make_int_list acc i = if i < 0 then acc else make_int_list (i::acc) (i-1) + +and slice_info_to_int_list si i = + if ( + (si.se_step > 0 && i > si.se_last) + || + (si.se_step < 0 && i < si.se_last) + ) + then + [] + else + i::(slice_info_to_int_list si (i + si.se_step)) + + +and (type_eff_to_atoms : atom -> type_eff -> atom list) = + fun str type_eff -> + let res = + match type_eff with + | Bool_type_eff + | Int_type_eff + | Real_type_eff + | Any + | Overload + | External_type_eff _ + | Enum_type_eff(_,_) -> [str] + | Array_type_eff(te,i) -> + List.flatten + (List.map + (fun i -> type_eff_to_atoms (str ^ "[" ^(string_of_int i)^"]") te) + (make_int_list [] (i-1))) + + | Struct_type_eff(name, fl) -> + List.flatten + (List.map + (fun (id,(te,_)) -> + type_eff_to_atoms (str ^ "." ^(Ident.to_string id)) te + ) + fl) + in + res + +(* Generates the string corresponding to the [left_eff]. It returns + a list of strings because of the slices. Indeed, when generating + the string for the [left_eff] corresponding to "expr[2..3].a", we + actually want to generate 2 strings: + + - "expr[2].a", and + - "expr[3].a" + + le pb, c'est que pour "t[1..10][2..4]", je veux pas générer + - "t[1][2]", etc., + mais "t[3]", "t[4]", "t[5]" ! arg... il me faut faire quelque chose + pour les tranches de tranches. + + + meme chose pour "T[1..4 step 2][1]" en fait (qui vaut t[3]) + + il faudrait que je normalise tout ca avant. Il y a plein de facon de dire + la même chose. + + -> rendre le step positif + -> mise a plat des tranches de tranches + -> mise a plat d'une tranche suivis d'un acces à un tableau + + +*) +and (left_eff_to_string : left_eff -> atom list) = + fun le -> + let res = + match le with + | LeftVarEff (v,_) -> [Ident.to_string v.var_name_eff] + | LeftFieldEff(le,id,te) -> + let strl = left_eff_to_string le in + List.map (fun str -> str^"."^(Ident.to_string id)) strl + | LeftArrayEff(le,i,te) -> + let strl = left_eff_to_string le in + List.map (fun str -> (str ^ "[" ^ (string_of_int i) ^ "]")) strl + + | LeftSliceEff(LeftSliceEff(le,si1,te1),si2,te2) -> + assert false + | LeftSliceEff(le,si,te) -> + let strl = left_eff_to_string le in + List.flatten + (List.map + (fun i -> List.map + (fun str -> (str^"["^(string_of_int i) ^ "]")) + strl) + (slice_info_to_int_list si si.se_first) + ) + in + res + +and (left_eff_to_atoms : left_eff * Lxm.t -> (atom * Lxm.t) list) = + fun (le,lxm) -> + let res = + match le with + | LeftVarEff (v,lxm) -> List.map (fun a -> a,lxm) (var_info_eff_to_atoms v) + + | LeftArrayEff(LeftSliceEff(le1,si1,te1),l,te2) -> + (* le1[i..j step k][l] = le1[i + k*l] *) + let (i,j,k) = + if si1.se_step > 0 + then (si1.se_first, si1.se_last,si1.se_step) + else (si1.se_last, si1.se_first, - si1.se_step) + in + let new_l = i + l * k in + left_eff_to_atoms (LeftArrayEff(le1, new_l, te2), lxm) + + | LeftSliceEff(LeftSliceEff(le1,si1,te1),si2,te2) -> + (* we need we interpret on-the-fly slices of slices... + le1[i1..j1 step k1][i2..j2 step k2] = + le1[ i1+i2*k1 + .. i1+(j2+i2*(k1-1))*k2 + step k1*k2 ] + if k1 and k2 are positive. + + k1<0, k2>0 + + what happens if one (or both) are negative ? + + *) + let (i1,j1,k1) = (si1.se_first, si1.se_last,si1.se_step) in + let (i2,j2,k2) = (si2.se_first, si2.se_last,si2.se_step) in + let si12 = { + se_first = i1+i2*k1; + se_last = i1+(j2+i2*(k1-1))*k2; + se_step = k1 * k2; (* bug si < 0 ! *) + se_width = -1; + } + in + left_eff_to_atoms(LeftSliceEff(le1, si12,te2), lxm) + | LeftFieldEff(le2,_,te) + | LeftArrayEff(le2,_,te) + | LeftSliceEff(le2,_,Array_type_eff(te,_)) -> + let al = left_eff_to_string le in + List.map (fun a -> a,lxm) + (List.flatten (List.map (fun a -> type_eff_to_atoms a te) al)) + in + res + +module StrSet = Set.Make(String) + +let (check_aux : Lxm.t -> var_info_eff list -> (left_eff * Lxm.t) list -> unit) = + fun lxm vl lel -> + let l1 = List.flatten (List.map var_info_eff_to_atoms vl) in + let l2 = List.flatten (List.map left_eff_to_atoms lel) in +(* let _ = *) +(* print_string ("\noutputs to be defined: "); *) +(* List.iter (fun str -> print_string (str ^ ", ")) l1; *) +(* print_string ("\ndefined left eff: "); *) +(* List.iter (fun (str,_) -> print_string (str ^ ", ")) l2; *) +(* print_string "\n checking...\n"; *) +(* flush stdout *) +(* in *) + let set1 = List.fold_left (fun set x -> StrSet.add x set) StrSet.empty l1 in + let set2 = + List.fold_left + (fun set (elt,lxm) -> + if StrSet.mem elt set then StrSet.remove elt set else + let msg = + if StrSet.mem elt set1 then + "\n*** This variable is defined twice: " ^ elt + else + "\n*** This variable is undeclared: " ^ elt + in + raise (Compile_error(lxm, msg)) + ) + set1 + l2 + in + if not (StrSet.is_empty set2) then + let vars = (StrSet.fold (fun elt acc -> elt::acc) set2 []) in + let msg = + (if List.length vars = 1 then + "\n*** The following variable is undefined: " + else + "\n*** The following variables are undefined: ") ^ + (String.concat ", " vars) + in + raise (Compile_error(lxm, msg)) + +(* Check that each output is defined exactly once *) + +let (check : CompiledData.node_exp_eff -> Lxm.t -> unit) = + fun node lxm -> + let ol = match node.loclist_eff with + None -> node.outlist_eff + | Some l -> node.outlist_eff @ l + in + match node.def_eff with + | ExternEff + | AbstractEff -> () + | BodyEff{ eqs_eff = eql } -> + let lpll = + List.map + (fun ({ it = (lel,_); src = lxm }) -> + List.map (fun le -> (le,lxm)) lel + ) + eql + in + let (lpl:(left_eff * Lxm.t) list) = List.flatten lpll in + + check_aux lxm ol lpl + + +(* Then, for each chunk, we search in [lel] a element [le] that + concerns v, and we compute the list of chunks that correspond to + the part of a that is not covered by [le]. That new list of chunks + is added to the list of chunks to be checked. And we continue + until there are no more chunks or no more [left_eff]. + + In order to reduce the complexity of that algo, we first partition + the [lel] according to the variable they define. +*) + + +(* module VarMap = Map.Make(struct type t=var_info_eff let compare = compare end) *) +(* *) +(* let (partition_var : left_eff list -> (left_eff list) VarMap.t) = *) +(* fun l -> *) +(* List.fold_left *) +(* (fun tab le -> *) +(* let v = var_info_of_left_eff le in *) +(* try VarMap.add v (le::(VarMap.find v tab)) tab *) +(* with Not_found -> VarMap.add v [le] tab *) +(* ) *) +(* VarMap.empty *) +(* l *) +(* *) +(* *) +(* (* Hence, given a list of [left_eff] that all concerns v, it is less *) +(* expensive (we operate on smaller lists) to check that [v] is *) +(* completety and uniquely defined. *) +(* *) +(* The idea to perform that check is to, from a left_eff and from a var_info_eff, *) +(* generates the list of atomic variables they defined. e.g., an array of *) +(* size 10 will generated 10 atomic variables. Then, we just have to *) +(* compare the list that comes from the left_eff, and the one that comes from *) +(* the output variables. *) +(* *) +(* *) *) +(* *) +(* type atom = *) +(* | Var of *) +(* | Field of *) +(* let ( *) +(* *) +(* *) +(* *) +(* *) +(* *) +(* *) +(* *) +(* *) +(* *) +(* *) +(* *) +(* *) +(* *) +(* let (check_one_chunk : chunk -> left_eff -> chunk list) = *) +(* fun c le -> match c,le with *) +(* | Var v -> ( *) +(* match le with *) +(* | LeftVarEff (_,_) -> [] *) +(* | LeftFieldEff(le,id,Struct_type_eff(_,fl)) -> *) +(* let fl = List.filter (fun f -> f <> id) fl in *) +(* List.map (fun (id, (te,_)) -> ) fl *) +(* | LeftArrayEff(le,i,_) -> *) +(* | LeftSliceEff(le,si,_) -> *) +(* ) *) +(* *) +(* | Field(c,id), LeftFieldEff(le,id,_) -> *) +(* | Array(c,i), LeftArrayEff(le,i,_) -> *) +(* | Slice(c, low, high),LeftSliceEff(le,si,_) -> *) +(* ddd *) +(* *) +(* *) +(* let (reconstruct : var_info_eff -> chunk list -> *) +(* *) +(* *) +(* *) +(* let (check_one_var : var_info_eff -> left_eff_list -> unit) = *) +(* fun v lel -> *) +(* let rec (aux : chunk list -> left_eff_list -> unit) = *) +(* fun cl lel -> *) +(* match cl with *) +(* | [] -> if lel <> [] then failwith "output variable defined twice" *) +(* | x::cl -> let new_chunks = check_one_chunk x lel *) +(* in *) +(* aux [Var v] lel *) +(* *) +(* let (check_one_chunk : chunk -> left_eff list -> chunk list) = *) +(* fun al le -> *) +(* (* checks that le is used in [lel]: *) +(* Removes the part that is used, but it migth add some chunks *) *) +(* match le with *) +(* | LeftVarEff(v,_) -> ( *) +(* let (al1, al2) = List.partition (fun a -> a = Var(v)) al in *) +(* match al1 with *) +(* | [] -> failwith "output variable undefined" *) +(* | _::_ -> failwith "output variable defined twice" *) +(* | [_] -> al2 *) +(* ) *) +(* | LeftFieldEff(le,id,_) -> ( *) +(* let (al1, al2) = List.partition (fun a -> a = Field(_,id)) al in *) +(* match al1 with *) +(* | [] -> failwith "output variable undefined" *) +(* | _::_ -> failwith "output variable defined twice" *) +(* | [_] -> al2 *) +(* ) *) +(* | LeftArrayEff(le,i,_) -> *) +(* | LeftSliceEff(le, si,_) -> *) +(* *) +(* (* (* (* *) *) *) *) -- GitLab