Epic: compiler improvements
This is an early draft of the future compiler improvements I'd like to, eventually. (I'm calling it a "compiler" because it's a long roadmap from the tree-walking interpreter to stack-based VM-like interpreter/compiler to Wasm compiler).
### Value-only stack
- [x] Convert Stack items from `{ name: string, value: Value }` to `Value`
Minor optimization, requires symbol table to be stored in Expression, so that we could generate bindings.
### Stack-compatible captures
- [x] Generate values captured by lambdas during compilation
This would require identifying all non-local values during compilation. It would help both with future performance optimizations, and with lambda serializations for Web Workers.
### Mutable stack
- [x] Convert Stack from `ImmutableList` to the plain array
This requires stack-compatible captures. Right now we make stack snapshots when lambda is created, but this won't perform well with mutable stacks.
### Mutable contexts
- [x] Edit `context` object instead of treating it as immutable
### Lazy framestacks (experimental)
- [ ] Construct framestack on exception
Right now we maintain framestack and modify it on each function call. Instead, we could capture-and-rethrow exceptions and reconstruct the framestack on errors only. (I'm not 100% sure it's a good idea, but worth trying.)
### Type inference
- [ ] https://github.com/quantified-uncertainty/squiggle/issues/1933
- [ ] Infer types during compilation
### Non-graph intermediate representation
- [ ] Replace recursive expressions with a stack-based intermediate representation
See e.g. here: https://cs.lmu.edu/~ray/notes/ir/
### Wasm
- [ ] Compile to WebAssembly
It's possible that we could output Wasm code outselves, but that might be a headache because we'd have to manage memory for strings and records (there is no built-in heap and GC in Wasm, AFAIK), so it'd be easier to generate AssemblyScript code instead (if AssemblyScript compile times would be good enough for the playground; I haven't checked).