Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 93 additions & 1 deletion apps/ff_core/src/ff_pipeline.erl
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,21 @@

-module(ff_pipeline).

-include_lib("syntax_tools/include/merl.hrl").

-export([do/1]).
-export([do/2]).
-export([unwrap/1]).
-export([unwrap/2]).
-export([wrap/1]).
-export([expect/2]).
-export([flip/1]).
-export([valid/2]).

-export([with/3]).

-export([parse_transform/2]).

%%

-type thrown(_E) ::
Expand All @@ -42,7 +47,7 @@ do(Fun) ->
ok | result(T, {Tag, E}).

do(Tag, Fun) ->
do(fun () -> unwrap(Tag, do(Fun)) end).
ff_pipeline:do(fun () -> unwrap(Tag, do(Fun)) end).

-spec unwrap
(ok) -> ok;
Expand All @@ -56,6 +61,14 @@ unwrap({ok, V}) ->
unwrap({error, E}) ->
throw(E).

-spec wrap(any()) ->
ok | {ok, any()}.

wrap(ok) ->
ok;
wrap(V) ->
{ok, V}.

-spec expect
(_E, ok) -> ok;
(_E, {ok, V}) -> V;
Expand Down Expand Up @@ -117,3 +130,82 @@ with(Model, St, F) ->
{error, Reason} ->
{error, {Model, Reason}}
end.

%% Parse transform
% -import(ff_pipeline, [do/1, unwrap/1]).
% f() ->
% do(fun() ->
% R0 = 1,
% R1 = unwrap(do_smth(R0)),
% R2 = ff_pipeline:unwrap(do_smth2(R1)),
% R2 + 1
% end).
% To
% -import(ff_pipeline, [unwrap/1]).
% f() ->
% try
% ff_pipeline:wrap(begin
% R0 = 1,
% R1 = unwrap(do_smth(R0)),
% R2 = ff_pipeline:unwrap(do_smth2(R1)),
% R2 + 1
% end)
% catch
% Thrown -> {error, Thrown}
% end.

-spec parse_transform(Forms, [compile:option()]) -> Forms when
Forms :: [erl_parse:abstract_form() | erl_parse:form_info()].
parse_transform(Forms, _Options) ->
[erl_syntax:revert(erl_syntax_lib:map(fun transform_do/1, Form)) || Form <- Forms].

transform_do(Tree) ->
TreePos = erl_syntax:get_pos(Tree),
case Tree of
?Q("do(_@Tag, fun() -> _@@Body end)") ->

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Мне кажется не очень корректным перефигачивать конструкции с do(...), даже в том случае, если эту псевдофункцию не импортировали в модуль. Кажется лучше было бы пойти по одному из двух путей:

  • перефигачивать, только если был импорт;
  • перефигачивать вообще все do, не требуя никаких имортов, только включения parse transform (не пытаться сделать вид, что do ‒ это функция в модуле ff_pipeline).

@ciiol ciiol Aug 14, 2019

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Да, согласен, это не достаточно явно.

перефигачивать, только если был импорт;

Попробую сделать.

перефигачивать вообще все do, не требуя никаких имортов

На это агрятся IDE. Плагин, что я использовал, ожидаемо не смог обработать parse transform.

Ну и, справедливости ради, do это все же функция ff_pipeline, тут делается что-то вроде инлайнинга частных случаев.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Попробую сделать.

👍

На это агрятся IDE. Плагин, что я использовал, ожидаемо не смог обработать parse transform.

Забавно, я не считаю это ожидаемым поведением. Это же просто ещё одна опция компиляции.

Ну и, справедливости ради, do это все же функция ff_pipeline, тут делается что-то вроде инлайнинга.

О, это я упустил.

build_do_statement(TreePos, Tag, Body);
?Q("ff_pipeline:do(_@Tag, fun() -> _@@Body end)") ->
build_do_statement(TreePos, Tag, Body);
?Q("do(fun() -> _@@Body end)") ->
build_do_statement(TreePos, Body);
?Q("ff_pipeline:do(fun() -> _@@Body end)") ->
build_do_statement(TreePos, Body);
?Q("-import(ff_pipeline, ['@_@Imports'/0]).") ->
build_import_statement(TreePos, Imports);
_ ->
Tree
end.

build_do_statement(Pos, Body) ->
ThrownVar = build_var(<<"Thrown">>, Pos),
build_do_statement(Pos, ThrownVar, ThrownVar, Body).

build_do_statement(Pos, Tag, Body) ->
ThrownVar = build_var(<<"Thrown">>, Pos),
Error = ?Q("{_@Tag, _@ThrownVar}"),
build_do_statement(Pos, ThrownVar, Error, Body).

build_do_statement(_Pos, ThrownVar, Error, Body) ->
?Q([
"try ff_pipeline:wrap(begin _@@Body end)",
"catch _@ThrownVar -> {error, _@Error} end"
]).

build_import_statement(_Pos, Imports) ->
FilteredImports = lists:filter(fun is_import_not_replaced/1, Imports),
?Q("-import(ff_pipeline, ['@_@FilteredImports'/0]).").

is_import_not_replaced(ImportItem) ->
case ?Q("-export(['@_ImportItem'/0]).") of

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Очень долго думал, почему тут export. Может комментом описать, что тут происходит и почему так?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Да, добавлю. Или посмотрю, чем из erl_syntax можно воспользоваться чтобы стало понятнее.

Это нужно потому, что грамматика языка не позволяет однозначно распарсить do/1. И, по-умолчанию, приоритет отдается предположению, что это деление атома на число. Как конструкцию "нечто с арностью" парсер интерпретирует это выражение только когда оно находится внутри атрибутов модуля. Причем не всех, а только известных ему.

?Q("-export([do/1]).") ->
false;
?Q("-export([do/2]).") ->
false;
_ ->
true
end.

build_var(Name, Line) ->
LineStr = erlang:integer_to_binary(Line),
VarName = erlang:binary_to_atom(<<"$Pipeline", Name/binary, "-", LineStr/binary>>, latin1),
merl:var(VarName).
1 change: 1 addition & 0 deletions apps/ff_transfer/src/ff_deposit.erl
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@

%% Pipeline

-compile({parse_transform, ff_pipeline}).
-import(ff_pipeline, [do/1, unwrap/1, unwrap/2, valid/2]).

%% Internal types
Expand Down
1 change: 1 addition & 0 deletions apps/ff_transfer/src/ff_instrument.erl
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@

%% Pipeline

-compile({parse_transform, ff_pipeline}).
-import(ff_pipeline, [do/1, unwrap/1, unwrap/2]).

%% Accessors
Expand Down
1 change: 1 addition & 0 deletions apps/ff_transfer/src/ff_instrument_machine.erl
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@

%% Pipeline

-compile({parse_transform, ff_pipeline}).
-import(ff_pipeline, [do/1, unwrap/1]).

%%
Expand Down
1 change: 1 addition & 0 deletions apps/ff_transfer/src/ff_transfer.erl
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@

%% Pipeline

-compile({parse_transform, ff_pipeline}).
-import(ff_pipeline, [do/1, unwrap/1, with/3]).

%% Internal types
Expand Down
1 change: 1 addition & 0 deletions apps/ff_transfer/src/ff_transfer_machine.erl
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@

%% Pipeline

-compile({parse_transform, ff_pipeline}).
-import(ff_pipeline, [do/1, unwrap/1]).

%% Internal types
Expand Down
1 change: 1 addition & 0 deletions apps/ff_transfer/src/ff_withdrawal.erl
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@

%% Pipeline

-compile({parse_transform, ff_pipeline}).
-import(ff_pipeline, [do/1, unwrap/1, unwrap/2, valid/2]).

%% Internal types
Expand Down
1 change: 1 addition & 0 deletions apps/ff_transfer/src/ff_withdrawal_session.erl
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@

%% Pipeline

-compile({parse_transform, ff_pipeline}).
-import(ff_pipeline, [unwrap/1]).

%%
Expand Down
1 change: 1 addition & 0 deletions apps/ff_transfer/src/ff_withdrawal_session_machine.erl
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@

%% Pipeline

-compile({parse_transform, ff_pipeline}).
-import(ff_pipeline, [do/1, unwrap/1]).

%%
Expand Down
1 change: 1 addition & 0 deletions apps/fistful/src/ff_account.erl
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@

%% Pipeline

-compile({parse_transform, ff_pipeline}).
-import(ff_pipeline, [do/1, unwrap/1, unwrap/2]).

%% Internal types
Expand Down
1 change: 1 addition & 0 deletions apps/fistful/src/ff_cash_flow.erl
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@

%% Pipeline

-compile({parse_transform, ff_pipeline}).
-import(ff_pipeline, [do/1, unwrap/1, unwrap/2]).

%% Internal types
Expand Down
1 change: 1 addition & 0 deletions apps/fistful/src/ff_currency.erl
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

%% Pipeline

-compile({parse_transform, ff_pipeline}).
-import(ff_pipeline, [do/1, unwrap/1]).

%% Accessors
Expand Down
1 change: 1 addition & 0 deletions apps/fistful/src/ff_identity.erl
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@

%% Pipeline

-compile({parse_transform, ff_pipeline}).
-import(ff_pipeline, [do/1, unwrap/1, unwrap/2, expect/2, flip/1, valid/2]).

%% Accessors
Expand Down
1 change: 1 addition & 0 deletions apps/fistful/src/ff_identity_challenge.erl
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@

%% Pipeline

-compile({parse_transform, ff_pipeline}).
-import(ff_pipeline, [do/1, unwrap/1, valid/2]).

%%
Expand Down
1 change: 1 addition & 0 deletions apps/fistful/src/ff_identity_machine.erl
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@

%% Pipeline

-compile({parse_transform, ff_pipeline}).
-import(ff_pipeline, [do/1, do/2, unwrap/1]).

-define(NS, 'ff/identity').
Expand Down
1 change: 1 addition & 0 deletions apps/fistful/src/ff_machine.erl
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@

%% Pipeline helpers

-compile({parse_transform, ff_pipeline}).
-import(ff_pipeline, [do/1, unwrap/1]).

%% Internal types
Expand Down
1 change: 1 addition & 0 deletions apps/fistful/src/ff_party.erl
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@

%% Pipeline

-compile({parse_transform, ff_pipeline}).
-import(ff_pipeline, [do/1, unwrap/1, unwrap/2]).

%%
Expand Down
1 change: 1 addition & 0 deletions apps/fistful/src/ff_payment_institution.erl
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

%% Pipeline

-compile({parse_transform, ff_pipeline}).
-import(ff_pipeline, [do/1, unwrap/1]).

%%
Expand Down
1 change: 1 addition & 0 deletions apps/fistful/src/ff_payouts_provider.erl
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

%% Pipeline

-compile({parse_transform, ff_pipeline}).
-import(ff_pipeline, [do/1, unwrap/1]).

%%
Expand Down
1 change: 1 addition & 0 deletions apps/fistful/src/ff_postings_transfer.erl
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@

%% Pipeline

-compile({parse_transform, ff_pipeline}).
-import(ff_pipeline, [do/1, unwrap/1, unwrap/2, valid/2]).

%% Internal types
Expand Down
1 change: 1 addition & 0 deletions apps/fistful/src/ff_provider.erl
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@

%% Pipeline

-compile({parse_transform, ff_pipeline}).
-import(ff_pipeline, [do/1, unwrap/1]).

%%
Expand Down
1 change: 1 addition & 0 deletions apps/fistful/src/ff_wallet.erl
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@

%% Pipeline

-compile({parse_transform, ff_pipeline}).
-import(ff_pipeline, [do/1, unwrap/1, unwrap/2]).

%% Accessors
Expand Down
1 change: 1 addition & 0 deletions apps/fistful/src/ff_wallet_machine.erl
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@

%% Pipeline

-compile({parse_transform, ff_pipeline}).
-import(ff_pipeline, [do/1, unwrap/1]).

-define(NS, 'ff/wallet_v2').
Expand Down
4 changes: 2 additions & 2 deletions apps/fistful/test/ff_identity_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
%%

-import(ct_helper, [cfg/2]).
-import(ff_pipeline, [unwrap/1]).

-type config() :: ct_helper:config().
-type test_case_name() :: ct_helper:test_case_name().
Expand Down Expand Up @@ -153,7 +152,8 @@ create_ok(C) ->
},
ff_ctx:new()
),
I1 = ff_identity_machine:identity(unwrap(ff_identity_machine:get(ID))),
{ok, IdentityMachine} = ff_identity_machine:get(ID),
I1 = ff_identity_machine:identity(IdentityMachine),
{ok, accessible} = ff_identity:is_accessible(I1),
Party = ff_identity:party(I1),
Party = ff_identity:party(I1).
Expand Down
4 changes: 2 additions & 2 deletions apps/fistful/test/ff_wallet_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
%%

-import(ct_helper, [cfg/2]).
-import(ff_pipeline, [unwrap/1]).

-type config() :: ct_helper:config().
-type test_case_name() :: ct_helper:test_case_name().
Expand Down Expand Up @@ -160,7 +159,8 @@ create_wallet_ok(C) ->
},
ff_ctx:new()
),
Wallet = ff_wallet_machine:wallet(unwrap(ff_wallet_machine:get(ID))),
{ok, WalletMachine} = ff_wallet_machine:get(ID),
Wallet = ff_wallet_machine:wallet(WalletMachine),
{ok, accessible} = ff_wallet:is_accessible(Wallet),
Account = ff_account:accounter_account_id(ff_wallet:account(Wallet)),
{ok, {Amount, <<"RUB">>}} = ff_transaction:balance(Account),
Expand Down
14 changes: 5 additions & 9 deletions apps/wapi/src/wapi_wallet_ff_backend.erl
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@

-dialyzer([{nowarn_function, [to_swag/2]}]).

%% Pipeline

-compile({parse_transform, ff_pipeline}).
-import(ff_pipeline, [do/1, unwrap/1, unwrap/2]).

%% API

%% Providers
Expand Down Expand Up @@ -836,15 +841,6 @@ get_email(AuthContext) ->
not_implemented() ->
wapi_handler_utils:throw_not_implemented().

do(Fun) ->
ff_pipeline:do(Fun).

unwrap(Res) ->
ff_pipeline:unwrap(Res).

unwrap(Tag, Res) ->
ff_pipeline:unwrap(Tag, Res).

valid(Val1, Val2) ->
ff_pipeline:valid(Val1, Val2).

Expand Down
3 changes: 2 additions & 1 deletion rebar.config
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@
race_conditions,
unknown
]},
{plt_apps, all_deps}
{plt_apps, all_deps},
{plt_extra_apps, [syntax_tools, compiler]} %% for ff_pipeline parse transform
]}.

{profiles, [
Expand Down