ソースを参照

Added the ebb_flow module.

The ebb_flow module contains a nicer interface for building programs than the
primitive operations alone.
Paul Downen 13 年 前
コミット
5e6f9403ea
1 ファイル変更101 行追加0 行削除
  1. 101 0
      src/ebb_flow.erl

+ 101 - 0
src/ebb_flow.erl

@@ -0,0 +1,101 @@
+-module(ebb_flow).
+
+%%% Convenience operations
+-export([id/0, id/1, nop/0, select/2]).
+
+%%% Parallelism
+-export([fanout/1, fanout/2]).
+
+%%% Sequencing
+-export([seq/1]).
+
+%%% Choice
+-export([cases/1, case_of/2,
+	 iff/2, if_else/3,
+	 fanin/1, fanin/2]).
+
+%%%-----------------------------------------------------------------------------
+%%% Convenience operations
+%%%-----------------------------------------------------------------------------
+
+id() ->
+    ebb_prim:route(1, [1]).
+
+id(N) ->
+    ebb_prim:route(N, lists:seq(1,N)).
+
+nop() ->
+    ebb_prim:value('nop').
+
+select(I, N) ->
+    ebb_prim:route(N, [I]).
+
+%%%-----------------------------------------------------------------------------
+%%% Parallelism
+%%%-----------------------------------------------------------------------------
+
+fanout(Copies) ->
+    fanout(1, Copies).
+
+fanout(In, Copies) ->
+    Out = Copies*In,
+    ebb_prim:route(In, [ (I rem In) + 1 || I <- lists:seq(0, Out-1) ]).
+
+%%%-----------------------------------------------------------------------------
+%%% Sequencing
+%%%-----------------------------------------------------------------------------
+
+seq(Ops = [Op1|Rest]) ->
+    {In, _} = ebb_prim:flatten_arity(Ops),
+    {Seq, _, _} =
+	lists:foldl(fun(Op, {Seq,Produced,Remaining}) ->
+			    Sync = ebb_prim:sync(Produced+Remaining),
+			    {ebb_prim:pipe(
+			       [Seq, Sync,
+				build_seq_step(Op, Produced, Remaining)]),
+			     Produced+ebb_prim:out_arity(Op),
+			     Remaining-ebb_prim:in_arity(Op)}
+		    end,
+		    {build_seq_step(Op1, 0, In),
+		     ebb_prim:out_arity(Op1),
+		     In-ebb_prim:in_arity(Op1)},
+		    Rest),
+    Seq.
+
+build_seq_step(Op, Produced, Remaining) ->
+    case {Produced, Remaining-ebb_prim:in_arity(Op)} of
+	{0, 0}          -> Op;
+	{_, 0}          -> ebb_prim:par([id(Produced), Op]);
+	{0, Remaining2} -> ebb_prim:par([Op, id(Remaining2)]);
+	{_, Remaining2} -> ebb_prim:par([id(Produced), Op, id(Remaining2)])
+    end.
+
+%%%-----------------------------------------------------------------------------
+%%% Choice
+%%%-----------------------------------------------------------------------------
+
+cases(Branches) ->
+    ebb_prim:switch(Branches).
+
+case_of(Disc, Branches) ->
+    Cases = cases(Branches),
+    case ebb_prim:in_arity(Cases)-1 of
+	0 -> ebb_prim:pipe([Disc, Cases]);
+	In -> ebb_prim:pipe(
+		[ebb_prim:par([Disc, id(In)]),
+		 Cases])
+    end.
+
+iff(Then, Else) ->
+    cases([{true, Then}, {false, Else}]).
+
+if_else(Test, Then, Else) ->
+    case_of(Test, [{true, Then}, {false, Else}]).
+
+fanin(Copies) ->
+    cases([ {I , select(I, Copies)} || I <- lists:seq(1, Copies) ]).
+
+fanin(Copies, Out) ->
+    In = Copies*Out,
+    cases([ {I, ebb_prim:route(In, [ (I-1)*Out + J || J <- lists:seq(1, Out)])}
+	    || I <- lists:seq(1, Copies) ]).