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