Compare commits

...

2 Commits

Author SHA1 Message Date
Jesse Brault
68de104595 Change Closure hierarchy. 2025-05-07 11:46:40 -05:00
Jesse Brault
9cec999cb9 Sketching out how templates might work. 2025-05-02 14:59:33 -05:00
2 changed files with 151 additions and 1 deletions

View File

@ -1,5 +1,5 @@
pub hkt Functor[Self<T>] {
fn <U> map(f: fn &T -> U) -> Self<U> // &self implied
fn <U> map(f: fn (t: &T) -> U) -> Self<U> // &self implied
}
pub hkt Applicative[Self<T>] : Functor[Self<T>] {

View File

@ -0,0 +1,150 @@
/* 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)
}