2019-05-13 00:56:22 +04:00
|
|
|
open Trace
|
|
|
|
open Function
|
|
|
|
module I = Parser.Camligo.Ast
|
|
|
|
module O = Ast_simplified
|
|
|
|
open O.Combinators
|
|
|
|
|
|
|
|
let unwrap : type a . a Location.wrap -> a = Location.unwrap
|
|
|
|
|
|
|
|
let type_constants = Operators.Simplify.type_constants
|
|
|
|
let constants = Operators.Simplify.Camligo.constants
|
|
|
|
|
|
|
|
let type_variable : string -> O.type_expression result = fun str ->
|
|
|
|
match List.assoc_opt str type_constants with
|
|
|
|
| Some 0 -> ok @@ O.T_constant (str, [])
|
|
|
|
| Some _ -> simple_fail "non-nullary type constructor"
|
|
|
|
| None -> ok @@ O.T_variable str
|
|
|
|
|
|
|
|
let get_param_restricted_pattern : I.param -> I.restricted_pattern Location.wrap result = fun p ->
|
|
|
|
match p with
|
|
|
|
| I.Param_restricted_pattern c -> ok c
|
|
|
|
| _ ->
|
|
|
|
let error =
|
|
|
|
let title () = "not a restricted param pattern" in
|
|
|
|
let content () = Format.asprintf "%a" I.pp_param p in
|
|
|
|
error title content in
|
|
|
|
fail error
|
|
|
|
|
|
|
|
let get_unrestricted_pattern : I.restricted_pattern -> I.pattern Location.wrap result = fun rp ->
|
|
|
|
match rp with
|
|
|
|
| I.Pr_restrict p -> ok p
|
|
|
|
| _ ->
|
|
|
|
let error =
|
|
|
|
let title () = "not an unrestricted param pattern" in
|
|
|
|
let content () = Format.asprintf "%a" I.pp_restricted_pattern rp in
|
|
|
|
error title content in
|
|
|
|
fail error
|
|
|
|
|
|
|
|
let get_p_type_annotation : I.pattern -> (I.pattern Location.wrap * I.restricted_type_expression Location.wrap) result = fun p ->
|
|
|
|
match p with
|
|
|
|
| I.P_type_annotation pta -> ok pta
|
|
|
|
| _ -> simple_fail "not a pattern type annotation"
|
|
|
|
|
|
|
|
let get_p_variable : I.pattern -> string Location.wrap result = fun p ->
|
|
|
|
match p with
|
|
|
|
| I.P_variable v -> ok v
|
|
|
|
| _ -> simple_fail "not a pattern variable"
|
|
|
|
|
2019-05-22 04:46:54 +04:00
|
|
|
let get_p_option_typed_variable : I.pattern -> (string Location.wrap * I.restricted_type_expression Location.wrap option) result = fun p ->
|
|
|
|
match p with
|
|
|
|
| I.P_variable v -> ok (v , None)
|
|
|
|
| I.P_type_annotation (pat , rte) -> (
|
|
|
|
let%bind v = get_p_variable @@ unwrap pat in
|
|
|
|
ok (v , Some rte)
|
|
|
|
)
|
|
|
|
| _ -> simple_fail "not an optionally typed pattern variable"
|
|
|
|
|
2019-05-13 00:56:22 +04:00
|
|
|
let get_p_typed_variable : I.pattern -> (string Location.wrap * I.restricted_type_expression Location.wrap) result = fun p ->
|
|
|
|
let%bind (p' , rte) =
|
|
|
|
trace (simple_error "get_p_typed_variable") @@
|
|
|
|
get_p_type_annotation p in
|
|
|
|
let%bind var = get_p_variable (unwrap p') in
|
|
|
|
ok (var , rte)
|
|
|
|
|
|
|
|
let get_eh_accessor : _ -> _ result = fun x ->
|
|
|
|
match x with
|
|
|
|
| I.Eh_accessor x -> ok x
|
|
|
|
| _ -> simple_fail "not a simple eh_accessor"
|
|
|
|
|
|
|
|
let get_typed_variable_param : I.param -> _ result = fun arg ->
|
|
|
|
let%bind up =
|
|
|
|
let%bind rp = get_param_restricted_pattern arg in
|
|
|
|
let%bind up = get_unrestricted_pattern (unwrap rp) in
|
|
|
|
ok up in
|
|
|
|
let%bind (var , rte) = get_p_typed_variable (unwrap up) in
|
|
|
|
ok (var , rte)
|
|
|
|
|
|
|
|
let get_untyped_variable_param : I.param -> _ result = fun arg ->
|
|
|
|
let%bind rp = get_param_restricted_pattern arg in
|
|
|
|
let%bind var = match (unwrap rp) with
|
|
|
|
| I.Pr_variable v -> ok v
|
|
|
|
| _ -> simple_fail "a regular variable was expected" in
|
|
|
|
ok var
|
|
|
|
|
|
|
|
let get_type_annotation_ : I.type_annotation_ -> I.type_expression Location.wrap result = fun p ->
|
|
|
|
match p with
|
|
|
|
| I.Type_annotation_ p -> ok p
|
|
|
|
|
|
|
|
let get_e_match_clause : I.e_match_clause -> (I.pattern Location.wrap * I.expression_no_match Location.wrap) result = fun e ->
|
|
|
|
match e with
|
|
|
|
| E_match_clause c -> ok c
|
|
|
|
|
|
|
|
let match_clauses : type a . (I.pattern * a) list -> a O.matching result = fun _clauses ->
|
|
|
|
let match_bool _ = simple_fail "" in
|
|
|
|
let match_stuff _ = simple_fail "" in
|
|
|
|
bind_find_map_list (simple_error "no weird matching yet") (fun f -> f ()) [ match_bool ; match_stuff ]
|
|
|
|
|
|
|
|
let rec of_no_match : I.expression_no_match -> I.expression = fun enm ->
|
|
|
|
let open I in
|
|
|
|
let self = Location.map of_no_match in
|
|
|
|
match enm with
|
|
|
|
| Em_let_in (a, b, c) -> E_let_in (a , self b , self c)
|
|
|
|
| Em_fun (a , b) -> E_fun (a , self b)
|
|
|
|
| Em_record r -> E_record r
|
|
|
|
| Em_ifthenelse (a , b , c) -> E_ifthenelse (self a , self b , self c)
|
|
|
|
| Em_ifthen (a , b) -> E_ifthen (self a , self b)
|
|
|
|
| Em_main m -> E_main m
|
|
|
|
|
|
|
|
let rec of_no_seq : I.expression_no_seq -> I.expression = fun enm ->
|
|
|
|
let open I in
|
|
|
|
let self = Location.map of_no_seq in
|
|
|
|
match enm with
|
|
|
|
| Es_let_in (a, b, c) -> E_let_in (a , self b , self c)
|
|
|
|
| Es_fun (a , b) -> E_fun (a , self b)
|
|
|
|
| Es_record r -> E_record r
|
|
|
|
| Es_ifthenelse (a , b , c) -> E_ifthenelse (self a , self b , self c)
|
|
|
|
| Es_ifthen (a , b) -> E_ifthen (self a , self b)
|
|
|
|
| Es_match (a , b) -> E_match (self a , b)
|
|
|
|
| Es_main m -> E_main m
|
|
|
|
|
|
|
|
let rec type_expression : I.type_expression -> O.type_expression result = fun te ->
|
|
|
|
match te with
|
|
|
|
| T_variable tv ->
|
|
|
|
let%bind tv' = bind_map_location type_variable tv in
|
|
|
|
ok @@ unwrap tv'
|
|
|
|
| T_tuple lst ->
|
|
|
|
let%bind lst' = bind_map_list (bind_map_location type_expression) lst in
|
|
|
|
ok @@ O.T_tuple (List.map unwrap lst')
|
|
|
|
| T_paren p ->
|
|
|
|
let%bind p' = bind_map_location type_expression p in
|
|
|
|
ok @@ unwrap p'
|
|
|
|
| T_record r ->
|
|
|
|
let aux : I.t_record_element -> _ = fun (T_record_element (s, te)) ->
|
|
|
|
let%bind te' = bind_map_location type_expression te in
|
|
|
|
ok (s, te')
|
|
|
|
in
|
|
|
|
let%bind r' = bind_map_list (bind_map_location aux) r in
|
|
|
|
let te_map =
|
|
|
|
let lst = List.map ((fun (x, y) -> unwrap x, unwrap y) >| unwrap) r' in
|
|
|
|
let open Map.String in
|
|
|
|
List.fold_left (fun prec (k , v) -> add k v prec) empty lst
|
|
|
|
in
|
|
|
|
ok @@ O.T_record te_map
|
|
|
|
| T_application (arg , f) ->
|
|
|
|
let%bind arg' = bind_map_location type_expression arg in
|
|
|
|
match unwrap f with
|
|
|
|
| I.T_variable v -> (
|
|
|
|
match List.assoc_opt v.wrap_content type_constants with
|
|
|
|
| Some n -> (
|
|
|
|
let error expected got =
|
|
|
|
let title () = "bad arity" in
|
|
|
|
let content () = Format.asprintf "Expected: %d. Got: %d." expected got in
|
|
|
|
error title content in
|
|
|
|
match arg'.wrap_content with
|
|
|
|
| T_tuple lst -> (
|
|
|
|
let%bind () =
|
|
|
|
trace (error n (List.length lst)) @@
|
|
|
|
Assert.assert_list_size lst n in
|
|
|
|
ok @@ O.T_constant (v.wrap_content , lst)
|
|
|
|
)
|
|
|
|
| e -> ok @@ O.T_constant ((unwrap v) , [ e ])
|
|
|
|
)
|
|
|
|
| None -> (
|
|
|
|
let error =
|
|
|
|
let title () = "unrecognized type-constant" in
|
|
|
|
let content () = Format.asprintf "%s" v.wrap_content in
|
|
|
|
error title content
|
|
|
|
in
|
|
|
|
fail error
|
|
|
|
)
|
|
|
|
)
|
|
|
|
| _ -> simple_fail "type applying to non-var"
|
|
|
|
|
|
|
|
let rec of_restricted_type_expression : I.restricted_type_expression -> I.type_expression = fun rte ->
|
|
|
|
let self = of_restricted_type_expression in
|
|
|
|
match rte with
|
|
|
|
| Tr_variable tv -> T_variable tv
|
|
|
|
| Tr_application (a , b) -> T_application (Location.map self a , Location.map self b)
|
|
|
|
| Tr_paren te -> unwrap te
|
|
|
|
|
|
|
|
let restricted_type_expression : I.restricted_type_expression -> O.type_expression result =
|
|
|
|
Function.compose type_expression of_restricted_type_expression
|
|
|
|
|
2019-05-23 10:22:58 +04:00
|
|
|
let rec expression : I.expression -> O.expression result = fun e ->
|
2019-05-13 00:56:22 +04:00
|
|
|
match e with
|
2019-05-22 04:46:54 +04:00
|
|
|
| I.E_sequence lst -> (
|
|
|
|
let%bind lst' = bind_map_list expression @@ List.map unwrap lst in
|
|
|
|
match lst' with
|
|
|
|
| [] -> simple_fail "empty sequence"
|
2019-05-23 10:22:58 +04:00
|
|
|
| hd :: tl -> ok @@ List.fold_right' (fun prec cur -> e_sequence prec cur) hd tl
|
2019-05-22 04:46:54 +04:00
|
|
|
)
|
|
|
|
| I.E_let_in (pattern , expr , body) -> (
|
|
|
|
let%bind (name , rte) = get_p_option_typed_variable @@ unwrap pattern in
|
|
|
|
let%bind type_expression' = bind_map_option (fun x -> restricted_type_expression @@ unwrap x) rte in
|
|
|
|
let%bind expr' = expression @@ unwrap expr in
|
|
|
|
let%bind body' = expression @@ unwrap body in
|
2019-05-23 10:22:58 +04:00
|
|
|
ok @@ e_let_in (unwrap name , type_expression') expr' body'
|
2019-05-22 04:46:54 +04:00
|
|
|
)
|
2019-05-13 00:56:22 +04:00
|
|
|
| I.E_ifthenelse ite -> ifthenelse ite
|
|
|
|
| I.E_ifthen it -> ifthen it
|
|
|
|
| I.E_match m -> match_ m
|
|
|
|
| I.E_record r -> record r
|
2019-05-22 04:46:54 +04:00
|
|
|
| I.E_fun (pattern , expr) -> (
|
|
|
|
let%bind (name , rte) = get_p_typed_variable @@ unwrap pattern in
|
|
|
|
let name' = unwrap name in
|
|
|
|
let%bind type_expression' = restricted_type_expression (unwrap rte) in
|
|
|
|
let%bind expr' = expression (unwrap expr) in
|
2019-05-23 10:22:58 +04:00
|
|
|
ok @@ e_lambda name'
|
|
|
|
(Some type_expression') None
|
|
|
|
expr'
|
2019-05-13 00:56:22 +04:00
|
|
|
)
|
2019-05-22 04:46:54 +04:00
|
|
|
| I.E_main m -> expression_main m
|
2019-05-13 00:56:22 +04:00
|
|
|
|
|
|
|
and ifthenelse
|
2019-05-23 10:22:58 +04:00
|
|
|
: (I.expression Location.wrap * I.expression Location.wrap * I.expression Location.wrap) -> O.expression result
|
2019-05-13 00:56:22 +04:00
|
|
|
= fun ite ->
|
|
|
|
let (cond , branch_true , branch_false) = ite in
|
|
|
|
let%bind cond' = bind_map_location expression cond in
|
|
|
|
let%bind branch_true' = bind_map_location expression branch_true in
|
|
|
|
let%bind branch_false' = bind_map_location expression branch_false in
|
2019-05-23 10:22:58 +04:00
|
|
|
ok @@ O.(e_match_bool (unwrap cond') (unwrap branch_true') (unwrap branch_false'))
|
2019-05-13 00:56:22 +04:00
|
|
|
|
|
|
|
and ifthen
|
2019-05-23 10:22:58 +04:00
|
|
|
: (I.expression Location.wrap * I.expression Location.wrap) -> O.expression result
|
2019-05-13 00:56:22 +04:00
|
|
|
= fun it ->
|
|
|
|
let (cond , branch_true) = it in
|
|
|
|
let%bind cond' = bind_map_location expression cond in
|
|
|
|
let%bind branch_true' = bind_map_location expression branch_true in
|
2019-05-23 10:22:58 +04:00
|
|
|
ok @@ O.(e_match_bool (unwrap cond') (unwrap branch_true') (e_unit ()))
|
2019-05-13 00:56:22 +04:00
|
|
|
|
|
|
|
and match_
|
2019-05-23 10:22:58 +04:00
|
|
|
: I.expression Location.wrap * I.e_match_clause Location.wrap list -> O.expression result
|
2019-05-13 00:56:22 +04:00
|
|
|
= fun m ->
|
|
|
|
let (expr , clauses) = m in
|
|
|
|
let%bind expr' = expression (unwrap expr) in
|
|
|
|
let%bind clauses' =
|
|
|
|
let%bind clauses =
|
|
|
|
bind_map_list get_e_match_clause
|
|
|
|
@@ List.map unwrap clauses in
|
|
|
|
let aux (x , y) =
|
|
|
|
let x' = unwrap x in
|
|
|
|
let%bind y' = expression @@ of_no_match @@ unwrap y in
|
|
|
|
ok (x' , y') in
|
|
|
|
bind_map_list aux clauses in
|
|
|
|
let%bind matching = match_clauses clauses' in
|
2019-05-23 10:22:58 +04:00
|
|
|
ok O.(e_match expr' matching)
|
2019-05-13 00:56:22 +04:00
|
|
|
|
|
|
|
and record
|
|
|
|
= fun r ->
|
|
|
|
let aux : I.e_record_element -> _ = fun re ->
|
|
|
|
match re with
|
|
|
|
| E_record_element_record_implicit _ -> simple_fail "no implicit record element yet"
|
|
|
|
| E_record_element_record_explicit (s, e) ->
|
|
|
|
let%bind e' = bind_map_location (Function.compose expression of_no_seq) e in
|
|
|
|
ok (s, e')
|
|
|
|
in
|
|
|
|
let%bind r' = bind_map_list (bind_map_location aux) r in
|
|
|
|
let lst = List.map ((fun (x, y) -> unwrap x, unwrap y) >| unwrap) r' in
|
2019-05-23 10:22:58 +04:00
|
|
|
ok @@ O.(e_record lst)
|
2019-05-13 00:56:22 +04:00
|
|
|
|
2019-05-23 10:22:58 +04:00
|
|
|
and expression_main : I.expression_main Location.wrap -> O.expression result = fun em ->
|
|
|
|
let return x = ok @@ x in
|
2019-05-13 00:56:22 +04:00
|
|
|
let simple_binop name ab =
|
|
|
|
let%bind (a' , b') = bind_map_pair expression_main ab in
|
2019-05-23 10:22:58 +04:00
|
|
|
return @@ e_binop name a' b' in
|
2019-05-13 00:56:22 +04:00
|
|
|
let error_main =
|
|
|
|
let title () = "simplifying main_expression" in
|
|
|
|
let content () = Format.asprintf "%a" I.pp_expression_main (unwrap em) in
|
|
|
|
error title content
|
|
|
|
in
|
|
|
|
trace error_main @@
|
|
|
|
match (unwrap em) with
|
|
|
|
| Eh_tuple lst ->
|
|
|
|
let%bind lst' = bind_map_list expression_main lst in
|
2019-05-23 10:22:58 +04:00
|
|
|
return @@ e_tuple lst'
|
2019-05-13 00:56:22 +04:00
|
|
|
| Eh_module_ident (lst , v) -> identifier_application (lst , v) None
|
|
|
|
| Eh_variable v -> identifier_application ([] , v) None
|
|
|
|
| Eh_application (f , arg) -> (
|
|
|
|
let%bind arg' = expression_main arg in
|
|
|
|
match unwrap f with
|
|
|
|
| Eh_variable v -> identifier_application ([] , v) (Some arg')
|
|
|
|
| Eh_module_ident (lst , v) -> identifier_application (lst , v) (Some arg')
|
|
|
|
| _ -> (
|
|
|
|
let%bind f' = expression_main f in
|
2019-05-23 10:22:58 +04:00
|
|
|
return @@ e_application f' arg'
|
2019-05-13 00:56:22 +04:00
|
|
|
)
|
|
|
|
)
|
2019-05-23 10:22:58 +04:00
|
|
|
| Eh_type_annotation (e, te) -> (
|
|
|
|
let%bind e' = expression_main e in
|
2019-05-13 00:56:22 +04:00
|
|
|
let%bind te' = bind_map_location restricted_type_expression te in
|
2019-05-23 10:22:58 +04:00
|
|
|
ok @@ e_annotation e' (unwrap te')
|
|
|
|
)
|
2019-05-13 00:56:22 +04:00
|
|
|
| Eh_lt ab ->
|
|
|
|
simple_binop "LT" ab
|
|
|
|
| Eh_gt ab ->
|
|
|
|
simple_binop "GT" ab
|
|
|
|
| Eh_le ab ->
|
|
|
|
simple_binop "LE" ab
|
|
|
|
| Eh_eq ab ->
|
|
|
|
simple_binop "EQ" ab
|
|
|
|
| Eh_neq ab ->
|
|
|
|
simple_binop "NEQ" ab
|
|
|
|
| Eh_cons ab ->
|
|
|
|
simple_binop "CONS" ab
|
|
|
|
| Eh_addition ab ->
|
|
|
|
simple_binop "ADD" ab
|
|
|
|
| Eh_substraction ab ->
|
|
|
|
simple_binop "MINUS" ab
|
|
|
|
| Eh_multiplication ab ->
|
|
|
|
simple_binop "TIMES" ab
|
|
|
|
| Eh_division ab ->
|
|
|
|
simple_binop "DIV" ab
|
|
|
|
| Eh_int n ->
|
2019-05-23 10:22:58 +04:00
|
|
|
return @@ e_int (unwrap n)
|
2019-05-13 00:56:22 +04:00
|
|
|
| Eh_string s ->
|
2019-05-23 10:22:58 +04:00
|
|
|
return @@ e_string (unwrap s)
|
2019-05-13 00:56:22 +04:00
|
|
|
| Eh_unit _ ->
|
2019-05-23 10:22:58 +04:00
|
|
|
return @@ e_unit ()
|
2019-05-13 00:56:22 +04:00
|
|
|
| Eh_tz n ->
|
2019-05-23 10:22:58 +04:00
|
|
|
return @@ e_tez (unwrap n)
|
2019-05-13 00:56:22 +04:00
|
|
|
| Eh_constructor _ ->
|
|
|
|
simple_fail "constructor without parameter"
|
|
|
|
| Eh_data_structure (kind , content) -> (
|
|
|
|
match unwrap kind with
|
|
|
|
| "list" -> (
|
|
|
|
let%bind lst = bind_map_list expression_main content in
|
2019-05-23 10:22:58 +04:00
|
|
|
ok @@ e_list lst
|
2019-05-13 00:56:22 +04:00
|
|
|
)
|
|
|
|
| kind' -> (
|
|
|
|
let error =
|
|
|
|
let title () = "data-structures not supported yet" in
|
|
|
|
let content () = Format.asprintf "%s" kind' in
|
|
|
|
error title content in
|
|
|
|
fail error
|
|
|
|
)
|
|
|
|
)
|
|
|
|
| Eh_name _ ->
|
|
|
|
simple_fail "named parameter not supported yet"
|
|
|
|
| Eh_assign x ->
|
|
|
|
simple_binop "ASSIGN" x
|
|
|
|
| Eh_accessor (src , path) ->
|
2019-05-23 10:22:58 +04:00
|
|
|
ok @@ O.(e_accessor_props (e_variable (unwrap src)) (List.map unwrap path))
|
2019-05-13 00:56:22 +04:00
|
|
|
| Eh_bottom e ->
|
|
|
|
expression (unwrap e)
|
|
|
|
|
2019-05-23 10:22:58 +04:00
|
|
|
and identifier_application : (string Location.wrap) list * string Location.wrap -> O.expression option -> _ result = fun (lst , v) param_opt ->
|
2019-05-13 00:56:22 +04:00
|
|
|
let constant_name = String.concat "." ((List.map unwrap lst) @ [unwrap v]) in
|
|
|
|
match List.assoc_opt constant_name constants , param_opt with
|
|
|
|
| Some 0 , None ->
|
2019-05-23 10:22:58 +04:00
|
|
|
ok O.(E_constant (constant_name , []))
|
2019-05-13 00:56:22 +04:00
|
|
|
| Some _ , None ->
|
|
|
|
simple_fail "n-ary constant without parameter"
|
|
|
|
| Some 0 , Some _ -> simple_fail "applying to nullary constant"
|
|
|
|
| Some 1 , Some param -> (
|
2019-05-23 10:22:58 +04:00
|
|
|
ok O.(E_constant (constant_name , [param]))
|
2019-05-13 00:56:22 +04:00
|
|
|
)
|
|
|
|
| Some n , Some param -> (
|
|
|
|
let params =
|
2019-05-23 10:22:58 +04:00
|
|
|
match param with
|
2019-05-13 00:56:22 +04:00
|
|
|
| E_tuple lst -> lst
|
|
|
|
| _ -> [ param ] in
|
|
|
|
let%bind () =
|
|
|
|
trace_strong (simple_error "bad constant arity") @@
|
|
|
|
Assert.assert_list_size params n in
|
2019-05-23 10:22:58 +04:00
|
|
|
ok O.(E_constant (constant_name , params))
|
2019-05-13 00:56:22 +04:00
|
|
|
)
|
|
|
|
| None , param_opt -> (
|
|
|
|
let%bind () =
|
|
|
|
let error =
|
|
|
|
let title () = "no module identifiers yet" in
|
|
|
|
let content () = Format.asprintf "%s" constant_name in
|
|
|
|
error title content in
|
|
|
|
trace_strong error @@
|
|
|
|
Assert.assert_list_empty lst in
|
2019-05-23 10:22:58 +04:00
|
|
|
match (constant_name , param_opt) with
|
|
|
|
| "failwith" , Some param -> ok O.(e_failwith param)
|
|
|
|
| _ , Some param -> ok @@ e_application (e_variable (unwrap v)) param
|
|
|
|
| _ , None -> ok @@ e_variable (unwrap v)
|
2019-05-13 00:56:22 +04:00
|
|
|
)
|
|
|
|
|
|
|
|
let let_content : I.let_content -> _ result = fun l ->
|
|
|
|
match l with
|
|
|
|
| (Let_content (n, args, ty_opt, e)) -> (
|
|
|
|
let%bind args' = bind_map_list (bind_map_location get_typed_variable_param) args in
|
|
|
|
let%bind ty' =
|
|
|
|
let%bind tya =
|
|
|
|
trace_option (simple_error "top-level declarations need a type") @@
|
|
|
|
ty_opt in
|
|
|
|
let%bind ty = get_type_annotation_ (unwrap tya) in
|
|
|
|
bind_map_location type_expression ty in
|
|
|
|
match args' with
|
|
|
|
| [] -> ( (* No arguments. Simplify as regular value. *)
|
2019-05-23 10:22:58 +04:00
|
|
|
let%bind e' = bind_map_location expression e in
|
|
|
|
ok @@ O.Declaration_constant (unwrap n , Some (unwrap ty') , unwrap e')
|
2019-05-13 00:56:22 +04:00
|
|
|
)
|
|
|
|
| [_param] ->
|
|
|
|
simple_fail "no syntactic sugar for functions yet param"
|
|
|
|
| _lst -> ( (* Arguments without fun. *)
|
|
|
|
simple_fail "if you want currified functions, please do so explicitly"
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
let let_entry : _ -> _ result = fun l ->
|
|
|
|
let (I.Let_content (n , args , ty_opt , e)) = l in
|
|
|
|
let%bind () =
|
|
|
|
trace_strong (simple_error "entry-point shouldn't have type annotations") @@
|
|
|
|
Assert.assert_none ty_opt in
|
|
|
|
let%bind (param , storage) =
|
|
|
|
trace_option (simple_error "entry-points should have exactly two params") @@
|
|
|
|
List.to_pair args in
|
|
|
|
let%bind (param_name , param_ty) =
|
|
|
|
let%bind param' = bind_map_location get_typed_variable_param param in
|
|
|
|
let (param_name , param_ty) = unwrap param' in
|
|
|
|
let param_name' = unwrap param_name in
|
|
|
|
let%bind param_ty' = restricted_type_expression (unwrap param_ty) in
|
|
|
|
ok (param_name' , param_ty') in
|
|
|
|
let%bind storage_name = get_untyped_variable_param (unwrap storage) in
|
|
|
|
let storage_ty = O.T_variable "storage" in
|
2019-05-23 10:22:58 +04:00
|
|
|
let (arguments_name , input_ty) =
|
|
|
|
let ty = t_tuple [param_ty ; storage_ty] in
|
|
|
|
let nty = ("arguments" , ty) in
|
2019-05-13 00:56:22 +04:00
|
|
|
nty in
|
|
|
|
let tpl_declarations =
|
2019-05-22 04:46:54 +04:00
|
|
|
let aux = fun i (name , type_expression) expr ->
|
2019-05-23 10:22:58 +04:00
|
|
|
e_let_in
|
|
|
|
(name , Some type_expression)
|
|
|
|
(e_accessor (e_variable arguments_name) [ Access_tuple i ])
|
|
|
|
expr
|
2019-05-13 00:56:22 +04:00
|
|
|
in
|
2019-05-22 04:46:54 +04:00
|
|
|
let lst = List.mapi aux [ (param_name , param_ty) ; ((unwrap storage_name) , storage_ty)] in
|
|
|
|
fun expr -> List.fold_right' (fun prec cur -> cur prec) expr lst
|
2019-05-13 00:56:22 +04:00
|
|
|
in
|
2019-05-22 04:46:54 +04:00
|
|
|
let%bind result = expression (unwrap e) in
|
|
|
|
let result = tpl_declarations result in
|
2019-05-23 10:22:58 +04:00
|
|
|
let input_type' = input_ty in
|
2019-05-16 20:17:27 +04:00
|
|
|
let output_type' = O.(t_pair (t_list t_operation , storage_ty)) in
|
2019-05-23 10:22:58 +04:00
|
|
|
let lambda = e_lambda
|
|
|
|
arguments_name
|
|
|
|
(Some input_ty) (Some output_type')
|
|
|
|
result in
|
2019-05-16 20:17:27 +04:00
|
|
|
let type_annotation = Some (O.T_function (input_type', output_type')) in
|
2019-05-23 10:22:58 +04:00
|
|
|
ok @@ O.Declaration_constant (unwrap n , type_annotation , lambda)
|
2019-05-13 00:56:22 +04:00
|
|
|
|
|
|
|
let let_init_storage : _ -> _ result = fun l ->
|
|
|
|
let (args , ty_opt , e) = l in
|
|
|
|
let%bind () =
|
|
|
|
trace_strong (simple_error "storage init shouldn't have a type annotation") @@
|
|
|
|
Assert.assert_none ty_opt in
|
|
|
|
let%bind () =
|
|
|
|
trace (simple_error "storage init should have no parameter (address)") @@
|
|
|
|
Assert.assert_list_size args 0 in
|
|
|
|
let%bind content =
|
2019-05-23 10:22:58 +04:00
|
|
|
let%bind expr = bind_map_location expression e in
|
|
|
|
ok expr
|
2019-05-13 00:56:22 +04:00
|
|
|
in
|
|
|
|
let type_annotation = O.t_variable "storage" in
|
2019-05-23 10:22:58 +04:00
|
|
|
ok @@ O.(Declaration_constant ("storage" , Some type_annotation , (unwrap content)))
|
2019-05-13 00:56:22 +04:00
|
|
|
|
|
|
|
|
|
|
|
let let_init_content : I.let_content -> _ result = fun l ->
|
|
|
|
let (I.Let_content (n, args, ty_opt, e)) = l in
|
|
|
|
match (unwrap n) with
|
|
|
|
| "storage" -> let_init_storage (args , ty_opt , e)
|
|
|
|
| _ -> simple_fail "%init directives are only used for storage"
|
|
|
|
|
|
|
|
let statement : I.statement -> O.declaration result = fun s ->
|
|
|
|
match s with
|
|
|
|
| Statement_variable_declaration x -> let_content (unwrap x)
|
|
|
|
| Statement_init_declaration x -> let_init_content (unwrap x)
|
|
|
|
| Statement_entry_declaration x -> let_entry (unwrap x)
|
|
|
|
| Statement_type_declaration (n, te) ->
|
|
|
|
let%bind te' = bind_map_location type_expression te in
|
2019-05-23 10:22:58 +04:00
|
|
|
ok @@ O.Declaration_type (unwrap n , unwrap te')
|
2019-05-13 00:56:22 +04:00
|
|
|
|
|
|
|
let program : I.program -> O.program result = fun (Program lst) ->
|
|
|
|
bind_map_list (bind_map_location statement) lst
|
|
|
|
|
|
|
|
let main : I.entry_point -> O.program Location.wrap result =
|
|
|
|
bind_map_location program
|