1 import Base 2 import ./world.bend as W 3 import ./schedule.bend as Sch 4 import ./schedule_provision.bend as SP 5 # Closed typed composition carries independently authored owners, never a copied 6 # closure or a caller-maintained dispatcher enumeration. 7 # Detached actual registration identity used by heterogeneous composition. 8 # Includes namespace/ID/name/access for validation; not a substitute for the 9 # affine owner or an authorization token on its own. 10 type Identity is Data: 11 Identity{namespace:U32,id:U32,name:String,access:List<&2,String>} 12 # Dispatch result retaining World and heterogeneous owner on completion, 13 # skip, failure or refusal. Error values are detached; owner restoration and 14 # transaction behavior belong to the selected registered runner. 15 type Outcome is Type: 16 Completed{world:World,owner:Owner} 17 Skipped{world:World,owner:Owner} 18 Failed{world:World,owner:Owner,error:Error} 19 Refused{world:World,owner:Owner} 20 # Detached heterogeneous error sum used when composing registered systems. 21 # LeftError and RightError identify the originating error branch; it carries 22 # neither the World nor affine system owners, which return separately. 23 type Choice is Data: 24 LeftError{error:L} 25 RightError{error:R} 26 def ids(items:List<&2,Identity>) -> List<&2,U32>: 27 match items: 28 case []:[] 29 case Identity{_,id,_,_} <> rest:id <> ids(rest) 30 def member(items:List<&2,Identity>,+wanted:U32) -> Bool: 31 match items: 32 case []:False{} 33 case Identity{_,id,_,_} <> rest:Bool.or(U32.is_eq(id,wanted),member(rest,wanted)) 34 def identities_valid(+namespace:U32,+registered:List<&2,W.RegistrationMeta>,items:List<&2,Identity>,+seen:List<&2,U32>) -> Bool: 35 match items: 36 case []:True{} 37 case Identity{ns,+id,name,access} <> rest:Bool.and(U32.is_eq(namespace,ns),Bool.and(W.registration_list_matches(registered,id,name,access),Bool.and(Bool.not(Sch.contains(seen,id)),identities_valid(namespace,registered,rest,id <> seen)))) 38 def pair_catalog_done(~L:Type,~R:Type,left:L,entries:List<&2,Identity>,result:R & List<&2,Identity>) -> (L & R) & List<&2,Identity>: 39 match result: 40 case (right,more):((left,right),List.append(&2,Identity,entries,more)) 41 def pair_catalog_left(~L:Type,~R:Type,~right:R -> R & List<&2,Identity>,other:R,result:L & List<&2,Identity>) -> (L & R) & List<&2,Identity>: 42 match result: 43 case (owner,entries):pair_catalog_done(~L,~R,owner,entries,right(other)) 44 # Advanced owner-threading catalog composition in left/right order. 45 # Returns both affine owners and appended identities without executing bodies. 46 # Supplied catalog callbacks must preserve actual registration correspondence. 47 def pair_catalog(~L:Type,~R:Type,~left:L -> L & List<&2,Identity>,~right:R -> R & List<&2,Identity>,owners:L & R) -> (L & R) & List<&2,Identity>: 48 match owners: 49 case (a,b):pair_catalog_left(~L,~R,~right,b,left(a)) 50 def left_returned(~World:Type,~L:Type,~R:Type,~LE:Data,~RE:Data,right:R,result:Outcome) -> Outcome>: 51 match result: 52 case Completed{world,left}:Completed{world,(left,right)} 53 case Skipped{world,left}:Skipped{world,(left,right)} 54 case Failed{world,left,error}:Failed{world,(left,right),LeftError{error}} 55 case Refused{world,left}:Refused{world,(left,right)} 56 def right_returned(~World:Type,~L:Type,~R:Type,~LE:Data,~RE:Data,left:L,result:Outcome) -> Outcome>: 57 match result: 58 case Completed{world,right}:Completed{world,(left,right)} 59 case Skipped{world,right}:Skipped{world,(left,right)} 60 case Failed{world,right,error}:Failed{world,(left,right),RightError{error}} 61 case Refused{world,right}:Refused{world,(left,right)} 62 def pair_selected(~World:Type,~L:Type,~R:Type,~LE:Data,~RE:Data,~left:L -> World -> U32 -> Outcome,~right:R -> World -> U32 -> Outcome,found:Bool,a:L,b:R,world:World,id:U32) -> Outcome>: 63 match found: 64 case True{}:left_returned(~World,~L,~R,~LE,~RE,b,left(a,world,id)) 65 case False{}:right_returned(~World,~L,~R,~LE,~RE,a,right(b,world,id)) 66 def pair_cataloged(~World:Type,~L:Type,~R:Type,~LE:Data,~RE:Data,~left:L -> World -> U32 -> Outcome,~right:R -> World -> U32 -> Outcome,b:R,world:World,+id:U32,result:L & List<&2,Identity>) -> Outcome>: 67 match result: 68 case (a,entries):pair_selected(~World,~L,~R,~LE,~RE,~left,~right,member(entries,id),a,b,world,id) 69 # Advanced heterogeneous dispatch using the left catalog to choose a branch. 70 # Retains both owners, wraps errors as LeftError/RightError and preserves skip/ 71 # refusal outcomes. The selected dispatcher performs registration validation; 72 # metadata membership alone confers no authority and adds no rollback. 73 def pair_dispatch(~World:Type,~L:Type,~R:Type,~LE:Data,~RE:Data,~catalog:L -> L & List<&2,Identity>,~left:L -> World -> U32 -> Outcome,~right:R -> World -> U32 -> Outcome,owners:L & R,world:World,id:U32) -> Outcome>: 74 match owners: 75 case (a,b):pair_cataloged(~World,~L,~R,~LE,~RE,~left,~right,b,world,id,catalog(a))