Addresses #4080. (Not ready to close it yet.)
# Important
Requires a fix for #4147 before it can work in ZMA.
# Overview
```kcl
// numbers.kcl
export fn inc = (x) => {
return x + 1
}
```
```kcl
import inc from "numbers.kcl"
answer = inc(41)
```
This also implements multiple imports with optional renaming.
```kcl
import inc, dec from "numbers.kcl"
import identity as id, length as len from "utils.kcl"
```
Note: Imported files _must_ be in the same directory.
Things for a follow-up PR:
- #4147. Currently, we cannot read files in WebAssembly, i.e. ZMA.
- Docs
- Should be an error to `import` anywhere besides the top level. Needs parser restructuring to track the context of a "function body".
- Should be an error to have `export` anywhere besides the top level. It has no effect, but we should tell people it's not valid instead of silently ignoring it.
- Error message for cycle detection is funky because the Rust side doesn't actually know the name of the first file. Message will say "b -> a -> b" instead of "a -> b -> a" when "a" is the top-level file.
- Cache imported files so that they don't need to be re-parsed and re-executed.
Rename kcl's Value to Expr
As Jon pointed out, kcl's `Value` enum is actually an expression.
"2+2" isn't a value, it's an expression, which can compute a value.
So I renamed it `Expr`.
Each AST node contains an Option<Digest> which can be optionally set by running compute_digest() over the AST. This will mutate the AST and set the Digest. Fundamentally, the digest is computed from the digest of AST children nodes (using compute_digest) or the explicit raw underlying value.
The underlying hash is changeable by modifying the macro and Digest type alias, and should enable us to determine when an AST -- or fragment of AST -- is the same.
This won't hash the start/end of the AST fragment, so it's, to some extent, position independent. It will hash newlines, comments, etc, which may change in the future depending on how we wind up using this.
Macro for parsing KCL at Rust compile-time
This adds a new `parse_kcl!` macro which takes a string as input. It parses the string into KCL source code _at compile-time_. Invalid KCL will make your Rust project fail to compile.
Fixes https://github.com/KittyCAD/modeling-app/issues/1018