1 import Base
2
3 # The existential field retains the actual typed owner header across a pure
4 # call. Its native layout stays boxed even when the held product is wide.
5 # Bind the header before that call: native ANF hoists nested call arguments
6 # before inline constructor arguments, otherwise retaining the unpacked owners.
7 type Header<-Input:Type,-Output:Type> is Type:
8 Header{-Held:Type,held:Held,resume:Held -> Input -> Output}
9 def returned(-Input:Type,-Output:Type,header:Header,value:Input) -> Output:
10 match header:
11 case Header{Held,held,resume}:resume(held,value)
12 def decided(-Output:Type,header:Header<(Bool & Bool),Output>,valid:Bool,compatible:Bool) -> Output:
13 returned(Bool & Bool,Output,header,(valid,compatible))
14
15 # A unary resume receives both actual owners together, avoiding a curried
16 # closure that captures the unpacked Held before receiving Input.
17 type PairedHeader<-Input:Type,-Output:Type> is Type:
18 PairedHeader{-Held:Type,held:Held,resume:(Held & Input) -> Output}
19 def paired_returned(-Input:Type,-Output:Type,header:PairedHeader,value:Input) -> Output:
20 match header:
21 case PairedHeader{Held,held,resume}:resume((held,value))
22 def pure_paired(-Output:Type,header:PairedHeader) -> IO(Output):
23 R => k => k(paired_returned(Unit,Output,header,Unit{}))