1 import Base 2 import ./change_tick.bend as Tick 3 import internal/relation_failures/domains.bend as D 4 import internal/relation_failures/readings.bend as Read 5 import internal/relation_failures/routing.bend as Route 6 import internal/relation_failures/barrier.bend as B 7 import world.bend as W 8 import system.bend as Sy 9 import event_runtime.bend as Ev 10 11 type Runtime is Type: 12 Runtime{world: W.World,domains: List<&2,D.Domain>,positions: List<&2,Ev.Position>,tick: Nat,frameStart: Nat,boundary: Nat,capacity: Nat,nextReader: U32} 13 type Input is Type: 14 Input{readings: List<&2,Read.KeyReading>,args: A} 15 type Reader -> Input -> Sy.Outcome,Error,O>> is Type: 16 Reader{registry: Sy.Registry,Error,O,runner>,keys: List<&2,D.DescriptorKey>,id: U32} 17 type Registered -> Input -> Sy.Outcome,Error,O>> is Type: 18 Registered{runtime: Runtime,reader: Reader} 19 RegistrationFailed{runtime: Runtime} 20 type Completion is Type: 21 Succeeded{output: O} 22 Failed{error: Error} 23 Rejected{args: A} 24 type RunResult -> Input -> Sy.Outcome,Error,O>> is Type: 25 Ran{runtime: Runtime,reader: Reader,completion: Completion} 26 27 def started_clocked(~S: Data,~C: Type,~R: Type,~E: Data,clocked: W.World & Tick.Tick) -> Runtime: 28 (world,clock) = clocked 29 Runtime{world,[],[],Tick.total(clock),0n,0n,65536n,1} 30 def start(~S: Data,~C: Type,~R: Type,~E: Data,world: W.World) -> Runtime: 31 started_clocked(~S,~C,~R,~E,W.clock(~S,~C,~R,~E,world)) 32 33 def frame(~S: Data,~C: Type,~R: Type,~E: Data,runtime: Runtime) -> Runtime: 34 match runtime: 35 case Runtime{world,domains,+positions,+tick,+frameStart,_,+capacity,+nextReader}: Runtime{world,D.trim(~S,~E,domains,positions,frameStart,capacity),positions,tick,tick,frameStart,capacity,nextReader} 36 37 def registered_result(~S: Data,~C: Type,~R: Type,~E: Data,~A: Type,~Error: Data,~O: Type,~runner: W.World -> Input -> Sy.Outcome,Error,O>,result: Sy.RegistrationResult,Error,O,runner>,+keys: List<&2,D.DescriptorKey>,domains: List<&2,D.Domain>,positions: List<&2,Ev.Position>,tick: Nat,frameStart: Nat,boundary: Nat,capacity: Nat,+nextReader: U32) -> Registered: 38 match result: 39 case Sy.RegistrationFailed{world}: RegistrationFailed{Runtime{world,domains,positions,tick,frameStart,boundary,capacity,nextReader}} 40 case Sy.Registered{world,registry}: Registered{Runtime{world,domains,positions,tick,frameStart,boundary,capacity,(nextReader+1 : U32)},Reader{registry,keys,nextReader}} 41 42 def register_available(~S: Data,~C: Type,~R: Type,~E: Data,~A: Type,~Error: Data,~O: Type,~runner: W.World -> Input -> Sy.Outcome,Error,O>,runtime: Runtime,+keys: List<&2,D.DescriptorKey>,+name: String,+access: List<&2,String>) -> Registered: 43 match runtime: 44 case Runtime{world,domains,positions,tick,frameStart,boundary,capacity,nextReader}: registered_result(~S,~C,~R,~E,~A,~Error,~O,~runner,Sy.register(~S,~C,~R,~E,~Input,~Error,~O,~runner,world,name,access),keys,domains,positions,tick,frameStart,boundary,capacity,nextReader) 45 46 47 # Shared by standalone readers and composed parameters; no system registration. 48 def reserve_reader_checked(~S:Data,~C:Type,~R:Type,~E:Data,available:Bool,runtime:Runtime) -> Runtime & Maybe<&2,U32>: 49 match available runtime: 50 case False{} runtime:(runtime,None{}) 51 case True{} Runtime{world,domains,positions,tick,frameStart,boundary,capacity,+nextReader}: 52 (Runtime{world,domains,positions,tick,frameStart,boundary,capacity,(nextReader+1 : U32)},Some{nextReader}) 53 def reserve_reader(~S:Data,~C:Type,~R:Type,~E:Data,runtime:Runtime) -> Runtime & Maybe<&2,U32>: 54 match runtime: 55 case Runtime{world,domains,positions,tick,frameStart,boundary,capacity,+nextReader}: 56 reserve_reader_checked(~S,~C,~R,~E,U32.is_lt(nextReader,4294967295),Runtime{world,domains,positions,tick,frameStart,boundary,capacity,nextReader}) 57 def register_checked(~S:Data,~C:Type,~R:Type,~E:Data,~A:Type,~Error:Data,~O:Type,~runner:W.World -> Input -> Sy.Outcome,Error,O>,available:Bool,runtime:Runtime,keys:List<&2,D.DescriptorKey>,name:String,access:List<&2,String>) -> Registered: 58 match available: 59 case False{}:RegistrationFailed{runtime} 60 case True{}:register_available(~S,~C,~R,~E,~A,~Error,~O,~runner,runtime,keys,name,access) 61 def register(~S:Data,~C:Type,~R:Type,~E:Data,~A:Type,~Error:Data,~O:Type,~runner:W.World -> Input -> Sy.Outcome,Error,O>,runtime:Runtime,keys:List<&2,D.DescriptorKey>,name:String,access:List<&2,String>) -> Registered: 62 match runtime: 63 case Runtime{world,domains,positions,tick,frameStart,boundary,capacity,+nextReader}: 64 register_checked(~S,~C,~R,~E,~A,~Error,~O,~runner,U32.is_lt(nextReader,4294967295),Runtime{world,domains,positions,tick,frameStart,boundary,capacity,nextReader},keys,name,access) 65 66 def position_or(position: Maybe,id: U32,tick: Nat) -> Ev.Position: 67 match position: 68 case None{}: Ev.Position{id,0n,tick} 69 case Some{found}: found 70 71 def succeeded_collected(~S: Data,~C: Type,~R: Type,~E: Data,~A: Type,~Error: Data,~O: Type,~runner: W.World -> Input -> Sy.Outcome,Error,O>,id:U32,joined: W.World & List<&2,D.Domain>,registry: Sy.Registry,Error,O,runner>,+keys: List<&2,D.DescriptorKey>,positions: List<&2,Ev.Position>,tick: Nat,frameStart: Nat,boundary: Nat,capacity: Nat,+nextReader: U32,output: O) -> RunResult: 72 (world,domains) = joined 73 Ran{Runtime{world,domains,positions,tick,frameStart,boundary,capacity,nextReader},Reader{registry,keys,id},Succeeded{output}} 74 75 def failed_clocked(~S: Data,~C: Type,~R: Type,~E: Data,~A: Type,~Error: Data,~O: Type,~runner: W.World -> Input -> Sy.Outcome,Error,O>,~classify: E -> Maybe>,clocked: W.World & Tick.Tick,registry: Sy.Registry,Error,O,runner>,+keys: List<&2,D.DescriptorKey>,+domains: List<&2,D.Domain>,+positions: List<&2,Ev.Position>,+id: U32,+previous: Nat,frameStart: Nat,boundary: Nat,capacity: Nat,+nextReader: U32,error: Error) -> RunResult: 76 (world,clock) = clocked 77 Ran{Runtime{world,Read.activate(~S,~E,keys,domains,id),Ev.activate(positions,id,previous),Tick.total(clock),frameStart,boundary,capacity,nextReader},Reader{registry,keys,id},Failed{error}} 78 def succeeded_clocked(~S: Data,~C: Type,~R: Type,~E: Data,~A: Type,~Error: Data,~O: Type,~runner: W.World -> Input -> Sy.Outcome,Error,O>,~classify: E -> Maybe>,clocked: W.World & Tick.Tick,registry: Sy.Registry,Error,O,runner>,+keys: List<&2,D.DescriptorKey>,+domains: List<&2,D.Domain>,+positions: List<&2,Ev.Position>,+id: U32,+previous: Nat,frameStart: Nat,boundary: Nat,capacity: Nat,+nextReader: U32,output: O) -> RunResult: 79 (world,+clock) = clocked 80 succeeded_collected(~S,~C,~R,~E,~A,~Error,~O,~runner,id,Route.collect(~S,~C,~R,~E,~classify,world,Tick.total(clock),Read.activate(~S,~E,keys,domains,id)),registry,keys,Ev.update(Ev.activate(positions,id,previous),id,Tick.total(clock),False{}),Tick.total(clock),frameStart,boundary,capacity,nextReader,output) 81 82 def outcome(~S: Data,~C: Type,~R: Type,~E: Data,~A: Type,~Error: Data,~O: Type,~runner: W.World -> Input -> Sy.Outcome,Error,O>,~classify: E -> Maybe>,outcome: Sy.Outcome,Error,O>,registry: Sy.Registry,Error,O,runner>,+keys: List<&2,D.DescriptorKey>,+domains: List<&2,D.Domain>,+positions: List<&2,Ev.Position>,+id: U32,+tick: Nat,+frameStart: Nat,+boundary: Nat,+capacity: Nat,+nextReader: U32) -> RunResult: 83 match outcome: 84 case Sy.Failed{world,error}: failed_clocked(~S,~C,~R,~E,~A,~Error,~O,~runner,~classify,W.clock(~S,~C,~R,~E,world),registry,keys,domains,positions,id,tick,frameStart,boundary,capacity,nextReader,error) 85 case Sy.Succeeded{world,output}: succeeded_clocked(~S,~C,~R,~E,~A,~Error,~O,~runner,~classify,W.clock(~S,~C,~R,~E,world),registry,keys,domains,positions,id,tick,frameStart,boundary,capacity,nextReader,output) 86 87 def run_result(~S: Data,~C: Type,~R: Type,~E: Data,~A: Type,~Error: Data,~O: Type,~runner: W.World -> Input -> Sy.Outcome,Error,O>,~classify: E -> Maybe>,result: Sy.RunResult,Error,O,runner>,+keys: List<&2,D.DescriptorKey>,domains: List<&2,D.Domain>,positions: List<&2,Ev.Position>,id: U32,tick: Nat,frameStart: Nat,boundary: Nat,capacity: Nat,+nextReader: U32) -> RunResult: 88 match result: 89 case Sy.RegistrationRejected{registry,world,Input{_,args}}: Ran{Runtime{world,domains,positions,tick,frameStart,boundary,capacity,nextReader},Reader{registry,keys,id},Rejected{args}} 90 case Sy.Completed{registry,completed}: outcome(~S,~C,~R,~E,~A,~Error,~O,~runner,~classify,completed,registry,keys,domains,positions,id,tick,frameStart,boundary,capacity,nextReader) 91 92 def effect_clocked(~S: Data,~C: Type,~R: Type,~E: Data,~O: Type,effect: W.World -> W.World & O,advanced: W.World & Tick.Tick) -> W.World & O: 93 (world,_) = advanced 94 effect(world) 95 96 97 def run_identified(~S: Data,~C: Type,~R: Type,~E: Data,~A: Type,~Error: Data,~O: Type,~runner: W.World -> Input -> Sy.Outcome,Error,O>,~classify: E -> Maybe>,runtime: Runtime,identified: Sy.Registry,Error,O,runner> & U32,+keys: List<&2,D.DescriptorKey>,args: A) -> RunResult: 98 match runtime: 99 case Runtime{world,+domains,+positions,+tick,+frameStart,+boundary,+capacity,+nextReader}: 100 (registry,+id) = identified 101 run_result(~S,~C,~R,~E,~A,~Error,~O,~runner,~classify,Sy.run(~S,~C,~R,~E,~Input,~Error,~O,~runner,registry,world,Input{Read.all(~S,~E,keys,domains,position_or(Ev.lookup(positions,id),id,tick)),args}),keys,domains,positions,id,tick,frameStart,boundary,capacity,nextReader) 102 103 def run(~S: Data,~C: Type,~R: Type,~E: Data,~A: Type,~Error: Data,~O: Type,~runner: W.World -> Input -> Sy.Outcome,Error,O>,~classify: E -> Maybe>,runtime: Runtime,reader: Reader,args: A) -> RunResult: 104 match reader: 105 case Reader{registry,keys,id}: run_identified(~S,~C,~R,~E,~A,~Error,~O,~runner,~classify,runtime,(registry,id),keys,args) 106 def skipped_checked(~S: Data,~C: Type,~R: Type,~E: Data,~A: Type,~Error: Data,~O: Type,~runner: W.World -> Input -> Sy.Outcome,Error,O>,allowed: Bool,runtime: Runtime,reader: Reader,+id: U32) -> Runtime & Reader: 107 match allowed runtime: 108 case False{} runtime: (runtime,reader) 109 case True{} Runtime{world,domains,positions,+tick,frameStart,boundary,capacity,nextReader}: (Runtime{world,domains,Ev.update(positions,id,tick,False{}),tick,frameStart,boundary,capacity,nextReader},reader) 110 111 def skip_meta(~S: Data,~C: Type,~R: Type,~E: Data,~A: Type,~Error: Data,~O: Type,~runner: W.World -> Input -> Sy.Outcome,Error,O>,checked: W.World & Bool,registry: Sy.Registry,Error,O,runner>,keys: List<&2,D.DescriptorKey>,domains: List<&2,D.Domain>,positions: List<&2,Ev.Position>,tick: Nat,frameStart: Nat,boundary: Nat,capacity: Nat,+nextReader: U32,+id: U32) -> Runtime & Reader: 112 (world,allowed) = checked 113 skipped_checked(~S,~C,~R,~E,~A,~Error,~O,~runner,allowed,Runtime{world,domains,positions,tick,frameStart,boundary,capacity,nextReader},Reader{registry,keys,id},id) 114 115 def skip_namespace(~S: Data,~C: Type,~R: Type,~E: Data,~A: Type,~Error: Data,~O: Type,~runner: W.World -> Input -> Sy.Outcome,Error,O>,same: Bool,world: W.World,registry: Sy.Registry,Error,O,runner>,keys: List<&2,D.DescriptorKey>,readerId:U32,domains: List<&2,D.Domain>,positions: List<&2,Ev.Position>,tick: Nat,frameStart: Nat,boundary: Nat,capacity: Nat,+nextReader: U32) -> Runtime & Reader: 116 match same registry: 117 case False{} registry: (Runtime{world,domains,positions,tick,frameStart,boundary,capacity,nextReader},Reader{registry,keys,readerId}) 118 case True{} Sy.Registry{+namespace,+id,+name,+access,+cursor}: skip_meta(~S,~C,~R,~E,~A,~Error,~O,~runner,W.registration_matches(~S,~C,~R,~E,world,id,name,access),Sy.Registry{namespace,id,name,access,cursor},keys,domains,positions,tick,frameStart,boundary,capacity,nextReader,readerId) 119 120 def skip_named(~S: Data,~C: Type,~R: Type,~E: Data,~A: Type,~Error: Data,~O: Type,~runner: W.World -> Input -> Sy.Outcome,Error,O>,reader: Reader,named: W.World & U32,domains: List<&2,D.Domain>,positions: List<&2,Ev.Position>,tick: Nat,frameStart: Nat,boundary: Nat,capacity: Nat,+nextReader: U32) -> Runtime & Reader: 121 match reader: 122 case Reader{Sy.Registry{+namespace,+id,+name,+access,+cursor},keys,readerId}: 123 (world,actual) = named 124 skip_namespace(~S,~C,~R,~E,~A,~Error,~O,~runner,U32.is_eq(namespace,actual),world,Sy.Registry{namespace,id,name,access,cursor},keys,readerId,domains,positions,tick,frameStart,boundary,capacity,nextReader) 125 126 def skip(~S: Data,~C: Type,~R: Type,~E: Data,~A: Type,~Error: Data,~O: Type,~runner: W.World -> Input -> Sy.Outcome,Error,O>,runtime: Runtime,reader: Reader) -> Runtime & Reader: 127 match runtime: 128 case Runtime{world,domains,positions,tick,frameStart,boundary,capacity,nextReader}: skip_named(~S,~C,~R,~E,~A,~Error,~O,~runner,reader,W.namespace(~S,~C,~R,~E,world),domains,positions,tick,frameStart,boundary,capacity,nextReader) 129 130 def barrier_join(~S: Data,~C: Type,~R: Type,~E: Data,state: B.BarrierState,positions: List<&2,Ev.Position>,frameStart: Nat,boundary: Nat,capacity: Nat,+nextReader: U32) -> Runtime: 131 match state: 132 case B.BarrierState{world,domains,tick}: Runtime{world,domains,positions,tick,frameStart,boundary,capacity,nextReader} 133 134 def barrier(~S: Data,~C: Type,~R: Type,~E: Data,~classify: E -> Maybe>,runtime: Runtime) -> Runtime: 135 match runtime: 136 case Runtime{world,domains,positions,tick,frameStart,boundary,capacity,nextReader}: barrier_join(~S,~C,~R,~E,B.barrier(~S,~C,~R,~E,~classify,world,domains),positions,frameStart,boundary,capacity,nextReader) 137 138 def with_world_collected(~S: Data,~C: Type,~R: Type,~E: Data,~O: Type,collected: W.World & List<&2,D.Domain>,output: O,positions: List<&2,Ev.Position>,tick: Nat,frameStart: Nat,boundary: Nat,capacity: Nat,+nextReader: U32) -> Runtime & O: 139 (world,domains) = collected 140 (Runtime{world,domains,positions,tick,frameStart,boundary,capacity,nextReader},output) 141 142 def with_world_clocked(~S: Data,~C: Type,~R: Type,~E: Data,~O: Type,~classify: E -> Maybe>,clocked: W.World & Tick.Tick,output: O,domains: List<&2,D.Domain>,positions: List<&2,Ev.Position>,frameStart: Nat,boundary: Nat,capacity: Nat,+nextReader: U32) -> Runtime & O: 143 (world,+clock) = clocked 144 with_world_collected(~S,~C,~R,~E,~O,Route.collect(~S,~C,~R,~E,~classify,world,Tick.total(clock),domains),output,positions,Tick.total(clock),frameStart,boundary,capacity,nextReader) 145 def with_world_result(~S: Data,~C: Type,~R: Type,~E: Data,~O: Type,~classify: E -> Maybe>,result: W.World & O,domains: List<&2,D.Domain>,positions: List<&2,Ev.Position>,_: Nat,frameStart: Nat,boundary: Nat,capacity: Nat,+nextReader: U32) -> Runtime & O: 146 (world,output) = result 147 with_world_clocked(~S,~C,~R,~E,~O,~classify,W.clock(~S,~C,~R,~E,world),output,domains,positions,frameStart,boundary,capacity,nextReader) 148 149 def with_world(~S: Data,~C: Type,~R: Type,~E: Data,~O: Type,~classify: E -> Maybe>,effect: W.World -> W.World & O,runtime: Runtime) -> Runtime & O: 150 match runtime: 151 case Runtime{world,domains,positions,tick,frameStart,boundary,capacity,nextReader}: with_world_result(~S,~C,~R,~E,~O,~classify,effect_clocked(~S,~C,~R,~E,~O,effect,W.write_clock(~S,~C,~R,~E,world)),domains,positions,tick,frameStart,boundary,capacity,nextReader)