151 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			151 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| /* Necessary utility types */
 | |
| 
 | |
| pub type First<T : Tuple(infer U, ...)> = U
 | |
| pub type Last<T : Tuple(..., infer U)> = U
 | |
| pub type Prefix<T : Tuple(...infer U, _)> = Tuple(...U)
 | |
| pub type Suffix<T : Tuple(_, ...infer U)> = Tuple(...U)
 | |
| 
 | |
| /* Closure interfaces */
 | |
| 
 | |
| /**
 | |
|  * Type is `cons fn (P)<D> -> T`
 | |
|  */
 | |
| pub int ConsClosure(P : Tuple = ())<D = Any> -> T {
 | |
|     ref fn getDelegate() -> Option<&D>
 | |
|     mut fn setDelegate(d: D) -> Void
 | |
| 
 | |
|     cons fn call(...p: P) -> T
 | |
| 
 | |
|     cons fn applyFirst(first: First<P>) -> Self(Suffix<P>)<D> -> T
 | |
|     cons fn applyLast(last: Last<P>) -> Self(Prefix<P>)<D> -> T
 | |
| 
 | |
|     def cons op >> alias applyFirst
 | |
|     def cons op << alias applyLast
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Type is `mut ref fn (P)<D> -> T`
 | |
|  */
 | |
| pub int MutRefClosure(P : Tuple = ())<D = Any> -> T : ConsClosure(P)<D> -> T {
 | |
|     mut ref fn call(...p: P) -> T
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Type is `ref fn (P)<D> -> T`
 | |
|  */
 | |
| pub int ReadRefClosure(P : Tuple = ())<D = Any> -> T : MutRefClosure(P)<D> -> T {
 | |
|     ref fn call(...p: P) -> T
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Type is `mut fn (P)<D> -> T`
 | |
|  */
 | |
| pub int MutClosure(P : Tuple = ())<D = Any> -> T : ConsClosure(P)<D> -> T {
 | |
|     mut fn call(...p: P) -> T
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Type is `fn (P)<D> -> T`
 | |
|  */
 | |
| pub int ReadClosure(P : Tuple = ())<D = Any> -> T : MutClosure(P)<D> -> 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 = ())<D> -> T : ConsClosure(P)<D> -> T {
 | |
|     include ClosureBase!(T, P, D)
 | |
| }
 | |
| 
 | |
| pub abstract class AbstractMutRefClosure(P : Tuple = ())<D> -> T : MutRefClosure(P)<D> -> T {
 | |
|     include ClosureBase!(T, P, D)
 | |
| }
 | |
| 
 | |
| pub abstract class AbstractMutClosure(P : Tuple = ())<D> -> T : MutClosure(P)<D> -> T {
 | |
|     include ClosureBase!(T, P, D)
 | |
| }
 | |
| 
 | |
| pub abstract class AbstractReadRefClosure(P : Tuple = ())<D> -> T : ReadRefClosure(P)<D> -> T {
 | |
|     include ClosureBase!(T, P, D)
 | |
| }
 | |
| 
 | |
| pub abstract class AbstractReadClosure(P : Tuple = ())<D> -> T : ReadClosure(P)<D> -> 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)<Any> -> Int
 | |
|     let applied0: fn (Int) -> Int = cl >> 16
 | |
|     let applied1: fn () -> Int = applied0 >> 42
 | |
|     let result = applied1()
 | |
|     assertEq(result, 65)
 | |
| }
 | 
