From 9cec999cb9318700e965ffb99d4b545403ff9dc7 Mon Sep 17 00:00:00 2001 From: Jesse Brault Date: Fri, 2 May 2025 14:59:33 -0500 Subject: [PATCH] Sketching out how templates might work. --- sketching/april_2025/template.dm | 150 +++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 sketching/april_2025/template.dm diff --git a/sketching/april_2025/template.dm b/sketching/april_2025/template.dm new file mode 100644 index 0000000..a2470b9 --- /dev/null +++ b/sketching/april_2025/template.dm @@ -0,0 +1,150 @@ +/* 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 `mut fn (P) -> T` + */ +pub int MutClosure(P : Tuple = ()) -> T : MutRefClosure(P) -> T { + mut 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 `fn (P) -> T` + */ +pub int ReadClosure(P : Tuple = ()) -> T : ReadRefClosure(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) +}