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.
@@ -399,9 +399,11 @@ module SyntaxTree
399
399
  # ~~~
400
400
  #
401
401
  class CheckMatch
402
- TYPE_WHEN = 1
403
- TYPE_CASE = 2
404
- TYPE_RESCUE = 3
402
+ VM_CHECKMATCH_TYPE_WHEN = 1
403
+ VM_CHECKMATCH_TYPE_CASE = 2
404
+ VM_CHECKMATCH_TYPE_RESCUE = 3
405
+ VM_CHECKMATCH_TYPE_MASK = 0x03
406
+ VM_CHECKMATCH_ARRAY = 0x04
405
407
 
406
408
  attr_reader :type
407
409
 
@@ -434,7 +436,32 @@ module SyntaxTree
434
436
  end
435
437
 
436
438
  def call(vm)
437
- raise NotImplementedError, "checkmatch"
439
+ target, pattern = vm.pop(2)
440
+
441
+ vm.push(
442
+ if type & VM_CHECKMATCH_ARRAY > 0
443
+ pattern.any? { |item| check?(item, target) }
444
+ else
445
+ check?(pattern, target)
446
+ end
447
+ )
448
+ end
449
+
450
+ private
451
+
452
+ def check?(pattern, target)
453
+ case type & VM_CHECKMATCH_TYPE_MASK
454
+ when VM_CHECKMATCH_TYPE_WHEN
455
+ pattern
456
+ when VM_CHECKMATCH_TYPE_CASE
457
+ pattern === target
458
+ when VM_CHECKMATCH_TYPE_RESCUE
459
+ unless pattern.is_a?(Module)
460
+ raise TypeError, "class or module required for rescue clause"
461
+ end
462
+
463
+ pattern === target
464
+ end
438
465
  end
439
466
  end
440
467
 
@@ -762,12 +789,26 @@ module SyntaxTree
762
789
 
763
790
  def call(vm)
764
791
  object, superclass = vm.pop(2)
765
- iseq = class_iseq
766
792
 
767
- clazz = Class.new(superclass || Object)
768
- vm.push(vm.run_class_frame(iseq, clazz))
793
+ if name == :singletonclass
794
+ vm.push(vm.run_class_frame(class_iseq, object.singleton_class))
795
+ elsif object.const_defined?(name)
796
+ vm.push(vm.run_class_frame(class_iseq, object.const_get(name)))
797
+ elsif flags & TYPE_MODULE > 0
798
+ clazz = Module.new
799
+ object.const_set(name, clazz)
800
+ vm.push(vm.run_class_frame(class_iseq, clazz))
801
+ else
802
+ clazz =
803
+ if flags & FLAG_HAS_SUPERCLASS > 0
804
+ Class.new(superclass)
805
+ else
806
+ Class.new
807
+ end
769
808
 
770
- object.const_set(name, clazz)
809
+ object.const_set(name, clazz)
810
+ vm.push(vm.run_class_frame(class_iseq, clazz))
811
+ end
771
812
  end
772
813
  end
773
814
 
@@ -882,17 +923,19 @@ module SyntaxTree
882
923
  when TYPE_NIL, TYPE_SELF, TYPE_TRUE, TYPE_FALSE, TYPE_ASGN, TYPE_EXPR
883
924
  message
884
925
  when TYPE_IVAR
885
- message if vm._self.instance_variable_defined?(name)
926
+ message if vm.frame._self.instance_variable_defined?(name)
886
927
  when TYPE_LVAR
887
928
  raise NotImplementedError, "defined TYPE_LVAR"
888
929
  when TYPE_GVAR
889
930
  message if global_variables.include?(name)
890
931
  when TYPE_CVAR
891
- clazz = vm._self
932
+ clazz = vm.frame._self
892
933
  clazz = clazz.singleton_class unless clazz.is_a?(Module)
893
934
  message if clazz.class_variable_defined?(name)
894
935
  when TYPE_CONST
895
- raise NotImplementedError, "defined TYPE_CONST"
936
+ clazz = vm.frame._self
937
+ clazz = clazz.singleton_class unless clazz.is_a?(Module)
938
+ message if clazz.const_defined?(name)
896
939
  when TYPE_METHOD
897
940
  raise NotImplementedError, "defined TYPE_METHOD"
898
941
  when TYPE_YIELD
@@ -904,7 +947,9 @@ module SyntaxTree
904
947
  when TYPE_FUNC
905
948
  message if object.respond_to?(name, true)
906
949
  when TYPE_CONST_FROM
907
- raise NotImplementedError, "defined TYPE_CONST_FROM"
950
+ defined =
951
+ vm.frame.nesting.any? { |scope| scope.const_defined?(name, true) }
952
+ message if defined
908
953
  end
909
954
 
910
955
  vm.push(result)
@@ -962,12 +1007,22 @@ module SyntaxTree
962
1007
 
963
1008
  def call(vm)
964
1009
  name = method_name
1010
+ nesting = vm.frame.nesting
965
1011
  iseq = method_iseq
966
1012
 
967
1013
  vm
1014
+ .frame
968
1015
  ._self
969
1016
  .__send__(:define_method, name) do |*args, **kwargs, &block|
970
- vm.run_method_frame(name, iseq, self, *args, **kwargs, &block)
1017
+ vm.run_method_frame(
1018
+ name,
1019
+ nesting,
1020
+ iseq,
1021
+ self,
1022
+ *args,
1023
+ **kwargs,
1024
+ &block
1025
+ )
971
1026
  end
972
1027
  end
973
1028
  end
@@ -1024,12 +1079,22 @@ module SyntaxTree
1024
1079
 
1025
1080
  def call(vm)
1026
1081
  name = method_name
1082
+ nesting = vm.frame.nesting
1027
1083
  iseq = method_iseq
1028
1084
 
1029
1085
  vm
1086
+ .frame
1030
1087
  ._self
1031
1088
  .__send__(:define_singleton_method, name) do |*args, **kwargs, &block|
1032
- vm.run_method_frame(name, iseq, self, *args, **kwargs, &block)
1089
+ vm.run_method_frame(
1090
+ name,
1091
+ nesting,
1092
+ iseq,
1093
+ self,
1094
+ *args,
1095
+ **kwargs,
1096
+ &block
1097
+ )
1033
1098
  end
1034
1099
  end
1035
1100
  end
@@ -1259,7 +1324,42 @@ module SyntaxTree
1259
1324
  end
1260
1325
 
1261
1326
  def call(vm)
1262
- raise NotImplementedError, "expandarray"
1327
+ object = vm.pop
1328
+ object =
1329
+ if Array === object
1330
+ object.dup
1331
+ elsif object.respond_to?(:to_ary, true)
1332
+ object.to_ary
1333
+ else
1334
+ [object]
1335
+ end
1336
+
1337
+ splat_flag = flags & 0x01 > 0
1338
+ postarg_flag = flags & 0x02 > 0
1339
+
1340
+ if number == 0 && splat_flag == 0
1341
+ # no space left on stack
1342
+ elsif postarg_flag
1343
+ values = []
1344
+
1345
+ if number > object.size
1346
+ (number - object.size).times { values.push(nil) }
1347
+ end
1348
+ [number, object.size].min.times { values.push(object.pop) }
1349
+ values.push(object.to_a) if splat_flag
1350
+
1351
+ values.each { |item| vm.push(item) }
1352
+ else
1353
+ values = []
1354
+
1355
+ [number, object.size].min.times { values.push(object.shift) }
1356
+ if number > values.size
1357
+ (number - values.size).times { values.push(nil) }
1358
+ end
1359
+ values.push(object.to_a) if splat_flag
1360
+
1361
+ values.reverse_each { |item| vm.push(item) }
1362
+ end
1263
1363
  end
1264
1364
  end
1265
1365
 
@@ -1424,7 +1524,7 @@ module SyntaxTree
1424
1524
  end
1425
1525
 
1426
1526
  def call(vm)
1427
- clazz = vm._self
1527
+ clazz = vm.frame._self
1428
1528
  clazz = clazz.class unless clazz.is_a?(Class)
1429
1529
  vm.push(clazz.class_variable_get(name))
1430
1530
  end
@@ -1474,14 +1574,20 @@ module SyntaxTree
1474
1574
  end
1475
1575
 
1476
1576
  def call(vm)
1477
- # const_base, allow_nil =
1478
- vm.pop(2)
1577
+ const_base, allow_nil = vm.pop(2)
1479
1578
 
1480
- vm.frame.nesting.reverse_each do |clazz|
1481
- if clazz.const_defined?(name)
1482
- vm.push(clazz.const_get(name))
1579
+ if const_base
1580
+ if const_base.const_defined?(name)
1581
+ vm.push(const_base.const_get(name))
1483
1582
  return
1484
1583
  end
1584
+ elsif const_base.nil? && allow_nil
1585
+ vm.frame.nesting.reverse_each do |clazz|
1586
+ if clazz.const_defined?(name)
1587
+ vm.push(clazz.const_get(name))
1588
+ return
1589
+ end
1590
+ end
1485
1591
  end
1486
1592
 
1487
1593
  raise NameError, "uninitialized constant #{name}"
@@ -1590,7 +1696,7 @@ module SyntaxTree
1590
1696
 
1591
1697
  def call(vm)
1592
1698
  method = Object.instance_method(:instance_variable_get)
1593
- vm.push(method.bind(vm._self).call(name))
1699
+ vm.push(method.bind(vm.frame._self).call(name))
1594
1700
  end
1595
1701
  end
1596
1702
 
@@ -1948,8 +2054,9 @@ module SyntaxTree
1948
2054
  def call(vm)
1949
2055
  block =
1950
2056
  if (iseq = block_iseq)
2057
+ frame = vm.frame
1951
2058
  ->(*args, **kwargs, &blk) do
1952
- vm.run_block_frame(iseq, *args, **kwargs, &blk)
2059
+ vm.run_block_frame(iseq, frame, *args, **kwargs, &blk)
1953
2060
  end
1954
2061
  end
1955
2062
 
@@ -2396,7 +2503,7 @@ module SyntaxTree
2396
2503
 
2397
2504
  def call(vm)
2398
2505
  return if @executed
2399
- vm.push(vm.run_block_frame(iseq))
2506
+ vm.push(vm.run_block_frame(iseq, vm.frame))
2400
2507
  @executed = true
2401
2508
  end
2402
2509
  end
@@ -2960,7 +3067,7 @@ module SyntaxTree
2960
3067
  end
2961
3068
 
2962
3069
  def call(vm)
2963
- current = vm._self
3070
+ current = vm.frame._self
2964
3071
  current = current.class unless current.is_a?(Class)
2965
3072
 
2966
3073
  names.each do |name|
@@ -4254,7 +4361,7 @@ module SyntaxTree
4254
4361
  end
4255
4362
 
4256
4363
  def call(vm)
4257
- vm.push(vm._self)
4364
+ vm.push(vm.frame._self)
4258
4365
  end
4259
4366
  end
4260
4367
 
@@ -4310,7 +4417,7 @@ module SyntaxTree
4310
4417
  when OBJECT_VMCORE
4311
4418
  vm.push(vm.frozen_core)
4312
4419
  when OBJECT_CBASE
4313
- value = vm._self
4420
+ value = vm.frame._self
4314
4421
  value = value.singleton_class unless value.is_a?(Class)
4315
4422
  vm.push(value)
4316
4423
  when OBJECT_CONST_BASE
@@ -4418,9 +4525,12 @@ module SyntaxTree
4418
4525
  def call(vm)
4419
4526
  block =
4420
4527
  if (iseq = block_iseq)
4528
+ frame = vm.frame
4421
4529
  ->(*args, **kwargs, &blk) do
4422
- vm.run_block_frame(iseq, *args, **kwargs, &blk)
4530
+ vm.run_block_frame(iseq, frame, *args, **kwargs, &blk)
4423
4531
  end
4532
+ elsif calldata.flag?(CallData::CALL_ARGS_BLOCKARG)
4533
+ vm.pop
4424
4534
  end
4425
4535
 
4426
4536
  keywords =
@@ -4542,7 +4652,7 @@ module SyntaxTree
4542
4652
  end
4543
4653
 
4544
4654
  def call(vm)
4545
- clazz = vm._self
4655
+ clazz = vm.frame._self
4546
4656
  clazz = clazz.class unless clazz.is_a?(Class)
4547
4657
  clazz.class_variable_set(name, vm.pop)
4548
4658
  end
@@ -4698,7 +4808,7 @@ module SyntaxTree
4698
4808
 
4699
4809
  def call(vm)
4700
4810
  method = Object.instance_method(:instance_variable_set)
4701
- method.bind(vm._self).call(name, vm.pop)
4811
+ method.bind(vm.frame._self).call(name, vm.pop)
4702
4812
  end
4703
4813
  end
4704
4814
 
@@ -4946,7 +5056,7 @@ module SyntaxTree
4946
5056
  def call(vm)
4947
5057
  case key
4948
5058
  when GetSpecial::SVAR_LASTLINE
4949
- raise NotImplementedError, "svar SVAR_LASTLINE"
5059
+ raise NotImplementedError, "setspecial SVAR_LASTLINE"
4950
5060
  when GetSpecial::SVAR_BACKREF
4951
5061
  raise NotImplementedError, "setspecial SVAR_BACKREF"
4952
5062
  when GetSpecial::SVAR_FLIPFLOP_START
@@ -4999,7 +5109,27 @@ module SyntaxTree
4999
5109
  end
5000
5110
 
5001
5111
  def call(vm)
5002
- vm.push(*vm.pop)
5112
+ value = vm.pop
5113
+
5114
+ vm.push(
5115
+ if Array === value
5116
+ value.instance_of?(Array) ? value.dup : Array[*value]
5117
+ elsif value.nil?
5118
+ value.to_a
5119
+ else
5120
+ if value.respond_to?(:to_a, true)
5121
+ result = value.to_a
5122
+
5123
+ if result.nil?
5124
+ [value]
5125
+ elsif !result.is_a?(Array)
5126
+ raise TypeError, "expected to_a to return an Array"
5127
+ end
5128
+ else
5129
+ [value]
5130
+ end
5131
+ end
5132
+ )
5003
5133
  end
5004
5134
  end
5005
5135
 
@@ -5061,15 +5191,18 @@ module SyntaxTree
5061
5191
  # ~~~
5062
5192
  #
5063
5193
  class Throw
5064
- TAG_NONE = 0x0
5065
- TAG_RETURN = 0x1
5066
- TAG_BREAK = 0x2
5067
- TAG_NEXT = 0x3
5068
- TAG_RETRY = 0x4
5069
- TAG_REDO = 0x5
5070
- TAG_RAISE = 0x6
5071
- TAG_THROW = 0x7
5072
- TAG_FATAL = 0x8
5194
+ RUBY_TAG_NONE = 0x0
5195
+ RUBY_TAG_RETURN = 0x1
5196
+ RUBY_TAG_BREAK = 0x2
5197
+ RUBY_TAG_NEXT = 0x3
5198
+ RUBY_TAG_RETRY = 0x4
5199
+ RUBY_TAG_REDO = 0x5
5200
+ RUBY_TAG_RAISE = 0x6
5201
+ RUBY_TAG_THROW = 0x7
5202
+ RUBY_TAG_FATAL = 0x8
5203
+
5204
+ VM_THROW_NO_ESCAPE_FLAG = 0x8000
5205
+ VM_THROW_STATE_MASK = 0xff
5073
5206
 
5074
5207
  attr_reader :type
5075
5208
 
@@ -5102,7 +5235,43 @@ module SyntaxTree
5102
5235
  end
5103
5236
 
5104
5237
  def call(vm)
5105
- raise NotImplementedError, "throw"
5238
+ state = type & VM_THROW_STATE_MASK
5239
+ value = vm.pop
5240
+
5241
+ case state
5242
+ when RUBY_TAG_NONE
5243
+ case value
5244
+ when nil
5245
+ # do nothing
5246
+ when Exception
5247
+ raise value
5248
+ else
5249
+ raise NotImplementedError
5250
+ end
5251
+ when RUBY_TAG_RETURN
5252
+ raise VM::ReturnError.new(value, error_backtrace(vm))
5253
+ when RUBY_TAG_BREAK
5254
+ raise VM::BreakError.new(value, error_backtrace(vm))
5255
+ when RUBY_TAG_NEXT
5256
+ raise VM::NextError.new(value, error_backtrace(vm))
5257
+ else
5258
+ raise NotImplementedError, "Unknown throw kind #{state}"
5259
+ end
5260
+ end
5261
+
5262
+ private
5263
+
5264
+ def error_backtrace(vm)
5265
+ backtrace = []
5266
+ current = vm.frame
5267
+
5268
+ while current
5269
+ backtrace << "#{current.iseq.file}:#{current.line}:in" \
5270
+ "`#{current.iseq.name}'"
5271
+ current = current.parent
5272
+ end
5273
+
5274
+ [*backtrace, *caller]
5106
5275
  end
5107
5276
  end
5108
5277
 
@@ -45,6 +45,14 @@ module SyntaxTree
45
45
  def pushes
46
46
  1
47
47
  end
48
+
49
+ def canonical
50
+ YARV::GetClassVariable.new(name, nil)
51
+ end
52
+
53
+ def call(vm)
54
+ canonical.call(vm)
55
+ end
48
56
  end
49
57
 
50
58
  # ### Summary
@@ -94,6 +102,10 @@ module SyntaxTree
94
102
  1
95
103
  end
96
104
 
105
+ def canonical
106
+ self
107
+ end
108
+
97
109
  def call(vm)
98
110
  vm.push(nil)
99
111
  end
@@ -102,8 +114,8 @@ module SyntaxTree
102
114
  # ### Summary
103
115
  #
104
116
  # `opt_setinlinecache` sets an inline cache for a constant lookup. It pops
105
- # the value it should set off the top of the stack. It then pushes that
106
- # value back onto the top of the stack.
117
+ # the value it should set off the top of the stack. It uses this value to
118
+ # set the cache. It then pushes that value back onto the top of the stack.
107
119
  #
108
120
  # This instruction is no longer used since in Ruby 3.2 it was replaced by
109
121
  # the consolidated `opt_getconstant_path` instruction.
@@ -141,8 +153,11 @@ module SyntaxTree
141
153
  1
142
154
  end
143
155
 
156
+ def canonical
157
+ self
158
+ end
159
+
144
160
  def call(vm)
145
- vm.push(vm.pop)
146
161
  end
147
162
  end
148
163
 
@@ -186,6 +201,14 @@ module SyntaxTree
186
201
  def pushes
187
202
  0
188
203
  end
204
+
205
+ def canonical
206
+ YARV::SetClassVariable.new(name, nil)
207
+ end
208
+
209
+ def call(vm)
210
+ canonical.call(vm)
211
+ end
189
212
  end
190
213
  end
191
214
  end