Promise

A promise, in E, is a kind of unresolved eventual ref. It is a ref which will resolve to some other ref later; therefore all sends it receives are stored, then forwarded at the time of the resolution. Every promise has a corresponding resolver (though it might be implicit), which constitutes the permission to cause it to resolve to a given other reference (which may itself be a promise).

A local promise is a promise whose resolver is in this vat; local promises are reliably implemented by the local ELib. A remote promise is a promise whose resolver is in a different vat; remote promises are implemented by proxies.

Local promises
The general-purpose operation to create a local promise is Ref#promise/0.

? def [promise, resolver] := Ref.promise ? Ref.state(promise) ? Ref.isResolved(promise)
 * 1) value: [, ]
 * 1) value: "EVENTUAL"
 * 1) value: false

Once a promise (local or remote) is resolved, it is indistinguishable from the reference which it is resolved to, whether that reference is Selfless,

? resolver.resolve(99) ? promise ? promise + 1 ? promise == 99
 * 1) value: 99
 * 1) value: 100
 * 1) value: true

or Selfish.

? def [promise, resolver] := Ref.promise > resolver.resolve(def x {}) > promise == x
 * 1) value: true

write tests and doc from the LocalResolver's perspective (isDone, resolveRace/smash, behavior after it is resolved) -- EoCL has some in ref.updoc

Calls and sends
? def [promise, resolver] := Ref.promise; null

As with any unresolved ref, a promise cannot be called.

? promise(1)
 * 1) problem: not synchronously callable: .run(1)

However, any sends to the promise are accepted and buffered in the resolver, in time order.

? promise <- (2) ? E.sendOnly(promise, "run", [3])
 * 1) value: 

If the resolver becomes garbage, then so does the buffer; future messages to the promise are silently discarded and do not accumulate. Note that this implies that the promise does not strongly refer to the resolver. ( write tests for this using finalizers.)

At the instant a local promise is resolved to another ref (which is known as its resolution), the buffered messages are sent, in the order they arrived, to the resolution.

? var items := [] > def resolution(x) { items with= x } > resolution <- (4)            # demonstrating exact ordering > def resolveReturn := resolver.resolve(resolution) > resolution <- (5) > resolveReturn ? items
 * 1) value: [4, 2, 3, 5]