ligo/src/passes/10-transpiler/untranspiler.ml

252 lines
8.6 KiB
OCaml
Raw Normal View History

2019-09-11 13:56:39 +02:00
open Helpers
module AST = Ast_typed
module Append_tree = Tree.Append
open Mini_c
open Trace
module Errors = struct
let corner_case ~loc message =
let title () = "corner case" in
let content () = "we don't have a good error message for this case. we are
striving find ways to better report them and find the use-cases that generate
them. please report this to the developers." in
let data = [
("location" , fun () -> loc) ;
("message" , fun () -> message) ;
] in
error ~data title content
let wrong_mini_c_value expected_type actual =
2020-04-22 17:56:27 +02:00
let title () = "untranspiler: illed typed intermediary value" in
2019-09-11 13:56:39 +02:00
let content () = "type of intermediary value doesn't match what was expected" in
let data = [
("expected_type" , fun () -> expected_type) ;
("actual" , fun () -> Format.asprintf "%a" Mini_c.PP.value actual ) ;
] in
error ~data title content
let bad_untranspile bad_type value =
let title () = "untranspiling bad value" in
let content () = Format.asprintf "can not untranspile %s" bad_type in
let data = [
("bad_type" , fun () -> bad_type) ;
("value" , fun () -> Format.asprintf "%a" Mini_c.PP.value value) ;
] in
error ~data title content
end
open Errors
2019-12-04 18:30:52 +01:00
let rec untranspile (v : value) (t : AST.type_expression) : AST.expression result =
2019-09-11 13:56:39 +02:00
let open! AST in
let return e = ok (make_a_e_empty e t) in
2019-12-04 18:30:52 +01:00
match t.type_content with
2020-04-22 17:56:27 +02:00
| T_variable (name) when Var.equal name Stage_common.Constant.t_bool -> (
let%bind b =
trace_strong (wrong_mini_c_value "bool" v) @@
get_bool v in
2020-05-07 16:08:31 +02:00
return (e_bool b Environment.empty)
2020-04-22 17:56:27 +02:00
)
2020-04-29 14:41:54 +02:00
| t when (compare t (t_bool ()).type_content) = 0-> (
2020-04-22 17:56:27 +02:00
let%bind b =
trace_strong (wrong_mini_c_value "bool" v) @@
get_bool v in
2020-05-07 16:08:31 +02:00
return (e_bool b Environment.empty)
2020-04-22 17:56:27 +02:00
)
| T_constant type_constant -> (
match type_constant with
| TC_unit -> (
let%bind () =
trace_strong (wrong_mini_c_value "unit" v) @@
get_unit v in
return (E_literal Literal_unit)
)
| TC_int -> (
let%bind n =
trace_strong (wrong_mini_c_value "int" v) @@
get_int v in
return (E_literal (Literal_int n))
)
| TC_nat -> (
let%bind n =
trace_strong (wrong_mini_c_value "nat" v) @@
get_nat v in
return (E_literal (Literal_nat n))
)
| TC_timestamp -> (
let%bind n =
trace_strong (wrong_mini_c_value "timestamp" v) @@
get_timestamp v in
return (E_literal (Literal_timestamp n))
)
| TC_mutez -> (
let%bind n =
trace_strong (wrong_mini_c_value "tez" v) @@
get_mutez v in
return (E_literal (Literal_mutez n))
)
| TC_string -> (
let%bind n =
trace_strong (wrong_mini_c_value "string" v) @@
get_string v in
return (E_literal (Literal_string n))
)
| TC_bytes -> (
let%bind n =
trace_strong (wrong_mini_c_value "bytes" v) @@
get_bytes v in
return (E_literal (Literal_bytes n))
)
| TC_address -> (
2019-12-04 18:30:52 +01:00
let%bind n =
trace_strong (wrong_mini_c_value "address" v) @@
get_string v in
return (E_literal (Literal_address n))
)
| TC_operation -> (
let%bind op =
trace_strong (wrong_mini_c_value "operation" v) @@
get_operation v in
return (E_literal (Literal_operation op))
)
| TC_key -> (
let%bind n =
trace_strong (wrong_mini_c_value "key" v) @@
get_string v in
return (E_literal (Literal_key n))
)
| TC_key_hash -> (
let%bind n =
trace_strong (wrong_mini_c_value "key_hash" v) @@
get_string v in
return (E_literal (Literal_key_hash n))
)
2020-01-13 11:37:10 +01:00
| TC_chain_id -> (
let%bind n =
trace_strong (wrong_mini_c_value "chain_id" v) @@
get_string v in
return (E_literal (Literal_chain_id n))
)
2019-12-04 18:30:52 +01:00
| TC_void -> (
let%bind () =
trace_strong (wrong_mini_c_value "void" v) @@
get_unit v in
return (E_literal (Literal_void))
)
2020-01-13 11:37:10 +01:00
| TC_signature -> (
let%bind n =
trace_strong (wrong_mini_c_value "signature" v) @@
get_string v in
return (E_literal (Literal_signature n))
)
)
| T_operator type_operator -> (
match type_operator with
| TC_option o -> (
let%bind opt =
trace_strong (wrong_mini_c_value "option" v) @@
get_option v in
match opt with
| None -> ok (e_a_empty_none o)
| Some s ->
let%bind s' = untranspile s o in
ok (e_a_empty_some s')
)
2020-04-10 04:39:44 +02:00
| TC_map {k=k_ty;v=v_ty}-> (
2020-03-19 16:55:13 +01:00
let%bind map =
trace_strong (wrong_mini_c_value "map" v) @@
get_map v in
2020-03-19 16:55:13 +01:00
let%bind map' =
let aux = fun (k, v) ->
let%bind k = untranspile k k_ty in
let%bind v = untranspile v v_ty in
ok ({k; v} : AST.map_kv) in
2020-03-19 16:55:13 +01:00
bind_map_list aux map in
let map' = List.sort_uniq compare map' in
let aux = fun prev ({ k ; v } : AST.map_kv) ->
return @@ E_constant {cons_name=C_MAP_ADD;arguments=[k ; v ; prev]}
2020-03-19 16:55:13 +01:00
in
let%bind init = return @@ E_constant {cons_name=C_MAP_EMPTY;arguments=[]} in
bind_fold_right_list aux init map'
)
2020-04-10 04:39:44 +02:00
| TC_big_map {k=k_ty; v=v_ty} -> (
let%bind big_map =
trace_strong (wrong_mini_c_value "big_map" v) @@
get_big_map v in
let%bind big_map' =
let aux = fun (k, v) ->
let%bind k = untranspile k k_ty in
let%bind v = untranspile v v_ty in
ok ({k; v} : AST.map_kv) in
bind_map_list aux big_map in
let big_map' = List.sort_uniq compare big_map' in
let aux = fun prev ({ k ; v } : AST.map_kv) ->
2020-03-19 16:55:13 +01:00
return @@ E_constant {cons_name=C_MAP_ADD;arguments=[k ; v ; prev]}
in
let%bind init = return @@ E_constant {cons_name=C_BIG_MAP_EMPTY;arguments=[]} in
bind_fold_right_list aux init big_map'
)
2020-04-10 04:39:44 +02:00
| TC_map_or_big_map _ -> fail @@ corner_case ~loc:"untranspiler" "TC_map_or_big_map t should not be present in mini-c"
| TC_list ty -> (
let%bind lst =
trace_strong (wrong_mini_c_value "list" v) @@
get_list v in
let%bind lst' =
let aux = fun e -> untranspile e ty in
bind_map_list aux lst in
2020-03-16 18:34:43 +01:00
let aux = fun prev cur ->
return @@ E_constant {cons_name=C_CONS;arguments=[cur ; prev]} in
let%bind init = return @@ E_constant {cons_name=C_LIST_EMPTY;arguments=[]} in
bind_fold_right_list aux init lst'
)
| TC_set ty -> (
let%bind lst =
trace_strong (wrong_mini_c_value "set" v) @@
get_set v in
let%bind lst' =
let aux = fun e -> untranspile e ty in
bind_map_list aux lst in
2020-03-16 18:34:43 +01:00
let lst' = List.sort_uniq compare lst' in
let aux = fun prev cur ->
return @@ E_constant {cons_name=C_SET_ADD;arguments=[cur ; prev]} in
let%bind init = return @@ E_constant {cons_name=C_SET_EMPTY;arguments=[]} in
bind_fold_list aux init lst'
)
| TC_contract _ ->
fail @@ bad_untranspile "contract" v
2019-11-20 15:01:04 +01:00
)
2019-09-11 13:56:39 +02:00
| T_sum m ->
let lst = List.map (fun (k,{ctor_type;_}) -> (k,ctor_type)) @@ kv_list_of_cmap m in
2019-09-11 13:56:39 +02:00
let%bind node = match Append_tree.of_list lst with
| Empty -> fail @@ corner_case ~loc:__LOC__ "empty sum type"
| Full t -> ok t
in
let%bind (name, v, tv) =
trace_strong (corner_case ~loc:__LOC__ "sum extract constructor") @@
extract_constructor v node in
let%bind sub = untranspile v tv in
2019-12-04 18:30:52 +01:00
return (E_constructor {constructor=Constructor name;element=sub})
2019-09-11 13:56:39 +02:00
| T_record m ->
2020-04-18 00:02:33 +02:00
let lst = List.map (fun (k,{field_type;_}) -> (k,field_type)) @@ Ast_typed.Helpers.kv_list_of_record_or_tuple m in
2019-09-11 13:56:39 +02:00
let%bind node = match Append_tree.of_list lst with
| Empty -> fail @@ corner_case ~loc:__LOC__ "empty record"
| Full t -> ok t in
let%bind lst =
trace_strong (corner_case ~loc:__LOC__ "record extract") @@
extract_record v node in
let%bind lst = bind_list
@@ List.map (fun (x, (y, z)) -> let%bind yz = untranspile y z in ok (x, yz)) lst in
let m' = AST.LMap.of_list lst in
2019-09-11 13:56:39 +02:00
return (E_record m')
| T_arrow _ ->
let%bind n =
trace_strong (wrong_mini_c_value "lambda as string" v) @@
get_string v in
return (E_literal (Literal_string n))
| T_variable _ ->
fail @@ corner_case ~loc:__LOC__ "trying to untranspile at variable type"