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.
@@ -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
- parent_iseq,
163
- location,
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
- "<compiled>",
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(type, name, location)
420
- InstructionSequence.new(type, name, self, location, options)
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(location)
431
+ def block_child_iseq(line)
424
432
  current = self
425
433
  current = current.parent_iseq while current.type == :block
426
- child_iseq(:block, "block in #{current.name}", location)
434
+ child_iseq("block in #{current.name}", line, :block)
427
435
  end
428
436
 
429
- def class_child_iseq(name, location)
430
- child_iseq(:class, "<class:#{name}>", location)
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, location)
434
- child_iseq(:method, name, location)
441
+ def method_child_iseq(name, line)
442
+ child_iseq(name, line, :method)
435
443
  end
436
444
 
437
- def module_child_iseq(name, location)
438
- child_iseq(:class, "<module:#{name}>", location)
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(location)
442
- child_iseq(:class, "singleton class", location)
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
- [:break, iseq.to_a, begin_label.name, end_label.name, exit_label.name]
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(iseq, begin_label, end_label, exit_label)
498
- end
499
-
500
- def catch_next(begin_label, end_label, exit_label)
501
- catch_table << CatchNext.new(nil, begin_label, end_label, exit_label)
502
- end
503
-
504
- def catch_redo(begin_label, end_label, exit_label)
505
- catch_table << CatchRedo.new(nil, begin_label, end_label, exit_label)
506
- end
507
-
508
- def catch_rescue(iseq, begin_label, end_label, exit_label)
509
- catch_table << CatchRescue.new(iseq, begin_label, end_label, exit_label)
510
- end
511
-
512
- def catch_retry(begin_label, end_label, exit_label)
513
- catch_table << CatchRetry.new(nil, begin_label, end_label, exit_label)
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 = new(source[9], source[5], parent_iseq, Location.default, options)
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
- # set up the catch table
918
- source[12].each do |entry|
919
- case entry[0]
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