1 import Base 2 import ./ordinary_checked_condition.bend as Cond 3 import ./check.bend as K 4 import ./schedule.bend as Sch 5 6 type Description is Data:Description{systemId:U32,condition:Cond.Description} 7 type Selection is Type: 8 Selected{world:World,owner:Owner,result:Result<&2,&2,Cond.Error,Bool>} 9 Unbound{world:World,owner:Owner} 10 type BoundOwner is Type:BoundOwner{systemId:U32,owner:Owner} 11 type Bindings World -> U32 -> Selection> is Type: 12 Bindings{owner:Owner,descriptions:List<&2,Description>} 13 def selected_returned(~World:Type,~Owner:Type,id:U32,value:Cond.Evaluation) -> Selection>: 14 match value: 15 case Cond.Evaluation{world,owner,Fail{Cond.NoBinding{}}}:Unbound{world,BoundOwner{id,owner}} 16 case Cond.Evaluation{world,owner,result}:Selected{world,BoundOwner{id,owner},result} 17 def selected(~World:Type,~Owner:Type,~evaluate:Owner -> World -> Cond.Evaluation,allowed:Bool,id:U32,owner:Owner,world:World) -> Selection>: 18 match allowed: 19 case False{}:Unbound{world,BoundOwner{id,owner}} 20 case True{}:selected_returned(~World,~Owner,id,evaluate(owner,world)) 21 def select(~World:Type,~Owner:Type,~evaluate:Owner -> World -> Cond.Evaluation,value:BoundOwner,world:World,target:U32) -> Selection>: 22 match value: 23 case BoundOwner{+id,owner}:selected(~World,~Owner,~evaluate,U32.is_eq(id,target),id,owner,world) 24 def bind(~World:Type,~Owner:Type,~evaluate:Owner -> World -> Cond.Evaluation,+id:U32,value:Cond.Condition) -> Bindings,select(~World,~Owner,~evaluate)>: 25 match value: 26 case Cond.Condition{owner,description}:Bindings{BoundOwner{id,owner},[Description{id,description}]} 27 def includes(values:List<&2,Description>,+id:U32) -> Bool: 28 match values: 29 case []:False{} 30 case Description{other,_} <> rest:Bool.or(U32.is_eq(id,other),includes(rest,id)) 31 def with_right(~World:Type,~Left:Type,~Right:Type,right:Right,value:Selection) -> Selection: 32 match value: 33 case Selected{world,left,result}:Selected{world,(left,right),result} 34 case Unbound{world,left}:Unbound{world,(left,right)} 35 def with_left(~World:Type,~Left:Type,~Right:Type,left:Left,value:Selection) -> Selection: 36 match value: 37 case Selected{world,right,result}:Selected{world,(left,right),result} 38 case Unbound{world,right}:Unbound{world,(left,right)} 39 def pair_left_returned(~World:Type,~Left:Type,~Right:Type,~right_select:Right -> World -> U32 -> Selection,right:Right,id:U32,value:Selection) -> Selection: 40 match value: 41 case Selected{world,left,result}:Selected{world,(left,right),result} 42 case Unbound{world,left}:with_left(~World,~Left,~Right,left,right_select(right,world,id)) 43 def pair_shared(~World:Type,~Left:Type,~Right:Type,~left_select:Left -> World -> U32 -> Selection,~right_select:Right -> World -> U32 -> Selection,owners:Left & Right,world:World,+id:U32) -> Selection: 44 match owners: 45 case (left,right):pair_left_returned(~World,~Left,~Right,~right_select,right,id,left_select(left,world,id)) 46 def pair_select(~World:Type,~Left:Type,~Right:Type,~left_select:Left -> World -> U32 -> Selection,~right_select:Right -> World -> U32 -> Selection,owners:Left & Right,world:World,id:U32) -> Selection: 47 pair_shared(~World,~Left,~Right,~left_select,~right_select,owners,world,id) 48 def pair(~World:Type,~Left:Type,~Right:Type,~left_select:Left -> World -> U32 -> Selection,~right_select:Right -> World -> U32 -> Selection,left:Bindings,right:Bindings) -> Bindings: 49 match left right: 50 case Bindings{left,ld} Bindings{right,rd}:Bindings{(left,right),List.append(&2,Description,ld,rd)} 51 def contains(ids:List<&2,U32>,+id:U32) -> Bool: 52 match ids: 53 case []:False{} 54 case head <> rest:Bool.or(U32.is_eq(id,head),contains(rest,id)) 55 def unique(values:List<&2,Description>,+seen:List<&2,U32>) -> Bool: 56 match values: 57 case []:True{} 58 case Description{+id,_} <> rest:Bool.and(Bool.not(contains(seen,id)),unique(rest,id <> seen)) 59 def has_system(steps:List<&2,Sch.Step>,+id:U32) -> Bool: 60 match steps: 61 case []:False{} 62 case Sch.System{other,_} <> rest:Bool.or(U32.is_eq(other,id),has_system(rest,id)) 63 case _ <> rest:has_system(rest,id) 64 def targets(values:List<&2,Description>,+steps:List<&2,Sch.Step>) -> Bool: 65 match values: 66 case []:True{} 67 case Description{id,_} <> rest:Bool.and(has_system(steps,id),targets(rest,steps))