1 import Base 2 import ./dependency_composer_program.bend as Scoped 3 import ./dependency_plan.bend as Plan 4 import ./schema_fragments.bend as Fragment 5 import ./execution_declaration.bend as D 6 7 type Error is Data: 8 Schema{error:Fragment.Error} 9 Schedule{error:Plan.Invalid} 10 Nesting{error:Scoped.NestError} 11 def first_error(first:Maybe<&2,Error>,second:Maybe<&2,Error>) -> Maybe<&2,Error>: 12 match first: 13 case Some{error}:Some{error} 14 case None{}:second 15 def schema_error(value:Fragment.Validation) -> Maybe<&2,Error>: 16 match value: 17 case Fragment.Valid{}:None{} 18 case Fragment.Invalid{error}:Some{Schema{error}} 19 def schedule_error(value:Maybe<&2,Plan.Invalid>) -> Maybe<&2,Error>: 20 match value: 21 case None{}:None{} 22 case Some{error}:Some{Schedule{error}} 23 def kind_key(kind:Fragment.RegistryKind,key:String) -> String: 24 match kind: 25 case Fragment.Component{}:D.requirement_key(D.ComponentAccess{},key) 26 case Fragment.Resource{}:D.requirement_key(D.ResourceAccess{},key) 27 case Fragment.Service{}:D.requirement_key(D.ServiceAccess{},key) 28 case Fragment.Event{}:"event/" ++ key 29 case Fragment.Relation{}:"relation/" ++ key 30 def entry_key(~S:Data,entry:Fragment.Entry) -> String: 31 match entry: 32 case Fragment.Entry{kind,key,_}:kind_key(kind,key) 33 case Fragment.Classified{kind,key,_,_}:kind_key(kind,key) 34 def provides(~S:Data,entries:List<&2,Fragment.Entry>,+key:String) -> Bool: 35 match entries: 36 case []:False{} 37 case entry <> rest:Bool.or(String.eq(entry_key(~S,entry),key),provides(~S,rest,key)) 38 def missing_step(available:Bool,id:U32,key:String,next:Maybe<&2,Plan.Invalid>) -> Maybe<&2,Plan.Invalid>: 39 match available: 40 case True{}:next 41 case False{}:Some{Plan.Missing{id,key}} 42 def missing_needs(~S:Data,needs:List<&2,String>,+entries:List<&2,Fragment.Entry>,+id:U32) -> Maybe<&2,Plan.Invalid>: 43 match needs: 44 case []:None{} 45 case +key <> rest:missing_step(provides(~S,entries,key),id,key,missing_needs(~S,rest,entries,id)) 46 def missing(~S:Data,nodes:List<&2,Plan.Node>,+entries:List<&2,Fragment.Entry>) -> Maybe<&2,Plan.Invalid>: 47 match nodes: 48 case []:None{} 49 case Plan.Node{id,needs} <> rest:Plan.first_error(~String,missing_needs(~S,needs,entries,id),missing(~S,rest,entries)) 50 def available(key:String) -> Bool:True{}