#.name _portexternal_queue (l : List (requires_events)) =
  (##l < QueueLength) -> (sum e: #x:makreel:interface-name events. #.name qin (e) . #.name flush . #.name _portexternal_queue (l = l <| #.name events (e)))
  + (l != [] && #.name is (head (l))) -> #.name internal(#x:makreel:interface-name inevitable) . #.name qout (#.name projection (head (l))) . #.name end . #.name _portexternal_queue(l = tail(l))
  + (##l == QueueLength) -> (sum e: #x:makreel:interface-name events. #.name qin (e) . #.name queue_full . delta)
;

#.name _portinternal = rename({
  #.name internal -> #x:basic-type tau_modeling
  , #.name end -> tau_void
  , #.name flush -> tau_void}, #.name _port);

#.name _portexternal_parallel = #.name _portexternal_queue([]) || #.name _portinternal;

#.name _portexternal_comm = comm({
  #.name out | #.name qin -> #.name qin'
  }, #.name _portexternal_parallel);

#.name _portexternal_allow = allow({
    #x:makreel:interface-name tau_modeling
  , #x:makreel:interface-name tau_reply
  , #.name in
  , #.name qin'
  , #.name qout
  , #.name reply
  , #.name internal
  , #.name end
  , #.name flush
  , #.name queue_full
  , declarative_illegal
  , illegal
  , tau_void
  }, #.name _portexternal_comm);

#.name _portexternal = rename({
  #.name qin' -> #x:basic-type tau_event
  , #.name qout -> #.name out
  }, #.name _portexternal_allow);
