diff --git a/src/aeso_ast_infer_types.erl b/src/aeso_ast_infer_types.erl index 7f6bc2b..c88349b 100644 --- a/src/aeso_ast_infer_types.erl +++ b/src/aeso_ast_infer_types.erl @@ -1133,9 +1133,11 @@ infer_case(Env, Attrs, Pattern, ExprType, Branch, SwitchType) -> %% NewStmts = infer_block(Env, Attrs, Stmts, BlockType) infer_block(_Env, Attrs, [], BlockType) -> error({impossible, empty_block, Attrs, BlockType}); -infer_block(Env, Attrs, [Def={letfun, _, _, _, _, _}|Rest], BlockType) -> - NewDef = infer_letfun(Env, Def), - [NewDef|infer_block(Env, Attrs, Rest, BlockType)]; +infer_block(Env, Attrs, [Def={letfun, Ann, _, _, _, _}|Rest], BlockType) -> + {{Name, TypeSig}, LetFun} = infer_letfun(Env, Def), + FunT = freshen_type(typesig_to_fun_t(TypeSig)), + NewE = bind_var({id, Ann, Name}, FunT, Env), + [LetFun|infer_block(NewE, Attrs, Rest, BlockType)]; infer_block(Env, Attrs, [Def={letrec, _, _}|Rest], BlockType) -> NewDef = infer_letrec(Env, Def), [NewDef|infer_block(Env, Attrs, Rest, BlockType)]; diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index 0e06cac..76f64ad 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -722,6 +722,9 @@ decision_tree_to_fcode({'if', A, Then, Else}) -> -spec stmts_to_fcode(env(), [aeso_syntax:stmt()]) -> fexpr(). stmts_to_fcode(Env, [{letval, _, {typed, _, {id, _, X}, _}, _, Expr} | Stmts]) -> {'let', X, expr_to_fcode(Env, Expr), stmts_to_fcode(bind_var(Env, X), Stmts)}; +stmts_to_fcode(Env, [{letfun, Ann, {id, _, X}, Args, _Type, Expr} | Stmts]) -> + {'let', X, expr_to_fcode(Env, {lam, Ann, Args, Expr}), + stmts_to_fcode(bind_var(Env, X), Stmts)}; stmts_to_fcode(Env, [Expr]) -> expr_to_fcode(Env, Expr); stmts_to_fcode(Env, [Expr | Stmts]) -> diff --git a/src/aeso_ast_to_icode.erl b/src/aeso_ast_to_icode.erl index 7ff8d6a..ca71d04 100644 --- a/src/aeso_ast_to_icode.erl +++ b/src/aeso_ast_to_icode.erl @@ -530,6 +530,8 @@ ast_body({switch,_,A,Cases}, Icode) -> ast_body({block,As,[{letval,_,Pat,_,E}|Rest]}, Icode) -> #switch{expr=ast_body(E, Icode), cases=[{ast_body(Pat, Icode),ast_body({block,As,Rest}, Icode)}]}; +ast_body({block, As, [{letfun, Ann, F, Args, _Type, Expr} | Rest]}, Icode) -> + ast_body({block, As, [{letval, Ann, F, unused, {lam, Ann, Args, Expr}} | Rest]}, Icode); ast_body({block,_,[]}, _Icode) -> #tuple{cpts=[]}; ast_body({block,_,[E]}, Icode) -> diff --git a/test/aeso_compiler_tests.erl b/test/aeso_compiler_tests.erl index fb630b7..dffb324 100644 --- a/test/aeso_compiler_tests.erl +++ b/test/aeso_compiler_tests.erl @@ -86,6 +86,7 @@ compilable_contracts() -> "dutch_auction", "environment", "factorial", + "functions", "fundme", "identity", "maps", diff --git a/test/contracts/functions.aes b/test/contracts/functions.aes new file mode 100644 index 0000000..058950c --- /dev/null +++ b/test/contracts/functions.aes @@ -0,0 +1,15 @@ +contract Functions = + private function curry(f : ('a, 'b) => 'c) = + (x) => (y) => f(x, y) + private function map(f : 'a => 'b, xs : list('a)) = + switch(xs) + [] => [] + x :: xs => f(x) :: map(f, xs) + private function map'() = map + private function plus(x, y) = x + y + function test1(xs : list(int)) = map(curry(plus)(5), xs) + function test2(xs : list(int)) = map'()(((x) => (y) => ((x, y) => x + y)(x, y))(100), xs) + function test3(xs : list(int)) = + let m(f, xs) = map(f, xs) + m((x) => x + 1, xs) +