
Erasure.pudu
Pudu38 lines1.3 KB
1/** @Utils.Erasure.Module — values carried without naming their type */2module PuduLangMediator.Utils.Erasure34import Std.Sync as Sync56/** @Utils.Erasure.Packed — a value whose type only its slot knows */7export type Packed = fn() -> ()89/** @Utils.Erasure.Slot — the one place a packed value of `T` reads back */10export type Slot[T] = { lock: Sync.Mutex, held: Sync.Cell[Option[T]] }111213export fn slot[T]() -> Slot[T] { Slot{lock: Sync.mutex(), held: Sync.cell(None)} }141516export fn pack[T](target: &Slot[T], value: T) -> Packed {17 let held = target.held18 fn() -> () { let _stored = Sync.set(&held, Some(value)) }19}202122export fn unpack[T](source: &Slot[T], packed: &Packed) -> Option[T] {23 let held = source.held24 let run = *packed25 let read = Sync.withLock(&source.lock, fn() -> Option[T] {26 let _cleared = Sync.set(&held, None)27 run()28 match Sync.swap(&held, None) {29 case Ok(found) => found30 case Err(problem) => panic("an erased value could not be read: " + show(problem))31 }32 })33 match read {34 case Ok(found) => found35 case Err(problem) => panic("an erased value could not be locked: " + show(problem))36 }37}38