topo 0.8.1

Reified activation records and scoped thread-locals for UI runtimes.

Topological functions execute within a context unique to the path in the runtime call graph of other topological functions preceding the current activation record.

Defining a topological function results in a macro definition for binding the topological function to each callsite where it is invoked.

Define a topological function with the topo::bound attribute:

#[topo::bound]
fn basic_topo() -> topo::Id { topo::Id::current() }

#[topo::bound]
fn tier_two() -> topo::Id { basic_topo!() }

// each of these functions will be run in separately identified
// contexts as the source locations for their calls are different
let first = basic_topo!();
let second = basic_topo!();
assert_ne!(first, second);

let third = tier_two!();
let fourth = tier_two!();
assert_ne!(third, fourth);
assert_ne!(first, third);
assert_ne!(first, fourth);
assert_ne!(second, fourth);

Because topological functions must be sensitive to the location at which they're invoked and bound to their parent, we transform the function definition into a macro so we can link the two activation records inside macro expansion. See the docs for the attribute for more detail and further discussion of the tradeoffs.

TODO include diagram of topology

TODO discuss creation of tree from "abstract stack frames" represented by topological invocations

TODO discuss propagating environment values down the topological call tree

TODO show example of a rendering loop