good clocks in signatures
This commit is contained in:
parent
40fcb4d73e
commit
9a17648516
13 changed files with 171 additions and 88 deletions
|
@ -115,11 +115,11 @@ let rec tuple ck = function
|
|||
*)
|
||||
(*
|
||||
let max ck_1 ck_2 = match ck_repr ck_1, ck_reprck_2 with
|
||||
|
|
||||
|
|
||||
|
||||
let rec optim_base_ck base_ck ct = match ct with
|
||||
| Ck ck ->
|
||||
| Cprod c_l ->
|
||||
| Ck ck ->
|
||||
| Cprod c_l ->
|
||||
*)
|
||||
|
||||
|
||||
|
|
|
@ -93,14 +93,14 @@ module S = Set.Make (struct type t = string
|
|||
module UniqueNames =
|
||||
struct
|
||||
open Names
|
||||
let used_names = ref (ref S.empty) (** Used strings in the current node *)
|
||||
let used_names = ref (ref NamesSet.empty) (** Used strings in the current node *)
|
||||
let env = ref Env.empty (** Map idents to their string *)
|
||||
let (node_env : S.t ref QualEnv.t ref) = ref QualEnv.empty
|
||||
let (node_env : NamesSet.t ref QualEnv.t ref) = ref QualEnv.empty
|
||||
|
||||
(** This function should be called every time we enter a node *)
|
||||
let enter_node n =
|
||||
(if not (QualEnv.mem n !node_env)
|
||||
then node_env := QualEnv.add n (ref S.empty) !node_env);
|
||||
then node_env := QualEnv.add n (ref NamesSet.empty) !node_env);
|
||||
used_names := QualEnv.find n !node_env
|
||||
|
||||
(** @return a unique string for each identifier. Idents corresponding
|
||||
|
@ -113,11 +113,11 @@ struct
|
|||
s ^ "_" ^ (string_of_int !num) in
|
||||
let rec fresh_string base =
|
||||
let fs = fresh base in
|
||||
if S.mem fs !(!used_names) then fresh_string base else fs in
|
||||
if NamesSet.mem fs !(!used_names) then fresh_string base else fs in
|
||||
if not (Env.mem n !env) then
|
||||
(let s = n.source in
|
||||
let s = if S.mem s !(!used_names) then fresh_string s else s in
|
||||
!used_names := S.add s !(!used_names);
|
||||
let s = if NamesSet.mem s !(!used_names) then fresh_string s else s in
|
||||
!used_names := NamesSet.add s !(!used_names);
|
||||
env := Env.add n s !env)
|
||||
|
||||
let name id =
|
||||
|
|
|
@ -42,9 +42,9 @@ module QualEnv = struct
|
|||
let append env' env = fold (fun key v env -> add key v env) env' env
|
||||
end
|
||||
|
||||
module NamesSet = Set.Make (struct type t = string let compare = compare end)
|
||||
module QualSet = Set.Make (struct type t = qualname let compare = compare end)
|
||||
module ModulSet = Set.Make (struct type t = modul let compare = compare end)
|
||||
module S = Set.Make (struct type t = string let compare = compare end)
|
||||
|
||||
|
||||
let shortname { name = n; } = n
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
(* global data in the symbol tables *)
|
||||
open Names
|
||||
open Types
|
||||
open Location
|
||||
|
||||
(** Warning: Whenever these types are modified,
|
||||
interface_format_version should be incremented. *)
|
||||
|
@ -40,7 +41,8 @@ type node = {
|
|||
node_outputs : arg list;
|
||||
node_stateful : bool;
|
||||
node_params : param list;
|
||||
node_params_constraints : size_constraint list }
|
||||
node_params_constraints : size_constraint list;
|
||||
node_loc : location}
|
||||
|
||||
type field = { f_name : field_name; f_type : ty }
|
||||
type structure = field list
|
||||
|
@ -53,6 +55,67 @@ type type_def =
|
|||
|
||||
type const_def = { c_type : ty; c_value : static_exp }
|
||||
|
||||
|
||||
(** { 3 Signature helper functions } *)
|
||||
|
||||
type error =
|
||||
| Eckvar_unbound of name option * name
|
||||
| Eckvar_unbound_input of name option * name
|
||||
| Eckvar_unbound_ouput of name option * name
|
||||
|
||||
exception SignatureError of error
|
||||
|
||||
let message loc e = begin match e with
|
||||
| Eckvar_unbound_input(var_name,ck_name) ->
|
||||
let a,name = match var_name with None -> "a","" | Some n -> "the"," "^n in
|
||||
Format.eprintf "%aThe variable %s is unbound.@\n
|
||||
Note that %s sampled input%s should come together with its clock.@."
|
||||
print_location loc
|
||||
ck_name a name
|
||||
| Eckvar_unbound_ouput (var_name,ck_name) ->
|
||||
let a,name = match var_name with None -> "a","" | Some n -> "the"," "^n in
|
||||
Format.eprintf "%aThe variable %s is unbound.@\n
|
||||
Note that %s sampled ouput%s should be returned with its clock.@."
|
||||
print_location loc
|
||||
ck_name a name
|
||||
| Eckvar_unbound(var_name,ck_name) ->
|
||||
Format.eprintf "%aThe variable %s is unbound.@." print_location loc ck_name
|
||||
end;
|
||||
raise Errors.Error
|
||||
|
||||
|
||||
(** @raise Errors.Error after printing the error *)
|
||||
let check_signature s =
|
||||
(* a simple env of defined names will be used, represented by a Set *)
|
||||
let rec append env sa_l = match sa_l with
|
||||
| [] -> env
|
||||
| sa::sa_l -> match sa.a_name with
|
||||
| None -> append env sa_l
|
||||
| Some x -> append (NamesSet.add x env) sa_l
|
||||
in
|
||||
(* the clock of [arg] is correct if all the vars used are in [env] *)
|
||||
let check env arg =
|
||||
let n = arg.a_name in
|
||||
let rec f = function
|
||||
| Cbase -> ()
|
||||
| Con(ck,_,x) ->
|
||||
if not (NamesSet.mem x env)
|
||||
then raise (SignatureError (Eckvar_unbound (n,x)));
|
||||
f ck
|
||||
in
|
||||
f arg.a_clock
|
||||
in
|
||||
(*initial env with only the inputs*)
|
||||
let env = append NamesSet.empty s.node_inputs in
|
||||
(try List.iter (check env) s.node_inputs
|
||||
with SignatureError (Eckvar_unbound (x,c)) ->
|
||||
message s.node_loc (Eckvar_unbound_input (x,c)));
|
||||
let env = append env s.node_outputs in
|
||||
try List.iter (check env) s.node_outputs
|
||||
with SignatureError (Eckvar_unbound (x,c)) ->
|
||||
message s.node_loc (Eckvar_unbound_ouput (x,c))
|
||||
|
||||
|
||||
let rec ck_to_sck ck =
|
||||
let ck = Clocks.ck_repr ck in
|
||||
match ck with
|
||||
|
@ -74,12 +137,13 @@ let mk_field n ty = { f_name = n; f_type = ty }
|
|||
let mk_const_def ty value =
|
||||
{ c_type = ty; c_value = value }
|
||||
|
||||
let mk_node ?(constraints = []) ins outs stateful params =
|
||||
let mk_node ?(constraints = []) loc ins outs stateful params =
|
||||
{ node_inputs = ins;
|
||||
node_outputs = outs;
|
||||
node_stateful = stateful;
|
||||
node_params = params;
|
||||
node_params_constraints = constraints }
|
||||
node_params_constraints = constraints;
|
||||
node_loc = loc}
|
||||
|
||||
let rec field_assoc f = function
|
||||
| [] -> raise Not_found
|
||||
|
|
|
@ -272,10 +272,10 @@ let add_distinct_qualset n acc =
|
|||
QualSet.add n acc
|
||||
|
||||
let add_distinct_S n acc =
|
||||
if S.mem n acc then
|
||||
if NamesSet.mem n acc then
|
||||
error (Ealready_defined n)
|
||||
else
|
||||
S.add n acc
|
||||
NamesSet.add n acc
|
||||
|
||||
(** Add two sets of names provided they are distinct *)
|
||||
let add env1 env2 =
|
||||
|
@ -337,23 +337,23 @@ let last = function | Var -> false | Last _ -> true
|
|||
of field name, exp.*)
|
||||
let check_field_unicity l =
|
||||
let add_field acc (f,e) =
|
||||
if S.mem (shortname f) acc then
|
||||
if NamesSet.mem (shortname f) acc then
|
||||
message e.e_loc (Ealready_defined (fullname f))
|
||||
else
|
||||
S.add (shortname f) acc
|
||||
NamesSet.add (shortname f) acc
|
||||
in
|
||||
ignore (List.fold_left add_field S.empty l)
|
||||
ignore (List.fold_left add_field NamesSet.empty l)
|
||||
|
||||
(** Checks that a field is not defined twice in a list
|
||||
of field name, exp.*)
|
||||
let check_static_field_unicity l =
|
||||
let add_field acc (f,se) =
|
||||
if S.mem (shortname f) acc then
|
||||
if NamesSet.mem (shortname f) acc then
|
||||
message se.se_loc (Ealready_defined (fullname f))
|
||||
else
|
||||
S.add (shortname f) acc
|
||||
NamesSet.add (shortname f) acc
|
||||
in
|
||||
ignore (List.fold_left add_field S.empty l)
|
||||
ignore (List.fold_left add_field NamesSet.empty l)
|
||||
|
||||
(** @return the qualified name and list of fields of
|
||||
the type with name [n].
|
||||
|
@ -917,10 +917,10 @@ and typing_automaton_handlers const_env h acc state_handlers =
|
|||
(* checks unicity of states *)
|
||||
let addname acc { s_state = n } =
|
||||
add_distinct_S n acc in
|
||||
let states = List.fold_left addname S.empty state_handlers in
|
||||
let states = List.fold_left addname NamesSet.empty state_handlers in
|
||||
|
||||
let escape h ({ e_cond = e; e_next_state = n } as esc) =
|
||||
if not (S.mem n states) then error (Eundefined(n));
|
||||
if not (NamesSet.mem n states) then error (Eundefined(n));
|
||||
let typed_e = expect const_env h (Tid Initial.pbool) e in
|
||||
{ esc with e_cond = typed_e } in
|
||||
|
||||
|
|
|
@ -98,3 +98,17 @@ let vars_pat pat =
|
|||
let rec vd_mem n = function
|
||||
| [] -> false
|
||||
| vd::l -> vd.v_ident = n or (vd_mem n l)
|
||||
|
||||
let args_of_var_decs =
|
||||
(* before the clocking the clock is wrong in the signature *)
|
||||
List.map (fun vd -> Signature.mk_arg (Some (Idents.source_name vd.v_ident))
|
||||
vd.v_type Signature.Cbase)
|
||||
|
||||
let signature_of_node n =
|
||||
{ node_inputs = args_of_var_decs n.n_input;
|
||||
node_outputs = args_of_var_decs n.n_output;
|
||||
node_stateful = n.n_stateful;
|
||||
node_params = n.n_params;
|
||||
node_params_constraints = n.n_params_constraints;
|
||||
node_loc = n.n_loc }
|
||||
|
||||
|
|
|
@ -279,7 +279,7 @@ ck_annot:
|
|||
| COLONCOLON ck=ck
|
||||
| ON ck=on_ck { Some ck }
|
||||
|
||||
ck:
|
||||
ck:
|
||||
| DOT { Cbase }
|
||||
| ck=on_ck { ck }
|
||||
|
||||
|
|
|
@ -103,7 +103,7 @@ let qualify_field = _qualify_with_error "field" qualify_field check_field
|
|||
(** Qualify a var name as a constant variable,
|
||||
if not in local_const or global_const then raise Not_found *)
|
||||
let qualify_var_as_const local_const c =
|
||||
if S.mem c local_const
|
||||
if NamesSet.mem c local_const
|
||||
then local_qn c
|
||||
else qualify_const c
|
||||
|
||||
|
@ -165,12 +165,12 @@ let mk_signature name ins outs stateful params loc =
|
|||
(** Function to build the defined static parameters set *)
|
||||
let build_const loc vd_list =
|
||||
let _add_const_var loc c local_const =
|
||||
if S.mem c local_const
|
||||
if NamesSet.mem c local_const
|
||||
then Error.message loc (Error.Econst_variable_already_defined c)
|
||||
else S.add c local_const in
|
||||
else NamesSet.add c local_const in
|
||||
let build local_const vd =
|
||||
_add_const_var loc vd.v_name local_const in
|
||||
List.fold_left build S.empty vd_list
|
||||
List.fold_left build NamesSet.empty vd_list
|
||||
|
||||
|
||||
(** { 3 Translate the AST into Heptagon. } *)
|
||||
|
@ -410,39 +410,34 @@ let params_of_var_decs =
|
|||
vd.v_name
|
||||
(translate_type vd.v_loc vd.v_type))
|
||||
|
||||
let args_of_var_decs =
|
||||
(* before the clocking the clock is wrong in the signature *)
|
||||
List.map (fun vd -> Signature.mk_arg (Some (Idents.source_name vd.Heptagon.v_ident))
|
||||
vd.Heptagon.v_type Signature.Cbase)
|
||||
|
||||
|
||||
let translate_node node =
|
||||
let n = current_qual node.n_name in
|
||||
Idents.enter_node n;
|
||||
let params = params_of_var_decs node.n_params in
|
||||
let input_env = Rename.append Rename.empty (node.n_input) in
|
||||
(* inputs should refer only to inputs *)
|
||||
(* inputs should refer only to inputs *)
|
||||
let inputs = translate_vd_list input_env node.n_input in
|
||||
(* Inputs and outputs define the initial local env *)
|
||||
(* Inputs and outputs define the initial local env *)
|
||||
let env0 = Rename.append input_env node.n_output in
|
||||
let outputs = translate_vd_list env0 node.n_output in
|
||||
let b, env = translate_block env0 node.n_block in
|
||||
(* the env of the block is used in the contract translation *)
|
||||
(* the env of the block is used in the contract translation *)
|
||||
let contract = Misc.optional (translate_contract env) node.n_contract in
|
||||
(* add the node signature to the environment *)
|
||||
let i = args_of_var_decs inputs in
|
||||
let o = args_of_var_decs outputs in
|
||||
let p = params_of_var_decs node.n_params in
|
||||
add_value n (Signature.mk_node i o node.n_stateful p);
|
||||
{ Heptagon.n_name = n;
|
||||
Heptagon.n_stateful = node.n_stateful;
|
||||
Heptagon.n_input = inputs;
|
||||
Heptagon.n_output = outputs;
|
||||
Heptagon.n_contract = contract;
|
||||
Heptagon.n_block = b;
|
||||
Heptagon.n_loc = node.n_loc;
|
||||
Heptagon.n_params = params;
|
||||
Heptagon.n_params_constraints = []; }
|
||||
let node = { Heptagon.n_name = n;
|
||||
Heptagon.n_stateful = node.n_stateful;
|
||||
Heptagon.n_input = inputs;
|
||||
Heptagon.n_output = outputs;
|
||||
Heptagon.n_contract = contract;
|
||||
Heptagon.n_block = b;
|
||||
Heptagon.n_loc = node.n_loc;
|
||||
Heptagon.n_params = params;
|
||||
Heptagon.n_params_constraints = []; }
|
||||
in
|
||||
add_value n (Hept_utils.signature_of_node node);
|
||||
node
|
||||
|
||||
|
||||
let translate_typedec ty =
|
||||
let n = current_qual ty.t_name in
|
||||
|
@ -496,33 +491,24 @@ let translate_program p =
|
|||
Heptagon.p_opened = p.p_opened;
|
||||
Heptagon.p_desc = desc; }
|
||||
|
||||
|
||||
let translate_signature s =
|
||||
(* helper functions, having [env] as being the list of existing var names *)
|
||||
let rec append env sa_l = match sa_l with
|
||||
| [] -> env
|
||||
| sa::sa_l -> match sa.a_name with
|
||||
| None -> append env sa_l
|
||||
| Some x -> append (x::env) sa_l
|
||||
and translate_some_clock loc env ck = match ck with
|
||||
let rec translate_some_clock ck = match ck with
|
||||
| None -> Signature.Cbase
|
||||
| Some ck -> translate_clock loc env ck
|
||||
and translate_clock loc env ck = match ck with
|
||||
| Some ck -> translate_clock ck
|
||||
and translate_clock ck = match ck with
|
||||
| Cbase -> Signature.Cbase
|
||||
| Con(ck,c,x) ->
|
||||
if not (List.mem x env)
|
||||
then message loc (Evar_unbound x)
|
||||
else Signature.Con(translate_clock loc env ck, qualify_constrs c, x)
|
||||
and translate_arg env a =
|
||||
Signature.mk_arg a.a_name (translate_type s.sig_loc a.a_type)
|
||||
(translate_some_clock s.sig_loc env a.a_clock)
|
||||
| Con(ck,c,x) -> Signature.Con(translate_clock ck, qualify_constrs c, x)
|
||||
and translate_arg a = Signature.mk_arg a.a_name (translate_type s.sig_loc a.a_type)
|
||||
(translate_some_clock a.a_clock)
|
||||
in
|
||||
let n = current_qual s.sig_name in
|
||||
let env = append [] s.sig_inputs in
|
||||
let i = List.map (translate_arg env) s.sig_inputs in
|
||||
let env = append env s.sig_outputs in
|
||||
let o = List.map (translate_arg env) s.sig_outputs in
|
||||
let i = List.map translate_arg s.sig_inputs in
|
||||
let o = List.map translate_arg s.sig_outputs in
|
||||
let p = params_of_var_decs s.sig_params in
|
||||
add_value n (Signature.mk_node i o s.sig_stateful p);
|
||||
let sig_node = Signature.mk_node s.sig_loc i o s.sig_stateful p in
|
||||
Signature.check_signature sig_node;
|
||||
add_value n sig_node;
|
||||
mk_signature n i o s.sig_stateful p s.sig_loc
|
||||
|
||||
|
||||
|
|
|
@ -72,13 +72,13 @@ let const_dec funs local_const cd =
|
|||
let program p =
|
||||
let funs = { Hept_parsetree_mapfold.defaults
|
||||
with node_dec = node; exp = exp; static_exp = static_exp; const_dec = const_dec } in
|
||||
let p, _ = Hept_parsetree_mapfold.program_it funs Names.S.empty p in
|
||||
let p, _ = Hept_parsetree_mapfold.program_it funs Names.NamesSet.empty p in
|
||||
p
|
||||
|
||||
(* (* TODO mapfold on interface *)
|
||||
let interface i =
|
||||
let funs = { Hept_parsetree_mapfold.defaults
|
||||
with node_dec = node; exp = exp; const_dec = const_dec } in
|
||||
let i, _ = Hept_parsetree_mapfold.interface_it funs Names.S.empty i in
|
||||
let i, _ = Hept_parsetree_mapfold.interface_it funs Names.NamesSet.empty i in
|
||||
i
|
||||
*)
|
||||
|
|
|
@ -117,11 +117,11 @@ let node_dec funs (env, newvars, newequs) nd =
|
|||
let program p =
|
||||
let env n =
|
||||
let d =
|
||||
List.find
|
||||
(function
|
||||
| Pnode nd -> nd.n_name = n
|
||||
| _ -> false)
|
||||
p.p_desc in
|
||||
List.find
|
||||
(function
|
||||
| Pnode nd -> nd.n_name = n
|
||||
| _ -> false)
|
||||
p.p_desc in
|
||||
match d with
|
||||
| Pnode nd -> nd
|
||||
| _ -> assert false in
|
||||
|
|
|
@ -133,7 +133,7 @@ let add_to_locals vd_env locals h =
|
|||
let add_one n nn (locals,vd_env) =
|
||||
let orig_vd = Idents.Env.find n vd_env in
|
||||
let vd_nn = mk_var_dec nn orig_vd.v_type in
|
||||
vd_nn::locals, Idents.Env.add vd_nn.v_ident vd_nn vd_env
|
||||
vd_nn::locals, Idents.Env.add vd_nn.v_ident vd_nn vd_env
|
||||
in
|
||||
fold add_one h (locals, vd_env)
|
||||
end
|
||||
|
@ -197,7 +197,7 @@ let eqdesc funs (vd_env,env,h) eqd = match eqd with
|
|||
let equs = (mk_equation (Eblock b_eq))::equs in
|
||||
((constr,h)::c_h_l, locals, equs, vd_env)
|
||||
in
|
||||
|
||||
|
||||
let (c_h_l, locals, equs, vd_env) =
|
||||
List.fold_left switch_handler ([], locals, equs, vd_env) sw_h_l
|
||||
in
|
||||
|
@ -212,7 +212,7 @@ let eqdesc funs (vd_env,env,h) eqd = match eqd with
|
|||
let equs =
|
||||
Idents.Env.fold (fun n ty equs -> new_merge n ty equs) defnames equs
|
||||
in
|
||||
|
||||
|
||||
(* return the transformation in a block *)
|
||||
let b = mk_block ~defnames:defnames ~locals:locals equs in
|
||||
Eblock b, (vd_env,env,h)
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
Idem for e_ct : if explicit, it represents a clock annotation.
|
||||
Unification is done on this mutable fields.
|
||||
e_base_ck is set according to node signatures.
|
||||
|
||||
|
||||
*)
|
||||
|
||||
open Misc
|
||||
|
@ -121,7 +121,7 @@ let typing_app h base pat op w_list = match op with
|
|||
let typing_eq h { eq_lhs = pat; eq_rhs = e } =
|
||||
(* typing the expression *)
|
||||
let ct,base = match e.e_desc with
|
||||
| Eextvalue w
|
||||
| Eextvalue w
|
||||
| Efby (_, w) ->
|
||||
let ck = typing_extvalue h w in
|
||||
Ck ck, ck
|
||||
|
@ -138,7 +138,7 @@ let typing_eq h { eq_lhs = pat; eq_rhs = e } =
|
|||
| None -> fresh_clock ()
|
||||
| Some(reset) -> ck_of_name h reset in
|
||||
let ct = typing_app h ck_r pat op args in
|
||||
ct, ck_r
|
||||
ct, ck_r
|
||||
| Eiterator (_, _, _, pargs, args, r) ->
|
||||
(* Typed exactly as a fun or a node... *)
|
||||
let ck_r = match r with
|
||||
|
@ -195,12 +195,18 @@ let typing_node node =
|
|||
let h = append_env h node.n_output in
|
||||
let h = typing_contract h node.n_contract in
|
||||
let h = append_env h node.n_local in
|
||||
(typing_eqs h node.n_equs;
|
||||
typing_eqs h node.n_equs;
|
||||
(*update clock info in variables descriptions *)
|
||||
let set_clock vd = { vd with v_clock = ck_repr (Env.find vd.v_ident h) } in
|
||||
{ node with n_input = List.map set_clock node.n_input;
|
||||
n_output = List.map set_clock node.n_output;
|
||||
n_local = List.map set_clock node.n_local })
|
||||
let node = { node with n_input = List.map set_clock node.n_input;
|
||||
n_output = List.map set_clock node.n_output;
|
||||
n_local = List.map set_clock node.n_local }
|
||||
in
|
||||
(* check signature causality and update it in the global env *)
|
||||
let sign = Mls_utils.signature_of_node node in
|
||||
Signature.check_signature sign;
|
||||
Modules.replace_value node.n_name sign;
|
||||
node
|
||||
|
||||
let program p =
|
||||
let program_desc pd = match pd with
|
||||
|
|
|
@ -196,4 +196,17 @@ let ident_list_of_pat pat =
|
|||
| Etuplepat [] -> acc
|
||||
| Etuplepat (pat::pat_l) -> f (f acc pat) (Etuplepat pat_l)
|
||||
in
|
||||
f [] pat
|
||||
f [] pat
|
||||
|
||||
|
||||
let args_of_var_decs =
|
||||
List.map (fun vd -> Signature.mk_arg (Some (Idents.source_name vd.v_ident))
|
||||
vd.v_type (Signature.ck_to_sck vd.v_clock))
|
||||
|
||||
let signature_of_node n =
|
||||
{ node_inputs = args_of_var_decs n.n_input;
|
||||
node_outputs = args_of_var_decs n.n_output;
|
||||
node_stateful = n.n_stateful;
|
||||
node_params = n.n_params;
|
||||
node_params_constraints = n.n_params_constraints;
|
||||
node_loc = n.n_loc }
|
||||
|
|
Loading…
Reference in a new issue