decode_construction.bend

bendvy-ecs-core@0.1.0.1 · 51 lines · 0 definitions

1import Base
2import ordinary_declaration.bend as Identity
3import persistence_declaration.bend as Decl
4import decode_data.bend as D
5import decode.bend as Decode
6import bundle_construction.bend as Build
7import capabilities.bend as Cap
8
9# A retained nominal declaration supplies admission. The schema author provides
10# an actual reversible constructor, not an implicit inverse for arbitrary Type.
11type Factory<-S:Data,-I:Type,-P:Type,-identity:Identity.Declaration<S,P>,-project:P -> P & D.Raw,-incoming:I -> I & D.Raw,-build:I -> D.Raw -> Build.Construction<I,P,D.Error>> is Data:
12  Factory{declaration:Decl.Constructed<S,P,identity,project>,inputCodec:D.Codec}
13def factory(~S:Data,~I:Type,~P:Type,~identity:Identity.Declaration<S,P>,~project:P -> P & D.Raw,~incoming:I -> I & D.Raw,~build:I -> D.Raw -> Build.Construction<I,P,D.Error>,+declaration:Decl.Constructed<S,P,identity,project>) -> Factory<S,I,P,identity,project,incoming,build>:Factory{declaration,Decl.codec(~S,~P,~identity,~project,declaration)}
14def factory_with_input_codec(~S:Data,~I:Type,~P:Type,~identity:Identity.Declaration<S,P>,~project:P -> P & D.Raw,~incoming:I -> I & D.Raw,~build:I -> D.Raw -> Build.Construction<I,P,D.Error>,declaration:Decl.Constructed<S,P,identity,project>,inputCodec:D.Codec) -> Factory<S,I,P,identity,project,incoming,build>:Factory{declaration,inputCodec}
15def checked(~I:Type,~P:Type,~build:I -> D.Raw -> Build.Construction<I,P,D.Error>,receipt:D.Receipt<I>) -> Build.Construction<I,P,D.Error>:
16  match receipt:
17    case D.Receipt{owner,D.Rejected{error}}:Build.Invalid{owner,error}
18    case D.Receipt{owner,D.Accepted{canonical}}:build(owner,canonical)
19def construct(~S:Data,~I:Type,~P:Type,~identity:Identity.Declaration<S,P>,~project:P -> P & D.Raw,~incoming:I -> I & D.Raw,~build:I -> D.Raw -> Build.Construction<I,P,D.Error>,factory:Factory<S,I,P,identity,project,incoming,build>,input:I) -> Build.Construction<I,P,D.Error>:
20  match factory:
21    case Factory{_,inputCodec}:checked(~I,~P,~build,Decode.decode_owner(~I,~incoming,inputCodec,input))
22def request(~S:Data,~I:Type,~P:Type,~identity:Identity.Declaration<S,P>,~project:P -> P & D.Raw,~incoming:I -> I & D.Raw,~build:I -> D.Raw -> Build.Construction<I,P,D.Error>,+factory:Factory<S,I,P,identity,project,incoming,build>,input:I) -> Factory<S,I,P,identity,project,incoming,build> & Build.Construction<I,P,D.Error>:
23  (factory,construct(~S,~I,~P,~identity,~project,~incoming,~build,factory,input))
24# Constructed output or exact refused raw owner crosses only an owned grant.
25def grant(~S:Data,~I:Type,~P:Type,~identity:Identity.Declaration<S,P>,~project:P -> P & D.Raw,~incoming:I -> I & D.Raw,~build:I -> D.Raw -> Build.Construction<I,P,D.Error>) -> Cap.OwnedRequest<Factory<S,I,P,identity,project,incoming,build>,I,Build.Construction<I,P,D.Error>>:
26  Cap.OwnedRequest{factory => input => request(~S,~I,~P,~identity,~project,~incoming,~build,factory,input)}
27def invoke(~S:Data,~I:Type,~P:Type,~identity:Identity.Declaration<S,P>,~project:P -> P & D.Raw,~incoming:I -> I & D.Raw,~build:I -> D.Raw -> Build.Construction<I,P,D.Error>,~A:Type,~Out:Type,~body:@-H:Type -> @-cap:Cap.OwnedRequest<H,I,Build.Construction<I,P,D.Error>> -> A -> H -> H & Out,factory:Factory<S,I,P,identity,project,incoming,build>,args:A) -> Factory<S,I,P,identity,project,incoming,build> & Out:
28  Cap.invoke_owned(~(H => Cap.OwnedRequest<H,I,Build.Construction<I,P,D.Error>>),~A,~Out,~body,~Factory<S,I,P,identity,project,incoming,build>,~grant(~S,~I,~P,~identity,~project,~incoming,~build),args,factory)
29
30# Custom constructors may fail with any Data error. Keep decoder and constructor
31# errors distinct rather than coercing a host/business error into a codec path.
32type Error<Custom:Data> is Data:Validation{error:D.Error} Constructor{error:Custom}
33type FallibleFactory<-S:Data,-I:Type,-P:Type,-Custom:Data,-identity:Identity.Declaration<S,P>,-project:P -> P & D.Raw,-incoming:I -> I & D.Raw,-build:I -> D.Raw -> Build.Construction<I,P,Custom>> is Data:
34  FallibleFactory{declaration:Decl.Constructed<S,P,identity,project>,inputCodec:D.Codec}
35def fallible_factory(~S:Data,~I:Type,~P:Type,~Custom:Data,~identity:Identity.Declaration<S,P>,~project:P -> P & D.Raw,~incoming:I -> I & D.Raw,~build:I -> D.Raw -> Build.Construction<I,P,Custom>,+declaration:Decl.Constructed<S,P,identity,project>) -> FallibleFactory<S,I,P,Custom,identity,project,incoming,build>:FallibleFactory{declaration,Decl.codec(~S,~P,~identity,~project,declaration)}
36def fallible_factory_with_input_codec(~S:Data,~I:Type,~P:Type,~Custom:Data,~identity:Identity.Declaration<S,P>,~project:P -> P & D.Raw,~incoming:I -> I & D.Raw,~build:I -> D.Raw -> Build.Construction<I,P,Custom>,declaration:Decl.Constructed<S,P,identity,project>,inputCodec:D.Codec) -> FallibleFactory<S,I,P,Custom,identity,project,incoming,build>:FallibleFactory{declaration,inputCodec}
37def custom_result(~I:Type,~P:Type,~Custom:Data,result:Build.Construction<I,P,Custom>) -> Build.Construction<I,P,Error<Custom>>:
38  match result:
39    case Build.Invalid{owner,error}:Build.Invalid{owner,Constructor{error}}
40    case Build.Constructed{owner,undo}:Build.Constructed{owner,undo}
41def fallible_checked(~I:Type,~P:Type,~Custom:Data,~build:I -> D.Raw -> Build.Construction<I,P,Custom>,receipt:D.Receipt<I>) -> Build.Construction<I,P,Error<Custom>>:
42  match receipt:
43    case D.Receipt{owner,D.Rejected{error}}:Build.Invalid{owner,Validation{error}}
44    case D.Receipt{owner,D.Accepted{canonical}}:custom_result(~I,~P,~Custom,build(owner,canonical))
45def fallible_construct(~S:Data,~I:Type,~P:Type,~Custom:Data,~identity:Identity.Declaration<S,P>,~project:P -> P & D.Raw,~incoming:I -> I & D.Raw,~build:I -> D.Raw -> Build.Construction<I,P,Custom>,factory:FallibleFactory<S,I,P,Custom,identity,project,incoming,build>,input:I) -> Build.Construction<I,P,Error<Custom>>:
46  match factory:
47    case FallibleFactory{_,inputCodec}:fallible_checked(~I,~P,~Custom,~build,Decode.decode_owner(~I,~incoming,inputCodec,input))
48def fallible_request(~S:Data,~I:Type,~P:Type,~Custom:Data,~identity:Identity.Declaration<S,P>,~project:P -> P & D.Raw,~incoming:I -> I & D.Raw,~build:I -> D.Raw -> Build.Construction<I,P,Custom>,+factory:FallibleFactory<S,I,P,Custom,identity,project,incoming,build>,input:I) -> FallibleFactory<S,I,P,Custom,identity,project,incoming,build> & Build.Construction<I,P,Error<Custom>>:
49  (factory,fallible_construct(~S,~I,~P,~Custom,~identity,~project,~incoming,~build,factory,input))
50def fallible_grant(~S:Data,~I:Type,~P:Type,~Custom:Data,~identity:Identity.Declaration<S,P>,~project:P -> P & D.Raw,~incoming:I -> I & D.Raw,~build:I -> D.Raw -> Build.Construction<I,P,Custom>) -> Cap.OwnedRequest<FallibleFactory<S,I,P,Custom,identity,project,incoming,build>,I,Build.Construction<I,P,Error<Custom>>>:
51  Cap.OwnedRequest{factory => input => fallible_request(~S,~I,~P,~Custom,~identity,~project,~incoming,~build,factory,input)}