Skip to content

Commit 8295d8c

Browse files
author
Ary Borenszweig
committedDec 8, 2016
Compiler: let method_missing work with named arguments. Fixes #3654
1 parent 8320e5e commit 8295d8c

File tree

2 files changed

+41
-1
lines changed

2 files changed

+41
-1
lines changed
 

‎spec/compiler/codegen/method_missing_spec.cr

+27
Original file line numberDiff line numberDiff line change
@@ -381,4 +381,31 @@ describe "Code gen: method_missing" do
381381
Foo.new.bar
382382
)).to_string.should eq("bar")
383383
end
384+
385+
it "works with named arguments, using names (#3654)" do
386+
run(%(
387+
class A
388+
macro method_missing(call)
389+
x + y
390+
end
391+
end
392+
393+
a = A.new
394+
a.b(x: 1, y: 2)
395+
)).to_i.should eq(3)
396+
end
397+
398+
it "works with named arguments, named args in call (#3654)" do
399+
run(%(
400+
class A
401+
macro method_missing(call)
402+
{{call.named_args[0].name}} +
403+
{{call.named_args[1].name}}
404+
end
405+
end
406+
407+
a = A.new
408+
a.b(x: 1, y: 2)
409+
)).to_i.should eq(3)
410+
end
384411
end

‎src/compiler/crystal/semantic/method_missing.cr

+14-1
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,21 @@ module Crystal
3838
def define_method_from_method_missing(method_missing, signature, original_call)
3939
name_node = StringLiteral.new(signature.name)
4040
args_nodes = [] of ASTNode
41+
named_args_nodes = nil
4142
args_nodes_names = Set(String).new
4243
signature.arg_types.each_index do |index|
4344
arg_node_name = "_arg#{index}"
4445
args_nodes << MacroId.new(arg_node_name)
4546
args_nodes_names << arg_node_name
4647
end
48+
if named_args = signature.named_args
49+
args_nodes_names << ""
50+
named_args.try &.each do |named_arg|
51+
named_args_nodes ||= [] of NamedArgument
52+
named_args_nodes << NamedArgument.new(named_arg.name, MacroId.new(named_arg.name))
53+
args_nodes_names << named_arg.name
54+
end
55+
end
4756
args_node = ArrayLiteral.new(args_nodes)
4857
if block = signature.block
4958
block_vars = block.args.map_with_index do |var, index|
@@ -57,8 +66,12 @@ module Crystal
5766
end
5867

5968
a_def = Def.new(signature.name, args_nodes_names.map { |name| Arg.new(name) })
69+
a_def.splat_index = signature.arg_types.size if signature.named_args
6070

61-
call = Call.new(nil, signature.name, args: args_nodes, block: block_node.is_a?(Block) ? block_node : nil)
71+
call = Call.new(nil, signature.name,
72+
args: args_nodes,
73+
named_args: named_args_nodes,
74+
block: block_node.is_a?(Block) ? block_node : nil)
6275
fake_call = Call.new(nil, "method_missing", [call] of ASTNode)
6376

6477
expanded_macro = program.expand_macro method_missing, fake_call, self, self

0 commit comments

Comments
 (0)
Please sign in to comment.