1 import Base 2 import ./execution_composer_layout.bend as Layout 3 import ./execution_resource_policy.bend as Policy 4 import ./execution_relation_resource_publication.bend as Cast 5 import ./execution_relation_store.bend as Store 6 import ./relation_types.bend as T 7 8 type GraphView<-S:Data> is Data: 9 GraphView{route:Layout.Route,descriptor:T.Descriptor,namespace:U32,graph:T.Graph} 10 def Program(~S:Data,~resources:Layout.Layout) -> Type: 11 Layout.resources(~S,resources) -> Layout.resources(~S,resources) & List<&2,GraphView> 12 def empty(~S:Data,~resources:Layout.Layout,owners:Layout.resources(~S,resources)) -> Layout.resources(~S,resources) & List<&2,GraphView>: 13 (owners,[]) 14 def observed(~S:Data,~descriptor:T.Descriptor,~key:String,~origin:Layout.Layout,route:Layout.Route,slot:Layout.ResourceSlot,Store.View>,key,origin>) -> Layout.ResourceSlot,Store.View>,key,origin> & GraphView: 15 match slot: 16 case Layout.ResourceSlot{Layout.Viewed{Store.Store{+namespace,+graph,failures,sequence,nextReader},cache},stamp}:(Layout.ResourceSlot{Layout.Viewed{Store.Store{namespace,graph,failures,sequence,nextReader},cache},stamp},GraphView{route,descriptor,namespace,graph}) 17 def restored(~S:Data,~resources:Layout.Layout,~route:Layout.Route,~descriptor:T.Descriptor,~payload:{Layout.payload(resources,route) == Store.Store : Type},~view:{Layout.view(resources,route) == Store.View : Data},previous:List<&2,GraphView>,rest:Layout.resource_rest(~S,resources,route),result:Layout.ResourceSlot,Store.View>,Layout.key(resources,route),Layout.origin(resources,route)> & GraphView) -> Layout.resources(~S,resources) & List<&2,GraphView>: 18 match result: 19 case (slot,seen):(Layout.resource_put(~S,resources,route,rest,Cast.slot(~S,~Layout.key(resources,route),~Layout.origin(resources,route),~Store.Store,~Layout.payload(resources,route),~Store.View,~Layout.view(resources,route),Equal.sym(Type,Layout.payload(resources,route),Store.Store,payload),Equal.sym(Data,Layout.view(resources,route),Store.View,view),slot)),seen <> previous) 20 def selected(~S:Data,~resources:Layout.Layout,~route:Layout.Route,~descriptor:T.Descriptor,~payload:{Layout.payload(resources,route) == Store.Store : Type},~view:{Layout.view(resources,route) == Store.View : Data},previous:List<&2,GraphView>,result:Layout.resource_rest(~S,resources,route) & Layout.ResourceSlot) -> Layout.resources(~S,resources) & List<&2,GraphView>: 21 match result: 22 case (rest,slot):restored(~S,~resources,~route,~descriptor,~payload,~view,previous,rest,observed(~S,~descriptor,~Layout.key(resources,route),~Layout.origin(resources,route),route,Cast.slot(~S,~Layout.key(resources,route),~Layout.origin(resources,route),~Layout.payload(resources,route),~Store.Store,~Layout.view(resources,route),~Store.View,payload,view,slot))) 23 def gathered(~S:Data,~resources:Layout.Layout,~route:Layout.Route,~descriptor:T.Descriptor,~payload:{Layout.payload(resources,route) == Store.Store : Type},~view:{Layout.view(resources,route) == Store.View : Data},result:Layout.resources(~S,resources) & List<&2,GraphView>) -> Layout.resources(~S,resources) & List<&2,GraphView>: 24 match result: 25 case (owners,previous):selected(~S,~resources,~route,~descriptor,~payload,~view,previous,Layout.resource_take(~S,resources,route,owners)) 26 # A closed grant extends this observer beside its mutating dispatcher. It never 27 # grants gameplay access to the graph owner, failure channel or resource lens. 28 def extend(~S:Data,~resources:Layout.Layout,~route:Layout.Route,~descriptor:T.Descriptor,~payload:{Layout.payload(resources,route) == Store.Store : Type},~view:{Layout.view(resources,route) == Store.View : Data},~protected:{Layout.policy(resources,route) == Policy.ProtectedRelation{S,descriptor} : Policy.Policy},previous:Program(~S,~resources)) -> Program(~S,~resources): 29 owners => gathered(~S,~resources,~route,~descriptor,~payload,~view,previous(owners))