Introduce pipe operator |> (#371)
* Add pipe operator * Add tests * Update docs and CHANGELOG
This commit is contained in:
parent
cfcf0a8a81
commit
74aff5401b
@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
### Added
|
### Added
|
||||||
- Compiler warnings for the follwing: shadowing, negative spends, division by zero, unused functions, unused includes, unused stateful annotations, unused variables, unused parameters, unused user-defined type, dead return value.
|
- Compiler warnings for the follwing: shadowing, negative spends, division by zero, unused functions, unused includes, unused stateful annotations, unused variables, unused parameters, unused user-defined type, dead return value.
|
||||||
|
- The pipe operator |>
|
||||||
|
```
|
||||||
|
[1, 2, 3] |> List.first |> Option.is_some // Option.is_some(List.first([1, 2, 3]))
|
||||||
|
```
|
||||||
### Changed
|
### Changed
|
||||||
- Error messages have been restructured (less newlines) to provide more unified errors. Also `pp_oneline/1` has been added.
|
- Error messages have been restructured (less newlines) to provide more unified errors. Also `pp_oneline/1` has been added.
|
||||||
### Removed
|
### Removed
|
||||||
|
@ -234,6 +234,7 @@ Path ::= Id // Record field
|
|||||||
|
|
||||||
BinOp ::= '||' | '&&' | '<' | '>' | '=<' | '>=' | '==' | '!='
|
BinOp ::= '||' | '&&' | '<' | '>' | '=<' | '>=' | '==' | '!='
|
||||||
| '::' | '++' | '+' | '-' | '*' | '/' | 'mod' | '^'
|
| '::' | '++' | '+' | '-' | '*' | '/' | 'mod' | '^'
|
||||||
|
| '|>'
|
||||||
UnOp ::= '-' | '!'
|
UnOp ::= '-' | '!'
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -245,6 +246,7 @@ UnOp ::= '-' | '!'
|
|||||||
| `!` `&&` `\|\|` | logical operators
|
| `!` `&&` `\|\|` | logical operators
|
||||||
| `==` `!=` `<` `>` `=<` `>=` | comparison operators
|
| `==` `!=` `<` `>` `=<` `>=` | comparison operators
|
||||||
| `::` `++` | list operators
|
| `::` `++` | list operators
|
||||||
|
| `\|>` | functional operators
|
||||||
|
|
||||||
## Operator precendences
|
## Operator precendences
|
||||||
|
|
||||||
@ -261,3 +263,4 @@ In order of highest to lowest precedence.
|
|||||||
| `<` `>` `=<` `>=` `==` `!=` | none
|
| `<` `>` `=<` `>=` `==` `!=` | none
|
||||||
| `&&` | right
|
| `&&` | right
|
||||||
| `\|\|` | right
|
| `\|\|` | right
|
||||||
|
| `\|>` | left
|
||||||
|
@ -1941,7 +1941,12 @@ infer_infix({'::', As}) ->
|
|||||||
infer_infix({'++', As}) ->
|
infer_infix({'++', As}) ->
|
||||||
ElemType = fresh_uvar(As),
|
ElemType = fresh_uvar(As),
|
||||||
ListType = {app_t, As, {id, As, "list"}, [ElemType]},
|
ListType = {app_t, As, {id, As, "list"}, [ElemType]},
|
||||||
{fun_t, As, [], [ListType, ListType], ListType}.
|
{fun_t, As, [], [ListType, ListType], ListType};
|
||||||
|
infer_infix({'|>', As}) ->
|
||||||
|
ArgType = fresh_uvar(As),
|
||||||
|
ResType = fresh_uvar(As),
|
||||||
|
FunType = {fun_t, As, [], [ArgType], ResType},
|
||||||
|
{fun_t, As, [], [ArgType, FunType], ResType}.
|
||||||
|
|
||||||
infer_prefix({'!',As}) ->
|
infer_prefix({'!',As}) ->
|
||||||
Bool = {id, As, "bool"},
|
Bool = {id, As, "bool"},
|
||||||
|
@ -703,8 +703,11 @@ expr_to_fcode(Env, _Type, {block, _, Stmts}) ->
|
|||||||
expr_to_fcode(Env, _Type, Expr = {app, _, {Op, _}, [_, _]}) when Op == '&&'; Op == '||' ->
|
expr_to_fcode(Env, _Type, Expr = {app, _, {Op, _}, [_, _]}) when Op == '&&'; Op == '||' ->
|
||||||
Tree = expr_to_decision_tree(Env, Expr),
|
Tree = expr_to_decision_tree(Env, Expr),
|
||||||
decision_tree_to_fcode(Tree);
|
decision_tree_to_fcode(Tree);
|
||||||
expr_to_fcode(Env, _Type, {app, _Ann, {Op, _}, [A, B]}) when is_atom(Op) ->
|
expr_to_fcode(Env, Type, {app, Ann, {Op, _}, [A, B]}) when is_atom(Op) ->
|
||||||
{op, Op, [expr_to_fcode(Env, A), expr_to_fcode(Env, B)]};
|
case Op of
|
||||||
|
'|>' -> expr_to_fcode(Env, Type, {app, Ann, B, [A]});
|
||||||
|
_ -> {op, Op, [expr_to_fcode(Env, A), expr_to_fcode(Env, B)]}
|
||||||
|
end;
|
||||||
expr_to_fcode(Env, _Type, {app, _Ann, {Op, _}, [A]}) when is_atom(Op) ->
|
expr_to_fcode(Env, _Type, {app, _Ann, {Op, _}, [A]}) when is_atom(Op) ->
|
||||||
case Op of
|
case Op of
|
||||||
'-' -> {op, '-', [{lit, {int, 0}}, expr_to_fcode(Env, A)]};
|
'-' -> {op, '-', [{lit, {int, 0}}, expr_to_fcode(Env, A)]};
|
||||||
|
@ -308,17 +308,18 @@ expr() -> expr100().
|
|||||||
|
|
||||||
expr100() ->
|
expr100() ->
|
||||||
Expr100 = ?LAZY_P(expr100()),
|
Expr100 = ?LAZY_P(expr100()),
|
||||||
Expr200 = ?LAZY_P(expr200()),
|
Expr150 = ?LAZY_P(expr150()),
|
||||||
choice(
|
choice(
|
||||||
[ ?RULE(lam_args(), keyword('=>'), body(), {lam, _2, _1, _3}) %% TODO: better location
|
[ ?RULE(lam_args(), keyword('=>'), body(), {lam, _2, _1, _3}) %% TODO: better location
|
||||||
, {'if', keyword('if'), parens(Expr100), Expr200, right(tok(else), Expr100)}
|
, {'if', keyword('if'), parens(Expr100), Expr150, right(tok(else), Expr100)}
|
||||||
, ?RULE(Expr200, optional(right(tok(':'), type())),
|
, ?RULE(Expr150, optional(right(tok(':'), type())),
|
||||||
case _2 of
|
case _2 of
|
||||||
none -> _1;
|
none -> _1;
|
||||||
{ok, Type} -> {typed, get_ann(_1), _1, Type}
|
{ok, Type} -> {typed, get_ann(_1), _1, Type}
|
||||||
end)
|
end)
|
||||||
]).
|
]).
|
||||||
|
|
||||||
|
expr150() -> infixl(expr200(), binop('|>')).
|
||||||
expr200() -> infixr(expr300(), binop('||')).
|
expr200() -> infixr(expr300(), binop('||')).
|
||||||
expr300() -> infixr(expr400(), binop('&&')).
|
expr300() -> infixr(expr400(), binop('&&')).
|
||||||
expr400() -> infix(expr500(), binop(['<', '>', '=<', '>=', '==', '!='])).
|
expr400() -> infix(expr500(), binop(['<', '>', '=<', '>=', '==', '!='])).
|
||||||
|
@ -218,6 +218,7 @@ compilable_contracts() ->
|
|||||||
"using_namespace",
|
"using_namespace",
|
||||||
"assign_patterns",
|
"assign_patterns",
|
||||||
"patterns_guards",
|
"patterns_guards",
|
||||||
|
"pipe_operator",
|
||||||
"test" % Custom general-purpose test file. Keep it last on the list.
|
"test" % Custom general-purpose test file. Keep it last on the list.
|
||||||
].
|
].
|
||||||
|
|
||||||
|
18
test/contracts/pipe_operator.aes
Normal file
18
test/contracts/pipe_operator.aes
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
contract Main =
|
||||||
|
function is_negative(x : int) =
|
||||||
|
if (x < 0)
|
||||||
|
true
|
||||||
|
else
|
||||||
|
false
|
||||||
|
|
||||||
|
function inc_by_one(x : int) = x + 1
|
||||||
|
function inc_by_two(x : int) = x + 2
|
||||||
|
|
||||||
|
type state = bool
|
||||||
|
|
||||||
|
entrypoint init(x : int) = x
|
||||||
|
|> inc_by_one
|
||||||
|
|> inc_by_one
|
||||||
|
|> inc_by_two
|
||||||
|
|> ((x) => x * 5)
|
||||||
|
|> is_negative
|
Loading…
x
Reference in New Issue
Block a user