This breaks out the pattern matching/unification algorithm from cl-interpret/interpret.rs to cl-interpret/pattern.rs
TODO: pattern destructuring in const, static :^)
- Patterns are no longer parsed with the highest precedence
- Function calls with just a path and a tuple of args can now be transformed into a Pattern
- Deny arbitrary paths in patterns (only one non-keyword identifier allowed!)
- Allow patterns in for-loop binders (literally useless atm, but it's a step toward making patterns the only way to bind names.)
Next: Functions, Tuple Struct Patterns... And solving the stupid syntactic ambiguity of structors.
- Everything is different now
- Builtins are now built on top of Rust functions, so they can be recursive!
- TODO: allow macro-defined builtins to call each other?
- The builtins! macro is a lot nicer to work with
- No redundant return value
- Maps the result over Into::into, allowing for type inference!
- Uses explicit pattern syntax instead of weird binding, where possible
- Does not #[allow(unused)], so you'll get unused variable warnings now!
- Integrate the Match and Pattern nodes into the AST
- TODO: `let x: T` is ambiguous with `let x: {}`. Currently the latter takes precedence in the parser.
- Implement pattern matching through unification in the interpreter.
- It's not fast, but it works!
- Refactor destructuring assignments to use the new pattern functionality
I used tree interning here, because the interner already contains the necessary locks to make it Sync, and I was lazy. Be my guest if you want to do something else.
The computational overhead of interning the ASTs here is negligible, since this is all CLI code anyway.
- Smuggle floats as integers to maintain `eq`
- This is bad, but not terrible for spec-compliant floats. Might have issues with NaN.
cl_parser: Smuggle floats
cl_interpret: unpack smuggled floats in float literal node