rubinius-ast 1.0.1
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 +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE +25 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/lib/rubinius/ast/constants.rb +324 -0
- data/lib/rubinius/ast/control_flow.rb +698 -0
- data/lib/rubinius/ast/data.rb +30 -0
- data/lib/rubinius/ast/definitions.rb +1134 -0
- data/lib/rubinius/ast/encoding.rb +26 -0
- data/lib/rubinius/ast/exceptions.rb +545 -0
- data/lib/rubinius/ast/file.rb +18 -0
- data/lib/rubinius/ast/grapher.rb +89 -0
- data/lib/rubinius/ast/literals.rb +555 -0
- data/lib/rubinius/ast/node.rb +389 -0
- data/lib/rubinius/ast/operators.rb +394 -0
- data/lib/rubinius/ast/self.rb +25 -0
- data/lib/rubinius/ast/sends.rb +1028 -0
- data/lib/rubinius/ast/transforms.rb +371 -0
- data/lib/rubinius/ast/values.rb +182 -0
- data/lib/rubinius/ast/variables.rb +842 -0
- data/lib/rubinius/ast/version.rb +5 -0
- data/lib/rubinius/ast.rb +18 -0
- data/rubinius-ast.gemspec +22 -0
- metadata +96 -0
@@ -0,0 +1,25 @@
|
|
1
|
+
# -*- encoding: us-ascii -*-
|
2
|
+
|
3
|
+
module Rubinius::ToolSet.current::TS
|
4
|
+
module AST
|
5
|
+
class Self < Node
|
6
|
+
def bytecode(g)
|
7
|
+
pos(g)
|
8
|
+
|
9
|
+
g.push :self
|
10
|
+
end
|
11
|
+
|
12
|
+
def defined(g)
|
13
|
+
g.push_literal "self"
|
14
|
+
end
|
15
|
+
|
16
|
+
def value_defined(g, f)
|
17
|
+
g.push :self
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_sexp
|
21
|
+
[:self]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,1028 @@
|
|
1
|
+
# -*- encoding: us-ascii -*-
|
2
|
+
|
3
|
+
module Rubinius::ToolSet.current::TS
|
4
|
+
module AST
|
5
|
+
class Send < Node
|
6
|
+
attr_accessor :receiver, :name, :privately, :block, :variable, :vcall_style
|
7
|
+
|
8
|
+
def initialize(line, receiver, name, privately=false, vcall_style=false)
|
9
|
+
@line = line
|
10
|
+
@receiver = receiver
|
11
|
+
@name = name
|
12
|
+
@privately = privately
|
13
|
+
@block = nil
|
14
|
+
@vcall_style = vcall_style
|
15
|
+
end
|
16
|
+
|
17
|
+
def check_local_reference(g)
|
18
|
+
if @receiver.kind_of? Self and g.state.check_for_locals
|
19
|
+
g.state.scope.search_local(@name)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def bytecode(g)
|
24
|
+
pos(g)
|
25
|
+
|
26
|
+
if @vcall_style and reference = check_local_reference(g)
|
27
|
+
return reference.get_bytecode(g)
|
28
|
+
end
|
29
|
+
|
30
|
+
@receiver.bytecode(g)
|
31
|
+
|
32
|
+
if @block
|
33
|
+
@block.bytecode(g)
|
34
|
+
g.send_with_block @name, 0, @privately
|
35
|
+
elsif @vcall_style
|
36
|
+
g.send_vcall @name
|
37
|
+
else
|
38
|
+
g.send @name, 0, @privately
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def value_defined(g, f)
|
43
|
+
# Save the current exception into a stack local
|
44
|
+
g.push_exception_state
|
45
|
+
outer_exc_state = g.new_stack_local
|
46
|
+
g.set_stack_local outer_exc_state
|
47
|
+
g.pop
|
48
|
+
|
49
|
+
ok = g.new_label
|
50
|
+
ex = g.new_label
|
51
|
+
g.setup_unwind ex, RescueType
|
52
|
+
|
53
|
+
bytecode(g)
|
54
|
+
|
55
|
+
g.pop_unwind
|
56
|
+
g.goto ok
|
57
|
+
|
58
|
+
ex.set!
|
59
|
+
g.clear_exception
|
60
|
+
g.push_stack_local outer_exc_state
|
61
|
+
g.restore_exception_state
|
62
|
+
g.goto f
|
63
|
+
|
64
|
+
ok.set!
|
65
|
+
end
|
66
|
+
|
67
|
+
def defined(g)
|
68
|
+
if @vcall_style and check_local_reference(g)
|
69
|
+
g.push_literal "local-variable"
|
70
|
+
return
|
71
|
+
end
|
72
|
+
|
73
|
+
f = g.new_label
|
74
|
+
done = g.new_label
|
75
|
+
|
76
|
+
@receiver.value_defined(g, f)
|
77
|
+
|
78
|
+
g.push_literal @name
|
79
|
+
|
80
|
+
if @vcall_style or @privately
|
81
|
+
g.push :true
|
82
|
+
g.send :__respond_to_p__, 2
|
83
|
+
else
|
84
|
+
g.push_self
|
85
|
+
g.invoke_primitive :vm_check_callable, 3
|
86
|
+
end
|
87
|
+
g.gif f
|
88
|
+
g.push_literal "method"
|
89
|
+
g.goto done
|
90
|
+
|
91
|
+
f.set!
|
92
|
+
g.push :nil
|
93
|
+
|
94
|
+
done.set!
|
95
|
+
end
|
96
|
+
|
97
|
+
def sexp_name
|
98
|
+
:call
|
99
|
+
end
|
100
|
+
|
101
|
+
def receiver_sexp
|
102
|
+
@privately ? nil : @receiver.to_sexp
|
103
|
+
end
|
104
|
+
|
105
|
+
def arguments_sexp
|
106
|
+
return nil if @vcall_style
|
107
|
+
|
108
|
+
sexp = [:arglist]
|
109
|
+
sexp << @block.to_sexp if @block.kind_of? BlockPass
|
110
|
+
sexp
|
111
|
+
end
|
112
|
+
|
113
|
+
def to_sexp
|
114
|
+
sexp = [sexp_name, receiver_sexp, @name, arguments_sexp]
|
115
|
+
case @block
|
116
|
+
when For
|
117
|
+
@block.to_sexp.insert 1, @receiver.to_sexp
|
118
|
+
when Iter
|
119
|
+
@block.to_sexp.insert 1, sexp
|
120
|
+
else
|
121
|
+
sexp
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
class SendWithArguments < Send
|
127
|
+
attr_accessor :arguments
|
128
|
+
|
129
|
+
def initialize(line, receiver, name, arguments, privately=false)
|
130
|
+
super line, receiver, name, privately
|
131
|
+
@block = nil
|
132
|
+
@arguments = ActualArguments.new line, arguments
|
133
|
+
end
|
134
|
+
|
135
|
+
def bytecode(g)
|
136
|
+
@receiver.bytecode(g)
|
137
|
+
@arguments.bytecode(g)
|
138
|
+
|
139
|
+
pos(g)
|
140
|
+
|
141
|
+
if @arguments.splat?
|
142
|
+
@block ? @block.bytecode(g) : g.push(:nil)
|
143
|
+
g.send_with_splat @name, @arguments.size, @privately, false
|
144
|
+
elsif @block
|
145
|
+
@block.bytecode(g)
|
146
|
+
g.send_with_block @name, @arguments.size, @privately
|
147
|
+
else
|
148
|
+
g.send @name, @arguments.size, @privately
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def arguments_sexp(name=:arglist)
|
153
|
+
sexp = [name] + @arguments.to_sexp
|
154
|
+
sexp << @block.to_sexp if @block
|
155
|
+
sexp
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
class AttributeAssignment < SendWithArguments
|
160
|
+
def initialize(line, receiver, name, arguments)
|
161
|
+
@line = line
|
162
|
+
|
163
|
+
@receiver = receiver
|
164
|
+
@privately = receiver.kind_of?(Self) ? true : false
|
165
|
+
|
166
|
+
@name = :"#{name}="
|
167
|
+
|
168
|
+
@arguments = ActualArguments.new line, arguments
|
169
|
+
end
|
170
|
+
|
171
|
+
def bytecode(g)
|
172
|
+
@receiver.bytecode(g)
|
173
|
+
if g.state.masgn?
|
174
|
+
g.swap
|
175
|
+
g.send @name, 1, @privately
|
176
|
+
else
|
177
|
+
@arguments.bytecode(g)
|
178
|
+
g.dup
|
179
|
+
|
180
|
+
if @arguments.splat?
|
181
|
+
g.move_down @arguments.size + 2
|
182
|
+
g.swap
|
183
|
+
g.push :nil
|
184
|
+
g.send_with_splat @name, @arguments.size, @privately, true
|
185
|
+
else
|
186
|
+
g.move_down @arguments.size + 1
|
187
|
+
g.send @name, @arguments.size, @privately
|
188
|
+
end
|
189
|
+
|
190
|
+
g.pop
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
def sexp_name
|
195
|
+
:attrasgn
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
class ElementAssignment < SendWithArguments
|
200
|
+
def initialize(line, receiver, arguments)
|
201
|
+
@line = line
|
202
|
+
|
203
|
+
@receiver = receiver
|
204
|
+
@privately = receiver.kind_of?(Self) ? true : false
|
205
|
+
|
206
|
+
@name = :[]=
|
207
|
+
|
208
|
+
case arguments
|
209
|
+
when PushArgs
|
210
|
+
@arguments = PushActualArguments.new arguments
|
211
|
+
else
|
212
|
+
@arguments = ActualArguments.new line, arguments
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
def masgn_bytecode(g)
|
217
|
+
@receiver.bytecode(g)
|
218
|
+
g.swap
|
219
|
+
@arguments.masgn_bytecode(g)
|
220
|
+
g.send @name, @arguments.size + 1, @privately
|
221
|
+
# TODO: splat
|
222
|
+
end
|
223
|
+
|
224
|
+
def bytecode(g)
|
225
|
+
return masgn_bytecode(g) if g.state.masgn?
|
226
|
+
|
227
|
+
@receiver.bytecode(g)
|
228
|
+
@arguments.bytecode(g)
|
229
|
+
g.dup
|
230
|
+
|
231
|
+
if @arguments.splat?
|
232
|
+
g.move_down @arguments.size + 2
|
233
|
+
g.swap
|
234
|
+
g.push :nil
|
235
|
+
g.send_with_splat @name, @arguments.size, @privately, true
|
236
|
+
else
|
237
|
+
g.move_down @arguments.size + 1
|
238
|
+
g.send @name, @arguments.size, @privately
|
239
|
+
end
|
240
|
+
|
241
|
+
g.pop
|
242
|
+
end
|
243
|
+
|
244
|
+
def sexp_name
|
245
|
+
:attrasgn
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
class PreExe < Node
|
250
|
+
attr_accessor :block
|
251
|
+
|
252
|
+
def initialize(line)
|
253
|
+
@line = line
|
254
|
+
end
|
255
|
+
|
256
|
+
def pre_bytecode(g)
|
257
|
+
pos(g)
|
258
|
+
|
259
|
+
g.push_state ClosedScope.new(@line)
|
260
|
+
g.state.push_name :BEGIN
|
261
|
+
|
262
|
+
g.push_literal Compiler::Runtime
|
263
|
+
@block.bytecode(g)
|
264
|
+
g.send_with_block :pre_exe, 0, false
|
265
|
+
|
266
|
+
g.state.pop_name
|
267
|
+
g.pop_state
|
268
|
+
end
|
269
|
+
|
270
|
+
def to_sexp
|
271
|
+
end
|
272
|
+
|
273
|
+
def pre_sexp
|
274
|
+
@block.to_sexp.insert 1, :pre_exe
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
class PreExe19 < PreExe
|
279
|
+
def pre_bytecode(g)
|
280
|
+
pos(g)
|
281
|
+
|
282
|
+
@block.body.bytecode(g)
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
class PushActualArguments
|
287
|
+
def initialize(pa)
|
288
|
+
@arguments = pa.arguments
|
289
|
+
@value = pa.value
|
290
|
+
end
|
291
|
+
|
292
|
+
def size
|
293
|
+
splat? ? 1 : @arguments.size + 1
|
294
|
+
end
|
295
|
+
|
296
|
+
def splat?
|
297
|
+
@arguments.splat?
|
298
|
+
end
|
299
|
+
|
300
|
+
def bytecode(g)
|
301
|
+
@arguments.bytecode(g)
|
302
|
+
@value.bytecode(g)
|
303
|
+
end
|
304
|
+
|
305
|
+
def to_sexp
|
306
|
+
[@arguments.to_sexp, @value.to_sexp]
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
class BlockPass < Node
|
311
|
+
attr_accessor :body
|
312
|
+
|
313
|
+
def initialize(line, body)
|
314
|
+
@line = line
|
315
|
+
@body = body
|
316
|
+
end
|
317
|
+
|
318
|
+
def convert(g)
|
319
|
+
nil_block = g.new_label
|
320
|
+
g.dup
|
321
|
+
g.is_nil
|
322
|
+
g.git nil_block
|
323
|
+
|
324
|
+
g.push_cpath_top
|
325
|
+
g.find_const :Proc
|
326
|
+
|
327
|
+
g.swap
|
328
|
+
g.send :__from_block__, 1
|
329
|
+
|
330
|
+
nil_block.set!
|
331
|
+
end
|
332
|
+
|
333
|
+
def bytecode(g)
|
334
|
+
@body.bytecode(g)
|
335
|
+
convert(g)
|
336
|
+
end
|
337
|
+
|
338
|
+
def assignment_bytecode(g)
|
339
|
+
g.push_block_arg
|
340
|
+
convert(g)
|
341
|
+
@body.bytecode(g)
|
342
|
+
end
|
343
|
+
|
344
|
+
def to_sexp
|
345
|
+
[:block_pass, @body.to_sexp]
|
346
|
+
end
|
347
|
+
end
|
348
|
+
|
349
|
+
class BlockPass19 < BlockPass
|
350
|
+
attr_accessor :arguments
|
351
|
+
|
352
|
+
def initialize(line, arguments, body)
|
353
|
+
super(line, body)
|
354
|
+
@arguments = arguments
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
358
|
+
class CollectSplat < Node
|
359
|
+
def initialize(line, *parts)
|
360
|
+
@line = line
|
361
|
+
@splat = parts.shift
|
362
|
+
@last = parts.pop
|
363
|
+
@array = parts
|
364
|
+
end
|
365
|
+
|
366
|
+
def bytecode(g)
|
367
|
+
@splat.bytecode(g)
|
368
|
+
g.cast_array
|
369
|
+
|
370
|
+
@array.each do |x|
|
371
|
+
x.bytecode(g)
|
372
|
+
g.cast_array
|
373
|
+
g.send :+, 1
|
374
|
+
end
|
375
|
+
|
376
|
+
return unless @last
|
377
|
+
|
378
|
+
not_hash = g.new_label
|
379
|
+
done = g.new_label
|
380
|
+
|
381
|
+
@last.bytecode(g)
|
382
|
+
g.dup
|
383
|
+
|
384
|
+
g.push_const :Hash
|
385
|
+
|
386
|
+
g.push_type
|
387
|
+
g.move_down 2
|
388
|
+
g.send :object_kind_of?, 2
|
389
|
+
g.gif not_hash
|
390
|
+
|
391
|
+
g.make_array 1
|
392
|
+
g.goto done
|
393
|
+
|
394
|
+
not_hash.set!
|
395
|
+
g.cast_array
|
396
|
+
|
397
|
+
done.set!
|
398
|
+
g.send :+, 1
|
399
|
+
end
|
400
|
+
|
401
|
+
def to_sexp
|
402
|
+
[:collect_splat] + @parts.map { |x| x.to_sexp }
|
403
|
+
end
|
404
|
+
end
|
405
|
+
|
406
|
+
class ActualArguments < Node
|
407
|
+
attr_accessor :array, :splat
|
408
|
+
|
409
|
+
def initialize(line, arguments=nil)
|
410
|
+
@line = line
|
411
|
+
@splat = nil
|
412
|
+
|
413
|
+
case arguments
|
414
|
+
when SplatValue
|
415
|
+
@splat = arguments
|
416
|
+
@array = []
|
417
|
+
when ConcatArgs
|
418
|
+
case arguments.array
|
419
|
+
when ArrayLiteral
|
420
|
+
@array = arguments.array.body
|
421
|
+
@splat = SplatValue.new line, arguments.rest
|
422
|
+
when PushArgs
|
423
|
+
@array = []
|
424
|
+
node = SplatValue.new line, arguments.rest
|
425
|
+
@splat = CollectSplat.new line, arguments.array, node
|
426
|
+
else
|
427
|
+
@array = []
|
428
|
+
@splat = CollectSplat.new line, arguments.array, arguments.rest
|
429
|
+
end
|
430
|
+
when PushArgs
|
431
|
+
if arguments.arguments.kind_of? ConcatArgs
|
432
|
+
if ary = arguments.arguments.peel_lhs
|
433
|
+
@array = ary
|
434
|
+
else
|
435
|
+
@array = []
|
436
|
+
end
|
437
|
+
else
|
438
|
+
@array = []
|
439
|
+
end
|
440
|
+
|
441
|
+
node = ArrayLiteral.new line, [arguments.value]
|
442
|
+
@splat = CollectSplat.new line, arguments.arguments, node
|
443
|
+
when ArrayLiteral
|
444
|
+
@array = arguments.body
|
445
|
+
when nil
|
446
|
+
@array = []
|
447
|
+
else
|
448
|
+
@array = [arguments]
|
449
|
+
end
|
450
|
+
end
|
451
|
+
|
452
|
+
def size
|
453
|
+
@array.size
|
454
|
+
end
|
455
|
+
|
456
|
+
def stack_size
|
457
|
+
size = @array.size
|
458
|
+
size += 1 if splat?
|
459
|
+
size
|
460
|
+
end
|
461
|
+
|
462
|
+
def splat?
|
463
|
+
not @splat.nil?
|
464
|
+
end
|
465
|
+
|
466
|
+
def masgn_bytecode(g)
|
467
|
+
@array.each do |x|
|
468
|
+
x.bytecode(g)
|
469
|
+
g.swap
|
470
|
+
end
|
471
|
+
# TODO: splat
|
472
|
+
end
|
473
|
+
|
474
|
+
def bytecode(g)
|
475
|
+
@array.each { |x| x.bytecode(g) }
|
476
|
+
@splat.bytecode(g) if @splat
|
477
|
+
end
|
478
|
+
|
479
|
+
def to_sexp
|
480
|
+
sexp = @array.map { |x| x.to_sexp }
|
481
|
+
sexp << @splat.to_sexp if @splat
|
482
|
+
sexp
|
483
|
+
end
|
484
|
+
end
|
485
|
+
|
486
|
+
class Iter < Node
|
487
|
+
include Compiler::LocalVariables
|
488
|
+
|
489
|
+
attr_accessor :parent, :arguments, :body
|
490
|
+
|
491
|
+
def initialize(line, arguments, body)
|
492
|
+
@line = line
|
493
|
+
@arguments = IterArguments.new line, arguments
|
494
|
+
@body = body || NilLiteral.new(line)
|
495
|
+
end
|
496
|
+
|
497
|
+
# 1.8 doesn't support declared Iter locals
|
498
|
+
def block_local?(name)
|
499
|
+
false
|
500
|
+
end
|
501
|
+
|
502
|
+
def module?
|
503
|
+
false
|
504
|
+
end
|
505
|
+
|
506
|
+
def nest_scope(scope)
|
507
|
+
scope.parent = self
|
508
|
+
end
|
509
|
+
|
510
|
+
# A nested scope is looking up a local variable. If the variable exists
|
511
|
+
# in our local variables hash, return a nested reference to it. If it
|
512
|
+
# exists in an enclosing scope, increment the depth of the reference
|
513
|
+
# when it passes through this nested scope (i.e. the depth of a
|
514
|
+
# reference is a function of the nested scopes it passes through from
|
515
|
+
# the scope it is defined in to the scope it is used in).
|
516
|
+
def search_local(name)
|
517
|
+
if variable = variables[name]
|
518
|
+
variable.nested_reference
|
519
|
+
elsif block_local?(name)
|
520
|
+
new_local name
|
521
|
+
elsif reference = @parent.search_local(name)
|
522
|
+
reference.depth += 1
|
523
|
+
reference
|
524
|
+
end
|
525
|
+
end
|
526
|
+
|
527
|
+
def new_local(name)
|
528
|
+
variables[name] ||= Compiler::LocalVariable.new allocate_slot
|
529
|
+
end
|
530
|
+
|
531
|
+
def new_nested_local(name)
|
532
|
+
new_local(name).nested_reference
|
533
|
+
end
|
534
|
+
|
535
|
+
# If the local variable exists in this scope, set the local variable
|
536
|
+
# node attribute to a reference to the local variable. If the variable
|
537
|
+
# exists in an enclosing scope, set the local variable node attribute to
|
538
|
+
# a nested reference to the local variable. Otherwise, create a local
|
539
|
+
# variable in this scope and set the local variable node attribute.
|
540
|
+
def assign_local_reference(var)
|
541
|
+
if variable = variables[var.name]
|
542
|
+
var.variable = variable.reference
|
543
|
+
elsif block_local?(var.name)
|
544
|
+
variable = new_local var.name
|
545
|
+
var.variable = variable.reference
|
546
|
+
elsif reference = @parent.search_local(var.name)
|
547
|
+
reference.depth += 1
|
548
|
+
var.variable = reference
|
549
|
+
else
|
550
|
+
variable = new_local var.name
|
551
|
+
var.variable = variable.reference
|
552
|
+
end
|
553
|
+
end
|
554
|
+
|
555
|
+
def bytecode(g)
|
556
|
+
pos(g)
|
557
|
+
|
558
|
+
state = g.state
|
559
|
+
state.scope.nest_scope self
|
560
|
+
|
561
|
+
blk = new_block_generator g, @arguments
|
562
|
+
|
563
|
+
blk.push_state self
|
564
|
+
blk.definition_line @line
|
565
|
+
blk.state.push_super state.super
|
566
|
+
blk.state.push_eval state.eval
|
567
|
+
|
568
|
+
blk.state.push_name blk.name
|
569
|
+
|
570
|
+
# Push line info down.
|
571
|
+
pos(blk)
|
572
|
+
|
573
|
+
@arguments.bytecode(blk)
|
574
|
+
|
575
|
+
blk.state.push_block
|
576
|
+
blk.push_modifiers
|
577
|
+
blk.break = nil
|
578
|
+
blk.next = nil
|
579
|
+
blk.redo = blk.new_label
|
580
|
+
blk.redo.set!
|
581
|
+
|
582
|
+
@body.bytecode(blk)
|
583
|
+
|
584
|
+
blk.pop_modifiers
|
585
|
+
blk.state.pop_block
|
586
|
+
blk.ret
|
587
|
+
blk.close
|
588
|
+
blk.pop_state
|
589
|
+
|
590
|
+
blk.splat_index = @arguments.splat_index
|
591
|
+
blk.local_count = local_count
|
592
|
+
blk.local_names = local_names
|
593
|
+
|
594
|
+
g.create_block blk
|
595
|
+
end
|
596
|
+
|
597
|
+
def sexp_name
|
598
|
+
:iter
|
599
|
+
end
|
600
|
+
|
601
|
+
def to_sexp
|
602
|
+
[sexp_name, @arguments.to_sexp, @body.to_sexp]
|
603
|
+
end
|
604
|
+
end
|
605
|
+
|
606
|
+
class Iter19 < Iter
|
607
|
+
def initialize(line, arguments, body)
|
608
|
+
@line = line
|
609
|
+
@arguments = arguments || IterArguments.new(line, nil)
|
610
|
+
@body = body || NilLiteral.new(line)
|
611
|
+
|
612
|
+
if @body.kind_of?(Block) and @body.locals
|
613
|
+
@locals = @body.locals.body.map { |x| x.value }
|
614
|
+
else
|
615
|
+
@locals = nil
|
616
|
+
end
|
617
|
+
end
|
618
|
+
|
619
|
+
def block_local?(name)
|
620
|
+
@locals.include?(name) if @locals
|
621
|
+
end
|
622
|
+
end
|
623
|
+
|
624
|
+
class IterArguments < Node
|
625
|
+
attr_accessor :prelude, :arity, :optional, :arguments, :splat_index, :block_index
|
626
|
+
attr_accessor :required_args
|
627
|
+
|
628
|
+
def initialize(line, arguments)
|
629
|
+
@line = line
|
630
|
+
@optional = 0
|
631
|
+
@arguments = nil
|
632
|
+
|
633
|
+
@splat_index = -1
|
634
|
+
@block_index = nil
|
635
|
+
@required_args = 0
|
636
|
+
@splat = nil
|
637
|
+
@block = nil
|
638
|
+
@prelude = nil
|
639
|
+
|
640
|
+
case arguments
|
641
|
+
when Fixnum
|
642
|
+
@splat_index = nil
|
643
|
+
@arity = 0
|
644
|
+
@prelude = nil
|
645
|
+
when MultipleAssignment
|
646
|
+
arguments.iter_arguments
|
647
|
+
|
648
|
+
if arguments.splat
|
649
|
+
case arguments.splat
|
650
|
+
when EmptySplat
|
651
|
+
@splat_index = -2
|
652
|
+
arguments.splat = nil
|
653
|
+
@prelude = :empty
|
654
|
+
else
|
655
|
+
@splat = arguments.splat = arguments.splat.value
|
656
|
+
end
|
657
|
+
|
658
|
+
@optional = 1
|
659
|
+
if arguments.left
|
660
|
+
@prelude = :multi
|
661
|
+
size = arguments.left.body.size
|
662
|
+
@arity = -(size + 1)
|
663
|
+
@required_args = size
|
664
|
+
else
|
665
|
+
@prelude = :splat unless @prelude
|
666
|
+
@arity = -1
|
667
|
+
end
|
668
|
+
elsif arguments.left
|
669
|
+
size = arguments.left.body.size
|
670
|
+
@prelude = :multi
|
671
|
+
@arity = size
|
672
|
+
@required_args = size
|
673
|
+
|
674
|
+
# distinguish { |a, | ... } from { |a| ... }
|
675
|
+
@splat_index = nil unless size == 1
|
676
|
+
else
|
677
|
+
@splat_index = 0
|
678
|
+
@prelude = :multi
|
679
|
+
@arity = -1
|
680
|
+
end
|
681
|
+
|
682
|
+
@block = arguments.block
|
683
|
+
|
684
|
+
@arguments = arguments
|
685
|
+
when nil
|
686
|
+
@arity = -1
|
687
|
+
@splat_index = -2 # -2 means accept the splat, but don't store it anywhere
|
688
|
+
@prelude = nil
|
689
|
+
when BlockPass
|
690
|
+
@arity = -1
|
691
|
+
@splat_index = -2
|
692
|
+
@prelude = nil
|
693
|
+
@block = arguments
|
694
|
+
else # Assignment
|
695
|
+
@splat_index = nil
|
696
|
+
@arguments = arguments
|
697
|
+
@arity = 1
|
698
|
+
@required_args = 1
|
699
|
+
@prelude = :single
|
700
|
+
end
|
701
|
+
end
|
702
|
+
|
703
|
+
alias_method :total_args, :required_args
|
704
|
+
|
705
|
+
def post_args
|
706
|
+
0
|
707
|
+
end
|
708
|
+
|
709
|
+
def names
|
710
|
+
case @arguments
|
711
|
+
when MultipleAssignment
|
712
|
+
if arguments = @arguments.left.body
|
713
|
+
array = arguments.map { |x| x.name }
|
714
|
+
else
|
715
|
+
array = []
|
716
|
+
end
|
717
|
+
|
718
|
+
if @arguments.splat.kind_of? SplatAssignment
|
719
|
+
array << @arguments.splat.name
|
720
|
+
end
|
721
|
+
|
722
|
+
array
|
723
|
+
when nil
|
724
|
+
[]
|
725
|
+
else
|
726
|
+
[@arguments.name]
|
727
|
+
end
|
728
|
+
end
|
729
|
+
|
730
|
+
def arguments_bytecode(g, is_array=false)
|
731
|
+
g.state.push_masgn
|
732
|
+
|
733
|
+
if @arguments.kind_of? MultipleAssignment
|
734
|
+
@arguments.bytecode(g, is_array)
|
735
|
+
else
|
736
|
+
@arguments.bytecode(g) if @arguments
|
737
|
+
end
|
738
|
+
|
739
|
+
g.state.pop_masgn
|
740
|
+
|
741
|
+
if @splat
|
742
|
+
@splat_index = @splat.variable.slot
|
743
|
+
end
|
744
|
+
end
|
745
|
+
|
746
|
+
def bytecode(g)
|
747
|
+
case @prelude
|
748
|
+
when :single
|
749
|
+
g.cast_for_single_block_arg
|
750
|
+
arguments_bytecode(g)
|
751
|
+
g.pop
|
752
|
+
when :multi
|
753
|
+
g.cast_for_multi_block_arg
|
754
|
+
arguments_bytecode(g, true)
|
755
|
+
g.pop
|
756
|
+
when :splat
|
757
|
+
g.cast_for_splat_block_arg
|
758
|
+
arguments_bytecode(g)
|
759
|
+
g.pop
|
760
|
+
when :empty
|
761
|
+
g.cast_for_splat_block_arg
|
762
|
+
g.pop
|
763
|
+
end
|
764
|
+
|
765
|
+
if @block
|
766
|
+
@block.assignment_bytecode(g)
|
767
|
+
end
|
768
|
+
end
|
769
|
+
|
770
|
+
def to_sexp
|
771
|
+
if @arguments
|
772
|
+
@arguments.to_sexp
|
773
|
+
elsif @arity == 0
|
774
|
+
0
|
775
|
+
else
|
776
|
+
nil
|
777
|
+
end
|
778
|
+
end
|
779
|
+
end
|
780
|
+
|
781
|
+
class For < Iter
|
782
|
+
def nest_scope(scope)
|
783
|
+
scope.parent = self
|
784
|
+
end
|
785
|
+
|
786
|
+
def search_local(name)
|
787
|
+
if reference = @parent.search_local(name)
|
788
|
+
reference.depth += 1
|
789
|
+
reference
|
790
|
+
end
|
791
|
+
end
|
792
|
+
|
793
|
+
def new_nested_local(name)
|
794
|
+
reference = @parent.new_nested_local name
|
795
|
+
reference.depth += 1
|
796
|
+
reference
|
797
|
+
end
|
798
|
+
|
799
|
+
def assign_local_reference(var)
|
800
|
+
unless reference = search_local(var.name)
|
801
|
+
reference = new_nested_local var.name
|
802
|
+
end
|
803
|
+
|
804
|
+
var.variable = reference
|
805
|
+
end
|
806
|
+
|
807
|
+
def sexp_name
|
808
|
+
:for
|
809
|
+
end
|
810
|
+
end
|
811
|
+
|
812
|
+
class For19Arguments < Node
|
813
|
+
attr_reader :block_index
|
814
|
+
|
815
|
+
def initialize(line, arguments)
|
816
|
+
@line = line
|
817
|
+
@arguments = arguments
|
818
|
+
|
819
|
+
if @arguments.kind_of? MultipleAssignment
|
820
|
+
@args = 0
|
821
|
+
@splat = 0
|
822
|
+
else
|
823
|
+
@args = 1
|
824
|
+
@splat = nil
|
825
|
+
end
|
826
|
+
end
|
827
|
+
|
828
|
+
def bytecode(g)
|
829
|
+
if @splat
|
830
|
+
g.push_literal Compiler::Runtime
|
831
|
+
g.push_local 0
|
832
|
+
g.send :unwrap_block_arg, 1
|
833
|
+
else
|
834
|
+
g.push_local 0
|
835
|
+
end
|
836
|
+
|
837
|
+
g.state.push_masgn
|
838
|
+
@arguments.bytecode(g)
|
839
|
+
g.state.pop_masgn
|
840
|
+
g.pop
|
841
|
+
end
|
842
|
+
|
843
|
+
def required_args
|
844
|
+
@args
|
845
|
+
end
|
846
|
+
|
847
|
+
def total_args
|
848
|
+
@args
|
849
|
+
end
|
850
|
+
|
851
|
+
def post_args
|
852
|
+
0
|
853
|
+
end
|
854
|
+
|
855
|
+
def splat_index
|
856
|
+
@splat
|
857
|
+
end
|
858
|
+
end
|
859
|
+
|
860
|
+
class For19 < For
|
861
|
+
def initialize(line, arguments, body)
|
862
|
+
@line = line
|
863
|
+
@arguments = For19Arguments.new line, arguments
|
864
|
+
@body = body || NilLiteral.new(line)
|
865
|
+
|
866
|
+
new_local :"$for_args"
|
867
|
+
end
|
868
|
+
end
|
869
|
+
|
870
|
+
class Negate < Node
|
871
|
+
attr_accessor :value
|
872
|
+
|
873
|
+
def initialize(line, value)
|
874
|
+
@line = line
|
875
|
+
@value = value
|
876
|
+
end
|
877
|
+
|
878
|
+
def bytecode(g)
|
879
|
+
pos(g)
|
880
|
+
|
881
|
+
if @value.kind_of? NumberLiteral
|
882
|
+
g.push(-@value.value)
|
883
|
+
else
|
884
|
+
@value.bytecode(g)
|
885
|
+
g.send :"-@", 0
|
886
|
+
end
|
887
|
+
end
|
888
|
+
|
889
|
+
def to_sexp
|
890
|
+
[:negate, @value.to_sexp]
|
891
|
+
end
|
892
|
+
end
|
893
|
+
|
894
|
+
class Super < SendWithArguments
|
895
|
+
attr_accessor :name, :block
|
896
|
+
|
897
|
+
def initialize(line, arguments)
|
898
|
+
@line = line
|
899
|
+
@block = nil
|
900
|
+
@name = nil
|
901
|
+
@arguments = ActualArguments.new line, arguments
|
902
|
+
end
|
903
|
+
|
904
|
+
def block_bytecode(g)
|
905
|
+
if @block
|
906
|
+
@block.bytecode(g)
|
907
|
+
else
|
908
|
+
g.push_block
|
909
|
+
end
|
910
|
+
end
|
911
|
+
|
912
|
+
def bytecode(g)
|
913
|
+
pos(g)
|
914
|
+
|
915
|
+
@name = g.state.super.name if g.state.super?
|
916
|
+
|
917
|
+
@arguments.bytecode(g)
|
918
|
+
|
919
|
+
block_bytecode(g)
|
920
|
+
|
921
|
+
if @arguments.splat?
|
922
|
+
g.send_super @name, @arguments.size, true
|
923
|
+
else
|
924
|
+
g.send_super @name, @arguments.size
|
925
|
+
end
|
926
|
+
end
|
927
|
+
|
928
|
+
def defined(g)
|
929
|
+
nope = g.new_label
|
930
|
+
done = g.new_label
|
931
|
+
|
932
|
+
g.invoke_primitive :vm_check_super_callable, 0
|
933
|
+
|
934
|
+
g.gif nope
|
935
|
+
|
936
|
+
g.push_literal "super"
|
937
|
+
g.string_dup
|
938
|
+
g.goto done
|
939
|
+
|
940
|
+
nope.set!
|
941
|
+
g.push :nil
|
942
|
+
|
943
|
+
done.set!
|
944
|
+
end
|
945
|
+
|
946
|
+
def to_sexp
|
947
|
+
arguments_sexp :super
|
948
|
+
end
|
949
|
+
end
|
950
|
+
|
951
|
+
class Yield < SendWithArguments
|
952
|
+
attr_accessor :flags
|
953
|
+
|
954
|
+
def initialize(line, arguments, unwrap)
|
955
|
+
@line = line
|
956
|
+
|
957
|
+
if arguments.kind_of? ArrayLiteral and not unwrap
|
958
|
+
arguments = ArrayLiteral.new line, [arguments]
|
959
|
+
end
|
960
|
+
|
961
|
+
@arguments = ActualArguments.new line, arguments
|
962
|
+
@argument_count = @arguments.size
|
963
|
+
@yield_splat = false
|
964
|
+
|
965
|
+
if @arguments.splat?
|
966
|
+
splat = @arguments.splat.value
|
967
|
+
if (splat.kind_of? ArrayLiteral or splat.kind_of? EmptyArray) and not unwrap
|
968
|
+
@argument_count += 1
|
969
|
+
else
|
970
|
+
@yield_splat = true
|
971
|
+
end
|
972
|
+
end
|
973
|
+
end
|
974
|
+
|
975
|
+
def bytecode(g)
|
976
|
+
pos(g)
|
977
|
+
|
978
|
+
@arguments.bytecode(g)
|
979
|
+
|
980
|
+
if @yield_splat
|
981
|
+
g.yield_splat @argument_count
|
982
|
+
else
|
983
|
+
g.yield_stack @argument_count
|
984
|
+
end
|
985
|
+
end
|
986
|
+
|
987
|
+
def defined(g)
|
988
|
+
t = g.new_label
|
989
|
+
f = g.new_label
|
990
|
+
|
991
|
+
g.push_block
|
992
|
+
g.git t
|
993
|
+
g.push :nil
|
994
|
+
g.goto f
|
995
|
+
|
996
|
+
t.set!
|
997
|
+
g.push_literal "yield"
|
998
|
+
|
999
|
+
f.set!
|
1000
|
+
end
|
1001
|
+
|
1002
|
+
def to_sexp
|
1003
|
+
arguments_sexp :yield
|
1004
|
+
end
|
1005
|
+
end
|
1006
|
+
|
1007
|
+
class ZSuper < Super
|
1008
|
+
def initialize(line)
|
1009
|
+
@line = line
|
1010
|
+
@block = nil
|
1011
|
+
end
|
1012
|
+
|
1013
|
+
def bytecode(g)
|
1014
|
+
pos(g)
|
1015
|
+
|
1016
|
+
@name = g.state.super.name if g.state.super?
|
1017
|
+
|
1018
|
+
block_bytecode(g)
|
1019
|
+
|
1020
|
+
g.zsuper @name
|
1021
|
+
end
|
1022
|
+
|
1023
|
+
def to_sexp
|
1024
|
+
[:zsuper]
|
1025
|
+
end
|
1026
|
+
end
|
1027
|
+
end
|
1028
|
+
end
|