diff --git a/spec/compiler/macro/macro_methods_spec.cr b/spec/compiler/macro/macro_methods_spec.cr index 5142ad86c5bd..dae2151da6e9 100644 --- a/spec/compiler/macro/macro_methods_spec.cr +++ b/spec/compiler/macro/macro_methods_spec.cr @@ -2763,6 +2763,12 @@ module Crystal end end + describe TypeOf do + it "executes args" do + assert_macro %({{x.args}}), "[1, 'a', Foo]", {x: TypeOf.new([1.int32, CharLiteral.new('a'), "Foo".path])} + end + end + describe "case methods" do describe "when" do case_node = Case.new(1.int32, [When.new([2.int32, 3.int32] of ASTNode, 4.int32)], 5.int32, exhaustive: false) diff --git a/src/compiler/crystal/macros.cr b/src/compiler/crystal/macros.cr index c18782dac954..15d0b64d8ccf 100644 --- a/src/compiler/crystal/macros.cr +++ b/src/compiler/crystal/macros.cr @@ -2255,8 +2255,18 @@ module Crystal::Macros end end - # class TypeOf < ASTNode - # end + # A `typeof` expression. + # + # Every expression *node* is equivalent to: + # + # ``` + # typeof({{ node.args.splat }}) + # ``` + class TypeOf < ASTNode + # Returns the arguments to this `typeof`. + def args : ArrayLiteral(ASTNode) + end + end # A macro expression, # surrounded by {{ ... }} (output = true) diff --git a/src/compiler/crystal/macros/methods.cr b/src/compiler/crystal/macros/methods.cr index 39ec31828328..d0a871fffb56 100644 --- a/src/compiler/crystal/macros/methods.cr +++ b/src/compiler/crystal/macros/methods.cr @@ -2351,6 +2351,17 @@ module Crystal end end + class TypeOf + def interpret(method : String, args : Array(ASTNode), named_args : Hash(String, ASTNode)?, block : Crystal::Block?, interpreter : Crystal::MacroInterpreter, name_loc : Location?) + case method + when "args" + interpret_check_args { ArrayLiteral.map(@expressions, &.itself) } + else + super + end + end + end + class Generic def interpret(method : String, args : Array(ASTNode), named_args : Hash(String, ASTNode)?, block : Crystal::Block?, interpreter : Crystal::MacroInterpreter, name_loc : Location?) case method