Skip to content

Commit 065dde3

Browse files
Group temporary variables by file name: splats (#16242)
Co-authored-by: Johannes Müller <[email protected]>
1 parent d566150 commit 065dde3

File tree

8 files changed

+95
-7
lines changed

8 files changed

+95
-7
lines changed

spec/compiler/normalize/array_literal_spec.cr

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,4 +97,25 @@ describe "Normalize: array literal" do
9797
__temp_3
9898
CRYSTAL
9999
end
100+
101+
# TODO: add md5 to the rest of the variables
102+
it "normalizes with filename" do
103+
assert_expand_named "Foo{x, *y}", <<-CRYSTAL, filename: "foo.cr"
104+
__temp_1 = x
105+
__temp_2 = y
106+
__temp_3 = Foo.new
107+
__temp_3 << __temp_1
108+
__temp_2.each do |__temp_cd6ae5dd_1| __temp_3 << __temp_cd6ae5dd_1 end
109+
__temp_3
110+
CRYSTAL
111+
112+
assert_expand_named "Foo{x, *y}", <<-CRYSTAL, filename: "bar.cr"
113+
__temp_1 = x
114+
__temp_2 = y
115+
__temp_3 = Foo.new
116+
__temp_3 << __temp_1
117+
__temp_2.each do |__temp_fbcf3d84_1| __temp_3 << __temp_fbcf3d84_1 end
118+
__temp_3
119+
CRYSTAL
120+
end
100121
end

spec/compiler/normalize/def_spec.cr

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,5 +251,55 @@ module Crystal
251251
end
252252
end
253253
end
254+
255+
it "normalizes with filename" do
256+
a_def = parse("def foo(*args, **options); args + options; end", filename: "foo.cr").as(Def)
257+
other_def = a_def.expand_default_arguments(Program.new, 2, ["x", "y"])
258+
other_def.to_s.should eq <<-CRYSTAL
259+
def foo:x:y(__temp_cd6ae5dd_1, __temp_cd6ae5dd_2, x __temp_cd6ae5dd_3, y __temp_cd6ae5dd_4)
260+
args = {__temp_cd6ae5dd_1, __temp_cd6ae5dd_2}
261+
options = {x: __temp_cd6ae5dd_3, y: __temp_cd6ae5dd_4}
262+
args + options
263+
end
264+
CRYSTAL
265+
266+
a_def = parse("def foo(*args, **options); args + options; end", filename: "bar.cr").as(Def)
267+
other_def = a_def.expand_default_arguments(Program.new, 2, ["x", "y"])
268+
other_def.to_s.should eq <<-CRYSTAL
269+
def foo:x:y(__temp_fbcf3d84_1, __temp_fbcf3d84_2, x __temp_fbcf3d84_3, y __temp_fbcf3d84_4)
270+
args = {__temp_fbcf3d84_1, __temp_fbcf3d84_2}
271+
options = {x: __temp_fbcf3d84_3, y: __temp_fbcf3d84_4}
272+
args + options
273+
end
274+
CRYSTAL
275+
end
276+
277+
it "normalizes `.new` with filename" do
278+
a_def = parse("def new(y, **options); end", filename: "foo.cr").as(Def)
279+
other_def = a_def.expand_new_default_arguments(Program.new, 0, ["x", "y", "z"])
280+
other_def.to_s.should eq <<-CRYSTAL
281+
def new:x:y:z(x __temp_cd6ae5dd_1, y __temp_cd6ae5dd_2, z __temp_cd6ae5dd_3)
282+
_ = allocate
283+
_.initialize(x: __temp_cd6ae5dd_1, y: __temp_cd6ae5dd_2, z: __temp_cd6ae5dd_3)
284+
if _.responds_to?(:finalize)
285+
::GC.add_finalizer(_)
286+
end
287+
_
288+
end
289+
CRYSTAL
290+
291+
a_def = parse("def new(y, **options); end", filename: "bar.cr").as(Def)
292+
other_def = a_def.expand_new_default_arguments(Program.new, 0, ["x", "y", "z"])
293+
other_def.to_s.should eq <<-CRYSTAL
294+
def new:x:y:z(x __temp_fbcf3d84_1, y __temp_fbcf3d84_2, z __temp_fbcf3d84_3)
295+
_ = allocate
296+
_.initialize(x: __temp_fbcf3d84_1, y: __temp_fbcf3d84_2, z: __temp_fbcf3d84_3)
297+
if _.responds_to?(:finalize)
298+
::GC.add_finalizer(_)
299+
end
300+
_
301+
end
302+
CRYSTAL
303+
end
254304
end
255305
end

spec/compiler/semantic/splat_spec.cr

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -808,4 +808,21 @@ describe "Semantic: splat" do
808808
a_def.location.should eq Location.new("", line_number: 2, column_number: 3)
809809
a_def.body.location.should eq Location.new("", line_number: 3, column_number: 5)
810810
end
811+
812+
it "normalizes with filename" do
813+
result = semantic <<-CRYSTAL
814+
def foo(x, y)
815+
end
816+
817+
#<loc:"foo.cr",1,1>foo(*{1, 2})
818+
#<loc:"bar.cr",1,1>foo(*{3, 4})
819+
CRYSTAL
820+
821+
result.node.to_s.should end_with <<-CRYSTAL
822+
__temp_cd6ae5dd_1 = {1, 2}
823+
foo(__temp_cd6ae5dd_1[0], __temp_cd6ae5dd_1[1])
824+
__temp_fbcf3d84_1 = {3, 4}
825+
foo(__temp_fbcf3d84_1[0], __temp_fbcf3d84_1[1])\n
826+
CRYSTAL
827+
end
811828
end

spec/spec_helper.cr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,10 +142,10 @@ def assert_expand(from_nodes : ASTNode, *, flags = nil, file = __FILE__, line =
142142
yield to_nodes, program
143143
end
144144

145-
def assert_expand_named(from : String, to, *, generic = nil, flags = nil, file = __FILE__, line = __LINE__)
145+
def assert_expand_named(from : String, to, *, generic = nil, flags = nil, filename = nil, file = __FILE__, line = __LINE__)
146146
program = new_program
147147
program.flags.concat(flags.split) if flags
148-
from_nodes = Parser.parse(from)
148+
from_nodes = parse(from, filename: filename)
149149
generic_type = generic.path if generic
150150
case from_nodes
151151
when ArrayLiteral

src/compiler/crystal/semantic/default_arguments.cr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ class Crystal::Def
6565
splat_size = 0 if splat_size < 0
6666

6767
splat_size.times do |index|
68-
splat_name = program.new_temp_var_name
68+
splat_name = program.new_temp_var_name(self)
6969
splat_names << splat_name
7070

7171
splat_arg = Arg.new(splat_name)
@@ -88,7 +88,7 @@ class Crystal::Def
8888
str << ':'
8989
str << named_arg
9090

91-
temp_name = program.new_temp_var_name
91+
temp_name = program.new_temp_var_name(self)
9292
named_args_temp_names << temp_name
9393

9494
# If a named argument matches an argument's external name, use the internal name

src/compiler/crystal/semantic/literal_expander.cr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ module Crystal
200200
node.elements.each_with_index do |elem, i|
201201
temp_var = elem_temp_vars.try &.[i]
202202
if elem.is_a?(Splat)
203-
yield_var = new_temp_var
203+
yield_var = new_temp_var(elem)
204204
each_body = Call.new(ary_var.clone, "<<", yield_var.clone).at(node)
205205
each_block = Block.new(args: [yield_var], body: each_body).at(node)
206206
exps << Call.new((temp_var || elem.exp).clone, "each", block: each_block).at(node)

src/compiler/crystal/semantic/main_visitor.cr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1464,7 +1464,7 @@ module Crystal
14641464
next
14651465
end
14661466

1467-
temp_var = @program.new_temp_var.at(arg)
1467+
temp_var = @program.new_temp_var(arg).at(arg)
14681468
assign = Assign.new(temp_var, exp).at(arg)
14691469
exps << assign
14701470
case arg

src/compiler/crystal/semantic/new.cr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ module Crystal
301301

302302
# When **opts is expanded for named arguments, we must use internal
303303
# names that won't clash with local variables defined in the method.
304-
temp_name = instance_type.program.new_temp_var_name
304+
temp_name = instance_type.program.new_temp_var_name(self)
305305
def_arg = Arg.new(temp_name, external_name: named_arg)
306306

307307
if matching_arg = args.find { |arg| arg.external_name == named_arg }

0 commit comments

Comments
 (0)