_Trying to address the elephant in the room._ ## Parse-time evaluation Different levels: 0. No parse-time eval 1. Can evaluate simple constants (Done) * Example: `const name = 'spam.nu'; use $name` 2. Able to evaluate simple calls (https://github.com/nushell/nushell/pull/9499) * Example: `const NU_LIB_DIRS = [( '~/.nuun/overlays' | path expand)]` * Only "simple" commands are allowed * _Seems_ to work fine but I can't prove it (see 4) 3. Able to evaluate complex calls that reference the working set * Example: `const x = (if true { 'a' } else { 'b' })` * This panics because the blocks are in working set, not engine state, during parsing * Requires API change: `Command::run()` would need to take `struct EngineSetView { engine_state: &EngineState, delta: &StateDelta }` ---- 4. Able to evaluate calls with parser side effects (parser keywords) * `Command::run()` would need to take a mutable reference to working set 5. 1:1 parity between runtime and parse-time eval I'd draw the line between 3. and 4. The API change in 3. doesn't fundamentally change how Nushell works. ## Type-safe eval ``- eval spam.nu [ foo [x: string]: int -> list<string> bar [--flag] ] spam foo spam bar eval eggs.nu [ baz [x: string]: stream<int> -> anyof<stream<int>, stream<string>> ] * baz ``` Use cases: * plugins (so we don't need to talk to externals during parsing) * maybe test runner