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.
@@ -0,0 +1,30 @@
1
+ # -*- encoding: us-ascii -*-
2
+
3
+ module Rubinius::ToolSet.current::TS
4
+ module AST
5
+ class EndData < Node
6
+ attr_accessor :data
7
+
8
+ def initialize(offset, body)
9
+ @offset = offset
10
+ @body = body || NilLiteral.new(1)
11
+ end
12
+
13
+ # When a script includes __END__, Ruby makes the data after it
14
+ # available as an IO instance via the DATA constant. Since code
15
+ # in the toplevel can access this constant, we have to set it up
16
+ # before any other code runs. This AST node wraps the top node
17
+ # returned by the file parser.
18
+ def bytecode(g)
19
+ g.push_rubinius
20
+ g.push_scope
21
+ g.send :data_path, 0
22
+ g.push_literal @offset
23
+ g.send :set_data, 2
24
+ g.pop
25
+
26
+ @body.bytecode(g)
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,1134 @@
1
+ # -*- encoding: us-ascii -*-
2
+
3
+ module Rubinius::ToolSet.current::TS
4
+ module AST
5
+ class Alias < Node
6
+ attr_accessor :to, :from
7
+
8
+ def initialize(line, to, from)
9
+ @line = line
10
+ @to = to
11
+ @from = from
12
+ end
13
+
14
+ def bytecode(g)
15
+ pos(g)
16
+
17
+ g.push_scope
18
+ @to.bytecode(g)
19
+ @from.bytecode(g)
20
+ g.send :alias_method, 2, true
21
+ end
22
+
23
+ def to_sexp
24
+ [:alias, @to.to_sexp, @from.to_sexp]
25
+ end
26
+ end
27
+
28
+ class VAlias < Alias
29
+ def bytecode(g)
30
+ pos(g)
31
+
32
+ g.push_rubinius
33
+ g.find_const :Globals
34
+ g.push_literal @from
35
+ g.push_literal @to
36
+ # TODO: fix #add_alias arg order to match #alias_method
37
+ g.send :add_alias, 2
38
+ end
39
+
40
+ def to_sexp
41
+ [:valias, @to, @from]
42
+ end
43
+ end
44
+
45
+ class Undef < Node
46
+ attr_accessor :name
47
+
48
+ def initialize(line, sym)
49
+ @line = line
50
+ @name = sym
51
+ end
52
+
53
+ def bytecode(g)
54
+ pos(g)
55
+
56
+ g.push_scope
57
+ @name.bytecode(g)
58
+ g.send :__undef_method__, 1
59
+ end
60
+
61
+ def to_sexp
62
+ [:undef, @name.to_sexp]
63
+ end
64
+ end
65
+
66
+ # Is it weird that Block has the :arguments attribute? Yes. Is it weird
67
+ # that MRI parse tree puts arguments and block_arg in Block? Yes. So we
68
+ # make do and pull them out here rather than having something else reach
69
+ # inside of Block.
70
+ class Block < Node
71
+ attr_accessor :array, :locals
72
+
73
+ def initialize(line, array)
74
+ @line = line
75
+ @array = array
76
+
77
+ # These are any local variable that are declared as explicit
78
+ # locals for this scope. This is only used by the |a;b| syntax.
79
+ @locals = nil
80
+ end
81
+
82
+ def strip_arguments
83
+ if @array.first.kind_of? FormalArguments
84
+ node = @array.shift
85
+ if @array.first.kind_of? BlockArgument
86
+ node.block_arg = @array.shift
87
+ end
88
+ return node
89
+ end
90
+ end
91
+
92
+ def bytecode(g)
93
+ count = @array.size - 1
94
+ @array.each_with_index do |x, i|
95
+ start_ip = g.ip
96
+ x.bytecode(g)
97
+ g.pop unless start_ip == g.ip or i == count
98
+ end
99
+ end
100
+
101
+ def to_sexp
102
+ @array.inject([:block]) { |s, x| s << x.to_sexp }
103
+ end
104
+ end
105
+
106
+ class ClosedScope < Node
107
+ include Compiler::LocalVariables
108
+
109
+ attr_accessor :body
110
+
111
+ # A nested scope is looking up a local variable. If the variable exists
112
+ # in our local variables hash, return a nested reference to it.
113
+ def search_local(name)
114
+ if variable = variables[name]
115
+ variable.nested_reference
116
+ end
117
+ end
118
+
119
+ def new_local(name)
120
+ variables[name] ||= Compiler::LocalVariable.new allocate_slot
121
+ end
122
+
123
+ def new_nested_local(name)
124
+ new_local(name).nested_reference
125
+ end
126
+
127
+ # There is no place above us that may contain a local variable. Set the
128
+ # local in our local variables hash if not set. Set the local variable
129
+ # node attribute to a reference to the local variable.
130
+ def assign_local_reference(var)
131
+ unless variable = variables[var.name]
132
+ variable = new_local var.name
133
+ end
134
+
135
+ var.variable = variable.reference
136
+ end
137
+
138
+ def nest_scope(scope)
139
+ scope.parent = self
140
+ end
141
+
142
+ def module?
143
+ false
144
+ end
145
+
146
+ def attach_and_call(g, arg_name, scoped=false, pass_block=false)
147
+ name = @name || arg_name
148
+ meth = new_generator(g, name)
149
+
150
+ meth.push_state self
151
+ meth.for_module_body = true
152
+
153
+ if scoped
154
+ meth.push_self
155
+ meth.add_scope
156
+ end
157
+
158
+ meth.state.push_name name
159
+
160
+ @body.bytecode meth
161
+
162
+ meth.state.pop_name
163
+
164
+ meth.ret
165
+ meth.close
166
+
167
+ meth.local_count = local_count
168
+ meth.local_names = local_names
169
+
170
+ meth.pop_state
171
+
172
+ g.create_block meth
173
+ g.swap
174
+ g.push_scope
175
+ g.push_true
176
+ g.send :call_under, 3
177
+
178
+ return meth
179
+ end
180
+
181
+ def to_sexp
182
+ sexp = [:scope]
183
+ sexp << @body.to_sexp if @body
184
+ sexp
185
+ end
186
+ end
187
+
188
+ class Define < ClosedScope
189
+ attr_accessor :name, :arguments
190
+
191
+ def initialize(line, name, block)
192
+ @line = line
193
+ @name = name
194
+ @arguments = block.strip_arguments
195
+ block.array << NilLiteral.new(line) if block.array.empty?
196
+ @body = block
197
+ end
198
+
199
+ def compile_body(g)
200
+ meth = new_generator(g, @name, @arguments)
201
+
202
+ meth.push_state self
203
+ meth.state.push_super self
204
+ meth.definition_line(@line)
205
+
206
+ meth.state.push_name @name
207
+
208
+ @arguments.bytecode(meth)
209
+ @body.bytecode(meth)
210
+
211
+ meth.state.pop_name
212
+
213
+ meth.local_count = local_count
214
+ meth.local_names = local_names
215
+
216
+ meth.ret
217
+ meth.close
218
+ meth.pop_state
219
+
220
+ return meth
221
+ end
222
+
223
+ def bytecode(g)
224
+ pos(g)
225
+
226
+ g.push_rubinius
227
+ g.push_literal @name
228
+ g.push_generator compile_body(g)
229
+ g.push_scope
230
+ g.push_variables
231
+ g.send :method_visibility, 0
232
+
233
+ g.send :add_defn_method, 4
234
+ end
235
+
236
+ def to_sexp
237
+ [:defn, @name, @arguments.to_sexp, [:scope, @body.to_sexp]]
238
+ end
239
+ end
240
+
241
+ class DefineSingleton < Node
242
+ attr_accessor :receiver, :body
243
+
244
+ def initialize(line, receiver, name, block)
245
+ @line = line
246
+ @receiver = receiver
247
+ @body = DefineSingletonScope.new line, name, block
248
+ end
249
+
250
+ def bytecode(g)
251
+ pos(g)
252
+
253
+ @body.bytecode(g, @receiver)
254
+ end
255
+
256
+ def to_sexp
257
+ [:defs, @receiver.to_sexp, @body.name,
258
+ @body.arguments.to_sexp, [:scope, @body.body.to_sexp]]
259
+ end
260
+ end
261
+
262
+ class DefineSingletonScope < Define
263
+ def initialize(line, name, block)
264
+ super line, name, block
265
+ end
266
+
267
+ def bytecode(g, recv)
268
+ pos(g)
269
+
270
+ g.push_rubinius
271
+ g.push_literal @name
272
+ g.push_generator compile_body(g)
273
+ g.push_scope
274
+ recv.bytecode(g)
275
+
276
+ g.send :attach_method, 4
277
+ end
278
+ end
279
+
280
+ class FormalArguments < Node
281
+ attr_accessor :names, :required, :optional, :defaults, :splat
282
+ attr_reader :block_arg, :block_index
283
+
284
+ def initialize(line, args, defaults, splat)
285
+ @line = line
286
+ @defaults = nil
287
+ @block_arg = nil
288
+ @block_index = nil
289
+
290
+ if defaults
291
+ defaults = DefaultArguments.new line, defaults
292
+ @defaults = defaults
293
+ @optional = defaults.names
294
+
295
+ stop = defaults.names.first
296
+ last = args.each_with_index { |a, i| break i if a == stop }
297
+ @required = args[0, last]
298
+ else
299
+ @required = args.dup
300
+ @optional = []
301
+ end
302
+
303
+ if splat.kind_of? Symbol
304
+ args << splat
305
+ elsif splat
306
+ splat = :*
307
+ args << splat
308
+ end
309
+ @names = args
310
+ @splat = splat
311
+ end
312
+
313
+ def block_arg=(node)
314
+ @names << node.name
315
+
316
+ @block_index = @names.length - 1
317
+ @block_arg = node
318
+ end
319
+
320
+ def bytecode(g)
321
+ g.state.check_for_locals = false
322
+ map_arguments g.state.scope
323
+
324
+ @defaults.bytecode(g) if @defaults
325
+ @block_arg.bytecode(g) if @block_arg
326
+ g.state.check_for_locals = true
327
+ end
328
+
329
+ def required_args
330
+ @required.size
331
+ end
332
+
333
+ alias_method :arity, :required_args
334
+
335
+ def post_args
336
+ 0
337
+ end
338
+
339
+ def total_args
340
+ @required.size + @optional.size
341
+ end
342
+
343
+ def splat_index
344
+ if @splat
345
+ index = @names.size
346
+ index -= 1 if @block_arg
347
+ index -= 1 if @splat.kind_of? Symbol
348
+ index
349
+ end
350
+ end
351
+
352
+ def map_arguments(scope)
353
+ @required.each { |arg| scope.new_local arg }
354
+ @defaults.map_arguments scope if @defaults
355
+ scope.new_local @splat if @splat.kind_of? Symbol
356
+ scope.assign_local_reference @block_arg if @block_arg
357
+ end
358
+
359
+ def to_actual(line)
360
+ arguments = ActualArguments.new line
361
+
362
+ last = -1
363
+ last -= 1 if @block_arg and @block_arg.name == names[last]
364
+ last -= 1 if @splat == names[last]
365
+
366
+ arguments.array = @names[0..last].map { |name| LocalVariableAccess.new line, name }
367
+
368
+ if @splat.kind_of? Symbol
369
+ arguments.splat = SplatValue.new(line, LocalVariableAccess.new(line, @splat))
370
+ end
371
+
372
+ arguments
373
+ end
374
+
375
+ def to_sexp
376
+ sexp = [:args]
377
+
378
+ @required.each { |x| sexp << x }
379
+ sexp += @defaults.names if @defaults
380
+
381
+ if @splat == :*
382
+ sexp << :*
383
+ elsif @splat
384
+ sexp << :"*#{@splat}"
385
+ end
386
+
387
+ sexp += @post if @post
388
+
389
+ sexp << :"&#{@block_arg.name}" if @block_arg
390
+
391
+ sexp << [:block] + @defaults.to_sexp if @defaults
392
+
393
+ sexp
394
+ end
395
+ end
396
+
397
+ class FormalArguments19 < FormalArguments
398
+ attr_accessor :post
399
+
400
+ def initialize(line, required, optional, splat, post, block)
401
+ @line = line
402
+ @defaults = nil
403
+ @block_arg = nil
404
+ @splat_index = nil
405
+ @block_index = nil
406
+
407
+ @required = []
408
+ names = []
409
+
410
+ if required
411
+ required.each do |arg|
412
+ case arg
413
+ when Symbol
414
+ names << arg
415
+ @required << arg
416
+ when MultipleAssignment
417
+ @required << PatternArguments.from_masgn(arg)
418
+ @splat_index = -4 if @required.size == 1
419
+ end
420
+ end
421
+ end
422
+
423
+ if optional
424
+ @defaults = DefaultArguments.new line, optional
425
+ @optional = @defaults.names
426
+ names.concat @optional
427
+ else
428
+ @optional = []
429
+ end
430
+
431
+ case splat
432
+ when Symbol
433
+ names << splat
434
+ when true
435
+ splat = :*
436
+ names << splat
437
+ when false
438
+ @splat_index = -3
439
+ splat = nil
440
+ end
441
+
442
+ if post
443
+ names.concat post
444
+ @post = post
445
+ else
446
+ @post = []
447
+ end
448
+
449
+ if block
450
+ @block_arg = BlockArgument.new line, block
451
+ names << block
452
+ @block_index = names.length - 1
453
+ end
454
+
455
+ @splat = splat
456
+ @names = names
457
+ end
458
+
459
+ def required_args
460
+ @required.size + @post.size
461
+ end
462
+
463
+ def post_args
464
+ @post.size
465
+ end
466
+
467
+ def total_args
468
+ @required.size + @optional.size + @post.size
469
+ end
470
+
471
+ def splat_index
472
+ return @splat_index if @splat_index
473
+
474
+ if @splat
475
+ index = @names.size
476
+ index -= 1 if @block_arg
477
+ index -= 1 if @splat.kind_of? Symbol
478
+ index -= @post.size
479
+ index
480
+ end
481
+ end
482
+
483
+ def map_arguments(scope)
484
+ @required.each_with_index do |arg, index|
485
+ case arg
486
+ when PatternArguments
487
+ arg.map_arguments scope
488
+ when Symbol
489
+ @required[index] = arg = :"_#{index}" if arg == :_ and index > 0
490
+ scope.new_local arg
491
+ end
492
+ end
493
+
494
+ @defaults.map_arguments scope if @defaults
495
+ scope.new_local @splat if @splat.kind_of? Symbol
496
+ @post.each { |arg| scope.new_local arg }
497
+ scope.assign_local_reference @block_arg if @block_arg
498
+ end
499
+
500
+ def bytecode(g)
501
+ g.state.check_for_locals = false
502
+ map_arguments g.state.scope
503
+
504
+ @required.each do |arg|
505
+ if arg.kind_of? PatternArguments
506
+ arg.argument.position_bytecode(g)
507
+ arg.bytecode(g)
508
+ g.pop
509
+ end
510
+ end
511
+
512
+ @defaults.bytecode(g) if @defaults
513
+ @block_arg.bytecode(g) if @block_arg
514
+ g.state.check_for_locals = true
515
+ end
516
+ end
517
+
518
+ class PatternArguments < Node
519
+ attr_accessor :arguments, :argument
520
+
521
+ def self.from_masgn(node)
522
+ array = []
523
+ size = 0
524
+ if node.left
525
+ size += node.left.body.size
526
+ node.left.body.map do |n|
527
+ case n
528
+ when MultipleAssignment
529
+ array << PatternArguments.from_masgn(n)
530
+ when LocalVariable
531
+ array << LeftPatternVariable.new(n.line, n.name)
532
+ end
533
+ end
534
+ end
535
+
536
+ if node.post
537
+ idx = 0
538
+ post_args = []
539
+ node.post.body.map do |n|
540
+ case n
541
+ when MultipleAssignment
542
+ post_args << PatternArguments.from_masgn(n)
543
+ when LocalVariable
544
+ post_args << PostPatternVariable.new(n.line, n.name, idx)
545
+ end
546
+ idx += 1
547
+ end
548
+ array.concat(post_args.reverse)
549
+ end
550
+
551
+ if node.splat
552
+ n = node.splat
553
+ case n
554
+ when EmptySplat
555
+ when SplatAssignment, SplatWrapped, SplatArray
556
+ array << SplatPatternVariable.new(n.value.line, n.value.name)
557
+ end
558
+ end
559
+
560
+ PatternArguments.new node.line, ArrayLiteral.new(node.line, array)
561
+ end
562
+
563
+ def initialize(line, arguments)
564
+ @line = line
565
+ @arguments = arguments
566
+ @argument = nil
567
+ end
568
+
569
+ # Assign the left-most, depth-first PatternVariable so that this local
570
+ # will be assigned the passed argument at that position. The rest of the
571
+ # pattern will be destructured from the value of this assignment.
572
+ def map_arguments(scope)
573
+ arguments = @arguments.body
574
+ while arguments
575
+ node = arguments.first
576
+ case node
577
+ when LeftPatternVariable, PostPatternVariable, SplatPatternVariable
578
+ @argument = node
579
+ scope.new_local node.name
580
+ scope.assign_local_reference node
581
+ return
582
+ end
583
+ arguments = node.arguments.body
584
+ end
585
+ end
586
+
587
+ def bytecode(g)
588
+ @arguments.body.each do |arg|
589
+ if arg.kind_of? PatternArguments
590
+ g.shift_array
591
+ g.cast_array
592
+ arg.bytecode(g)
593
+ g.pop
594
+ else
595
+ arg.bytecode(g)
596
+ end
597
+ end
598
+ end
599
+ end
600
+
601
+ class DefaultArguments < Node
602
+ attr_accessor :arguments, :names
603
+
604
+ def initialize(line, block)
605
+ @line = line
606
+ array = block.array
607
+ @names = array.map { |a| a.name }
608
+ @arguments = array
609
+ end
610
+
611
+ def map_arguments(scope)
612
+ @arguments.each { |var| scope.assign_local_reference var }
613
+ end
614
+
615
+ def bytecode(g)
616
+ @arguments.each do |arg|
617
+ done = g.new_label
618
+
619
+ g.passed_arg arg.variable.slot
620
+ g.git done
621
+ arg.bytecode(g)
622
+ g.pop
623
+
624
+ done.set!
625
+ end
626
+ end
627
+
628
+ def to_sexp
629
+ @arguments.map { |x| x.to_sexp }
630
+ end
631
+ end
632
+
633
+ module LocalVariable
634
+ attr_accessor :variable
635
+ end
636
+
637
+ class BlockArgument < Node
638
+ include LocalVariable
639
+
640
+ attr_accessor :name
641
+
642
+ def initialize(line, name)
643
+ @line = line
644
+ @name = name
645
+ end
646
+
647
+ def bytecode(g)
648
+ pos(g)
649
+
650
+ g.push_proc
651
+
652
+ if @variable.respond_to?(:depth) && @variable.depth != 0
653
+ g.set_local_depth @variable.depth, @variable.slot
654
+ else
655
+ g.set_local @variable.slot
656
+ end
657
+
658
+ g.pop
659
+ end
660
+ end
661
+
662
+ class Class < Node
663
+ attr_accessor :name, :superclass, :body
664
+
665
+ def initialize(line, name, superclass, body)
666
+ @line = line
667
+
668
+ @superclass = superclass ? superclass : NilLiteral.new(line)
669
+
670
+ case name
671
+ when Symbol
672
+ @name = ClassName.new line, name, @superclass
673
+ when ToplevelConstant
674
+ @name = ToplevelClassName.new line, name, @superclass
675
+ else
676
+ @name = ScopedClassName.new line, name, @superclass
677
+ end
678
+
679
+ if body
680
+ @body = ClassScope.new line, @name, body
681
+ else
682
+ @body = EmptyBody.new line
683
+ end
684
+ end
685
+
686
+ def bytecode(g)
687
+ @name.bytecode(g)
688
+ @body.bytecode(g)
689
+ end
690
+
691
+ def to_sexp
692
+ superclass = @superclass.kind_of?(NilLiteral) ? nil : @superclass.to_sexp
693
+ [:class, @name.to_sexp, superclass, @body.to_sexp]
694
+ end
695
+ end
696
+
697
+ class ClassScope < ClosedScope
698
+ def initialize(line, name, body)
699
+ @line = line
700
+ @name = name.name
701
+ @body = body
702
+ end
703
+
704
+ def module?
705
+ true
706
+ end
707
+
708
+ def bytecode(g)
709
+ pos(g)
710
+
711
+ attach_and_call g, :__class_init__, true
712
+ end
713
+ end
714
+
715
+ class ClassName < Node
716
+ attr_accessor :name, :superclass
717
+
718
+ def initialize(line, name, superclass)
719
+ @line = line
720
+ @name = name
721
+ @superclass = superclass
722
+ end
723
+
724
+ def name_bytecode(g)
725
+ g.push_rubinius
726
+ g.push_literal @name
727
+ @superclass.bytecode(g)
728
+ end
729
+
730
+ def bytecode(g)
731
+ pos(g)
732
+
733
+ name_bytecode(g)
734
+ g.push_scope
735
+ g.send :open_class, 3
736
+ end
737
+
738
+ def to_sexp
739
+ @name
740
+ end
741
+ end
742
+
743
+ class ToplevelClassName < ClassName
744
+ def initialize(line, node, superclass)
745
+ @line = line
746
+ @name = node.name
747
+ @superclass = superclass
748
+ end
749
+
750
+ def bytecode(g)
751
+ pos(g)
752
+
753
+ name_bytecode(g)
754
+ g.push_cpath_top
755
+ g.send :open_class_under, 3
756
+ end
757
+
758
+ def to_sexp
759
+ [:colon3, @name]
760
+ end
761
+ end
762
+
763
+ class ScopedClassName < ClassName
764
+ attr_accessor :parent
765
+
766
+ def initialize(line, node, superclass)
767
+ @line = line
768
+ @name = node.name
769
+ @parent = node.parent
770
+ @superclass = superclass
771
+ end
772
+
773
+ def bytecode(g)
774
+ pos(g)
775
+
776
+ name_bytecode(g)
777
+ @parent.bytecode(g)
778
+ g.send :open_class_under, 3
779
+ end
780
+
781
+ def to_sexp
782
+ [:colon2, @parent.to_sexp, @name]
783
+ end
784
+ end
785
+
786
+ class Module < Node
787
+ attr_accessor :name, :body
788
+
789
+ def initialize(line, name, body)
790
+ @line = line
791
+
792
+ case name
793
+ when Symbol
794
+ @name = ModuleName.new line, name
795
+ when ToplevelConstant
796
+ @name = ToplevelModuleName.new line, name
797
+ else
798
+ @name = ScopedModuleName.new line, name
799
+ end
800
+
801
+ if body
802
+ @body = ModuleScope.new line, @name, body
803
+ else
804
+ @body = EmptyBody.new line
805
+ end
806
+ end
807
+
808
+ def bytecode(g)
809
+ @name.bytecode(g)
810
+ @body.bytecode(g)
811
+ end
812
+
813
+ def to_sexp
814
+ [:module, @name.to_sexp, @body.to_sexp]
815
+ end
816
+ end
817
+
818
+ class EmptyBody < Node
819
+ def bytecode(g)
820
+ g.pop
821
+ g.push :nil
822
+ end
823
+
824
+ def to_sexp
825
+ [:scope]
826
+ end
827
+ end
828
+
829
+ class ModuleName < Node
830
+ attr_accessor :name
831
+
832
+ def initialize(line, name)
833
+ @line = line
834
+ @name = name
835
+ end
836
+
837
+ def name_bytecode(g)
838
+ g.push_rubinius
839
+ g.push_literal @name
840
+ end
841
+
842
+ def bytecode(g)
843
+ pos(g)
844
+
845
+ name_bytecode(g)
846
+ g.push_scope
847
+ g.send :open_module, 2
848
+ end
849
+
850
+ def to_sexp
851
+ @name
852
+ end
853
+ end
854
+
855
+ class ToplevelModuleName < ModuleName
856
+ def initialize(line, node)
857
+ @line = line
858
+ @name = node.name
859
+ end
860
+
861
+ def bytecode(g)
862
+ pos(g)
863
+
864
+ name_bytecode(g)
865
+ g.push_cpath_top
866
+ g.send :open_module_under, 2
867
+ end
868
+
869
+ def to_sexp
870
+ [:colon3, @name]
871
+ end
872
+ end
873
+
874
+ class ScopedModuleName < ModuleName
875
+ attr_accessor :parent
876
+
877
+ def initialize(line, node)
878
+ @line = line
879
+ @name = node.name
880
+ @parent = node.parent
881
+ end
882
+
883
+ def bytecode(g)
884
+ pos(g)
885
+
886
+ name_bytecode(g)
887
+ @parent.bytecode(g)
888
+ g.send :open_module_under, 2
889
+ end
890
+
891
+ def to_sexp
892
+ [:colon2, @parent.to_sexp, @name]
893
+ end
894
+ end
895
+
896
+ class ModuleScope < ClosedScope
897
+ def initialize(line, name, body)
898
+ @line = line
899
+ @name = name.name
900
+ @body = body
901
+ end
902
+
903
+ def module?
904
+ true
905
+ end
906
+
907
+ def bytecode(g)
908
+ pos(g)
909
+
910
+ attach_and_call g, :__module_init__, true
911
+ end
912
+ end
913
+
914
+ class SClass < Node
915
+ attr_accessor :receiver
916
+
917
+ def initialize(line, receiver, body)
918
+ @line = line
919
+ @receiver = receiver
920
+ @body = SClassScope.new line, body
921
+ end
922
+
923
+ def bytecode(g)
924
+ pos(g)
925
+ @receiver.bytecode(g)
926
+ @body.bytecode(g)
927
+ end
928
+
929
+ def to_sexp
930
+ [:sclass, @receiver.to_sexp, @body.to_sexp]
931
+ end
932
+ end
933
+
934
+ class SClassScope < ClosedScope
935
+ def initialize(line, body)
936
+ @line = line
937
+ @body = body
938
+ @name = nil
939
+ end
940
+
941
+ def bytecode(g)
942
+ pos(g)
943
+
944
+ g.push_type
945
+ g.swap
946
+ g.send :object_singleton_class, 1
947
+
948
+ if @body
949
+ # if @body just returns self, don't bother with it.
950
+ if @body.kind_of? Block
951
+ ary = @body.array
952
+ return if ary.size == 1 and ary[0].kind_of? Self
953
+ end
954
+
955
+ # Ok, emit it.
956
+ attach_and_call g, :__metaclass_init__, true, true
957
+ else
958
+ g.pop
959
+ g.push :nil
960
+ end
961
+ end
962
+ end
963
+
964
+ class Container < ClosedScope
965
+ attr_accessor :file, :name, :variable_scope, :pre_exe
966
+
967
+ def initialize(body)
968
+ @body = body || NilLiteral.new(1)
969
+ @pre_exe = []
970
+ end
971
+
972
+ def push_state(g)
973
+ g.push_state self
974
+ end
975
+
976
+ def pop_state(g)
977
+ g.pop_state
978
+ end
979
+
980
+ def container_bytecode(g)
981
+ g.name = @name
982
+ g.file = @file.to_sym
983
+
984
+ push_state(g)
985
+ @pre_exe.each { |pe| pe.pre_bytecode(g) }
986
+
987
+ yield if block_given?
988
+ pop_state(g)
989
+
990
+ g.local_count = local_count
991
+ g.local_names = local_names
992
+ end
993
+
994
+ def to_sexp
995
+ sexp = [sexp_name]
996
+ @pre_exe.each { |pe| sexp << pe.pre_sexp }
997
+ sexp << @body.to_sexp
998
+ sexp
999
+ end
1000
+ end
1001
+
1002
+ class EvalExpression < Container
1003
+ def initialize(body)
1004
+ super body
1005
+ @name = :__eval_script__
1006
+ end
1007
+
1008
+ def should_cache?
1009
+ !@body.kind_of?(AST::ClosedScope)
1010
+ end
1011
+
1012
+ def search_scopes(name)
1013
+ depth = 1
1014
+ scope = @variable_scope
1015
+ while scope
1016
+ if !scope.method.for_eval? and slot = scope.method.local_slot(name)
1017
+ return Compiler::NestedLocalVariable.new(depth, slot)
1018
+ elsif scope.eval_local_defined?(name, false)
1019
+ return Compiler::EvalLocalVariable.new(name)
1020
+ end
1021
+
1022
+ depth += 1
1023
+ scope = scope.parent
1024
+ end
1025
+ end
1026
+
1027
+ # Returns a cached reference to a variable or searches all
1028
+ # surrounding scopes for a variable. If no variable is found,
1029
+ # it returns nil and a nested scope will create the variable
1030
+ # in itself.
1031
+ def search_local(name)
1032
+ if variable = variables[name]
1033
+ return variable.nested_reference
1034
+ end
1035
+
1036
+ if variable = search_scopes(name)
1037
+ variables[name] = variable
1038
+ return variable.nested_reference
1039
+ end
1040
+ end
1041
+
1042
+ def new_local(name)
1043
+ variables[name] ||= Compiler::EvalLocalVariable.new name
1044
+ end
1045
+
1046
+ def assign_local_reference(var)
1047
+ unless reference = search_local(var.name)
1048
+ variable = new_local var.name
1049
+ reference = variable.reference
1050
+ end
1051
+
1052
+ var.variable = reference
1053
+ end
1054
+
1055
+ def push_state(g)
1056
+ g.push_state self
1057
+ g.state.push_eval self
1058
+ end
1059
+
1060
+ def bytecode(g)
1061
+ super(g)
1062
+
1063
+ container_bytecode(g) do
1064
+ @body.bytecode(g)
1065
+ g.ret
1066
+ end
1067
+ end
1068
+
1069
+ def sexp_name
1070
+ :eval
1071
+ end
1072
+ end
1073
+
1074
+ class Snippet < Container
1075
+ def initialize(body)
1076
+ super body
1077
+ @name = :__snippet__
1078
+ end
1079
+
1080
+ def bytecode(g)
1081
+ super(g)
1082
+
1083
+ container_bytecode(g) do
1084
+ @body.bytecode(g)
1085
+ end
1086
+ end
1087
+
1088
+ def sexp_name
1089
+ :snippet
1090
+ end
1091
+ end
1092
+
1093
+ class Script < Container
1094
+ def initialize(body)
1095
+ super body
1096
+ @name = :__script__
1097
+ end
1098
+
1099
+ def bytecode(g)
1100
+ super(g)
1101
+
1102
+ container_bytecode(g) do
1103
+ @body.bytecode(g)
1104
+ g.pop
1105
+ g.push :true
1106
+ g.ret
1107
+ end
1108
+ end
1109
+
1110
+ def sexp_name
1111
+ :script
1112
+ end
1113
+ end
1114
+
1115
+ class Defined < Node
1116
+ attr_accessor :expression
1117
+
1118
+ def initialize(line, expr)
1119
+ @line = line
1120
+ @expression = expr
1121
+ end
1122
+
1123
+ def bytecode(g)
1124
+ pos(g)
1125
+
1126
+ @expression.defined(g)
1127
+ end
1128
+
1129
+ def to_sexp
1130
+ [:defined, @expression.to_sexp]
1131
+ end
1132
+ end
1133
+ end
1134
+ end