1 import Base 2 import ./change_tick.bend as Tick 3 import ./world.bend as W 4 import ./system.bend as Sys 5 import ./system_instance.bend as SI 6 import ./system_cleanup.bend as Cleanup 7 import ./machine.bend as M 8 import ./machine_stream.bend as St 9 import ./event_runtime.bend as Ev 10 import ./ordinary_machine_initialization.bend as Resource 11 import ./ordinary_machine_declaration.bend as Machine 12 13 # One schema-owned declaration binds the actual stream lens and descriptive name. 14 type Declaration<-S:Data,-K:Data,-V:Data,-R:Type,-take:R -> R & St.Stream,-put:R -> St.Stream -> R> is Data: 15 Declaration{name:String} 16 type Input is Type: 17 Input{reading:Ev.Reading>,args:A} 18 type Completion is Type: 19 CallbackSucceeded{output:Out} 20 CallbackFailed{error:Error} 21 type ReadResult<-World:Type,-Reader:Type,-Args:Type,-Error:Data,-Out:Type,-V:Data> is Type: 22 ReadSucceeded{world:World,reader:Reader,output:Out,reading:Ev.Reading>} 23 ReadFailed{world:World,reader:Reader,error:Error,reading:Ev.Reading>} 24 ReadRejected{world:World,reader:Reader,args:Args} 25 26 def validate(~S:Data,~K:Data,reader:St.Reader,namespace:U32,id:U32) -> St.Reader & Bool: 27 match reader: 28 case St.Reader{+actual,+key}:(St.Reader{actual,key},Bool.and(U32.is_eq(actual,namespace),U32.is_eq(key,id))) 29 def create(~S:Data,~K:Data,~C:Type,~R:Type,~E:Data,namespace:U32,id:U32,world:W.World) -> W.World & St.Reader: 30 (world,St.Reader{namespace,id}) 31 def stream_set_result(~S:Data,~C:Type,~R:Type,~E:Data,result:W.World & Unit) -> W.World: 32 match result: 33 case (world,_):world 34 def stream_set_resource(~V:Data,~R:Type,~put:R -> St.Stream -> R,stream:St.Stream,resource:R) -> R & Unit: 35 (put(resource,stream),Unit{}) 36 def stream_set(~S:Data,~V:Data,~C:Type,~R:Type,~E:Data,~put:R -> St.Stream -> R,world:W.World,stream:St.Stream) -> W.World: 37 stream_set_result(~S,~C,~R,~E,Resource.with_resource(~S,~C,~R,~E,~Unit,(resource => stream_set_resource(~V,~R,~put,stream,resource)),world)) 38 def removed(~S:Data,~V:Data,~C:Type,~R:Type,~E:Data,~put:R -> St.Stream -> R,id:U32,result:W.World & St.Stream) -> W.World: 39 match result: 40 case (world,stream):stream_set(~S,~V,~C,~R,~E,~put,world,St.dispose(~V,stream,id)) 41 def remove(~S:Data,~K:Data,~V:Data,~C:Type,~R:Type,~E:Data,~take:R -> R & St.Stream,~put:R -> St.Stream -> R,world:W.World,reader:St.Reader) -> W.World: 42 match reader: 43 case St.Reader{_,id}:removed(~S,~V,~C,~R,~E,~put,id,W.observe_resource(~S,~C,~R,~E,~St.Stream,~take,world)) 44 45 # Initializer declarations supply the same operational state cell and name. 46 def initialized_taken(~S:Data,~K:Data,~V:Data,~R:Type,~put:R -> Resource.State -> R,result:R & Resource.State) -> R & St.Stream: 47 match result: 48 case (resource,Resource.State{slot,+stream,revision}):(put(resource,Resource.State{slot,stream,revision}),stream) 49 def initialized_take(~S:Data,~K:Data,~V:Data,~R:Type,~take:R -> R & Resource.State,~put:R -> Resource.State -> R,resource:R) -> R & St.Stream: 50 initialized_taken(~S,~K,~V,~R,~put,take(resource)) 51 def initialized_put_taken(~S:Data,~K:Data,~V:Data,~R:Type,~put:R -> Resource.State -> R,stream:St.Stream,result:R & Resource.State) -> R: 52 match result: 53 case (resource,Resource.State{slot,_,revision}):put(resource,Resource.State{slot,stream,revision}) 54 def initialized_put(~S:Data,~K:Data,~V:Data,~R:Type,~take:R -> R & Resource.State,~put:R -> Resource.State -> R,resource:R,stream:St.Stream) -> R: 55 initialized_put_taken(~S,~K,~V,~R,~put,stream,take(resource)) 56 def from_initialization(~S:Data,~K:Data,~V:Data,~R:Type,~take:R -> R & Resource.State,~put:R -> Resource.State -> R,~declaration:Machine.Declaration) -> Declaration: 57 Declaration{Machine.name(~S,~K,~V,~R,~Resource.take_slot(~S,~K,~V,~R,~take,~put),declaration)} 58 59 def instance_type(~S:Data,~K:Data,~V:Data,~C:Type,~R:Type,~E:Data,~A:Type,~Error:Data,~Out:Type,~take:R -> R & St.Stream,~put:R -> St.Stream -> R,~callback:W.World -> Input -> Sys.Outcome,Error,Out>) -> Type:SI.Instance,Error,Out,callback,St.Reader,validate(~S,~K),remove(~S,~K,~V,~C,~R,~E,~take,~put)> 60 def registration_type(~S:Data,~K:Data,~V:Data,~C:Type,~R:Type,~E:Data,~A:Type,~Error:Data,~Out:Type,~take:R -> R & St.Stream,~put:R -> St.Stream -> R,~callback:W.World -> Input -> Sys.Outcome,Error,Out>) -> Type:SI.Registration,Error,Out,callback,St.Reader,validate(~S,~K),remove(~S,~K,~V,~C,~R,~E,~take,~put)> 61 def disposal_type(~S:Data,~K:Data,~V:Data,~C:Type,~R:Type,~E:Data,~A:Type,~Error:Data,~Out:Type,~take:R -> R & St.Stream,~put:R -> St.Stream -> R,~callback:W.World -> Input -> Sys.Outcome,Error,Out>) -> Type:SI.Disposal,Error,Out,callback,St.Reader,validate(~S,~K),remove(~S,~K,~V,~C,~R,~E,~take,~put)> 62 def access(~S:Data,~K:Data,~V:Data,~R:Type,~take:R -> R & St.Stream,~put:R -> St.Stream -> R,value:Declaration) -> List<&2,String>: 63 match value: 64 case Declaration{name}:["machine." ++ name ++ ".transition.read"] 65 def register(~S:Data,~K:Data,~V:Data,~C:Type,~R:Type,~E:Data,~A:Type,~Error:Data,~Out:Type,~take:R -> R & St.Stream,~put:R -> St.Stream -> R,~callback:W.World -> Input -> Sys.Outcome,Error,Out>,~declaration:Declaration,world:W.World,name:String) -> registration_type(~S,~K,~V,~C,~R,~E,~A,~Error,~Out,~take,~put,~callback): 66 SI.register(~S,~C,~R,~E,~Input,~Error,~Out,~callback,~St.Reader,~validate(~S,~K),~remove(~S,~K,~V,~C,~R,~E,~take,~put),~create(~S,~K,~C,~R,~E),world,name,access(~S,~K,~V,~R,~take,~put,declaration)) 67 def dispose(~S:Data,~K:Data,~V:Data,~C:Type,~R:Type,~E:Data,~A:Type,~Error:Data,~Out:Type,~take:R -> R & St.Stream,~put:R -> St.Stream -> R,~callback:W.World -> Input -> Sys.Outcome,Error,Out>,reader:instance_type(~S,~K,~V,~C,~R,~E,~A,~Error,~Out,~take,~put,~callback),world:W.World) -> disposal_type(~S,~K,~V,~C,~R,~E,~A,~Error,~Out,~take,~put,~callback): 68 SI.dispose(~S,~C,~R,~E,~Input,~Error,~Out,~callback,~St.Reader,~validate(~S,~K),~remove(~S,~K,~V,~C,~R,~E,~take,~put),reader,world) 69 # Unrun reader parameters neither activate nor consume unread transitions. 70 def skip(~S:Data,~K:Data,~V:Data,~C:Type,~R:Type,~E:Data,~A:Type,~Error:Data,~Out:Type,~take:R -> R & St.Stream,~put:R -> St.Stream -> R,~callback:W.World -> Input -> Sys.Outcome,Error,Out>,reader:instance_type(~S,~K,~V,~C,~R,~E,~A,~Error,~Out,~take,~put,~callback),world:W.World) -> instance_type(~S,~K,~V,~C,~R,~E,~A,~Error,~Out,~take,~put,~callback) & W.World:(reader,world) 71 72 def delivered(~S:Data,~K:Data,~V:Data,~C:Type,~R:Type,~E:Data,~A:Type,~Error:Data,~Out:Type,~take:R -> R & St.Stream,~put:R -> St.Stream -> R,~callback:W.World -> Input -> Sys.Outcome,Error,Out>,reader:instance_type(~S,~K,~V,~C,~R,~E,~A,~Error,~Out,~take,~put,~callback),world:W.World,reading:Ev.Reading>,completion:Completion) -> ReadResult,instance_type(~S,~K,~V,~C,~R,~E,~A,~Error,~Out,~take,~put,~callback),A,Error,Out,V>: 73 match completion: 74 case CallbackSucceeded{output}:ReadSucceeded{world,reader,output,reading} 75 case CallbackFailed{error}:ReadFailed{world,reader,error,reading} 76 def finished(~S:Data,~K:Data,~V:Data,~C:Type,~R:Type,~E:Data,~A:Type,~Error:Data,~Out:Type,~take:R -> R & St.Stream,~put:R -> St.Stream -> R,~callback:W.World -> Input -> Sys.Outcome,Error,Out>,registry:Sys.Registry,Error,Out,callback>,world:W.World,reading:Ev.Reading>,completion:Completion,result:St.Reader & St.Stream) -> ReadResult,instance_type(~S,~K,~V,~C,~R,~E,~A,~Error,~Out,~take,~put,~callback),A,Error,Out,V>: 77 match result: 78 case (reader,stream):delivered(~S,~K,~V,~C,~R,~E,~A,~Error,~Out,~take,~put,~callback,SI.Instance{Cleanup.Instance{registry,reader}},stream_set(~S,~V,~C,~R,~E,~put,world,stream),reading,completion) 79 def finishing(~S:Data,~K:Data,~V:Data,~C:Type,~R:Type,~E:Data,~A:Type,~Error:Data,~Out:Type,~take:R -> R & St.Stream,~put:R -> St.Stream -> R,~callback:W.World -> Input -> Sys.Outcome,Error,Out>,reader:instance_type(~S,~K,~V,~C,~R,~E,~A,~Error,~Out,~take,~put,~callback),reading:Ev.Reading>,tick:Nat,success:Bool,completion:Completion,result:W.World & St.Stream) -> ReadResult,instance_type(~S,~K,~V,~C,~R,~E,~A,~Error,~Out,~take,~put,~callback),A,Error,Out,V>: 80 match reader result: 81 case SI.Instance{Cleanup.Instance{registry,ports}}, (world,stream):finished(~S,~K,~V,~C,~R,~E,~A,~Error,~Out,~take,~put,~callback,registry,world,reading,completion,St.finish(~S,~K,~V,ports,stream,tick,success)) 82 def finish(~S:Data,~K:Data,~V:Data,~C:Type,~R:Type,~E:Data,~A:Type,~Error:Data,~Out:Type,~take:R -> R & St.Stream,~put:R -> St.Stream -> R,~callback:W.World -> Input -> Sys.Outcome,Error,Out>,reader:instance_type(~S,~K,~V,~C,~R,~E,~A,~Error,~Out,~take,~put,~callback),world:W.World,reading:Ev.Reading>,tick:Nat,success:Bool,completion:Completion) -> ReadResult,instance_type(~S,~K,~V,~C,~R,~E,~A,~Error,~Out,~take,~put,~callback),A,Error,Out,V>: 83 finishing(~S,~K,~V,~C,~R,~E,~A,~Error,~Out,~take,~put,~callback,reader,reading,tick,success,completion,W.observe_resource(~S,~C,~R,~E,~St.Stream,~take,world)) 84 def callback_result(~S:Data,~K:Data,~V:Data,~C:Type,~R:Type,~E:Data,~A:Type,~Error:Data,~Out:Type,~take:R -> R & St.Stream,~put:R -> St.Stream -> R,~callback:W.World -> Input -> Sys.Outcome,Error,Out>,reading:Ev.Reading>,tick:Nat,result:SI.RunResult,Error,Out,callback,St.Reader,validate(~S,~K),remove(~S,~K,~V,~C,~R,~E,~take,~put)>) -> ReadResult,instance_type(~S,~K,~V,~C,~R,~E,~A,~Error,~Out,~take,~put,~callback),A,Error,Out,V>: 85 match result: 86 case SI.Completed{reader,Sys.Succeeded{world,output}}:finish(~S,~K,~V,~C,~R,~E,~A,~Error,~Out,~take,~put,~callback,reader,world,reading,tick,True{},CallbackSucceeded{output}) 87 case SI.Completed{reader,Sys.Failed{world,error}}:finish(~S,~K,~V,~C,~R,~E,~A,~Error,~Out,~take,~put,~callback,reader,world,reading,tick,False{},CallbackFailed{error}) 88 case SI.RegistrationRejected{reader,world,Input{_,args}}:ReadRejected{world,reader,args} 89 def opened(~S:Data,~K:Data,~V:Data,~C:Type,~R:Type,~E:Data,~A:Type,~Error:Data,~Out:Type,~take:R -> R & St.Stream,~put:R -> St.Stream -> R,~callback:W.World -> Input -> Sys.Outcome,Error,Out>,registry:Sys.Registry,Error,Out,callback>,world:W.World,args:A,tick:Nat,result:St.OpenResult) -> ReadResult,instance_type(~S,~K,~V,~C,~R,~E,~A,~Error,~Out,~take,~put,~callback),A,Error,Out,V>: 90 match result: 91 case St.ReaderRefused{reader,stream}:ReadRejected{stream_set(~S,~V,~C,~R,~E,~put,world,stream),SI.Instance{Cleanup.Instance{registry,reader}},args} 92 case St.Opened{reader,stream,+reading}:callback_result(~S,~K,~V,~C,~R,~E,~A,~Error,~Out,~take,~put,~callback,reading,tick,SI.run(~S,~C,~R,~E,~Input,~Error,~Out,~callback,~St.Reader,~validate(~S,~K),~remove(~S,~K,~V,~C,~R,~E,~take,~put),SI.Instance{Cleanup.Instance{registry,reader}},stream_set(~S,~V,~C,~R,~E,~put,world,stream),Input{reading,args})) 93 def opening(~S:Data,~K:Data,~V:Data,~C:Type,~R:Type,~E:Data,~A:Type,~Error:Data,~Out:Type,~take:R -> R & St.Stream,~put:R -> St.Stream -> R,~callback:W.World -> Input -> Sys.Outcome,Error,Out>,reader:instance_type(~S,~K,~V,~C,~R,~E,~A,~Error,~Out,~take,~put,~callback),args:A,+tick:Nat,result:W.World & St.Stream) -> ReadResult,instance_type(~S,~K,~V,~C,~R,~E,~A,~Error,~Out,~take,~put,~callback),A,Error,Out,V>: 94 match reader result: 95 case SI.Instance{Cleanup.Instance{registry,St.Reader{+namespace,id}}}, (world,stream):opened(~S,~K,~V,~C,~R,~E,~A,~Error,~Out,~take,~put,~callback,registry,world,args,tick,St.open(~S,~K,~V,St.Reader{namespace,id},stream,namespace,tick)) 96 def clocked(~S:Data,~K:Data,~V:Data,~C:Type,~R:Type,~E:Data,~A:Type,~Error:Data,~Out:Type,~take:R -> R & St.Stream,~put:R -> St.Stream -> R,~callback:W.World -> Input -> Sys.Outcome,Error,Out>,reader:instance_type(~S,~K,~V,~C,~R,~E,~A,~Error,~Out,~take,~put,~callback),args:A,result:W.World & Tick.Tick) -> ReadResult,instance_type(~S,~K,~V,~C,~R,~E,~A,~Error,~Out,~take,~put,~callback),A,Error,Out,V>: 97 match result: 98 case (world,tick):opening(~S,~K,~V,~C,~R,~E,~A,~Error,~Out,~take,~put,~callback,reader,args,Tick.total(tick),W.observe_resource(~S,~C,~R,~E,~St.Stream,~take,world)) 99 def checked(~S:Data,~K:Data,~V:Data,~C:Type,~R:Type,~E:Data,~A:Type,~Error:Data,~Out:Type,~take:R -> R & St.Stream,~put:R -> St.Stream -> R,~callback:W.World -> Input -> Sys.Outcome,Error,Out>,allowed:Bool,reader:instance_type(~S,~K,~V,~C,~R,~E,~A,~Error,~Out,~take,~put,~callback),args:A,result:W.World & Bool) -> ReadResult,instance_type(~S,~K,~V,~C,~R,~E,~A,~Error,~Out,~take,~put,~callback),A,Error,Out,V>: 100 match allowed result: 101 case False{}, (world,_):ReadRejected{world,reader,args} 102 case True{}, (world,False{}):ReadRejected{world,reader,args} 103 case True{}, (world,True{}):clocked(~S,~K,~V,~C,~R,~E,~A,~Error,~Out,~take,~put,~callback,reader,args,W.clock(~S,~C,~R,~E,world)) 104 def namespaced(~S:Data,~K:Data,~V:Data,~C:Type,~R:Type,~E:Data,~A:Type,~Error:Data,~Out:Type,~take:R -> R & St.Stream,~put:R -> St.Stream -> R,~callback:W.World -> Input -> Sys.Outcome,Error,Out>,reader:instance_type(~S,~K,~V,~C,~R,~E,~A,~Error,~Out,~take,~put,~callback),args:A,result:W.World & U32) -> ReadResult,instance_type(~S,~K,~V,~C,~R,~E,~A,~Error,~Out,~take,~put,~callback),A,Error,Out,V>: 105 match reader result: 106 case SI.Instance{Cleanup.Instance{Sys.Registry{+namespace,+id,+name,+access,cursor},St.Reader{+owner,+key}}}, (world,actual):checked(~S,~K,~V,~C,~R,~E,~A,~Error,~Out,~take,~put,~callback,Bool.and(U32.is_eq(namespace,actual),Bool.and(U32.is_eq(owner,namespace),U32.is_eq(key,id))),SI.Instance{Cleanup.Instance{Sys.Registry{namespace,id,name,access,cursor},St.Reader{owner,key}}},args,W.registration_matches(~S,~C,~R,~E,world,id,name,access)) 107 # Namespace/registration checks precede activation, callback and any cursor change. 108 def read(~S:Data,~K:Data,~V:Data,~C:Type,~R:Type,~E:Data,~A:Type,~Error:Data,~Out:Type,~take:R -> R & St.Stream,~put:R -> St.Stream -> R,~callback:W.World -> Input -> Sys.Outcome,Error,Out>,reader:instance_type(~S,~K,~V,~C,~R,~E,~A,~Error,~Out,~take,~put,~callback),world:W.World,args:A) -> ReadResult,instance_type(~S,~K,~V,~C,~R,~E,~A,~Error,~Out,~take,~put,~callback),A,Error,Out,V>: 109 namespaced(~S,~K,~V,~C,~R,~E,~A,~Error,~Out,~take,~put,~callback,reader,args,W.namespace(~S,~C,~R,~E,world))