rubinius-ast 1.0.1

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