add iter for set and lists
This commit is contained in:
parent
33101820ec
commit
9dd8e63cbf
@ -19,7 +19,7 @@ let get_predicate : string -> type_value -> expression list -> predicate result
|
|||||||
| "NONE" -> (
|
| "NONE" -> (
|
||||||
let%bind ty' = Mini_c.get_t_option ty in
|
let%bind ty' = Mini_c.get_t_option ty in
|
||||||
let%bind m_ty = Compiler_type.type_ ty' in
|
let%bind m_ty = Compiler_type.type_ ty' in
|
||||||
ok @@ simple_unary @@ prim ~children:[m_ty] I_NONE
|
ok @@ simple_constant @@ prim ~children:[m_ty] I_NONE
|
||||||
)
|
)
|
||||||
| "NIL" -> (
|
| "NIL" -> (
|
||||||
let%bind ty' = Mini_c.get_t_list ty in
|
let%bind ty' = Mini_c.get_t_list ty in
|
||||||
@ -380,6 +380,36 @@ and translate_expression ?push_var_name (expr:expression) (env:environment) : (m
|
|||||||
]) in
|
]) in
|
||||||
return code
|
return code
|
||||||
)
|
)
|
||||||
|
| E_iterator (name , (v , body) , expr) -> (
|
||||||
|
let%bind (expr' , expr_env) = translate_expression ~push_var_name:"iter_expr" expr env in
|
||||||
|
let%bind popped = Compiler_environment.pop expr_env in
|
||||||
|
let%bind env' = ok @@ Environment.add v popped in
|
||||||
|
let%bind (body' , body_env) = translate_expression ~push_var_name:"iter_body" body env' in
|
||||||
|
match name with
|
||||||
|
| "ITER" -> (
|
||||||
|
let%bind restrict =
|
||||||
|
Compiler_environment.select_env body_env popped in
|
||||||
|
let%bind code = ok (seq [
|
||||||
|
expr' ;
|
||||||
|
i_iter (seq [body' ; restrict]) ;
|
||||||
|
]) in
|
||||||
|
return ~end_env:popped code
|
||||||
|
)
|
||||||
|
| "MAP" -> (
|
||||||
|
let%bind restrict =
|
||||||
|
let%bind popped = Compiler_environment.pop body_env in
|
||||||
|
Compiler_environment.select_env popped env in
|
||||||
|
let%bind code = ok (seq [
|
||||||
|
expr' ;
|
||||||
|
i_map (seq [body' ; restrict]) ;
|
||||||
|
]) in
|
||||||
|
return code
|
||||||
|
)
|
||||||
|
| s -> (
|
||||||
|
let error = error (thunk "bad iterator") (thunk s) in
|
||||||
|
fail error
|
||||||
|
)
|
||||||
|
)
|
||||||
| E_assignment (name , lrs , expr) -> (
|
| E_assignment (name , lrs , expr) -> (
|
||||||
let%bind (expr' , env') = translate_expression ~push_var_name:"assignment_expr" expr env in
|
let%bind (expr' , env') = translate_expression ~push_var_name:"assignment_expr" expr env in
|
||||||
let%bind get_code = Compiler_environment.get env' name in
|
let%bind get_code = Compiler_environment.get env' name in
|
||||||
|
@ -17,3 +17,13 @@ const bl : foobar = list
|
|||||||
120 ;
|
120 ;
|
||||||
421 ;
|
421 ;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function iter_op (const s : list(int)) : int is
|
||||||
|
var r : int := 0 ;
|
||||||
|
function aggregate (const i : int) : unit is
|
||||||
|
begin
|
||||||
|
r := r + i ;
|
||||||
|
end with unit
|
||||||
|
begin
|
||||||
|
list_iter(s , aggregate) ;
|
||||||
|
end with r
|
||||||
|
@ -1,3 +1,13 @@
|
|||||||
|
function iter_op (const s : set(int)) : int is
|
||||||
|
var r : int := 0 ;
|
||||||
|
function aggregate (const i : int) : unit is
|
||||||
|
begin
|
||||||
|
r := r + i ;
|
||||||
|
end with unit
|
||||||
|
begin
|
||||||
|
set_iter(s , aggregate) ;
|
||||||
|
end with r
|
||||||
|
|
||||||
const s_e : set(string) = (set_empty : set(string))
|
const s_e : set(string) = (set_empty : set(string))
|
||||||
|
|
||||||
const s_fb : set(string) = set [
|
const s_fb : set(string) = set [
|
||||||
@ -13,3 +23,4 @@ function remove_op (const s : set(string)) : set(string) is
|
|||||||
|
|
||||||
function mem_op (const s : set(string)) : bool is
|
function mem_op (const s : set(string)) : bool is
|
||||||
begin skip end with set_mem("foobar" , s)
|
begin skip end with set_mem("foobar" , s)
|
||||||
|
|
||||||
|
@ -86,6 +86,8 @@ and expression' ppf (e:expression') = match e with
|
|||||||
| E_sequence (a , b) -> fprintf ppf "%a ;; %a" expression a expression b
|
| E_sequence (a , b) -> fprintf ppf "%a ;; %a" expression a expression b
|
||||||
| E_let_in ((name , _) , expr , body) ->
|
| E_let_in ((name , _) , expr , body) ->
|
||||||
fprintf ppf "let %s = %a in ( %a )" name expression expr expression body
|
fprintf ppf "let %s = %a in ( %a )" name expression expr expression body
|
||||||
|
| E_iterator (s , ((name , _) , body) , expr) ->
|
||||||
|
fprintf ppf "for_%s %s of %a do ( %a )" s name expression expr expression body
|
||||||
| E_assignment (r , path , e) ->
|
| E_assignment (r , path , e) ->
|
||||||
fprintf ppf "%s.%a := %a" r (list_sep lr (const ".")) path expression e
|
fprintf ppf "%s.%a := %a" r (list_sep lr (const ".")) path expression e
|
||||||
| E_while (e , b) ->
|
| E_while (e , b) ->
|
||||||
|
@ -69,6 +69,7 @@ and expression' =
|
|||||||
| E_make_empty_list of type_value
|
| E_make_empty_list of type_value
|
||||||
| E_make_empty_set of type_value
|
| E_make_empty_set of type_value
|
||||||
| E_make_none of type_value
|
| E_make_none of type_value
|
||||||
|
| E_iterator of (string * ((var_name * type_value) * expression) * expression)
|
||||||
| E_if_bool of expression * expression * expression
|
| E_if_bool of expression * expression * expression
|
||||||
| E_if_none of expression * expression * ((var_name * type_value) * expression)
|
| E_if_none of expression * expression * ((var_name * type_value) * expression)
|
||||||
| E_if_left of expression * ((var_name * type_value) * expression) * ((var_name * type_value) * expression)
|
| E_if_left of expression * ((var_name * type_value) * expression) * ((var_name * type_value) * expression)
|
||||||
|
@ -79,6 +79,7 @@ module Simplify = struct
|
|||||||
("set_add" , "SET_ADD") ;
|
("set_add" , "SET_ADD") ;
|
||||||
("set_remove" , "SET_REMOVE") ;
|
("set_remove" , "SET_REMOVE") ;
|
||||||
("set_iter" , "SET_ITER") ;
|
("set_iter" , "SET_ITER") ;
|
||||||
|
("list_iter" , "LIST_ITER") ;
|
||||||
]
|
]
|
||||||
|
|
||||||
let type_constants = type_constants
|
let type_constants = type_constants
|
||||||
@ -585,6 +586,8 @@ module Typer = struct
|
|||||||
set_mem ;
|
set_mem ;
|
||||||
set_add ;
|
set_add ;
|
||||||
set_remove ;
|
set_remove ;
|
||||||
|
set_iter ;
|
||||||
|
list_iter ;
|
||||||
int ;
|
int ;
|
||||||
size ;
|
size ;
|
||||||
failwith_ ;
|
failwith_ ;
|
||||||
|
@ -135,7 +135,7 @@ module Errors = struct
|
|||||||
let unsupported_for_loops region =
|
let unsupported_for_loops region =
|
||||||
let title () = "bounded iterators" in
|
let title () = "bounded iterators" in
|
||||||
let message () =
|
let message () =
|
||||||
Format.asprintf "for loops are not supported yet" in
|
Format.asprintf "only simple for loops are supported yet" in
|
||||||
let data = [
|
let data = [
|
||||||
("loop_loc",
|
("loop_loc",
|
||||||
fun () -> Format.asprintf "%a" Location.pp_lift @@ region)
|
fun () -> Format.asprintf "%a" Location.pp_lift @@ region)
|
||||||
@ -744,8 +744,19 @@ and simpl_statement : Raw.statement -> (_ -> expression result) result =
|
|||||||
and simpl_single_instruction : Raw.single_instr -> (_ -> expression result) result =
|
and simpl_single_instruction : Raw.single_instr -> (_ -> expression result) result =
|
||||||
fun t ->
|
fun t ->
|
||||||
match t with
|
match t with
|
||||||
| ProcCall call ->
|
| ProcCall x -> (
|
||||||
fail @@ unsupported_proc_calls call
|
let ((name, args) , loc) = r_split x in
|
||||||
|
let (f , f_loc) = r_split name in
|
||||||
|
let (args , args_loc) = r_split args in
|
||||||
|
let args' = npseq_to_list args.inside in
|
||||||
|
match List.assoc_opt f constants with
|
||||||
|
| None ->
|
||||||
|
let%bind arg = simpl_tuple_expression ~loc:args_loc args' in
|
||||||
|
return @@ e_application ~loc (e_variable ~loc:f_loc f) arg
|
||||||
|
| Some s ->
|
||||||
|
let%bind lst = bind_map_list simpl_expression args' in
|
||||||
|
return @@ e_constant ~loc s lst
|
||||||
|
)
|
||||||
| Fail e -> (
|
| Fail e -> (
|
||||||
let%bind expr = simpl_expression e.value.fail_expr in
|
let%bind expr = simpl_expression e.value.fail_expr in
|
||||||
return @@ e_failwith expr
|
return @@ e_failwith expr
|
||||||
@ -760,6 +771,12 @@ and simpl_single_instruction : Raw.single_instr -> (_ -> expression result) resu
|
|||||||
let%bind body = simpl_block l.block.value in
|
let%bind body = simpl_block l.block.value in
|
||||||
let%bind body = body None in
|
let%bind body = body None in
|
||||||
return @@ e_loop cond body
|
return @@ e_loop cond body
|
||||||
|
(* | Loop (For (ForCollect x)) -> (
|
||||||
|
* let (x' , loc) = r_split x in
|
||||||
|
* let%bind expr = simpl_expression x'.expr in
|
||||||
|
* let%bind body = simpl_block x'.block.value in
|
||||||
|
* ok _
|
||||||
|
* ) *)
|
||||||
| Loop (For (ForInt {region; _} | ForCollect {region ; _})) ->
|
| Loop (For (ForInt {region; _} | ForCollect {region ; _})) ->
|
||||||
fail @@ unsupported_for_loops region
|
fail @@ unsupported_for_loops region
|
||||||
| Cond c -> (
|
| Cond c -> (
|
||||||
|
@ -185,6 +185,10 @@ let set_arithmetic () : unit result =
|
|||||||
expect_eq program "mem_op"
|
expect_eq program "mem_op"
|
||||||
(e_set [e_string "foo" ; e_string "bar"])
|
(e_set [e_string "foo" ; e_string "bar"])
|
||||||
(e_bool false) in
|
(e_bool false) in
|
||||||
|
let%bind () =
|
||||||
|
expect_eq program "iter_op"
|
||||||
|
(e_set [e_int 2 ; e_int 4 ; e_int 7])
|
||||||
|
(e_int 13) in
|
||||||
ok ()
|
ok ()
|
||||||
|
|
||||||
let unit_expression () : unit result =
|
let unit_expression () : unit result =
|
||||||
@ -365,6 +369,10 @@ let list () : unit result =
|
|||||||
let expected = ez [144 ; 51 ; 42 ; 120 ; 421] in
|
let expected = ez [144 ; 51 ; 42 ; 120 ; 421] in
|
||||||
expect_eq_evaluate program "bl" expected
|
expect_eq_evaluate program "bl" expected
|
||||||
in
|
in
|
||||||
|
let%bind () =
|
||||||
|
expect_eq program "iter_op"
|
||||||
|
(e_list [e_int 2 ; e_int 4 ; e_int 7])
|
||||||
|
(e_int 13) in
|
||||||
ok ()
|
ok ()
|
||||||
|
|
||||||
let condition () : unit result =
|
let condition () : unit result =
|
||||||
|
@ -32,11 +32,21 @@ them. please report this to the developers." in
|
|||||||
let content () = name in
|
let content () = name in
|
||||||
error title content
|
error title content
|
||||||
|
|
||||||
|
let row_loc l = ("location" , fun () -> Format.asprintf "%a" Location.pp l)
|
||||||
|
|
||||||
let unsupported_pattern_matching kind location =
|
let unsupported_pattern_matching kind location =
|
||||||
let title () = "unsupported pattern-matching" in
|
let title () = "unsupported pattern-matching" in
|
||||||
let content () = Format.asprintf "%s patterns aren't supported yet" kind in
|
let content () = Format.asprintf "%s patterns aren't supported yet" kind in
|
||||||
let data = [
|
let data = [
|
||||||
("location" , fun () -> Format.asprintf "%a" Location.pp location) ;
|
row_loc location ;
|
||||||
|
] in
|
||||||
|
error ~data title content
|
||||||
|
|
||||||
|
let unsupported_iterator location =
|
||||||
|
let title () = "unsupported iterator" in
|
||||||
|
let content () = "only lambda are supported as iterators" in
|
||||||
|
let data = [
|
||||||
|
row_loc location ;
|
||||||
] in
|
] in
|
||||||
error ~data title content
|
error ~data title content
|
||||||
|
|
||||||
@ -342,14 +352,49 @@ and translate_annotated_expression (ae:AST.annotated_expression) : expression re
|
|||||||
let expr = List.fold_left aux record' path in
|
let expr = List.fold_left aux record' path in
|
||||||
ok expr
|
ok expr
|
||||||
| E_constant (name , lst) -> (
|
| E_constant (name , lst) -> (
|
||||||
|
let (iter , map) =
|
||||||
|
let iterator name = fun (lst : AST.annotated_expression list) -> match lst with
|
||||||
|
| [i ; f] -> (
|
||||||
|
let%bind f' = match f.expression with
|
||||||
|
| E_lambda l -> (
|
||||||
|
let%bind body' = translate_annotated_expression l.result in
|
||||||
|
let%bind input' = translate_type l.input_type in
|
||||||
|
ok ((l.binder , input') , body')
|
||||||
|
)
|
||||||
|
| E_variable v -> (
|
||||||
|
let%bind elt =
|
||||||
|
trace_option (corner_case ~loc:__LOC__ "missing var") @@
|
||||||
|
AST.Environment.get_opt v f.environment in
|
||||||
|
match elt.definition with
|
||||||
|
| ED_declaration (f , _) -> (
|
||||||
|
match f.expression with
|
||||||
|
| E_lambda l -> (
|
||||||
|
let%bind body' = translate_annotated_expression l.result in
|
||||||
|
let%bind input' = translate_type l.input_type in
|
||||||
|
ok ((l.binder , input') , body')
|
||||||
|
)
|
||||||
|
| _ -> fail @@ unsupported_iterator f.location
|
||||||
|
)
|
||||||
|
| _ -> fail @@ unsupported_iterator f.location
|
||||||
|
)
|
||||||
|
| _ -> fail @@ unsupported_iterator f.location
|
||||||
|
in
|
||||||
|
let%bind i' = translate_annotated_expression i in
|
||||||
|
return @@ E_iterator (name , f' , i')
|
||||||
|
)
|
||||||
|
| _ -> fail @@ corner_case ~loc:__LOC__ "bad iterator arity"
|
||||||
|
in
|
||||||
|
iterator "ITER" , iterator "MAP" in
|
||||||
|
match (name , lst) with
|
||||||
|
| ("SET_ITER" , lst) -> iter lst
|
||||||
|
| ("LIST_ITER" , lst) -> iter lst
|
||||||
|
| ("MAP_ITER" , lst) -> iter lst
|
||||||
|
| ("LIST_MAP" , lst) -> map lst
|
||||||
|
| ("MAP_MAP" , lst) -> map lst
|
||||||
|
| _ -> (
|
||||||
let%bind lst' = bind_map_list (translate_annotated_expression) lst in
|
let%bind lst' = bind_map_list (translate_annotated_expression) lst in
|
||||||
match name, lst with
|
return @@ E_constant (name , lst')
|
||||||
| "NONE", [] ->
|
)
|
||||||
let%bind o =
|
|
||||||
trace_strong (corner_case ~loc:__LOC__ "not an option") @@
|
|
||||||
Mini_c.Combinators.get_t_option tv in
|
|
||||||
return @@ E_make_none o
|
|
||||||
| _ -> return @@ E_constant (name, lst')
|
|
||||||
)
|
)
|
||||||
| E_lambda l ->
|
| E_lambda l ->
|
||||||
let%bind env =
|
let%bind env =
|
||||||
|
@ -48,6 +48,8 @@ let i_push_string str = i_push t_string (string str)
|
|||||||
let i_none ty = prim ~children:[ty] I_NONE
|
let i_none ty = prim ~children:[ty] I_NONE
|
||||||
let i_nil ty = prim ~children:[ty] I_NIL
|
let i_nil ty = prim ~children:[ty] I_NIL
|
||||||
let i_empty_set ty = prim ~children:[ty] I_EMPTY_SET
|
let i_empty_set ty = prim ~children:[ty] I_EMPTY_SET
|
||||||
|
let i_iter body = prim ~children:[body] I_ITER
|
||||||
|
let i_map body = prim ~children:[body] I_MAP
|
||||||
let i_some = prim I_SOME
|
let i_some = prim I_SOME
|
||||||
let i_lambda arg ret body = prim ~children:[arg;ret;body] I_LAMBDA
|
let i_lambda arg ret body = prim ~children:[arg;ret;body] I_LAMBDA
|
||||||
let i_empty_map src dst = prim ~children:[src;dst] I_EMPTY_MAP
|
let i_empty_map src dst = prim ~children:[src;dst] I_EMPTY_MAP
|
||||||
|
Loading…
Reference in New Issue
Block a user