This commit is contained in:
Galfour 2019-04-17 22:53:43 +00:00
parent c74e2846df
commit 079e997cc4
4 changed files with 36 additions and 26 deletions

View File

@ -560,6 +560,7 @@ module Combinators = struct
type_value (T_sum map) None type_value (T_sum map) None
let t_function param result ?s () : type_value = type_value (T_function (param, result)) s let t_function param result ?s () : type_value = type_value (T_function (param, result)) s
let t_shallow_closure param result ?s () : type_value = type_value (T_function (param, result)) s
let get_annotation (x:annotated_expression) = x.type_annotation let get_annotation (x:annotated_expression) = x.type_annotation

View File

@ -80,6 +80,9 @@ let get_last_statement ((b', _):block) : statement result =
let t_int : type_value = T_base Base_int let t_int : type_value = T_base Base_int
let t_nat : type_value = T_base Base_nat let t_nat : type_value = T_base Base_nat
let t_function x y : type_value = T_function ( x , y )
let t_pair x y : type_value = T_pair ( x , y )
let quote binder input output body result : anon_function = let quote binder input output body result : anon_function =
let content : anon_function_content = { let content : anon_function_content = {
binder ; input ; output ; binder ; input ; output ;

View File

@ -203,8 +203,8 @@ and translate_expression ((expr', ty, env) as expr:expression) : michelson resul
] in ] in
ok code ok code
| E_function anon -> ( | E_function anon -> (
match ty with match anon.capture_type with
| T_function (_, _) -> | No_capture ->
let%bind body = translate_function_body anon in let%bind body = translate_function_body anon in
let%bind input_type = Compiler_type.type_ anon.input in let%bind input_type = Compiler_type.type_ anon.input in
let%bind output_type = Compiler_type.type_ anon.output in let%bind output_type = Compiler_type.type_ anon.output in
@ -213,7 +213,7 @@ and translate_expression ((expr', ty, env) as expr:expression) : michelson resul
i_pair ; i_pair ;
] in ] in
ok code ok code
| T_deep_closure (small_env, _, _) -> | Deep_capture small_env ->
(* Capture the variable bounds, assemble them. On call, append the input. *) (* Capture the variable bounds, assemble them. On call, append the input. *)
let%bind body = translate_function_body anon in let%bind body = translate_function_body anon in
let%bind capture = Environment.Small.to_mini_c_capture env small_env in let%bind capture = Environment.Small.to_mini_c_capture env small_env in
@ -228,19 +228,18 @@ and translate_expression ((expr', ty, env) as expr:expression) : michelson resul
i_pair ; i_pair ;
] in ] in
ok code ok code
| T_shallow_closure (_, _, _) -> | Shallow_capture _ ->
(* Capture the whole environment. *) (* Capture the whole environment. *)
let%bind body = translate_function_body anon in let%bind body = translate_function_body anon in
let%bind input_type = Compiler_type.type_ anon.input in let%bind input_type = Compiler_type.type_ anon.input in
let%bind output_type = Compiler_type.type_ anon.output in let%bind output_type = Compiler_type.type_ anon.output in
let code = seq [ let code = seq [ (* stack :: env *)
dip i_dup ; i_swap ; dip i_dup ; i_swap ; (* env :: stack :: env *)
i_lambda input_type output_type body ; i_lambda input_type output_type body ; (* lambda :: env :: stack :: env *)
i_piar ; i_piar ; (* (env * lambda) :: stack :: env *)
i_pair ; i_pair ; (* new_stack :: env *)
] in ] in
ok code ok code
| _ -> simple_fail "expected function code"
) )
| E_Cond (c, a, b) -> ( | E_Cond (c, a, b) -> (
let%bind c' = translate_expression c in let%bind c' = translate_expression c in
@ -431,7 +430,9 @@ and translate_function_body ({body;result} as f:anon_function_content) : michels
let%bind body = translate_regular_block body in let%bind body = translate_regular_block body in
let%bind expr = translate_expression result in let%bind expr = translate_expression result in
let code = seq [ let code = seq [
i_comment "function body" ;
body ; body ;
i_comment "function result" ;
i_push_unit ; expr ; i_car ; i_push_unit ; expr ; i_car ;
dip i_drop ; dip i_drop ;
] in ] in
@ -443,8 +444,10 @@ and translate_function_body ({body;result} as f:anon_function_content) : michels
let output_stack_ty = Stack.(output_ty @: nil) in let output_stack_ty = Stack.(output_ty @: nil) in
let error_message () = let error_message () =
Format.asprintf Format.asprintf
"\ncode : %a\n" "\ncode : %a\ninput : %a\noutput : %a\n"
Tezos_utils.Micheline.Michelson.pp code Tezos_utils.Micheline.Michelson.pp code
PP.type_ f.input
PP.type_ f.output
in in
let%bind _ = let%bind _ =
Trace.trace_tzresult_lwt ( Trace.trace_tzresult_lwt (

View File

@ -288,7 +288,7 @@ and translate_annotated_expression (env:Environment.t) (ae:AST.annotated_express
ok (E_make_none o, tv, env) ok (E_make_none o, tv, env)
| _ -> ok (E_constant (name, lst'), tv, env) | _ -> ok (E_constant (name, lst'), tv, env)
) )
| E_lambda l -> translate_lambda env l tv | E_lambda l -> translate_lambda env l
| E_list lst -> | E_list lst ->
let%bind t = Mini_c.Combinators.get_t_list tv in let%bind t = Mini_c.Combinators.get_t_list tv in
let%bind lst' = bind_map_list (translate_annotated_expression env) lst in let%bind lst' = bind_map_list (translate_annotated_expression env) lst in
@ -320,7 +320,7 @@ and translate_annotated_expression (env:Environment.t) (ae:AST.annotated_express
simple_fail "only match bool exprs are translated yet" simple_fail "only match bool exprs are translated yet"
) )
and translate_lambda_shallow env l tv = and translate_lambda_shallow env l =
let { binder ; input_type ; output_type ; body ; result } : AST.lambda = l in let { binder ; input_type ; output_type ; body ; result } : AST.lambda = l in
(* Shallow capture. Capture the whole environment. Extend it with a new scope. Append it the input. *) (* Shallow capture. Capture the whole environment. Extend it with a new scope. Append it the input. *)
let%bind input = translate_type input_type in let%bind input = translate_type input_type in
@ -329,20 +329,20 @@ and translate_lambda_shallow env l tv =
let%bind (_, e) as body = translate_block full_env body in let%bind (_, e) as body = translate_block full_env body in
let%bind result = translate_annotated_expression e.post_environment result in let%bind result = translate_annotated_expression e.post_environment result in
let capture_type = Shallow_capture sub_env in let capture_type = Shallow_capture sub_env in
let input = Environment.to_mini_c_type full_env in let input' = Environment.to_mini_c_type full_env in
let%bind output = translate_type output_type in let%bind output = translate_type output_type in
let content = {binder;input;output;body;result;capture_type} in let tv =
let open Combinators in
let f = t_function input' output in
let env_type = Environment.to_mini_c_type env in
t_pair env_type f
in
let content = {binder;input=input';output;body;result;capture_type} in
ok (E_function content, tv, env) ok (E_function content, tv, env)
and translate_lambda env l tv = and translate_lambda env l =
let { binder ; input_type ; output_type ; body ; result } : AST.lambda = l in let { binder ; input_type ; output_type ; body ; result } : AST.lambda = l in
(* Try to translate it in an empty env, if it succeeds, transpiles it as a quote value, else, as a closure expression. *) (* Try to translate it in an empty env, if it succeeds, transpiles it as a quote value, else, as a closure expression. *)
let%bind init_env =
let%bind input = translate_type input_type in
ok Environment.(add (binder, input) env) in
let%bind empty_env =
let%bind input = translate_type input_type in
ok Environment.(add (binder, input) empty) in
let ((_body_bounds , body_fvs) , result_fvs) = AST.Free_variables.( let ((_body_bounds , body_fvs) , result_fvs) = AST.Free_variables.(
let bindings = singleton binder in let bindings = singleton binder in
let ((body_bounds , _) as b) = block' bindings body in let ((body_bounds , _) as b) = block' bindings body in
@ -350,18 +350,22 @@ and translate_lambda env l tv =
) in ) in
match (body_fvs, result_fvs) with match (body_fvs, result_fvs) with
| [] , [] -> ( | [] , [] -> (
let%bind empty_env =
let%bind input = translate_type input_type in
ok Environment.(add (binder, input) empty) in
let%bind ((_, e) as body') = translate_block empty_env body in let%bind ((_, e) as body') = translate_block empty_env body in
let%bind result' = translate_annotated_expression e.post_environment result in let%bind result' = translate_annotated_expression e.post_environment result in
trace (simple_error "translate quote") @@ trace (simple_error "translate quote") @@
let capture_type = No_capture in let capture_type = No_capture in
let%bind input = translate_type input_type in let%bind input = translate_type input_type in
let%bind output = translate_type output_type in let%bind output = translate_type output_type in
let tv = Combinators.t_function input output in
let content = {binder;input;output;body=body';result=result';capture_type} in let content = {binder;input;output;body=body';result=result';capture_type} in
ok (E_literal (D_function {capture=None;content}), tv, env) ok (E_literal (D_function {capture=None;content}), tv, env)
) )
| _ -> ( | _ -> (
trace (simple_error "translate lambda shallow") @@ trace (simple_error "translate lambda shallow") @@
translate_lambda_shallow init_env l tv translate_lambda_shallow env l
) )
let translate_declaration env (d:AST.declaration) : toplevel_statement result = let translate_declaration env (d:AST.declaration) : toplevel_statement result =
@ -380,9 +384,8 @@ let translate_program (lst:AST.program) : program result =
let%bind (statements, _) = List.fold_left aux (ok ([], Environment.empty)) (temp_unwrap_loc_list lst) in let%bind (statements, _) = List.fold_left aux (ok ([], Environment.empty)) (temp_unwrap_loc_list lst) in
ok statements ok statements
let translate_main (l:AST.lambda) (t:AST.type_value) : anon_function result = let translate_main (l:AST.lambda) (_t:AST.type_value) : anon_function result =
let%bind t' = translate_type t in let%bind (expr, _, _) = translate_lambda Environment.empty l in
let%bind (expr, _, _) = translate_lambda Environment.empty l t' in
match expr with match expr with
| E_literal (D_function f) -> ok f | E_literal (D_function f) -> ok f
| _ -> simple_fail "main is not a function" | _ -> simple_fail "main is not a function"