123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 |
- -module(ebb_prim).
- -include("../include/ebb_prim.hrl").
- %%% Operation construction
- -export([func/1, value/1,
- pipe/1, par/1,
- route/2, sync/1,
- split/1, merge/1,
- switch/1]).
- %%% Operation querying
- -export([is_operation/1,
- in_arity/1, out_arity/1,
- flatten_arity/1,
- can_connect/2]).
- %%%-----------------------------------------------------------------------------
- %%% Operation construction
- %%%-----------------------------------------------------------------------------
- func(F) when is_function(F) ->
- {arity, N} = erlang:fun_info(F, arity),
- #func{in=N, code=F}.
- value(X) -> #value{value=X}.
- pipe(Ops = [First|Rest]) ->
- try
- lists:foldl(fun(Op2, Op1) -> case is_operation(Op2) andalso
- can_connect(Op1, Op2) of
- true -> Op2;
- false -> throw(badarg)
- end
- end,
- case is_operation(First) of
- true -> First;
- false -> throw(badarg)
- end,
- Rest)
- of
- Last -> #pipe{in=in_arity(First), out=out_arity(Last), ops=Ops}
- catch
- throw:badarg -> erlang:error(badarg, [Ops])
- end.
- par(Ops = [_|_]) ->
- case lists:all(fun is_operation/1, Ops) of
- true -> ok;
- false -> erlang:error(badarg, [Ops])
- end,
- {In, Out} = flatten_arity(Ops),
- #par{in=In, out=Out, ops=Ops}.
- route(N, Map) when is_number(N) ->
- Good = lists:all(fun(Source) ->is_number(Source) andalso
- Source > 0 andalso Source =< N
- end,
- Map),
- case Good of
- true -> #route{in=N, out=length(Map), map=Map};
- false -> erlang:error(badarg, [N, Map])
- end.
- sync(N) when is_number(N) -> #sync{size=N}.
- split(N) when is_number(N) -> #split{size=N}.
- merge(N) when is_number(N) -> #merge{size=N}.
- switch(Map = [{_Tag1, Op1}|Rest]) ->
- In = in_arity(Op1),
- Out = out_arity(Op1),
- Match = lists:all(
- fun({_T_I, Op}) ->
- is_operation(Op) andalso
- in_arity(Op) == In andalso out_arity(Op) == Out
- end,
- Rest),
- case Match of
- true -> #switch{in=1+In, out=Out, map=Map};
- false -> erlang:error(badarg, [Map])
- end.
- %%%-----------------------------------------------------------------------------
- %%% Operation querying
- %%%-----------------------------------------------------------------------------
- is_operation(#func{}) -> true;
- is_operation(#value{}) -> true;
- is_operation(#pipe{}) -> true;
- is_operation(#par{}) -> true;
- is_operation(#route{}) -> true;
- is_operation(#sync{}) -> true;
- is_operation(#split{}) -> true;
- is_operation(#merge{}) -> true;
- is_operation(#switch{}) -> true;
- is_operation(_) -> false.
- in_arity(#func{in=In}) -> In;
- in_arity(#value{}) -> 0;
- in_arity(#pipe{in=In}) -> In;
- in_arity(#par{in=In}) -> In;
- in_arity(#route{in=In}) -> In;
- in_arity(#sync{size=N}) -> N;
- in_arity(#split{}) -> 1;
- in_arity(#merge{size=N}) -> N;
- in_arity(#switch{in=In}) -> In.
- out_arity(#func{}) -> 1;
- out_arity(#value{}) -> 1;
- out_arity(#pipe{out=Out}) -> Out;
- out_arity(#par{out=Out}) -> Out;
- out_arity(#route{out=Out}) -> Out;
- out_arity(#sync{size=N}) -> N;
- out_arity(#split{size=N}) -> N;
- out_arity(#merge{}) -> 1;
- out_arity(#switch{out=Out}) -> Out.
- flatten_arity([First|Rest]) ->
- lists:foldl(fun(Op, {In, Out}) ->
- {In + in_arity(Op), Out + out_arity(Op)}
- end,
- {in_arity(First), out_arity(First)}, Rest).
- can_connect(Op1, Op2) ->
- case {out_arity(Op1), in_arity(Op2)} of
- {N, N} -> true;
- _ -> false
- end.
|