Skip to content
Snippets Groups Projects
getEff.ml 31.1 KiB
Newer Older
(** Time-stamp: <modified the 26/05/2009 (at 15:27) by Erwan Jahier> *)
open SyntaxTreeCore
open Eff

(******************************************************************************)
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
Erwan Jahier's avatar
Erwan Jahier committed
        | 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? *)


let rec (clock : Eff.id_solver -> SyntaxTreeCore.var_info -> Eff.id_clock)=
    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)
Erwan Jahier's avatar
Erwan Jahier committed

(******************************************************************************)
(* 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
        raise (Compile_error(lxm, 
Erwan Jahier's avatar
Erwan Jahier committed
                             "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"   
                            ))
Erwan Jahier's avatar
Erwan Jahier committed
        List.iter2
          (fun le re -> 
             if le <> re then
               let msg = "type mismatch: \n***\t'" 
Erwan Jahier's avatar
Erwan Jahier committed
                 "' (left-hand-side) \n*** is not compatible with \n***\t'" 
                 ^ (LicDump.string_of_type_eff4msg re) ^ "' (right-hand-side)"
Erwan Jahier's avatar
Erwan Jahier committed
               in
                 raise (Compile_error(lxm, msg))
Erwan Jahier's avatar
Erwan Jahier committed
          )
          lpl_teff
          right_part

(* 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;
(******************************************************************************)
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).  *)
      []
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

Erwan Jahier's avatar
Erwan Jahier committed
        
(** [check_static_arg this pn id sa (symbols, acc)] compile a static arg 
    into a static_arg
and (check_static_arg : Eff.id_solver ->
      SyntaxTreeCore.static_param srcflagged  -> 
      SyntaxTreeCore.static_arg srcflagged -> 
      Eff.static_arg) =

    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: '" ^ 
          (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.")) 
    let sa_eff =
      match sa.it, sp.it with
        | StaticArgIdent idref, StaticParamConst(id, type_exp) ->
Erwan Jahier's avatar
Erwan Jahier committed
            let ceff = node_id_solver.id2const idref sa.src in
            let t_ceff = type_of_const ceff in
              check_type_arg t_ceff type_exp;
Erwan Jahier's avatar
Erwan Jahier committed
              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) -> (
Erwan Jahier's avatar
Erwan Jahier committed
            let ceff = EvalConst.f node_id_solver ce in
            let t_ceff = type_of_const (List.hd ceff) in
              check_type_arg t_ceff type_exp;
Erwan Jahier's avatar
Erwan Jahier committed
              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)

	| 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's avatar
Erwan Jahier committed
            let neff = node node_id_solver ne in
            let (inlist, outlist) = check_node_arg neff vii vio in
            let neff = fst neff.node_key_eff in
              NodeStaticArgEff (id, (neff, inlist, outlist))
Erwan Jahier's avatar
Erwan Jahier committed

        | StaticArgNode(Predef_n (op,sargs)), StaticParamNode(id,vii,vio,_) ->
Erwan Jahier's avatar
Erwan Jahier committed
            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
            let (inlist, outlist) = check_node_arg opeff vii vio in
            let opeff = fst opeff.node_key_eff in
              NodeStaticArgEff (id, (opeff, inlist, outlist))
Erwan Jahier's avatar
Erwan Jahier committed

        | 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
Erwan Jahier's avatar
Erwan Jahier committed
            |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...*)
(******************************************************************************)
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 -> 
Erwan Jahier's avatar
Erwan Jahier committed
          let vi_eff = 
            id_solver.id2var (Ident.idref_of_string (Ident.to_string id.it)) id.src 
          in
Erwan Jahier's avatar
Erwan Jahier committed
            LeftVarEff (vi_eff, id.src)
              
      | LeftField (lp, id) -> (
Erwan Jahier's avatar
Erwan Jahier committed
          let lp_eff = translate_left_part id_solver lp in
          let teff = Eff.type_of_left lp_eff in
Erwan Jahier's avatar
Erwan Jahier committed
            (* 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) -> (
Erwan Jahier's avatar
Erwan Jahier committed
          let lp_eff = translate_left_part id_solver lp in
          let teff = Eff.type_of_left lp_eff in
Erwan Jahier's avatar
Erwan Jahier committed
          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
Erwan Jahier's avatar
Erwan Jahier committed
                    LeftArrayEff(lp_eff, index, teff_elt)
                      
              | _ -> raise (Compile_error(vef.src, "an array was expected"))
        )
      | LeftSlice (lp, sif) -> (
Erwan Jahier's avatar
Erwan Jahier committed
          let lp_eff = translate_left_part id_solver lp in
          let teff = Eff.type_of_left lp_eff in
Erwan Jahier's avatar
Erwan Jahier committed
            match teff with  
              | Array_type_eff(teff_elt, size) -> 
                  let sieff = translate_slice_info id_solver sif.it sif.src in
Erwan Jahier's avatar
Erwan Jahier committed
                  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, 
               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
              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]. 
                            *)
			    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,[]))
                    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))
                              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
                    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))
                      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 }))
                          EvalConst.eval_array_index id_solver ve_index lxm))
                      (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))
    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_anonymous_n -> STRUCT_anonymous
    | 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"))

and get_node id_solver node_or_node_ident lxm =
  match node_or_node_ident with
    | StaticArgIdent(id) -> 
        let sargs = [] in (* it is an alias: no static arg *)
Erwan Jahier's avatar
Erwan Jahier committed
          id_solver.id2node id sargs lxm 

    | StaticArgNode(CALL_n ne) -> node id_solver ne
    | StaticArgNode(Predef_n (op,sargs)) ->
Erwan Jahier's avatar
Erwan Jahier committed
        let sargs_eff = translate_predef_static_args id_solver sargs lxm in
          PredefEvalType.make_node_exp_eff None op lxm sargs_eff 
    | StaticArgType _ 
    | StaticArgConst _ -> raise (Compile_error(lxm, "a node was expected"))


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 *)

	      |  { 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 -> 
      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}] -> 
Erwan Jahier's avatar
Erwan Jahier committed
          [
            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's avatar
Erwan Jahier committed
          let node_eff = get_node id_solver node lxm_n in
            (* 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);
Erwan Jahier's avatar
Erwan Jahier committed
             ConstStaticArgEff(Ident.of_string "size",get_const id_solver const lxm_c)]
Erwan Jahier's avatar
Erwan Jahier committed
          raise (Compile_error(lxm, "bad arguments number for array iterator"))
and (translate_slice_info  : Eff.id_solver -> SyntaxTreeCore.slice_info -> 
      Lxm.t -> Eff.slice_info) =
  fun id_solver si lxm ->
    EvalConst.eval_array_slice id_solver si lxm
Erwan Jahier's avatar
Erwan Jahier committed
(**********************************************************************************)
let (assertion : Eff.id_solver -> SyntaxTreeCore.val_exp Lxm.srcflagged -> 
      Eff.val_exp Lxm.srcflagged) =
    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
Erwan Jahier's avatar
Erwan Jahier committed
        (fun ve -> 
           if ve <> Bool_type_eff then
             let msg = "type mismatch: \n\tthe content of the assertion is of type " 
Erwan Jahier's avatar
Erwan Jahier committed
               ^ " whereas it shoud be a Boolean\n"
             in
               raise (Compile_error(vef.src, msg))
        )
        evaled_exp;
      let _, clock_eff_list, _s = 
        EvalClock.f vef.src id_solver s val_exp_eff [BaseEff]
          | [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
      
(******************************************************************************)