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)}