diff --git a/spec/compiler/macro/macro_methods_spec.cr b/spec/compiler/macro/macro_methods_spec.cr index 5142ad86c5bd..516c3e408280 100644 --- a/spec/compiler/macro/macro_methods_spec.cr +++ b/spec/compiler/macro/macro_methods_spec.cr @@ -2505,6 +2505,13 @@ module Crystal end end + describe Primitive do + it "executes name" do + assert_macro %({{x.name}}), %(:abc), {x: Primitive.new("abc")} + assert_macro %({{x.name}}), %(:"x.y.z"), {x: Primitive.new("x.y.z")} + end + end + describe "macro methods" do it "executes name" do assert_macro %({{x.name}}), "some_macro", {x: Macro.new("some_macro")} diff --git a/src/compiler/crystal/macros.cr b/src/compiler/crystal/macros.cr index c18782dac954..f18c3c7246ab 100644 --- a/src/compiler/crystal/macros.cr +++ b/src/compiler/crystal/macros.cr @@ -1407,6 +1407,27 @@ module Crystal::Macros end end + # A fictitious node representing the body of a `Def` marked with + # `@[Primitive]`. + class Primitive < ASTNode + # Returns the name of the primitive. + # + # This is identical to the argument to the associated `@[Primitive]` + # annotation. + # + # ``` + # module Foo + # @[Primitive(:abc)] + # def foo + # end + # end + # + # {{ Foo.methods.first.body.name }} # => :abc + # ``` + def name : SymbolLiteral + end + end + # A macro definition. class Macro < ASTNode # Returns the name of this macro. diff --git a/src/compiler/crystal/macros/methods.cr b/src/compiler/crystal/macros/methods.cr index 39ec31828328..60ecdb528509 100644 --- a/src/compiler/crystal/macros/methods.cr +++ b/src/compiler/crystal/macros/methods.cr @@ -1459,6 +1459,17 @@ module Crystal end end + class Primitive + def interpret(method : String, args : Array(ASTNode), named_args : Hash(String, ASTNode)?, block : Crystal::Block?, interpreter : Crystal::MacroInterpreter, name_loc : Location?) + case method + when "name" + interpret_check_args { SymbolLiteral.new(@name) } + else + super + end + end + end + class Macro def interpret(method : String, args : Array(ASTNode), named_args : Hash(String, ASTNode)?, block : Crystal::Block?, interpreter : Crystal::MacroInterpreter, name_loc : Location?) case method