1 import Base 2 import entity_key.bend as Key 3 import ./relation_types.bend as G 4 import ./relation_graph.bend as Graph 5 import ./relation_commands.bend as A 6 import ./relation_reorder.bend as Reorder 7 import ./relation_providers.bend as Relations 8 import ./world.bend as W 9 import ./capabilities.bend as Cap 10 import ./hierarchy_traversal.bend as T 11 12 type Path is Data: 13 Complete{handles:List<&2,W.Handle>} 14 Incomplete{handles:List<&2,W.Handle>,pending:List<&2,W.Handle>} 15 type Frame is Data: 16 Frame{entity:W.Handle,parent:Maybe<&2,W.Handle>,children:List<&2,W.Handle>,ancestors:Path,root:Maybe<&2,W.Handle>,depth:Path,breadth:Path} 17 type Read is Type: 18 Read{lookup:Cap.Request,Maybe<&2,Frame>>} 19 def path(~S:Data,walk:T.Walk,+namespace:U32) -> Path: 20 match walk: 21 case T.Complete{ids}: Complete{Relations.handle_ids(~S,ids,namespace)} 22 case T.Incomplete{ids,pending}: Incomplete{Relations.handle_ids(~S,ids,namespace),Relations.handle_ids(~S,pending,namespace)} 23 def handle(~S:Data,id:Maybe<&2,Key.Key>,namespace:U32) -> Maybe<&2,W.Handle>: 24 match id: 25 case None{}: None{} 26 case Some{id}: Some{W.Handle{namespace,id}} 27 def snapshot(~S:Data,+graph:G.Graph,+descriptor:G.Descriptor,target:W.Handle) -> Frame: 28 match target: 29 case W.Handle{+namespace,+id}: Frame{W.Handle{namespace,id},handle(~S,Graph.target(~S,graph,descriptor,id),namespace),Relations.handle_ids(~S,Graph.inverse(~S,graph,descriptor,id),namespace),path(~S,T.ancestors(~S,graph,descriptor,id),namespace),handle(~S,T.root(T.ancestors(~S,graph,descriptor,id),id),namespace),path(~S,T.descendants(~S,graph,descriptor,id,T.Depth{}),namespace),path(~S,T.descendants(~S,graph,descriptor,id,T.Breadth{}),namespace)} 30 def store_snapshot(~S:Data,~C:Type,store:A.Store,descriptor:G.Descriptor,target:W.Handle) -> A.Store & Frame: 31 match store: 32 case A.Store{components,+graph}: (A.Store{components,graph},snapshot(~S,graph,descriptor,target)) 33 def present(~S:Data,~C:Type,~R:Type,~E:Data,result:W.World,R,A.Notice> & Frame) -> W.World,R,A.Notice> & Maybe<&2,Frame>: 34 (world,frame) = result 35 (world,Some{frame}) 36 def checked(~S:Data,~C:Type,~R:Type,~E:Data,~descriptor:G.HierarchyDescriptor,observed:W.World,R,A.Notice> & Bool,target:W.Handle) -> W.World,R,A.Notice> & Maybe<&2,Frame>: 37 match observed: 38 case (world,False{}): (world,None{}) 39 case (world,True{}): present(~S,~C,~R,~E,W.with_store(~S,~A.Store,~R,~A.Notice,~Frame,store => store_snapshot(~S,~C,store,Reorder.descriptor(~S,descriptor),target),world)) 40 def lookup(~S:Data,~C:Type,~R:Type,~E:Data,~descriptor:G.HierarchyDescriptor,world:W.World,R,A.Notice>,target:W.Handle) -> W.World,R,A.Notice> & Maybe<&2,Frame>: 41 match target: 42 case W.Handle{+ns,+id}: checked(~S,~C,~R,~E,~descriptor,W.valid(~S,~A.Store,~R,~A.Notice,world,W.Handle{ns,id}),W.Handle{ns,id}) 43 def read(-H:Type,-S:Data,caps:Read,owner:H,target:W.Handle) -> H & Maybe<&2,Frame>: 44 match caps: 45 case Read{Cap.Request{get}}: get(owner,target) 46 def grant(~S:Data,~C:Type,~R:Type,~E:Data,~descriptor:G.HierarchyDescriptor,~Out:Type,~body:@-H:Type -> Read -> W.Handle -> H -> H & Out,target:W.Handle,world:W.World,R,A.Notice>) -> W.World,R,A.Notice> & Out: 47 body(W.World,R,A.Notice>,Read{Cap.Request{lookup(~S,~C,~R,~E,~descriptor)}},target,world)