1 import Base 2 import queue.bend as Q 3 import domains.bend as D 4 import ../../world.bend as W 5 6 type PendingBatch is Data: 7 PendingBatch{key: D.DescriptorKey,reversed: List<&2,E>} 8 type Partition is Data: 9 Partition{ordinary: List<&2,E>,batches: List<&2,PendingBatch>} 10 11 def group_found(~S: Data,~E: Data,same: Bool,+key: D.DescriptorKey,items: List<&2,E>,+rest: List<&2,PendingBatch>,+item: E,ih: Unit -> List<&2,PendingBatch>) -> List<&2,PendingBatch>: 12 match same: 13 case True{}: PendingBatch{key,item <> items} <> rest 14 case False{}: PendingBatch{key,items} <> ih(Unit{}) 15 16 def group(~S: Data,~E: Data,batches: List<&2,PendingBatch>,+wanted: D.DescriptorKey,+item: E) -> List<&2,PendingBatch>: 17 match batches: 18 case []: [PendingBatch{wanted,[item]}] 19 case PendingBatch{+key,+items} <> +rest: group_found(~S,~E,D.key_equal(~S,key,wanted),key,items,rest,item,_ => group(~S,~E,rest,wanted,item)) 20 21 def partition_selected(~S: Data,~E: Data,key: Maybe>,item: E,ordinary: List<&2,E>,batches: List<&2,PendingBatch>) -> Partition: 22 match key: 23 case None{}: Partition{item <> ordinary,batches} 24 case Some{wanted}: Partition{ordinary,group(~S,~E,batches,wanted,item)} 25 26 def partition_loop(~S: Data,~E: Data,~classify: E -> Maybe>,items: List<&2,E>,acc: Partition) -> Partition: 27 match items acc: 28 case Nil{} acc: acc 29 case +item <> rest Partition{ordinary,batches}: partition_loop(~S,~E,~classify,rest,partition_selected(~S,~E,classify(item),item,ordinary,batches)) 30 31 def publish_found(~S: Data,~E: Data,same: Bool,+key: D.DescriptorKey,queue: Q.Queue,ids: List<&2,U32>,+rest: List<&2,D.Domain>,tick: Nat,items: List<&2,E>,ih: Unit -> List<&2,D.Domain>) -> List<&2,D.Domain>: 32 match same: 33 case True{}: D.Domain{key,Q.publish(~E,queue,tick,items),ids} <> rest 34 case False{}: D.Domain{key,queue,ids} <> ih(Unit{}) 35 36 def publish_one(~S: Data,~E: Data,domains: List<&2,D.Domain>,+wanted: D.DescriptorKey,+tick: Nat,+items: List<&2,E>) -> List<&2,D.Domain>: 37 match domains: 38 case []: [D.Domain{wanted,Q.publish(~E,Q.empty(~E),tick,items),[]}] 39 case D.Domain{+key,+queue,+ids} <> +rest: publish_found(~S,~E,D.key_equal(~S,key,wanted),key,queue,ids,rest,tick,items,_ => publish_one(~S,~E,rest,wanted,tick,items)) 40 41 def publish_batches(~S: Data,~E: Data,batches: List<&2,PendingBatch>,+tick: Nat,domains: List<&2,D.Domain>) -> List<&2,D.Domain>: 42 match batches: 43 case []: domains 44 case PendingBatch{key,reversed} <> rest: publish_batches(~S,~E,rest,tick,publish_one(~S,~E,domains,key,tick,List.reverse(&2,E,reversed))) 45 46 def collected(~S: Data,~C: Type,~R: Type,~E: Data,world: W.World,partition: Partition,tick: Nat,domains: List<&2,D.Domain>) -> W.World & List<&2,D.Domain>: 47 match partition: 48 case Partition{ordinary,batches}: (W.events_replace(~S,~C,~R,~E,world,List.reverse(&2,E,ordinary)),publish_batches(~S,~E,batches,tick,domains)) 49 50 def collect_view(~S: Data,~C: Type,~R: Type,~E: Data,~classify: E -> Maybe>,view: W.World & List<&2,E>,tick: Nat,domains: List<&2,D.Domain>) -> W.World & List<&2,D.Domain>: 51 (world,items) = view 52 collected(~S,~C,~R,~E,world,partition_loop(~S,~E,~classify,items,Partition{[],[]}),tick,domains) 53 54 def collect(~S: Data,~C: Type,~R: Type,~E: Data,~classify: E -> Maybe>,world: W.World,tick: Nat,domains: List<&2,D.Domain>) -> W.World & List<&2,D.Domain>: 55 collect_view(~S,~C,~R,~E,~classify,W.events_view(~S,~C,~R,~E,world),tick,domains)