Skip to content

ProcLiteral#call for macros #16451

@HertzDevil

Description

@HertzDevil

#8835 proposes a way to have user-definable methods in the macro language that accept and return AST nodes:

macro def foo(x : StringLiteral) : StringLiteral
  "foo#{x.id}"
end

{{ foo "x" }} # => "foox"

There is a similar concept that would complement this kind of code reuse. We only need to implement ProcLiteral#call, interpreting the literal's entire body as a macro expression:

Foo = ->(x : StringLiteral) : StringLiteral do
  "foo#{x.id}"
end

{{ Foo.call "x" }} # => "foox"

Parameter and return types are optional as long as the constant is not referenced in normal code; if present, they are assumed to be AST node names and correspondingly typechecked. (Unlike defs, we do not have to care about overloading here.) This is also doable:

Fib = ->(x) { x <= 2 ? 1 : Fib.call(x - 1) + Fib.call(x - 2) }

{{ (1..10).map { |v| Fib.call(v) } }} # => [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

This requires no changes to the language grammar and can be further enhanced by features that make them closer to Procs in normal code, e.g. closures and macro ProcPointers.


Add a 👍 reaction to issues you find important.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions