Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 593486d

Browse files
committed
Handle the &. operator
1 parent 358d029 commit 593486d

File tree

2 files changed

+60
-26
lines changed

2 files changed

+60
-26
lines changed

lib/syntax_tree/visitor/compiler.rb

Lines changed: 56 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -404,8 +404,8 @@ def to_a
404404
def serialize(insn)
405405
case insn[0]
406406
when :checkkeyword, :getblockparam, :getblockparamproxy,
407-
:getlocal_WC_0, :getlocal_WC_1, :getlocal,
408-
:setlocal_WC_0, :setlocal_WC_1, :setlocal
407+
:getlocal_WC_0, :getlocal_WC_1, :getlocal, :setlocal_WC_0,
408+
:setlocal_WC_1, :setlocal
409409
iseq = self
410410

411411
case insn[0]
@@ -480,6 +480,11 @@ def branchif(index)
480480
iseq.push([:branchif, index])
481481
end
482482

483+
def branchnil(index)
484+
stack.change_by(-1)
485+
iseq.push([:branchnil, index])
486+
end
487+
483488
def branchunless(index)
484489
stack.change_by(-1)
485490
iseq.push([:branchunless, index])
@@ -1268,14 +1273,16 @@ def visit_bodystmt(node)
12681273

12691274
def visit_call(node)
12701275
if node.is_a?(CallNode)
1271-
return visit_call(
1272-
CommandCall.new(
1273-
receiver: node.receiver,
1274-
operator: node.operator,
1275-
message: node.message,
1276-
arguments: node.arguments,
1277-
block: nil,
1278-
location: node.location
1276+
return(
1277+
visit_call(
1278+
CommandCall.new(
1279+
receiver: node.receiver,
1280+
operator: node.operator,
1281+
message: node.message,
1282+
arguments: node.arguments,
1283+
block: nil,
1284+
location: node.location
1285+
)
12791286
)
12801287
)
12811288
end
@@ -1319,7 +1326,11 @@ def visit_call(node)
13191326
end
13201327

13211328
if node.receiver
1322-
if node.receiver.is_a?(VarRef) && (lookup = current_iseq.local_variable(node.receiver.value.value.to_sym)) && lookup.local.is_a?(LocalTable::BlockLocal)
1329+
if node.receiver.is_a?(VarRef) &&
1330+
(
1331+
lookup =
1332+
current_iseq.local_variable(node.receiver.value.value.to_sym)
1333+
) && lookup.local.is_a?(LocalTable::BlockLocal)
13231334
builder.getblockparamproxy(lookup.index, lookup.level)
13241335
else
13251336
visit(node.receiver)
@@ -1328,6 +1339,12 @@ def visit_call(node)
13281339
builder.putself
13291340
end
13301341

1342+
branchnil =
1343+
if node.operator&.value == "&."
1344+
builder.dup
1345+
builder.branchnil(-1)
1346+
end
1347+
13311348
flag = 0
13321349

13331350
arg_parts.each do |arg_part|
@@ -1361,6 +1378,7 @@ def visit_call(node)
13611378
flag |= VM_CALL_FCALL if node.receiver.nil?
13621379

13631380
builder.send(node.message.value.to_sym, argc, flag, block_iseq)
1381+
branchnil[1] = builder.label if branchnil
13641382
end
13651383

13661384
def visit_case(node)
@@ -1390,11 +1408,7 @@ def visit_case(node)
13901408

13911409
builder.pop
13921410

1393-
if else_clause
1394-
visit(else_clause)
1395-
else
1396-
builder.putnil
1397-
end
1411+
else_clause ? visit(else_clause) : builder.putnil
13981412

13991413
builder.leave
14001414

@@ -1701,7 +1715,12 @@ def visit_label(node)
17011715

17021716
def visit_lambda(node)
17031717
lambda_iseq =
1704-
with_instruction_sequence(:block, "block in #{current_iseq.name}", current_iseq, node) do
1718+
with_instruction_sequence(
1719+
:block,
1720+
"block in #{current_iseq.name}",
1721+
current_iseq,
1722+
node
1723+
) do
17051724
visit(node.params)
17061725
visit(node.statements)
17071726
builder.leave
@@ -1746,9 +1765,7 @@ def visit_mlhs(node)
17461765

17471766
builder.expandarray(lookups.length, 0)
17481767

1749-
lookups.each do |lookup|
1750-
builder.setlocal(lookup.index, lookup.level)
1751-
end
1768+
lookups.each { |lookup| builder.setlocal(lookup.index, lookup.level) }
17521769
end
17531770

17541771
def visit_module(node)
@@ -1944,10 +1961,14 @@ def visit_params(node)
19441961
if node.keyword_rest.is_a?(ArgsForward)
19451962
current_iseq.local_table.plain(:*)
19461963
current_iseq.local_table.plain(:&)
1947-
1948-
current_iseq.argument_options[:rest_start] = current_iseq.argument_size
1949-
current_iseq.argument_options[:block_start] = current_iseq.argument_size + 1
1950-
1964+
1965+
current_iseq.argument_options[
1966+
:rest_start
1967+
] = current_iseq.argument_size
1968+
current_iseq.argument_options[
1969+
:block_start
1970+
] = current_iseq.argument_size + 1
1971+
19511972
current_iseq.argument_size += 2
19521973
elsif node.keyword_rest
19531974
visit(node.keyword_rest)
@@ -2042,12 +2063,21 @@ def visit_sclass(node)
20422063
builder.putnil
20432064

20442065
singleton_iseq =
2045-
with_instruction_sequence(:class, "singleton class", current_iseq, node) do
2066+
with_instruction_sequence(
2067+
:class,
2068+
"singleton class",
2069+
current_iseq,
2070+
node
2071+
) do
20462072
visit(node.bodystmt)
20472073
builder.leave
20482074
end
20492075

2050-
builder.defineclass(:singletonclass, singleton_iseq, VM_DEFINECLASS_TYPE_SINGLETON_CLASS)
2076+
builder.defineclass(
2077+
:singletonclass,
2078+
singleton_iseq,
2079+
VM_DEFINECLASS_TYPE_SINGLETON_CLASS
2080+
)
20512081
end
20522082

20532083
def visit_statements(node)

test/compiler_test.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,10 @@ class CompilerTest < Minitest::Test
259259
"Foo::Bar.baz = 1",
260260
"::Foo::Bar.baz = 1",
261261
# Control flow
262+
"foo&.bar",
263+
"foo&.bar(1)",
264+
"foo&.bar 1, 2, 3",
265+
"foo&.bar {}",
262266
"foo && bar",
263267
"foo || bar",
264268
"if foo then bar end",

0 commit comments

Comments
 (0)