syntax_tree 6.0.1 → 6.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -792,9 +792,10 @@ module SyntaxTree
792
792
  private
793
793
 
794
794
  def trailing_comma?
795
+ arguments = self.arguments
795
796
  return false unless arguments.is_a?(Args)
796
- parts = arguments.parts
797
797
 
798
+ parts = arguments.parts
798
799
  if parts.last.is_a?(ArgBlock)
799
800
  # If the last argument is a block, then we can't put a trailing comma
800
801
  # after it without resulting in a syntax error.
@@ -1188,8 +1189,11 @@ module SyntaxTree
1188
1189
  end
1189
1190
 
1190
1191
  def format(q)
1191
- if lbracket.comments.empty? && contents && contents.comments.empty? &&
1192
- contents.parts.length > 1
1192
+ lbracket = self.lbracket
1193
+ contents = self.contents
1194
+
1195
+ if lbracket.is_a?(LBracket) && lbracket.comments.empty? && contents &&
1196
+ contents.comments.empty? && contents.parts.length > 1
1193
1197
  if qwords?
1194
1198
  QWordsFormatter.new(contents).format(q)
1195
1199
  return
@@ -2091,6 +2095,7 @@ module SyntaxTree
2091
2095
  end
2092
2096
 
2093
2097
  def format(q)
2098
+ left = self.left
2094
2099
  power = operator == :**
2095
2100
 
2096
2101
  q.group do
@@ -2307,6 +2312,8 @@ module SyntaxTree
2307
2312
  end
2308
2313
 
2309
2314
  def bind(parser, start_char, start_column, end_char, end_column)
2315
+ rescue_clause = self.rescue_clause
2316
+
2310
2317
  @location =
2311
2318
  Location.new(
2312
2319
  start_line: location.start_line,
@@ -2330,6 +2337,7 @@ module SyntaxTree
2330
2337
  # Next we're going to determine the rescue clause if there is one
2331
2338
  if rescue_clause
2332
2339
  consequent = else_clause || ensure_clause
2340
+
2333
2341
  rescue_clause.bind_end(
2334
2342
  consequent ? consequent.location.start_char : end_char,
2335
2343
  consequent ? consequent.location.start_column : end_column
@@ -2735,7 +2743,7 @@ module SyntaxTree
2735
2743
  children << receiver
2736
2744
  end
2737
2745
  when MethodAddBlock
2738
- if receiver.call.is_a?(CallNode) && !receiver.call.receiver.nil?
2746
+ if (call = receiver.call).is_a?(CallNode) && !call.receiver.nil?
2739
2747
  children << receiver
2740
2748
  else
2741
2749
  break
@@ -2744,8 +2752,8 @@ module SyntaxTree
2744
2752
  break
2745
2753
  end
2746
2754
  when MethodAddBlock
2747
- if child.call.is_a?(CallNode) && !child.call.receiver.nil?
2748
- children << child.call
2755
+ if (call = child.call).is_a?(CallNode) && !call.receiver.nil?
2756
+ children << call
2749
2757
  else
2750
2758
  break
2751
2759
  end
@@ -2767,8 +2775,8 @@ module SyntaxTree
2767
2775
  # of just Statements nodes.
2768
2776
  parent = parents[3] if parent.is_a?(BlockNode) && parent.keywords?
2769
2777
 
2770
- if parent.is_a?(MethodAddBlock) && parent.call.is_a?(CallNode) &&
2771
- parent.call.message.value == "sig"
2778
+ if parent.is_a?(MethodAddBlock) &&
2779
+ (call = parent.call).is_a?(CallNode) && call.message.value == "sig"
2772
2780
  threshold = 2
2773
2781
  end
2774
2782
  end
@@ -2813,10 +2821,10 @@ module SyntaxTree
2813
2821
 
2814
2822
  while (child = children.pop)
2815
2823
  if child.is_a?(CallNode)
2816
- if child.receiver.is_a?(CallNode) &&
2817
- (child.receiver.message != :call) &&
2818
- (child.receiver.message.value == "where") &&
2819
- (child.message.value == "not")
2824
+ if (receiver = child.receiver).is_a?(CallNode) &&
2825
+ (receiver.message != :call) &&
2826
+ (receiver.message.value == "where") &&
2827
+ (message.value == "not")
2820
2828
  # This is very specialized behavior wherein we group
2821
2829
  # .where.not calls together because it looks better. For more
2822
2830
  # information, see
@@ -2872,7 +2880,8 @@ module SyntaxTree
2872
2880
  when CallNode
2873
2881
  !node.receiver.nil?
2874
2882
  when MethodAddBlock
2875
- node.call.is_a?(CallNode) && !node.call.receiver.nil?
2883
+ call = node.call
2884
+ call.is_a?(CallNode) && !call.receiver.nil?
2876
2885
  else
2877
2886
  false
2878
2887
  end
@@ -3629,6 +3638,10 @@ module SyntaxTree
3629
3638
  end
3630
3639
 
3631
3640
  def format(q)
3641
+ message = self.message
3642
+ arguments = self.arguments
3643
+ block = self.block
3644
+
3632
3645
  q.group do
3633
3646
  doc =
3634
3647
  q.nest(0) do
@@ -3637,7 +3650,7 @@ module SyntaxTree
3637
3650
  # If there are leading comments on the message then we know we have
3638
3651
  # a newline in the source that is forcing these things apart. In
3639
3652
  # this case we will have to use a trailing operator.
3640
- if message.comments.any?(&:leading?)
3653
+ if message != :call && message.comments.any?(&:leading?)
3641
3654
  q.format(CallOperatorFormatter.new(operator), stackable: false)
3642
3655
  q.indent do
3643
3656
  q.breakable_empty
@@ -4153,6 +4166,9 @@ module SyntaxTree
4153
4166
  end
4154
4167
 
4155
4168
  def format(q)
4169
+ params = self.params
4170
+ bodystmt = self.bodystmt
4171
+
4156
4172
  q.group do
4157
4173
  q.group do
4158
4174
  q.text("def")
@@ -4209,6 +4225,8 @@ module SyntaxTree
4209
4225
  end
4210
4226
 
4211
4227
  def arity
4228
+ params = self.params
4229
+
4212
4230
  case params
4213
4231
  when Params
4214
4232
  params.arity
@@ -5293,6 +5311,7 @@ module SyntaxTree
5293
5311
  end
5294
5312
 
5295
5313
  def child_nodes
5314
+ operator = self.operator
5296
5315
  [parent, (operator if operator != :"::"), name]
5297
5316
  end
5298
5317
 
@@ -5674,7 +5693,7 @@ module SyntaxTree
5674
5693
  end
5675
5694
 
5676
5695
  def child_nodes
5677
- [lbrace] + assocs
5696
+ [lbrace].concat(assocs)
5678
5697
  end
5679
5698
 
5680
5699
  def copy(lbrace: nil, assocs: nil, location: nil)
@@ -5766,7 +5785,7 @@ module SyntaxTree
5766
5785
  # [Array[ Comment | EmbDoc ]] the comments attached to this node
5767
5786
  attr_reader :comments
5768
5787
 
5769
- def initialize(beginning:, ending: nil, dedent: 0, parts: [], location:)
5788
+ def initialize(beginning:, location:, ending: nil, dedent: 0, parts: [])
5770
5789
  @beginning = beginning
5771
5790
  @ending = ending
5772
5791
  @dedent = dedent
@@ -6134,6 +6153,8 @@ module SyntaxTree
6134
6153
  private
6135
6154
 
6136
6155
  def format_contents(q, parts, nested)
6156
+ keyword_rest = self.keyword_rest
6157
+
6137
6158
  q.group { q.seplist(parts) { |part| q.format(part, stackable: false) } }
6138
6159
 
6139
6160
  # If there isn't a constant, and there's a blank keyword_rest, then we
@@ -6763,10 +6784,13 @@ module SyntaxTree
6763
6784
 
6764
6785
  def format(q)
6765
6786
  keyword = "in "
6787
+ pattern = self.pattern
6788
+ consequent = self.consequent
6766
6789
 
6767
6790
  q.group do
6768
6791
  q.text(keyword)
6769
6792
  q.nest(keyword.length) { q.format(pattern) }
6793
+ q.text(" then") if pattern.is_a?(RangeNode) && pattern.right.nil?
6770
6794
 
6771
6795
  unless statements.empty?
6772
6796
  q.indent do
@@ -7164,6 +7188,8 @@ module SyntaxTree
7164
7188
  end
7165
7189
 
7166
7190
  def format(q)
7191
+ params = self.params
7192
+
7167
7193
  q.text("->")
7168
7194
  q.group do
7169
7195
  if params.is_a?(Paren)
@@ -7642,7 +7668,7 @@ module SyntaxTree
7642
7668
  # [Array[ Comment | EmbDoc ]] the comments attached to this node
7643
7669
  attr_reader :comments
7644
7670
 
7645
- def initialize(parts:, comma: false, location:)
7671
+ def initialize(parts:, location:, comma: false)
7646
7672
  @parts = parts
7647
7673
  @comma = comma
7648
7674
  @location = location
@@ -7703,7 +7729,7 @@ module SyntaxTree
7703
7729
  # [Array[ Comment | EmbDoc ]] the comments attached to this node
7704
7730
  attr_reader :comments
7705
7731
 
7706
- def initialize(contents:, comma: false, location:)
7732
+ def initialize(contents:, location:, comma: false)
7707
7733
  @contents = contents
7708
7734
  @comma = comma
7709
7735
  @location = location
@@ -8286,14 +8312,14 @@ module SyntaxTree
8286
8312
  attr_reader :comments
8287
8313
 
8288
8314
  def initialize(
8315
+ location:,
8289
8316
  requireds: [],
8290
8317
  optionals: [],
8291
8318
  rest: nil,
8292
8319
  posts: [],
8293
8320
  keywords: [],
8294
8321
  keyword_rest: nil,
8295
- block: nil,
8296
- location:
8322
+ block: nil
8297
8323
  )
8298
8324
  @requireds = requireds
8299
8325
  @optionals = optionals
@@ -8320,6 +8346,8 @@ module SyntaxTree
8320
8346
  end
8321
8347
 
8322
8348
  def child_nodes
8349
+ keyword_rest = self.keyword_rest
8350
+
8323
8351
  [
8324
8352
  *requireds,
8325
8353
  *optionals.flatten(1),
@@ -8374,16 +8402,19 @@ module SyntaxTree
8374
8402
  end
8375
8403
 
8376
8404
  def format(q)
8405
+ rest = self.rest
8406
+ keyword_rest = self.keyword_rest
8407
+
8377
8408
  parts = [
8378
8409
  *requireds,
8379
8410
  *optionals.map { |(name, value)| OptionalFormatter.new(name, value) }
8380
8411
  ]
8381
8412
 
8382
8413
  parts << rest if rest && !rest.is_a?(ExcessedComma)
8383
- parts += [
8384
- *posts,
8385
- *keywords.map { |(name, value)| KeywordFormatter.new(name, value) }
8386
- ]
8414
+ parts.concat(posts)
8415
+ parts.concat(
8416
+ keywords.map { |(name, value)| KeywordFormatter.new(name, value) }
8417
+ )
8387
8418
 
8388
8419
  parts << KeywordRestFormatter.new(keyword_rest) if keyword_rest
8389
8420
  parts << block if block
@@ -8510,6 +8541,8 @@ module SyntaxTree
8510
8541
  end
8511
8542
 
8512
8543
  def format(q)
8544
+ contents = self.contents
8545
+
8513
8546
  q.group do
8514
8547
  q.format(lparen)
8515
8548
 
@@ -9424,11 +9457,11 @@ module SyntaxTree
9424
9457
  end_column: end_column
9425
9458
  )
9426
9459
 
9427
- if consequent
9428
- consequent.bind_end(end_char, end_column)
9460
+ if (next_node = consequent)
9461
+ next_node.bind_end(end_char, end_column)
9429
9462
  statements.bind_end(
9430
- consequent.location.start_char,
9431
- consequent.location.start_column
9463
+ next_node.location.start_char,
9464
+ next_node.location.start_column
9432
9465
  )
9433
9466
  else
9434
9467
  statements.bind_end(end_char, end_column)
@@ -9871,8 +9904,8 @@ module SyntaxTree
9871
9904
  end_column: end_column
9872
9905
  )
9873
9906
 
9874
- if body[0].is_a?(VoidStmt)
9875
- location = body[0].location
9907
+ if (void_stmt = body[0]).is_a?(VoidStmt)
9908
+ location = void_stmt.location
9876
9909
  location =
9877
9910
  Location.new(
9878
9911
  start_line: location.start_line,
@@ -10351,7 +10384,7 @@ module SyntaxTree
10351
10384
  opening_quote, closing_quote =
10352
10385
  if !Quotes.locked?(self, q.quote)
10353
10386
  [q.quote, q.quote]
10354
- elsif quote.start_with?("%")
10387
+ elsif quote&.start_with?("%")
10355
10388
  [quote, Quotes.matching(quote[/%[qQ]?(.)/, 1])]
10356
10389
  else
10357
10390
  [quote, quote]
@@ -11520,7 +11553,7 @@ module SyntaxTree
11520
11553
  end
11521
11554
 
11522
11555
  def child_nodes
11523
- [value]
11556
+ value == :nil ? [] : [value]
11524
11557
  end
11525
11558
 
11526
11559
  def copy(value: nil, location: nil)
@@ -2132,13 +2132,20 @@ module SyntaxTree
2132
2132
  ending = consequent || consume_keyword(:end)
2133
2133
 
2134
2134
  statements_start = pattern
2135
- if (token = find_keyword(:then))
2135
+ if (token = find_keyword_between(:then, pattern, statements))
2136
2136
  tokens.delete(token)
2137
2137
  statements_start = token
2138
2138
  end
2139
2139
 
2140
2140
  start_char =
2141
2141
  find_next_statement_start((token || statements_start).location.end_char)
2142
+
2143
+ # Ripper ignores parentheses on patterns, so we need to do the same in
2144
+ # order to attach comments correctly to the pattern.
2145
+ if source[start_char] == ")"
2146
+ start_char = find_next_statement_start(start_char + 1)
2147
+ end
2148
+
2142
2149
  statements.bind(
2143
2150
  self,
2144
2151
  start_char,
@@ -2391,8 +2398,14 @@ module SyntaxTree
2391
2398
  }
2392
2399
  }
2393
2400
 
2401
+ parent_line = lineno - 1
2402
+ parent_column =
2403
+ consume_token(Semicolon).location.start_column - tokens[index][0][1]
2404
+
2394
2405
  tokens[(index + 1)..].each_with_object([]) do |token, locals|
2395
2406
  (lineno, column), type, value, = token
2407
+ column += parent_column if lineno == 1
2408
+ lineno += parent_line
2396
2409
 
2397
2410
  # Make the state transition for the parser. If there isn't a transition
2398
2411
  # from the current state to a new state for this type, then we're in a
@@ -138,12 +138,13 @@ module SyntaxTree
138
138
  # as a placeholder for collecting all of the various places that nodes are
139
139
  # used.
140
140
  class Node
141
- attr_reader :name, :comment, :attributes
141
+ attr_reader :name, :comment, :attributes, :visitor_method
142
142
 
143
- def initialize(name, comment, attributes)
143
+ def initialize(name, comment, attributes, visitor_method)
144
144
  @name = name
145
145
  @comment = comment
146
146
  @attributes = attributes
147
+ @visitor_method = visitor_method
147
148
  end
148
149
  end
149
150
 
@@ -176,16 +177,18 @@ module SyntaxTree
176
177
  program =
177
178
  SyntaxTree.parse(SyntaxTree.read(File.expand_path("node.rb", __dir__)))
178
179
 
179
- main_statements = program.statements.body.last.bodystmt.statements.body
180
+ program_statements = program.statements
181
+ main_statements = program_statements.body.last.bodystmt.statements.body
180
182
  main_statements.each_with_index do |main_statement, main_statement_index|
181
183
  # Ensure we are only looking at class declarations.
182
184
  next unless main_statement.is_a?(SyntaxTree::ClassDeclaration)
183
185
 
184
186
  # Ensure we're looking at class declarations with superclasses.
185
- next unless main_statement.superclass.is_a?(SyntaxTree::VarRef)
187
+ superclass = main_statement.superclass
188
+ next unless superclass.is_a?(SyntaxTree::VarRef)
186
189
 
187
190
  # Ensure we're looking at class declarations that inherit from Node.
188
- next unless main_statement.superclass.value.value == "Node"
191
+ next unless superclass.value.value == "Node"
189
192
 
190
193
  # All child nodes inherit the location attr_reader from Node, so we'll add
191
194
  # that to the list of attributes first.
@@ -194,6 +197,10 @@ module SyntaxTree
194
197
  Attribute.new(:location, "[Location] the location of this node")
195
198
  }
196
199
 
200
+ # This is the name of the method tha gets called on the given visitor when
201
+ # the accept method is called on this node.
202
+ visitor_method = nil
203
+
197
204
  statements = main_statement.bodystmt.statements.body
198
205
  statements.each_with_index do |statement, statement_index|
199
206
  case statement
@@ -223,16 +230,25 @@ module SyntaxTree
223
230
  end
224
231
 
225
232
  attributes[attribute.name] = attribute
233
+ when SyntaxTree::DefNode
234
+ if statement.name.value == "accept"
235
+ call_node = statement.bodystmt.statements.body.first
236
+ visitor_method = call_node.message.value.to_sym
237
+ end
226
238
  end
227
239
  end
228
240
 
241
+ # If we never found a visitor method, then we have an error.
242
+ raise if visitor_method.nil?
243
+
229
244
  # Finally, set it up in the hash of nodes so that we can use it later.
230
245
  comments = parse_comments(main_statements, main_statement_index)
231
246
  node =
232
247
  Node.new(
233
248
  main_statement.constant.constant.value.to_sym,
234
249
  "#{comments.join("\n")}\n",
235
- attributes
250
+ attributes,
251
+ visitor_method
236
252
  )
237
253
 
238
254
  @nodes[node.name] = node
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SyntaxTree
4
- VERSION = "6.0.1"
4
+ VERSION = "6.1.0"
5
5
  end
@@ -189,6 +189,15 @@ module SyntaxTree
189
189
  super
190
190
  end
191
191
 
192
+ def visit_block_var(node)
193
+ node.locals.each do |local|
194
+ current_scope.add_local_definition(local, :variable)
195
+ end
196
+
197
+ super
198
+ end
199
+ alias visit_lambda_var visit_block_var
200
+
192
201
  # Visit for keeping track of local variable definitions
193
202
  def visit_var_field(node)
194
203
  value = node.value
@@ -217,11 +226,72 @@ module SyntaxTree
217
226
  super
218
227
  end
219
228
 
229
+ # When using regex named capture groups, vcalls might actually be a variable
230
+ def visit_vcall(node)
231
+ value = node.value
232
+ definition = current_scope.find_local(value.value)
233
+ current_scope.add_local_usage(value, definition.type) if definition
234
+
235
+ super
236
+ end
237
+
238
+ # Visit for capturing local variables defined in regex named capture groups
239
+ def visit_binary(node)
240
+ if node.operator == :=~
241
+ left = node.left
242
+
243
+ if left.is_a?(RegexpLiteral) && left.parts.length == 1 &&
244
+ left.parts.first.is_a?(TStringContent)
245
+ content = left.parts.first
246
+
247
+ value = content.value
248
+ location = content.location
249
+ start_line = location.start_line
250
+
251
+ Regexp
252
+ .new(value, Regexp::FIXEDENCODING)
253
+ .names
254
+ .each do |name|
255
+ offset = value.index(/\(\?<#{Regexp.escape(name)}>/)
256
+ line = start_line + value[0...offset].count("\n")
257
+
258
+ # We need to add 3 to account for these three characters
259
+ # prefixing a named capture (?<
260
+ column = location.start_column + offset + 3
261
+ if value[0...offset].include?("\n")
262
+ column =
263
+ value[0...offset].length - value[0...offset].rindex("\n") +
264
+ 3 - 1
265
+ end
266
+
267
+ ident_location =
268
+ Location.new(
269
+ start_line: line,
270
+ start_char: location.start_char + offset,
271
+ start_column: column,
272
+ end_line: line,
273
+ end_char: location.start_char + offset + name.length,
274
+ end_column: column + name.length
275
+ )
276
+
277
+ identifier = Ident.new(value: name, location: ident_location)
278
+ current_scope.add_local_definition(identifier, :variable)
279
+ end
280
+ end
281
+ end
282
+
283
+ super
284
+ end
285
+
220
286
  private
221
287
 
222
288
  def add_argument_definitions(list)
223
289
  list.each do |param|
224
- if param.is_a?(SyntaxTree::MLHSParen)
290
+ case param
291
+ when ArgStar
292
+ value = param.value
293
+ current_scope.add_local_definition(value, :argument) if value
294
+ when MLHSParen
225
295
  add_argument_definitions(param.contents.parts)
226
296
  else
227
297
  current_scope.add_local_definition(param, :argument)
@@ -875,8 +875,7 @@ module SyntaxTree
875
875
  when Ident
876
876
  iseq.putobject("local-variable")
877
877
  when IVar
878
- iseq.putnil
879
- iseq.defined(Defined::TYPE_IVAR, name, "instance-variable")
878
+ iseq.definedivar(name, iseq.inline_storage, "instance-variable")
880
879
  when Kw
881
880
  case name
882
881
  when :false
@@ -50,7 +50,7 @@ module SyntaxTree
50
50
  @tail_node = nil
51
51
  end
52
52
 
53
- def each
53
+ def each(&_blk)
54
54
  return to_enum(__method__) unless block_given?
55
55
  each_node { |node| yield node.value }
56
56
  end
@@ -673,12 +673,21 @@ module SyntaxTree
673
673
  push(ConcatStrings.new(number))
674
674
  end
675
675
 
676
+ def defineclass(name, class_iseq, flags)
677
+ push(DefineClass.new(name, class_iseq, flags))
678
+ end
679
+
676
680
  def defined(type, name, message)
677
681
  push(Defined.new(type, name, message))
678
682
  end
679
683
 
680
- def defineclass(name, class_iseq, flags)
681
- push(DefineClass.new(name, class_iseq, flags))
684
+ def definedivar(name, cache, message)
685
+ if RUBY_VERSION < "3.3"
686
+ push(PutNil.new)
687
+ push(Defined.new(Defined::TYPE_IVAR, name, message))
688
+ else
689
+ push(DefinedIVar.new(name, cache, message))
690
+ end
682
691
  end
683
692
 
684
693
  def definemethod(name, method_iseq)
@@ -1058,6 +1067,8 @@ module SyntaxTree
1058
1067
  iseq.defineclass(opnds[0], from(opnds[1], options, iseq), opnds[2])
1059
1068
  when :defined
1060
1069
  iseq.defined(opnds[0], opnds[1], opnds[2])
1070
+ when :definedivar
1071
+ iseq.definedivar(opnds[0], opnds[1], opnds[2])
1061
1072
  when :definemethod
1062
1073
  iseq.definemethod(opnds[0], from(opnds[1], options, iseq))
1063
1074
  when :definesmethod
@@ -994,6 +994,64 @@ module SyntaxTree
994
994
  end
995
995
  end
996
996
 
997
+ # ### Summary
998
+ #
999
+ # `definedivar` checks if an instance variable is defined. It is a
1000
+ # specialization of the `defined` instruction. It accepts three arguments:
1001
+ # the name of the instance variable, an inline cache, and the string that
1002
+ # should be pushed onto the stack in the event that the instance variable
1003
+ # is defined.
1004
+ #
1005
+ # ### Usage
1006
+ #
1007
+ # ~~~ruby
1008
+ # defined?(@value)
1009
+ # ~~~
1010
+ #
1011
+ class DefinedIVar < Instruction
1012
+ attr_reader :name, :cache, :message
1013
+
1014
+ def initialize(name, cache, message)
1015
+ @name = name
1016
+ @cache = cache
1017
+ @message = message
1018
+ end
1019
+
1020
+ def disasm(fmt)
1021
+ fmt.instruction(
1022
+ "definedivar",
1023
+ [fmt.object(name), fmt.inline_storage(cache), fmt.object(message)]
1024
+ )
1025
+ end
1026
+
1027
+ def to_a(_iseq)
1028
+ [:definedivar, name, cache, message]
1029
+ end
1030
+
1031
+ def deconstruct_keys(_keys)
1032
+ { name: name, cache: cache, message: message }
1033
+ end
1034
+
1035
+ def ==(other)
1036
+ other.is_a?(DefinedIVar) && other.name == name &&
1037
+ other.cache == cache && other.message == message
1038
+ end
1039
+
1040
+ def length
1041
+ 4
1042
+ end
1043
+
1044
+ def pushes
1045
+ 1
1046
+ end
1047
+
1048
+ def call(vm)
1049
+ result = (message if vm.frame._self.instance_variable_defined?(name))
1050
+
1051
+ vm.push(result)
1052
+ end
1053
+ end
1054
+
997
1055
  # ### Summary
998
1056
  #
999
1057
  # `definemethod` defines a method on the class of the current value of
data/lib/syntax_tree.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "prettier_print"
4
+ require "pp"
4
5
  require "ripper"
5
6
 
6
7
  require_relative "syntax_tree/node"