Fall cleaning pass ideas :fallen_leaf: :broom:
Just documenting a few cleanup ideas to give an opportunity for input before I embark on a few cleanup passes:
- [x] Convert
lazy_static!toOnceCell - [x] Improve how formal arguments are defined, planning something like to derive formal arguments for primitive functions as well as the
Symclass for the builtin symbol. As amacro_rules!macro, it could look something like
This feels a bit clunky to me - especially if it would implement a trait. That definitely feels like something a proc macro should do.formals! { PrimitivePaste, "..., sep = ' ', collapse = NULL" }
Probably requires that the#[builtin("paste(..., sep = ' ', collapse = NULL)")] pub struct PrimitivePaste {}r_deriveproc macro crate is able to use the parsing component from the core language in order to parse this, which would mean... - [ ] Break up crate into separate crates as a workspace
- [x] Want to do a clean-up pass on macros, removing anything that isn't widely used and standardizing the few that are.
- [ ] Would like to explore ways to reduce the number of flavors of
call_*andeval_*, etc that fuse things like argument matching, calling, evaluation and finalizing. Preferred outcomes would be an API that composes more nicely so that these behaviors can be built instead of individually handled:
This would require that- stack.eval_and_finalize(expr) + stack.eval(expr).finalize()EvalResults carry a reference to theCallStack - [ ] Clean up
Contextimplementations, as there is a lot of code lingering in theEnvironmentimplementation that is never called
In the spirit of honing the scope of a few distinct crates, I'd like to explore decoupling the parsing from the evaluation a bit more consciously.
This is almost decoupled, but is tethered just a bit by the Expr::Primitive variant, which contains boxed references to actual functions. I'm exploring whether it's worth separating these steps so that the actual look-up of the primitive only happens upon evaluation, not during parsing.
Instead of
Expr::Call(Expr::Primitive(Box<InfixAdd>), ...)
We'd have
Expr::Call(CallKind::Infix, Expr::Symbol("+"), ...)
This would allow us to expose the parser to derive macros to declare the formal arguments in a proc macro instead of an inline macro.
This design would be more difficult to deal with using things like Rs do.call - specifically for [ and ( if they’re being repurposed as vector and list constructor syntax.
In do.call, should they call the constructor or the indexing function?
To avoid this, I’m considering a design that looks like Julia’s juxtapose “function”, as a mechanism of differentiating these while still using simple S-expression like representations.