/* Necessary utility types */ pub type First = U pub type Last = U pub type Prefix = Tuple(...U) pub type Suffix = Tuple(...U) /* Closure interfaces */ /** * Type is `cons fn (P) -> T` */ pub int ConsClosure(P : Tuple = ()) -> T { ref fn getDelegate() -> Option<&D> mut fn setDelegate(d: D) -> Void cons fn call(...p: P) -> T cons fn applyFirst(first: First

) -> Self(Suffix

) -> T cons fn applyLast(last: Last

) -> Self(Prefix

) -> T def cons op >> alias applyFirst def cons op << alias applyLast } /** * Type is `mut ref fn (P) -> T` */ pub int MutRefClosure(P : Tuple = ()) -> T : ConsClosure(P) -> T { mut ref fn call(...p: P) -> T } /** * Type is `ref fn (P) -> T` */ pub int ReadRefClosure(P : Tuple = ()) -> T : MutRefClosure(P) -> T { ref fn call(...p: P) -> T } /** * Type is `mut fn (P) -> T` */ pub int MutClosure(P : Tuple = ()) -> T : ConsClosure(P) -> T { mut fn call(...p: P) -> T } /** * Type is `fn (P) -> T` */ pub int ReadClosure(P : Tuple = ()) -> T : MutClosure(P) -> T { fn call(...p: P) -> T } /* Closure partial implementations */ pub template class ClosureBase!($T: type, $P: type = (), $D: type = Any) where Self : ConsClosure($P)<$D> -> $T { mut fld delegate: Option<$D> impl ref fn getDelegate() -> Option<&$D> = delegate is Some(d) ? Some(&d) : None impl mut fn setDelegate(d: $D) { delegate = Some(d) } } pub abstract class AbstractConsClosure(P : Tuple = ()) -> T : ConsClosure(P) -> T { include ClosureBase!(T, P, D) } pub abstract class AbstractMutRefClosure(P : Tuple = ()) -> T : MutRefClosure(P) -> T { include ClosureBase!(T, P, D) } pub abstract class AbstractMutClosure(P : Tuple = ()) -> T : MutClosure(P) -> T { include ClosureBase!(T, P, D) } pub abstract class AbstractReadRefClosure(P : Tuple = ()) -> T : ReadRefClosure(P) -> T { include ClosureBase!(T, P, D) } pub abstract class AbstractReadClosure(P : Tuple = ()) -> T : ReadClosure(P) -> T { include ClosureBase!(T, P, D) } /* Templates for ApplyFirst and ApplyLast */ pub template class-fn ApplyFirst!($T: type, $P: type, ...$callMods: fn-mod) where Self : Closure($P)<$D> -> $T && $P : Tuple { $P is Tuple() => {}, $P is Tuple($Param) && Self has (impl $callMods fn call($Param) -> $T) => { impl cons fn applyFirst(first: First<$P>) -> Self()<$D> -> $T { return |self| { call(first) } } } $P is Tuple($First, ...$Suffix) && Self has (impl $callMods fn call($First, ...$Suffix) -> $T) => { impl cons fn applyFirst(first: First<$P>) -> Self($Suffix)<$D> -> $T { return |self| { ...suffix: Suffix<$P> -> call(first, ...suffix) } } } _ => Unreachable! } pub template class-fn ApplyLast!($T: type, $P: type, ...$callMods: fn-mod) where Self : Closure($P)<$D> -> $T && $P : Tuple { $P is Tuple() => {}, $P is Tuple($Param) && Self has (impl $callMods fn call($Param) -> $T) => { impl cons fn applyLast(last: Last<$P>) -> Self()<$D> -> $T { return |self| { call(last) } } } $P is Tuple(...$Prefix, $Last) && Self has (impl $callMods fn call(...$Prefix, $Last) -> T) => { impl cons fn applyLast(last: Last<$P>) -> Self($Prefix)<$D> -> $T) => { return |self| { ...prefix: Prefix<$P> -> call(...prefix, last) } } } _ => Unreachable! } /* Example */ @Synthetic class CompiledReadClosure(captured: Int) : ReadClosureBase(Int, Int) -> Int { include ApplyFirst!(Int, (Int, Int)) include ApplyLast!(Int, (Int, Int)) impl fn call(x: Int, y: Int) -> Int = captured + x + y } // Example main fn main() { let captured = 7 let cl: fn (Int, Int) -> Int = { x, y -> captured + x + y } // the capture of `captured` is automatically inferred // because Int is Copy, everything is okay // cl is ReadClosure(Int, Int) -> Int let applied0: fn (Int) -> Int = cl >> 16 let applied1: fn () -> Int = applied0 >> 42 let result = applied1() assertEq(result, 65) }