1 import Base 2 import ./decode_data.bend as D 3 import ./restore_graph_data.bend as R 4 import ./ordinary_machine_declaration.bend as Ordinary 5 import ./ordinary_machine_initialization.bend as Init 6 import ./machine.bend as M 7 import ./machine_stream.bend as Stream 8 import ./machine_stream_queue.bend as Queue 9 import ./owner_product.bend as Product 10 11 type Dispatch is Data:Unhandled{} Valid{} Invalid{} 12 type Schema<-Resources:Type,-read:Resources -> Resources & List<&2,D.Field>,-check:D.Field -> Dispatch,-clear:Resources -> Resources,-install:Resources -> List<&2,D.Field> -> Resources> is Data: 13 Schema{} 14 def take_slot(~S:Data,~K:Data,~V:Data,state:Init.State) -> Init.State & M.Slot: 15 Init.slot(~S,~K,~V,state) 16 def cleared_stream(~V:Data,value:Stream.Stream) -> Stream.Stream: 17 match value: 18 case Stream.Stream{Queue.Queue{_,_,_,dropped,_},positions,frameStart}:Stream.Stream{Queue.Queue{[],[],0n,dropped,0n},positions,frameStart} 19 def clear(~S:Data,~K:Data,~V:Data,state:Init.State) -> Init.State: 20 match state: 21 case Init.State{slot,stream,revision}:Init.State{M.reset(~S,~K,~V,slot),cleared_stream(~V,stream),revision} 22 def encoded(~S:Data,~K:Data,~V:Data,~encode:V -> D.Raw,name:String,slot:M.Slot) -> List<&2,D.Field>: 23 match slot: 24 case M.Missing{}:[] 25 case M.Present{value,_,_,_}:[D.Field{name,encode(value)}] 26 def read(~S:Data,~K:Data,~V:Data,~encode:V -> D.Raw,~DeclaredOwner:Type,~take:DeclaredOwner -> DeclaredOwner & M.Slot,~declaration:Ordinary.Declaration,state:Init.State) -> Init.State & List<&2,D.Field>: 27 match state: 28 case Init.State{+slot,+stream,+revision}:(Init.State{slot,stream,revision},encoded(~S,~K,~V,~encode,Ordinary.name(~S,~K,~V,~DeclaredOwner,~take,declaration),slot)) 29 def member(~V:Data,~same:V -> V -> Bool,+value:V,values:List<&2,V>) -> Bool: 30 match values: 31 case []:False{} 32 case other <> rest:Bool.or(same(value,other),member(~V,~same,value,rest)) 33 def permitted(~V:Data,~same:V -> V -> Bool,value:V,values:Maybe<&2,List<&2,V>>) -> Bool: 34 match values: 35 case None{}:True{} 36 case Some{values}:member(~V,~same,value,values) 37 def selected(value:Bool) -> Dispatch: 38 match value: 39 case True{}:Valid{} 40 case False{}:Invalid{} 41 def decoded(~V:Data,~same:V -> V -> Bool,values:Maybe<&2,List<&2,V>>,value:Maybe<&2,V>) -> Dispatch: 42 match value: 43 case None{}:Invalid{} 44 case Some{value}:selected(permitted(~V,~same,value,values)) 45 def checked(~V:Data,~decode:D.Raw -> Maybe<&2,V>,~same:V -> V -> Bool,values:Maybe<&2,List<&2,V>>,result:D.Checked) -> Dispatch: 46 match result: 47 case D.Rejected{_}:Invalid{} 48 case D.Accepted{raw}:decoded(~V,~same,values,decode(raw)) 49 def named(~V:Data,~decode:D.Raw -> Maybe<&2,V>,~same:V -> V -> Bool,found:Bool,values:Maybe<&2,List<&2,V>>,+raw:D.Raw,codec:D.Codec) -> Dispatch: 50 match found: 51 case False{}:Unhandled{} 52 case True{}:checked(~V,~decode,~same,values,D.validate(100000n,D.Continue{[D.Work{codec,raw,"$"}]},raw)) 53 def check(~S:Data,~K:Data,~V:Data,~codec:D.Codec,~decode:D.Raw -> Maybe<&2,V>,~same:V -> V -> Bool,~DeclaredOwner:Type,~take:DeclaredOwner -> DeclaredOwner & M.Slot,~declaration:Ordinary.Declaration,field:D.Field) -> Dispatch: 54 match field: 55 case D.Field{name,raw}:named(~V,~decode,~same,String.eq(name,Ordinary.name(~S,~K,~V,~DeclaredOwner,~take,declaration)),Ordinary.values(~S,~K,~V,~DeclaredOwner,~take,declaration),raw,codec) 56 def installed(~S:Data,~K:Data,~V:Data,state:Init.State,value:V) -> Init.State: 57 match state: 58 case Init.State{slot,stream,revision}:Init.State{Init.insertion_slot(~S,~K,~V,value,M.reset(~S,~K,~V,slot)),cleared_stream(~V,stream),1n+revision} 59 def decoded_install(~S:Data,~K:Data,~V:Data,state:Init.State,value:Maybe<&2,V>) -> Init.State: 60 match value: 61 case None{}:state 62 case Some{value}:installed(~S,~K,~V,state,value) 63 def install_named(~S:Data,~K:Data,~V:Data,~decode:D.Raw -> Maybe<&2,V>,found:Bool,state:Init.State,raw:D.Raw) -> Init.State: 64 match found: 65 case False{}:state 66 case True{}:decoded_install(~S,~K,~V,state,decode(raw)) 67 def install_loop(~S:Data,~K:Data,~V:Data,~decode:D.Raw -> Maybe<&2,V>,~DeclaredOwner:Type,~take:DeclaredOwner -> DeclaredOwner & M.Slot,~declaration:Ordinary.Declaration,values:List<&2,D.Field>,state:Init.State) -> Init.State: 68 match values: 69 case []:state 70 case D.Field{name,raw} <> rest:install_loop(~S,~K,~V,~decode,~DeclaredOwner,~take,~declaration,rest,install_named(~S,~K,~V,~decode,String.eq(name,Ordinary.name(~S,~K,~V,~DeclaredOwner,~take,declaration)),state,raw)) 71 def install(~S:Data,~K:Data,~V:Data,~decode:D.Raw -> Maybe<&2,V>,~DeclaredOwner:Type,~take:DeclaredOwner -> DeclaredOwner & M.Slot,~declaration:Ordinary.Declaration,state:Init.State,values:List<&2,D.Field>) -> Init.State: 72 install_loop(~S,~K,~V,~decode,~DeclaredOwner,~take,~declaration,values,state) 73 def machine(~S:Data,~K:Data,~V:Data,~codec:D.Codec,~encode:V -> D.Raw,~decode:D.Raw -> Maybe<&2,V>,~same:V -> V -> Bool,~DeclaredOwner:Type,~take:DeclaredOwner -> DeclaredOwner & M.Slot,~declaration:Ordinary.Declaration) -> Schema,read(~S,~K,~V,~encode,~DeclaredOwner,~take,~declaration),check(~S,~K,~V,~codec,~decode,~same,~DeclaredOwner,~take,~declaration),clear(~S,~K,~V),install(~S,~K,~V,~decode,~DeclaredOwner,~take,~declaration)>: 74 Schema{} 75 def joined_read(~L:Type,~Right:Type,left:L,leftFields:List<&2,D.Field>,result:Right & List<&2,D.Field>) -> Product.Owner & List<&2,D.Field>: 76 match result: 77 case (right,rightFields):(Product.Owner{left,right},List.append(&2,D.Field,leftFields,rightFields)) 78 def left_read(~L:Type,~Right:Type,~readRight:Right -> Right & List<&2,D.Field>,right:Right,result:L & List<&2,D.Field>) -> Product.Owner & List<&2,D.Field>: 79 match result: 80 case (left,fields):joined_read(~L,~Right,left,fields,readRight(right)) 81 def product_read(~L:Type,~Right:Type,~readLeft:L -> L & List<&2,D.Field>,~readRight:Right -> Right & List<&2,D.Field>,owner:Product.Owner) -> Product.Owner & List<&2,D.Field>: 82 match owner: 83 case Product.Owner{left,right}:left_read(~L,~Right,~readRight,right,readLeft(left)) 84 def next_check(result:Dispatch,next:Unit -> Dispatch) -> Dispatch: 85 match result: 86 case Unhandled{}:next(Unit{}) 87 case result:result 88 def product_check(~left:D.Field -> Dispatch,~right:D.Field -> Dispatch,field:D.Field) -> Dispatch: 89 +value=field 90 next_check(left(value),_ => right(value)) 91 def product_clear(~L:Type,~Right:Type,~left:L -> L,~right:Right -> Right,owner:Product.Owner) -> Product.Owner: 92 match owner: 93 case Product.Owner{l,r}:Product.Owner{left(l),right(r)} 94 def product_install(~L:Type,~Right:Type,~left:L -> List<&2,D.Field> -> L,~right:Right -> List<&2,D.Field> -> Right,owner:Product.Owner,fields:List<&2,D.Field>) -> Product.Owner: 95 match owner: 96 case Product.Owner{l,r}: 97 +values=fields 98 Product.Owner{left(l,values),right(r,values)} 99 def product(~L:Type,~Right:Type,~readLeft:L -> L & List<&2,D.Field>,~checkLeft:D.Field -> Dispatch,~clearLeft:L -> L,~installLeft:L -> List<&2,D.Field> -> L,~readRight:Right -> Right & List<&2,D.Field>,~checkRight:D.Field -> Dispatch,~clearRight:Right -> Right,~installRight:Right -> List<&2,D.Field> -> Right,-left:Schema,-right:Schema) -> Schema,product_read(~L,~Right,~readLeft,~readRight),product_check(~checkLeft,~checkRight),product_clear(~L,~Right,~clearLeft,~clearRight),product_install(~L,~Right,~installLeft,~installRight)>: 100 Schema{} 101 def field_checked(+field:D.Field,result:Dispatch) -> Maybe<&2,R.Error>: 102 match field result: 103 case D.Field{name,_} Unhandled{}:Some{R.UnknownMachine{name}} 104 case D.Field{name,raw} Invalid{}:Some{R.InvalidMachineState{name,raw}} 105 case _ Valid{}:None{} 106 def continued(error:Maybe<&2,R.Error>,next:Unit -> Maybe<&2,R.Error>) -> Maybe<&2,R.Error>: 107 match error: 108 case Some{error}:Some{error} 109 case None{}:next(Unit{}) 110 def validate(~check:D.Field -> Dispatch,values:List<&2,D.Field>) -> Maybe<&2,R.Error>: 111 match values: 112 case []:None{} 113 case +field <> rest:continued(field_checked(field,check(field)),_ => validate(~check,rest))