Skip to content

DSL handling #958

Description

@vinistock

Ruby has lots of DSLs (method calls that mutate what is defined by the code). We need a flexible way of handling this type of code or else we will not be able to represent all of the richness that Rubyists can express.

In other attempts, like the Ruby LSP indexer or Spoom plugins, we used Ruby's own dynamic nature to load custom logic that can tailor the analysis. With a Rust backend, these options aren't really viable as we want to make the most out of parallelism without hitting the GVL and keeping the core logic agnostic from the Ruby VM.

Our primary idea now is shifting Rubydex to use an intermediate representation (IR), where we compile the code into fundamental type-level operations, like enter_class, leave, define_method and so on. This would allow us to expose a Ruby API for registering how to compile specific method call DSLs. Since everything is a simple type and easily shareable with Rust, it would satisfy our performance needs to continue making the most out of parallelism.

Additionally, by compiling the DSLs into resolution-level instructions, we make sure that any DSLs that impact resolution results are actually taken into account. For example, a method call that creates a new class, which is then used as a parent for another class (which impacts ancestor linearization and therefore constant resolution inside of that lexical scope).

This is roughly what the idea is:

graph.register_compiler(
  owner: "Module",
  method_name: "new",
  instructions: [
    [:enter_module, lexical_scope: false],
  ]
)

graph.register_compiler(
  owner: "Struct",
  method_name: "new",
  instructions: [
    [:enter_class, lexical_scope: false, parent: "Struct"],
    [:define_method, :initialize, ...],
    [:for_each_param, :define_attr_reader, :param]
  ]
)

Metadata

Metadata

Assignees

No one assigned

    Labels

    hardThis issue is hard. It may involve ambiguity and challenging technical aspects

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions