syntax_tree 5.1.0 → 5.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|