From 3a80fadcc82a4dd76e0d9b1356f4217e26cbcbd1 Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Thu, 12 Mar 2020 17:32:49 +0100 Subject: [PATCH] rewrite interpreter recursion within the initial formalism. --- src/bin/expect_tests/ligo_interpreter_tests.ml | 4 +++- src/passes/6-interpreter/interpreter.ml | 18 +++++++++--------- src/stages/ligo_interpreter/types.ml | 2 +- src/test/contracts/interpret_test.mligo | 7 ++++++- 4 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/bin/expect_tests/ligo_interpreter_tests.ml b/src/bin/expect_tests/ligo_interpreter_tests.ml index 3dbf06bde..9a6069338 100644 --- a/src/bin/expect_tests/ligo_interpreter_tests.ml +++ b/src/bin/expect_tests/ligo_interpreter_tests.ml @@ -54,4 +54,6 @@ let%expect_test _ = val set_add = { ; 0 = ({ ; 1 : int ; 2 : int ; 3 : int}) ; 1 = ({ ; 1 : int ; 2 : int ; 3 : int ; 4 : int}) ; 2 = ({ ; 1 : int}) } val set_iter_fail = "set_iter_fail" : failure val set_mem = { ; 0 = (true) ; 1 = (false) ; 2 = (false) } - val recursion = 55 : int |}] ; \ No newline at end of file + val recursion_let_rec_in = 55 : int + val sum_rec = + val top_level_recursion = 55 : int |}] ; \ No newline at end of file diff --git a/src/passes/6-interpreter/interpreter.ml b/src/passes/6-interpreter/interpreter.ml index 96957225c..cdbee239c 100644 --- a/src/passes/6-interpreter/interpreter.ml +++ b/src/passes/6-interpreter/interpreter.ml @@ -272,25 +272,23 @@ and eval : Ast_typed.expression -> env -> value result match term.expression_content with | E_application ({expr1 = f; expr2 = args}) -> ( let%bind f' = eval f env in + let%bind args' = eval args env in match f' with | V_Func_val (arg_names, body, f_env) -> - let%bind args' = eval args env in let f_env' = Env.extend f_env (arg_names, args') in eval body f_env' - | V_Func_rec (_fun_name,_fun_type,lambda, _env) -> - let%bind args' = eval args env in - let f_env' = Env.extend env (lambda.binder,args') in - eval lambda.result f_env' + | V_Func_rec (fun_name, arg_names, body, f_env) -> + let f_env' = Env.extend f_env (arg_names, args') in + let f_env'' = Env.extend f_env' (fun_name, f') in + eval body f_env'' | _ -> simple_fail "trying to apply on something that is not a function" ) | E_lambda {binder; result;} -> ok @@ V_Func_val (binder,result,env) - | E_recursive {fun_name; fun_type;lambda} -> - let env' = Env.extend env (fun_name, V_Func_rec(fun_name,fun_type,lambda,env)) in - ok @@ V_Func_rec (fun_name,fun_type,lambda,env') - | E_let_in { let_binder; rhs; let_result; _} -> + | E_let_in {let_binder ; rhs; let_result} -> ( let%bind rhs' = eval rhs env in eval let_result (Env.extend env (let_binder,rhs')) + ) | E_map kvlist | E_big_map kvlist -> let%bind kvlist' = bind_map_list (fun kv -> bind_map_pair (fun (el:Ast_typed.expression) -> eval el env) kv) @@ -378,6 +376,8 @@ and eval : Ast_typed.expression -> env -> value result | _ -> simple_fail "not yet supported case" (* ((ctor,name),body) *) ) + | E_recursive {fun_name; fun_type=_; lambda} -> + ok @@ V_Func_rec (fun_name, lambda.binder, lambda.result, env) | E_look_up _ -> let serr = Format.asprintf "Unsupported construct :\n %a\n" Ast_typed.PP.expression term in simple_fail serr diff --git a/src/stages/ligo_interpreter/types.ml b/src/stages/ligo_interpreter/types.ml index b9f9a7e5e..d2274e9ee 100644 --- a/src/stages/ligo_interpreter/types.ml +++ b/src/stages/ligo_interpreter/types.ml @@ -31,7 +31,7 @@ and constant_val = and value = | V_Func_val of (expression_variable * Ast_typed.expression * env) - | V_Func_rec of (expression_variable * Ast_typed.type_expression * Ast_typed.lambda * env) + | V_Func_rec of (expression_variable * expression_variable * Ast_typed.expression * env) | V_Ct of constant_val | V_List of value list | V_Record of value label_map diff --git a/src/test/contracts/interpret_test.mligo b/src/test/contracts/interpret_test.mligo index ebabbcf53..07932653e 100644 --- a/src/test/contracts/interpret_test.mligo +++ b/src/test/contracts/interpret_test.mligo @@ -233,9 +233,14 @@ let set_mem = Set.mem 4 s, Set.mem 1 (Set.empty : int set) -let recursion = +let recursion_let_rec_in = let rec sum : int*int -> int = fun ((n,res):int*int) -> let i = 1 in if (n<1) then res else sum (n-i,res+n) in sum (10,0) + +let rec sum_rec ((n,acc):int * int) : int = + if (n < 1) then acc else sum_rec (n-1, acc+n) + +let top_level_recursion = sum_rec (10,0) \ No newline at end of file