mutant-melbourne 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. data/LICENSE +25 -0
  2. data/README.md +69 -0
  3. data/Rakefile +14 -0
  4. data/ext/melbourne/.gitignore +3 -0
  5. data/ext/melbourne/bstring-license.txt +29 -0
  6. data/ext/melbourne/bstrlib.c +2687 -0
  7. data/ext/melbourne/bstrlib.h +267 -0
  8. data/ext/melbourne/encoding_compat.cpp +188 -0
  9. data/ext/melbourne/encoding_compat.hpp +57 -0
  10. data/ext/melbourne/extconf.rb +87 -0
  11. data/ext/melbourne/grammar18.cpp +11280 -0
  12. data/ext/melbourne/grammar18.hpp +13 -0
  13. data/ext/melbourne/grammar18.y +6088 -0
  14. data/ext/melbourne/grammar19.cpp +12420 -0
  15. data/ext/melbourne/grammar19.hpp +11 -0
  16. data/ext/melbourne/grammar19.y +7113 -0
  17. data/ext/melbourne/lex.c.blt +152 -0
  18. data/ext/melbourne/lex.c.tab +136 -0
  19. data/ext/melbourne/local_state.hpp +43 -0
  20. data/ext/melbourne/melbourne.cpp +88 -0
  21. data/ext/melbourne/melbourne.hpp +19 -0
  22. data/ext/melbourne/node18.hpp +262 -0
  23. data/ext/melbourne/node19.hpp +271 -0
  24. data/ext/melbourne/node_types.rb +304 -0
  25. data/ext/melbourne/node_types18.cpp +255 -0
  26. data/ext/melbourne/node_types18.hpp +129 -0
  27. data/ext/melbourne/node_types19.cpp +249 -0
  28. data/ext/melbourne/node_types19.hpp +126 -0
  29. data/ext/melbourne/parser_state18.hpp +181 -0
  30. data/ext/melbourne/parser_state19.hpp +251 -0
  31. data/ext/melbourne/quark.cpp +42 -0
  32. data/ext/melbourne/quark.hpp +45 -0
  33. data/ext/melbourne/symbols.cpp +224 -0
  34. data/ext/melbourne/symbols.hpp +119 -0
  35. data/ext/melbourne/var_table18.cpp +83 -0
  36. data/ext/melbourne/var_table18.hpp +33 -0
  37. data/ext/melbourne/var_table19.cpp +65 -0
  38. data/ext/melbourne/var_table19.hpp +35 -0
  39. data/ext/melbourne/visitor18.cpp +963 -0
  40. data/ext/melbourne/visitor18.hpp +12 -0
  41. data/ext/melbourne/visitor19.cpp +960 -0
  42. data/ext/melbourne/visitor19.hpp +15 -0
  43. data/lib/compiler/ast/constants.rb +81 -0
  44. data/lib/compiler/ast/control_flow.rb +290 -0
  45. data/lib/compiler/ast/data.rb +14 -0
  46. data/lib/compiler/ast/definitions.rb +749 -0
  47. data/lib/compiler/ast/encoding.rb +18 -0
  48. data/lib/compiler/ast/exceptions.rb +138 -0
  49. data/lib/compiler/ast/file.rb +11 -0
  50. data/lib/compiler/ast/grapher.rb +89 -0
  51. data/lib/compiler/ast/literals.rb +207 -0
  52. data/lib/compiler/ast/node.rb +362 -0
  53. data/lib/compiler/ast/operators.rb +106 -0
  54. data/lib/compiler/ast/self.rb +15 -0
  55. data/lib/compiler/ast/sends.rb +615 -0
  56. data/lib/compiler/ast/transforms.rb +298 -0
  57. data/lib/compiler/ast/values.rb +88 -0
  58. data/lib/compiler/ast/variables.rb +351 -0
  59. data/lib/compiler/ast.rb +20 -0
  60. data/lib/compiler/locals.rb +109 -0
  61. data/lib/melbourne/processor.rb +651 -0
  62. data/lib/melbourne/version.rb +3 -0
  63. data/lib/melbourne.rb +143 -0
  64. metadata +112 -0
@@ -0,0 +1,963 @@
1
+ #include <sstream>
2
+
3
+ #include "melbourne.hpp"
4
+ #include "parser_state18.hpp"
5
+ #include "visitor18.hpp"
6
+ #include "symbols.hpp"
7
+
8
+ namespace melbourne {
9
+ namespace grammar18 {
10
+
11
+ static VALUE string_newfrombstr(bstring str)
12
+ {
13
+ if(str == NULL) {
14
+ return rb_str_new2("");
15
+ }
16
+
17
+ return rb_str_new((const char*)str->data, str->slen);
18
+ }
19
+
20
+ void create_error(rb_parser_state *parser_state, char *msg) {
21
+ VALUE err_msg;
22
+
23
+ // Cleanup one of the common and ugly syntax errors.
24
+ if(std::string("syntax error, unexpected $end, expecting kEND") ==
25
+ std::string(msg)) {
26
+ if(start_lines->size() > 0) {
27
+ StartPosition& pos = start_lines->back();
28
+
29
+ std::ostringstream ss;
30
+ ss << "missing 'end' for '"
31
+ << pos.kind
32
+ << "' started on line "
33
+ << pos.line;
34
+ err_msg = rb_str_new2(ss.str().c_str());
35
+
36
+ } else {
37
+ err_msg = rb_str_new2("missing 'end' for unknown start");
38
+ }
39
+ } else {
40
+ err_msg = 0;
41
+
42
+ std::string pmsg(msg);
43
+ std::string comma(", ");
44
+
45
+ size_t one = pmsg.find(comma);
46
+ if(one != std::string::npos) {
47
+ size_t two = pmsg.find(comma, one+1);
48
+ if(two != std::string::npos) {
49
+ std::string sub = pmsg.substr(two+2);
50
+
51
+ err_msg = rb_str_new2(sub.c_str());
52
+ }
53
+ }
54
+
55
+ if(!err_msg) err_msg = rb_str_new2(msg);
56
+ }
57
+
58
+ int col = (int)(lex_p - lex_pbeg);
59
+
60
+ rb_funcall(processor,
61
+ rb_intern("process_parse_error"),4,
62
+ err_msg,
63
+ INT2FIX(col),
64
+ INT2FIX(ruby_sourceline),
65
+ string_newfrombstr(lex_lastline));
66
+
67
+ parse_error = true;
68
+ }
69
+
70
+ const char *op_to_name(rb_parser_state* parser_state, QUID id);
71
+
72
+
73
+ static VALUE quark_to_symbol(rb_parser_state* parser_state, quark quark) {
74
+ const char *op;
75
+ if((op = op_to_name(parser_state, quark)) ||
76
+ (op = quark_to_string(parser_state, id_to_quark(parser_state, quark)))) {
77
+ return ID2SYM(rb_intern(op));
78
+ } else {
79
+ fprintf(stderr,
80
+ "unable to retrieve string from parser symbol(quark: %#zx, id: %#zx)\n",
81
+ quark, id_to_quark(parser_state, quark));
82
+ abort();
83
+ }
84
+ }
85
+
86
+ #define nd_3rd u3.node
87
+ #define Q2SYM(v) quark_to_symbol(parser_state, v)
88
+
89
+ VALUE process_parse_tree(rb_parser_state*, VALUE, NODE*, QUID*);
90
+
91
+ static VALUE process_dynamic(rb_parser_state *parser_state,
92
+ VALUE ptp, NODE *node, QUID *locals)
93
+ {
94
+ VALUE array = rb_ary_new();
95
+
96
+ while(node) {
97
+ if (node->nd_head) {
98
+ rb_ary_push(array, process_parse_tree(parser_state, ptp, node->nd_head, locals));
99
+ }
100
+ node = node->nd_next;
101
+ }
102
+
103
+ return array;
104
+ }
105
+
106
+ static VALUE process_iter(rb_parser_state *parser_state, VALUE ptp, NODE *node,
107
+ QUID *locals, int *level, ID method, VALUE line)
108
+ {
109
+ VALUE iter, body, args;
110
+
111
+ iter = process_parse_tree(parser_state, ptp, node->nd_iter, locals);
112
+ (*level)++;
113
+ if (node->nd_var != (NODE *)1
114
+ && node->nd_var != (NODE *)2
115
+ && node->nd_var != NULL) {
116
+ args = process_parse_tree(parser_state, ptp, node->nd_var, locals);
117
+ } else {
118
+ if (node->nd_var == NULL) {
119
+ // e.g. proc {}
120
+ args = Qnil;
121
+ } else {
122
+ // e.g. proc {||}
123
+ args = INT2FIX(0);
124
+ }
125
+ }
126
+ (*level)--;
127
+ body = process_parse_tree(parser_state, ptp, node->nd_body, locals);
128
+ return rb_funcall(ptp, method, 4, line, iter, args, body);
129
+ }
130
+
131
+ /* Visits all the nodes in the parse tree.
132
+ * Adapted from ParseTree by Ryan Davis and Eric Hodel.
133
+ */
134
+ VALUE process_parse_tree(rb_parser_state *parser_state,
135
+ VALUE ptp, NODE *n, QUID *locals)
136
+ {
137
+ NODE * volatile node = n;
138
+
139
+ static int masgn_level = 0;
140
+ static unsigned case_level = 0;
141
+ static unsigned when_level = 0;
142
+ static unsigned inside_case_args = 0;
143
+
144
+ VALUE line, tree = Qnil;
145
+
146
+ if(!node) return tree;
147
+
148
+ again:
149
+
150
+ if(node) {
151
+ line = INT2FIX(nd_line(node));
152
+ } else {
153
+ return rb_funcall(ptp, rb_intern("process_dangling_node"), 0);
154
+ }
155
+
156
+ switch(nd_type(node)) {
157
+
158
+ case NODE_BLOCK: {
159
+ VALUE array = rb_ary_new();
160
+
161
+ while (node) {
162
+ rb_ary_push(array, process_parse_tree(parser_state, ptp, node->nd_head, locals));
163
+ node = node->nd_next;
164
+ }
165
+ tree = rb_funcall(ptp, rb_sBlock, 2, line, array);
166
+ break;
167
+ }
168
+ case NODE_DEFINED: {
169
+ VALUE expr = process_parse_tree(parser_state, ptp, node->nd_head, locals);
170
+ tree = rb_funcall(ptp, rb_sDefined, 2, line, expr);
171
+ break;
172
+ }
173
+ case NODE_COLON2: {
174
+ VALUE container = process_parse_tree(parser_state, ptp, node->nd_head, locals);
175
+ tree = rb_funcall(ptp, rb_sColon2, 3, line,
176
+ container, Q2SYM(node->nd_mid));
177
+ break;
178
+ }
179
+ case NODE_MATCH2: {
180
+ VALUE pattern = process_parse_tree(parser_state, ptp, node->nd_recv, locals);
181
+ VALUE value = process_parse_tree(parser_state, ptp, node->nd_value, locals);
182
+ tree = rb_funcall(ptp, rb_sMatch2, 3, line, pattern, value);
183
+ break;
184
+ }
185
+ case NODE_MATCH3: {
186
+ VALUE pattern = process_parse_tree(parser_state, ptp, node->nd_recv, locals);
187
+ VALUE value = process_parse_tree(parser_state, ptp, node->nd_value, locals);
188
+ tree = rb_funcall(ptp, rb_sMatch3, 3, line, pattern, value);
189
+ break;
190
+ }
191
+ case NODE_BEGIN: {
192
+ VALUE body = process_parse_tree(parser_state, ptp, node->nd_body, locals);
193
+ tree = rb_funcall(ptp, rb_sBegin, 2, line, body);
194
+ break;
195
+ }
196
+ case NODE_NOT: {
197
+ VALUE expr = process_parse_tree(parser_state, ptp, node->nd_body, locals);
198
+ tree = rb_funcall(ptp, rb_sNot, 2, line, expr);
199
+ break;
200
+ }
201
+ case NODE_IF: {
202
+ VALUE cond, body = Qnil, else_body = Qnil;
203
+
204
+ cond = process_parse_tree(parser_state, ptp, node->nd_cond, locals);
205
+ if (node->nd_body) {
206
+ body = process_parse_tree(parser_state, ptp, node->nd_body, locals);
207
+ }
208
+ if (node->nd_else) {
209
+ else_body = process_parse_tree(parser_state, ptp, node->nd_else, locals);
210
+ }
211
+ tree = rb_funcall(ptp, rb_sIf, 4, line, cond, body, else_body);
212
+ break;
213
+ }
214
+ case NODE_CASE: {
215
+ VALUE expr = Qnil, els = Qnil;
216
+ NODE* else_node = 0;
217
+
218
+ case_level++;
219
+ if(node->nd_head) {
220
+ expr = process_parse_tree(parser_state, ptp, node->nd_head, locals); /* expr */
221
+ }
222
+
223
+ VALUE whens = rb_ary_new();
224
+ node = node->nd_body;
225
+ while(node) {
226
+ if (nd_type(node) == NODE_WHEN) { /* when */
227
+ rb_ary_push(whens, process_parse_tree(parser_state, ptp, node, locals));
228
+ node = node->nd_next;
229
+ } else {
230
+ else_node = node;
231
+ break; /* else */
232
+ }
233
+ }
234
+
235
+ case_level--;
236
+
237
+ // Be sure to decrease the case_level before processing the else.
238
+ // See http://github.com/rubinius/rubinius/issues#issue/240 for an example of
239
+ // why.
240
+ if(else_node) {
241
+ els = process_parse_tree(parser_state, ptp, else_node, locals);
242
+ }
243
+
244
+ tree = rb_funcall(ptp, rb_sCase, 4, line, expr, whens, els);
245
+ break;
246
+ }
247
+ case NODE_WHEN: {
248
+ VALUE body = Qnil;
249
+
250
+ when_level++;
251
+ /* when without case, ie, no expr in case */
252
+ if(!inside_case_args && case_level < when_level) {
253
+ if(when_level > 0) when_level--;
254
+ node = NEW_CASE(0, node);
255
+ goto again;
256
+ }
257
+ inside_case_args++;
258
+ VALUE args = process_parse_tree(parser_state, ptp, node->nd_head, locals); /* args */
259
+ inside_case_args--;
260
+
261
+ if(node->nd_body) {
262
+ body = process_parse_tree(parser_state, ptp, node->nd_body, locals); /* body */
263
+ }
264
+ if(when_level > 0) when_level--;
265
+
266
+ tree = rb_funcall(ptp, rb_sWhen, 3, line, args, body);
267
+ break;
268
+ }
269
+ case NODE_WHILE: {
270
+ VALUE cond, body = Qnil, post_cond;
271
+
272
+ cond = process_parse_tree(parser_state, ptp, node->nd_cond, locals);
273
+ if(node->nd_body) {
274
+ body = process_parse_tree(parser_state, ptp, node->nd_body, locals);
275
+ }
276
+ post_cond = node->nd_3rd == 0 ? Qfalse : Qtrue;
277
+ tree = rb_funcall(ptp, rb_sWhile, 4, line, cond, body, post_cond);
278
+ break;
279
+ }
280
+ case NODE_UNTIL: {
281
+ VALUE cond, body = Qnil, post_cond;
282
+
283
+ cond = process_parse_tree(parser_state, ptp, node->nd_cond, locals);
284
+ if(node->nd_body) {
285
+ body = process_parse_tree(parser_state, ptp, node->nd_body, locals);
286
+ }
287
+ post_cond = node->nd_3rd == 0 ? Qfalse : Qtrue;
288
+ tree = rb_funcall(ptp, rb_sUntil, 4, line, cond, body, post_cond);
289
+ break;
290
+ }
291
+ case NODE_BLOCK_PASS: {
292
+ VALUE body = process_parse_tree(parser_state, ptp, node->nd_body, locals);
293
+ VALUE iter = Qnil;
294
+ if(node->nd_iter != (NODE*)1) {
295
+ iter = process_parse_tree(parser_state, ptp, node->nd_iter, locals);
296
+ }
297
+
298
+ tree = rb_funcall(ptp, rb_sBlockPass, 3, line, iter, body);
299
+ break;
300
+ }
301
+ case NODE_FOR:
302
+ tree = process_iter(parser_state, ptp, node, locals, &masgn_level, rb_sFor, line);
303
+ break;
304
+
305
+ case NODE_ITER:
306
+ tree = process_iter(parser_state, ptp, node, locals, &masgn_level, rb_sIter, line);
307
+ break;
308
+
309
+ case NODE_BREAK: {
310
+ VALUE expr = Qnil;
311
+
312
+ if (node->nd_stts) {
313
+ expr = process_parse_tree(parser_state, ptp, node->nd_stts, locals);
314
+ }
315
+ tree = rb_funcall(ptp, rb_sBreak, 2, line, expr);
316
+ break;
317
+ }
318
+ case NODE_NEXT: {
319
+ VALUE expr = Qnil;
320
+
321
+ if (node->nd_stts) {
322
+ expr = process_parse_tree(parser_state, ptp, node->nd_stts, locals);
323
+ }
324
+ tree = rb_funcall(ptp, rb_sNext, 2, line, expr);
325
+ break;
326
+ }
327
+ case NODE_YIELD: {
328
+ VALUE expr = Qnil;
329
+
330
+ if (node->nd_stts) {
331
+ expr = process_parse_tree(parser_state, ptp, node->nd_stts, locals);
332
+ }
333
+ tree = rb_funcall(ptp, rb_sYield, 3, line, expr, node->u3.value);
334
+ break;
335
+ }
336
+ case NODE_RESCUE: {
337
+ VALUE body = process_parse_tree(parser_state, ptp, node->nd_1st, locals);
338
+ VALUE resc = process_parse_tree(parser_state, ptp, node->nd_2nd, locals);
339
+ VALUE els = process_parse_tree(parser_state, ptp, node->nd_3rd, locals);
340
+ tree = rb_funcall(ptp, rb_sRescue, 4, line, body, resc, els);
341
+ break;
342
+ }
343
+ case NODE_RESBODY: {
344
+ /* rescue body:
345
+ * begin stmt rescue exception => var; stmt; [rescue e2 => v2; s2;]* end
346
+ * stmt rescue stmt
347
+ * a = b rescue c
348
+ */
349
+
350
+ VALUE conditions = Qnil;
351
+
352
+ if(node->nd_3rd) {
353
+ conditions = process_parse_tree(parser_state, ptp, node->nd_3rd, locals);
354
+ }
355
+ VALUE body = process_parse_tree(parser_state, ptp, node->nd_2nd, locals);
356
+ VALUE next = process_parse_tree(parser_state, ptp, node->nd_1st, locals);
357
+ tree = rb_funcall(ptp, rb_sResbody, 4, line, conditions, body, next);
358
+ break;
359
+ }
360
+ case NODE_ENSURE: {
361
+ VALUE head, ensr = Qnil;
362
+
363
+ head = process_parse_tree(parser_state, ptp, node->nd_head, locals);
364
+ if (node->nd_ensr) {
365
+ ensr = process_parse_tree(parser_state, ptp, node->nd_ensr, locals);
366
+ }
367
+ tree = rb_funcall(ptp, rb_sEnsure, 3, line, head, ensr);
368
+ break;
369
+ }
370
+ case NODE_AND: {
371
+ VALUE left = process_parse_tree(parser_state, ptp, node->nd_1st, locals);
372
+ VALUE right = process_parse_tree(parser_state, ptp, node->nd_2nd, locals);
373
+ tree = rb_funcall(ptp, rb_sAnd, 3, line, left, right);
374
+ break;
375
+ }
376
+ case NODE_OR: {
377
+ VALUE left = process_parse_tree(parser_state, ptp, node->nd_1st, locals);
378
+ VALUE right = process_parse_tree(parser_state, ptp, node->nd_2nd, locals);
379
+ tree = rb_funcall(ptp, rb_sOr, 3, line, left, right);
380
+ break;
381
+ }
382
+ case NODE_DOT2: {
383
+ VALUE start = process_parse_tree(parser_state, ptp, node->nd_beg, locals);
384
+ VALUE finish = process_parse_tree(parser_state, ptp, node->nd_end, locals);
385
+ tree = rb_funcall(ptp, rb_sDot2, 3, line, start, finish);
386
+ break;
387
+ }
388
+ case NODE_DOT3: {
389
+ VALUE start = process_parse_tree(parser_state, ptp, node->nd_beg, locals);
390
+ VALUE finish = process_parse_tree(parser_state, ptp, node->nd_end, locals);
391
+ tree = rb_funcall(ptp, rb_sDot3, 3, line, start, finish);
392
+ break;
393
+ }
394
+ case NODE_FLIP2: {
395
+ VALUE start = process_parse_tree(parser_state, ptp, node->nd_beg, locals);
396
+ VALUE finish = process_parse_tree(parser_state, ptp, node->nd_end, locals);
397
+ tree = rb_funcall(ptp, rb_sFlip2, 3, line, start, finish);
398
+ break;
399
+ }
400
+ case NODE_FLIP3: {
401
+ VALUE start = process_parse_tree(parser_state, ptp, node->nd_beg, locals);
402
+ VALUE finish = process_parse_tree(parser_state, ptp, node->nd_end, locals);
403
+ tree = rb_funcall(ptp, rb_sFlip3, 3, line, start, finish);
404
+ break;
405
+ }
406
+ case NODE_RETURN: {
407
+ VALUE expr = Qnil;
408
+
409
+ if (node->nd_stts) {
410
+ expr = process_parse_tree(parser_state, ptp, node->nd_stts, locals);
411
+ }
412
+ tree = rb_funcall(ptp, rb_sReturn, 2, line, expr);
413
+ break;
414
+ }
415
+ case NODE_ARGSCAT: {
416
+ VALUE array = process_parse_tree(parser_state, ptp, node->nd_head, locals);
417
+ VALUE rest = process_parse_tree(parser_state, ptp, node->nd_body, locals);
418
+ tree = rb_funcall(ptp, rb_sArgsCat, 3, line, array, rest);
419
+ break;
420
+ }
421
+ case NODE_ARGSPUSH: {
422
+ VALUE head = process_parse_tree(parser_state, ptp, node->nd_head, locals);
423
+ VALUE body = process_parse_tree(parser_state, ptp, node->nd_body, locals);
424
+ tree = rb_funcall(ptp, rb_sArgsPush, 3, line, head, body);
425
+ break;
426
+ }
427
+ case NODE_CALL: {
428
+ VALUE args = Qnil;
429
+
430
+ VALUE recv = process_parse_tree(parser_state, ptp, node->nd_recv, locals);
431
+ if (node->nd_args) {
432
+ args = process_parse_tree(parser_state, ptp, node->nd_args, locals);
433
+ }
434
+ tree = rb_funcall(ptp, rb_sCall, 4, line,
435
+ recv, Q2SYM(node->nd_mid), args);
436
+ break;
437
+ }
438
+ case NODE_FCALL: {
439
+ VALUE args = Qnil;
440
+
441
+ if (node->nd_args) {
442
+ args = process_parse_tree(parser_state, ptp, node->nd_args, locals);
443
+ }
444
+ tree = rb_funcall(ptp, rb_sFCall, 3, line, Q2SYM(node->nd_mid), args);
445
+ break;
446
+ }
447
+ case NODE_VCALL:
448
+ tree = rb_funcall(ptp, rb_sVCall, 2, line, Q2SYM(node->nd_mid));
449
+ break;
450
+
451
+ case NODE_SUPER: {
452
+ VALUE args = process_parse_tree(parser_state, ptp, node->nd_args, locals);
453
+ tree = rb_funcall(ptp, rb_sSuper, 2, line, args);
454
+ break;
455
+ }
456
+ case NODE_SCOPE: {
457
+ VALUE body = process_parse_tree(parser_state, ptp, node->nd_next, node->nd_tbl);
458
+ tree = rb_funcall(ptp, rb_sScope, 2, line, body);
459
+ break;
460
+ }
461
+ case NODE_OP_ASGN1: {
462
+ VALUE op;
463
+
464
+ VALUE recv = process_parse_tree(parser_state, ptp, node->nd_recv, locals);
465
+ VALUE args = process_parse_tree(parser_state, ptp, node->nd_args->nd_2nd, locals);
466
+ switch(node->nd_mid) {
467
+ case 0:
468
+ op = ID2SYM(rb_intern("or"));
469
+ break;
470
+ case 1:
471
+ op = ID2SYM(rb_intern("and"));
472
+ break;
473
+ default:
474
+ op = Q2SYM(node->nd_mid);
475
+ }
476
+ VALUE value = process_parse_tree(parser_state, ptp, node->nd_args->nd_head, locals);
477
+ tree = rb_funcall(ptp, rb_sOpAsgn1, 5, line, recv, args, op, value);
478
+ break;
479
+ }
480
+ case NODE_OP_ASGN2: {
481
+ VALUE op;
482
+
483
+ VALUE recv = process_parse_tree(parser_state, ptp, node->nd_recv, locals);
484
+ switch(node->nd_next->nd_mid) {
485
+ case 0:
486
+ op = ID2SYM(rb_intern("or"));
487
+ break;
488
+ case 1:
489
+ op = ID2SYM(rb_intern("and"));
490
+ break;
491
+ default:
492
+ op = Q2SYM(node->nd_next->nd_mid);
493
+ }
494
+ VALUE value = process_parse_tree(parser_state, ptp, node->nd_value, locals);
495
+ tree = rb_funcall(ptp, rb_sOpAsgn2, 5, line,
496
+ recv, Q2SYM(node->nd_next->nd_aid), op, value);
497
+ break;
498
+ }
499
+ case NODE_OP_ASGN_AND: {
500
+ VALUE var = process_parse_tree(parser_state, ptp, node->nd_head, locals);
501
+ VALUE value = process_parse_tree(parser_state, ptp, node->nd_value, locals);
502
+ tree = rb_funcall(ptp, rb_sOpAsgnAnd, 3, line, var, value);
503
+ break;
504
+ }
505
+ case NODE_OP_ASGN_OR: {
506
+ VALUE var = process_parse_tree(parser_state, ptp, node->nd_head, locals);
507
+ VALUE value = process_parse_tree(parser_state, ptp, node->nd_value, locals);
508
+ tree = rb_funcall(ptp, rb_sOpAsgnOr, 3, line, var, value);
509
+ break;
510
+ }
511
+ case NODE_MASGN: {
512
+ VALUE args = Qnil;
513
+
514
+ masgn_level++;
515
+ VALUE head = process_parse_tree(parser_state, ptp, node->nd_head, locals);
516
+ if (node->nd_args) {
517
+ if(node->nd_args != (NODE *)-1) {
518
+ args = process_parse_tree(parser_state, ptp, node->nd_args, locals);
519
+ } else {
520
+ args = Qtrue;
521
+ }
522
+ }
523
+ VALUE value = process_parse_tree(parser_state, ptp, node->nd_value, locals);
524
+ tree = rb_funcall(ptp, rb_sMAsgn, 4, line, head, value, args);
525
+ masgn_level--;
526
+ break;
527
+ }
528
+ case NODE_LASGN: {
529
+ VALUE expr = process_parse_tree(parser_state, ptp, node->nd_value, locals);
530
+ tree = rb_funcall(ptp, rb_sLAsgn, 3, line, Q2SYM(node->nd_vid), expr);
531
+ break;
532
+ }
533
+ case NODE_IASGN: {
534
+ VALUE expr = process_parse_tree(parser_state, ptp, node->nd_value, locals);
535
+ tree = rb_funcall(ptp, rb_sIAsgn, 3, line, Q2SYM(node->nd_vid), expr);
536
+ break;
537
+ }
538
+ case NODE_CVASGN: {
539
+ VALUE expr = process_parse_tree(parser_state, ptp, node->nd_value, locals);
540
+ tree = rb_funcall(ptp, rb_sCVAsgn, 3, line, Q2SYM(node->nd_vid), expr);
541
+ break;
542
+ }
543
+ case NODE_CVDECL: {
544
+ VALUE expr = process_parse_tree(parser_state, ptp, node->nd_value, locals);
545
+ tree = rb_funcall(ptp, rb_sCVDecl, 3, line, Q2SYM(node->nd_vid), expr);
546
+ break;
547
+ }
548
+ case NODE_GASGN: {
549
+ VALUE expr = process_parse_tree(parser_state, ptp, node->nd_value, locals);
550
+ tree = rb_funcall(ptp, rb_sGAsgn, 3, line, Q2SYM(node->nd_vid), expr);
551
+ break;
552
+ }
553
+ case NODE_CDECL: {
554
+ VALUE expr;
555
+
556
+ if(node->nd_vid) {
557
+ expr = Q2SYM(node->nd_vid);
558
+ } else {
559
+ expr = process_parse_tree(parser_state, ptp, node->nd_else, locals);
560
+ }
561
+ VALUE value = process_parse_tree(parser_state, ptp, node->nd_value, locals);
562
+ tree = rb_funcall(ptp, rb_sCDecl, 3, line, expr, value);
563
+ break;
564
+ }
565
+ case NODE_VALIAS: /* u1 u2 (alias $global $global2) */
566
+ tree = rb_funcall(ptp, rb_sVAlias, 3, line,
567
+ Q2SYM(node->u2.id), Q2SYM(node->u1.id));
568
+ break;
569
+
570
+ case NODE_ALIAS: { /* u1 u2 (alias :blah :blah2) */
571
+ VALUE to = process_parse_tree(parser_state, ptp, node->u2.node, locals);
572
+ VALUE from = process_parse_tree(parser_state, ptp, node->u1.node, locals);
573
+ tree = rb_funcall(ptp, rb_sAlias, 3, line, to, from);
574
+ break;
575
+ }
576
+ case NODE_UNDEF: { /* u2 (undef instvar) */
577
+ VALUE name = process_parse_tree(parser_state, ptp, node->u2.node, locals);
578
+ tree = rb_funcall(ptp, rb_sUndef, 2, line, name);
579
+ break;
580
+ }
581
+ case NODE_COLON3: /* u2 (::OUTER_CONST) */
582
+ tree = rb_funcall(ptp, rb_sColon3, 2, line, Q2SYM(node->u2.id));
583
+ break;
584
+
585
+ case NODE_HASH: {
586
+ VALUE array = rb_ary_new();
587
+
588
+ node = node->nd_head;
589
+ while (node) {
590
+ rb_ary_push(array, process_parse_tree(parser_state, ptp, node->nd_head, locals));
591
+ if (!(node = node->nd_next)) {
592
+ // @todo: properly process the parse error
593
+ printf("odd number list for Hash");
594
+ abort();
595
+ }
596
+ rb_ary_push(array, process_parse_tree(parser_state, ptp, node->nd_head, locals));
597
+ node = node->nd_next;
598
+ }
599
+ tree = rb_funcall(ptp, rb_sHash, 2, line, array);
600
+ break;
601
+ }
602
+ case NODE_ARRAY: {
603
+ VALUE array = rb_ary_new();
604
+
605
+ while (node) {
606
+ rb_ary_push(array, process_parse_tree(parser_state, ptp, node->nd_head, locals));
607
+ node = node->nd_next;
608
+ }
609
+ tree = rb_funcall(ptp, rb_sArray, 2, line, array);
610
+ break;
611
+ }
612
+ case NODE_DSTR: {
613
+ VALUE array = process_dynamic(parser_state, ptp, node->nd_next, locals);
614
+ VALUE str = string_newfrombstr(node->nd_str);
615
+ tree = rb_funcall(ptp, rb_sDStr, 3, line, str, array);
616
+ bdestroy(node->nd_str);
617
+ break;
618
+ }
619
+ case NODE_DSYM: {
620
+ VALUE array = process_dynamic(parser_state, ptp, node->nd_next, locals);
621
+ VALUE str = string_newfrombstr(node->nd_str);
622
+ tree = rb_funcall(ptp, rb_sDSym, 3, line, str, array);
623
+ bdestroy(node->nd_str);
624
+ break;
625
+ }
626
+ case NODE_DXSTR: {
627
+ VALUE array = process_dynamic(parser_state, ptp, node->nd_next, locals);
628
+ VALUE str = string_newfrombstr(node->nd_str);
629
+ tree = rb_funcall(ptp, rb_sDXStr, 3, line, str, array);
630
+ bdestroy(node->nd_str);
631
+ break;
632
+ }
633
+ case NODE_DREGX: {
634
+ VALUE flags = Qnil;
635
+
636
+ VALUE array = process_dynamic(parser_state, ptp, node->nd_next, locals);
637
+ VALUE str = string_newfrombstr(node->nd_str);
638
+ if (node->nd_cflag) flags = INT2FIX(node->nd_cflag);
639
+ tree = rb_funcall(ptp, rb_sDRegx, 4, line, str, array, flags);
640
+ bdestroy(node->nd_str);
641
+ break;
642
+ }
643
+ case NODE_DREGX_ONCE: {
644
+ VALUE flags = Qnil;
645
+
646
+ VALUE array = process_dynamic(parser_state, ptp, node->nd_next, locals);
647
+ VALUE str = string_newfrombstr(node->nd_str);
648
+ if (node->nd_cflag) flags = INT2FIX(node->nd_cflag);
649
+ tree = rb_funcall(ptp, rb_sDRegxOnce, 4, line, str, array, flags);
650
+ bdestroy(node->nd_str);
651
+ break;
652
+ }
653
+ case NODE_DEFN: {
654
+ VALUE body = Qnil;
655
+
656
+ if (node->nd_defn) {
657
+ body = process_parse_tree(parser_state, ptp, node->nd_defn, locals);
658
+ }
659
+ tree = rb_funcall(ptp, rb_sDefn, 3, line, Q2SYM(node->nd_mid), body);
660
+ break;
661
+ }
662
+ case NODE_DEFS: {
663
+ VALUE recv = Qnil, body = Qnil;
664
+
665
+ if (node->nd_defn) {
666
+ recv = process_parse_tree(parser_state, ptp, node->nd_recv, locals);
667
+ body = process_parse_tree(parser_state, ptp, node->nd_defn, locals);
668
+ }
669
+ tree = rb_funcall(ptp, rb_sDefs, 4, line, recv, Q2SYM(node->nd_mid), body);
670
+ break;
671
+ }
672
+ case NODE_CLASS: {
673
+ VALUE name, super = Qnil;
674
+
675
+ if (nd_type(node->nd_cpath) == NODE_COLON2 && !node->nd_cpath->nd_vid) {
676
+ name = Q2SYM((QUID)node->nd_cpath->nd_mid);
677
+ } else {
678
+ name = process_parse_tree(parser_state, ptp, node->nd_cpath, locals);
679
+ }
680
+ if(node->nd_super) {
681
+ super = process_parse_tree(parser_state, ptp, node->nd_super, locals);
682
+ }
683
+ VALUE body = process_parse_tree(parser_state, ptp, node->nd_body, locals);
684
+ tree = rb_funcall(ptp, rb_sClass, 4, line, name, super, body);
685
+ break;
686
+ }
687
+ case NODE_MODULE: {
688
+ VALUE name;
689
+
690
+ if (nd_type(node->nd_cpath) == NODE_COLON2 && !node->nd_cpath->nd_vid) {
691
+ name = Q2SYM((QUID)node->nd_cpath->nd_mid);
692
+ } else {
693
+ name = process_parse_tree(parser_state, ptp, node->nd_cpath, locals);
694
+ }
695
+ VALUE body = process_parse_tree(parser_state, ptp, node->nd_body, locals);
696
+ tree = rb_funcall(ptp, rb_sModule, 3, line, name, body);
697
+ break;
698
+ }
699
+ case NODE_SCLASS: {
700
+ VALUE recv = process_parse_tree(parser_state, ptp, node->nd_recv, locals);
701
+ VALUE body = process_parse_tree(parser_state, ptp, node->nd_body, locals);
702
+ tree = rb_funcall(ptp, rb_sSClass, 3, line, recv, body);
703
+ break;
704
+ }
705
+ case NODE_ARGS: {
706
+ VALUE splat = Qnil, args = rb_ary_new();
707
+ NODE *optnode;
708
+ int i = 0, max_args = (int)node->nd_cnt;
709
+
710
+ /* push regular argument names */
711
+ for (; i < max_args; i++) {
712
+ rb_ary_push(args, Q2SYM(locals[i + 3]));
713
+ }
714
+
715
+ /* look for optional arguments: we cannot assume these
716
+ * are left-to-right what the locals array contains
717
+ * (e.g. def(a=1, b=2, c=lambda {|n| n } will have 'n'
718
+ * at i (above) + 2 + 3); instead we walk the chain
719
+ * and look at the actual LASGN nodes
720
+ */
721
+ masgn_level++;
722
+ optnode = node->nd_opt;
723
+ while (optnode) {
724
+ if(nd_type(optnode) == NODE_LASGN) {
725
+ rb_ary_push(args, Q2SYM(optnode->nd_vid));
726
+ } else if(nd_type(optnode) == NODE_BLOCK
727
+ && nd_type(optnode->nd_head) == NODE_LASGN) {
728
+ rb_ary_push(args, Q2SYM(optnode->nd_head->nd_vid));
729
+ }
730
+ i++; // do not use here but keep track for '*args' name below
731
+ optnode = optnode->nd_next;
732
+ }
733
+
734
+ /* look for vargs */
735
+ long arg_count = (long)node->nd_rest;
736
+ if (arg_count > 0) {
737
+ /* *arg name */
738
+ if (locals[i + 3]) {
739
+ splat = quark_to_symbol(parser_state, locals[i + 3]);
740
+ } else {
741
+ splat = Qtrue;
742
+ }
743
+ } else if (arg_count == 0) {
744
+ /* nothing to do in this case, empty list */
745
+ } else if (arg_count == -1) {
746
+ /* nothing to do in this case, handled above */
747
+ } else if (arg_count == -2) {
748
+ /* nothing to do in this case, no name == no use */
749
+ splat = Qtrue;
750
+ } else {
751
+ // HACK: replace with Exception::argument_error()
752
+ printf("Unknown arg_count %ld encountered while processing args.\n", arg_count);
753
+ }
754
+
755
+ VALUE opt = Qnil;
756
+ optnode = node->nd_opt;
757
+ if (optnode) {
758
+ opt = process_parse_tree(parser_state, ptp, node->nd_opt, locals);
759
+ }
760
+ masgn_level--;
761
+
762
+ tree = rb_funcall(ptp, rb_sArgs, 4, line, args, opt, splat);
763
+ break;
764
+ }
765
+ case NODE_LVAR:
766
+ tree = rb_funcall(ptp, rb_sLVar, 2, line, Q2SYM(node->nd_vid));
767
+ break;
768
+
769
+ case NODE_IVAR:
770
+ tree = rb_funcall(ptp, rb_sIVar, 2, line, Q2SYM(node->nd_vid));
771
+ break;
772
+
773
+ case NODE_CVAR:
774
+ tree = rb_funcall(ptp, rb_sCVar, 2, line, Q2SYM(node->nd_vid));
775
+ break;
776
+
777
+ case NODE_GVAR:
778
+ tree = rb_funcall(ptp, rb_sGVar, 2, line, Q2SYM(node->nd_vid));
779
+ break;
780
+
781
+ case NODE_CONST:
782
+ tree = rb_funcall(ptp, rb_sConst, 2, line, Q2SYM(node->nd_vid));
783
+ break;
784
+
785
+ case NODE_FIXNUM:
786
+ tree = rb_funcall(ptp, rb_sFixnum, 2, line, INT2FIX(node->nd_cnt));
787
+ break;
788
+
789
+ case NODE_NUMBER:
790
+ tree = rb_funcall(ptp, rb_sNumber, 3, line, INT2FIX(0),
791
+ string_newfrombstr(node->nd_str));
792
+ bdestroy(node->nd_str);
793
+ break;
794
+
795
+ case NODE_HEXNUM:
796
+ tree = rb_funcall(ptp, rb_sNumber, 3, line, INT2FIX(16),
797
+ string_newfrombstr(node->nd_str));
798
+ bdestroy(node->nd_str);
799
+ break;
800
+
801
+ case NODE_BINNUM:
802
+ tree = rb_funcall(ptp, rb_sNumber, 3, line, INT2FIX(2),
803
+ string_newfrombstr(node->nd_str));
804
+ bdestroy(node->nd_str);
805
+ break;
806
+
807
+ case NODE_OCTNUM:
808
+ tree = rb_funcall(ptp, rb_sNumber, 3, line, INT2FIX(8),
809
+ string_newfrombstr(node->nd_str));
810
+ bdestroy(node->nd_str);
811
+ break;
812
+
813
+ case NODE_FLOAT:
814
+ tree = rb_funcall(ptp, rb_sFloat, 2, line,
815
+ string_newfrombstr(node->nd_str));
816
+ bdestroy(node->nd_str);
817
+ break;
818
+
819
+ case NODE_XSTR: /* u1 (%x{ls}) */
820
+ tree = rb_funcall(ptp, rb_sXStr, 2, line,
821
+ string_newfrombstr(node->nd_str));
822
+ bdestroy(node->nd_str);
823
+ break;
824
+
825
+ case NODE_STR: /* u1 */
826
+ tree = rb_funcall(ptp, rb_sStr, 2, line,
827
+ string_newfrombstr(node->nd_str));
828
+ bdestroy(node->nd_str);
829
+ break;
830
+
831
+ case NODE_REGEX:
832
+ tree = rb_funcall(ptp, rb_sRegex, 3, line,
833
+ string_newfrombstr(node->nd_str), INT2FIX(node->nd_cnt));
834
+ bdestroy(node->nd_str);
835
+ break;
836
+
837
+ case NODE_MATCH:
838
+ tree = rb_funcall(ptp, rb_sMatch, 3, line,
839
+ string_newfrombstr(node->nd_str), INT2FIX(node->nd_cnt));
840
+ bdestroy(node->nd_str);
841
+ break;
842
+
843
+ case NODE_LIT:
844
+ tree = rb_funcall(ptp, rb_sLit, 2, line, Q2SYM((uintptr_t)node->nd_lit));
845
+ break;
846
+
847
+ case NODE_NEWLINE:
848
+ node = node->nd_next;
849
+ goto again;
850
+ break;
851
+
852
+ case NODE_NTH_REF: /* u2 u3 ($1) - u3 is local_cnt('~') ignorable? */
853
+ tree = rb_funcall(ptp, rb_sNthRef, 2, line, INT2FIX(node->nd_nth));
854
+ break;
855
+
856
+ case NODE_BACK_REF: { /* u2 u3 ($& etc) */
857
+ char str[2];
858
+ str[0] = node->nd_nth;
859
+ str[1] = 0;
860
+ tree = rb_funcall(ptp, rb_sBackRef, 2, line, ID2SYM(rb_intern(str)));
861
+ break;
862
+ }
863
+
864
+ case NODE_BLOCK_ARG: /* u1 u3 (def x(&b) */
865
+ tree = rb_funcall(ptp, rb_sBlockArg, 2, line, Q2SYM(node->u1.id));
866
+ break;
867
+
868
+ case NODE_RETRY:
869
+ tree = rb_funcall(ptp, rb_sRetry, 1, line);
870
+ break;
871
+
872
+ case NODE_FALSE:
873
+ tree = rb_funcall(ptp, rb_sFalse, 1, line);
874
+ break;
875
+
876
+ case NODE_NIL:
877
+ tree = rb_funcall(ptp, rb_sNil, 1, line);
878
+ break;
879
+
880
+ case NODE_SELF:
881
+ tree = rb_funcall(ptp, rb_sSelf, 1, line);
882
+ break;
883
+
884
+ case NODE_TRUE:
885
+ tree = rb_funcall(ptp, rb_sTrue, 1, line);
886
+ break;
887
+
888
+ case NODE_ZARRAY:
889
+ tree = rb_funcall(ptp, rb_sZArray, 1, line);
890
+ break;
891
+
892
+ case NODE_ZSUPER:
893
+ tree = rb_funcall(ptp, rb_sZSuper, 1, line);
894
+ break;
895
+
896
+ case NODE_REDO:
897
+ tree = rb_funcall(ptp, rb_sRedo, 1, line);
898
+ break;
899
+
900
+ case NODE_FILE:
901
+ tree = rb_funcall(ptp, rb_sFile, 1, line);
902
+ break;
903
+
904
+ case NODE_SPLAT: {
905
+ VALUE expr = process_parse_tree(parser_state, ptp, node->nd_head, locals);
906
+ tree = rb_funcall(ptp, rb_sSplat, 2, line, expr);
907
+ break;
908
+ }
909
+ case NODE_TO_ARY: {
910
+ VALUE expr = process_parse_tree(parser_state, ptp, node->nd_head, locals);
911
+ tree = rb_funcall(ptp, rb_sToAry, 2, line, expr);
912
+ break;
913
+ }
914
+ case NODE_SVALUE: { /* a = b, c */
915
+ VALUE expr = process_parse_tree(parser_state, ptp, node->nd_head, locals);
916
+ tree = rb_funcall(ptp, rb_sSValue, 2, line, expr);
917
+ break;
918
+ }
919
+ case NODE_ATTRASGN: { /* literal.meth = y u1 u2 u3 */
920
+ VALUE recv;
921
+
922
+ /* node id node */
923
+ if (node->nd_1st == RNODE(1)) {
924
+ recv = process_parse_tree(parser_state, ptp, NEW_SELF(), locals);
925
+ } else {
926
+ recv = process_parse_tree(parser_state, ptp, node->nd_1st, locals);
927
+ }
928
+ VALUE value = process_parse_tree(parser_state, ptp, node->nd_3rd, locals);
929
+ tree = rb_funcall(ptp, rb_sAttrAsgn, 4, line,
930
+ recv, Q2SYM(node->u2.id), value);
931
+ break;
932
+ }
933
+ case NODE_EVSTR: {
934
+ VALUE value = process_parse_tree(parser_state, ptp, node->nd_2nd, locals);
935
+ tree = rb_funcall(ptp, rb_sEvStr, 2, line, value);
936
+ break;
937
+ }
938
+ case NODE_NEGATE: {
939
+ VALUE expr = process_parse_tree(parser_state, ptp, node->nd_head, locals);
940
+ tree = rb_funcall(ptp, rb_sNegate, 2, line, expr);
941
+ break;
942
+ }
943
+ case NODE_PREEXE: { /* BEGIN { ... } */
944
+ tree = rb_funcall(ptp, rb_sPreExe, 1, line);
945
+ break;
946
+ }
947
+ case NODE_POSTEXE: /* END { ... } */
948
+ tree = rb_funcall(ptp, rb_sPostExe, 1, line);
949
+ break;
950
+
951
+ default: {
952
+ VALUE node_name = rb_str_new2(get_node_type_string((enum node_type)nd_type(node)));
953
+ VALUE node_type = INT2FIX(nd_type(node));
954
+ tree = rb_funcall(ptp, rb_intern("process_missing_node"), 3,
955
+ line, node_name, node_type);
956
+ break;
957
+ }
958
+ }
959
+
960
+ return tree;
961
+ }
962
+ }; // namespace grammar18
963
+ };