From 9308f5b41641ac538f7e804d5426a06dd68d5c7d Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Wed, 1 Jun 2022 14:27:21 +0400 Subject: [PATCH 1/7] Add operator lambdas --- src/aeso_parser.erl | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/aeso_parser.erl b/src/aeso_parser.erl index 7e5fa62..306bd13 100644 --- a/src/aeso_parser.erl +++ b/src/aeso_parser.erl @@ -335,7 +335,7 @@ exprAtom() -> ?LAZY_P(begin Expr = ?LAZY_P(expr()), choice( - [ id_or_addr(), con(), token(qid), token(qcon) + [ id_or_addr(), con(), token(qid), token(qcon), binop_as_lam() , token(bytes), token(string), token(char) , token(int) , ?RULE(token(hex), set_ann(format, hex, setelement(1, _1, int))) @@ -472,6 +472,19 @@ id() -> token(id). tvar() -> token(tvar). str() -> token(string). +binop_as_lam() -> + BinOps = ['&&', '||', + '+', '-', '*', '/', '^', 'mod', + '==', '!=', '<', '>', '<=', '=<', '>=', + '..', '::', '++', '|>'], + OpToLam = fun(Op = {_, Ann}) -> + IdL = {id, Ann, "l"}, + IdR = {id, Ann, "r"}, + Arg = fun(Id) -> {arg, Ann, Id, type_wildcard(Ann)} end, + {lam, Ann, [Arg(IdL), Arg(IdR)], infix(IdL, Op, IdR)} + end, + ?RULE(parens(choice(lists:map(fun token/1, BinOps))), OpToLam(_1)). + token(Tag) -> ?RULE(tok(Tag), case _1 of -- 2.30.2 From 8b2fdd5ab9c8910b5a1a3e0a423ea13ee09f0395 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Wed, 1 Jun 2022 14:27:51 +0400 Subject: [PATCH 2/7] Do not register anonymous functions as called functions --- src/aeso_ast_infer_types.erl | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/aeso_ast_infer_types.erl b/src/aeso_ast_infer_types.erl index 8af28ae..d7fd152 100644 --- a/src/aeso_ast_infer_types.erl +++ b/src/aeso_ast_infer_types.erl @@ -1641,7 +1641,10 @@ infer_expr(Env, {app, Ann, Fun, Args0} = App) -> GeneralResultType = fresh_uvar(Ann), ResultType = fresh_uvar(Ann), when_warning(warn_unused_functions, - fun() -> register_function_call(Namespace ++ qname(CurrentFun), Name) end), + fun() -> if element(1, Name) == lam -> ok; + true -> register_function_call(Namespace ++ qname(CurrentFun), Name) + end + end), unify(Env, FunType, {fun_t, [], NamedArgsVar, ArgTypes, GeneralResultType}, When), when_warning(warn_negative_spend, fun() -> warn_potential_negative_spend(Ann, NewFun1, NewArgs) end), add_constraint( -- 2.30.2 From c3f057c438c702d0f600b43f71ed36600bb4dc98 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Wed, 1 Jun 2022 14:28:30 +0400 Subject: [PATCH 3/7] Add tests --- test/aeso_compiler_tests.erl | 8 ++++++++ test/contracts/operator_lambdas.aes | 14 ++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 test/contracts/operator_lambdas.aes diff --git a/test/aeso_compiler_tests.erl b/test/aeso_compiler_tests.erl index fd1c9a1..13f07d0 100644 --- a/test/aeso_compiler_tests.erl +++ b/test/aeso_compiler_tests.erl @@ -795,6 +795,14 @@ failing_contracts() -> [<> ]) + , ?TYPE_ERROR(operator_lambdas, + [< int` and `(int) => 'a`\n" + "when checking the application of\n" + " `(l : _, r : _) => l + r : (int, int) => int`\n" + "to arguments\n" + " `1 : int`">> + ]) , ?TYPE_ERROR(warnings, [<>, diff --git a/test/contracts/operator_lambdas.aes b/test/contracts/operator_lambdas.aes new file mode 100644 index 0000000..ade8f20 --- /dev/null +++ b/test/contracts/operator_lambdas.aes @@ -0,0 +1,14 @@ +include "List.aes" + +contract C = + type state = int + + function sum(l : list(bool)) : bool = List.foldl((||), false, l) + + entrypoint init() = + let bad_application = (+)(1) + let good_application = (-)(3, 4) + let op_var = (+) + let op_var_application = op_var(3, 4) + + good_application + op_var_application \ No newline at end of file -- 2.30.2 From 4b81eb9646936f61669a8892c1c2a43b6d63f978 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Wed, 1 Jun 2022 14:32:04 +0400 Subject: [PATCH 4/7] Update CHANGELOG --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 486c81d..218866c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ``` [1, 2, 3] |> List.first |> Option.is_some // Option.is_some(List.first([1, 2, 3])) ``` +- Allow binary operators to be used as lambdas + ``` + function sum(l : list(int)) : int = foldl((+), 0, l) + function logical_and(x, y) = (&&)(x, y) + ``` ### Changed - Error messages have been restructured (less newlines) to provide more unified errors. Also `pp_oneline/1` has been added. - Ban empty record definitions (e.g. `record r = {}` would give an error). -- 2.30.2 From 7f19cf1700ec1732469aa57596c53b2f5b08468f Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Wed, 1 Jun 2022 14:38:16 +0400 Subject: [PATCH 5/7] Update the docs --- docs/sophia_syntax.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/sophia_syntax.md b/docs/sophia_syntax.md index b9c6aa0..a55fa60 100644 --- a/docs/sophia_syntax.md +++ b/docs/sophia_syntax.md @@ -200,6 +200,7 @@ switch(f(x)) ```c Expr ::= '(' LamArgs ')' '=>' Block(Stmt) // Anonymous function (x) => x + 1 + | '(' BinOp ')' // Operator lambda (+) | 'if' '(' Expr ')' Expr 'else' Expr // If expression if(x < y) y else x | Expr ':' Type // Type annotation 5 : int | Expr BinOp Expr // Binary operator x + y -- 2.30.2 From 8851629fc7f0b1d8599c6f30166b0437857d570b Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Thu, 2 Jun 2022 13:36:25 +0400 Subject: [PATCH 6/7] Do not allow (..) to be used as a lambda --- src/aeso_parser.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/aeso_parser.erl b/src/aeso_parser.erl index 306bd13..9175e0f 100644 --- a/src/aeso_parser.erl +++ b/src/aeso_parser.erl @@ -476,7 +476,7 @@ binop_as_lam() -> BinOps = ['&&', '||', '+', '-', '*', '/', '^', 'mod', '==', '!=', '<', '>', '<=', '=<', '>=', - '..', '::', '++', '|>'], + '::', '++', '|>'], OpToLam = fun(Op = {_, Ann}) -> IdL = {id, Ann, "l"}, IdR = {id, Ann, "r"}, -- 2.30.2 From 642f5a4da32090f2e1dd277b9d9b84482b3b8942 Mon Sep 17 00:00:00 2001 From: Gaith Hallak Date: Thu, 2 Jun 2022 13:36:38 +0400 Subject: [PATCH 7/7] Rename the function sum to any --- test/contracts/operator_lambdas.aes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/contracts/operator_lambdas.aes b/test/contracts/operator_lambdas.aes index ade8f20..9f5b41e 100644 --- a/test/contracts/operator_lambdas.aes +++ b/test/contracts/operator_lambdas.aes @@ -3,7 +3,7 @@ include "List.aes" contract C = type state = int - function sum(l : list(bool)) : bool = List.foldl((||), false, l) + function any(l : list(bool)) : bool = List.foldl((||), false, l) entrypoint init() = let bad_application = (+)(1) -- 2.30.2