syntax_tree 5.1.0 → 5.2.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/main.yml +5 -2
- data/.gitmodules +6 -0
- data/.rubocop.yml +7 -1
- data/CHANGELOG.md +12 -1
- data/Gemfile.lock +7 -7
- data/Rakefile +7 -0
- data/exe/yarv +63 -0
- data/lib/syntax_tree/node.rb +19 -10
- data/lib/syntax_tree/parser.rb +1 -1
- data/lib/syntax_tree/version.rb +1 -1
- data/lib/syntax_tree/yarv/assembler.rb +7 -7
- data/lib/syntax_tree/yarv/bf.rb +13 -16
- data/lib/syntax_tree/yarv/compiler.rb +24 -13
- data/lib/syntax_tree/yarv/decompiler.rb +9 -0
- data/lib/syntax_tree/yarv/disassembler.rb +3 -2
- data/lib/syntax_tree/yarv/instruction_sequence.rb +190 -86
- data/lib/syntax_tree/yarv/instructions.rb +211 -42
- data/lib/syntax_tree/yarv/legacy.rb +26 -3
- data/lib/syntax_tree/yarv/vm.rb +624 -0
- data/lib/syntax_tree/yarv.rb +0 -269
- data/lib/syntax_tree.rb +1 -0
- metadata +7 -3
@@ -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
|