fastruby 0.0.19 → 0.0.20

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) hide show
  1. data/CHANGELOG +8 -0
  2. data/{README → README.rdoc} +6 -1
  3. data/Rakefile +7 -7
  4. data/benchmarks/benchmark.rb~ +14 -2
  5. data/ext/fastruby_base/fastruby_base.inl +8 -4
  6. data/lib/fastruby/builder/inference_updater.rb +76 -0
  7. data/lib/fastruby/builder/inference_updater.rb~ +76 -0
  8. data/lib/fastruby/builder/inferencer.rb +38 -0
  9. data/lib/fastruby/{inliner → builder}/inliner.rb +16 -27
  10. data/lib/fastruby/builder/inliner.rb~ +60 -0
  11. data/lib/fastruby/builder/locals_inference.rb +53 -0
  12. data/lib/fastruby/builder/lvar_type.rb +43 -0
  13. data/lib/fastruby/builder/lvar_type.rb~ +44 -0
  14. data/lib/fastruby/builder/pipeline.rb +43 -0
  15. data/lib/fastruby/builder/pipeline.rb~ +43 -0
  16. data/lib/fastruby/{reductor → builder}/reductor.rb +6 -3
  17. data/lib/fastruby/builder/reductor.rb~ +42 -0
  18. data/lib/fastruby/builder.rb +73 -25
  19. data/lib/fastruby/builder.rb~ +311 -0
  20. data/lib/fastruby/corelib/fixnum.rb +75 -0
  21. data/lib/fastruby/corelib/fixnum.rb~ +146 -0
  22. data/lib/fastruby/corelib/integer.rb +96 -0
  23. data/lib/fastruby/corelib/integer.rb~ +96 -0
  24. data/lib/fastruby/corelib.rb +23 -0
  25. data/lib/fastruby/corelib.rb~ +23 -0
  26. data/lib/fastruby/getlocals.rb +3 -1
  27. data/lib/fastruby/logging.rb +2 -2
  28. data/lib/fastruby/modules/inferencer/infer.rb +31 -0
  29. data/lib/fastruby/modules/inferencer/literal.rb +42 -0
  30. data/lib/fastruby/modules/inliner/call.rb +327 -0
  31. data/lib/fastruby/{inliner/modules/call.rb → modules/inliner/call.rb~} +14 -24
  32. data/lib/fastruby/modules/inliner/defn.rb +41 -0
  33. data/lib/fastruby/modules/inliner/defn.rb~ +29 -0
  34. data/lib/fastruby/modules/inliner/recursive.rb +40 -0
  35. data/lib/fastruby/{inliner/modules/recursive.rb → modules/inliner/recursive.rb~} +1 -1
  36. data/lib/fastruby/modules/lvar_type/call.rb +36 -0
  37. data/lib/fastruby/modules/lvar_type/call.rb~ +36 -0
  38. data/lib/fastruby/modules/lvar_type/defn.rb +42 -0
  39. data/lib/fastruby/modules/lvar_type/defn.rb~ +42 -0
  40. data/lib/fastruby/modules/lvar_type/lasgn.rb +41 -0
  41. data/lib/fastruby/modules/lvar_type/lasgn.rb~ +42 -0
  42. data/lib/fastruby/modules/lvar_type/recursive.rb +33 -0
  43. data/lib/fastruby/modules/lvar_type/recursive.rb~ +33 -0
  44. data/lib/fastruby/{reductor/modules → modules/reductor}/case.rb +0 -0
  45. data/lib/fastruby/modules/reductor/fastruby_flag.rb +33 -0
  46. data/lib/fastruby/{reductor/modules → modules/reductor}/for.rb +0 -0
  47. data/lib/fastruby/{reductor/modules → modules/reductor}/nontree.rb +0 -0
  48. data/lib/fastruby/modules/reductor/nontree.rb~ +32 -0
  49. data/lib/fastruby/{reductor/modules → modules/reductor}/recursive.rb +1 -1
  50. data/lib/fastruby/modules/reductor/recursive.rb~ +31 -0
  51. data/lib/fastruby/{translator/modules → modules/translator}/block.rb +0 -0
  52. data/lib/fastruby/modules/translator/call.rb +344 -0
  53. data/lib/fastruby/{translator/modules/call.rb → modules/translator/call.rb~} +24 -3
  54. data/lib/fastruby/{translator/modules → modules/translator}/defn.rb +10 -9
  55. data/lib/fastruby/modules/translator/defn.rb~ +267 -0
  56. data/lib/fastruby/{translator/modules → modules/translator}/directive.rb +3 -1
  57. data/lib/fastruby/modules/translator/directive.rb~ +44 -0
  58. data/lib/fastruby/{translator/modules → modules/translator}/exceptions.rb +3 -1
  59. data/lib/fastruby/modules/translator/exceptions.rb~ +120 -0
  60. data/lib/fastruby/{translator/modules → modules/translator}/flow.rb +0 -0
  61. data/lib/fastruby/modules/translator/iter.rb +745 -0
  62. data/lib/fastruby/{translator/modules/iter.rb → modules/translator/iter.rb~} +103 -48
  63. data/lib/fastruby/modules/translator/literal.rb +150 -0
  64. data/lib/fastruby/{translator/modules/literal.rb → modules/translator/literal.rb~} +3 -3
  65. data/lib/fastruby/{translator/modules → modules/translator}/logical.rb +0 -0
  66. data/lib/fastruby/{translator/modules → modules/translator}/method_group.rb +0 -0
  67. data/lib/fastruby/{translator/modules → modules/translator}/nonlocal.rb +18 -6
  68. data/lib/fastruby/modules/translator/nonlocal.rb~ +298 -0
  69. data/lib/fastruby/modules/translator/static.rb +290 -0
  70. data/lib/fastruby/{translator/modules/static.rb → modules/translator/static.rb~} +66 -17
  71. data/lib/fastruby/modules/translator/variable.rb +280 -0
  72. data/lib/fastruby/{translator/modules/variable.rb → modules/translator/variable.rb~} +14 -44
  73. data/lib/fastruby/modules.rb +30 -0
  74. data/lib/fastruby/object.rb +42 -6
  75. data/lib/fastruby/object.rb~ +159 -0
  76. data/lib/fastruby/set_tree.rb +7 -11
  77. data/lib/fastruby/set_tree.rb~ +71 -0
  78. data/lib/fastruby/sexp_extension.rb +29 -7
  79. data/lib/fastruby/sexp_extension.rb~ +262 -0
  80. data/lib/fastruby/translator/scope_mode_helper.rb~ +138 -0
  81. data/lib/fastruby/translator/translator.rb +87 -92
  82. data/lib/fastruby/translator/translator.rb~ +1600 -0
  83. data/lib/fastruby/translator/translator_modules.rb +3 -1
  84. data/lib/fastruby/translator/translator_modules.rb~ +53 -0
  85. data/lib/fastruby.rb +3 -1
  86. data/lib/fastruby.rb~ +3 -1
  87. data/lib/fastruby_only/base.rb +1 -0
  88. data/spec/corelib/numeric/fixnum_spec.rb +110 -0
  89. data/spec/corelib/numeric/fixnum_spec.rb~ +104 -0
  90. data/spec/corelib/numeric/integer_spec.rb +173 -0
  91. data/spec/corelib/numeric/integer_spec.rb~ +173 -0
  92. data/spec/fastruby_only/base_spec.rb +74 -0
  93. data/spec/graph/base_spec.rb +2 -1
  94. data/spec/graph/base_spec.rb~ +35 -0
  95. data/spec/graph/path_spec.rb +2 -2
  96. data/spec/graph/path_spec.rb~ +48 -0
  97. data/spec/graph/vertex_spec.rb +2 -1
  98. data/spec/graph/vertex_spec.rb~ +58 -0
  99. data/spec/reductor/base_spec.rb +1 -1
  100. data/spec/ruby/block/lambda_spec.rb~ +163 -0
  101. data/spec/ruby/block/proc_as_block_spec.rb~ +69 -1
  102. data/spec/ruby/block_spec.rb~ +2 -494
  103. data/spec/ruby/call/base_call_spec.rb +1 -1
  104. data/spec/ruby/call/base_call_spec.rb~ +2 -60
  105. data/spec/ruby/defn/replacement_spec.rb +26 -14
  106. data/spec/ruby/defn/replacement_spec.rb~ +13 -3
  107. data/spec/ruby/exception/internal_ex_spec.rb~ +86 -0
  108. data/spec/ruby/integrity_spec.rb~ +35 -1
  109. data/spec/ruby/variable_spec.rb~ +31 -0
  110. data/spec/scope_mode/flow_spec.rb +1 -1
  111. data/spec/scope_mode/flow_spec.rb~ +109 -0
  112. data/spec/sugar/base_spec.rb +29 -0
  113. data/spec/sugar/base_spec.rb~ +16 -0
  114. metadata +100 -43
  115. data/spec/fastruby/inliner/modules/call_spec.rb +0 -0
  116. data/spec/fastruby/translator/modules/nonlocal_spec.rb +0 -0
  117. data/spec/fastruby/translator/translator_spec.rb +0 -0
  118. data/spec/ruby/block/arguments_spec.rb~ +0 -214
  119. data/spec/ruby/block/break_spec.rb~ +0 -236
  120. data/spec/ruby/block/next_spec.rb~ +0 -85
  121. data/spec/ruby/block/retry_spec.rb~ +0 -43
@@ -0,0 +1,745 @@
1
+ =begin
2
+
3
+ This file is part of the fastruby project, http://github.com/tario/fastruby
4
+
5
+ Copyright (c) 2011 Roberto Dario Seminara <robertodarioseminara@gmail.com>
6
+
7
+ fastruby is free software: you can redistribute it and/or modify
8
+ it under the terms of the gnu general public license as published by
9
+ the free software foundation, either version 3 of the license, or
10
+ (at your option) any later version.
11
+
12
+ fastruby is distributed in the hope that it will be useful,
13
+ but without any warranty; without even the implied warranty of
14
+ merchantability or fitness for a particular purpose. see the
15
+ gnu general public license for more details.
16
+
17
+ you should have received a copy of the gnu general public license
18
+ along with fastruby. if not, see <http://www.gnu.org/licenses/>.
19
+
20
+ =end
21
+ module FastRuby
22
+ class Context
23
+
24
+ define_translator_for(:iter, :method => :to_c_iter)
25
+ def to_c_iter(tree, result_var = nil)
26
+
27
+ call_tree = tree[1]
28
+ args_tree = tree[2]
29
+ recv_tree = call_tree[1]
30
+
31
+ directive_code = directive(call_tree)
32
+ if directive_code
33
+ if result_var
34
+ return "#{result_var} = #{directive_code};\n"
35
+ else
36
+ return directive_code
37
+ end
38
+ end
39
+
40
+ other_call_tree = call_tree.dup
41
+ other_call_tree[1] = s(:lvar, :arg)
42
+
43
+ mname = call_tree[2]
44
+
45
+ call_args_tree = call_tree[3]
46
+
47
+ caller_code = nil
48
+
49
+ recvtype = infer_type(recv_tree || s(:self))
50
+
51
+ address = nil
52
+ mobject = nil
53
+ len = nil
54
+
55
+ if recvtype
56
+
57
+ inference_complete = true
58
+ signature = [recvtype]
59
+
60
+ call_args_tree[1..-1].each do |arg|
61
+ argtype = infer_type(arg)
62
+ if argtype
63
+ signature << argtype
64
+ else
65
+ inference_complete = false
66
+ end
67
+ end
68
+ end
69
+
70
+ anonymous_impl = tree[3]
71
+
72
+ str_lvar_initialization = "#{@frame_struct} *pframe;
73
+ #{@locals_struct} *plocals;
74
+
75
+ "
76
+
77
+ str_arg_initialization = ""
78
+
79
+ str_impl = ""
80
+ on_block do
81
+ str_impl = to_c(anonymous_impl, "last_expression")
82
+ end
83
+
84
+ if not args_tree
85
+ elsif args_tree.first == :lasgn
86
+ if RUBY_VERSION =~ /^1\.8/
87
+ str_arg_initialization << "plocals->#{args_tree[1]} = arg;"
88
+ elsif RUBY_VERSION =~ /^1\.9/
89
+ str_arg_initialization << "
90
+ if (TYPE(arg) != T_ARRAY) {
91
+ plocals->#{args_tree[1]} = arg;
92
+ } else {
93
+ plocals->#{args_tree[1]} = rb_ary_entry(arg,0);
94
+ }
95
+ "
96
+ end
97
+ elsif args_tree.first == :masgn
98
+
99
+ if RUBY_VERSION =~ /^1\.8/
100
+ str_arg_initialization << "
101
+ {
102
+ if (TYPE(arg) != T_ARRAY) {
103
+ if (arg != Qnil) {
104
+ arg = rb_ary_new4(1,&arg);
105
+ } else {
106
+ arg = rb_ary_new2(0);
107
+ }
108
+ } else if (_RARRAY_LEN(arg) <= 1) {
109
+ arg = rb_ary_new4(1,&arg);
110
+ }
111
+ }
112
+ "
113
+ elsif RUBY_VERSION =~ /^1\.9/
114
+ str_arg_initialization << "
115
+ {
116
+ }
117
+ "
118
+ end
119
+
120
+ arguments = args_tree[1][1..-1]
121
+
122
+ (0..arguments.size-1).each do |i|
123
+ arg = arguments[i]
124
+ if arg[0] == :lasgn
125
+ str_arg_initialization << "plocals->#{arguments[i].last} = rb_ary_entry(arg,#{i});\n"
126
+ elsif arg[0] == :splat
127
+ str_arg_initialization << "plocals->#{arg.last.last} = rb_ary_new2(_RARRAY_LEN(arg)-#{i});\n
128
+
129
+ int i;
130
+ for (i=#{i};i<_RARRAY_LEN(arg);i++){
131
+ rb_ary_store(plocals->#{arg.last.last},i-#{i},rb_ary_entry(arg,i));
132
+ }
133
+ "
134
+ end
135
+ end
136
+ end
137
+ str_recv = "pframe->next_recv"
138
+ str_recv = "plocals->self" unless recv_tree
139
+
140
+ strargs = if call_args_tree.size > 1
141
+ "," + (0..call_args_tree.size-2).map{|i| "arg#{i}"}.join(",")
142
+ else
143
+ ""
144
+ end
145
+
146
+ str_evaluate_args = ""
147
+
148
+ rb_funcall_caller_code = proc { |name, call_type| "
149
+ static VALUE #{name}(VALUE param) {
150
+ // call to #{call_tree[2]}
151
+ VALUE last_expression = Qnil;
152
+ VALUE* args_array = (VALUE*)param;
153
+
154
+ #{str_lvar_initialization}
155
+ pframe = (void*)args_array[0];
156
+ plocals = (void*)pframe->plocals;
157
+ #{str_evaluate_args};
158
+
159
+ VALUE ret = rb_funcall(#{str_recv}, #{intern_num call_tree[2]}, #{call_args_tree.size-1} #{strargs});
160
+ #{
161
+ if call_type == :lambda
162
+ "
163
+
164
+ // freeze all stacks
165
+ struct FASTRUBYTHREADDATA* thread_data = rb_current_thread_data();
166
+
167
+ if (thread_data != 0) {
168
+ VALUE rb_stack_chunk = thread_data->rb_stack_chunk;
169
+
170
+ // add reference to stack chunk to lambda object
171
+ rb_ivar_set(ret,#{intern_num :_fastruby_stack_chunk},rb_stack_chunk);
172
+
173
+ // freeze the complete chain of stack chunks
174
+ while (rb_stack_chunk != Qnil) {
175
+ struct STACKCHUNK* stack_chunk;
176
+ Data_Get_Struct(rb_stack_chunk,struct STACKCHUNK,stack_chunk);
177
+
178
+ stack_chunk_freeze(stack_chunk);
179
+
180
+ rb_stack_chunk = rb_ivar_get(rb_stack_chunk,#{intern_num :_parent_stack_chunk});
181
+ }
182
+ }
183
+ "
184
+ end
185
+ }
186
+ return ret;
187
+ }
188
+ "
189
+ }
190
+
191
+
192
+ if call_args_tree.size > 1
193
+ if call_args_tree.last[0] == :splat
194
+ rb_funcall_caller_code = proc { |name,call_type| "
195
+ static VALUE #{name}(VALUE param) {
196
+ // call to #{call_tree[2]}
197
+
198
+ VALUE* args_array = (VALUE*)param;
199
+ int argc = args_array[1];
200
+ VALUE* argv = (VALUE*)args_array[2];
201
+
202
+ VALUE last_expression = Qnil;
203
+ #{str_lvar_initialization}
204
+
205
+ pframe = (void*)args_array[0];
206
+ plocals = (void*)pframe->plocals;
207
+
208
+ return rb_funcall2(#{str_recv}, #{intern_num call_tree[2]}, argc, argv);
209
+ }
210
+ "
211
+ }
212
+ else
213
+ str_evaluate_args = "
214
+ #{
215
+ (0..call_args_tree.size-2).map{|i|
216
+ "VALUE arg#{i} = args_array[#{i+1}];"
217
+ }.join("\n")
218
+ }
219
+
220
+ "
221
+ end
222
+ end
223
+
224
+ argument_array_read = "
225
+ VALUE arg;
226
+ #{
227
+ # TODO: access directly to argc and argv for optimal execution
228
+ if RUBY_VERSION =~ /^1\.9/
229
+ "
230
+ if (TYPE(arg_) == T_ARRAY) {
231
+ if (_RARRAY_LEN(arg_) <= 1) {
232
+ arg = rb_ary_new4(argc,argv);
233
+ } else {
234
+ arg = arg_;
235
+ }
236
+ } else {
237
+ arg = rb_ary_new4(argc,argv);
238
+ }
239
+ "
240
+ else
241
+ "arg = arg_;"
242
+ end
243
+ }
244
+ "
245
+
246
+ rb_funcall_block_code = proc { |name,call_type| "
247
+ static VALUE #{name}(VALUE arg_, VALUE _plocals, int argc, VALUE* argv) {
248
+ // block for call to #{call_tree[2]}
249
+ #{argument_array_read}
250
+
251
+ volatile VALUE last_expression = Qnil;
252
+
253
+ #{@frame_struct} frame;
254
+ #{@frame_struct} * volatile pframe = (void*)&frame;
255
+ #{@locals_struct} * volatile plocals = (void*)_plocals;
256
+
257
+ frame.plocals = plocals;
258
+ frame.parent_frame = 0;
259
+ frame.return_value = Qnil;
260
+ frame.rescue = 0;
261
+ frame.targetted = 0;
262
+ frame.thread_data = rb_current_thread_data();
263
+
264
+ #{str_arg_initialization}
265
+
266
+ #{
267
+ if call_type == :lambda or call_type == :proc_new
268
+ "
269
+ void* volatile old_call_frame = ((typeof(plocals))(pframe->plocals))->call_frame;
270
+ ((typeof(plocals))(pframe->plocals))->call_frame = pframe;
271
+ "
272
+ end
273
+ }
274
+
275
+ int aux = setjmp(frame.jmp);
276
+ if (aux != 0) {
277
+
278
+ if (aux == FASTRUBY_TAG_NEXT) {
279
+ last_expression = pframe->thread_data->accumulator;
280
+ goto fastruby_local_next;
281
+ } else if (aux == FASTRUBY_TAG_REDO) {
282
+ // do nothing and let execute the block again
283
+ #{
284
+ if call_type == :lambda
285
+ "
286
+
287
+ } else if (aux == FASTRUBY_TAG_BREAK) {
288
+ last_expression = frame.return_value;
289
+ typeof(pframe) target_frame_ = (void*)plocals->call_frame;
290
+
291
+ if (target_frame_ == 0) {
292
+ goto fastruby_local_next;
293
+ } else {
294
+ if (target_frame_->targetted == 1) {
295
+ goto fastruby_local_next;
296
+ } else {
297
+ #{_raise("rb_eLocalJumpError","illegal break")};
298
+ }
299
+ }
300
+ "
301
+ end
302
+ }
303
+ #{
304
+ if call_type == :lambda or call_type == :proc_new
305
+ "
306
+ } else if (aux == FASTRUBY_TAG_RAISE) {
307
+ rb_funcall(((typeof(plocals))(pframe->plocals))->self, #{intern_num :raise}, 1, frame.thread_data->exception);
308
+ return Qnil;
309
+ "
310
+ end
311
+ }
312
+ } else {
313
+ #{
314
+ case call_type
315
+ when :proc_new
316
+ "
317
+ _local_return:
318
+ if (plocals->targetted == 1) {
319
+ if (plocals->active == Qfalse) {
320
+ rb_raise(rb_eLocalJumpError,\"return from proc-closure\");
321
+ } else {
322
+ ((typeof(plocals))(pframe->plocals))->call_frame = old_call_frame;
323
+ frb_jump_tag(aux);
324
+ }
325
+ } else {
326
+ rb_raise(rb_eLocalJumpError, \"unexpected return\");
327
+ }
328
+ "
329
+ when :lambda
330
+ "
331
+ if (aux == FASTRUBY_TAG_RETURN) {
332
+ if (plocals->targetted == 1) {
333
+ last_expression = ((typeof(plocals))(pframe->plocals))->return_value;
334
+ goto fastruby_local_next;
335
+
336
+ } else {
337
+ rb_raise(rb_eLocalJumpError, \"unexpected return\");
338
+ }
339
+ } else {
340
+ rb_raise(rb_eLocalJumpError, \"unexpected return\");
341
+ }
342
+ "
343
+ else
344
+ "
345
+ frb_jump_tag(aux);
346
+ return frame.return_value;
347
+ "
348
+ end
349
+ }
350
+
351
+ }
352
+ }
353
+
354
+ #{
355
+ if call_type == :callcc
356
+ "
357
+ if (rb_obj_is_kind_of(arg, rb_const_get(rb_cObject, #{intern_num :Continuation}))) {
358
+ struct FASTRUBYTHREADDATA* thread_data = frame.thread_data;
359
+ rb_ivar_set(arg,#{intern_num :__stack_chunk},thread_data->rb_stack_chunk);
360
+ }
361
+ "
362
+ end
363
+ }
364
+
365
+ fastruby_local_redo:
366
+ #{str_impl};
367
+
368
+ #{
369
+ case call_type
370
+ when :proc_new
371
+ "
372
+ return last_expression;
373
+ local_return:
374
+ aux = FASTRUBY_TAG_RETURN;
375
+ plocals->return_value = last_expression;
376
+ plocals->targetted = 1;
377
+ goto _local_return;
378
+ "
379
+ when :lambda
380
+ "
381
+ local_return:
382
+ "
383
+ else
384
+ "
385
+ return last_expression;
386
+ local_return:
387
+ plocals->return_value = last_expression;
388
+ plocals->targetted = 1;
389
+ frb_jump_tag(FASTRUBY_TAG_RETURN);
390
+ "
391
+ end
392
+ }
393
+
394
+
395
+ fastruby_local_next:
396
+ #{
397
+ if call_type == :proc_new or call_type == :lambda
398
+ "
399
+ ((typeof(plocals))(pframe->plocals))->call_frame = old_call_frame;
400
+ "
401
+ end
402
+ }
403
+ return last_expression;
404
+ }
405
+ "
406
+ }
407
+
408
+ fastruby_str_arg_initialization = ""
409
+
410
+ if not args_tree
411
+ fastruby_str_arg_initialization = ""
412
+ elsif args_tree.first == :lasgn
413
+ fastruby_str_arg_initialization = "plocals->#{args_tree[1]} = argv[0];"
414
+ elsif args_tree.first == :masgn
415
+ arguments = args_tree[1][1..-1]
416
+
417
+ (0..arguments.size-1).each do |i|
418
+ arg = arguments[i]
419
+ if arg[0] == :lasgn
420
+ fastruby_str_arg_initialization << "plocals->#{arg.last} = #{i} < argc ? argv[#{i}] : Qnil;\n"
421
+ elsif arg[0] == :splat
422
+ fastruby_str_arg_initialization << "plocals->#{arg.last.last} = rb_ary_new2(#{arguments.size-1-i});\n
423
+ {
424
+ int i;
425
+ for (i=#{i};i<argc;i++){
426
+ rb_ary_store(plocals->#{arg.last.last},i-#{i},argv[i]);
427
+ }
428
+ }
429
+ "
430
+ end
431
+ end
432
+ end
433
+
434
+ block_code = proc { |name| "
435
+ static VALUE #{name}(int argc, VALUE* argv, VALUE _locals, VALUE _parent_frame) {
436
+ // block for call to #{call_tree[2]}
437
+ volatile VALUE last_expression = Qnil;
438
+ #{@frame_struct} frame;
439
+ #{@frame_struct} * volatile pframe = (void*)&frame;
440
+ #{@frame_struct} * volatile parent_frame = (void*)_parent_frame;
441
+ #{@locals_struct} * volatile plocals;
442
+
443
+ frame.plocals = (void*)_locals;
444
+ frame.parent_frame = parent_frame;
445
+ frame.return_value = Qnil;
446
+ frame.rescue = 0;
447
+ frame.targetted = 0;
448
+ frame.thread_data = parent_frame->thread_data;
449
+ if (frame.thread_data == 0) frame.thread_data = rb_current_thread_data();
450
+
451
+ plocals = frame.plocals;
452
+
453
+ #{fastruby_str_arg_initialization}
454
+
455
+ int aux = setjmp(frame.jmp);
456
+ if (aux != 0) {
457
+ if (pframe->targetted == 0) {
458
+ if (aux == FASTRUBY_TAG_NEXT) {
459
+ return pframe->thread_data->accumulator;
460
+ } else if (aux == FASTRUBY_TAG_REDO) {
461
+ // do nothing and let execute the block again
462
+ } else {
463
+ longjmp(((typeof(pframe))_parent_frame)->jmp,aux);
464
+ }
465
+ }
466
+
467
+ }
468
+
469
+ fastruby_local_redo:
470
+ #{str_impl};
471
+
472
+ return last_expression;
473
+ local_return:
474
+ plocals->return_value = last_expression;
475
+ plocals->targetted = 1;
476
+ longjmp(pframe->jmp, FASTRUBY_TAG_RETURN);
477
+ fastruby_local_next:
478
+ return last_expression; }
479
+ "
480
+ }
481
+
482
+ caller_code = nil
483
+ convention_global_name = add_global_name("int",0)
484
+
485
+ precode = "
486
+ struct FASTRUBYTHREADDATA* thread_data = 0;
487
+ VALUE saved_rb_stack_chunk = Qnil;
488
+
489
+ VALUE next_recv = plocals->self;
490
+
491
+ #{
492
+ if recv_tree
493
+ to_c recv_tree, "next_recv"
494
+ end
495
+ };
496
+
497
+ pframe->next_recv = next_recv;
498
+ #ifdef RUBY_1_8
499
+ NODE* node = rb_method_node(CLASS_OF(pframe->next_recv), #{intern_num mname});
500
+ #endif
501
+ #ifdef RUBY_1_9
502
+ void* node = rb_method_entry(CLASS_OF(pframe->next_recv), #{intern_num mname});
503
+ #endif
504
+
505
+ if (node == #{@callcc_node_gvar}) {
506
+
507
+ // freeze all stacks
508
+ thread_data = rb_current_thread_data();
509
+
510
+ if (thread_data != 0) {
511
+ VALUE rb_stack_chunk = thread_data->rb_stack_chunk;
512
+ saved_rb_stack_chunk = rb_stack_chunk;
513
+
514
+ // freeze the complete chain of stack chunks
515
+ while (rb_stack_chunk != Qnil) {
516
+ struct STACKCHUNK* stack_chunk;
517
+ Data_Get_Struct(rb_stack_chunk,struct STACKCHUNK,stack_chunk);
518
+
519
+ stack_chunk_freeze(stack_chunk);
520
+
521
+ rb_stack_chunk = rb_ivar_get(rb_stack_chunk,#{intern_num :_parent_stack_chunk});
522
+ }
523
+ }
524
+ }
525
+ "
526
+
527
+ postcode = "
528
+ if (node == #{@callcc_node_gvar}) {
529
+ thread_data->rb_stack_chunk = saved_rb_stack_chunk;
530
+ }
531
+ "
532
+
533
+
534
+ funcall_call_code = "
535
+ #{
536
+ frame_call(
537
+ "ret = " + protected_block("
538
+
539
+ void* caller_func;
540
+ void* block_func;
541
+ typeof(plocals) current_plocals;
542
+
543
+ if (pframe->thread_data == 0) pframe->thread_data = rb_current_thread_data();
544
+ void* last_plocals = pframe->thread_data->last_plocals;
545
+
546
+ #ifdef RUBY_1_8
547
+ NODE* node = rb_method_node(CLASS_OF(pframe->next_recv), #{intern_num mname});
548
+ #endif
549
+ #ifdef RUBY_1_9
550
+ void* node = rb_method_entry(CLASS_OF(pframe->next_recv), #{intern_num mname});
551
+ #endif
552
+
553
+ if (
554
+ node == #{@proc_node_gvar} ||
555
+ node == #{@lambda_node_gvar}
556
+ ) {
557
+
558
+ caller_func = #{anonymous_function(:lambda,&rb_funcall_caller_code)};
559
+ block_func = #{anonymous_function(:lambda,&rb_funcall_block_code)};
560
+ } else if (node == #{@procnew_node_gvar} && pframe->next_recv == rb_cProc) {
561
+ caller_func = #{anonymous_function(:lambda,&rb_funcall_caller_code)};
562
+ block_func = #{anonymous_function(:proc_new,&rb_funcall_block_code)};
563
+ } else if (node == #{@callcc_node_gvar}) {
564
+ caller_func = #{anonymous_function(:normal,&rb_funcall_caller_code)};
565
+ block_func = #{anonymous_function(:callcc,&rb_funcall_block_code)};
566
+ } else {
567
+ caller_func = #{anonymous_function(:normal,&rb_funcall_caller_code)};
568
+ block_func = #{anonymous_function(:normal,&rb_funcall_block_code)};
569
+ }
570
+
571
+
572
+ #{if call_args_tree.size > 1 and call_args_tree.last[0] == :splat
573
+ "
574
+ VALUE args_array[3];
575
+ VALUE array = Qnil;
576
+
577
+ #{to_c call_args_tree.last[1], "array"};
578
+
579
+ if (TYPE(array) != T_ARRAY) {
580
+ array = rb_ary_new4(1,&array);
581
+ }
582
+
583
+ int argc = #{call_args_tree.size-2};
584
+ VALUE argv[#{call_args_tree.size} + _RARRAY_LEN(array)];
585
+
586
+ VALUE aux_ = Qnil;;
587
+ #{
588
+ i = -1
589
+ call_args_tree[1..-2].map {|arg|
590
+ i = i + 1
591
+ "
592
+ #{to_c arg, "aux_"};
593
+ argv[#{i}] = aux_;
594
+ "
595
+ }.join(";\n")
596
+ };
597
+
598
+ int array_len = _RARRAY_LEN(array);
599
+
600
+ int i;
601
+ for (i=0; i<array_len;i++) {
602
+ argv[argc] = rb_ary_entry(array,i);
603
+ argc++;
604
+ }
605
+
606
+ args_array[0] = (VALUE)pframe;
607
+ args_array[1] = (VALUE)argc;
608
+ args_array[2] = (VALUE)argv;
609
+
610
+ last_expression = rb_iterate(
611
+ caller_func,
612
+ (VALUE)args_array,
613
+ block_func,
614
+ (VALUE)plocals);
615
+
616
+ "
617
+ else
618
+ "
619
+
620
+ VALUE args_array[#{call_args_tree.size+2}];
621
+ VALUE aux___ = Qnil;
622
+ args_array[0] = (VALUE)pframe;
623
+
624
+ #{
625
+ (0..call_args_tree.size-2).map{|i|
626
+ to_c(call_args_tree[i+1], "aux___")+";"+
627
+ "args_array[#{i+1}] = aux___;"
628
+ }.join("\n")
629
+ }
630
+
631
+ last_expression = rb_iterate(
632
+ caller_func,
633
+ (VALUE)args_array,
634
+ block_func,
635
+ (VALUE)plocals);
636
+ "
637
+ end
638
+ }
639
+ if (node == #{@callcc_node_gvar}) {
640
+
641
+ // remove active flags of abandoned stack
642
+ current_plocals = pframe->thread_data->last_plocals;
643
+ while (current_plocals) {
644
+ current_plocals->active = Qfalse;
645
+ current_plocals = (typeof(current_plocals))(current_plocals->parent_locals);
646
+ }
647
+
648
+ // restore last_plocals
649
+ pframe->thread_data->last_plocals = last_plocals;
650
+
651
+ // mark all scopes as active
652
+ current_plocals = last_plocals;
653
+
654
+ while (current_plocals) {
655
+ current_plocals->active = Qtrue;
656
+ current_plocals = (typeof(current_plocals))(current_plocals->parent_locals);
657
+ }
658
+ }
659
+ ", true), precode, postcode
660
+ )
661
+ };
662
+ "
663
+
664
+ recvtype = nil if call_args_tree.size > 1 ? call_args_tree.last[0] == :splat : false
665
+ unless recvtype
666
+ if result_var
667
+ "#{result_var} = #{funcall_call_code};"
668
+ else
669
+ funcall_call_code
670
+ end
671
+ else
672
+ encoded_address = encode_address(recvtype,signature,mname,call_tree,inference_complete,convention_global_name, true)
673
+
674
+ if call_args_tree.size > 1
675
+ strargs = (0..call_args_tree.size-2).map{|i| "arg#{i}"}.join(",")
676
+ else
677
+ strargs = ""
678
+ end
679
+
680
+ fastruby_call_code = "
681
+ // call to #{call_tree[2]}
682
+ #{
683
+ if call_args_tree.size > 1
684
+ " #{
685
+ (0..call_args_tree.size-2).map{|i|
686
+ "VALUE arg#{i} = Qnil;"
687
+ }.join("\n")
688
+ }
689
+
690
+ #{
691
+ (0..call_args_tree.size-2).map{|i|
692
+ to_c(call_args_tree[i+1], "arg#{i}")+";"
693
+ }.join("\n")
694
+ }
695
+ "
696
+ end
697
+ };
698
+
699
+ VALUE recv = plocals->self;
700
+
701
+ #{
702
+ if recv_tree
703
+ to_c recv_tree, "recv"
704
+ end
705
+ }
706
+
707
+ ret = ((VALUE(*)(VALUE,VALUE,VALUE,int,VALUE*))#{encoded_address})(recv, (VALUE)&block, (VALUE)&call_frame, #{call_args_tree.size-1}, (VALUE[]){#{strargs}});
708
+ "
709
+
710
+ code = "
711
+ if (#{@last_address_name} == 0) {
712
+ return #{funcall_call_code};
713
+ } else {
714
+ #{if recvtype and inference_complete
715
+ "if (*#{@last_address_name} == 0) {
716
+ rb_funcall(#{literal_value recvtype},#{intern_num :build}, 2, #{literal_value signature}, #{literal_value mname});
717
+ }
718
+ "
719
+ end
720
+ }
721
+ if (*#{@last_address_name} == 0) {
722
+ return #{funcall_call_code};
723
+ } else {
724
+ #{fastruby_call_code}
725
+ }
726
+ }
727
+ "
728
+
729
+ fastruby_precode = " #{@block_struct} block;
730
+
731
+ block.block_function_address = ((void*)#{anonymous_function(&block_code)});
732
+ block.block_function_param = ((void*)plocals);
733
+ block.proc = Qnil;
734
+ "
735
+
736
+ if result_var
737
+ "#{result_var} = #{frame_call(code,fastruby_precode,"")}"
738
+ else
739
+ frame_call(code,fastruby_precode,"")
740
+ end
741
+
742
+ end
743
+ end
744
+ end
745
+ end