From 09b1e4d6dba949bfef839d34efcbf09112c94b02 Mon Sep 17 00:00:00 2001 From: Erwan Jahier <jahier@imag.fr> Date: Thu, 12 Jun 2008 11:21:10 +0200 Subject: [PATCH] Begin to implement clock checkinhg of expressions. It does not work, I have changed my mind to use a more general clocking algorithm based on unification. I commit that current state just in case I change my mind again... --- src/Makefile | 2 + src/TODO | 3 + src/compiledData.ml | 28 +- src/compiledDataDump.ml | 8 + src/evalClock.ml | 374 ++++++++++++++++++ src/evalClock.mli | 35 ++ src/evalType.ml | 4 +- src/getEff.ml | 83 ++-- src/getEff.mli | 6 +- src/lazyCompiler.ml | 3 +- src/parserUtils.ml | 52 +-- src/predefEvalClock.ml | 57 ++- src/predefEvalClock.mli | 6 +- src/predefEvalType.ml | 15 +- src/predefEvalType.mli | 4 +- src/syntaxTreeCore.ml | 3 +- src/test/should_fail/clock/clock.lus | 14 +- src/test/should_fail/semantics/bad_call03.lus | 2 +- src/test/test.res.exp | 36 +- 19 files changed, 635 insertions(+), 100 deletions(-) create mode 100644 src/evalClock.ml create mode 100644 src/evalClock.mli diff --git a/src/Makefile b/src/Makefile index 00354d09..ff93d3dc 100644 --- a/src/Makefile +++ b/src/Makefile @@ -46,6 +46,8 @@ SOURCES = \ ./evalConst.ml \ ./evalType.mli \ ./evalType.ml \ + ./evalClock.mli \ + ./evalClock.ml \ ./getEff.mli \ ./getEff.ml \ ./lazyCompiler.ml \ diff --git a/src/TODO b/src/TODO index ce75d692..84c7f2bf 100644 --- a/src/TODO +++ b/src/TODO @@ -136,6 +136,9 @@ n'est pas le cas pour l'instant... *** facile +* dans evalType, je ne checke pas tous les arguments ! +ecrire les tests idoines puis faire ces checks. + * verifier que chacun des exemples du repertoire "should_fail" échoue avec un bon message d'erreur. diff --git a/src/compiledData.ml b/src/compiledData.ml index c7f579a8..15bfdd2a 100644 --- a/src/compiledData.ml +++ b/src/compiledData.ml @@ -1,4 +1,4 @@ -(** Time-stamp: <modified the 09/06/2008 (at 10:05) by Erwan Jahier> *) +(** Time-stamp: <modified the 12/06/2008 (at 11:06) by Erwan Jahier> *) (** @@ -239,6 +239,7 @@ and const_eff = and var_info_eff = { var_name_eff : Ident.t; var_nature_eff : var_nature; + var_number_eff : int; var_type_eff : type_eff; var_clock_eff : clock_eff; } @@ -285,7 +286,24 @@ and static_arg_eff = | NodeStaticArgEff of (Ident.t * node_exp_eff) - +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 @@ -439,6 +457,12 @@ let (type_eff_of_left_eff: left_eff -> type_eff) = | LeftArrayEff(_, _, t_eff) -> t_eff | LeftSliceEff(_, _, t_eff) -> t_eff +let rec (clock_of_left_eff: left_eff -> clock_eff) = + function + | LeftVarEff (var_info_eff, _) -> var_info_eff.var_clock_eff + | LeftFieldEff (left_eff,_,_) -> clock_of_left_eff left_eff + | LeftArrayEff (left_eff,_,_) -> clock_of_left_eff left_eff + | LeftSliceEff (left_eff,_,_) -> clock_of_left_eff left_eff (*--------------------------------------------------------------------- diff --git a/src/compiledDataDump.ml b/src/compiledDataDump.ml index fd2b1a68..55bb79b0 100644 --- a/src/compiledDataDump.ml +++ b/src/compiledDataDump.ml @@ -313,6 +313,12 @@ and (node_of_node_exp_eff: node_exp_eff -> string) = ) +and string_of_clock2 (ck : clock_eff) = + match ck with + | BaseEff -> " on base " + | On veff ->" on " ^ (Ident.to_string veff.var_name_eff) ^ + (string_of_clock veff.var_clock_eff) + and string_of_clock (ck : clock_eff) = match ck with | BaseEff -> "" @@ -320,6 +326,8 @@ and string_of_clock (ck : clock_eff) = (string_of_clock veff.var_clock_eff) +and string_of_clock_list cl = + "(" ^ (String.concat ", " (List.map string_of_clock cl)) ^ ")" (*--------------------------------------------------------------------- Formatage standard des erreurs de compil diff --git a/src/evalClock.ml b/src/evalClock.ml new file mode 100644 index 00000000..fb1c68b4 --- /dev/null +++ b/src/evalClock.ml @@ -0,0 +1,374 @@ +(** Time-stamp: <modified the 12/06/2008 (at 11:10) by Erwan Jahier> *) + + +open Predef +open PredefEvalConst +open SyntaxTree +open SyntaxTreeCore +open CompiledData +open CompiledDataDump +open Printf +open Lxm +open Errors + + +(** clock checking of expression. + + nb: + In the following, we speak about input/output arguments/parameters of an + expression because: + - the difficult case wrt clock checking concerns nodes + - other kind of expressions can be seen as nodes, as they «take» some input + arguments, and return some outputs. + + + The clock checking consists in verifying that expression arguments clocks + are compatible with the expression parameters clocks. + + For instance, for a node of profile: + + node toto(a; b when a) returns (x when a; y when x); + + when it is called, e.g., like that: + + (v1,v2) = toto(v3,v4); + + we need to check that: + - the argument clocks are ok, i.e., v4 is on v3 (1) + cf the [check_arg] function below + - the result clocks are ok, i.e., v2 is on v1 + v1 is on v3 (2) + cf the [check_res] function below + + Let's focus first on argument checking: +*) +type clock_info_par = + | Base_par of var_info_eff + | Input_par of var_info_eff * int + | Output_par of var_info_eff * int + +(** A [clock_info_par] is an abstraction of a [var_info_eff] meant to + be able to check the clocks of expressions arguments. A pair of + list of [clock_info_par] is therefore represent the expression + clock profile. + + In this abstraction, the name binding is replaced by a relative + position binding. + + For instance, for a node toto of profile: + + node toto(a; b when a) returns (x when a; y when x); + + we have as input profile: [Base_arg; Input_par 0] + and as output profile: [Input_par 0, Output_par 0] + + This information is extracted from the node profile by + [get_clock_profile]: +*) + +type clock_profile = clock_info_par list * clock_info_par list + +let (get_clock_profile : Lxm.t -> node_exp_eff -> clock_profile) = + fun lxm n -> + let (il, ol) = (n.inlist_eff, n.outlist_eff) in + let rec find_index v l i = + match l with + | [] -> raise Not_found + | v2::tail -> if v=v2 then i else find_index v tail (i+1) + in + let f v = + match v.var_clock_eff with + | BaseEff -> Base_par(v) + | On clk -> + try Input_par(v, find_index clk il 0) + with Not_found -> + try Output_par(v, find_index clk ol 0) + with Not_found -> + let msg = "\n*** "^ (Ident.to_string clk.var_name_eff)^ + ": unknown clock" in + raise(Compile_error (lxm, msg)) + in + (List.map f il, List.map f ol) + +(** We also introduce a second kind of var_info_eff abstraction, dedicated + to the checking of expresion result: +*) +type clock_info_res = + | Base_res of var_info_eff + | OnVar of var_info_eff * var_info_eff + | OnRel of var_info_eff * int + +let string_of_clock_info_res = function + | Base_res v -> (Ident.to_string v.var_name_eff) ^ " on base" + | OnVar (v,clk) -> (Ident.to_string v.var_name_eff) ^ " on " ^ + (Ident.to_string clk.var_name_eff) + | OnRel (v,i) -> (Ident.to_string v.var_name_eff) ^ " on #" ^ + (string_of_int i) ^ "^nth" + +(** For example, when checking the equation + + (x,y)=toto(a,b); + + the clock checking of "toto(a,b)" will return + [OnVar a, OnRel 0] + which makes it easy to compute that: + - x is on a, + - y is on x + + Hence, [clock_info_res list] is the type that is return by f, the + main function of this clock checking module. + + + ** Checking expression arguments + -------------------------------- + + ok. So now, let us detail how we clock check expression + arguments. e.g., in the equation + + (x,y)=toto(a,b); + + we want to make sure that the clocks of the argument "a" and "b" are compatible + with the input clock profile of "toto". + + To do that, we suppose we have already computed: + + - "ci_par_l" the expected input clock profile (via "get_clock_profile" defined + above) + - "cl" the list of arguments "clock_info_res" (via a rec call to f) +*) +let (check_args : Lxm.t -> clock_info_par list -> clock_info_res list -> unit) = + fun lxm ci_par_l cl -> + let (f : clock_info_par -> clock_info_res -> unit) = + fun cip cir -> match (cip,cir) with + | Base_par _, Base_res _ -> () + | Input_par(vpar,i), OnRel (v,j) -> if i = j then () else + let msg = "\n*** clock error" in + raise(Compile_error(lxm,msg)) + + | Input_par(vpar,i), OnVar (v,clk) -> + (match List.nth cl i with + | OnVar (v2,clk2) -> + if clk2 = clk then () else + let msg = "\n*** clock error: " ^ + (string_of_clock_info_res (OnVar (v,clk))) ^ " (provided) <> " ^ + (string_of_clock_info_res (OnVar (v2,clk2))) ^ " (expected)" + in + raise(Compile_error(lxm, msg)) + | Base_res(v2) -> + let msg = "\n*** clock error: " ^ + (string_of_clock_info_res (OnVar (v,clk))) ^ " (provided) <> " ^ + "base (expected)" + in + raise(Compile_error(lxm,msg)) + | OnRel (v,i) -> assert false + ) + | Input_par _, Base_res(_) + | Base_par _, _ -> + raise(Compile_error(lxm,"\n*** clock error: bad arg clocks")) + | Output_par _, _ -> assert false (* inputs cannot be clocked on outputs*) + in + List.iter2 f ci_par_l cl + +(** In order to use check_args, we need another intermediary function + that merges list of list of [clock_info_res]. Indeed, to be able + to check the arguments of an expression like: + + tata(toto(a,b),toto(c,d)); + + We sais before that we compute the [clock_info_res list] of the + arguments via a recursive call to f. But such a recursive call + returns a list of list of [clock_info_res], which contains + information relative to variable positions. Therefore we cannot + just flatten that list of list; we also need to shift the indexes + encoding variable positions. + + For example, for checking the args of tata above, we call + + merge_clock_ll [[OnVar a; OnRel 0]; [OnVar c; OnRel 0]] + + that ougth to return the following flattenned list with shifted index: + + [OnVar a; OnRel 0; OnVar c; OnRel 2] + + and then we can call check_res with that list. +*) + +let (merge_clock_ll: clock_info_res list list -> clock_info_res list) = + fun ll -> + let f (shift,acc) l = + let new_l = List.map + (function + | Base_res(v) -> Base_res(v) + | OnVar(v,clk) -> OnVar(v,clk) + | OnRel(v,j) -> OnRel(v,j+shift) + ) + l + in + (shift + (List.length l), acc @ new_l) + in + snd (List.fold_left f (0,[]) ll) + + + +(** Checking expression result + -------------------------- + + e.g., in the equation: + + (x,y)=toto(a,b); + + we want to check that the clocks of "x" and "y" are compatible with + the output clock profile of node "toto". + + To do that, we suppose we have already computed: + + - "cil" the expected output clock profile (via "get_clock_profile" again) + - "cel" the list of result "clock_info_res" + +*) +let (check_res2 : Lxm.t -> clock_info_res list -> clock_info_res list -> unit) = + fun lxm cil cel -> + if cil = cel then () else + let msg = "\n*** clock error: " ^ + (String.concat ", " (List.map string_of_clock_info_res cil)) ^ " <> " ^ + (String.concat ", " (List.map string_of_clock_info_res cel)) + in + raise(Compile_error(lxm,msg)) + +let (get_nth_var : clock_info_res list -> int -> var_info_eff) = + fun vil i -> + match List.nth vil i with + | Base_res(v) -> v + | OnVar(v,_) -> v + | OnRel(v,_) -> v + +let (check_res : Lxm.t -> clock_info_res list -> clock_eff list -> unit) = + fun lxm rigth left -> + let cpt = ref 0 in + let (f : clock_info_res -> clock_eff -> unit) = + fun cip ce -> + incr cpt; + match (cip,ce) with + | Base_res(_), BaseEff -> () + | OnVar(v1,clk1), On clk2 -> + if clk1 = clk2 then () else + let msg = "\n*** clock error (ckeck_res), " ^ + (string_of_int !cpt) ^ "nth element:"^ + (Ident.to_string clk2.var_name_eff) ^ " <> " ^ + (Ident.to_string clk1.var_name_eff) + in + raise(Compile_error(lxm,msg)) + + | OnRel(v,i), On clk -> + let clk2 = get_nth_var rigth i in + if clk2 = clk then () else + let msg = "\n*** clock error (ckeck_res), " ^ + (string_of_int !cpt) ^ "nth element:"^ + (Ident.to_string clk.var_name_eff) ^ " <> " ^ + (Ident.to_string clk2.var_name_eff) + in + raise(Compile_error(lxm,msg)) + + + | Base_res _, On _ + | _, BaseEff -> raise(Compile_error(lxm,"\n*** clock error")) + in + if List.length rigth <> List.length left then + raise(Compile_error(lxm,"\n*** clock error")) + else + List.iter2 f rigth left + + + + +(** Now we can go on and define [f]. *) + +(******************************************************************************) + +let rec (f : id_solver -> val_exp_eff -> clock_info_res list) = + fun id_solver ve -> + match ve with + | CallByPosEff ({it=posop; src=lxm}, OperEff args) -> ( + eval_by_pos_clock id_solver posop lxm args + ) + | CallByNameEff ({it=nmop; src=lxm}, nmargs ) -> + try eval_by_name_clock id_solver nmop lxm nmargs + with EvalConst_error msg -> + raise (Compile_error(lxm, "\n*** can't eval constant: "^msg)) + +and (eval_by_pos_clock : id_solver -> by_pos_op_eff -> Lxm.t -> val_exp_eff list + -> clock_info_res list) = + fun id_solver posop lxm args -> + match posop with + | CALL_eff node_exp_eff -> + let (ip,op) = get_clock_profile node_exp_eff.src node_exp_eff.it in + let clocks_of_args = merge_clock_ll (List.map (f id_solver) args) in + let res = + List.map + (function + | Base_par(v) -> Base_res(v) + | Output_par(v, i) -> OnRel(v, i) + | Input_par(v, i) -> + (* that would occur if one writes + toto(tata(x),x) + where one output clock of tata depends on one of its input, eg + + node tata(i) returns (o when i) + + arg... + *) + let msg = "\n*** clock error: this kind of expression can "^ + "not be clocked with our current algo, sorry..." in + raise (Compile_error(lxm,msg)) + ) + op + in + check_args lxm ip clocks_of_args; + res + + + | CURRENT_eff -> assert false (* prendre l'horloge de l'horloge de l'argument *) + + | WHEN_eff -> + let clk_exp = List.nth args 1 in + (* Non: je doit plutot extraire de clk_exp une var_info_eff, + et raler si ca n'est pas possible. + *) + (f id_solver clk_exp) + + + | MERGE_eff _ -> f id_solver (List.hd args) + + | Predef_eff (_,_) + | WITH_eff + | ARROW_eff + | FBY_eff + | CONCAT_eff + | HAT_eff(_,_) + | PRE_eff + | STRUCT_ACCESS_eff _ + | ARRAY_ACCES_eff (_, _) + | ARRAY_SLICE_eff (_,_) + | ARRAY_eff -> ( + (* check that args are of the same clocks, which also is the + returned clock *) + match List.flatten (List.map (f id_solver) args) with + | clk1::tail -> + if List.for_all (fun clk -> clk = clk1) tail then [clk1] else + raise (Compile_error(lxm, "clock mismatch")) + | [] -> assert false + ) + + | 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 *) + + +and (eval_by_name_clock : id_solver -> by_name_op_eff -> Lxm.t -> + (Ident.t Lxm.srcflagged * val_exp_eff) list -> clock_info_res list) = + fun id_solver namop lxm namargs -> + match namop with + | STRUCT_anonymous_eff -> assert false (* cf EvalClock.f *) + | STRUCT_eff opid -> assert false +(* [id_solver.id2clock opid lxm] *) + diff --git a/src/evalClock.mli b/src/evalClock.mli new file mode 100644 index 00000000..d911f3f3 --- /dev/null +++ b/src/evalClock.mli @@ -0,0 +1,35 @@ +(** Time-stamp: <modified the 12/06/2008 (at 09:50) by Erwan Jahier> *) + +open CompiledData + + +(** [f ids ve ]checks that [ve] is well-clocked (i.e., for node calls, + it checks that the argument and the parameter clocks are correct), + and returns a clock profile that contains all the necessary information + to be able to check. +*) + +type clock_info_res + +val f : id_solver -> val_exp_eff -> clock_info_res list + +(** [check_res lxm cel cil] check that the expected output clock + profile of an expression "cil" is compatible with the result clocks + "cel" of the expression. + + For instance, for clocks checking the equation + + (x,y)=toto(a,b); + + it checks that the clock of "(x,y)" (cel) is compatible with the + output clock profile of node toto (cil). + + The type [clock_info_res] is exported to be able to call that + function outside this module, which is necessary to clock + equations (an equation is not an expression (i.e., not a + val_exp_eff). + +*) + +val check_res : Lxm.t -> clock_info_res list -> clock_eff list -> unit +val merge_clock_ll: clock_info_res list list -> clock_info_res list diff --git a/src/evalType.ml b/src/evalType.ml index 05738353..21613165 100644 --- a/src/evalType.ml +++ b/src/evalType.ml @@ -1,4 +1,4 @@ -(** Time-stamp: <modified the 09/06/2008 (at 10:50) by Erwan Jahier> *) +(** Time-stamp: <modified the 09/06/2008 (at 14:47) by Erwan Jahier> *) open Predef @@ -99,7 +99,7 @@ and (eval_by_pos_type : | [x] -> type_error [x] "struct type" | x -> arity_error x "1" ) - | ARRAY_ACCES_eff (_, teff) -> [teff] + | ARRAY_ACCES_eff (_, teff) -> [teff] (* XXX check args type! *) | ARRAY_SLICE_eff (sieff,teff) -> [Array_type_eff(teff, sieff.se_width)] diff --git a/src/getEff.ml b/src/getEff.ml index 4c4e55eb..c12aebf2 100644 --- a/src/getEff.ml +++ b/src/getEff.ml @@ -1,4 +1,4 @@ -(** Time-stamp: <modified the 09/06/2008 (at 10:03) by Erwan Jahier> *) +(** Time-stamp: <modified the 12/06/2008 (at 11:12) by Erwan Jahier> *) open Lxm @@ -32,7 +32,6 @@ let rec (typ:CompiledData.id_solver -> SyntaxTreeCore.type_exp -> with GetEffType_error msg -> raise (Compile_error(texp.src, "can't eval type: "^msg)) -(******************************************************************************) (* exported *) let rec (clock : CompiledData.id_solver -> SyntaxTreeCore.clock_exp -> CompiledData.clock_eff)= @@ -42,6 +41,43 @@ let rec (clock : CompiledData.id_solver -> SyntaxTreeCore.clock_exp -> | NamedClock id -> On (id_solver.id2var (Ident.to_idref id.it) id.src) +(******************************************************************************) +(* Checks that the left part has the same type as the right one. *) +and (type_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_teff = List.map type_eff_of_left_eff lpl_eff in + let right_part = EvalType.f id_solver ve_eff in + if (List.length lpl_teff <> List.length right_part) then + raise (Compile_error(eq_info.src, + "tuple size error: \n*** the tuple size is\n***\t"^ + (string_of_int (List.length lpl_teff)) ^ + " for the left-hand-side, and \n***\t" ^ + (string_of_int (List.length right_part)) ^ + " for the right-hand-side")) + else + List.iter2 + (fun le re -> + if le <> re then + let msg = "type mismatch: \n***\t'" + ^ (CompiledDataDump.string_of_type_eff le) ^ + "' (left-hand-side) \n*** is not compatible with \n***\t'" + ^ (CompiledDataDump.string_of_type_eff re) ^ "' (right-hand-side)" + in + raise (Compile_error(eq_info.src, msg)) + ) + lpl_teff + right_part + +(* Checks that the left part has the same clock as the right one. *) +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 (get_static_params_from_idref : SymbolTab.t -> Lxm.t -> Ident.idref -> static_param srcflagged list) = @@ -64,7 +100,7 @@ let rec (node : CompiledData.id_solver -> SyntaxTreeCore.node_exp srcflagged -> in id_solver.id2node idref static_args_eff lxm - + (** [check_static_arg this pn id sa (symbols, acc)] compile a static arg into a static_arg_eff *) @@ -82,12 +118,12 @@ and (check_static_arg : CompiledData.id_solver -> | StaticArgIdent idref, StaticParamType(id) -> let teff = node_id_solver.id2type idref sa.src in TypeStaticArgEff (id, teff) - + | StaticArgIdent idref, StaticParamNode(id,_,_,_) -> let sargs = [] in - (* We suppose that static arg cannot themselves be - template calls (eg, f<<g<<3>>>> is forbidden) - *) + (* We suppose that static arg cannot themselves be + template calls (eg, f<<g<<3>>>> is forbidden) + *) let neff = node_id_solver.id2node idref sargs sa.src in NodeStaticArgEff (id, neff) @@ -122,16 +158,17 @@ and (check_static_arg : CompiledData.id_solver -> | StaticArgNode _, StaticParamType(id) | StaticArgNode _, StaticParamConst(id,_) - + | StaticArgConst _, StaticParamNode(id,_,_,_) | StaticArgConst _, StaticParamType(id) - -> + -> assert false (* can it occur actually? Let's wait it occurs...*) in sa_eff (******************************************************************************) + (* exported *) and (eq : id_solver -> eq_info srcflagged -> eq_info_eff srcflagged) = fun id_solver eq_info -> @@ -139,32 +176,8 @@ and (eq : id_solver -> eq_info srcflagged -> eq_info_eff srcflagged) = let lpl_eff = List.map (translate_left_part id_solver) lpl and ve_eff = translate_val_exp id_solver ve in - (* Type check here (i.e., check that the left part has the same type as the - right one). - *) - let lpl_teff = List.map type_eff_of_left_eff lpl_eff in - let right_part = EvalType.f id_solver ve_eff in - if (List.length lpl_teff <> List.length right_part) then - raise (Compile_error(eq_info.src, - "tuple size error: \n*** the tuple size is\n***\t"^ - (string_of_int (List.length lpl_teff)) ^ - " for the left-hand-side, and \n***\t" ^ - (string_of_int (List.length right_part)) ^ - " for the right-hand-side")) - else - List.iter2 - (fun le re -> - if le <> re then - let msg = "type mismatch: \n***\t'" - ^ (CompiledDataDump.string_of_type_eff le) ^ - "' (left-hand-side) \n*** is not compatible with \n***\t'" - ^ (CompiledDataDump.string_of_type_eff re) ^ "' (right-hand-side)" - in - raise (Compile_error(eq_info.src, msg)) - ) - lpl_teff - right_part; - (* type is ok *) + type_check_equation id_solver eq_info lpl_eff ve_eff; +(* clock_check_equation id_solver eq_info lpl_eff ve_eff; *) flagit (lpl_eff, ve_eff) eq_info.src diff --git a/src/getEff.mli b/src/getEff.mli index ff5df7dc..cc6a5826 100644 --- a/src/getEff.mli +++ b/src/getEff.mli @@ -1,4 +1,4 @@ -(** Time-stamp: <modified the 09/06/2008 (at 10:05) by Erwan Jahier> *) +(** Time-stamp: <modified the 09/06/2008 (at 11:27) by Erwan Jahier> *) (** This module defines functions that translate SyntaxTreeCore datatypes into @@ -9,8 +9,8 @@ - calls [EvalConst.f] wherever it is necessary, i.e., for items that are required to be static, such as arrays sizes, or array indexes. - - - recursively call itself for translating sub-terms + - recursively calls itself for translating sub-terms + - checks the arguments and the parameters are compatible (i.e., that they unify) *) val typ : CompiledData.id_solver -> SyntaxTreeCore.type_exp -> CompiledData.type_eff diff --git a/src/lazyCompiler.ml b/src/lazyCompiler.ml index 48f83c5b..3a3d27f0 100644 --- a/src/lazyCompiler.ml +++ b/src/lazyCompiler.ml @@ -1,4 +1,4 @@ -(** Time-stamp: <modified the 09/06/2008 (at 10:20) by Erwan Jahier> *) +(** Time-stamp: <modified the 10/06/2008 (at 10:47) by Erwan Jahier> *) open Lxm @@ -565,6 +565,7 @@ and (node_check_do: t -> CompiledData.node_key -> Lxm.t -> SymbolTab.t -> let vi_eff = { var_name_eff = vi.it.var_name; var_nature_eff = vi.it.var_nature; + var_number_eff = vi.it.var_number; var_type_eff = t_eff; var_clock_eff = c_eff; } diff --git a/src/parserUtils.ml b/src/parserUtils.ml index c2d48e1d..8e230a56 100644 --- a/src/parserUtils.ml +++ b/src/parserUtils.ml @@ -1,4 +1,4 @@ -(** Time-stamp: <modified the 06/06/2008 (at 18:01) by Erwan Jahier> *) +(** Time-stamp: <modified the 10/06/2008 (at 10:20) by Erwan Jahier> *) @@ -310,15 +310,21 @@ let (clocked_ids_to_var_infos : var_nature -> (((Lxm.t list) * type_exp) list * SyntaxTreeCore.clock_exp) list -> var_info srcflagged list) = fun vnat vdefs -> + let i = ref 0 in let makevar lxm te ce = - Lxm.flagit - { - var_nature = vnat ; - var_name = (Lxm.id lxm) ; - var_type = te ; - var_clock = ce ; - } - lxm + let res = + Lxm.flagit + { + var_nature = vnat; + var_name = (Lxm.id lxm); + var_number = !i; + var_type = te; + var_clock = ce; + } + lxm + in + incr i; + res in flat_twice_flagged_list vdefs makevar @@ -338,20 +344,22 @@ let (treat_node_decl : bool -> Lxm.t -> static_param srcflagged list -> let rec (treat_vars : clocked_ids list -> var_nature -> var_info srcflagged list) = (* Procedure de traitement des in, out ou loc, paramétrée par la [var_nature] *) fun vdefs nat -> - match vdefs with - | [] -> [] - | (tids, ck)::reste -> - let put_var_in_table (lxm: Lxm.t) (ty: type_exp) = - let vinfo = { - var_nature = nat; var_name = (Lxm.id lxm); - var_type = ty; var_clock = ck - } + let i = ref 0 in + match vdefs with + | [] -> [] + | (tids, ck)::reste -> + let put_var_in_table (lxm: Lxm.t) (ty: type_exp) = + let vinfo = { + var_nature = nat; var_name = (Lxm.id lxm); + var_type = ty; var_clock = ck; var_number = !i + } + in + incr i; + add_info vtable "variable" lxm vinfo; + Lxm.flagit vinfo lxm in - add_info vtable "variable" lxm vinfo; - Lxm.flagit vinfo lxm - in - (flat_flagged_list tids put_var_in_table) - @ (treat_vars reste nat) + (flat_flagged_list tids put_var_in_table) + @ (treat_vars reste nat) in let invars = treat_vars indefs VarInput and outvars = treat_vars outdefs VarOutput diff --git a/src/predefEvalClock.ml b/src/predefEvalClock.ml index 511a9be2..de392113 100644 --- a/src/predefEvalClock.ml +++ b/src/predefEvalClock.ml @@ -1,30 +1,59 @@ -(** Time-stamp: <modified the 05/06/2008 (at 11:11) by Erwan Jahier> *) +(** Time-stamp: <modified the 09/06/2008 (at 12:25) by Erwan Jahier> *) open Predef open CompiledData +(* exported *) type clocker = CompiledData.clock_eff Predef.evaluator -let (aa_clocker: clocker) = +(* exported *) +exception EvalClock_error of string + + +(** A few useful clock profiles *) + +let (arity_zero_profile: clocker) = assert false +let (arity_one_profile: clocker) = function | [clk1] -> clk1 - | _ -> print_string "a good error msg"; assert false + | _ -> raise (EvalClock_error "a good error msg") -let (aaa_clocker: clocker) = +let (arity_two_profile: clocker) = function | [clk1; clk2] -> - if clk1 = clk2 then clk1 else (print_string "a good error msg"; assert false) + if clk1 = clk2 then clk1 else raise (EvalClock_error "a good error msg") | _ -> - print_string "a good error msg"; assert false + raise (EvalClock_error "a good error msg") - -(** A few useful clock profiles *) -(* let bb_profile = [(id "i", b)], [(id "o", b)] *) - - + +let if_clock_profile c = assert false +let fillred_clock_profile c = assert false +let map_clock_profile c = assert false +let boolred_clock_profile c = assert false (* This table contains the clock profile of predefined operators *) -let (f: op -> clocker) = - fun op -> - assert false +let (f: op -> Lxm.t -> CompiledData.static_arg_eff list -> clocker) = + fun op lxm sargs -> assert false +(* match op with *) +(* | TRUE_n | FALSE_n | ICONST_n _id | RCONST_n _id *) +(* -> arity_zero_profile *) +(* *) +(* | NOT_n | REAL2INT_n | INT2REAL_n | UMINUS_n | IUMINUS_n | RUMINUS_n *) +(* -> arity_one_profile *) +(* *) +(* *) +(* | IMPL_n | AND_n | OR_n | XOR_n *) +(* | NEQ_n | EQ_n | LT_n | LTE_n | GT_n | GTE_n *) +(* | MINUS_n | PLUS_n | TIMES_n | SLASH_n *) +(* | RMINUS_n | RPLUS_n | RTIMES_n | RSLASH_n *) +(* | DIV_n | MOD_n | IMINUS_n | IPLUS_n | ISLASH_n | ITIMES_n *) +(* -> arity_two_profile *) +(* *) +(* | IF_n -> if_clock_profile *) +(* | Red | Fill | FillRed -> fillred_clock_profile lxm sargs *) +(* | Map -> map_clock__profile lxm sargs *) +(* | BoolRed -> boolred_clock__profile lxm sargs *) +(* *) +(* | NOR_n | DIESE_n -> assert false *) + diff --git a/src/predefEvalClock.mli b/src/predefEvalClock.mli index 8e561823..cd2dabb5 100644 --- a/src/predefEvalClock.mli +++ b/src/predefEvalClock.mli @@ -1,4 +1,8 @@ -(** Time-stamp: <modified the 05/06/2008 (at 11:01) by Erwan Jahier> *) +(** Time-stamp: <modified the 09/06/2008 (at 12:31) by Erwan Jahier> *) type clocker = CompiledData.clock_eff Predef.evaluator +exception EvalClock_error of string + + +val f: Predef.op -> Lxm.t -> CompiledData.static_arg_eff list -> clocker diff --git a/src/predefEvalType.ml b/src/predefEvalType.ml index b95b27a2..6c9d127d 100644 --- a/src/predefEvalType.ml +++ b/src/predefEvalType.ml @@ -1,4 +1,4 @@ -(** Time-stamp: <modified the 09/06/2008 (at 10:09) by Erwan Jahier> *) +(** Time-stamp: <modified the 10/06/2008 (at 10:48) by Erwan Jahier> *) open Predef open SyntaxTreeCore @@ -198,10 +198,12 @@ let (make_node_exp_eff : op -> Lxm.t -> static_arg_eff list -> node_exp_eff) = (Ident.pack_name_of_string "Lustre") (Ident.of_string (Predef.op2string op)) in let (lti,lto) = op2profile op lxm sargs in + let i = ref 0 in let to_var_info_eff nature (id, te) = { var_name_eff = id; var_nature_eff = nature; + var_number_eff = !i; var_type_eff = te; var_clock_eff = BaseEff; } @@ -209,7 +211,7 @@ let (make_node_exp_eff : op -> Lxm.t -> static_arg_eff list -> node_exp_eff) = { node_key_eff = id,sargs ; inlist_eff = List.map (to_var_info_eff VarInput) lti; - outlist_eff = List.map (to_var_info_eff VarOutput) lto; + outlist_eff = (i:=0; List.map (to_var_info_eff VarOutput) lto); loclist_eff = None; def_eff = ExternEff; has_mem_eff = false; @@ -249,12 +251,11 @@ let (f : op -> Lxm.t -> CompiledData.static_arg_eff list -> typer) = fun t teff -> match teff with (* substitutes [t] in [teff] *) | Bool_type_eff -> Bool_type_eff - | Int_type_eff -> Int_type_eff + | Int_type_eff -> Int_type_eff | Real_type_eff -> Real_type_eff - | External_type_eff l -> External_type_eff l - | Enum_type_eff(l,el) -> Enum_type_eff(l,el) - | Array_type_eff(teff,i) -> - Array_type_eff(subst_type t teff, i) + | External_type_eff l -> External_type_eff l + | Enum_type_eff(l,el) -> Enum_type_eff(l,el) + | Array_type_eff(teff,i) -> Array_type_eff(subst_type t teff, i) | Struct_type_eff(l, fl) -> Struct_type_eff( l, diff --git a/src/predefEvalType.mli b/src/predefEvalType.mli index 707db070..668759ba 100644 --- a/src/predefEvalType.mli +++ b/src/predefEvalType.mli @@ -1,4 +1,4 @@ -(** Time-stamp: <modified the 09/06/2008 (at 10:05) by Erwan Jahier> *) +(** Time-stamp: <modified the 09/06/2008 (at 12:23) by Erwan Jahier> *) open CompiledData @@ -16,7 +16,7 @@ val arity_error : 'a list -> string -> 'b val f : Predef.op -> Lxm.t -> CompiledData.static_arg_eff list -> typer - +(* Does not work for NOR_n and DIESE_n! *) val make_node_exp_eff : Predef.op -> Lxm.t -> static_arg_eff list -> node_exp_eff diff --git a/src/syntaxTreeCore.ml b/src/syntaxTreeCore.ml index bb0e67c1..d5bd7a13 100644 --- a/src/syntaxTreeCore.ml +++ b/src/syntaxTreeCore.ml @@ -1,4 +1,4 @@ -(** Time-stamp: <modified the 05/06/2008 (at 16:09) by Erwan Jahier> *) +(** Time-stamp: <modified the 10/06/2008 (at 10:49) by Erwan Jahier> *) (** (Raw) Abstract syntax tree of source programs. *) @@ -48,6 +48,7 @@ and var_info_table = (Ident.t, var_info srcflagged) Hashtbl.t and var_info = { var_nature : var_nature; var_name : Ident.t; + var_number : int; var_type : type_exp; var_clock : clock_exp } diff --git a/src/test/should_fail/clock/clock.lus b/src/test/should_fail/clock/clock.lus index 86512949..9e9a0645 100644 --- a/src/test/should_fail/clock/clock.lus +++ b/src/test/should_fail/clock/clock.lus @@ -1,15 +1,15 @@ --- Entee sur entree +-- Entree sur entree: ok extern node clock2(u: bool; v: bool when u) returns (y: bool ); --- Sortie sur sortie +-- Sortie sur sortie: ok extern node clock3(u: bool) returns (x: bool; y: bool when x); --- Entree sur entree et sortie sur sortie +-- Entree sur entree et sortie sur sortie: ok extern node clock4(u: bool; v: bool when u) returns (x: bool; y: bool when x); --- Noeud principale. +-- Noeud principal. node clock(a: bool; b: bool) returns (c: bool; d: bool when c); var z: bool; @@ -18,7 +18,7 @@ var 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; - (z, x) = clock3(z); - (c, d) = clock4(a, b when a); + y = clock2(a, b when a) when x; -- ok + (z, x) = clock3(z);-- ok + (c, d) = clock4(a, b when c); -- a la place de clock4(a, b when c) tel diff --git a/src/test/should_fail/semantics/bad_call03.lus b/src/test/should_fail/semantics/bad_call03.lus index d4b59319..c8a5e8a9 100644 --- a/src/test/should_fail/semantics/bad_call03.lus +++ b/src/test/should_fail/semantics/bad_call03.lus @@ -11,5 +11,5 @@ node bad_call03(a,b:int^3; c,d:real^3) returns (x : int^3; y:real^3); let x = toto(a,b); - y = titi(c,d); + y = toto(c,d); tel diff --git a/src/test/test.res.exp b/src/test/test.res.exp index dc5fbb46..6ae23879 100644 --- a/src/test/test.res.exp +++ b/src/test/test.res.exp @@ -3835,6 +3835,38 @@ let tel -- end of node call07__call07 +---------------------------------------------------------------------- +====> ../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); + +extern node clock__clock4( + u:bool; + v:bool when u) +returns ( + x:bool; + y:bool when x); + +extern node clock__clock5( + x:bool; + y:bool when x; + z:bool when y when x) +returns ( + a:bool); +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 when z; + 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); + ---------------------------------------------------------------------- ====> ../lus2lic -vl 2 --compile-all-items should_work/demo/Gyroscope2.lus Opening file /home/jahier/lus2lic/src/test/should_work/demo/Gyroscope2.lus @@ -9313,7 +9345,7 @@ var let y = clock__clock2(a, b when a) when x; (z, x) = clock__clock3(z); - (c, d) = clock__clock4(a, b when a); + (c, d) = clock__clock4(a, b when c); tel -- end of node clock__clock @@ -9405,7 +9437,7 @@ returns ( y:real^3); let x = bad_call03__toto(a, b); - y = bad_call03__titi(c, d); + y = bad_call03__toto(c, d); tel -- end of node bad_call03__bad_call03 -- GitLab