@ -19,21 +19,29 @@ open Obc_mapfold
open Initial
let fresh_it () = Idents . gen_var " mls2obc " " i "
let fresh_it () =
let id = Idents . gen_var " mls2obc " " i " in
id , mk_var_dec id Initial . tint
let gen_obj_ident n = Idents . gen_var " mls2obc " ( ( shortname n ) ^ " _inst " )
let op_from_string op = { qual = " Pervasives " ; name = op ; }
let rec lhs_of_idx_list e = function
| [] -> e | idx :: l -> mk_lhs ( Larray ( lhs_of_idx_list e l , idx ) )
let rec pattern_of_idx_list p l =
let rec aux ty l = match ty , l with
| _ , [] -> p
| Tarray ( ty' , _ ) , idx :: l -> mk_pattern ty ( Larray ( aux ty' l , idx ) )
| _ -> internal_error " mls2obc " 1
in
aux p . pat_ty l
let array_elt_of_exp idx e =
match e . e_desc with
| Econst ( { se_desc = Sarray_power ( c , _ ) } ) ->
mk_exp ( Econst c )
| _ ->
mk_lhs_exp ( Larray ( lhs_of_exp e , mk_exp ( Elhs idx ) ) )
match e . e_desc , Modules . unalias_type e . e_ty with
| Econst ( { se_desc = Sarray_power ( c , _ ) } ) , Tarray ( ty , _ ) ->
mk_exp ty ( Econst c )
| _ , Tarray ( ty , _ ) ->
mk_pattern_exp ty ( Larray ( pattern_of_exp e , mk_exp Initial . tint ( Epattern idx ) ) )
| _ -> internal_error " mls2obc " 2
(* * Creates the expression that checks that the indices
in idx_list are in the bounds . If idx_list = [ e1 ; .. ; ep ]
@ -41,15 +49,11 @@ let array_elt_of_exp idx e =
e1 < = n1 && .. && ep < = np * )
let rec bound_check_expr idx_list bounds =
match ( idx_list , bounds ) with
| [ idx ] , [ n ] ->
mk_exp ( Eop ( op_from_string " < " ,
[ idx ; mk_exp ( Econst n ) ] ) )
| [ idx ] , [ n ] -> mk_exp_bool ( Eop ( op_from_string " < " , [ idx ; mk_exp_int ( Econst n ) ] ) )
| ( idx :: idx_list , n :: bounds ) ->
let e = mk_exp ( Eop ( op_from_string " < " ,
[ idx ; mk_exp ( Econst n ) ] ) ) in
mk_exp ( Eop ( op_from_string " & " ,
[ e ; bound_check_expr idx_list bounds ] ) )
| ( _ , _ ) -> assert false
let e = mk_exp_bool ( Eop ( op_from_string " < " , [ idx ; mk_exp_int ( Econst n ) ] ) ) in
mk_exp_bool ( Eop ( op_from_string " & " , [ e ; bound_check_expr idx_list bounds ] ) )
| ( _ , _ ) -> internal_error " mls2obc " 3
let reinit o =
Acall ( [] , o , Mreset , [] )
@ -70,7 +74,7 @@ let translate_var_dec l =
let rec translate map e =
let desc = match e . Minils . e_desc with
| Minils . Econst v -> Econst v
| Minils . Evar n -> E lhs ( Control . var_from_name map n )
| Minils . Evar n -> E pattern ( Control . var_from_name map n )
| Minils . Eapp ( { Minils . a_op = Minils . Eequal } , e_list , _ ) ->
Eop ( op_from_string " = " , List . map ( translate map ) e_list )
| Minils . Eapp ( { Minils . a_op = Minils . Efun n } , e_list , _ ) when Mls_utils . is_op n ->
@ -85,17 +89,17 @@ let rec translate map e =
let f_e_list = List . map ( fun ( f , e ) -> ( f , ( translate map e ) ) ) f_e_list in
Estruct ( type_name , f_e_list )
| Minils . Eapp ( { Minils . a_op = Minils . Efield ; Minils . a_params = params } , e_list , _ ) ->
let f = match ( assert_1 params ) . se_desc with Sfield f -> f | _ -> assert false in
let f = match ( assert_1 params ) . se_desc with Sfield f -> f | _ -> internal_error " mls2obc " 4 in
let e = translate map ( assert_1 e_list ) in
Elhs ( mk_lhs ( Lfield ( lhs _of_exp e , f ) ) )
Epattern ( mk_pattern e . e_ty ( Lfield ( pattern _of_exp e , f ) ) )
(* Remaining array operators *)
| Minils . Eapp ( { Minils . a_op = Minils . Earray } , e_list , _ ) ->
Earray ( List . map ( translate map ) e_list )
| Minils . Eapp ( { Minils . a_op = Minils . Eselect ;
Minils . a_params = idx } , e_list , _ ) ->
let e = translate map ( assert_1 e_list ) in
let idx_list = List . map ( fun idx -> mk_exp ( Econst idx ) ) idx in
E lhs ( lhs_of_idx_list ( lhs _of_exp e ) idx_list )
let idx_list = List . map ( fun idx -> mk_exp tint ( Econst idx ) ) idx in
E pattern ( pattern_of_idx_list ( pattern _of_exp e ) idx_list )
(* Async operators *)
| Minils . Eapp ( { Minils . a_op = Minils . Ebang } , e_list , _ ) ->
let e = translate map ( assert_1 e_list ) in
@ -105,11 +109,12 @@ let rec translate map e =
| Minils . Eapp ( { Minils . a_op = ( Minils . Enode _ | Minils . Efun _ | Minils . Econcat | Minils . Eupdate | Minils . Eselect_dyn
| Minils . Eselect_slice | Minils . Earray_fill | Minils . Efield_update | Minils . Eifthenelse
| Minils . Etuple ) } , _ , _ ) ->
Format . eprintf " %aThis should not be treated as an exp in mls2obc : %a@. "
(* Format.eprintf " %aThis should not be treated as an exp in mls2obc : %a@."
Location . print_location e . Minils . e_loc Mls_printer . print_exp e ;
assert false
assert false * )
internal_error " mls2obc " 5
in
mk_exp ~ ty : e . Minils . e_ty desc
mk_exp e . Minils . e_ty desc
(* [translate pat act = si, d] *)
and translate_act map pat
@ -124,54 +129,53 @@ and translate_act map pat
| pat , Minils . Ewhen ( e , _ , _ ) ->
translate_act map pat e
| pat , Minils . Emerge ( x , c_act_list ) ->
let lhs = Control . var_from_name map x in
[ Acase ( mk_exp ( Elhs lhs ) , translate_c_act_list map pat c_act_list ) ]
let pattern = Control . var_from_name map x in
[ Acase ( mk_exp pattern . pat_ty ( Epattern pattern ) , translate_c_act_list map pat c_act_list ) ]
(* Array ops *)
| Minils . Evarpat x , Minils . Eapp ( { Minils . a_op = Minils . Econcat } , [ e1 ; e2 ] , _ ) ->
let cpt1 = fresh_it () in
let cpt2 = fresh_it () in
let cpt1 , cpt1d = fresh_it () in
let cpt2 , cpt2d = fresh_it () in
let x = Control . var_from_name map x in
let t = x . pat_ty in
( match e1 . Minils . e_ty , e2 . Minils . e_ty with
| Tarray ( _ , n1 ) , Tarray ( _ , n2 ) ->
| Tarray ( t1 , n1 ) , Tarray ( t2 , n2 ) ->
let e1 = translate map e1 in
let e2 = translate map e2 in
let a1 =
Afor ( cpt1 , mk_static_int 0 , n1 ,
mk_block [ Aassgn ( mk_lhs ( Larray ( x , mk_evar cpt1 ) ) ,
mk_lhs_exp ( Larray ( lhs_of_exp e1 ,
mk_evar cpt1 ) ) ) ] ) in
let idx = mk_exp ( Eop ( op_from_string " + " ,
[ mk_exp ( Econst n1 ) ; mk_evar cpt2 ] ) ) in
Afor ( cpt1d , mk_static_int 0 , n1 ,
mk_block [ Aassgn ( mk_pattern t ( Larray ( x , mk_evar_int cpt1 ) ) ,
mk_pattern_exp t1 ( Larray ( pattern_of_exp e1 , mk_evar_int cpt1 ) ) ) ] ) in
let idx = mk_exp_int ( Eop ( op_from_string " + " , [ mk_exp_int ( Econst n1 ) ; mk_evar_int cpt2 ] ) ) in
let a2 =
Afor ( cpt2 , mk_static_int 0 , n2 ,
mk_block [ Aassgn ( mk_lhs ( Larray ( x , idx ) ) ,
mk_lhs_exp ( Larray ( lhs_of_exp e2 ,
mk_evar cpt2 ) ) ) ] )
Afor ( cpt2d , mk_static_int 0 , n2 ,
mk_block [ Aassgn ( mk_pattern t ( Larray ( x , idx ) ) ,
mk_pattern_exp t2 ( Larray ( pattern_of_exp e2 , mk_evar_int cpt2 ) ) ) ] )
in
[ a1 ; a2 ]
| _ -> assert false )
| Minils . Evarpat x , Minils . Eapp ( { Minils . a_op = Minils . Earray_fill ; Minils . a_params = [ n ] } , [ e ] , _ ) ->
let cpt = fresh_it () in
let cpt , cptd = fresh_it () in
let e = translate map e in
[ Afor ( cpt , mk_static_int 0 , n ,
mk_block [ Aassgn ( mk_lhs ( Larray ( Control . var_from_name map x , mk_evar cpt ) ) , e ) ] ) ]
let x = Control . var_from_name map x in
[ Afor ( cptd , mk_static_int 0 , n , mk_block [ Aassgn ( mk_pattern x . pat_ty ( Larray ( x , mk_evar_int cpt ) ) , e ) ] ) ]
| Minils . Evarpat x , Minils . Eapp ( { Minils . a_op = Minils . Eselect_slice ; Minils . a_params = [ idx1 ; idx2 ] } , [ e ] , _ ) ->
let cpt = fresh_it () in
let cpt , cptd = fresh_it () in
let e = translate map e in
let idx = mk_exp ( Eop ( op_from_string " + " , [ mk_evar cpt ; mk_exp ( Econst idx1 ) ] ) ) in
let x = Control . var_from_name map x in
let idx = mk_exp_int ( Eop ( op_from_string " + " , [ mk_evar_int cpt ; mk_exp_int ( Econst idx1 ) ] ) ) in
(* bound = ( idx2 - idx1 ) + 1 *)
let bound = mk_static_int_op ( op_from_string " + " )
[ mk_static_int 1 ; mk_static_int_op ( op_from_string " - " ) [ idx2 ; idx1 ] ] in
[ Afor ( cpt , mk_static_int 0 , bound ,
mk_block [ Aassgn ( mk_ lhs ( Larray ( Control . var_from_name map x , mk_evar cpt ) ) ,
mk_lhs_exp ( Larray ( lhs _of_exp e , idx ) ) ) ] ) ]
[ mk_static_int 1 ; mk_static_int_op ( op_from_string " - " ) [ idx2 ; idx1 ] ] in
[ Afor ( cpt d , mk_static_int 0 , bound ,
mk_block [ Aassgn ( mk_ pattern x . pat_ty ( Larray ( x , mk_evar_int cpt ) ) ,
mk_pattern_exp e . e_ty ( Larray ( pattern _of_exp e , idx ) ) ) ] ) ]
| Minils . Evarpat x , Minils . Eapp ( { Minils . a_op = Minils . Eselect_dyn } , e1 :: e2 :: idx , _ ) ->
let x = Control . var_from_name map x in
let bounds = Mls_utils . bounds_list e1 . Minils . e_ty in
let e1 = translate map e1 in
let idx = List . map ( translate map ) idx in
let true _ act =
Aassgn ( x , mk_exp ( Elhs ( lhs_of_idx_list ( lhs_of_exp e1 ) idx ) ) ) in
let p = pattern_of_idx_list ( pattern_of_exp e1 ) idx in
let true _ act = Aassgn ( x , mk_exp p . pat_ty ( Epattern p ) ) in
let false _ act = Aassgn ( x , translate map e2 ) in
let cond = bound_check_expr idx bounds in
[ Acase ( cond , [ ptrue , mk_block [ true _ act ] ; pfalse , mk_block [ false _ act ] ] ) ]
@ -179,7 +183,7 @@ and translate_act map pat
let x = Control . var_from_name map x in
let bounds = Mls_utils . bounds_list e1 . Minils . e_ty in
let idx = List . map ( translate map ) idx in
let action = Aassgn ( lhs _of_idx_list x idx ,
let action = Aassgn ( pattern _of_idx_list x idx ,
translate map e2 ) in
let cond = bound_check_expr idx bounds in
let action = Acase ( cond , [ ptrue , mk_block [ action ] ] ) in
@ -190,8 +194,8 @@ and translate_act map pat
Minils . Eapp ( { Minils . a_op = Minils . Efield_update ; Minils . a_params = [ { se_desc = Sfield f } ] } , [ e1 ; e2 ] , _ ) ->
let x = Control . var_from_name map x in
let copy = Aassgn ( x , translate map e1 ) in
let action = Aassgn ( mk_ lhs ( Lfield ( x , f ) ) , translate map e2 ) in
[ copy ; action ]
let action = Aassgn ( mk_ pattern x . pat_ty ( Lfield ( x , f ) ) , translate map e2 ) in
[ copy ; action ]
| Minils . Evarpat n , _ ->
[ Aassgn ( Control . var_from_name map n , translate map act ) ]
@ -233,7 +237,7 @@ let rec translate_eq map call_context { Minils.eq_lhs = pat; Minils.eq_rhs = e }
let x = Control . var_from_name map n in
let si = ( match opt_c with
| None -> si
| Some c -> ( Aassgn ( x , mk_exp ( Econst c ) ) ) :: si ) in
| Some c -> ( Aassgn ( x , mk_exp x . pat_ty ( Econst c ) ) ) :: si ) in
let action = Aassgn ( Control . var_from_name map n , translate map e ) in
v , si , j , ( Control . control map ck action ) :: s
@ -258,12 +262,10 @@ let rec translate_eq map call_context { Minils.eq_lhs = pat; Minils.eq_rhs = e }
pfalse , mk_block ~ locals : vf false _ act ] ) in
v , si , j , ( Control . control map ck action ) :: s
| pat , Minils . Eapp ( { Minils . a_op = Minils . Efun _ | Minils . Enode _ } as app ,
e_list , r ) ->
| pat , Minils . Eapp ( { Minils . a_op = Minils . Efun _ | Minils . Enode _ } as app , e_list , r ) ->
let name_list = translate_pat map pat in
let c_list = List . map ( translate map ) e_list in
let v' , si' , j' , action = mk_node_call map call_context
app loc name_list c_list in
let v' , si' , j' , action = mk_node_call map call_context app loc name_list c_list e . Minils . e_ty in
let action = List . map ( Control . control map ck ) action in
let s = ( match r , app . Minils . a_op with
| Some r , Minils . Enode _ ->
@ -275,12 +277,10 @@ let rec translate_eq map call_context { Minils.eq_lhs = pat; Minils.eq_rhs = e }
| pat , Minils . Eiterator ( it , app , n , e_list , reset ) ->
let name_list = translate_pat map pat in
let c_list =
List . map ( translate map ) e_list in
let x = fresh_it () in
let call_context = Some { oa_index = mk_lhs ( Lvar x ) ; oa_size = n } in
let si' , j' , action = translate_iterator map call_context it
name_list app loc n x c_list in
let c_list = List . map ( translate map ) e_list in
let x , xd = fresh_it () in
let call_context = Some { oa_index = mk_pattern_int ( Lvar x ) ; oa_size = n } in
let si' , j' , action = translate_iterator map call_context it name_list app loc n x xd c_list e . Minils . e_ty in
let action = List . map ( Control . control map ck ) action in
let s =
( match reset , app . Minils . a_op with
@ -299,18 +299,18 @@ let rec translate_eq map call_context { Minils.eq_lhs = pat; Minils.eq_rhs = e }
and translate_eq_list map call_context act_list =
List . fold_right ( translate_eq map call_context ) act_list ( [] , [] , [] , [] )
and mk_node_call map call_context app loc name_list args =
and mk_node_call map call_context app loc name_list args ty =
match app . Minils . a_op with
| Minils . Efun f when Mls_utils . is_op f ->
let e = mk_exp ( Eop ( f , args ) ) in
[] , [] , [] , [ Aassgn ( List . hd name_list , e ) ]
let e = mk_exp ty ( Eop ( f , args ) ) in
[] , [] , [] , [ Aassgn ( List . hd name_list , e ) ]
| Minils . Enode f when Itfusion . is_anon_node f ->
let add_input env vd = Env . add vd . Minils . v_ident ( mk_ lh s ( Lvar vd . Minils . v_ident ) ) env in
let add_input env vd = Env . add vd . Minils . v_ident ( mk_ pattern vd . Mini ls. v_type ( Lvar vd . Minils . v_ident ) ) env in
let build env vd a = Env . add vd . Minils . v_ident a env in
let subst_act_list env act_list =
let exp funs env e = match e . e_desc with
| E lhs { pat_desc = Lvar x } ->
| E pattern { pat_desc = Lvar x } ->
let e =
( try Env . find x env
with Not_found -> e ) in
@ -346,61 +346,66 @@ and mk_node_call map call_context app loc name_list args =
[] , si , [ obj ] , s
| _ -> assert false
and translate_iterator map call_context it name_list app loc n x c_list =
let array_of_output name_list =
List . map ( fun l -> mk_lhs ( Larray ( l , mk_evar x ) ) ) name_list in
let array_of_input c_list =
List . map ( array_elt_of_exp ( mk_lhs ( Lvar x ) ) ) c_list in
and translate_iterator map call_context it name_list app loc n x xd c_list ty =
let unarray ty = match ty with
| Tarray ( t , _ ) -> t
| _ -> Format . eprintf " %a " Global_printer . print_type ty ; internal_error " mls2obc " 6
in
let array_of_output name_list ty_list =
List . map ( fun l -> mk_pattern ty ( Larray ( l , mk_evar_int x ) ) ) name_list (* TODO not ty, but Tprod ( ti... ) -> ti *)
in
let array_of_input c_list = List . map ( array_elt_of_exp ( mk_pattern_int ( Lvar x ) ) ) c_list in
match it with
| Minils . Imap ->
let c_list = array_of_input c_list in
let name_list = array_of_output name_list in
let v , si , j , action = mk_node_call map call_context
app loc name_list c_list in
let ty_list = Types . unprod ty in
let name_list = array_of_output name_list ty_list in
let node_out_ty = Types . prod ( List . map unarray ty_list ) in
let v , si , j , action = mk_node_call map call_context app loc name_list c_list node_out_ty in
let v = translate_var_dec v in
let b = mk_block ~ locals : v action in
si , j , [ Afor ( x , mk_static_int 0 , n , b ) ]
si , j , [ Afor ( x d , mk_static_int 0 , n , b ) ]
| Minils . Imapfold ->
let ( c_list , acc_in ) = split_last c_list in
let c_list = array_of_input c_list in
let ty_list = Types . unprod ty in
let ( name_list , acc_out ) = split_last name_list in
let name_list = array_of_output name_list in
let v , si , j , action = mk_node_call map call_context
app loc ( name_list @ [ acc_out ] )
( c_list @ [ mk_exp ( Elhs acc_out ) ] ) in
let name_list = array_of_output name_list ty_list in
let node_out_ty = Types . prod ( Misc . map_butlast unarray ty_list ) in
let v , si , j , action = mk_node_call map call_context app loc ( name_list @ [ acc_out ] )
( c_list @ [ mk_exp acc_out . pat_ty ( Epattern acc_out ) ] ) node_out_ty
in
let v = translate_var_dec v in
let b = mk_block ~ locals : v action in
si , j , [ Aassgn ( acc_out , acc_in ) ;
Afor ( x , mk_static_int 0 , n , b ) ]
si , j , [ Aassgn ( acc_out , acc_in ) ; Afor ( xd , mk_static_int 0 , n , b ) ]
| Minils . Ifold ->
let ( c_list , acc_in ) = split_last c_list in
let c_list = array_of_input c_list in
let acc_out = last_element name_list in
let v , si , j , action = mk_node_call map call_context
app loc name_list ( c_list @ [ mk_exp ( Elhs acc_out ) ] ) in
let v , si , j , action =
mk_node_call map call_context app loc name_list ( c_list @ [ mk_exp acc_out . pat_ty ( Epattern acc_out ) ] ) ty
in
let v = translate_var_dec v in
let b = mk_block ~ locals : v action in
si , j , [ Aassgn ( acc_out , acc_in ) ;
Afor ( x , mk_static_int 0 , n , b ) ]
si , j , [ Aassgn ( acc_out , acc_in ) ; Afor ( xd , mk_static_int 0 , n , b ) ]
| Minils . Ifoldi ->
let ( c_list , acc_in ) = split_last c_list in
let c_list = array_of_input c_list in
let acc_out = last_element name_list in
let v , si , j , action = mk_node_call map call_context
app loc name_list ( c_list @ [ mk_evar x ; mk_exp ( Elhs acc_out ) ] ) in
let v , si , j , action = mk_node_call map call_context app loc name_list
( c_list @ [ mk_evar_int x ; mk_exp acc_out . pat_ty ( Epattern acc_out ) ] ) ty
in
let v = translate_var_dec v in
let b = mk_block ~ locals : v action in
si , j , [ Aassgn ( acc_out , acc_in ) ;
Afor ( x , mk_static_int 0 , n , b ) ]
si , j , [ Aassgn ( acc_out , acc_in ) ; Afor ( xd , mk_static_int 0 , n , b ) ]
let remove m d_list =
List . filter ( fun { Minils . v_ident = n } -> not ( List . mem_assoc n m ) ) d_list
let translate_contract map mem_var s =
let translate_contract map mem_var _ty s =
function
| None -> ( [] , [] , [] , [] )
| Some
@ -408,23 +413,22 @@ let translate_contract map mem_vars =
Minils . c_eq = eq_list ;
Minils . c_local = d_list ;
} ->
let ( v , si , j , s_list ) = translate_eq_list map
empty_call_context eq_list in
let ( v , si , j , s_list ) = translate_eq_list map empty_call_context eq_list in
let d_list = translate_var_dec ( v @ d_list ) in
let d_list = List . filter
( fun vd -> not ( List . mem vd . v_ident mem_var s) ) d_list in
( fun vd -> not ( List . exists ( fun ( i , _ ) -> i = vd . v_ident ) mem_var_ty s) ) d_list in
( si , j , s_list , d_list )
(* * Returns a map, mapping variables names to the variables
where they will be stored . * )
let subst_map inputs outputs locals mem s =
let subst_map inputs outputs locals mem _ty s =
(* Create a map that simply maps each var to itself *)
let m =
let m ap =
List . fold_left
( fun m { Minils . v_ident = x } -> Env . add x ( mk_ lhs ( Lvar x ) ) m )
( fun m { Minils . v_ident = x ; Minils . v_type = ty } -> Env . add x ( mk_ pattern ty ( Lvar x ) ) m )
Env . empty ( inputs @ outputs @ locals )
in
List . fold_left ( fun m x -> Env . add x ( mk_ lhs ( Lmem x ) ) m ) m mem s
List . fold_left ( fun m ap ( x , x _ty) -> Env . add x ( mk_ pattern x_ty ( Lmem x ) ) m ap ) m ap mem _ty s
let translate_node
( {
@ -438,15 +442,15 @@ let translate_node
Minils . n_loc = loc ;
} as n ) =
Idents . enter_node f ;
let mem_var s = Mls_utils . node_memory_vars n in
let subst_map = subst_map i_list o_list d_list mem_var s in
let mem_var _ty s = Mls_utils . node_memory_vars n in
let subst_map = subst_map i_list o_list d_list mem_var _ty s in
let ( v , si , j , s_list ) = translate_eq_list subst_map empty_call_context eq_list in
let ( si' , j' , s_list' , d_list' ) = translate_contract subst_map mem_var s contract in
let ( si' , j' , s_list' , d_list' ) = translate_contract subst_map mem_var _ty s contract in
let i_list = translate_var_dec i_list in
let o_list = translate_var_dec o_list in
let d_list = translate_var_dec ( v @ d_list ) in
let m , d_list = List . partition
( fun vd -> List . mem vd . v_ident mem_var s) d_list in
( fun vd -> List . exists ( fun ( i , _ ) -> i = vd . v_ident ) mem_var_ty s) d_list in
let s = Control . joinlist ( s_list @ s_list' ) in
let j = j' @ j in
let si = Control . joinlist ( si @ si' ) in