sort
#x:action-sort
#x:modeling-sort
#x:enum-sort
#x:reply-sort
#x:event-sort

provides_ports = struct no_port?no_port_is#x:provides-port-construct;

requires_events
 = struct no_event
#x:requires-sort-construct
 ;

map

QueueLength : Nat;

remove : requires_events # List (requires_events) -> List(requires_events);

find : requires_events # List (requires_events) -> Bool;

var e, h: requires_events;
    t: List(requires_events);

eqn

QueueLength = #x:makreel:queue-length;

remove(e, []) = [];
remove(e, h |> t) = if((e == h), t, h |> remove(e,t));

find(e, []) = false;
find(e, h |> t) = if((e == h), true, find(e, t));


act
#x:event-act
#x:makreel:model-name end;
#x:makreel:model-name end';
async_not_pending;
async_not_pending';
async_pending;
async_pending';
queue_full;
queue_empty;
queue_empty';
queue_not_empty;
queue_not_empty';

%%%%%%%%%%%%%%%%% INTERFACE %%%%%%%%%%%%%%%%%

#x:interface-proc-memo

%%%%%%%%%%%%%% PORT PROCESSES %%%%%%%%%%%%%%%

#x:interface-action-proc

%%%%%%%%%%%%%%%%%%%%%%% PROVIDES %%%%%%%%%%%%%%%%%%%%%%%%%%

proc
provides_r2c = #x:provides-r2c-proc;

#x:provides-out-proc

provides_parallel = #x:provides-port-parallel-proc || provides_r2c;

provides_comm = comm ({
#x:provides-comm
 }, provides_parallel);

provides_allow = allow ({
   declarative_illegal
 , illegal
 , missing_reply
 , range_error
 , second_reply
 , tau_void
#x:provides-allow
 }, provides_comm);

provides_rename = rename ({
#x:provides-rename
 }, provides_allow);

provides = hide ({
   tau_void
 , #x:allow-tau
 }, provides_rename);

%%%%%%%%%%%%%%%%%%% COMPONENT %%%%%%%%%%%%%%%%%%%

#x:proc

component_behavior = #x:action-proc

%%%%%%%%%%%%%%%%%%%% Q %%%%%%%%%%%%%%%%%%%%%%

proc
#x:queue-proc
#x:no-queue-proc

async (l: List (requires_events))
 = (l != []) -> async_pending . async()
 + (l == []) -> async_not_pending . async()
#x:async-parallel-port
 ;

%%%%%%%%%%%%%%%%%%%%% COMPONENT REORDER %%%%%%%%%%%%%%%%%%%%%%%%%%%

component_reorder
 = #x:reorder-provides
 + #x:makreel:model-name end . component_reorder
 ;

#x:reorder-flush

component_reorder_block
 = #x:makreel:model-name end . component_reorder_block
 + #x:reorder-block
 ;

component_reorder_parallel = component_behavior || component_reorder;

component_reorder_comm = comm({
  #x:makreel:model-name end | #x:makreel:model-name end  -> #x:makreel:model-name end'
#x:reorder-comm-provides
 }, component_reorder_parallel);

component_reorder_allow = allow({
   #x:makreel:model-name end'
#x:reorder-allow-provides
#x:reorder-allow-requires
 , declarative_illegal
 , illegal
 , missing_reply
 , queue_empty
 , queue_not_empty
 , range_error
 , recurse
 , return
 , second_reply
 }, component_reorder_comm);

component_reordered = rename({
  #x:makreel:model-name end' -> #x:makreel:model-name end
#x:reorder-rename-provides
#x:reorder-rename-requires
 }, component_reorder_allow);

%%%%%%%%%%%%%%%%%%%%%%%%% SEMANTICS %%%%%%%%%%%%%%%%%%%%%%%%%%%

semantics
 = semantics_provides
#x:semantics-requires
 ;

semantics_provides
 = #x:semantics-provides
 ;

semantics_provides_unblocked
 = #x:semantics-provides-unblocked
 + #x:makreel:model-name end . (queue_empty . (#x:semantics-provides-unblocked-replies)
                               #x:semantics-provides-flush)
 ;

semantics_async(port: provides_ports, pending: Bool)
 = #x:makreel:model-name end . (queue_empty . (async_not_pending . (no_port_is(port) -> semantics #x:semantics-requires-flush)
                                              +async_pending . (no_port_is(port) -> semantics_async_allow_ack(pending=true) #x:semantics-async-flush))
                               +queue_not_empty . (async_not_pending . semantics_async (pending=false)
                                                  +async_pending . semantics_async(pending=true)))



#x:semantics-async
#x:semantics-async-qout
#x:semantics-async-requires
 ;

semantics_async_allow_ack(port: provides_ports, pending: Bool) = #x:semantics-async-allow-ack #x:semantics-no-async
 ;

semantics_provides_blocked
 = #x:semantics-provides-replies #x:semantics-provides-blocked-provides #x:semantics-provides-blocked-requires #x:semantics-provides-blocked-async #x:semantics-provides-blocked-internal
 ;

component_semantics_parallel = component_reordered || semantics;

component_semantics_comm = comm({
   #x:makreel:model-name end | #x:makreel:model-name end -> #x:makreel:model-name end'
#x:semantics-comm-provides
#x:semantics-comm-requires
 }, component_semantics_parallel);

component_semantics_allow = allow({
   #x:makreel:model-name end'
 , #x:allow-tau
#x:semantics-allow-provides
#x:semantics-allow-requires
#x:semantics-allow-async
 , async_not_pending
 , async_pending
 , declarative_illegal
 , illegal
 , missing_reply
 , queue_empty
 , queue_not_empty
 , range_error
 , recurse
 , return
 , second_reply
 , tau_void
 }, component_semantics_comm);

component_semantics = rename({
   #x:makreel:model-name end' -> #x:makreel:model-name end
#x:semantics-rename-provides
#x:semantics-rename-requires
 }, component_semantics_allow);

%%%%%%%%%%%%%%%%%%%%% COMPONENT ASSEMBLY %%%%%%%%%%%%%%%%%%%%%%

component_parallel = component_semantics || req_and_queue;

component_comm = comm({
   async_not_pending | async_not_pending -> async_not_pending'
 , async_pending | async_pending -> async_pending'
 , queue_empty | queue_empty -> queue_empty'
 , queue_not_empty | queue_not_empty -> queue_not_empty'
#x:component-comm-requires
#x:component-comm-async
 }, component_parallel);

component_allow = allow({
   #x:makreel:model-name end
 , #x:allow-tau
#x:component-allow-provides
#x:component-allow-requires
#x:component-allow-async
 , async_not_pending'
 , async_pending'
 , declarative_illegal
 , illegal
 , missing_reply
 , queue_empty'
 , queue_not_empty'
 , queue_full
 , range_error
 , recurse
 , return
 , second_reply
 , tau_void
 }, component_comm);

component_rename = rename({
   async_not_pending' -> async_not_pending
 , async_pending' -> async_pending
 , queue_empty' -> queue_empty
 , queue_not_empty' -> queue_not_empty
#x:component-rename-provides
#x:component-rename-requires
#x:component-rename-async
 }, component_allow);

component = hide({
   #x:makreel:model-name end
 , #x:allow-tau
#x:component-hide-provides
#x:component-hide-requires
#x:component-hide-async
 , async_not_pending
 , async_pending
 , queue_empty
 , queue_not_empty
 , recurse
 , return
 , tau_void
 }, component_rename);
