syntax_tree 5.1.0 → 5.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/dependabot.yml +4 -0
- data/.github/workflows/auto-merge.yml +1 -1
- data/.github/workflows/gh-pages.yml +1 -1
- data/.github/workflows/main.yml +5 -2
- data/.gitmodules +9 -0
- data/.rubocop.yml +11 -1
- data/CHANGELOG.md +29 -1
- data/Gemfile.lock +10 -10
- data/README.md +1 -0
- data/Rakefile +7 -0
- data/exe/yarv +63 -0
- data/lib/syntax_tree/cli.rb +3 -2
- data/lib/syntax_tree/formatter.rb +23 -2
- data/lib/syntax_tree/index.rb +374 -0
- data/lib/syntax_tree/node.rb +146 -107
- data/lib/syntax_tree/parser.rb +20 -3
- data/lib/syntax_tree/plugin/disable_ternary.rb +7 -0
- data/lib/syntax_tree/version.rb +1 -1
- data/lib/syntax_tree/yarv/assembler.rb +17 -13
- data/lib/syntax_tree/yarv/bf.rb +13 -16
- data/lib/syntax_tree/yarv/compiler.rb +25 -14
- data/lib/syntax_tree/yarv/decompiler.rb +10 -1
- data/lib/syntax_tree/yarv/disassembler.rb +3 -2
- data/lib/syntax_tree/yarv/instruction_sequence.rb +191 -87
- data/lib/syntax_tree/yarv/instructions.rb +1011 -42
- data/lib/syntax_tree/yarv/legacy.rb +59 -3
- data/lib/syntax_tree/yarv/vm.rb +628 -0
- data/lib/syntax_tree/yarv.rb +0 -269
- data/lib/syntax_tree.rb +16 -0
- metadata +9 -3
@@ -285,7 +285,7 @@ module SyntaxTree
|
|
285
285
|
# if we need to return the value of the last statement.
|
286
286
|
attr_reader :last_statement
|
287
287
|
|
288
|
-
def initialize(options)
|
288
|
+
def initialize(options = Options.new)
|
289
289
|
@options = options
|
290
290
|
@iseq = nil
|
291
291
|
@last_statement = false
|
@@ -304,10 +304,11 @@ module SyntaxTree
|
|
304
304
|
end
|
305
305
|
|
306
306
|
def visit_END(node)
|
307
|
+
start_line = node.location.start_line
|
307
308
|
once_iseq =
|
308
|
-
with_child_iseq(iseq.block_child_iseq(
|
309
|
+
with_child_iseq(iseq.block_child_iseq(start_line)) do
|
309
310
|
postexe_iseq =
|
310
|
-
with_child_iseq(iseq.block_child_iseq(
|
311
|
+
with_child_iseq(iseq.block_child_iseq(start_line)) do
|
311
312
|
iseq.event(:RUBY_EVENT_B_CALL)
|
312
313
|
|
313
314
|
*statements, last_statement = node.statements.body
|
@@ -567,7 +568,7 @@ module SyntaxTree
|
|
567
568
|
end
|
568
569
|
|
569
570
|
def visit_block(node)
|
570
|
-
with_child_iseq(iseq.block_child_iseq(node.location)) do
|
571
|
+
with_child_iseq(iseq.block_child_iseq(node.location.start_line)) do
|
571
572
|
iseq.event(:RUBY_EVENT_B_CALL)
|
572
573
|
visit(node.block_var)
|
573
574
|
visit(node.bodystmt)
|
@@ -751,7 +752,9 @@ module SyntaxTree
|
|
751
752
|
def visit_class(node)
|
752
753
|
name = node.constant.constant.value.to_sym
|
753
754
|
class_iseq =
|
754
|
-
with_child_iseq(
|
755
|
+
with_child_iseq(
|
756
|
+
iseq.class_child_iseq(name, node.location.start_line)
|
757
|
+
) do
|
755
758
|
iseq.event(:RUBY_EVENT_CLASS)
|
756
759
|
visit(node.bodystmt)
|
757
760
|
iseq.event(:RUBY_EVENT_END)
|
@@ -818,7 +821,8 @@ module SyntaxTree
|
|
818
821
|
|
819
822
|
def visit_def(node)
|
820
823
|
name = node.name.value.to_sym
|
821
|
-
method_iseq =
|
824
|
+
method_iseq =
|
825
|
+
iseq.method_child_iseq(name.to_s, node.location.start_line)
|
822
826
|
|
823
827
|
with_child_iseq(method_iseq) do
|
824
828
|
visit(node.params) if node.params
|
@@ -939,7 +943,9 @@ module SyntaxTree
|
|
939
943
|
iseq.local_table.plain(name)
|
940
944
|
|
941
945
|
block_iseq =
|
942
|
-
with_child_iseq(
|
946
|
+
with_child_iseq(
|
947
|
+
iseq.block_child_iseq(node.statements.location.start_line)
|
948
|
+
) do
|
943
949
|
iseq.argument_options[:lead_num] ||= 0
|
944
950
|
iseq.argument_options[:lead_num] += 1
|
945
951
|
iseq.argument_options[:ambiguous_param0] = true
|
@@ -1076,7 +1082,7 @@ module SyntaxTree
|
|
1076
1082
|
|
1077
1083
|
def visit_lambda(node)
|
1078
1084
|
lambda_iseq =
|
1079
|
-
with_child_iseq(iseq.block_child_iseq(node.location)) do
|
1085
|
+
with_child_iseq(iseq.block_child_iseq(node.location.start_line)) do
|
1080
1086
|
iseq.event(:RUBY_EVENT_B_CALL)
|
1081
1087
|
visit(node.params)
|
1082
1088
|
visit(node.statements)
|
@@ -1127,7 +1133,9 @@ module SyntaxTree
|
|
1127
1133
|
def visit_module(node)
|
1128
1134
|
name = node.constant.constant.value.to_sym
|
1129
1135
|
module_iseq =
|
1130
|
-
with_child_iseq(
|
1136
|
+
with_child_iseq(
|
1137
|
+
iseq.module_child_iseq(name, node.location.start_line)
|
1138
|
+
) do
|
1131
1139
|
iseq.event(:RUBY_EVENT_CLASS)
|
1132
1140
|
visit(node.bodystmt)
|
1133
1141
|
iseq.event(:RUBY_EVENT_END)
|
@@ -1375,10 +1383,11 @@ module SyntaxTree
|
|
1375
1383
|
|
1376
1384
|
top_iseq =
|
1377
1385
|
InstructionSequence.new(
|
1378
|
-
:top,
|
1379
1386
|
"<compiled>",
|
1387
|
+
"<compiled>",
|
1388
|
+
1,
|
1389
|
+
:top,
|
1380
1390
|
nil,
|
1381
|
-
node.location,
|
1382
1391
|
options
|
1383
1392
|
)
|
1384
1393
|
|
@@ -1543,7 +1552,9 @@ module SyntaxTree
|
|
1543
1552
|
iseq.putnil
|
1544
1553
|
|
1545
1554
|
singleton_iseq =
|
1546
|
-
with_child_iseq(
|
1555
|
+
with_child_iseq(
|
1556
|
+
iseq.singleton_class_child_iseq(node.location.start_line)
|
1557
|
+
) do
|
1547
1558
|
iseq.event(:RUBY_EVENT_CLASS)
|
1548
1559
|
visit(node.bodystmt)
|
1549
1560
|
iseq.event(:RUBY_EVENT_END)
|
@@ -2018,7 +2029,7 @@ module SyntaxTree
|
|
2018
2029
|
if node.constant
|
2019
2030
|
iseq.dup
|
2020
2031
|
visit(node.constant)
|
2021
|
-
iseq.checkmatch(CheckMatch::
|
2032
|
+
iseq.checkmatch(CheckMatch::VM_CHECKMATCH_TYPE_CASE)
|
2022
2033
|
iseq.branchunless(match_failure_label)
|
2023
2034
|
end
|
2024
2035
|
|
@@ -2078,7 +2089,7 @@ module SyntaxTree
|
|
2078
2089
|
iseq.setlocal(lookup.index, lookup.level)
|
2079
2090
|
else
|
2080
2091
|
visit(required)
|
2081
|
-
iseq.checkmatch(CheckMatch::
|
2092
|
+
iseq.checkmatch(CheckMatch::VM_CHECKMATCH_TYPE_CASE)
|
2082
2093
|
iseq.branchunless(match_failure_label)
|
2083
2094
|
end
|
2084
2095
|
|
@@ -64,6 +64,13 @@ module SyntaxTree
|
|
64
64
|
clauses[label] = clause
|
65
65
|
clause = []
|
66
66
|
label = insn.name
|
67
|
+
when BranchIf
|
68
|
+
body = [
|
69
|
+
Assign(block_label.field, node_for(insn.label.name)),
|
70
|
+
Next(Args([]))
|
71
|
+
]
|
72
|
+
|
73
|
+
clause << UnlessNode(clause.pop, Statements(body), nil)
|
67
74
|
when BranchUnless
|
68
75
|
body = [
|
69
76
|
Assign(block_label.field, node_for(insn.label.name)),
|
@@ -90,7 +97,7 @@ module SyntaxTree
|
|
90
97
|
clause << Next(Args([]))
|
91
98
|
when Leave
|
92
99
|
value = Args([clause.pop])
|
93
|
-
clause << (iseq.type
|
100
|
+
clause << (iseq.type != :top ? Break(value) : ReturnNode(value))
|
94
101
|
when OptAnd, OptDiv, OptEq, OptGE, OptGT, OptLE, OptLT, OptLTLT,
|
95
102
|
OptMinus, OptMod, OptMult, OptOr, OptPlus
|
96
103
|
left, right = clause.pop(2)
|
@@ -157,6 +164,8 @@ module SyntaxTree
|
|
157
164
|
)
|
158
165
|
end
|
159
166
|
end
|
167
|
+
when Pop
|
168
|
+
# skip
|
160
169
|
when PutObject
|
161
170
|
case insn.object
|
162
171
|
when Float
|
@@ -4,7 +4,8 @@ module SyntaxTree
|
|
4
4
|
module YARV
|
5
5
|
class Disassembler
|
6
6
|
attr_reader :output, :queue
|
7
|
-
attr_reader :current_prefix
|
7
|
+
attr_reader :current_prefix
|
8
|
+
attr_accessor :current_iseq
|
8
9
|
|
9
10
|
def initialize
|
10
11
|
@output = StringIO.new
|
@@ -114,7 +115,7 @@ module SyntaxTree
|
|
114
115
|
output << "#{current_prefix}== disasm: "
|
115
116
|
output << "#<ISeq:#{iseq.name}@<compiled>:1 "
|
116
117
|
|
117
|
-
location = iseq.
|
118
|
+
location = Location.fixed(line: iseq.line, char: 0, column: 0)
|
118
119
|
output << "(#{location.start_line},#{location.start_column})-"
|
119
120
|
output << "(#{location.end_line},#{location.end_column})"
|
120
121
|
output << "> "
|
@@ -70,7 +70,7 @@ module SyntaxTree
|
|
70
70
|
[Fiddle::TYPE_VOIDP] * 3,
|
71
71
|
Fiddle::TYPE_VOIDP
|
72
72
|
)
|
73
|
-
rescue NameError
|
73
|
+
rescue NameError, Fiddle::DLError
|
74
74
|
end
|
75
75
|
|
76
76
|
# This object is used to track the size of the stack at any given time. It
|
@@ -116,18 +116,18 @@ module SyntaxTree
|
|
116
116
|
end
|
117
117
|
end
|
118
118
|
|
119
|
-
# The type of the instruction sequence.
|
120
|
-
attr_reader :type
|
121
|
-
|
122
119
|
# The name of the instruction sequence.
|
123
120
|
attr_reader :name
|
124
121
|
|
122
|
+
# The source location of the instruction sequence.
|
123
|
+
attr_reader :file, :line
|
124
|
+
|
125
|
+
# The type of the instruction sequence.
|
126
|
+
attr_reader :type
|
127
|
+
|
125
128
|
# The parent instruction sequence, if there is one.
|
126
129
|
attr_reader :parent_iseq
|
127
130
|
|
128
|
-
# The location of the root node of this instruction sequence.
|
129
|
-
attr_reader :location
|
130
|
-
|
131
131
|
# This is the list of information about the arguments to this
|
132
132
|
# instruction sequence.
|
133
133
|
attr_accessor :argument_size
|
@@ -157,16 +157,18 @@ module SyntaxTree
|
|
157
157
|
attr_reader :options
|
158
158
|
|
159
159
|
def initialize(
|
160
|
-
type,
|
161
160
|
name,
|
162
|
-
|
163
|
-
|
161
|
+
file,
|
162
|
+
line,
|
163
|
+
type,
|
164
|
+
parent_iseq = nil,
|
164
165
|
options = Compiler::Options.new
|
165
166
|
)
|
166
|
-
@type = type
|
167
167
|
@name = name
|
168
|
+
@file = file
|
169
|
+
@line = line
|
170
|
+
@type = type
|
168
171
|
@parent_iseq = parent_iseq
|
169
|
-
@location = location
|
170
172
|
|
171
173
|
@argument_size = 0
|
172
174
|
@argument_options = {}
|
@@ -256,9 +258,9 @@ module SyntaxTree
|
|
256
258
|
node_ids: [-1] * insns.length
|
257
259
|
},
|
258
260
|
name,
|
261
|
+
file,
|
259
262
|
"<compiled>",
|
260
|
-
|
261
|
-
location.start_line,
|
263
|
+
line,
|
262
264
|
type,
|
263
265
|
local_table.names,
|
264
266
|
dumped_options,
|
@@ -278,6 +280,12 @@ module SyntaxTree
|
|
278
280
|
def compile!
|
279
281
|
specialize_instructions! if options.specialized_instruction?
|
280
282
|
|
283
|
+
catch_table.each do |catch_entry|
|
284
|
+
if !catch_entry.is_a?(CatchBreak) && catch_entry.iseq
|
285
|
+
catch_entry.iseq.compile!
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
281
289
|
length = 0
|
282
290
|
insns.each do |insn|
|
283
291
|
case insn
|
@@ -416,30 +424,30 @@ module SyntaxTree
|
|
416
424
|
# Child instruction sequence methods
|
417
425
|
##########################################################################
|
418
426
|
|
419
|
-
def child_iseq(
|
420
|
-
InstructionSequence.new(
|
427
|
+
def child_iseq(name, line, type)
|
428
|
+
InstructionSequence.new(name, file, line, type, self, options)
|
421
429
|
end
|
422
430
|
|
423
|
-
def block_child_iseq(
|
431
|
+
def block_child_iseq(line)
|
424
432
|
current = self
|
425
433
|
current = current.parent_iseq while current.type == :block
|
426
|
-
child_iseq(
|
434
|
+
child_iseq("block in #{current.name}", line, :block)
|
427
435
|
end
|
428
436
|
|
429
|
-
def class_child_iseq(name,
|
430
|
-
child_iseq(
|
437
|
+
def class_child_iseq(name, line)
|
438
|
+
child_iseq("<class:#{name}>", line, :class)
|
431
439
|
end
|
432
440
|
|
433
|
-
def method_child_iseq(name,
|
434
|
-
child_iseq(
|
441
|
+
def method_child_iseq(name, line)
|
442
|
+
child_iseq(name, line, :method)
|
435
443
|
end
|
436
444
|
|
437
|
-
def module_child_iseq(name,
|
438
|
-
child_iseq(
|
445
|
+
def module_child_iseq(name, line)
|
446
|
+
child_iseq("<module:#{name}>", line, :class)
|
439
447
|
end
|
440
448
|
|
441
|
-
def singleton_class_child_iseq(
|
442
|
-
child_iseq(
|
449
|
+
def singleton_class_child_iseq(line)
|
450
|
+
child_iseq("singleton class", line, :class)
|
443
451
|
end
|
444
452
|
|
445
453
|
##########################################################################
|
@@ -447,19 +455,39 @@ module SyntaxTree
|
|
447
455
|
##########################################################################
|
448
456
|
|
449
457
|
class CatchEntry
|
450
|
-
attr_reader :iseq, :begin_label, :end_label, :exit_label
|
458
|
+
attr_reader :iseq, :begin_label, :end_label, :exit_label, :restore_sp
|
451
459
|
|
452
|
-
def initialize(iseq, begin_label, end_label, exit_label)
|
460
|
+
def initialize(iseq, begin_label, end_label, exit_label, restore_sp)
|
453
461
|
@iseq = iseq
|
454
462
|
@begin_label = begin_label
|
455
463
|
@end_label = end_label
|
456
464
|
@exit_label = exit_label
|
465
|
+
@restore_sp = restore_sp
|
457
466
|
end
|
458
467
|
end
|
459
468
|
|
460
469
|
class CatchBreak < CatchEntry
|
461
470
|
def to_a
|
462
|
-
[
|
471
|
+
[
|
472
|
+
:break,
|
473
|
+
iseq.to_a,
|
474
|
+
begin_label.name,
|
475
|
+
end_label.name,
|
476
|
+
exit_label.name,
|
477
|
+
restore_sp
|
478
|
+
]
|
479
|
+
end
|
480
|
+
end
|
481
|
+
|
482
|
+
class CatchEnsure < CatchEntry
|
483
|
+
def to_a
|
484
|
+
[
|
485
|
+
:ensure,
|
486
|
+
iseq.to_a,
|
487
|
+
begin_label.name,
|
488
|
+
end_label.name,
|
489
|
+
exit_label.name
|
490
|
+
]
|
463
491
|
end
|
464
492
|
end
|
465
493
|
|
@@ -493,24 +521,64 @@ module SyntaxTree
|
|
493
521
|
end
|
494
522
|
end
|
495
523
|
|
496
|
-
def catch_break(iseq, begin_label, end_label, exit_label)
|
497
|
-
catch_table << CatchBreak.new(
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
524
|
+
def catch_break(iseq, begin_label, end_label, exit_label, restore_sp)
|
525
|
+
catch_table << CatchBreak.new(
|
526
|
+
iseq,
|
527
|
+
begin_label,
|
528
|
+
end_label,
|
529
|
+
exit_label,
|
530
|
+
restore_sp
|
531
|
+
)
|
532
|
+
end
|
533
|
+
|
534
|
+
def catch_ensure(iseq, begin_label, end_label, exit_label, restore_sp)
|
535
|
+
catch_table << CatchEnsure.new(
|
536
|
+
iseq,
|
537
|
+
begin_label,
|
538
|
+
end_label,
|
539
|
+
exit_label,
|
540
|
+
restore_sp
|
541
|
+
)
|
542
|
+
end
|
543
|
+
|
544
|
+
def catch_next(begin_label, end_label, exit_label, restore_sp)
|
545
|
+
catch_table << CatchNext.new(
|
546
|
+
nil,
|
547
|
+
begin_label,
|
548
|
+
end_label,
|
549
|
+
exit_label,
|
550
|
+
restore_sp
|
551
|
+
)
|
552
|
+
end
|
553
|
+
|
554
|
+
def catch_redo(begin_label, end_label, exit_label, restore_sp)
|
555
|
+
catch_table << CatchRedo.new(
|
556
|
+
nil,
|
557
|
+
begin_label,
|
558
|
+
end_label,
|
559
|
+
exit_label,
|
560
|
+
restore_sp
|
561
|
+
)
|
562
|
+
end
|
563
|
+
|
564
|
+
def catch_rescue(iseq, begin_label, end_label, exit_label, restore_sp)
|
565
|
+
catch_table << CatchRescue.new(
|
566
|
+
iseq,
|
567
|
+
begin_label,
|
568
|
+
end_label,
|
569
|
+
exit_label,
|
570
|
+
restore_sp
|
571
|
+
)
|
572
|
+
end
|
573
|
+
|
574
|
+
def catch_retry(begin_label, end_label, exit_label, restore_sp)
|
575
|
+
catch_table << CatchRetry.new(
|
576
|
+
nil,
|
577
|
+
begin_label,
|
578
|
+
end_label,
|
579
|
+
exit_label,
|
580
|
+
restore_sp
|
581
|
+
)
|
514
582
|
end
|
515
583
|
|
516
584
|
##########################################################################
|
@@ -895,7 +963,8 @@ module SyntaxTree
|
|
895
963
|
# This method will create a new instruction sequence from a serialized
|
896
964
|
# RubyVM::InstructionSequence object.
|
897
965
|
def self.from(source, options = Compiler::Options.new, parent_iseq = nil)
|
898
|
-
iseq =
|
966
|
+
iseq =
|
967
|
+
new(source[5], source[6], source[8], source[9], parent_iseq, options)
|
899
968
|
|
900
969
|
# set up the labels object so that the labels are shared between the
|
901
970
|
# location in the instruction sequence and the instructions that
|
@@ -914,45 +983,9 @@ module SyntaxTree
|
|
914
983
|
iseq.argument_options[:opt].map! { |opt| labels[opt] }
|
915
984
|
end
|
916
985
|
|
917
|
-
#
|
918
|
-
|
919
|
-
|
920
|
-
when :break
|
921
|
-
iseq.catch_break(
|
922
|
-
from(entry[1]),
|
923
|
-
labels[entry[2]],
|
924
|
-
labels[entry[3]],
|
925
|
-
labels[entry[4]]
|
926
|
-
)
|
927
|
-
when :next
|
928
|
-
iseq.catch_next(
|
929
|
-
labels[entry[2]],
|
930
|
-
labels[entry[3]],
|
931
|
-
labels[entry[4]]
|
932
|
-
)
|
933
|
-
when :rescue
|
934
|
-
iseq.catch_rescue(
|
935
|
-
from(entry[1]),
|
936
|
-
labels[entry[2]],
|
937
|
-
labels[entry[3]],
|
938
|
-
labels[entry[4]]
|
939
|
-
)
|
940
|
-
when :redo
|
941
|
-
iseq.catch_redo(
|
942
|
-
labels[entry[2]],
|
943
|
-
labels[entry[3]],
|
944
|
-
labels[entry[4]]
|
945
|
-
)
|
946
|
-
when :retry
|
947
|
-
iseq.catch_retry(
|
948
|
-
labels[entry[2]],
|
949
|
-
labels[entry[3]],
|
950
|
-
labels[entry[4]]
|
951
|
-
)
|
952
|
-
else
|
953
|
-
raise "unknown catch type: #{entry[0]}"
|
954
|
-
end
|
955
|
-
end
|
986
|
+
# track the child block iseqs so that our catch table can point to the
|
987
|
+
# correctly created iseqs
|
988
|
+
block_iseqs = []
|
956
989
|
|
957
990
|
# set up all of the instructions
|
958
991
|
source[13].each do |insn|
|
@@ -1135,6 +1168,7 @@ module SyntaxTree
|
|
1135
1168
|
iseq.putspecialobject(opnds[0])
|
1136
1169
|
when :send
|
1137
1170
|
block_iseq = opnds[1] ? from(opnds[1], options, iseq) : nil
|
1171
|
+
block_iseqs << block_iseq if block_iseq
|
1138
1172
|
iseq.send(CallData.from(opnds[0]), block_iseq)
|
1139
1173
|
when :setclassvariable
|
1140
1174
|
iseq.push(SetClassVariable.new(opnds[0], opnds[1]))
|
@@ -1163,6 +1197,76 @@ module SyntaxTree
|
|
1163
1197
|
end
|
1164
1198
|
end
|
1165
1199
|
|
1200
|
+
# set up the catch table
|
1201
|
+
source[12].each do |entry|
|
1202
|
+
case entry[0]
|
1203
|
+
when :break
|
1204
|
+
if entry[1]
|
1205
|
+
break_iseq =
|
1206
|
+
block_iseqs.find do |block_iseq|
|
1207
|
+
block_iseq.name == entry[1][5] &&
|
1208
|
+
block_iseq.file == entry[1][6] &&
|
1209
|
+
block_iseq.line == entry[1][8]
|
1210
|
+
end
|
1211
|
+
|
1212
|
+
iseq.catch_break(
|
1213
|
+
break_iseq || from(entry[1], options, iseq),
|
1214
|
+
labels[entry[2]],
|
1215
|
+
labels[entry[3]],
|
1216
|
+
labels[entry[4]],
|
1217
|
+
entry[5]
|
1218
|
+
)
|
1219
|
+
else
|
1220
|
+
iseq.catch_break(
|
1221
|
+
nil,
|
1222
|
+
labels[entry[2]],
|
1223
|
+
labels[entry[3]],
|
1224
|
+
labels[entry[4]],
|
1225
|
+
entry[5]
|
1226
|
+
)
|
1227
|
+
end
|
1228
|
+
when :ensure
|
1229
|
+
iseq.catch_ensure(
|
1230
|
+
from(entry[1], options, iseq),
|
1231
|
+
labels[entry[2]],
|
1232
|
+
labels[entry[3]],
|
1233
|
+
labels[entry[4]],
|
1234
|
+
entry[5]
|
1235
|
+
)
|
1236
|
+
when :next
|
1237
|
+
iseq.catch_next(
|
1238
|
+
labels[entry[2]],
|
1239
|
+
labels[entry[3]],
|
1240
|
+
labels[entry[4]],
|
1241
|
+
entry[5]
|
1242
|
+
)
|
1243
|
+
when :rescue
|
1244
|
+
iseq.catch_rescue(
|
1245
|
+
from(entry[1], options, iseq),
|
1246
|
+
labels[entry[2]],
|
1247
|
+
labels[entry[3]],
|
1248
|
+
labels[entry[4]],
|
1249
|
+
entry[5]
|
1250
|
+
)
|
1251
|
+
when :redo
|
1252
|
+
iseq.catch_redo(
|
1253
|
+
labels[entry[2]],
|
1254
|
+
labels[entry[3]],
|
1255
|
+
labels[entry[4]],
|
1256
|
+
entry[5]
|
1257
|
+
)
|
1258
|
+
when :retry
|
1259
|
+
iseq.catch_retry(
|
1260
|
+
labels[entry[2]],
|
1261
|
+
labels[entry[3]],
|
1262
|
+
labels[entry[4]],
|
1263
|
+
entry[5]
|
1264
|
+
)
|
1265
|
+
else
|
1266
|
+
raise "unknown catch type: #{entry[0]}"
|
1267
|
+
end
|
1268
|
+
end
|
1269
|
+
|
1166
1270
|
iseq.compile! if iseq.type == :top
|
1167
1271
|
iseq
|
1168
1272
|
end
|