Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fall cleaning pass ideas 🍂 🧹 #170

Open
3 of 6 tasks
dgkf opened this issue Aug 4, 2024 · 2 comments
Open
3 of 6 tasks

Fall cleaning pass ideas 🍂 🧹 #170

dgkf opened this issue Aug 4, 2024 · 2 comments

Comments

@dgkf
Copy link
Owner

dgkf commented Aug 4, 2024

Just documenting a few cleanup ideas to give an opportunity for input before I embark on a few cleanup passes:

  • Convert lazy_static! to OnceCell
  • Improve how formal arguments are defined, planning something like to derive formal arguments for primitive functions as well as the Sym class for the builtin symbol.
    As a macro_rules! macro, it could look something like
    formals! { PrimitivePaste, "..., sep = ' ', collapse = NULL" }
    This feels a bit clunky to me - especially if it would implement a trait. That definitely feels like something a proc macro should do.
    #[builtin("paste(..., sep = ' ', collapse = NULL)")]
    pub struct PrimitivePaste {}
    Probably requires that the r_derive proc 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
  • 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_* and eval_*, 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:
    - stack.eval_and_finalize(expr)
    + stack.eval(expr).finalize()
    This would require that EvalResults carry a reference to the CallStack
  • Clean up Context implementations, as there is a lot of code lingering in the Environment implementation that is never called
@dgkf
Copy link
Owner Author

dgkf commented Aug 7, 2024

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.

@dgkf
Copy link
Owner Author

dgkf commented Aug 14, 2024

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant