%% operation(A, B) = A |->| B %% task(B) = operation((), B) = () |->| B = || %% operation(A, B) ::= func_F(A, B) %% | value_X(A, B) %% | pipe_Op1,...,Op_I(A, B) %% | par_Op1,...,Op_I(A, B) %% | route_N,M,R(A, B) %% | sync_N(A, B) %% | split_N(A, B) %% | merge_N(A, B) %% | switch_I,N(A, B) %% func_F(A_1 * ... * A_n, B) ::= { in = arity(F) : number, code = F } %% where F : fun(A_1, ..., A_n) -> B -record(func, {in, code}). %% value_X((), B) ::= { value = X } %% where X : B -record(value, {value}). %% pipe_Op_1,Op_2,...,Op_I(A_1_1 * ... * A_1_N1, B_1 * ... * B_M) ::= %% { in = N1 : number, out = M : number, %% ops : [ Op_1, Op_2, ..., Op_i ] } %% where Op_1 : A_1_1 * ... * A_1_N1 |->| A_2_1 * ... * A_2_N2 %% Op_2 : A_2_1 * ... * A_2_N2 |->| A_3_1 * ... * A_3_N3 %% ... %% Op_I : A_I_1 * ... * A_I_NI |->| B_1 * ... * B_M -record(pipe, {in, out, ops}). %% par_Op_1,Op2_,...,Op_I(A, B) ::= %% { in = size(A) : number, %% out = size(B) : number, %% ops : [ Op_1, Op_2, ..., Op_I ] } %% where Op_1 : A_1 |->| B_1 %% Op_2 : A_2 |->| B_2 %% ... %% Op_I : A_I |->| B_I %% A = flatten([A_1, A_2, ..., A_I]) %% B = flatten([B_1, B_2, ..., B_I]) -record(par, {in, out, ops}). %% route_N,M,R(A, [ sources(R, Target) || Target <- [1..M] ]) ::= %% { in = N, out = M, map = R } %% where N : number, M : number %% R : [{source, target}] %% source : [1..N], target : [1..M] -record(route, {in, out, map}). %% sync_N(A_1 * ... * A_N, A_1 * ... A_N) ::= { size = N : number } -record(sync, {size}). %% split_N(unit(A_1 * ... * A_N), A_1 * ... * A_N) ::= { size = N : number } -record(split, {size}). %% merge_N(A_1 * ... * A_N, unit(A_1 * ... * A_N)) ::= { size = N : number } -record(merge, {size}). %% switch_Op_1,...,Op_I((T_1 + ... + T_I) * A_1 * ... * A_N, %% (B_1_1 + ... + B_I_1) * ... * (B_1_M + ... + B_I_M)) ::= %% { in = 1+N : number, out = M : number, %% map : [ {T_J, Op_J} || J <- [1..I] ] } %% where Op_1 : A_1 * ... * A_N |->| B_1_1 * ... * B_1_M %% ... %% Op_I : A_1 * ... * A_N |->| B_I_1 * ... * B_I_M -record(switch, {in, out, map}).