rubinius-compiler 2.1.0 → 2.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +8 -0
  3. data/lib/rubinius/compiler/compiled_file.rb +32 -32
  4. data/lib/rubinius/compiler/version.rb +2 -2
  5. data/rubinius-compiler.gemspec +6 -0
  6. data/spec/alias_spec.rb +39 -0
  7. data/spec/and_spec.rb +44 -0
  8. data/spec/array_spec.rb +110 -0
  9. data/spec/attrasgn_spec.rb +186 -0
  10. data/spec/back_ref_spec.rb +11 -0
  11. data/spec/call_spec.rb +580 -0
  12. data/spec/case_spec.rb +576 -0
  13. data/spec/cdecl_spec.rb +70 -0
  14. data/spec/class_spec.rb +120 -0
  15. data/spec/colon2_spec.rb +8 -0
  16. data/spec/colon3_spec.rb +8 -0
  17. data/spec/const_spec.rb +7 -0
  18. data/spec/custom/guards/profiler.rb +18 -0
  19. data/spec/custom/helpers/generator.rb +828 -0
  20. data/spec/custom/matchers/compile_as.rb +46 -0
  21. data/spec/custom/mspec.rb +15 -0
  22. data/spec/custom/runner/actions/debug.rb +10 -0
  23. data/spec/custom/runner/actions/gcstats.rb +17 -0
  24. data/spec/custom/runner/actions/memory.rb +11 -0
  25. data/spec/custom/runner/actions/parser.rb +14 -0
  26. data/spec/custom/runner/actions/profiler.rb +19 -0
  27. data/spec/custom/runner/relates.rb +86 -0
  28. data/spec/custom/utils/options.rb +40 -0
  29. data/spec/custom/utils/script.rb +50 -0
  30. data/spec/cvar_spec.rb +39 -0
  31. data/spec/cvasgn_spec.rb +33 -0
  32. data/spec/cvdecl_spec.rb +17 -0
  33. data/spec/defined_spec.rb +616 -0
  34. data/spec/defn_spec.rb +732 -0
  35. data/spec/defs_spec.rb +113 -0
  36. data/spec/dot2_spec.rb +16 -0
  37. data/spec/dot3_spec.rb +17 -0
  38. data/spec/dregx_spec.rb +160 -0
  39. data/spec/dstr_spec.rb +424 -0
  40. data/spec/dsym_spec.rb +18 -0
  41. data/spec/dxstr_spec.rb +24 -0
  42. data/spec/ensure_spec.rb +196 -0
  43. data/spec/false_spec.rb +7 -0
  44. data/spec/flip2_spec.rb +21 -0
  45. data/spec/flip3_spec.rb +12 -0
  46. data/spec/for_spec.rb +228 -0
  47. data/spec/gasgn_spec.rb +15 -0
  48. data/spec/generator/encode_spec.rb +34 -0
  49. data/spec/gvar_spec.rb +37 -0
  50. data/spec/hash_spec.rb +108 -0
  51. data/spec/iasgn_spec.rb +26 -0
  52. data/spec/if_spec.rb +415 -0
  53. data/spec/iter_spec.rb +1011 -0
  54. data/spec/lasgn_spec.rb +561 -0
  55. data/spec/lit_spec.rb +61 -0
  56. data/spec/masgn_spec.rb +1558 -0
  57. data/spec/match2_spec.rb +42 -0
  58. data/spec/match3_spec.rb +54 -0
  59. data/spec/match_spec.rb +29 -0
  60. data/spec/module_spec.rb +73 -0
  61. data/spec/nil_spec.rb +7 -0
  62. data/spec/not_spec.rb +47 -0
  63. data/spec/nth_ref_spec.rb +7 -0
  64. data/spec/op_asgn_spec.rb +563 -0
  65. data/spec/or_spec.rb +126 -0
  66. data/spec/postexe_spec.rb +11 -0
  67. data/spec/preexe_spec.rb +21 -0
  68. data/spec/regex_spec.rb +54 -0
  69. data/spec/rescue_spec.rb +763 -0
  70. data/spec/return_spec.rb +152 -0
  71. data/spec/sclass_spec.rb +138 -0
  72. data/spec/spec_helper.rb +12 -0
  73. data/spec/str_spec.rb +118 -0
  74. data/spec/super_spec.rb +170 -0
  75. data/spec/transforms/assembly_spec.rb +195 -0
  76. data/spec/transforms/block_given_spec.rb +75 -0
  77. data/spec/transforms/fast_coerce_spec.rb +112 -0
  78. data/spec/transforms/fast_new_spec.rb +255 -0
  79. data/spec/transforms/invoke_primitive_spec.rb +14 -0
  80. data/spec/transforms/kernel_methods_spec.rb +29 -0
  81. data/spec/transforms/primitive_spec.rb +33 -0
  82. data/spec/transforms/privately_spec.rb +24 -0
  83. data/spec/true_spec.rb +7 -0
  84. data/spec/undef_spec.rb +133 -0
  85. data/spec/until_spec.rb +254 -0
  86. data/spec/valias_spec.rb +11 -0
  87. data/spec/while_spec.rb +494 -0
  88. data/spec/xstr_spec.rb +10 -0
  89. data/spec/yield_spec.rb +92 -0
  90. data/spec/zsuper_spec.rb +63 -0
  91. metadata +258 -3
@@ -0,0 +1,70 @@
1
+ describe "A Cdecl node" do
2
+ relates "X = 42" do
3
+ compile do |g|
4
+ g.push_scope
5
+ g.push_literal :X
6
+ g.push 42
7
+ g.send :const_set, 2
8
+ end
9
+ end
10
+
11
+ relates "::X = 1" do
12
+ compile do |g|
13
+ g.push_cpath_top
14
+ g.push_literal :X
15
+ g.push 1
16
+ g.send :const_set, 2
17
+ end
18
+ end
19
+
20
+ relates "X::Y = 1" do
21
+ compile do |g|
22
+ g.push 1
23
+ g.push_literal :Y
24
+ g.push_const :X
25
+ g.rotate 3
26
+ g.send :const_set, 2
27
+ end
28
+ end
29
+
30
+ relates "X::Y::Z = a" do
31
+ compile do |g|
32
+ g.push :self
33
+ g.send :a, 0, true
34
+ g.push_literal :Z
35
+ g.push_const :X
36
+ g.find_const :Y
37
+ g.rotate 3
38
+ g.send :const_set, 2
39
+ end
40
+ end
41
+
42
+ relates "a::A = 1" do
43
+ compile do |g|
44
+ g.push 1
45
+ g.push_literal :A
46
+ g.push :self
47
+ g.send :a, 0, true
48
+ g.rotate 3
49
+ g.send :const_set, 2
50
+ end
51
+ end
52
+
53
+ relates <<-ruby do
54
+ a = Object
55
+ a::B = b
56
+ ruby
57
+
58
+ compile do |g|
59
+ g.push_const :Object
60
+ g.set_local 0
61
+ g.pop
62
+ g.push :self
63
+ g.send :b, 0, true
64
+ g.push_literal :B
65
+ g.push_local 0
66
+ g.rotate 3
67
+ g.send :const_set, 2
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,120 @@
1
+ describe "A Class node" do
2
+ relates <<-ruby do
3
+ class X
4
+ puts((1 + 1))
5
+ def blah
6
+ puts("hello")
7
+ end
8
+ end
9
+ ruby
10
+
11
+ compile do |g|
12
+ in_class :X do |d|
13
+ d.push :self
14
+ d.push 1
15
+ d.push 1
16
+ d.send :+, 1, false
17
+ d.send :puts, 1, true
18
+ d.pop
19
+
20
+ d.in_method :blah do |d2|
21
+ d2.push :self
22
+ d2.push_literal "hello"
23
+ d2.string_dup
24
+ d2.send :puts, 1, true
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ relates <<-ruby do
31
+ class ::Y
32
+ c
33
+ end
34
+ ruby
35
+
36
+ compile do |g|
37
+ g.push_rubinius
38
+ g.push_literal :Y
39
+ g.push :nil
40
+ g.push_cpath_top
41
+ g.send :open_class_under, 3
42
+ d = new_generator(g, :Y)
43
+ g.create_block d
44
+ d.push_self
45
+ d.add_scope
46
+ d.push :self
47
+ d.send :c, 0, true
48
+ d.ret
49
+
50
+ g.swap
51
+ g.push_scope
52
+ g.push_true
53
+ g.send :call_under, 3
54
+ end
55
+ end
56
+
57
+ relates <<-ruby do
58
+ class X::Y
59
+ c
60
+ end
61
+ ruby
62
+
63
+ compile do |g|
64
+ in_class "X::Y" do |d|
65
+ d.push :self
66
+ d.send :c, 0, true
67
+ end
68
+ end
69
+ end
70
+
71
+ relates <<-ruby do
72
+ class X < Array
73
+ end
74
+ ruby
75
+
76
+ compile do |g|
77
+ g.push_rubinius
78
+ g.push_literal :X
79
+ g.push_const :Array
80
+ g.push_scope
81
+ g.send :open_class, 3
82
+ g.pop
83
+ g.push :nil
84
+ end
85
+ end
86
+
87
+ relates <<-ruby do
88
+ class X < expr
89
+ end
90
+ ruby
91
+
92
+ compile do |g|
93
+ g.push_rubinius
94
+ g.push_literal :X
95
+ g.push :self
96
+ g.send :expr, 0, true
97
+ g.push_scope
98
+ g.send :open_class, 3
99
+
100
+ g.pop
101
+ g.push :nil
102
+ end
103
+ end
104
+
105
+ relates <<-ruby do
106
+ class X < Object
107
+ end
108
+ ruby
109
+
110
+ compile do |g|
111
+ g.push_rubinius
112
+ g.push_literal :X
113
+ g.push_const :Object
114
+ g.push_scope
115
+ g.send :open_class, 3
116
+ g.pop
117
+ g.push :nil
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,8 @@
1
+ describe "A Colon2 node" do
2
+ relates "X::Y" do
3
+ compile do |g|
4
+ g.push_const :X
5
+ g.find_const :Y
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ describe "A Colon3 node" do
2
+ relates "::X" do
3
+ compile do |g|
4
+ g.push_cpath_top
5
+ g.find_const :X
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,7 @@
1
+ describe "A Const node" do
2
+ relates "X" do
3
+ compile do |g|
4
+ g.push_const :X
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,18 @@
1
+ require 'tooling/profiler/profiler'
2
+
3
+ class ProfilerGuard < SpecGuard
4
+ def match?
5
+ Rubinius::Profiler::Instrumenter.available? and
6
+ not Rubinius::Profiler::Instrumenter.active?
7
+ end
8
+ end
9
+
10
+ class Object
11
+ def with_profiler
12
+ g = ProfilerGuard.new
13
+ g.name = :with_profiler
14
+ yield if g.yield?
15
+ ensure
16
+ g.unregister
17
+ end
18
+ end
@@ -0,0 +1,828 @@
1
+ # TODO: document TestGenerator
2
+ module Rubinius
3
+ class TestGenerator
4
+ class Label
5
+ attr_reader :ip
6
+
7
+ def initialize(gen)
8
+ @generator = gen
9
+ @ip = nil
10
+ @used = false
11
+ end
12
+
13
+ attr_reader :used
14
+ alias_method :used?, :used
15
+
16
+ def used!
17
+ @used = true
18
+ end
19
+
20
+ def inspect
21
+ self.to_sym.inspect
22
+ end
23
+
24
+ def to_sym
25
+ return :UNSET_LABEL unless @ip
26
+ # raise "Unset label!" unless @ip
27
+ :"label_#{@ip}"
28
+ end
29
+
30
+ def set!
31
+ @ip = @generator.new_label_id
32
+ @generator.set_label self.to_sym
33
+ end
34
+
35
+ def ==(lbl)
36
+ raise "Unset label!" unless @ip
37
+ return self.to_sym == lbl if Symbol === lbl
38
+ @ip == lbl.ip
39
+ end
40
+ end
41
+
42
+ # TestGenerator methods
43
+
44
+ def self.define_opcode_method(name)
45
+ class_eval <<-CODE
46
+ def #{name}(*args)
47
+ add :#{name}, *args
48
+ end
49
+ CODE
50
+ end
51
+
52
+ excluded_opcodes = [:class, :goto, :set_label, :cast_array, :setup_unwind]
53
+
54
+ Rubinius::InstructionSet.opcodes.each do |opcode|
55
+ next if excluded_opcodes.include? opcode.name
56
+ define_opcode_method opcode.name
57
+ end
58
+
59
+ [:add_literal,
60
+ :pop_modifiers,
61
+ :push,
62
+ :push_literal_at,
63
+ :push_modifiers,
64
+ :invoke_primitive,
65
+ :last_match,
66
+ :send,
67
+ :send_super,
68
+ :send_with_block,
69
+ :send_with_splat,
70
+ :swap].each do |name|
71
+ define_opcode_method name
72
+ end
73
+
74
+ def git(lbl)
75
+ lbl.used!
76
+ add :goto_if_true, lbl
77
+ end
78
+
79
+ def gif(lbl)
80
+ lbl.used!
81
+ add :goto_if_false, lbl
82
+ end
83
+
84
+ def send_vcall(meth)
85
+ send meth, 0, true
86
+ end
87
+
88
+ # The :g accessor is provided to make the code in the
89
+ # utility methods below clearer
90
+ attr_reader :g
91
+ attr_accessor :stream, :ip, :redo, :break, :next, :retry,
92
+ :name, :file, :line, :primitive, :for_block, :for_module_body,
93
+ :required_args, :post_args, :total_args, :splat_index,
94
+ :local_count, :local_names, :block_index
95
+
96
+
97
+ def initialize
98
+ @stream = []
99
+ @ip = 0
100
+ @lbl = 0
101
+ @slot = 0
102
+ @g = self
103
+ @state = []
104
+ @stack_locals = 0
105
+ end
106
+
107
+ def new_stack_local
108
+ idx = @stack_locals
109
+ @stack_locals += 1
110
+ return idx
111
+ end
112
+
113
+ def state
114
+ @state.last
115
+ end
116
+
117
+ # TODO: put TestGenerator under Rubinius
118
+ def push_state(scope)
119
+ @state << Rubinius::ToolSets::Spec::AST::State.new(scope)
120
+ end
121
+
122
+ def pop_state
123
+ @state.pop
124
+ end
125
+ def run(node)
126
+ node.bytecode(self)
127
+ end
128
+
129
+ def convert_to_ary(ary)
130
+ ary.map do |item|
131
+ if item.respond_to? :to_ary
132
+ convert_to_ary item.to_ary
133
+ elsif item.kind_of? TestGenerator
134
+ item.to_a
135
+ else
136
+ item
137
+ end
138
+ end
139
+ end
140
+
141
+ def to_a
142
+ convert_to_ary [:test_generator, @stream]
143
+ end
144
+
145
+ def pretty_inspect
146
+ to_a.pretty_inspect
147
+ end
148
+
149
+ def inspect
150
+ to_a.inspect
151
+ end
152
+
153
+ def add(*args)
154
+ @last = args
155
+ @stream << args
156
+ @ip += 1
157
+ end
158
+
159
+ def new_slot
160
+ @ip
161
+ end
162
+
163
+ def new_label
164
+ Label.new self
165
+ end
166
+
167
+ def new_label_id
168
+ @lbl += 1
169
+ @lbl
170
+ end
171
+
172
+ def dup
173
+ add :dup
174
+ end
175
+
176
+ def definition_line(line)
177
+ # nothing
178
+ end
179
+
180
+ def set_line(line)
181
+ @line = line
182
+ end
183
+
184
+ def set_label(lbl)
185
+ @stream << [:set_label, lbl.to_sym]
186
+ end
187
+
188
+ def close
189
+ end
190
+
191
+ def ==(tg)
192
+ tg.class == self.class && tg.stream == @stream
193
+ end
194
+
195
+ # Hack to provide expected semantics
196
+ def ===(other)
197
+ equal? other
198
+ end
199
+
200
+ def find_literal(lit)
201
+ lit
202
+ end
203
+
204
+ def goto(x)
205
+ raise "Bad goto: #{x.inspect} on #{caller.first}" unless Label === x
206
+ x.used!
207
+ add :goto, x
208
+ end
209
+
210
+ def setup_unwind(label, *)
211
+ add :setup_unwind, label
212
+ end
213
+
214
+ def send_primitive(name)
215
+ @primitive = name
216
+ end
217
+
218
+ def push_unique_literal(lit)
219
+ push_literal lit
220
+ end
221
+
222
+ def push_generator(desc)
223
+ push_literal desc
224
+ end
225
+
226
+ def new_block_generator(g)
227
+ blk = g.class.new
228
+ blk.name == :__block__
229
+
230
+ blk
231
+ end
232
+
233
+ def new_generator(g, name=nil)
234
+ meth = g.class.new
235
+ meth.name = name
236
+
237
+ meth
238
+ end
239
+
240
+ def splatted_array(n=1)
241
+ bottom = g.new_label
242
+
243
+ if block_given?
244
+ yield
245
+ else
246
+ g.push 1
247
+ end
248
+ g.make_array n
249
+
250
+ g.cast_array
251
+ g.dup
252
+ g.send :size, 0
253
+ g.push 1
254
+ g.send :>, 1
255
+ g.git bottom
256
+
257
+ g.push 0
258
+ g.send :at, 1
259
+
260
+ bottom.set!
261
+ end
262
+
263
+ def in_block_send(name, type, required=nil, call_count=0, vis=true)
264
+ d = new_block_generator(g)
265
+
266
+ # Arguments for blocks are handled differently in 1.9
267
+ ruby_version_is ""..."1.9" do
268
+ count = nil
269
+
270
+ case type
271
+ when :none
272
+ required = -1
273
+ when :empty
274
+ required = 0
275
+ when :blank
276
+ required = -1
277
+ d.cast_for_splat_block_arg
278
+ when :single
279
+ required = 1
280
+ d.cast_for_single_block_arg
281
+ d.set_local 0
282
+ when :splat
283
+ required = -1
284
+ d.cast_for_splat_block_arg
285
+ d.set_local 0
286
+ when :rest
287
+ count = required.abs - 1
288
+ when :multi
289
+ count = required.abs
290
+ end
291
+
292
+ if count
293
+ d.cast_for_multi_block_arg
294
+
295
+ (0...count).each do |n|
296
+ d.shift_array
297
+ d.set_local n
298
+ d.pop
299
+ end
300
+ end
301
+
302
+ if type == :rest
303
+ d.set_local count
304
+ end
305
+
306
+ if type != :none and type != :empty and type != 0
307
+ d.pop
308
+ end
309
+ end
310
+
311
+ d.push_modifiers
312
+ d.new_label.set!
313
+
314
+ yield d
315
+
316
+ d.pop_modifiers
317
+ d.ret
318
+
319
+ g.create_block(d)
320
+
321
+ g.send_with_block name, call_count, vis
322
+ end
323
+
324
+ def in_class(name)
325
+ case name
326
+ when Symbol
327
+ g.push_rubinius
328
+ g.push_literal name
329
+ g.push :nil
330
+
331
+ g.push_scope
332
+ g.send :open_class, 3
333
+ when String
334
+ g.push_rubinius
335
+
336
+ levels = name.split(/::/).map { |s| s.to_sym }
337
+ klass = levels.pop
338
+
339
+ g.push_literal klass
340
+ g.push :nil
341
+
342
+ levels.each do |level|
343
+ g.push_const level
344
+ end
345
+
346
+ g.send :open_class_under, 3
347
+ end
348
+
349
+ return unless block_given?
350
+
351
+ d = new_generator(g, :Y)
352
+
353
+ g.create_block d
354
+
355
+ d.push_self
356
+ d.add_scope
357
+
358
+ yield d
359
+
360
+ d.ret
361
+
362
+ g.swap
363
+ g.push_scope
364
+ g.push_true
365
+ g.send :call_under, 3
366
+ end
367
+
368
+ def in_singleton_method(name, sing)
369
+ g.push_rubinius
370
+
371
+ g.push_literal name
372
+
373
+ d = new_generator(g, name)
374
+
375
+ yield d
376
+ d.ret
377
+
378
+ g.push_literal(d)
379
+
380
+ g.push_scope
381
+
382
+ if sing.kind_of? Array
383
+ g.add *sing
384
+ else
385
+ g.add sing
386
+ end
387
+
388
+ g.send :attach_method, 4
389
+ end
390
+
391
+ def in_method(name, singleton=false)
392
+ if singleton
393
+ raise "use in_singleton_method"
394
+ end
395
+
396
+ g.push_rubinius
397
+
398
+ g.push_literal name
399
+
400
+ d = new_generator(g, name)
401
+
402
+ yield d
403
+ d.ret
404
+
405
+ g.push_literal(d)
406
+
407
+ g.push_scope
408
+
409
+ g.push_variables
410
+ g.send :method_visibility, 0
411
+ g.send :add_defn_method, 4
412
+ end
413
+
414
+ def in_module(name)
415
+ case name
416
+ when Symbol
417
+ g.push_rubinius
418
+ g.push_literal name
419
+ g.push_scope
420
+ g.send :open_module, 2
421
+ when String
422
+ levels = name.split(/::/).map { |s| s.to_sym }
423
+ klass = levels.pop
424
+
425
+ g.push_rubinius
426
+ g.push_literal klass
427
+
428
+ levels.each do |level|
429
+ g.push_const level
430
+ end
431
+
432
+ g.send :open_module_under, 2
433
+ end
434
+
435
+ return unless block_given?
436
+
437
+ d = new_generator(g, :Y)
438
+
439
+ g.create_block d
440
+
441
+ d.push_self
442
+ d.add_scope
443
+
444
+ yield d
445
+
446
+ d.ret
447
+
448
+ g.swap
449
+ g.push_scope
450
+ g.push_true
451
+ g.send :call_under, 3
452
+ end
453
+
454
+ def save_exception
455
+ idx = new_stack_local
456
+ push_exception_state
457
+ set_stack_local idx
458
+ pop
459
+
460
+ return idx
461
+ end
462
+
463
+ def restore_exception(idx)
464
+ push_stack_local idx
465
+ restore_exception_state
466
+ end
467
+
468
+ class Break
469
+ def initialize(g)
470
+ @label = g.new_label
471
+ @original = g.break
472
+ @emit = false
473
+ end
474
+
475
+ attr_accessor :label, :original, :emit
476
+ end
477
+
478
+ class Next < Break
479
+ end
480
+
481
+ class RescueBlock
482
+ def initialize(g)
483
+ @body = nil
484
+ @conditions = []
485
+ @else = nil
486
+ @break = nil
487
+ @next = nil
488
+ @g = g
489
+ end
490
+
491
+ attr_reader :conditions, :current_break
492
+ attr_accessor :saved_exc
493
+
494
+ def set_break(b)
495
+ @break = b
496
+ end
497
+
498
+ def body(&block)
499
+ @body ||= block
500
+ end
501
+
502
+ def condition(klass, top_level = false, &block)
503
+ @conditions << [klass, block, top_level]
504
+ end
505
+
506
+ def raw_condition(&block)
507
+ @conditions << [nil, block, false]
508
+ end
509
+
510
+ def els(&block)
511
+ @else ||= block
512
+ end
513
+
514
+ def new_break
515
+ @break = Break.new(@g)
516
+ end
517
+
518
+ def new_next
519
+ @next = Next.new(@g)
520
+ end
521
+
522
+ def clear_break
523
+ @break = nil
524
+ end
525
+
526
+ def clear_next
527
+ @next = nil
528
+ end
529
+
530
+ def break
531
+ raise "no break info" unless @break
532
+ @g.goto @break.label
533
+ @break.emit = true
534
+ end
535
+
536
+ def next
537
+ raise "no next info" unless @next
538
+ @g.goto @next.label
539
+ @next.emit = true
540
+ end
541
+
542
+ def restore_exception
543
+ @g.restore_exception @saved_exc
544
+ end
545
+
546
+ end
547
+
548
+ def for_rescue
549
+ rb = RescueBlock.new(self)
550
+ yield rb
551
+
552
+ jump_retry = g.new_label
553
+ jump_else = g.new_label
554
+ jump_last = g.new_label
555
+
556
+ g.push_modifiers
557
+
558
+ rb.saved_exc = save_exception
559
+
560
+ jump_retry.set!
561
+
562
+ exc_lbl = g.new_label
563
+ g.setup_unwind exc_lbl
564
+
565
+ g.new_label.set!
566
+
567
+ br = rb.new_break
568
+ nx = rb.new_next
569
+
570
+ rb.body.call
571
+
572
+ g.pop_unwind
573
+ g.goto jump_else
574
+
575
+ if br.emit
576
+ br.label.set!
577
+ g.pop_unwind
578
+
579
+ g.restore_exception rb.saved_exc
580
+
581
+ if br.original
582
+ g.goto br.original
583
+ else
584
+ g.goto jump_else
585
+ end
586
+ end
587
+
588
+ if nx.emit
589
+ nx.label.set!
590
+
591
+ g.pop_unwind
592
+
593
+ g.restore_exception rb.saved_exc
594
+
595
+ if nx.original
596
+ g.goto nx.original
597
+ else
598
+ g.ret
599
+ end
600
+ end
601
+
602
+ exc_lbl.set!
603
+
604
+ g.push_exception_state
605
+ raised_state = g.new_stack_local
606
+ g.set_stack_local raised_state
607
+ g.pop
608
+
609
+ g.push_current_exception
610
+
611
+ rb.conditions.each do |klass, code, top_level|
612
+ jump_body = g.new_label
613
+ jump_next = g.new_label
614
+
615
+ if klass
616
+ g.dup
617
+ if top_level
618
+ g.push_cpath_top
619
+ g.find_const klass
620
+ else
621
+ g.push_const klass
622
+ end
623
+ g.swap
624
+ g.send :===, 1
625
+ g.git jump_body
626
+
627
+ g.goto jump_next
628
+
629
+ jump_body.set!
630
+
631
+ g.pop # remove the saved exception on the stack
632
+ end
633
+
634
+ br = rb.new_break
635
+ nx = rb.new_next
636
+
637
+ code.call(jump_body, jump_next)
638
+
639
+ g.clear_exception
640
+ g.goto jump_last
641
+
642
+ if br.emit
643
+ br.label.set!
644
+ g.clear_exception
645
+
646
+ g.restore_exception rb.saved_exc
647
+
648
+ if br.original
649
+ g.goto br.original
650
+ else
651
+ g.raise_break
652
+ end
653
+ end
654
+
655
+ if nx.emit
656
+ nx.label.set!
657
+ g.clear_exception
658
+
659
+ g.restore_exception rb.saved_exc
660
+
661
+ if br.original
662
+ g.goto br.original
663
+ else
664
+ g.ret
665
+ end
666
+ end
667
+
668
+ jump_next.set!
669
+ end
670
+
671
+ g.pop
672
+
673
+ g.push_stack_local raised_state
674
+ g.restore_exception_state
675
+ g.reraise
676
+
677
+ jump_else.set!
678
+
679
+ rb.els.call if rb.els
680
+
681
+ jump_last.set!
682
+
683
+ restore_exception rb.saved_exc
684
+
685
+ g.pop_modifiers
686
+ end
687
+
688
+ class EnsureBlock
689
+ def initialize
690
+ @body = nil
691
+ @handler = nil
692
+ end
693
+
694
+ def body(&block)
695
+ @body ||= block
696
+ end
697
+
698
+ def handler(&block)
699
+ @handler ||= block
700
+ end
701
+ end
702
+
703
+ def for_ensure
704
+ eb = EnsureBlock.new
705
+
706
+ yield eb
707
+
708
+ ensure_good = g.new_label
709
+ ensure_bad = g.new_label
710
+
711
+ g.setup_unwind ensure_bad
712
+
713
+ jump_top = g.new_label
714
+ jump_top.set!
715
+
716
+ g.save_exception
717
+
718
+ old_break = g.break
719
+ new_break = g.new_label
720
+ g.break = new_break
721
+
722
+ eb.body.call
723
+
724
+ g.break = old_break
725
+
726
+ g.pop_unwind
727
+ g.goto ensure_good
728
+
729
+ check_break = nil
730
+
731
+ if new_break.used?
732
+ used_break_local = g.new_stack_local
733
+ check_break = g.new_label
734
+
735
+ new_break.set!
736
+ g.pop_unwind
737
+
738
+ g.push :true
739
+ g.set_stack_local used_break_local
740
+ g.pop
741
+
742
+ g.goto check_break
743
+ end
744
+
745
+ ensure_bad.set!
746
+ g.push_exception_state
747
+
748
+ eb.handler.call
749
+ g.restore_exception_state
750
+ g.reraise
751
+
752
+ ensure_good.set!
753
+
754
+ if check_break
755
+ g.push :false
756
+ g.set_stack_local used_break_local
757
+ g.pop
758
+
759
+ check_break.set!
760
+ end
761
+
762
+ eb.handler.call
763
+
764
+ if check_break
765
+ post = g.new_label
766
+
767
+ g.push_stack_local used_break_local
768
+ g.gif post
769
+
770
+ if g.break
771
+ g.goto g.break
772
+ else
773
+ g.raise_break
774
+ end
775
+
776
+ post.set!
777
+ end
778
+ end
779
+
780
+ def optional_arg(slot)
781
+ if_set = g.new_label
782
+ g.passed_arg slot
783
+ g.git if_set
784
+ g.push 42
785
+ g.set_local slot
786
+ g.pop
787
+ if_set.set!
788
+ end
789
+
790
+ def block_arg(slot)
791
+ g.push_proc
792
+ g.set_local slot
793
+ g.pop
794
+ end
795
+
796
+ def memoize
797
+ memo = g.new_label
798
+ g.add_literal nil
799
+ slot = new_slot
800
+ g.push_literal_at slot
801
+ g.dup
802
+ g.is_nil
803
+ g.gif memo
804
+ g.pop
805
+
806
+ yield g
807
+
808
+ g.set_literal slot
809
+ memo.set!
810
+ end
811
+
812
+ def undef_bytecode(*names)
813
+ last_name = names.last
814
+ names.each do |name|
815
+ g.push_scope
816
+ g.push_literal name
817
+ g.send :__undef_method__, 1
818
+ g.pop unless name == last_name
819
+ end
820
+ end
821
+
822
+ def cast_array
823
+ unless @last and [:cast_array, :make_array].include? @last.first
824
+ add :cast_array
825
+ end
826
+ end
827
+ end
828
+ end