
# tecs.Future


A value that settles once, and the combinators over it.

Assets, child processes, and HTTP requests return
`Future<T>`. Compose their
results without blocking a frame:

```teal
local process, reason = tecs.io.Process.new({args = {"git", "status", "--porcelain"}})
if process == nil then
    error(reason)
end

process.finished
    :map(function(exit: tecs.io.Process.Exit): boolean
        return exit:succeeded()
    end)
    :recover(function(): boolean
        return false
    end)
    :onSettle(function(succeeded: tecs.Future<boolean>)
        print(succeeded.value)
        process:close()
    end)
```

## Settlement

`status` starts as `"pending"` and moves once to `"ready"`, `"failed"`, or
`"canceled"`. A process exit code or HTTP error status still produces a ready
result because the operation returned an answer. Failure means the operation
produced none.

Reading `value` is the blocking dereference. It advances a pending future for
its source's default wait budget, returns a ready result, and raises on failure,
cancellation, or a budget that expires first. Successful non-nil results are
stored directly, so reads after settlement are ordinary field reads. Use
`status` and `error` when inspecting an outcome without raising.

`map` transforms a ready value. `flatMap` starts dependent work and adopts its
future. `recover` turns failure into a value. Canceled futures skip all three
transforms except cancellation propagation.

Listeners run in registration order. With no delivery in progress, registering
a listener after settlement runs it before `onSettle` returns. During delivery,
a new listener joins the current drain instead of growing the Lua stack. It may
run after that nested `onSettle` returns, but before the outermost drain returns.

## Pumping and waiting

A future advances when its subsystem pumps the source.
[`Application`](/modules/Application/) frames do
that automatically. `wait` pumps in blocking slices for startup, tools, and
tests:

```teal
local process, reason = tecs.io.Process.new({args = {"git", "status", "--porcelain"}})
if process == nil then
    error(reason)
end
local finished <const> = process.finished:wait(2000)

if finished.status == "ready" then
    print(finished.value.exitCode)
end

process:close()
```

Do not call `wait` or read a pending `value` from a frame. A timeout leaves the
future pending. A listener must not wait on another pending future driven by the
same non-reentrant source.

Waiting until a subsystem has nothing outstanding is that subsystem's own drain
rather than a join over futures a caller holds. `Future.all` reads its inputs
once and holds each one, so it answers for a set fixed at the call and not for a
set that work started during the wait joins.

A source must settle its futures on the same thread that pumps it.

Canceling releases one consumer's interest. Shared operations stop only after
their last consumer releases the root future.

## Snapshots

A snapshot never stores a future because it contains runtime listeners and
source state. A saved sequence cursor retains only its provider, entity, and
key. Reissue and track the work under the same key after load when the wait
must continue.

So a future is not a component field. Keep it in a table beside the world,
keyed by the entity waiting on it, and give that entity a transient marker
instead. A snapshot writer that reaches a future walks its listener graph
rather than refusing the component, so the save fails without naming either.

## Module contents

### Types

| Type | Kind | Description |
| --- | --- | --- |
| [`Listener`](/modules/Future/#tecs.Future.Listener) | <span class="tealdoc-kind-badge tealdoc-kind-type">type</span> | Receives a settled future. |
| [`Source`](/modules/Future/#tecs.Future.Source) | <span class="tealdoc-kind-badge tealdoc-kind-record">record</span> | Defines how a future receives settlements and advances a blocking wait. |

### Functions

| Function | Kind | Description |
| --- | --- | --- |
| [`all`](/modules/Future/#tecs.Future.all) | <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span> | Joins every input value into one future in input order. |
| [`failed`](/modules/Future/#tecs.Future.failed) | <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span> | Creates a future that already carries a failure. |
| [`pending`](/modules/Future/#tecs.Future.pending) | <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span> | Creates a future nothing has settled yet. |
| [`settled`](/modules/Future/#tecs.Future.settled) | <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span> | Creates a future that already carries a value. |
| [`track`](/modules/Future/#tecs.Future.track) | <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span> | Makes a future something a sequence can wait for. |
| [`abandon`](/modules/Future/#tecs.Future.abandon) | <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span> | Settles this future as canceled, if nothing has settled it yet. |
| [`cancel`](/modules/Future/#tecs.Future.cancel) | <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span> | Gives up this consumer's interest in the work. |
| [`complete`](/modules/Future/#tecs.Future.complete) | <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span> | Settles this future with a value, if nothing has settled it yet. |
| [`fail`](/modules/Future/#tecs.Future.fail) | <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span> | Settles this future as failed, if nothing has settled it yet. |
| [`flatMap`](/modules/Future/#tecs.Future.flatMap) | <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span> | Returns a future that adopts the future started by transform. |
| [`map`](/modules/Future/#tecs.Future.map) | <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span> | Returns a future carrying transform applied to this future's value. |
| [`onSettle`](/modules/Future/#tecs.Future.onSettle) | <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span> | Registers a dependent, and returns this future. |
| [`recover`](/modules/Future/#tecs.Future.recover) | <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span> | Returns a future that turns this future's failure into a value. |
| [`wait`](/modules/Future/#tecs.Future.wait) | <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span> | Blocks until this future settles, advancing its source. |

### Values

| Value | Type | Description |
| --- | --- | --- |
| [`error`](/modules/Future/#tecs.Future.error) | `string` | Read-only. Explains a "failed" or "canceled" result. |
| [`status`](/modules/Future/#tecs.Future.status) | `string` | Read-only. Reports "pending", "ready", "failed" or "canceled". |
| [`value`](/modules/Future/#tecs.Future.value) | `T` | Read-only. Returns the result, waiting for it when necessary. |

## Types

<a id="tecs.Future.Listener"></a>
### tecs.Future.Listener <span class="tealdoc-kind-badge tealdoc-kind-type">type</span>

Receives a settled future.


```teal
type tecs.Future.Listener = function(Future<any>)
```

<a id="tecs.Future.Source"></a>
### tecs.Future.Source <span class="tealdoc-kind-badge tealdoc-kind-record">record</span>

Defines how a future receives settlements and advances a blocking wait.

Every source in this tree is something that can be told to block for up
to N milliseconds and hand over whatever arrived, which is the whole of
what a future needs from the work behind it. An asset decode and a child
process are a worker channel; an HTTP transfer is a Reqwest task whose
bounded event queue has the same shape.


```teal
record tecs.Future.Source
    sliceMs: number
    defaultWaitMs: number

    advance: function(self, ms: number): integer
    cancel: function(self, future: Future<any>)
    poll: function(self): integer
end
```

<a id="tecs.Future.Source.sliceMs"></a>
#### tecs.Future.Source.sliceMs <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets the maximum milliseconds one `wait` slice
blocks. The source may omit it to use 16.


```teal
tecs.Future.Source.sliceMs: number
```

<a id="tecs.Future.Source.defaultWaitMs"></a>
#### tecs.Future.Source.defaultWaitMs <span class="tealdoc-kind-badge tealdoc-kind-field">field</span>

Caller-writable. Sets the milliseconds `wait` spends when its caller
supplies no timeout. The source may omit it to use 5000.


```teal
tecs.Future.Source.defaultWaitMs: number
```

<a id="tecs.Future.Source.advance"></a>
#### tecs.Future.Source:advance <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span>

Caller-writable. Blocks up to `ms` for one result and settles its
future.

What `Future:wait` spends a slice in, so it must not block for
longer than the requested duration.


```teal
function tecs.Future.Source.advance(self, ms: number): integer
```

##### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `self` | [`Source`](/modules/Future/#tecs.Future.Source) | The source to advance. |
| `ms` | `number` | The maximum number of milliseconds to block. |

##### Returns

| Type | Description |
| --- | --- |
| `integer` | Returns the number of futures settled while advancing. |

<a id="tecs.Future.Source.cancel"></a>
#### tecs.Future.Source:cancel <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span>

Caller-writable. Stops the work behind a root future after its last
watcher leaves.

Optional. A source with no hook leaves the work running and stops
caring, which is what a future over something uncancelable can
honestly do.


```teal
function tecs.Future.Source.cancel(self, future: Future<any>)
```

##### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `self` | [`Source`](/modules/Future/#tecs.Future.Source) | The source that owns the work. |
| `future` | [`Future`](/modules/Future/)`<any>` | The root future whose last watcher left. |

##### Returns

None.

<a id="tecs.Future.Source.poll"></a>
#### tecs.Future.Source:poll <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span>

Caller-writable. Takes every ready result and settles its future.

Called once per frame per source, and costs a non-blocking receive
that answers nil on any frame where nothing finished.


```teal
function tecs.Future.Source.poll(self): integer
```

##### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `self` | [`Source`](/modules/Future/#tecs.Future.Source) | The source to poll. |

##### Returns

| Type | Description |
| --- | --- |
| `integer` | Returns the number of futures settled by this poll. |

## Functions

<a id="tecs.Future.all"></a>
### tecs.Future.all <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span>

Joins every input value into one future in input order.

Settles when the last input does, whatever order they settle in. A
failed or canceled input fails the join with that input's error; the
rest are left running, because an input shared with something outside
the join is not this join's to stop. A caller that wants every outcome
rather than the first failure puts a `recover` on each input, which is
the shape a value that may be missing already uses.

Fan-in does not nest: each listener decrements a counter and only the
last input settles the join, so a join over five hundred loads is two
deep rather than five hundred.

Joining takes a hold on every input, so an input the join is still
waiting for is not abandoned while the join lives, and canceling the join
releases every one of those holds. A join dropped without being canceled
keeps them, which is why a barrier over work another subsystem started is
a drain on that subsystem rather than a join here: the hold would outlive
the wait and leave that subsystem's own `cancel` unable to reach zero.

An input that settles "ready" carrying nil fails the join rather than
filling its slot, because nil is a legal value and an array cannot hold
one: the slot would read as absent and every index past it would be
past a hole. A caller with a value that may be missing recovers to
something rather than to nil.



```teal
function tecs.Future.all<U>(inputs: {Future<U>}): Future<{U}>
```

#### Type Parameters

| Name | Constraint | Description |
| --- | --- | --- |
| `U` |  |  |

#### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `inputs` | `{`[`Future`](/modules/Future/)`<U>}` | Read once; adding to the list afterwards changes nothing. Empty gives an already-ready future over an empty array. Nil raises. |

#### Returns

| Type | Description |
| --- | --- |
| [`Future`](/modules/Future/)`<{U}>` | A future whose value is a fresh array in `inputs` order. The join settles "ready" only after every slot contains a value, so no hole can appear. |

<a id="tecs.Future.failed"></a>
### tecs.Future.failed <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span>

Creates a future that already carries a failure.



```teal
function tecs.Future.failed<U>(err: string): Future<U>
```

#### Type Parameters

| Name | Constraint | Description |
| --- | --- | --- |
| `U` |  |  |

#### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `err` | `string` | Nil becomes "failed". |

#### Returns

| Type | Description |
| --- | --- |
| [`Future`](/modules/Future/)`<U>` | A future at "failed" with no source, so `wait` on it returns at once and `cancel` does nothing. `map` on it propagates without running the transform, while `recover` on it is the one thing that still runs. |

<a id="tecs.Future.pending"></a>
### tecs.Future.pending <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span>

Creates a future nothing has settled yet.

The producer half, for a source settling its own work and for a test
that decides when something finishes. `source` is what a `wait` on it
advances. When omitted, only code that holds the future can settle it,
and a `wait` on it returns at once.



```teal
function tecs.Future.pending<U>(source: Source): Future<U>
```

#### Type Parameters

| Name | Constraint | Description |
| --- | --- | --- |
| `U` |  |  |

#### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `source` | [`Source`](/modules/Future/#tecs.Future.Source) | The optional source that advances blocking waits. |

#### Returns

| Type | Description |
| --- | --- |
| [`Future`](/modules/Future/)`<U>` | A future at "pending" with one watcher, so a single `cancel` on it settles it "canceled" and calls the source's hook. |

<a id="tecs.Future.settled"></a>
### tecs.Future.settled <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span>

Creates a future that already carries a value.



```teal
function tecs.Future.settled<U>(value: U): Future<U>
```

#### Type Parameters

| Name | Constraint | Description |
| --- | --- | --- |
| `U` |  |  |

#### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `value` | `U` | The value to store without copying. |

#### Returns

| Type | Description |
| --- | --- |
| [`Future`](/modules/Future/)`<U>` | A future at "ready" with no source, so `wait` on it returns at once and `cancel` does nothing. A listener added to it follows the synchronous and reentrant delivery contract documented on `onSettle`. |

<a id="tecs.Future.track"></a>
### tecs.Future.track <span class="tealdoc-kind-badge tealdoc-kind-static">Static</span>

Makes a future something a sequence can wait for.

The sequencer has a registry for waiting on work outside it, and this
module is its one engine registrant, under the name `"tecs.future"`. So
a program parks on a decode, a subprocess or a request with

sequence.await("tecs.future", sequence.bind("loader"), "level1")

against a future tracked here under that same entity and key.

Three properties of the machinery underneath, none of them this
function's to change. An await needs a live bound entity, because the VM
releases a cursor whose entity is dead rather than stranding it, so the
key is a pair and the entity is the game's own loader. The key is a
program constant, so a program awaits a future by the name used to track it
under rather than by identity, which is what lets the wait survive a
snapshot the future cannot. And only the fixed clock delivers awaits, so
a program on the frame or presentation clock parked on a future is
released by a fixed step; that is already true of every awaitable.

Tecs drops the entry when the future settles, so a program that reaches
its await after the work finished carries on rather than hanging, and
nothing accumulates. Tracking a second future under one entity and key
replaces the first.

There is no `setPaused`: the asset worker cannot pause a decode in flight, and the
contract says a provider that cannot pause its work does not offer it.



```teal
function tecs.Future.track<U>(
    world: World, entity: integer, key: string, future: Future<U>
)
```

#### Type Parameters

| Name | Constraint | Description |
| --- | --- | --- |
| `U` |  |  |

#### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `world` | [`World`](/modules/ecs/#tecs.World) | The world that owns the bound entity. |
| `entity` | `integer` | What the await binds to, and it must still be alive when the program parks; the VM releases a cursor whose entity is dead. |
| `key` | `string` | A program constant, not something derived per call, since the await names it. Nil or empty raises. |
| `future` | [`Future`](/modules/Future/)`<U>` | Nil raises. One that has already settled is deliberately not written down, so a later await on that key carries straight on rather than hanging. |

#### Returns

None.

<a id="tecs.Future.abandon"></a>
### tecs.Future:abandon <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span>

Settles this future as canceled, if nothing has settled it yet.

The producer half of the third terminal state, and the counterpart of
`cancel` rather than a spelling of it: `cancel` is a consumer saying it
no longer wants the work and counts the others who might, while this
states an outcome that has already happened. A child killed on request
or at its deadline reaches its future through here, as does a transfer
taken off the multi.



```teal
function tecs.Future.abandon(self, err: string)
```

#### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `self` | `Future<T>` | The future to settle as canceled. |
| `err` | `string` | Nil becomes "canceled". No watcher counting happens here: this settles the future outright, whoever else was waiting on it. |

#### Returns

None.

<a id="tecs.Future.cancel"></a>
### tecs.Future:cancel <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span>

Gives up this consumer's interest in the work.

Reference counted, because a shared root is real: two loads of one path
that overlap get the same future, and one of them canceling must not
break the other. So this decrements, and only the last one settles the
future "canceled" and asks the source to stop the work. Canceling a
derived future drops its listener and decrements its upstream, which may
in turn reach zero.

Canceling a settled future is a no-op.


```teal
function tecs.Future.cancel(self)
```

#### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `self` | `Future<T>` | The future whose consumer interest to release. |

#### Returns

None.

<a id="tecs.Future.complete"></a>
### tecs.Future:complete <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span>

Settles this future with a value, if nothing has settled it yet.

The producer half. Whoever created a future through `Future.pending`
owns this and its sibling `fail`; a future handed out by a subsystem is
settled by that subsystem's source, and calling this on one is a caller
settling work it does not own. Settling twice is a no-op, so the first
answer wins.



```teal
function tecs.Future.complete(self, value: T)
```

#### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `self` | `Future<T>` | The future to settle. |
| `value` | `T` | Stored as it is, not copied, and read back off `value`. Nil is a legal value and still settles "ready", which is how a future over nothing settles. |

#### Returns

None.

<a id="tecs.Future.fail"></a>
### tecs.Future:fail <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span>

Settles this future as failed, if nothing has settled it yet.



```teal
function tecs.Future.fail(self, err: string)
```

#### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `self` | `Future<T>` | The future to fail. |
| `err` | `string` | A sentence for a log, not something to match on. Nil becomes "failed", so `error` is set on every failed future. |

#### Returns

None.

<a id="tecs.Future.flatMap"></a>
### tecs.Future:flatMap <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span>

Returns a future that adopts the future started by `transform`.

The one combinator that expresses a dependent second request. Two things
follow from `transform` starting work rather than transforming work
already done: the derived future's source becomes the inner future's, so
a chain can begin on a worker and end somewhere else; and canceling
before the outer settles prevents any call to `transform`, since
there is nothing yet to cancel afterwards.



```teal
function tecs.Future.flatMap<U>(
    self, transform: function(T): Future<U>
): Future<U>
```

#### Type Parameters

| Name | Constraint | Description |
| --- | --- | --- |
| `U` |  |  |

#### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `self` | [`Future`](/modules/Future/)`<T>` | The future whose ready value starts the dependent work. |
| `transform` | `function(T): `[`Future`](/modules/Future/)`<U>` | Called at most once, on "ready" only. Returning nil rather than a future fails this link; nil for `transform` itself raises here and now. |

#### Returns

| Type | Description |
| --- | --- |
| [`Future`](/modules/Future/)`<U>` | A new future settling to whatever the inner one settles to, status and all, so canceling an inner leaves this future canceled and not failed. |

<a id="tecs.Future.map"></a>
### tecs.Future:map <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span>

Returns a future carrying `transform` applied to this future's value.

`transform` runs only on "ready". A "failed" or "canceled" upstream
propagates without calling it, and a raise inside it becomes this link's
failure.



```teal
function tecs.Future.map<U>(
    self, transform: function(T): U
): Future<U>
```

#### Type Parameters

| Name | Constraint | Description |
| --- | --- | --- |
| `U` |  |  |

#### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `self` | [`Future`](/modules/Future/)`<T>` | The future whose ready value to transform. |
| `transform` | `function(T): U` | Called at most once, with the upstream value. Nil raises here and now rather than at settlement. |

#### Returns

| Type | Description |
| --- | --- |
| [`Future`](/modules/Future/)`<U>` | A new future watching this one. Canceling it gives up this link's interest in the upstream and does not settle the upstream unless nothing else wants it. |

<a id="tecs.Future.onSettle"></a>
### tecs.Future:onSettle <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span>

Registers a dependent, and returns this future.

The primitive the others are built on. With no delivery in progress, a
listener on a future that has already settled runs before this call
returns. During delivery, a new listener joins the current drain instead
of growing the Lua stack. It may run after this nested call returns, but
before the outermost drain returns. A listener that raises writes to the
log and does not stop the others.



```teal
function tecs.Future.onSettle(
    self, listener: function(Future<T>)
): Future<T>
```

#### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `self` | `Future<T>` | The future on which to register the listener. |
| `listener` | `function(`[`Future`](/modules/Future/)`<T>)` | Called once, with this future, whichever of the three terminal states it reached; read `status` rather than assuming a value. Nil raises. |

#### Returns

| Type | Description |
| --- | --- |
| [`Future`](/modules/Future/)`<T>` | This same future, not a derived one, so chaining `onSettle` registers several listeners on one thing rather than building a chain. |

<a id="tecs.Future.recover"></a>
### tecs.Future:recover <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span>

Returns a future that turns this future's failure into a value.

`recovery` runs only on "failed". A "canceled" upstream is not
recovered, which is the whole reason the two are distinct states.



```teal
function tecs.Future.recover(
    self, recovery: function(string): T
): Future<T>
```

#### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `self` | `Future<T>` | The future whose failure to recover. |
| `recovery` | `function(string): T` | Given the upstream's error string. Raising inside it fails this link with that raise instead, so a recovery cannot fail silently. Nil raises here and now. |

#### Returns

| Type | Description |
| --- | --- |
| [`Future`](/modules/Future/)`<T>` | A new future watching this one, carrying the same type: a recovery produces a value where the upstream produced an error, so a ready upstream passes through untouched. |

<a id="tecs.Future.wait"></a>
### tecs.Future:wait <span class="tealdoc-kind-badge tealdoc-kind-instance">Instance</span>

Blocks until this future settles, advancing its source.

For startup, tools and tests; a frame polls `status` instead. Never a
busy loop: the time is spent inside the source's blocking receive. The
budget is wall clock rather than a count of slices, so a source that
answers faster than its slice size does not shorten the wait.

A future with no source cannot advance and returns at once.


```teal
function tecs.Future.wait(self, timeoutMs: number): Future<T>
```

#### Arguments

| Name | Type | Description |
| --- | --- | --- |
| `self` | `Future<T>` | The future to wait for. |
| `timeoutMs` | `number` | How long to wait. Defaults to the source's `defaultWaitMs`, or 5000. Running out leaves it "pending". |

#### Returns

| Type | Description |
| --- | --- |
| [`Future`](/modules/Future/)`<T>` | This future. |

## Values

<a id="tecs.Future.error"></a>
### tecs.Future.error <span class="tealdoc-kind-badge tealdoc-kind-variable">variable</span>

Read-only. Explains a `"failed"` or `"canceled"` result. The source
writes it, and game code should not assign it.


```teal
tecs.Future.error: string
```

<a id="tecs.Future.status"></a>
### tecs.Future.status <span class="tealdoc-kind-badge tealdoc-kind-variable">variable</span>

Read-only. Reports `"pending"`, `"ready"`, `"failed"` or `"canceled"`.
The source changes it once, and game code should not assign it.


```teal
tecs.Future.status: string
```

<a id="tecs.Future.value"></a>
### tecs.Future.value <span class="tealdoc-kind-badge tealdoc-kind-variable">variable</span>

Read-only. Returns the result, waiting for it when necessary.

A pending read advances the source for its default wait budget. A
`"failed"` or `"canceled"` result raises with `error`, as does a future
that remains pending after that budget. A pending future with no source
raises immediately because nothing can advance it. Waiting here has the
same frame and source-reentrancy constraints as `wait`.

The source writes this field, and game code should not assign it.


```teal
tecs.Future.value: T
```