2019-05-23 19:43:18 +04:00
|
|
|
module Typer = struct
|
|
|
|
|
|
|
|
open Trace
|
|
|
|
open Ast_typed
|
|
|
|
|
|
|
|
module Errors = struct
|
|
|
|
let wrong_param_number = fun name expected got ->
|
|
|
|
let title () = "wrong number of params" in
|
|
|
|
let full () = Format.asprintf "constant name: %s\nexpected: %d\ngot: %d\n"
|
|
|
|
name expected (List.length got) in
|
|
|
|
error title full
|
|
|
|
|
2019-06-05 21:16:54 +04:00
|
|
|
let error_uncomparable_types a b () =
|
|
|
|
let title () = "these types are not comparable" in
|
|
|
|
let message () = "" in
|
|
|
|
let data = [
|
2019-12-04 21:30:52 +04:00
|
|
|
("a" , fun () -> Format.asprintf "%a" PP.type_expression a) ;
|
|
|
|
("b" , fun () -> Format.asprintf "%a" PP.type_expression b )
|
2019-06-05 21:16:54 +04:00
|
|
|
] in
|
|
|
|
error ~data title message ()
|
|
|
|
end
|
|
|
|
open Errors
|
2019-05-23 19:43:18 +04:00
|
|
|
|
2019-12-04 21:30:52 +04:00
|
|
|
type type_result = type_expression
|
|
|
|
type typer = type_expression list -> type_expression option -> type_result result
|
2019-05-23 19:43:18 +04:00
|
|
|
|
2019-12-04 21:30:52 +04:00
|
|
|
let typer_0 : string -> (type_expression option -> type_expression result) -> typer = fun s f lst tv_opt ->
|
2019-05-23 19:43:18 +04:00
|
|
|
match lst with
|
|
|
|
| [] -> (
|
|
|
|
let%bind tv' = f tv_opt in
|
2019-12-04 15:40:58 +04:00
|
|
|
ok (tv')
|
2019-05-23 19:43:18 +04:00
|
|
|
)
|
2019-06-05 21:16:54 +04:00
|
|
|
| _ -> fail @@ wrong_param_number s 0 lst
|
2019-05-23 19:43:18 +04:00
|
|
|
|
2019-12-04 21:30:52 +04:00
|
|
|
let typer_1 : string -> (type_expression -> type_expression result) -> typer = fun s f lst _ ->
|
2019-05-23 19:43:18 +04:00
|
|
|
match lst with
|
|
|
|
| [ a ] -> (
|
|
|
|
let%bind tv' = f a in
|
2019-12-04 15:40:58 +04:00
|
|
|
ok (tv')
|
2019-05-23 19:43:18 +04:00
|
|
|
)
|
2019-06-05 21:16:54 +04:00
|
|
|
| _ -> fail @@ wrong_param_number s 1 lst
|
2019-05-23 19:43:18 +04:00
|
|
|
|
2019-12-04 21:30:52 +04:00
|
|
|
let typer_1_opt : string -> (type_expression -> type_expression option -> type_expression result) -> typer = fun s f lst tv_opt ->
|
2019-05-23 19:43:18 +04:00
|
|
|
match lst with
|
|
|
|
| [ a ] -> (
|
|
|
|
let%bind tv' = f a tv_opt in
|
2019-12-04 15:40:58 +04:00
|
|
|
ok (tv')
|
2019-05-23 19:43:18 +04:00
|
|
|
)
|
2019-06-05 21:16:54 +04:00
|
|
|
| _ -> fail @@ wrong_param_number s 1 lst
|
2019-05-23 19:43:18 +04:00
|
|
|
|
2019-12-04 21:30:52 +04:00
|
|
|
let typer_2 : string -> (type_expression -> type_expression -> type_expression result) -> typer = fun s f lst _ ->
|
2019-05-23 19:43:18 +04:00
|
|
|
match lst with
|
|
|
|
| [ a ; b ] -> (
|
|
|
|
let%bind tv' = f a b in
|
2019-12-04 15:40:58 +04:00
|
|
|
ok (tv')
|
2019-05-23 19:43:18 +04:00
|
|
|
)
|
2019-06-05 21:16:54 +04:00
|
|
|
| _ -> fail @@ wrong_param_number s 2 lst
|
2019-05-23 19:43:18 +04:00
|
|
|
|
2019-12-04 21:30:52 +04:00
|
|
|
let typer_2_opt : string -> (type_expression -> type_expression -> type_expression option -> type_expression result) -> typer = fun s f lst tv_opt ->
|
2019-11-09 11:27:30 +04:00
|
|
|
match lst with
|
|
|
|
| [ a ; b ] -> (
|
|
|
|
let%bind tv' = f a b tv_opt in
|
2019-12-04 15:40:58 +04:00
|
|
|
ok (tv')
|
2019-11-09 11:27:30 +04:00
|
|
|
)
|
|
|
|
| _ -> fail @@ wrong_param_number s 2 lst
|
|
|
|
|
2019-12-04 21:30:52 +04:00
|
|
|
let typer_3 : string -> (type_expression -> type_expression -> type_expression -> type_expression result) -> typer = fun s f lst _ ->
|
2019-05-23 19:43:18 +04:00
|
|
|
match lst with
|
|
|
|
| [ a ; b ; c ] -> (
|
|
|
|
let%bind tv' = f a b c in
|
2019-12-04 15:40:58 +04:00
|
|
|
ok (tv')
|
2019-05-23 19:43:18 +04:00
|
|
|
)
|
2019-06-05 21:16:54 +04:00
|
|
|
| _ -> fail @@ wrong_param_number s 3 lst
|
2019-05-23 19:43:18 +04:00
|
|
|
|
2019-12-04 21:30:52 +04:00
|
|
|
let typer_4 : string -> (type_expression -> type_expression -> type_expression -> type_expression -> type_expression result) -> typer = fun s f lst _ ->
|
2019-07-19 14:13:09 +04:00
|
|
|
match lst with
|
|
|
|
| [ a ; b ; c ; d ] -> (
|
|
|
|
let%bind tv' = f a b c d in
|
2019-12-04 15:40:58 +04:00
|
|
|
ok (tv')
|
2019-07-19 14:13:09 +04:00
|
|
|
)
|
|
|
|
| _ -> fail @@ wrong_param_number s 4 lst
|
|
|
|
|
2019-12-04 21:30:52 +04:00
|
|
|
let typer_5 : string -> (type_expression -> type_expression -> type_expression -> type_expression -> type_expression -> type_expression result) -> typer = fun s f lst _ ->
|
2019-07-19 14:13:09 +04:00
|
|
|
match lst with
|
|
|
|
| [ a ; b ; c ; d ; e ] -> (
|
|
|
|
let%bind tv' = f a b c d e in
|
2019-12-04 15:40:58 +04:00
|
|
|
ok (tv')
|
2019-07-19 14:13:09 +04:00
|
|
|
)
|
|
|
|
| _ -> fail @@ wrong_param_number s 5 lst
|
|
|
|
|
2019-12-04 21:30:52 +04:00
|
|
|
let typer_6 : string -> (type_expression -> type_expression -> type_expression -> type_expression -> type_expression -> type_expression -> type_expression result) -> typer = fun s f lst _ ->
|
2019-07-19 14:13:09 +04:00
|
|
|
match lst with
|
|
|
|
| [ a ; b ; c ; d ; e ; f_ ] -> (
|
|
|
|
let%bind tv' = f a b c d e f_ in
|
2019-12-04 15:40:58 +04:00
|
|
|
ok (tv')
|
2019-07-19 14:13:09 +04:00
|
|
|
)
|
|
|
|
| _ -> fail @@ wrong_param_number s 6 lst
|
|
|
|
|
2019-12-04 21:30:52 +04:00
|
|
|
let constant' name cst = typer_0 name (fun _ -> ok cst)
|
2019-05-23 19:43:18 +04:00
|
|
|
|
|
|
|
open Combinators
|
|
|
|
|
2019-12-04 21:30:52 +04:00
|
|
|
let eq_1 a cst = type_expression_eq (a , cst)
|
|
|
|
let eq_2 (a , b) cst = type_expression_eq (a , cst) && type_expression_eq (b , cst)
|
2019-05-23 19:43:18 +04:00
|
|
|
|
2019-09-24 01:33:25 +04:00
|
|
|
let assert_eq_1 ?msg a b = Assert.assert_true ?msg (eq_1 a b)
|
2019-07-19 14:13:09 +04:00
|
|
|
|
2019-05-23 19:43:18 +04:00
|
|
|
let comparator : string -> typer = fun s -> typer_2 s @@ fun a b ->
|
|
|
|
let%bind () =
|
2019-06-05 21:16:54 +04:00
|
|
|
trace_strong (error_uncomparable_types a b) @@
|
2019-05-23 19:43:18 +04:00
|
|
|
Assert.assert_true @@
|
|
|
|
List.exists (eq_2 (a , b)) [
|
|
|
|
t_int () ;
|
|
|
|
t_nat () ;
|
2020-02-12 23:22:59 +04:00
|
|
|
t_bool () ;
|
2019-10-09 08:51:29 +04:00
|
|
|
t_mutez () ;
|
2019-05-23 19:43:18 +04:00
|
|
|
t_string () ;
|
|
|
|
t_bytes () ;
|
|
|
|
t_address () ;
|
2019-06-11 02:06:00 +04:00
|
|
|
t_timestamp () ;
|
2019-11-21 16:12:52 +04:00
|
|
|
t_key_hash () ;
|
2019-05-23 19:43:18 +04:00
|
|
|
] in
|
|
|
|
ok @@ t_bool ()
|
|
|
|
|
|
|
|
let boolean_operator_2 : string -> typer = fun s -> typer_2 s @@ fun a b ->
|
|
|
|
let%bind () =
|
|
|
|
trace_strong (simple_error "A isn't of type bool") @@
|
|
|
|
Assert.assert_true @@
|
2019-12-04 21:30:52 +04:00
|
|
|
type_expression_eq (t_bool () , a) in
|
2019-05-23 19:43:18 +04:00
|
|
|
let%bind () =
|
|
|
|
trace_strong (simple_error "B isn't of type bool") @@
|
|
|
|
Assert.assert_true @@
|
2019-12-04 21:30:52 +04:00
|
|
|
type_expression_eq (t_bool () , b) in
|
2019-05-23 19:43:18 +04:00
|
|
|
ok @@ t_bool ()
|
|
|
|
|
2020-04-22 21:44:21 +04:00
|
|
|
module Converter = struct
|
|
|
|
open Ast_typed
|
2020-04-28 02:34:03 +04:00
|
|
|
open Trace
|
2020-04-22 21:44:21 +04:00
|
|
|
|
|
|
|
let record_checks kvl =
|
|
|
|
let%bind () = Assert.assert_true_err
|
|
|
|
(simple_error "converted record must have at least two elements")
|
|
|
|
(List.length kvl >=2) in
|
2020-04-28 18:58:47 +04:00
|
|
|
let all_undefined = List.for_all (fun (_,{field_decl_pos;_}) -> field_decl_pos = 0) kvl in
|
2020-04-22 21:44:21 +04:00
|
|
|
let%bind () = Assert.assert_true_err
|
|
|
|
(simple_error "can't retrieve declaration order in the converted record, you need to annotate it")
|
|
|
|
(not all_undefined) in
|
|
|
|
ok ()
|
|
|
|
|
|
|
|
let annotate_field (field:field_content) (ann:string) : field_content =
|
|
|
|
{field with michelson_annotation=Some ann}
|
|
|
|
|
|
|
|
let comb (t:type_content) : field_content =
|
|
|
|
let field_type = {
|
|
|
|
type_content = t ;
|
|
|
|
type_meta = None ;
|
|
|
|
location = Location.generated ; } in
|
2020-04-28 18:58:47 +04:00
|
|
|
{field_type ; michelson_annotation = Some "" ; field_decl_pos = 0}
|
2020-04-22 21:44:21 +04:00
|
|
|
|
|
|
|
let rec to_right_comb_t l new_map =
|
|
|
|
match l with
|
|
|
|
| [] -> new_map
|
|
|
|
| [ (Label ann_l, field_content_l) ; (Label ann_r, field_content_r) ] ->
|
|
|
|
LMap.add_bindings [
|
|
|
|
(Label "0" , annotate_field field_content_l ann_l) ;
|
|
|
|
(Label "1" , annotate_field field_content_r ann_r) ] new_map
|
|
|
|
| (Label ann, field)::tl ->
|
|
|
|
let new_map' = LMap.add (Label "0") (annotate_field field ann) new_map in
|
|
|
|
LMap.add (Label "1") (comb (T_record (to_right_comb_t tl new_map'))) new_map'
|
|
|
|
|
2020-04-28 02:34:03 +04:00
|
|
|
let rec to_left_comb_t' first l new_map =
|
2020-04-22 21:44:21 +04:00
|
|
|
match l with
|
|
|
|
| [] -> new_map
|
|
|
|
| (Label ann_l, field_content_l) :: (Label ann_r, field_content_r) ::tl when first ->
|
|
|
|
let new_map' = LMap.add_bindings [
|
|
|
|
(Label "0" , annotate_field field_content_l ann_l) ;
|
|
|
|
(Label "1" , annotate_field field_content_r ann_r) ] LMap.empty in
|
2020-04-28 02:34:03 +04:00
|
|
|
to_left_comb_t' false tl new_map'
|
2020-04-22 21:44:21 +04:00
|
|
|
| (Label ann, field)::tl ->
|
|
|
|
let new_map' = LMap.add_bindings [
|
|
|
|
(Label "0" , comb (T_record new_map)) ;
|
|
|
|
(Label "1" , annotate_field field ann ) ;] LMap.empty in
|
2020-04-28 02:34:03 +04:00
|
|
|
to_left_comb_t' first tl new_map'
|
|
|
|
let to_left_comb_t = to_left_comb_t' true
|
2020-04-22 21:44:21 +04:00
|
|
|
|
|
|
|
let convert_type_to_right_comb l =
|
2020-04-28 18:58:47 +04:00
|
|
|
let l' = List.sort (fun (_,{field_decl_pos=a;_}) (_,{field_decl_pos=b;_}) -> Int.compare a b) l in
|
2020-04-22 21:44:21 +04:00
|
|
|
T_record (to_right_comb_t l' LMap.empty)
|
|
|
|
|
|
|
|
let convert_type_to_left_comb l =
|
2020-04-28 18:58:47 +04:00
|
|
|
let l' = List.sort (fun (_,{field_decl_pos=a;_}) (_,{field_decl_pos=b;_}) -> Int.compare a b) l in
|
2020-04-22 21:44:21 +04:00
|
|
|
T_record (to_left_comb_t l' LMap.empty)
|
2020-04-28 02:34:03 +04:00
|
|
|
|
|
|
|
let rec from_right_comb (l:field_content label_map) (size:int) : (field_content list) result =
|
|
|
|
let l' = List.rev @@ LMap.to_kv_list l in
|
|
|
|
match l' , size with
|
|
|
|
| [ (_,l) ; (_,r) ] , 2 -> ok [ l ; r ]
|
|
|
|
| [ (_,l) ; (_,{field_type=tr;_}) ], _ ->
|
|
|
|
let%bind comb_lmap = get_t_record tr in
|
|
|
|
let%bind next = from_right_comb comb_lmap (size-1) in
|
|
|
|
ok (l :: next)
|
2020-04-28 23:29:21 +04:00
|
|
|
| _ -> simple_fail "Could not convert michelson_pair_right_comb pair to a record"
|
2020-04-28 02:34:03 +04:00
|
|
|
|
|
|
|
let rec from_left_comb (l:field_content label_map) (size:int) : (field_content list) result =
|
|
|
|
let l' = List.rev @@ LMap.to_kv_list l in
|
|
|
|
match l' , size with
|
|
|
|
| [ (_,l) ; (_,r) ] , 2 -> ok [ l ; r ]
|
|
|
|
| [ (_,{field_type=tl;_}) ; (_,r) ], _ ->
|
|
|
|
let%bind comb_lmap = get_t_record tl in
|
|
|
|
let%bind next = from_left_comb comb_lmap (size-1) in
|
|
|
|
ok (List.append next [r])
|
2020-04-28 23:29:21 +04:00
|
|
|
| _ -> simple_fail "Could not convert michelson_pair_left_comb pair to a record"
|
2020-04-28 02:34:03 +04:00
|
|
|
|
|
|
|
let convert_from_right_comb (src: field_content label_map) (dst: field_content label_map) : type_content result =
|
|
|
|
let%bind fields = from_right_comb src (LMap.cardinal dst) in
|
|
|
|
let labels = List.map (fun (l,_) -> l) @@
|
2020-04-28 18:58:47 +04:00
|
|
|
List.sort (fun (_,{field_decl_pos=a;_}) (_,{field_decl_pos=b;_}) -> Int.compare a b ) @@
|
2020-04-28 02:34:03 +04:00
|
|
|
LMap.to_kv_list dst in
|
|
|
|
ok @@ (T_record (LMap.of_list @@ List.combine labels fields))
|
|
|
|
|
|
|
|
let convert_from_left_comb (src: field_content label_map) (dst: field_content label_map) : type_content result =
|
|
|
|
let%bind fields = from_left_comb src (LMap.cardinal dst) in
|
|
|
|
let labels = List.map (fun (l,_) -> l) @@
|
2020-04-28 18:58:47 +04:00
|
|
|
List.sort (fun (_,{field_decl_pos=a;_}) (_,{field_decl_pos=b;_}) -> Int.compare a b ) @@
|
2020-04-28 02:34:03 +04:00
|
|
|
LMap.to_kv_list dst in
|
|
|
|
ok @@ (T_record (LMap.of_list @@ List.combine labels fields))
|
|
|
|
|
2020-04-22 21:44:21 +04:00
|
|
|
end
|
|
|
|
|
2019-05-23 19:43:18 +04:00
|
|
|
end
|
|
|
|
|
|
|
|
module Compiler = struct
|
|
|
|
|
|
|
|
open Tezos_utils.Michelson
|
|
|
|
|
|
|
|
type predicate =
|
|
|
|
| Constant of michelson
|
|
|
|
| Unary of michelson
|
|
|
|
| Binary of michelson
|
|
|
|
| Ternary of michelson
|
2019-07-19 14:13:09 +04:00
|
|
|
| Tetrary of michelson
|
|
|
|
| Pentary of michelson
|
|
|
|
| Hexary of michelson
|
2019-05-23 19:43:18 +04:00
|
|
|
let simple_constant c = Constant c
|
|
|
|
let simple_unary c = Unary c
|
|
|
|
let simple_binary c = Binary c
|
|
|
|
let simple_ternary c = Ternary c
|
2019-07-19 14:13:09 +04:00
|
|
|
let simple_tetrary c = Tetrary c
|
|
|
|
let simple_pentary c = Pentary c
|
|
|
|
let simple_hexary c = Hexary c
|
2019-05-23 19:43:18 +04:00
|
|
|
end
|