Newer
Older
(** Time-stamp: <modified the 26/05/2009 (at 15:27) by Erwan Jahier> *)
open Predef
open SyntaxTree
Erwan Jahier
committed
open Ident
(******************************************************************************)
exception GetEffType_error of string
(* exported *)
let rec (typ:Eff.id_solver -> SyntaxTreeCore.type_exp -> Eff.type_) =
fun env texp ->
try (
match texp.it with
| Bool_type_exp -> Bool_type_eff
| Int_type_exp -> Int_type_eff
| Real_type_exp -> Real_type_eff
| Named_type_exp s -> env.id2type s texp.src
| Array_type_exp (elt_texp, szexp) ->
let elt_teff = typ env elt_texp in
try
let sz = EvalConst.eval_array_size env szexp in
Array_type_eff (elt_teff, sz)
with EvalConst.EvalArray_error msg -> raise(GetEffType_error msg)
)
with GetEffType_error msg ->
raise (Compile_error(texp.src, "can't eval type: "^msg))
let (add_pack_name : id_solver -> Lxm.t -> Ident.idref -> Ident.idref) =
fun id_solver lxm cc ->
try
match Ident.pack_of_idref cc with
| Some _ -> cc
| None ->
let id = Ident.of_idref cc in
let pn =
SymbolTab.find_pack_of_const id_solver.symbols id lxm
in
Ident.make_idref pn id
with _ -> cc (* raise en error? *)
(* exported *)
let rec (clock : Eff.id_solver -> SyntaxTreeCore.var_info -> Eff.id_clock)=
fun id_solver v ->
match v.var_clock with
| Base -> v.var_name, BaseEff
| NamedClock({ it=(cc,cv) ; src=lxm }) ->
let cc = add_pack_name id_solver lxm cc in
let vi = id_solver.id2var (Ident.to_idref cv) lxm in
let id, clk = vi.var_clock_eff in
v.var_name, On((cc,cv), clk)
(******************************************************************************)
(* Checks that the left part has the same type as the right one. *)
and (type_check_equation: Eff.id_solver -> Lxm.t -> Eff.left list ->
Eff.val_exp -> unit) =
fun id_solver lxm lpl_eff ve_eff ->
let lpl_teff = List.map Eff.type_of_left lpl_eff in
let ve_eff, right_part = EvalType.f id_solver ve_eff in
if (List.length lpl_teff <> List.length right_part) then
"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 (in " ^
(String.concat ","
(List.map LicDump.string_of_leff lpl_eff)) ^ " = " ^
(LicDump.string_of_val_exp_eff ve_eff) ^
")\n"
))
List.iter2
(fun le re ->
if le <> re then
let msg = "type mismatch: \n***\t'"
Erwan Jahier
committed
^ (LicDump.string_of_type_eff4msg le) ^
"' (left-hand-side) \n*** is not compatible with \n***\t'"
Erwan Jahier
committed
^ (LicDump.string_of_type_eff4msg re) ^ "' (right-hand-side)"
(* Checks that the left part has the same clock as the right one. *)
and (clock_check_equation:Eff.id_solver -> Lxm.t -> UnifyClock.subst ->
Eff.left list -> Eff.val_exp -> unit) =
fun id_solver lxm s lpl_eff ve_eff ->
let clk_list = List.map Eff.clock_of_left lpl_eff in
let _, right_part_clks, s = EvalClock.f lxm id_solver s ve_eff clk_list in
EvalClock.check_res lxm s lpl_eff right_part_clks
(******************************************************************************)
(* exported *)
let (dump_polymorphic_nodes : Eff.type_ -> unit) =
fun t ->
let nodes =
Polymorphism.unstack_polymorphic_nodes StructArrayExpand.node t
in
List.iter
(fun (id_solver,nenv,node) ->
let node =
if !Global.inline_iterator
then Inline.iterators nenv id_solver node
else node
in
let str = LicDump.node_of_node_exp_eff node in
output_string !Global.oc str
)
nodes;
Polymorphism.reset_type ()
(******************************************************************************)
let (get_static_params_from_idref : SymbolTab.t -> Lxm.t -> Ident.idref ->
static_param srcflagged list) =
fun symbols lxm idref ->
try
match SymbolTab.find_node symbols (Ident.name_of_idref idref) lxm with
| SymbolTab.Local ni -> ni.it.static_params
| SymbolTab.Imported(imported_node, params) -> params
with _ ->
(* can occur for static node parameters, which cannot
themselves have static parameters. A better solution ougth
to be to add node static parameters in the SymbolTab.t
however (in Lazycompiler.node_check_do most probably). *)
[]
(* exported *)
let rec (node : Eff.id_solver -> SyntaxTreeCore.node_exp srcflagged ->
Eff.node_exp) =
fun id_solver { src = lxm; it=(idref, static_args) } ->
let static_params = get_static_params_from_idref id_solver.symbols lxm idref in
let static_args_eff =
let sp_l = List.length static_params
and sa_l = List.length static_args in
if (sp_l <> sa_l) then
let msg = "Bad number of (static) arguments: " ^
(string_of_int sp_l) ^ " expected, and " ^
(string_of_int sa_l) ^ " provided."
in
raise (Compile_error(lxm, msg))
else
List.map2 (check_static_arg id_solver)
static_params
static_args
in
id_solver.id2node idref static_args_eff lxm
(** [check_static_arg this pn id sa (symbols, acc)] compile a static arg
SyntaxTreeCore.static_param srcflagged ->
SyntaxTreeCore.static_arg srcflagged ->
fun node_id_solver sp sa ->
let rec (eff_type_and_type_exp_are_equal:
Eff.type_ -> SyntaxTreeCore.type_exp_core -> bool) =
fun teff texp ->
match teff, texp with
| Bool_type_eff, Bool_type_exp
| Real_type_eff, Real_type_exp
| Int_type_eff, Int_type_exp -> true
| Abstract_type_eff(l,_), Named_type_exp idref ->
l = Ident.long_of_idref idref
| External_type_eff(l), Named_type_exp idref ->
(* This seems a little bit wrong *)
l = Ident.long_of_idref idref
| _ , Named_type_exp idref -> true
| Array_type_eff(teff_ext,i),Array_type_exp(texp,j) ->
i=(EvalConst.eval_array_size node_id_solver j)
& (eff_type_and_type_exp_are_equal teff texp.it)
| Any,_ -> assert false (* for TTB, polymorphism is not supported *)
| Overload, _ -> assert false (* ditto *)
| Struct_type_eff(_),_ -> assert false (* impossible *)
| Enum_type_eff(_),_ -> assert false (* ditto *)
| _ -> false
in
let check_type_arg type_eff type_exp =
if not (eff_type_and_type_exp_are_equal type_eff type_exp.it) then
let msg = "Bad (static) type argument: '" ^
Erwan Jahier
committed
(LicDump.string_of_type_eff4msg type_eff) ^
"' and '" ^ (string_of_type_exp type_exp) ^ "' differs."
in
raise (Compile_error(type_exp.src, msg))
else ()
in
let type_check_var_info acc vi_eff vi_exp = acc &
eff_type_and_type_exp_are_equal vi_eff.var_type_eff vi_exp.it.var_type.it
in
let type_check_var_info_list vil_eff vil_exp =
List.fold_left2 type_check_var_info true vil_eff vil_exp
in
let check_node_arg neff vii vio =
let str = "Bad (static) node argument: " in
if (List.length neff.inlist_eff) <> (List.length vii) then
raise (Compile_error(sa.src, str ^ "arity error (inputs)."))
else if (List.length neff.outlist_eff) <> (List.length vio) then
raise (Compile_error(sa.src, str ^ "arity error (outputs)."))
else if not (type_check_var_info_list neff.inlist_eff vii) then
raise (Compile_error(sa.src, str ^ "wrong input type profile."))
else if not (type_check_var_info_list neff.outlist_eff vio) then
raise (Compile_error(sa.src, str ^ "wrong output type profile."))
Erwan Jahier
committed
else (neff.inlist_eff, neff.outlist_eff)
let sa_eff =
match sa.it, sp.it with
| StaticArgIdent idref, StaticParamConst(id, type_exp) ->
let t_ceff = type_of_const ceff in
check_type_arg t_ceff type_exp;
ConstStaticArgEff (id, ceff)
| StaticArgIdent idref, StaticParamType(id) ->
let teff = node_id_solver.id2type idref sa.src in
TypeStaticArgEff (id, teff)
| StaticArgConst ce, StaticParamConst(id, type_exp) -> (
let t_ceff = type_of_const (List.hd ceff) in
check_type_arg t_ceff type_exp;
match ceff with
| [ceff] -> ConstStaticArgEff (id,ceff)
| _ -> assert false (* should not occur *)
)
| StaticArgType te, StaticParamType id ->
let teff = typ node_id_solver te in
TypeStaticArgEff (id, teff)
Erwan Jahier
committed
| StaticArgIdent idref, StaticParamNode(id, vii, vio,_) ->
(* idref is an alias, hence it cannot have static argument *)
let sargs = [] in
let neff = node_id_solver.id2node idref sargs sa.src in
let (inlist, outlist) = check_node_arg neff vii vio in
let neff = fst neff.node_key_eff in
NodeStaticArgEff (id, (neff, inlist, outlist))
| StaticArgNode(CALL_n ne), StaticParamNode(id,vii,vio,_) ->
Erwan Jahier
committed
let (inlist, outlist) = check_node_arg neff vii vio in
let neff = fst neff.node_key_eff in
NodeStaticArgEff (id, (neff, inlist, outlist))
| StaticArgNode(Predef_n (op,sargs)), StaticParamNode(id,vii,vio,_) ->
let sargs_eff =
translate_predef_static_args node_id_solver sargs sa.src
in
let opeff = PredefEvalType.make_node_exp_eff None op sa.src sargs_eff in
Erwan Jahier
committed
let (inlist, outlist) = check_node_arg opeff vii vio in
let opeff = fst opeff.node_key_eff in
NodeStaticArgEff (id, (opeff, inlist, outlist))
| StaticArgNode(
(MERGE_n _|ARRAY_SLICE_n _|ARRAY_ACCES_n _|STRUCT_ACCESS_n _|IDENT_n _
|ARRAY_n|HAT_n|CONCAT_n|WITH_n(_)|TUPLE_n|WHEN_n(_)|CURRENT_n|FBY_n
|ARROW_n|PRE_n)), _ -> assert false
| StaticArgType _, StaticParamNode(id,_,_,_)
| StaticArgType _, StaticParamConst(id,_)
| 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:Eff.id_solver -> SyntaxTreeCore.eq_info srcflagged -> Eff.eq_info srcflagged) =
fun id_solver eq_info ->
let (lpl, ve) = eq_info.it in
let lpl_eff = List.map (translate_left_part id_solver) lpl
and clk_subst,ve_eff = translate_val_exp id_solver UnifyClock.empty_subst ve
type_check_equation id_solver eq_info.src lpl_eff ve_eff;
clock_check_equation id_solver eq_info.src clk_subst lpl_eff ve_eff;
flagit (lpl_eff, ve_eff) eq_info.src
and (translate_left_part : id_solver -> SyntaxTreeCore.left_part -> Eff.left) =
fun id_solver lp_top ->
match lp_top with
| LeftVar id ->
id_solver.id2var (Ident.idref_of_string (Ident.to_string id.it)) id.src
in
| LeftField (lp, id) -> (
(* check that [lp_eff] is a struct that have a field named [id] *)
match teff with
| Struct_type_eff(_, fl) -> (
try let (teff_field,_) = List.assoc id.it fl in
LeftFieldEff(lp_eff, id.it, teff_field)
with Not_found ->
raise (Compile_error(id.src, "bad field name in structure"))
)
| _ -> raise (Compile_error(id.src, "a structure was expected"))
)
| LeftArray (lp, vef) -> (
let lxm = vef.src in
match teff with
| Array_type_eff(teff_elt, size) ->
let index = EvalConst.eval_array_index id_solver vef.it lxm in
LeftArrayEff(lp_eff, index, teff_elt)
| _ -> raise (Compile_error(vef.src, "an array was expected"))
)
| LeftSlice (lp, sif) -> (
match teff with
| Array_type_eff(teff_elt, size) ->
let sieff = translate_slice_info id_solver sif.it sif.src in
let size_slice = sieff.se_width in
let teff_slice = Array_type_eff(teff_elt, size_slice) in
LeftSliceEff(lp_eff, sieff, teff_slice)
| _ -> raise (Compile_error(sif.src, "an array was expected"))
)
and (translate_val_exp : Eff.id_solver -> UnifyClock.subst ->
SyntaxTreeCore.val_exp -> UnifyClock.subst * Eff.val_exp) =
fun id_solver s ve ->
let s, vef_core, lxm =
match ve with
| CallByName(by_name_op, field_list) ->
let s,fl = List.fold_left
(fun (s,fl) f ->
let s,f = translate_field id_solver s f in
s,f::fl
)
(s,[])
field_list
in
let fl = List.rev fl in
s,
(CallByNameEff(
flagit (translate_by_name_op id_solver by_name_op) by_name_op.src, fl)),
by_name_op.src
| CallByPos(by_pos_op, Oper vel) ->
let s, vel_eff =
List.fold_left
(fun (s,vel) ve ->
let s, ve = translate_val_exp id_solver s ve in
s,ve::vel
)
(s,[]) vel
in
let vel_eff = List.rev vel_eff in
let lxm = by_pos_op.src in
let by_pos_op = by_pos_op.it in
let mk_by_pos_op by_pos_op_eff =
CallByPosEff(flagit by_pos_op_eff lxm, OperEff vel_eff)
in
let s, vef_core =
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
match by_pos_op with
(* put that in another module ? yes, see above.*)
| Predef_n(Map, sargs)
| Predef_n(Fill, sargs)
| Predef_n(Red, sargs)
| Predef_n(FillRed, sargs)
| Predef_n(BoolRed, sargs) ->
(* We will make use of [vel_eff] to resolve the polymorphism *)
let vel_eff, type_ll =
List.split (List.map (EvalType.f id_solver) vel_eff)
in
let type_l : Eff.type_ list = List.flatten type_ll in
let sargs_eff = translate_predef_static_args id_solver sargs lxm in
let iter_op = match by_pos_op with
Predef_n(op,_) -> op | _ -> assert false
in
let iter_profile = match by_pos_op with
| Predef_n(Map,_) ->
PredefEvalType.map_profile lxm sargs_eff
| Predef_n(Fill,_) | Predef_n(Red,_) | Predef_n(FillRed,_) ->
PredefEvalType.fillred_profile lxm sargs_eff
| Predef_n(BoolRed,_) ->
PredefEvalType.boolred_profile lxm sargs_eff
| _ -> assert false
in
let type_l_exp = snd (List.split (fst iter_profile)) in
let sargs_eff =
if List.length type_l <> List.length type_l_exp then
raise (Compile_error(lxm, "the iterator has a wrong arity."))
else
match UnifyType.f type_l type_l_exp with
| UnifyType.Equal -> sargs_eff
| UnifyType.Unif typ ->
(* the iterated nodes was polymorphic, but we know here
that the type variable was [typ].
*)
dump_polymorphic_nodes typ;
List.map (instanciate_type typ) sargs_eff
| UnifyType.Ko str -> raise (Compile_error(lxm, str))
in
s, mk_by_pos_op (Eff.Predef(iter_op, sargs_eff))
(* other predef operators *)
| Predef_n(op, args) ->
assert (args=[]); s, mk_by_pos_op(Predef (op,[]))
| CALL_n node_exp_f ->
s, mk_by_pos_op(Eff.CALL (flagit (node id_solver node_exp_f)
node_exp_f.src))
| IDENT_n idref -> (
try
let s, const = UnifyClock.const_to_val_eff lxm false s
(id_solver.id2const idref lxm)
s, const.core
with _ -> (* In case idref is not a static constant. *)
match Ident.pack_of_idref idref with
| Some pn -> s, mk_by_pos_op(Eff.IDENT idref)
(** Constant with a pack name are treated as
Eff.IDENT. *)
| None ->
try
(* try to add its pack name... *)
let id = Ident.of_idref idref in
let pn =
SymbolTab.find_pack_of_const id_solver.symbols id lxm
in
let idref = Ident.make_idref pn id in
s, mk_by_pos_op(Eff.IDENT (idref))
with _ ->
s, mk_by_pos_op(Eff.IDENT idref)
| CURRENT_n -> s, mk_by_pos_op Eff.CURRENT
| PRE_n -> s, mk_by_pos_op Eff.PRE
| ARROW_n -> s, mk_by_pos_op Eff.ARROW
| FBY_n -> s, mk_by_pos_op Eff.FBY
| CONCAT_n -> s, mk_by_pos_op Eff.CONCAT
| TUPLE_n -> s, mk_by_pos_op Eff.TUPLE
| ARRAY_n ->
s, CallByPosEff(flagit (Eff.ARRAY vel_eff) lxm, OperEff [])
| WITH_n(c,e1,e2) ->
let c_eff = EvalConst.f id_solver c in
if c_eff = [ Bool_const_eff true ] then
let s, ve1 = translate_val_exp id_solver s e1 in
s, mk_by_pos_op (Eff.WITH (ve1))
let s, ve2 = translate_val_exp id_solver s e2 in
s, mk_by_pos_op (Eff.WITH (ve2))
| STRUCT_ACCESS_n fid ->
s, mk_by_pos_op (Eff.STRUCT_ACCESS (fid))
| WHEN_n Base -> s, mk_by_pos_op (Eff.WHEN Base)
| WHEN_n (NamedClock { it = (cc,cv) ; src = lxm }) ->
let cc = add_pack_name id_solver lxm cc in
s,
mk_by_pos_op (Eff.WHEN (NamedClock { it = (cc,cv) ; src = lxm }))
| ARRAY_ACCES_n ve_index ->
s, mk_by_pos_op (
Eff.ARRAY_ACCES(
EvalConst.eval_array_index id_solver ve_index lxm))
| ARRAY_SLICE_n si ->
s, mk_by_pos_op
(Eff.ARRAY_SLICE(
EvalConst.eval_array_slice id_solver si lxm))
| HAT_n -> (
match vel with
| [exp; ve_size] ->
let size_const_eff = EvalConst.f id_solver ve_size
and s, exp_eff = translate_val_exp id_solver s exp in
(match size_const_eff with
| [Int_const_eff size] ->
s, mk_by_pos_op (Eff.HAT(size, exp_eff))
| _ -> assert false)
| _ -> assert false
)
| MERGE_n(id, idl) -> s, mk_by_pos_op (Eff.MERGE(id, idl))
s, vef_core, lxm
let vef, tl = EvalType.f id_solver { core=vef_core; typ=[]; clk = [] } in
let vef, _, s = EvalClock.f lxm id_solver s vef [] in
s, vef
and translate_by_name_op id_solver op =
match op.it with
| STRUCT_n idref ->
match Ident.pack_of_idref idref with
| None ->
(* If no pack name is provided, we lookup it in the symbol table *)
let id = Ident.of_idref idref in
let pn = SymbolTab.find_pack_of_type id_solver.symbols id op.src in
STRUCT (pn, idref)
| Some pn -> STRUCT (pn, idref)
and translate_field id_solver s (id, ve) =
let s, ve = translate_val_exp id_solver s ve in
s, (id, ve)
(* XXX autre nom, autre module ?
ca fait partie de la definition des iterateurs d'une certaine maniere...
-> crer 2 modules, Iterator + IteratorSemantics
*)
and get_const id_solver const_or_const_ident lxm =
match const_or_const_ident with
| StaticArgConst(c) -> List.hd (EvalConst.f id_solver c)
| StaticArgIdent(id) -> id_solver.id2const id lxm
| StaticArgType _
| StaticArgNode _ -> raise (Compile_error(lxm, "a constant was expected"))
Erwan Jahier
committed
and get_node id_solver node_or_node_ident lxm =
match node_or_node_ident with
| StaticArgIdent(id) ->
Erwan Jahier
committed
let sargs = [] in (* it is an alias: no static arg *)
| StaticArgNode(CALL_n ne) -> node id_solver ne
let sargs_eff = translate_predef_static_args id_solver sargs lxm in
PredefEvalType.make_node_exp_eff None op lxm sargs_eff
| StaticArgNode(_) -> assert false
| StaticArgType _
| StaticArgConst _ -> raise (Compile_error(lxm, "a node was expected"))
Erwan Jahier
committed
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
and (instanciate_type: Eff.type_ -> Eff.static_arg -> Eff.static_arg) =
fun t sarg ->
let make_long pstr idstr =
Ident.long_of_idref { id_pack = Some pstr ; id_id = idstr }
in
let instanciate_var_info vi =
{ vi with var_type_eff = Eff.subst_type t vi.var_type_eff }
in
match sarg with
| ConstStaticArgEff _ -> sarg
| TypeStaticArgEff _ -> sarg (* we cannot denote polymorphic type... *)
| NodeStaticArgEff(id,(node,il,ol)) ->
let node = match Ident.idref_of_long node with
| { id_pack = Some "Lustre" ; id_id = "times" } ->
let op = if t = Int_type_eff then "itimes" else "rtimes" in
make_long "Lustre" op
| { id_pack = Some "Lustre" ; id_id = "slash" } ->
let op = if t = Int_type_eff then "islash" else "rslash" in
make_long "Lustre" op
| { id_pack = Some "Lustre" ; id_id = "plus" } ->
let op = if t = Int_type_eff then "iplus" else "rplus" in
make_long "Lustre" op
| { id_pack = Some "Lustre" ; id_id = "minus" } ->
let op = if t = Int_type_eff then "iminus" else "rminus" in
make_long "Lustre" op
| { id_pack = Some "Lustre" ; id_id = "uminus" } ->
let op = if t = Int_type_eff then "iuminus" else "ruminus" in
make_long "Lustre" op
| { id_pack = Some "Lustre" ; id_id = "div" } ->
let op = if t = Int_type_eff then "div" else "rdiv" in
make_long "Lustre" op
(* polymorphic op. what should be done for type different from
int and real?
*)
(* Lustre::ilt and co are not compiled yet. *)
(* | { id_pack = Some "Lustre" ; id_id = "lt" } -> *)
(* let op = if t = Int_type_eff then "ilt" *)
(* else if t = Real_type_eff then "rlt" else "lt" in *)
(* make_long "Lustre" op *)
(* | { id_pack = Some "Lustre" ; id_id = "gt" } -> *)
(* let op = if t = Int_type_eff then "igt" *)
(* else if t = Real_type_eff then "rgt" else "gt" in *)
(* make_long "Lustre" op *)
(* | { id_pack = Some "Lustre" ; id_id = "lte" } -> *)
(* let op = if t = Int_type_eff then "ilte" *)
(* else if t = Real_type_eff then "rlte" else "lte" in *)
(* make_long "Lustre" op *)
(* | { id_pack = Some "Lustre" ; id_id = "gte" } -> *)
(* let op = if t = Int_type_eff then "igte" *)
(* else if t = Real_type_eff then "rgte" else "gte" in *)
(* make_long "Lustre" op *)
Erwan Jahier
committed
| { id_pack = Some "Lustre" ; id_id = "equal" } ->
let op = if t = Int_type_eff then "iequal"
else if t = Real_type_eff then "requal"
else if t = Bool_type_eff then "bequal" else "equal" in
make_long "Lustre" op
| { id_pack = Some "Lustre" ; id_id = "diff" } ->
let op = if t = Int_type_eff then "idiff"
else if t = Real_type_eff then "rdiff"
else if t = Bool_type_eff then "bdiff" else "diff" in
make_long "Lustre" op
| _ -> node
in
let il = List.map instanciate_var_info il
and ol = List.map instanciate_var_info ol
in
NodeStaticArgEff(id,(node,il,ol))
and (translate_predef_static_args: Eff.id_solver ->
Erwan Jahier
committed
SyntaxTreeCore.static_arg srcflagged list -> Lxm.t ->
Eff.static_arg list) =
fun id_solver sargs lxm ->
match sargs with
| [] -> []
| [{src=lxm_c1;it=c1}; {src=lxm_c2;it=c2}; {src=lxm_c3;it=c3}] ->
[
ConstStaticArgEff(Ident.of_string "min", get_const id_solver c1 lxm_c1);
ConstStaticArgEff(Ident.of_string "max", get_const id_solver c2 lxm_c2);
ConstStaticArgEff(Ident.of_string "size",get_const id_solver c3 lxm_c3)
]
| [{src=lxm_n;it=node}; {src=lxm_c;it=const}] ->
Erwan Jahier
committed
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
(* There is two cases:
- node_eff is a simple node (no static arg). Then there
is nothing special todo. We use it to build the static arg.
- node_eff is a node with static arguments. We need to
unnest this. Therefore, we create on-the-fly an alias
pointing to this node_eff, compile it, and use the
result (which is then a simple node) as the current
node_eff. *)
let node_eff =
if snd node_eff.node_key_eff = [] then
node_eff
else
(*
- create a fresh node alias name (node_alias)
- build a fake node_info containing the alias definition
- add this entry in the SymbolTab (via id_solver.symbols)
- call id_solver.id2node on node_alias to compile this new node
*)
let node_alias_str = Name.node_key node_eff.node_key_eff "node_alias" in
let node_alias_idref = Ident.idref_of_string node_alias_str in
let node_alias_ident = Ident.of_string node_alias_str in
let by_pos_op =
match node with
| StaticArgNode(by_pos_op) -> by_pos_op
| StaticArgIdent(id) -> assert false
| StaticArgType _
| StaticArgConst _ ->
raise (Compile_error(lxm_n, "a node was expected"))
in
let node_alias_info =
{ src = lxm_n ;
it = {
name = node_alias_ident;
static_params = [] ;
vars = None;
def = Alias { src = lxm_n ; it = by_pos_op };
has_mem = node_eff.has_mem_eff;
is_safe = node_eff.is_safe_eff;
}
}
in
let _ =
SymbolTab.add_node id_solver.symbols node_alias_ident node_alias_info
in
id_solver.id2node node_alias_idref [] lxm_n
in
let node_arg =
fst node_eff.node_key_eff, node_eff.inlist_eff, node_eff.outlist_eff
in
[NodeStaticArgEff(Ident.of_string "node", node_arg);
ConstStaticArgEff(Ident.of_string "size",get_const id_solver const lxm_c)]
raise (Compile_error(lxm, "bad arguments number for array iterator"))
Erwan Jahier
committed
and (translate_slice_info : Eff.id_solver -> SyntaxTreeCore.slice_info ->
fun id_solver si lxm ->
EvalConst.eval_array_slice id_solver si lxm
(**********************************************************************************)
(* exported *)
let (assertion : Eff.id_solver -> SyntaxTreeCore.val_exp Lxm.srcflagged ->
Eff.val_exp Lxm.srcflagged) =
fun id_solver vef ->
let s, val_exp_eff = translate_val_exp id_solver UnifyClock.empty_subst vef.it in
(* Check that the assert is a bool. *)
let val_exp_eff, evaled_exp = EvalType.f id_solver val_exp_eff in
List.iter
(fun ve ->
if ve <> Bool_type_eff then
let msg = "type mismatch: \n\tthe content of the assertion is of type "
Erwan Jahier
committed
^ (LicDump.string_of_type_eff4msg ve)
^ " whereas it shoud be a Boolean\n"
in
raise (Compile_error(vef.src, msg))
)
evaled_exp;
(* type is ok *)
(* Clock check the assertion*)
let _, clock_eff_list, _s =
EvalClock.f vef.src id_solver s val_exp_eff [BaseEff]
in
match clock_eff_list with
| [id, BaseEff]
| [id, On(_,BaseEff)]
| [id, ClockVar _] -> Lxm.flagit val_exp_eff vef.src
| [id, ce] ->
let msg = "clock error: assert should be on the base clock, "^
"but it is on "^ (LicDump.string_of_clock2 ce) ^ "\n"
in
raise (Compile_error(vef.src, msg))
| _ -> assert false
(******************************************************************************)