/*---------------------------------------------------------------------------
  Copyright 2023-2024, Microsoft Research, Daan Leijen.

  This is free software; you can redistribute it and/or modify it under the
  terms of the Apache License, Version 2.0. A copy of the License can be
  found in the LICENSE file at the root of this distribution.
---------------------------------------------------------------------------*/

// Delayed computations.
module std/core/delayedstd/core/delayed

import std/core/typesstd/core/types
import std/core/hndstd/core/hnd
import std/core/unsafestd/core/unsafe

// ----------------------------------------------------------------------------
// Delayed values
// ----------------------------------------------------------------------------

// Delayed (or _lazy_) values are computed (with effect `:e`) only the first time
// `force` is called and cached afterwards.
abstract value type delayedstd/core/delayed/delayed: (E, V) -> V<ee: E,aa: V>
  con XDelaystd/core/delayed/XDelay: forall<e,a> (dref : ref<global,either<() -> e a,a>>) -> delayed<e,a>( drefstd/core/delayed/delayed/dref: forall<e,a> (delayed : delayed<e,a>) -> ref<global,either<() -> e a,a>> : refstd/core/types/ref: (H, V) -> V<globalstd/core/types/global: H,eitherstd/core/types/either: (V, V) -> V<() -> ee: E aa: V,aa: V>> )

// Create a new `:delayed` value.
pub fun delaystd/core/delayed/delay: forall<a,e> (action : () -> e a) -> delayed<e,a>( actionaction: () -> $115 $114 : () -> ee: E aa: V )result: -> total delayed<162,161> : delayedstd/core/delayed/delayed: (E, V) -> V<ee: E,aa: V>
  unsafe-totalstd/core/unsafe/unsafe-total: (action : () -> <alloc<global>|_133> delayed<$115,$114>) -> delayed<$115,$114>
    val rr: ref<global,either<() -> $115 $114,$114>> : refstd/core/types/ref: (H, V) -> V<globalstd/core/types/global: H,eitherstd/core/types/either: (V, V) -> V<__w-l28-c31: V,__w-l28-c33: V>> = refstd/core/types/ref: (value : either<() -> $115 $114,$114>) -> <alloc<global>|_133> ref<global,either<() -> $115 $114,$114>>(Leftstd/core/types/Left: forall<a,b> (left : a) -> either<a,b>(actionaction: () -> $115 $114))
    XDelaystd/core/delayed/XDelay: forall<e,a> (dref : ref<global,either<() -> e a,a>>) -> delayed<e,a>(rr: ref<global,either<() -> $115 $114,$114>>)

// Force a delayed value; the value is computed only on the first
// call to `force` and cached afterwards.
pub fun forcestd/core/delayed/force: forall<a,e> (delayed : delayed<e,a>) -> e a( delayeddelayed: delayed<$171,$170> : delayedstd/core/delayed/delayed: (E, V) -> V<ee: E,aa: V> )result: -> 271 270 : ee: E aa: V
  unsafe-totalstd/core/unsafe/unsafe-total: (action : () -> <alloc<global>,div,read<global>,write<global>|$171> $170) -> $171 $170
    val rr: ref<global,either<() -> $171 $170,$170>> = delayeddelayed: delayed<$171,$170>.drefstd/core/delayed/delayed/dref: (delayed : delayed<$171,$170>) -> <alloc<global>,div,read<global>,write<global>|$171> ref<global,either<() -> $171 $170,$170>>
    match !std/core/types/ref/(!): (ref : ref<global,either<() -> $171 $170,$170>>) -> <read<global>,div,alloc<_227>,write<global>|$171> either<() -> $171 $170,$170>rr: ref<global,either<() -> $171 $170,$170>>
      Rightstd/core/types/Right: forall<a,b> (right : b) -> either<a,b>(xx: $170) -> xx: $170
      Leftstd/core/types/Left: forall<a,b> (left : a) -> either<a,b>(actionaction: () -> $171 $170) ->
        val xx: $170 = mask-ststd/core/types/mask-st: (() -> <div|$171> $170) -> <alloc<global>,div,read<global>,write<global>|$171> (() -> <st<global>,div|$171> $170){ mask<divstd/core/types/div: X>(actionaction: () -> $171 $170) }()
        rr: ref<global,either<() -> $171 $170,$170>> :=std/core/types/set: (ref : ref<global,either<() -> $171 $170,$170>>, assigned : either<() -> $171 $170,$170>) -> <write<global>,alloc<global>,div,read<global>|$171> () Rightstd/core/types/Right: forall<a,b> (right : b) -> either<a,b>(xx: $170)
        xx: $170

// Given a total function to calculate a value `:a`, return
// a total function that only calculates the value once and then
// returns the cached result.
pub fun oncestd/core/delayed/once: forall<a> (calc : () -> a) -> (() -> a)( calccalc: () -> $278 : () -> astd/core/types/total: E )result: -> total () -> 371 : ((std/core/types/total: E) -> astd/core/types/total: E)
  unsafe-totalstd/core/unsafe/unsafe-total: (action : () -> <alloc<_296>|_297> (() -> $278)) -> (() -> $278)
    val rr: ref<_296,maybe<$278>> = refstd/core/types/ref: (value : maybe<$278>) -> <alloc<_296>|_297> ref<_296,maybe<$278>>(Nothingstd/core/types/Nothing: forall<a> maybe<a>)
    returnreturn: () -> $278 fnfn: () -> $278()
      unsafe-totalstd/core/unsafe/unsafe-total: (action : () -> <read<_296>,write<_296>,div|_365> $278) -> $278
        match !std/core/types/ref/(!): (ref : ref<_296,maybe<$278>>) -> <read<_296>,write<_296>,div|_365> maybe<$278>rr: ref<_296,maybe<$278>>
          Juststd/core/types/Just: forall<a> (value : a) -> maybe<a>(xx: $278) -> xx: $278
          Nothingstd/core/types/Nothing: forall<a> maybe<a> ->
            val xx: $278 = calccalc: () -> <write<_296>,read<_296>,div|_365> $278()
            rr: ref<_296,maybe<$278>> :=std/core/types/set: (ref : ref<_296,maybe<$278>>, assigned : maybe<$278>) -> <write<_296>,read<_296>,div|_365> () Juststd/core/types/Just: forall<a> (value : a) -> maybe<a>(xx: $278)
            xx: $278