syntax_tree 5.1.0 → 5.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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