source: EcnlProtoTool/trunk/webapp/webmrbc/MrbAstNodes.cs@ 270

Last change on this file since 270 was 270, checked in by coas-nagasima, 7 years ago

mruby版ECNLプロトタイピング・ツールを追加

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-csharp
File size: 106.3 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.Linq;
4using System.Text;
5using Bridge;
6using Bridge.Html5;
7
8namespace WebMrbc
9{
10 public interface IMrbParser
11 {
12 int lineno { get; set; }
13 int column { get; set; }
14 string filename { get; }
15 string sym2name(mrb_sym sym);
16 mrb_sym[] locals_node();
17 void yyError(string message, params object[] expected);
18 }
19
20 public enum node_type
21 {
22 NODE_METHOD = 1,
23 NODE_FBODY,
24 NODE_CFUNC,
25 NODE_SCOPE,
26 NODE_BLOCK,
27 NODE_IF,
28 NODE_CASE,
29 NODE_WHEN,
30 NODE_OPT_N,
31 NODE_WHILE,
32 NODE_UNTIL,
33 NODE_ITER,
34 NODE_FOR,
35 NODE_BREAK,
36 NODE_NEXT,
37 NODE_REDO,
38 NODE_RETRY,
39 NODE_BEGIN,
40 NODE_RESCUE,
41 NODE_ENSURE,
42 NODE_AND,
43 NODE_OR,
44 NODE_NOT,
45 NODE_MASGN,
46 NODE_ASGN,
47 NODE_CDECL,
48 NODE_CVASGN,
49 NODE_CVDECL,
50 NODE_OP_ASGN,
51 NODE_CALL,
52 NODE_SCALL,
53 NODE_FCALL,
54 NODE_VCALL,
55 NODE_SUPER,
56 NODE_ZSUPER,
57 NODE_ARRAY,
58 NODE_ZARRAY,
59 NODE_HASH,
60 NODE_RETURN,
61 NODE_YIELD,
62 NODE_LVAR,
63 NODE_DVAR,
64 NODE_GVAR,
65 NODE_IVAR,
66 NODE_CONST,
67 NODE_CVAR,
68 NODE_NTH_REF,
69 NODE_BACK_REF,
70 NODE_MATCH,
71 NODE_MATCH2,
72 NODE_MATCH3,
73 NODE_INT,
74 NODE_FLOAT,
75 NODE_NEGATE,
76 NODE_LAMBDA,
77 NODE_SYM,
78 NODE_STR,
79 NODE_DSTR,
80 NODE_XSTR,
81 NODE_DXSTR,
82 NODE_REGX,
83 NODE_DREGX,
84 NODE_DREGX_ONCE,
85 NODE_LIST,
86 NODE_ARG,
87 NODE_ARGSCAT,
88 NODE_ARGSPUSH,
89 NODE_SPLAT,
90 NODE_TO_ARY,
91 NODE_SVALUE,
92 NODE_BLOCK_ARG,
93 NODE_DEF,
94 NODE_SDEF,
95 NODE_ALIAS,
96 NODE_UNDEF,
97 NODE_CLASS,
98 NODE_MODULE,
99 NODE_SCLASS,
100 NODE_COLON2,
101 NODE_COLON3,
102 NODE_CREF,
103 NODE_DOT2,
104 NODE_DOT3,
105 NODE_FLIP2,
106 NODE_FLIP3,
107 NODE_ATTRSET,
108 NODE_SELF,
109 NODE_NIL,
110 NODE_TRUE,
111 NODE_FALSE,
112 NODE_DEFINED,
113 NODE_NEWLINE,
114 NODE_POSTEXE,
115 NODE_ALLOCA,
116 NODE_DMETHOD,
117 NODE_BMETHOD,
118 NODE_MEMO,
119 NODE_IFUNC,
120 NODE_DSYM,
121 NODE_ATTRASGN,
122 NODE_HEREDOC,
123 NODE_LITERAL_DELIM,
124 NODE_WORDS,
125 NODE_SYMBOLS,
126 NODE_LAST
127 }
128
129 /* lexer states */
130 public enum mrb_lex_state_enum
131 {
132 EXPR_BEG, /* ignore newline, +/- is a sign. */
133 EXPR_END, /* newline significant, +/- is an operator. */
134 EXPR_ENDARG, /* ditto, and unbound braces. */
135 EXPR_ENDFN, /* ditto, and unbound braces. */
136 EXPR_ARG, /* newline significant, +/- is an operator. */
137 EXPR_CMDARG, /* newline significant, +/- is an operator. */
138 EXPR_MID, /* newline significant, +/- is an operator. */
139 EXPR_FNAME, /* ignore newline, no reserved words. */
140 EXPR_DOT, /* right after '.' or '::', no reserved words. */
141 EXPR_CLASS, /* immediate after 'class', no here document. */
142 EXPR_VALUE, /* alike EXPR_BEG but label is disallowed. */
143 EXPR_MAX_STATE
144 }
145
146 public enum mrb_sym { }
147
148 public enum stack_type { }
149
150 [Flags]
151 enum mrb_string_type
152 {
153 STR_FUNC_PARSING = 0x01,
154 STR_FUNC_EXPAND = 0x02,
155 STR_FUNC_REGEXP = 0x04,
156 STR_FUNC_WORD = 0x08,
157 STR_FUNC_SYMBOL = 0x10,
158 STR_FUNC_ARRAY = 0x20,
159 STR_FUNC_HEREDOC = 0x40,
160 STR_FUNC_XQUOTE = 0x80,
161
162 str_not_parsing = (0),
163 str_squote = (STR_FUNC_PARSING),
164 str_dquote = (STR_FUNC_PARSING | STR_FUNC_EXPAND),
165 str_regexp = (STR_FUNC_PARSING | STR_FUNC_REGEXP | STR_FUNC_EXPAND),
166 str_sword = (STR_FUNC_PARSING | STR_FUNC_WORD | STR_FUNC_ARRAY),
167 str_dword = (STR_FUNC_PARSING | STR_FUNC_WORD | STR_FUNC_ARRAY | STR_FUNC_EXPAND),
168 str_ssym = (STR_FUNC_PARSING | STR_FUNC_SYMBOL),
169 str_ssymbols = (STR_FUNC_PARSING | STR_FUNC_SYMBOL | STR_FUNC_ARRAY),
170 str_dsymbols = (STR_FUNC_PARSING | STR_FUNC_SYMBOL | STR_FUNC_ARRAY | STR_FUNC_EXPAND),
171 str_heredoc = (STR_FUNC_PARSING | STR_FUNC_HEREDOC),
172 str_xquote = (STR_FUNC_PARSING | STR_FUNC_XQUOTE | STR_FUNC_EXPAND),
173 }
174
175 class parser_heredoc_info
176 {
177 public bool allow_indent;
178 public bool line_head;
179 public mrb_string_type type;
180 public Uint8Array term;
181 public int term_len;
182 public node[] doc = new node[0];
183
184 public string GetString()
185 {
186 var sb = new StringBuilder();
187
188 foreach (var str in doc) {
189 if (str is str_node) {
190 sb.Append(MrbParser.UTF8ArrayToString(((str_node)str).str, 0));
191 }
192 else if (str is begin_node) {
193 foreach (var p in ((begin_node)str).progs) {
194 if (p is str_node) {
195 sb.Append(MrbParser.UTF8ArrayToString(((str_node)p).str, 0));
196 }
197 else if (p is heredoc_node) {
198 sb.Append(((heredoc_node)p).info.GetString());
199 }
200 else if (p is call_node) {
201
202 }
203 else {
204 throw new NotImplementedException();
205 }
206 }
207 }
208 else {
209 throw new NotImplementedException();
210 }
211 }
212
213 return sb.ToString();
214 }
215
216 public override string ToString()
217 {
218 return $"{term} {GetString()}";
219 }
220
221 internal void push_doc(node str)
222 {
223 doc.Push(str);
224 }
225
226 internal void claer_doc()
227 {
228 doc.Splice(0, doc.Length);
229 }
230
231 internal void to_ruby(ruby_code_cond cond)
232 {
233 cond.write_line("<<" + MrbParser.UTF8ArrayToString(term, 0));
234 foreach (var d in doc) {
235 if (d is begin_node) {
236 cond.write("#{");
237 d.to_ruby(cond);
238 cond.write("}");
239 }
240 else {
241 d.to_ruby(cond);
242 }
243 }
244 cond.write_line();
245 cond.write_line(MrbParser.UTF8ArrayToString(term, 0));
246 }
247 }
248
249 public class xml_code_cond
250 {
251 public xml_code_cond()
252 {
253 }
254
255 internal Element CreateElement(string tagname)
256 {
257 return Document.CreateElement(tagname);
258 }
259
260 internal Node CreateTextNode(string text)
261 {
262 return Document.CreateTextNode(text);
263 }
264 }
265
266 public class ruby_code_cond
267 {
268 public string newline_str { get; private set; }
269 public string indent_str { get; set; }
270 public string indent { get; private set; }
271 public int nest { get; private set; }
272
273 bool first;
274 bool space;
275 StringBuilder _code = new StringBuilder();
276 public string filename { get; private set; }
277 public int lineno { get; private set; }
278 public int column { get; private set; }
279
280 public ruby_code_cond(string filename, string indent_str = " ")
281 {
282 this.filename = filename;
283 lineno = 1;
284 column = 0;
285 this.indent_str = indent_str;
286 indent = "";
287 newline_str = "\r\n";
288 first = true;
289 space = false;
290 }
291
292 public void increment_indent()
293 {
294 indent += indent_str;
295 if (!first) {
296 new_line();
297 first = true;
298 space = false;
299 }
300 }
301
302 private void new_line()
303 {
304 _code.Append(newline_str);
305 lineno++;
306 column = 0;
307 }
308
309 private void write_code(string code)
310 {
311 _code.Append(code);
312 column += code.Length;
313 }
314
315 public void decrement_indent()
316 {
317 indent = indent.Substring(0, indent.Length - indent_str.Length);
318 if (!first) {
319 new_line();
320 first = true;
321 space = false;
322 }
323 }
324
325 public void increment_nest()
326 {
327 nest++;
328 }
329
330 public void decrement_nest()
331 {
332 nest--;
333 System.Diagnostics.Debug.Assert(nest >= 0);
334 }
335
336 public void write(string code)
337 {
338 if (first) {
339 first = false;
340 write_code(indent);
341 }
342 write_code(code);
343 space = code.EndsWith(" ");
344 }
345
346 public void write_line(string code = null)
347 {
348 if (nest != 0 && !first && !space) {
349 write_code(" ");
350 space = true;
351 }
352 if (code != null) {
353 if (first) {
354 first = false;
355 write_code(indent);
356 }
357 write_code(code);
358 space = code.EndsWith(" ");
359 }
360 if (nest == 0) {
361 new_line();
362 space = false;
363 first = true;
364 }
365 }
366
367 internal void separate_line()
368 {
369 if (!first) {
370 new_line();
371 first = true;
372 }
373 }
374
375 public node[] nodes = new node[0];
376
377 public void add_node(node node)
378 {
379 nodes.Push(node);
380 }
381
382 public override string ToString()
383 {
384 return _code.ToString();
385 }
386 }
387
388 public class node
389 {
390 object _car;
391 object _cdr;
392
393 public IMrbParser p { get; private set; }
394 public object car {
395 get { return _car; }
396 set {
397 System.Diagnostics.Debug.Assert(GetType() == typeof(node));
398 _car = value;
399 }
400 }
401 public object cdr {
402 get { return _cdr; }
403 set {
404 System.Diagnostics.Debug.Assert(GetType() == typeof(node));
405 _cdr = value;
406 }
407 }
408 public int lineno { get; private set; }
409 public int column { get; private set; }
410 public string filename { get; private set; }
411 public string block_id;
412
413 protected node(IMrbParser p, node_type car)
414 {
415 this.p = p;
416 _car = car;
417 lineno = p.lineno;
418 column = p.column;
419 filename = p.filename;
420 }
421
422 public override string ToString()
423 {
424 if (cdr == null)
425 return $"({car})";
426 return $"({car}, {cdr})";
427 }
428
429 public void SET_LINENO(int n) { lineno = n; }
430
431 public void NODE_LINENO(node n)
432 {
433 if (n != null) {
434 filename = n.filename;
435 lineno = n.lineno;
436 column = n.column;
437 }
438 }
439
440 public static node cons(IMrbParser p, object car, object cdr)
441 {
442 var result = new node(p, 0);
443 result.car = car;
444 result.cdr = cdr;
445 return result;
446 }
447
448 public virtual void append(node b)
449 {
450 node c = this;
451 while (c.cdr != null) {
452 c = (node)c.cdr;
453 }
454 if (b != null) {
455 c.cdr = b;
456 }
457 }
458
459 public static void dump_recur<T>(T[] list, node tree)
460 {
461 while (tree != null) {
462 list.Push((T)tree.car);
463 tree = (node)tree.cdr;
464 }
465 }
466
467 public virtual Element to_xml(xml_code_cond cond)
468 {
469 var a = car as node;
470 if (a != null && cdr == null) {
471 return a.to_xml(cond);
472 }
473
474 throw new NotImplementedException();
475 }
476
477 public int start_lineno { get; private set; }
478 public int start_column { get; private set; }
479
480 public void to_ruby(ruby_code_cond cond)
481 {
482 filename = cond.filename;
483 start_lineno = cond.lineno;
484 start_column = cond.column;
485
486 to_rb(cond);
487
488 lineno = cond.lineno;
489 column = cond.column;
490
491 cond.add_node(this);
492 }
493
494 protected virtual void to_rb(ruby_code_cond cond)
495 {
496 var a = car as node;
497 while (a != null) {
498 a.to_ruby(cond);
499 a = a.cdr as node;
500 }
501 }
502 }
503
504 public class locals_node
505 {
506 public mrb_sym[] symList = new mrb_sym[0];
507 public locals_node cdr;
508
509 public locals_node(locals_node cdr)
510 {
511 this.cdr = cdr;
512 }
513
514 internal void push(mrb_sym sym)
515 {
516 symList.Push(sym);
517 }
518 }
519
520 /* (:scope (vars..) (prog...)) */
521 class scope_node : node
522 {
523 private mrb_sym[] _local_variables = new mrb_sym[0];
524 private node _body;
525
526 public scope_node(IMrbParser p, node body)
527 : base(p, node_type.NODE_SCOPE)
528 {
529 _local_variables = (mrb_sym[])_local_variables.Concat(p.locals_node());
530 _body = body;
531 }
532
533 public mrb_sym[] local_variables { get { return _local_variables; } }
534 public node body { get { return _body; } }
535
536 public override Element to_xml(xml_code_cond cond)
537 {
538 // TODO:???
539 var s = cond.CreateElement("scope");
540 var b = _body.to_xml(cond);
541 if (b != null) {
542 s.AppendChild(b);
543 }
544 return s;
545 }
546
547 protected override void to_rb(ruby_code_cond cond)
548 {
549 _body.to_ruby(cond);
550 }
551
552 public override string ToString()
553 {
554 var str = "(:scope (";
555 foreach (var v in local_variables) {
556 str += $"{v}, ";
557 }
558 return str + $") {body})";
559 }
560 }
561
562 /* (:begin prog...) */
563 public class begin_node : node
564 {
565 private node[] _progs = new node[0];
566 bool _parentheses;
567
568 public begin_node(IMrbParser p, node body, bool parentheses = false)
569 : base(p, node_type.NODE_BEGIN)
570 {
571 while (body != null) {
572 _progs.Push(body);
573 body = (node)body.cdr;
574 }
575 _parentheses = parentheses;
576 }
577
578 public begin_node(IMrbParser p, node[] progs)
579 : base(p, node_type.NODE_BEGIN)
580 {
581 _progs = (node[])_progs.Concat(progs);
582 }
583
584 public node[] progs { get { return _progs; } }
585
586 public override void append(node b)
587 {
588 _progs.Push((node)b.car);
589 }
590
591 public override Element to_xml(xml_code_cond cond)
592 {
593 switch (_progs.Length) {
594 case 0:
595 return null;
596 case 1:
597 return _progs[0].to_xml(cond);
598 }
599 var b = _progs[0].to_xml(cond);
600 var p = b;
601 for (int i = 1; i < _progs.Length; i++) {
602 var n = cond.CreateElement("next");
603 var q = _progs[i].to_xml(cond);
604 n.AppendChild(q);
605 p.AppendChild(n);
606 p = q;
607 }
608
609 return b;
610 }
611
612 protected override void to_rb(ruby_code_cond cond)
613 {
614 var i = progs.Length;
615 foreach (var v in progs) {
616 var prn = _parentheses || (v is dot2_node);
617 if (prn) {
618 cond.increment_nest();
619 cond.write("(");
620 }
621 v.to_ruby(cond);
622 if (prn) {
623 cond.write(")");
624 cond.decrement_nest();
625 }
626 i--; if (i > 0) cond.separate_line();
627 }
628 }
629
630 public override string ToString()
631 {
632 var str = "(:begin ";
633 foreach (var v in progs) {
634 str += $"{v}, ";
635 }
636 return str + ")";
637 }
638 }
639
640 /* (:rescue body rescue else) */
641 class rescue_node : node
642 {
643 public class rescue_t
644 {
645 public node[] handle_classes = new node[0];
646 public node exc_var;
647 public node body;
648
649 public override string ToString()
650 {
651 var str = "(";
652 foreach (var c in handle_classes) {
653 str += $"{c}, ";
654 }
655 return $"{exc_var} {body})";
656 }
657
658 internal void to_ruby(ruby_code_cond cond)
659 {
660 cond.increment_nest();
661 cond.write("rescue");
662 int i = handle_classes.Length;
663 if (i > 0)
664 cond.write(" ");
665 foreach (var c in handle_classes) {
666 c.to_ruby(cond);
667 i--; if (i > 0) cond.write(", ");
668 }
669 if (exc_var != null) {
670 cond.write(" => ");
671 exc_var.to_ruby(cond);
672 }
673 cond.decrement_nest();
674 cond.write_line();
675 cond.increment_indent();
676 body.to_ruby(cond);
677 cond.decrement_indent();
678 }
679 }
680
681 private node _body;
682 private rescue_t[] _rescue = new rescue_t[0];
683 private node _else;
684 public bool ensure;
685
686 public rescue_node(IMrbParser p, node body, node resq, node els)
687 : base(p, node_type.NODE_RESCUE)
688 {
689 _body = body;
690 if (resq != null) {
691 var n2 = (node)resq;
692
693 while (n2 != null) {
694 rescue_t r = new rescue_t();
695 var n3 = (node)n2.car;
696 if (n3.car != null) {
697 dump_recur(r.handle_classes, (node)n3.car);
698 }
699 r.exc_var = (node)((node)n3.cdr).car;
700 r.body = (node)((node)((node)n3.cdr).cdr).car;
701 _rescue.Push(r);
702 n2 = (node)n2.cdr;
703 }
704 }
705 _else = els;
706 }
707
708 public node body { get { return _body; } }
709 public rescue_t[] rescue { get { return _rescue; } }
710 public node @else { get { return _else; } }
711
712 public override Element to_xml(xml_code_cond cond)
713 {
714 // TODO:???
715 return body.to_xml(cond);
716 }
717
718 protected override void to_rb(ruby_code_cond cond)
719 {
720 if (!ensure) {
721 cond.write_line("begin");
722 cond.increment_indent();
723 }
724 _body.to_ruby(cond);
725 cond.decrement_indent();
726 foreach (var r in _rescue) {
727 r.to_ruby(cond);
728 }
729 if (_else != null) {
730 cond.write_line("else");
731 cond.increment_indent();
732 _else.to_ruby(cond);
733 cond.decrement_indent();
734 }
735 if (!ensure) {
736 cond.write_line("end");
737 }
738 else {
739 cond.increment_indent();
740 }
741 }
742
743 public override string ToString()
744 {
745 var str = $"(:rescue {body} ";
746 foreach (var r in rescue) {
747 str += $"{r}, ";
748 }
749 return str + $" {@else})";
750 }
751 }
752
753 /* (:ensure body ensure) */
754 class ensure_node : node
755 {
756 private node _body;
757 private node _ensure;
758 public bool def;
759
760 public ensure_node(IMrbParser p, node a, node b)
761 : base(p, node_type.NODE_ENSURE)
762 {
763 _body = a;
764 _ensure = b;
765 if (_body is rescue_node) {
766 ((rescue_node)_body).ensure = true;
767 }
768 }
769
770 public node body { get { return _body; } }
771 public node ensure { get { return _ensure; } }
772
773 public override Element to_xml(xml_code_cond cond)
774 {
775 throw new NotImplementedException();
776 }
777
778 protected override void to_rb(ruby_code_cond cond)
779 {
780 if (!def) {
781 cond.write_line("begin");
782 cond.increment_indent();
783 }
784 _body.to_ruby(cond);
785 cond.decrement_indent();
786 cond.write_line("ensure");
787 cond.increment_indent();
788 _ensure.to_ruby(cond);
789 if (!def) {
790 cond.decrement_indent();
791 cond.write_line("end");
792 }
793 }
794
795 public override string ToString()
796 {
797 return $"(:ensure {body} {ensure})";
798 }
799 }
800
801 /* (:nil) */
802 class nil_node : node, IEvaluatable
803 {
804 public nil_node(IMrbParser p)
805 : base(p, node_type.NODE_NIL)
806 {
807 }
808
809 public override Element to_xml(xml_code_cond cond)
810 {
811 var block = cond.CreateElement("block");
812 block.SetAttribute("type", "logic_null");
813 return block;
814 }
815
816 protected override void to_rb(ruby_code_cond cond)
817 {
818 cond.write("nil");
819 }
820
821 public override string ToString()
822 {
823 return $"(:nil)";
824 }
825
826 public node evaluate(string method, node[] args)
827 {
828 switch (method) {
829 case "!":
830 if (args.Length != 0)
831 break;
832 return new true_node(p);
833 }
834 return null;
835 }
836 }
837
838 /* (:true) */
839 class true_node : node, IEvaluatable
840 {
841 public true_node(IMrbParser p)
842 : base(p, node_type.NODE_TRUE)
843 {
844 }
845
846 public override Element to_xml(xml_code_cond cond)
847 {
848 var block = cond.CreateElement("block");
849 block.SetAttribute("type", "logic_boolean");
850
851 var field = cond.CreateElement("field");
852 field.SetAttribute("name", "BOOL");
853 field.AppendChild(cond.CreateTextNode("TRUE"));
854 block.AppendChild(field);
855
856 return block;
857 }
858
859 protected override void to_rb(ruby_code_cond cond)
860 {
861 cond.write("true");
862 }
863
864 public override string ToString()
865 {
866 return $"(:true)";
867 }
868
869 public node evaluate(string method, node[] args)
870 {
871 switch (method) {
872 case "!":
873 if (args.Length != 0)
874 break;
875 return new false_node(p);
876 }
877 return null;
878 }
879 }
880
881 /* (:false) */
882 class false_node : node, IEvaluatable
883 {
884 public false_node(IMrbParser p)
885 : base(p, node_type.NODE_FALSE)
886 {
887 }
888
889 public override Element to_xml(xml_code_cond cond)
890 {
891 var block = cond.CreateElement("block");
892 block.SetAttribute("type", "logic_boolean");
893
894 var field = cond.CreateElement("field");
895 field.SetAttribute("name", "BOOL");
896 field.AppendChild(cond.CreateTextNode("FALSE"));
897 block.AppendChild(field);
898
899 return block;
900 }
901
902 protected override void to_rb(ruby_code_cond cond)
903 {
904 cond.write("false");
905 }
906
907 public override string ToString()
908 {
909 return $"(:false)";
910 }
911
912 public node evaluate(string method, node[] args)
913 {
914 switch (method) {
915 case "!":
916 if (args.Length != 0)
917 break;
918 return new true_node(p);
919 }
920 return null;
921 }
922 }
923
924 /* (:alias new old) */
925 class alias_node : node
926 {
927 private mrb_sym _new;
928 private mrb_sym _old;
929
930 public alias_node(IMrbParser p, mrb_sym a, mrb_sym b)
931 : base(p, node_type.NODE_ALIAS)
932 {
933 _new = a;
934 _old = b;
935 }
936
937 public mrb_sym @new { get { return _new; } }
938 public mrb_sym old { get { return _old; } }
939
940 public override Element to_xml(xml_code_cond cond)
941 {
942 throw new NotImplementedException();
943 }
944
945 protected override void to_rb(ruby_code_cond cond)
946 {
947 cond.write_line($"alias {p.sym2name(_new)} {p.sym2name(_old)}");
948 }
949
950 public override string ToString()
951 {
952 return $"(:alias {p.sym2name(@new)} {p.sym2name(old)})";
953 }
954 }
955
956 /* (:if cond then else) */
957 class if_node : node
958 {
959 private node _cond;
960 private node _then;
961 private node _else;
962 bool _inline;
963
964 public if_node(IMrbParser p, node cond, node then, node @else, bool inline)
965 : base(p, node_type.NODE_IF)
966 {
967 _cond = cond;
968 _then = then;
969 _else = @else;
970 _inline = inline;
971 }
972
973 public node cond { get { return _cond; } }
974 public node then { get { return _then; } }
975 public node @else { get { return _else; } }
976
977 public override Element to_xml(xml_code_cond cond)
978 {
979 var _elsif = new Tuple<node, node>[0];
980 node _else = this._else;
981
982 _elsif.Push(new Tuple<node, node>(_cond, _then));
983 for (var c = _else as if_node; c != null; _else = c._else, c = _else as if_node) {
984 _elsif.Push(new Tuple<node, node>(c._cond, c._then));
985 }
986
987 var block = cond.CreateElement("block");
988 block.SetAttribute("type", "controls_if");
989
990 var mutation = cond.CreateElement("mutation");
991 mutation.SetAttribute("elseif", _elsif.Length.ToString());
992 mutation.SetAttribute("else", _else != null ? "1" : "0");
993 block.AppendChild(mutation);
994
995 int i = 0;
996 foreach (var e in _elsif) {
997 var value = cond.CreateElement("value");
998 value.SetAttribute("name", $"IF{i}");
999 value.AppendChild(e.Item1.to_xml(cond));
1000 block.AppendChild(value);
1001
1002 var statement = cond.CreateElement("statement");
1003 statement.SetAttribute("name", $"DO{i}");
1004 statement.AppendChild(e.Item2.to_xml(cond));
1005 block.AppendChild(statement);
1006 i++;
1007 }
1008
1009 if (_else != null) {
1010 var statement = cond.CreateElement("statement");
1011 statement.SetAttribute("name", "ELSE");
1012 statement.AppendChild(_else.to_xml(cond));
1013 block.AppendChild(statement);
1014 }
1015
1016 return block;
1017 }
1018
1019 protected override void to_rb(ruby_code_cond cond)
1020 {
1021 if (_inline) {
1022 cond.increment_nest();
1023 cond.write("(");
1024 _cond.to_ruby(cond);
1025 cond.write(" ? ");
1026 _then.to_ruby(cond);
1027 cond.write(" : ");
1028 _else.to_ruby(cond);
1029 cond.decrement_nest();
1030 }
1031 else {
1032 var _elsif = new Tuple<node, node>[0];
1033 node _else = this._else;
1034
1035 for (var c = _else as if_node; c != null; _else = c._else, c = _else as if_node) {
1036 _elsif.Push(new Tuple<node, node>(c._cond, c._then));
1037 }
1038
1039 cond.increment_nest();
1040 cond.write("if ");
1041 _cond.to_ruby(cond);
1042 cond.decrement_nest();
1043 cond.increment_indent();
1044 _then.to_ruby(cond);
1045 cond.decrement_indent();
1046 foreach (var e in _elsif) {
1047 cond.increment_nest();
1048 cond.write("elsif ");
1049 e.Item1.to_ruby(cond);
1050 cond.decrement_nest();
1051 cond.write_line();
1052 cond.increment_indent();
1053 e.Item2.to_ruby(cond);
1054 cond.decrement_indent();
1055 }
1056
1057 if (_else != null) {
1058 cond.write_line("else");
1059 cond.increment_indent();
1060 _else.to_ruby(cond);
1061 cond.decrement_indent();
1062 }
1063 cond.write_line("end");
1064 }
1065 }
1066
1067 public override string ToString()
1068 {
1069 return $"(:if {cond} {then} {@else})";
1070 }
1071 }
1072
1073 /* (:unless cond then else) */
1074 class unless_node : node
1075 {
1076 private node _cond;
1077 private node _then;
1078 private node _else;
1079
1080 public unless_node(IMrbParser p, node a, node b, node c)
1081 : base(p, node_type.NODE_IF)
1082 {
1083 _cond = a;
1084 _then = c;
1085 _else = b;
1086 }
1087
1088 public node cond { get { return _cond; } }
1089 public node then { get { return _then; } }
1090 public node @else { get { return _else; } }
1091
1092 public override Element to_xml(xml_code_cond cond)
1093 {
1094 var block = cond.CreateElement("block");
1095 block.SetAttribute("type", "controls_if");
1096
1097 var value = cond.CreateElement("value");
1098 value.SetAttribute("name", "IF0");
1099 value.AppendChild(_cond.to_xml(cond));
1100 block.AppendChild(value);
1101
1102 if (_then != null) {
1103 var statement = cond.CreateElement("statement");
1104 statement.SetAttribute("name", "DO0");
1105 block.AppendChild(statement);
1106
1107 statement.AppendChild(_then.to_xml(cond));
1108 }
1109
1110 if (_else != null) {
1111 var statement = cond.CreateElement("statement");
1112 statement.SetAttribute("name", "ELSE");
1113 block.AppendChild(statement);
1114
1115 statement.AppendChild(_else.to_xml(cond));
1116 }
1117
1118 return block;
1119 }
1120
1121 protected override void to_rb(ruby_code_cond cond)
1122 {
1123 cond.increment_nest();
1124 cond.write("unless ");
1125 _cond.to_ruby(cond);
1126 cond.decrement_nest();
1127 cond.increment_indent();
1128 _else.to_ruby(cond);
1129 cond.decrement_indent();
1130
1131 if (_then != null) {
1132 cond.write_line("else");
1133 cond.increment_indent();
1134 _then.to_ruby(cond);
1135 cond.decrement_indent();
1136 }
1137 cond.write_line("end");
1138 }
1139
1140 public override string ToString()
1141 {
1142 return $"(:unless {cond} {then} {@else})";
1143 }
1144 }
1145
1146 /* (:while cond body) */
1147 class while_node : node
1148 {
1149 private node _cond;
1150 private node _body;
1151
1152 public while_node(IMrbParser p, node a, node b)
1153 : base(p, node_type.NODE_WHILE)
1154 {
1155 _cond = a;
1156 _body = b;
1157 }
1158
1159 public node cond { get { return _cond; } }
1160 public node body { get { return _body; } }
1161
1162 public override Element to_xml(xml_code_cond cond)
1163 {
1164 var block = cond.CreateElement("block");
1165 block.SetAttribute("type", "controls_whileUntil");
1166
1167 var field = cond.CreateElement("field");
1168 field.SetAttribute("name", "MODE");
1169 field.AppendChild(cond.CreateTextNode("WHILE"));
1170 block.AppendChild(field);
1171
1172 var value = cond.CreateElement("value");
1173 value.SetAttribute("name", "BOOL");
1174 value.AppendChild(_cond.to_xml(cond));
1175 block.AppendChild(value);
1176
1177 var statement = cond.CreateElement("statement");
1178 statement.SetAttribute("name", "DO");
1179 statement.AppendChild(_body.to_xml(cond));
1180 block.AppendChild(statement);
1181
1182 return block;
1183 }
1184
1185 protected override void to_rb(ruby_code_cond cond)
1186 {
1187 cond.increment_nest();
1188 cond.write("while ");
1189 _cond.to_ruby(cond);
1190 cond.decrement_nest();
1191 cond.increment_indent();
1192 _body.to_ruby(cond);
1193 cond.decrement_indent();
1194 cond.write_line("end");
1195 }
1196
1197 public override string ToString()
1198 {
1199 return $"(:while {cond} {body})";
1200 }
1201 }
1202
1203 /* (:until cond body) */
1204 class until_node : node
1205 {
1206 private node _cond;
1207 private node _body;
1208
1209 public until_node(IMrbParser p, node a, node b)
1210 : base(p, node_type.NODE_UNTIL)
1211 {
1212 _cond = a;
1213 _body = b;
1214 }
1215
1216 public node cond { get { return _cond; } }
1217 public node body { get { return _body; } }
1218
1219 public override Element to_xml(xml_code_cond cond)
1220 {
1221 var block = cond.CreateElement("block");
1222 block.SetAttribute("type", "controls_whileUntil");
1223
1224 var field = cond.CreateElement("field");
1225 field.SetAttribute("name", "MODE");
1226 field.AppendChild(cond.CreateTextNode("UNTIL"));
1227 block.AppendChild(field);
1228
1229 var value = cond.CreateElement("value");
1230 value.SetAttribute("name", "BOOL");
1231 value.AppendChild(_cond.to_xml(cond));
1232 block.AppendChild(value);
1233
1234 var statement = cond.CreateElement("statement");
1235 statement.SetAttribute("name", "DO");
1236 statement.AppendChild(_body.to_xml(cond));
1237 block.AppendChild(statement);
1238
1239 return block;
1240 }
1241
1242 protected override void to_rb(ruby_code_cond cond)
1243 {
1244 cond.increment_nest();
1245 cond.write("until ");
1246 _cond.to_ruby(cond);
1247 cond.decrement_nest();
1248 cond.increment_indent();
1249 _body.to_ruby(cond);
1250 cond.decrement_indent();
1251 cond.write_line("end");
1252 }
1253
1254 public override string ToString()
1255 {
1256 return $"(:until {cond} {body})";
1257 }
1258 }
1259
1260 /* (:for var obj body) */
1261 class for_node : node
1262 {
1263 public class var_t
1264 {
1265 public node[] pre = new node[0];
1266 public node rest;
1267 public node[] post = new node[0];
1268
1269 public override string ToString()
1270 {
1271 var str = "(";
1272 foreach (var p in pre) {
1273 str += $"{p} ";
1274 }
1275 str += $"{rest} ";
1276 foreach (var p in post) {
1277 str += $"{p} ";
1278 }
1279 return str + ")";
1280 }
1281
1282 internal void to_ruby(ruby_code_cond cond)
1283 {
1284 int i = pre.Length + (rest != null ? 1 : 0) + post.Length;
1285 foreach (var p in pre) {
1286 p.to_ruby(cond);
1287 i--; if (i > 0) cond.write(", ");
1288 }
1289 if (rest != null) {
1290 rest.to_ruby(cond);
1291 i--; if (i > 0) cond.write(", ");
1292 }
1293 foreach (var p in post) {
1294 p.to_ruby(cond);
1295 i--; if (i > 0) cond.write(", ");
1296 }
1297 }
1298 }
1299 private var_t _var;
1300 private node _in;
1301 private node _do;
1302
1303 public for_node(IMrbParser p, node v, node o, node b)
1304 : base(p, node_type.NODE_FOR)
1305 {
1306 _var = new var_t();
1307 node n2 = v;
1308
1309 if (n2.car != null) {
1310 dump_recur(_var.pre, (node)n2.car);
1311 }
1312 n2 = (node)n2.cdr;
1313 if (n2 != null) {
1314 if (n2.car != null) {
1315 _var.rest = (node)n2.car;
1316 }
1317 n2 = (node)n2.cdr;
1318 if (n2 != null) {
1319 if (n2.car != null) {
1320 dump_recur(_var.post, (node)n2.car);
1321 }
1322 }
1323 }
1324 _in = o;
1325 _do = b;
1326 }
1327
1328 public var_t var { get { return _var; } }
1329 public node @in { get { return _in; } }
1330 public node @do { get { return _do; } }
1331
1332 public override Element to_xml(xml_code_cond cond)
1333 {
1334 var block = cond.CreateElement("block");
1335 block.SetAttribute("type", "controls_forEach");
1336
1337 var field = cond.CreateElement("field");
1338 field.SetAttribute("name", "VAR");
1339 // TODO:var?
1340 var pre = var.pre[0];
1341 switch ((node_type)pre.car) {
1342 case node_type.NODE_GVAR:
1343 field.AppendChild(cond.CreateTextNode(p.sym2name(((gvar_node)pre).name)));
1344 break;
1345 case node_type.NODE_CVAR:
1346 field.AppendChild(cond.CreateTextNode(p.sym2name(((cvar_node)pre).name)));
1347 break;
1348 case node_type.NODE_IVAR:
1349 field.AppendChild(cond.CreateTextNode(p.sym2name(((ivar_node)pre).name)));
1350 break;
1351 case node_type.NODE_LVAR:
1352 field.AppendChild(cond.CreateTextNode(p.sym2name(((lvar_node)pre).name)));
1353 break;
1354 default:
1355 // TODO: ?
1356 throw new NotImplementedException();
1357 }
1358 block.AppendChild(field);
1359
1360 var value = cond.CreateElement("value");
1361 value.SetAttribute("name", "LIST");
1362 value.AppendChild(_in.to_xml(cond));
1363 block.AppendChild(value);
1364
1365 var statement = cond.CreateElement("statement");
1366 statement.SetAttribute("name", "DO");
1367 statement.AppendChild(_do.to_xml(cond));
1368 block.AppendChild(statement);
1369
1370 return block;
1371 }
1372
1373 protected override void to_rb(ruby_code_cond cond)
1374 {
1375 cond.increment_nest();
1376 cond.write("for ");
1377 _var.to_ruby(cond);
1378 cond.write(" in ");
1379 _in.to_ruby(cond);
1380 cond.write(" do");
1381 cond.decrement_nest();
1382 cond.increment_indent();
1383 _do.to_ruby(cond);
1384 cond.decrement_indent();
1385 cond.write_line("end");
1386 }
1387
1388 public override string ToString()
1389 {
1390 return $"(:for {var} {@in} {@do})";
1391 }
1392 }
1393
1394 /* (:case a ((when ...) body) ((when...) body)) */
1395 class case_node : node
1396 {
1397 public class when_t
1398 {
1399 public node[] value = new node[0];
1400 public node body;
1401
1402 public override string ToString()
1403 {
1404 var str = $"(when ";
1405 foreach (var c in value) {
1406 str += $"{c} ";
1407 }
1408 return str + $"{body})";
1409 }
1410 }
1411 private node _arg;
1412 private when_t[] _when = new when_t[0];
1413
1414 public case_node(IMrbParser p, node a, node b)
1415 : base(p, node_type.NODE_CASE)
1416 {
1417 _arg = a;
1418 while (b != null) {
1419 var w = new when_t();
1420 dump_recur(w.value, (node)((node)b.car).car);
1421 w.body = (node)((node)b.car).cdr;
1422 _when.Push(w);
1423 b = (node)b.cdr;
1424 }
1425 }
1426
1427 public case_node(IMrbParser p, node a, when_t[] b)
1428 : base(p, node_type.NODE_CASE)
1429 {
1430 _arg = a;
1431 _when = (when_t[])_when.Concat(b);
1432 }
1433
1434 public node arg { get { return _arg; } }
1435 public when_t[] when { get { return _when; } }
1436
1437 public override Element to_xml(xml_code_cond cond)
1438 {
1439 var block = cond.CreateElement("block");
1440 block.SetAttribute("type", "switch_case_number");
1441
1442 int c = 0, d = 0;
1443 when_t default_node = null;
1444 foreach (var w in _when) {
1445 if (w.value.Length == 0) {
1446 default_node = w;
1447 d = 1;
1448 }
1449 else
1450 c++;
1451 }
1452
1453 var mutation = cond.CreateElement("mutation");
1454 mutation.SetAttribute("case", c.ToString());
1455 mutation.SetAttribute("default", d.ToString());
1456 block.AppendChild(mutation);
1457
1458 int i = 0;
1459 foreach (var w in _when) {
1460 if (w.value.Length == 0)
1461 continue;
1462
1463 var field = cond.CreateElement("field");
1464 field.SetAttribute("name", "CONST" + i);
1465 // TODO:whenの値が複数の場合
1466 field.AppendChild(cond.CreateTextNode(MrbParser.UTF8ArrayToString(((int_node)w.value[0]).num, 0)));
1467 block.AppendChild(field);
1468 i++;
1469 }
1470
1471 var value = cond.CreateElement("value");
1472 value.SetAttribute("name", "SWITCH");
1473 block.AppendChild(value);
1474
1475 value.AppendChild(_arg.to_xml(cond));
1476
1477 foreach (var w in _when) {
1478 if (w.value.Length == 0)
1479 continue;
1480
1481 var statement = cond.CreateElement("statement");
1482 statement.SetAttribute("name", "DO" + i);
1483 statement.AppendChild(w.body.to_xml(cond));
1484 block.AppendChild(statement);
1485 }
1486
1487 if (default_node != null) {
1488 var statement = cond.CreateElement("statement");
1489 statement.SetAttribute("name", "DEFAULT");
1490 statement.AppendChild(default_node.body.to_xml(cond));
1491 block.AppendChild(statement);
1492 }
1493
1494 return block;
1495 }
1496
1497 protected override void to_rb(ruby_code_cond cond)
1498 {
1499 cond.increment_nest();
1500 cond.write("case ");
1501 if (_arg != null)
1502 _arg.to_ruby(cond);
1503 cond.decrement_nest();
1504 cond.separate_line();
1505 foreach (var w in _when) {
1506 cond.increment_nest();
1507 var count = w.value.Length;
1508 if (count != 0) {
1509 cond.write("when ");
1510 foreach (var v in w.value) {
1511 v.to_ruby(cond);
1512 count--;
1513 if (count > 0)
1514 cond.write(", ");
1515 }
1516 }
1517 else
1518 cond.write("else");
1519 cond.decrement_nest();
1520
1521 cond.increment_indent();
1522 w.body.to_ruby(cond);
1523 cond.decrement_indent();
1524 }
1525 cond.write_line("end");
1526 }
1527
1528 public override string ToString()
1529 {
1530 var str = $"(:case {arg} ";
1531 foreach (var w in when) {
1532 str += $"{w} ";
1533 }
1534 return str + ")";
1535 }
1536 }
1537
1538 /* (:postexe a) */
1539 class postexe_node : node
1540 {
1541 private node _postexe;
1542
1543 public postexe_node(IMrbParser p, node a)
1544 : base(p, node_type.NODE_POSTEXE)
1545 {
1546 _postexe = a;
1547 }
1548
1549 public node postexe { get { return _postexe; } }
1550
1551 public override Element to_xml(xml_code_cond cond)
1552 {
1553 throw new NotImplementedException();
1554 }
1555
1556 protected override void to_rb(ruby_code_cond cond)
1557 {
1558 cond.write_line("END {");
1559 _postexe.to_ruby(cond);
1560 cond.write_line("}");
1561 }
1562
1563 public override string ToString()
1564 {
1565 return $"(:postexe {postexe})";
1566 }
1567 }
1568
1569 /* (:self) */
1570 class self_node : node
1571 {
1572 public self_node(IMrbParser p)
1573 : base(p, node_type.NODE_SELF)
1574 {
1575 }
1576
1577 public override Element to_xml(xml_code_cond cond)
1578 {
1579 throw new NotImplementedException();
1580 }
1581
1582 protected override void to_rb(ruby_code_cond cond)
1583 {
1584 cond.write("self");
1585 }
1586
1587 public override string ToString()
1588 {
1589 return $"(:self)";
1590 }
1591 }
1592
1593 /* (:call a b c) */
1594 class call_node : node
1595 {
1596 private node _obj;
1597 private mrb_sym _method;
1598 private node[] _args = new node[0];
1599 private node _block;
1600 private MrbTokens _pass;
1601
1602 public call_node(IMrbParser p, node a, mrb_sym b, node c, MrbTokens pass)
1603 : base(p, pass != 0 ? node_type.NODE_CALL : node_type.NODE_SCALL)
1604 {
1605 _pass = pass;
1606 NODE_LINENO(a);
1607
1608 _obj = a;
1609 _method = b;
1610 if (c != null) {
1611 dump_recur(_args, (node)c.car);
1612 if (c.cdr != null) {
1613 _block = (node)c.cdr;
1614 }
1615 }
1616 }
1617
1618 public call_node(IMrbParser p, node a, mrb_sym b, node[] args = null, node block = null)
1619 : base(p, node_type.NODE_CALL)
1620 {
1621 _obj = a;
1622 _method = b;
1623 if (args != null)
1624 _args = (node[])_args.Concat(args);
1625 _block = block;
1626 }
1627
1628 public call_node(IMrbParser p, node a, mrb_sym b, node arg)
1629 : base(p, node_type.NODE_CALL)
1630 {
1631 _obj = a;
1632 _method = b;
1633 if (arg != null)
1634 _args.Push(arg);
1635 _pass = (MrbTokens)1;
1636 }
1637
1638 public node obj { get { return _obj; } }
1639 public mrb_sym method { get { return _method; } }
1640 public node[] args { get { return _args; } }
1641 public node block { get { return _block; } }
1642
1643 internal void add_block(node b)
1644 {
1645 if (b != null) {
1646 if (_block != null) {
1647 p.yyError("both block arg and actual block given");
1648 }
1649 _block = b;
1650 }
1651 }
1652
1653 public override Element to_xml(xml_code_cond cond)
1654 {
1655 var method = p.sym2name(_method);
1656 switch (method) {
1657 case "==": return logic_compare(cond, "EQ");
1658 case "!=": return logic_compare(cond, "NEQ");
1659 case "<": return logic_compare(cond, "LT");
1660 case "<=": return logic_compare(cond, "LTE");
1661 case ">": return logic_compare(cond, "GT");
1662 case ">=": return logic_compare(cond, "GTE");
1663 }
1664
1665 return procedures_callreturn(cond, method);
1666 }
1667
1668 private Element procedures_callreturn(xml_code_cond cond, string method)
1669 {
1670 var block = cond.CreateElement("block");
1671 block.SetAttribute("type", "procedures_callreturn");
1672
1673 var mutation = cond.CreateElement("mutation");
1674 mutation.SetAttribute("name", method);
1675 block.AppendChild(mutation);
1676
1677 int i = 0;
1678 foreach (var a in args) {
1679 var arg = cond.CreateElement("arg");
1680 // TODO: 引数名を持ってくkる
1681 arg.SetAttribute("name", i.ToString());
1682 arg.AppendChild(a.to_xml(cond));
1683 block.AppendChild(arg);
1684 i++;
1685 }
1686
1687 return block;
1688 }
1689
1690 private Element logic_compare(xml_code_cond cond, string op)
1691 {
1692 var block = cond.CreateElement("block");
1693 block.SetAttribute("type", "logic_compare");
1694
1695 var field = cond.CreateElement("field");
1696 field.SetAttribute("name", "OP");
1697 field.AppendChild(cond.CreateTextNode(op));
1698 block.AppendChild(field);
1699
1700 var value = cond.CreateElement("value");
1701 value.SetAttribute("name", "A");
1702 value.AppendChild(_obj.to_xml(cond));
1703 block.AppendChild(value);
1704
1705 // argsは1つ
1706 value = cond.CreateElement("value");
1707 value.SetAttribute("name", "B");
1708 value.AppendChild(args[0].to_xml(cond));
1709 block.AppendChild(value);
1710
1711 return block;
1712 }
1713
1714 public bool isArray(node _obj)
1715 {
1716 var cnst = _obj as const_node;
1717 return (cnst != null) && (p.sym2name(cnst.name) == "Array");
1718 }
1719
1720 protected override void to_rb(ruby_code_cond cond)
1721 {
1722 var blk_arg = _block as block_arg_node;
1723 var blk = _block;
1724 if (blk_arg != null)
1725 blk = null;
1726 var m = p.sym2name(_method);
1727 int i = _args.Length + (blk_arg != null ? 1 : 0);
1728 if (_pass == (MrbTokens)1) {
1729 cond.increment_nest();
1730 switch (m) {
1731 case "!":
1732 case "~":
1733 cond.write(m);
1734 _obj.to_ruby(cond);
1735 foreach (var a in _args) {
1736 a.to_ruby(cond);
1737 i--; if (i > 0) cond.write(", ");
1738 }
1739 if (blk_arg != null) {
1740 blk_arg.to_ruby(cond);
1741 }
1742 break;
1743 case "+@":
1744 case "-@":
1745 cond.write(m.Substring(0, 1));
1746 _obj.to_ruby(cond);
1747 foreach (var a in _args) {
1748 a.to_ruby(cond);
1749 i--; if (i > 0) cond.write(", ");
1750 }
1751 if (blk_arg != null) {
1752 blk_arg.to_ruby(cond);
1753 }
1754 break;
1755 default:
1756 _obj.to_ruby(cond);
1757 cond.write(" " + m + " ");
1758 foreach (var a in _args) {
1759 a.to_ruby(cond);
1760 i--; if (i > 0) cond.write(", ");
1761 }
1762 if (blk_arg != null) {
1763 blk_arg.to_ruby(cond);
1764 }
1765 break;
1766 }
1767 cond.decrement_nest();
1768 }
1769 else {
1770 string call_op = _pass == MrbTokens.tCOLON2 ? "::" : ".";
1771 switch (m) {
1772 case "[]":
1773 cond.increment_nest();
1774 _obj.to_ruby(cond);
1775 if (isArray(_obj)) {
1776 cond.write(call_op + "[]");
1777 cond.write("(");
1778 foreach (var a in _args) {
1779 a.to_ruby(cond);
1780 i--; if (i > 0) cond.write(", ");
1781 }
1782 cond.write(")");
1783 }
1784 else if (i == 0)
1785 cond.write("[]");
1786 else {
1787 cond.write("[");
1788 foreach (var a in _args) {
1789 a.to_ruby(cond);
1790 i--; if (i > 0) cond.write(", ");
1791 }
1792 cond.write("]");
1793 }
1794 cond.decrement_nest();
1795 break;
1796 case "[]=":
1797 cond.increment_nest();
1798 _obj.to_ruby(cond);
1799 cond.write(".[]=");
1800 cond.write("(");
1801 foreach (var a in _args) {
1802 a.to_ruby(cond);
1803 i--; if (i > 0) cond.write(", ");
1804 }
1805 if (blk_arg != null) {
1806 blk_arg.to_ruby(cond);
1807 }
1808 cond.write(")");
1809 cond.decrement_nest();
1810 break;
1811 default:
1812 cond.increment_nest();
1813 _obj.to_ruby(cond);
1814 if (i == 0)
1815 cond.write(call_op + m);
1816 else {
1817 cond.write(call_op + m + "(");
1818 foreach (var a in _args) {
1819 a.to_ruby(cond);
1820 i--; if (i > 0) cond.write(", ");
1821 }
1822 if (blk_arg != null) {
1823 blk_arg.to_ruby(cond);
1824 }
1825 cond.write(")");
1826 }
1827 cond.decrement_nest();
1828 break;
1829 }
1830 }
1831 if (blk != null) {
1832 blk.to_ruby(cond);
1833 }
1834 else if (cond.nest == 0)
1835 cond.write_line();
1836 }
1837
1838 public override string ToString()
1839 {
1840 var str = $"(:call {obj} {p.sym2name(method)} ";
1841 foreach (var v in args) {
1842 str += v.ToString() + " ";
1843 }
1844 return str + $"{block})";
1845 }
1846 }
1847
1848 /* (:fcall self mid args) */
1849 class fcall_node : node
1850 {
1851 private node _self;
1852 private mrb_sym _method;
1853 private node[] _args = new node[0];
1854 private node _block;
1855
1856 public fcall_node(IMrbParser p, mrb_sym b, node c)
1857 : base(p, node_type.NODE_FCALL)
1858 {
1859 node n = new self_node(p);
1860 n.NODE_LINENO(c);
1861 NODE_LINENO(c);
1862
1863 _self = n;
1864 _method = b;
1865 if (c != null) {
1866 dump_recur(_args, (node)c.car);
1867 if (c.cdr != null) {
1868 _block = (node)c.cdr;
1869 }
1870 }
1871 }
1872
1873 public fcall_node(IMrbParser p, mrb_sym b, node[] args = null, node block = null)
1874 : base(p, node_type.NODE_FCALL)
1875 {
1876 _self = new self_node(p);
1877 _method = b;
1878 if (args != null)
1879 _args = (node[])_args.Concat(args);
1880 _block = block;
1881 }
1882
1883 public node self { get { return _self; } }
1884 public mrb_sym method { get { return _method; } }
1885 public node[] args { get { return _args; } }
1886 public node block { get { return _block; } }
1887
1888 internal void add_block(node b)
1889 {
1890 if (b != null) {
1891 if (_block != null) {
1892 p.yyError("both block arg and actual block given");
1893 }
1894 _block = b;
1895 }
1896 }
1897
1898 public override Element to_xml(xml_code_cond cond)
1899 {
1900 var block = cond.CreateElement("block");
1901 block.SetAttribute("type", "procedures_callreturn");
1902
1903 var mutation = cond.CreateElement("mutation");
1904 mutation.SetAttribute("name", p.sym2name(_method));
1905 block.AppendChild(mutation);
1906
1907 int i = 0;
1908 foreach (var a in args) {
1909 var arg = cond.CreateElement("arg");
1910 // TODO: 引数名を持ってくkる
1911 arg.SetAttribute("name", i.ToString());
1912 arg.AppendChild(a.to_xml(cond));
1913 block.AppendChild(arg);
1914 i++;
1915 }
1916
1917 return block;
1918 }
1919
1920 protected override void to_rb(ruby_code_cond cond)
1921 {
1922 cond.increment_nest();
1923 var blk_arg = _block as block_arg_node;
1924 var blk = _block;
1925 if (blk_arg != null)
1926 blk = null;
1927 var m = p.sym2name(_method);
1928 int i = _args.Length + (blk_arg != null ? 1 : 0);
1929 switch (m) {
1930 case "include":
1931 case "raise":
1932 cond.write(m + " ");
1933 foreach (var a in _args) {
1934 a.to_ruby(cond);
1935 i--; if (i > 0) cond.write(", ");
1936 }
1937 if (blk_arg != null) {
1938 blk_arg.to_ruby(cond);
1939 }
1940 break;
1941 default:
1942 if (i == 0)
1943 cond.write(m);
1944 else {
1945 cond.write(m + "(");
1946 foreach (var a in _args) {
1947 a.to_ruby(cond);
1948 i--; if (i > 0) cond.write(", ");
1949 }
1950 if (blk_arg != null) {
1951 blk_arg.to_ruby(cond);
1952 }
1953 cond.write(")");
1954 }
1955 break;
1956 }
1957 cond.decrement_nest();
1958 if (blk != null) {
1959 blk.to_ruby(cond);
1960 }
1961 else if (cond.nest == 0)
1962 cond.write_line();
1963 }
1964
1965 public override string ToString()
1966 {
1967 var str = $"(:fcall {self} {p.sym2name(method)} ";
1968 foreach (var v in args) {
1969 str += v.ToString() + " ";
1970 }
1971 return str + $"{block})";
1972 }
1973 }
1974
1975 /* (:super . c) */
1976 class super_node : node
1977 {
1978 private node[] _args = new node[0];
1979 private node _block;
1980
1981 public super_node(IMrbParser p, node c)
1982 : base(p, node_type.NODE_SUPER)
1983 {
1984 if (c != null) {
1985 dump_recur(_args, (node)c.car);
1986 if (c.cdr != null) {
1987 _block = (node)c.cdr;
1988 }
1989 }
1990 }
1991
1992 public super_node(IMrbParser p, node[] args)
1993 : base(p, node_type.NODE_SUPER)
1994 {
1995 _args = (node[])_args.Concat(args);
1996 }
1997
1998 public node[] args { get { return _args; } }
1999 public node block { get { return _block; } }
2000
2001 public override Element to_xml(xml_code_cond cond)
2002 {
2003 var block = cond.CreateElement("block");
2004 block.SetAttribute("type", "procedures_callreturn");
2005
2006 var mutation = cond.CreateElement("mutation");
2007 mutation.SetAttribute("name", "super");
2008 block.AppendChild(mutation);
2009
2010 int i = 0;
2011 foreach (var a in args) {
2012 var arg = cond.CreateElement("arg");
2013 // TODO: 引数名を持ってくkる
2014 arg.SetAttribute("name", i.ToString());
2015 arg.AppendChild(a.to_xml(cond));
2016 block.AppendChild(arg);
2017 i++;
2018 }
2019
2020 return block;
2021 }
2022
2023 protected override void to_rb(ruby_code_cond cond)
2024 {
2025 cond.increment_nest();
2026 var blk_arg = _block as block_arg_node;
2027 var blk = _block;
2028 if (blk_arg != null)
2029 blk = null;
2030 int i = _args.Length + (blk_arg != null ? 1 : 0);
2031 if (i == 0)
2032 cond.write("super");
2033 else {
2034 cond.write("super(");
2035 foreach (var a in _args) {
2036 a.to_ruby(cond);
2037 i--; if (i > 0) cond.write(", ");
2038 }
2039 if (blk_arg != null) {
2040 blk_arg.to_ruby(cond);
2041 }
2042 cond.write(")");
2043 }
2044 cond.decrement_nest();
2045 if (blk != null) {
2046 blk.to_ruby(cond);
2047 }
2048 else if (cond.nest == 0)
2049 cond.write_line();
2050 }
2051
2052 public override string ToString()
2053 {
2054 var str = "(:super ";
2055 foreach (var v in args) {
2056 str += v.ToString() + " ";
2057 }
2058 return str + block + ")";
2059 }
2060
2061 internal void add_block(node b)
2062 {
2063 if (b != null) {
2064 if (_block != null) {
2065 p.yyError("both block arg and actual block given");
2066 }
2067 _block = b;
2068 }
2069 }
2070 }
2071
2072 /* (:zsuper) */
2073 class zsuper_node : node
2074 {
2075 private node _block; // 必要?
2076
2077 public zsuper_node(IMrbParser p)
2078 : base(p, node_type.NODE_ZSUPER)
2079 {
2080 }
2081
2082 internal void add_block(node b)
2083 {
2084 if (b != null) {
2085 if (_block != null) {
2086 p.yyError("both block arg and actual block given");
2087 }
2088 _block = b;
2089 }
2090 }
2091
2092 public override Element to_xml(xml_code_cond cond)
2093 {
2094 throw new NotImplementedException();
2095 }
2096
2097 protected override void to_rb(ruby_code_cond cond)
2098 {
2099 cond.increment_nest();
2100 var blk_arg = _block as block_arg_node;
2101 var blk = _block;
2102 if (blk_arg != null)
2103 blk = null;
2104 if (blk_arg == null)
2105 cond.write("super");
2106 else {
2107 cond.write("super(");
2108 if (blk_arg != null) {
2109 blk_arg.to_ruby(cond);
2110 }
2111 cond.write(")");
2112 }
2113 cond.decrement_nest();
2114 if (blk != null) {
2115 blk.to_ruby(cond);
2116 }
2117 else if (cond.nest == 0)
2118 cond.write_line();
2119 }
2120
2121 public override string ToString()
2122 {
2123 return $"(:zsuper)";
2124 }
2125 }
2126
2127 /* (:yield . c) */
2128 class yield_node : node
2129 {
2130 private node[] _args = new node[0];
2131
2132 public yield_node(IMrbParser p, node c)
2133 : base(p, node_type.NODE_YIELD)
2134 {
2135 if (c != null) {
2136 if (c.cdr != null) {
2137 p.yyError("both block arg and actual block given");
2138 }
2139 c = (node)c.car;
2140 }
2141
2142 dump_recur(_args, (node)c);
2143 }
2144
2145 public node[] args { get { return _args; } }
2146
2147 public override Element to_xml(xml_code_cond cond)
2148 {
2149 throw new NotImplementedException();
2150 }
2151
2152 protected override void to_rb(ruby_code_cond cond)
2153 {
2154 cond.increment_nest();
2155 int i = _args.Length;
2156 if (i == 0)
2157 cond.write("yield");
2158 else {
2159 cond.write("yield ");
2160 foreach (var a in _args) {
2161 a.to_ruby(cond);
2162 i--; if (i > 0) cond.write(", ");
2163 }
2164 }
2165 cond.decrement_nest();
2166 if (cond.nest == 0)
2167 cond.write_line();
2168 }
2169
2170 public override string ToString()
2171 {
2172 var str = "(:yield ";
2173 foreach (var v in args) {
2174 str += v.ToString() + " ";
2175 }
2176 return str + ")";
2177 }
2178 }
2179
2180 /* (:return . c) */
2181 class return_node : node
2182 {
2183 private node _retval;
2184
2185 public return_node(IMrbParser p, node c)
2186 : base(p, node_type.NODE_RETURN)
2187 {
2188 _retval = c;
2189 }
2190
2191 public node retval { get { return _retval; } }
2192
2193 public override Element to_xml(xml_code_cond cond)
2194 {
2195 var block = cond.CreateElement("block");
2196 block.SetAttribute("type", "procedures_return");
2197
2198 var mutation = cond.CreateElement("mutation");
2199 mutation.SetAttribute("value", (_retval != null) ? "0" : "1");
2200 block.AppendChild(mutation);
2201
2202 if (_retval != null) {
2203 var value = cond.CreateElement("value");
2204 value.SetAttribute("name", "VALUE");
2205 value.AppendChild(_retval.to_xml(cond));
2206 block.AppendChild(value);
2207 }
2208
2209 return block;
2210 }
2211
2212 protected override void to_rb(ruby_code_cond cond)
2213 {
2214 cond.increment_nest();
2215 if (_retval != null) {
2216 cond.write("return ");
2217 _retval.to_ruby(cond);
2218 cond.write_line();
2219 }
2220 else {
2221 cond.write_line("return");
2222 }
2223 cond.decrement_nest();
2224 }
2225
2226 public override string ToString()
2227 {
2228 return $"(:return . {retval})";
2229 }
2230 }
2231
2232 /* (:break . c) */
2233 class break_node : node
2234 {
2235 private node _retval;
2236
2237 public break_node(IMrbParser p, node c)
2238 : base(p, node_type.NODE_BREAK)
2239 {
2240 _retval = c;
2241 }
2242
2243 public node retval { get { return _retval; } }
2244
2245 public override Element to_xml(xml_code_cond cond)
2246 {
2247 var block = cond.CreateElement("block");
2248 block.SetAttribute("type", "controls_flow_statements");
2249
2250 var field = cond.CreateElement("field");
2251 field.SetAttribute("name", "FLOW");
2252 field.AppendChild(cond.CreateTextNode("BREAK"));
2253 block.AppendChild(field);
2254
2255 return block;
2256 }
2257
2258 protected override void to_rb(ruby_code_cond cond)
2259 {
2260 cond.increment_nest();
2261 if (_retval != null) {
2262 cond.write("break ");
2263 _retval.to_ruby(cond);
2264 cond.write_line();
2265 }
2266 else {
2267 cond.write_line("break");
2268 }
2269 cond.decrement_nest();
2270 }
2271
2272 public override string ToString()
2273 {
2274 return $"(:break . {retval})";
2275 }
2276 }
2277
2278 /* (:next . c) */
2279 class next_node : node
2280 {
2281 private node _retval;
2282
2283 public next_node(IMrbParser p, node c)
2284 : base(p, node_type.NODE_NEXT)
2285 {
2286 _retval = c;
2287 }
2288
2289 public node retval { get { return _retval; } }
2290
2291 public override Element to_xml(xml_code_cond cond)
2292 {
2293 var block = cond.CreateElement("block");
2294 block.SetAttribute("type", "controls_flow_statements");
2295
2296 var field = cond.CreateElement("field");
2297 field.SetAttribute("name", "FLOW");
2298 field.AppendChild(cond.CreateTextNode("CONTINUE"));
2299 block.AppendChild(field);
2300
2301 return block;
2302 }
2303
2304 protected override void to_rb(ruby_code_cond cond)
2305 {
2306 cond.increment_nest();
2307 if (_retval != null) {
2308 cond.write("next ");
2309 _retval.to_ruby(cond);
2310 cond.write_line();
2311 }
2312 else {
2313 cond.write_line("next");
2314 }
2315 cond.decrement_nest();
2316 }
2317
2318 public override string ToString()
2319 {
2320 return $"(:next . {retval})";
2321 }
2322 }
2323
2324 /* (:redo) */
2325 class redo_node : node
2326 {
2327 public redo_node(IMrbParser p)
2328 : base(p, node_type.NODE_REDO)
2329 {
2330 }
2331
2332 public override Element to_xml(xml_code_cond cond)
2333 {
2334 throw new NotImplementedException();
2335 }
2336
2337 protected override void to_rb(ruby_code_cond cond)
2338 {
2339 cond.write_line("redo");
2340 }
2341
2342 public override string ToString()
2343 {
2344 return $"(:redo)";
2345 }
2346 }
2347
2348 /* (:retry) */
2349 class retry_node : node
2350 {
2351 public retry_node(IMrbParser p)
2352 : base(p, node_type.NODE_RETRY)
2353 {
2354 }
2355
2356 public override Element to_xml(xml_code_cond cond)
2357 {
2358 throw new NotImplementedException();
2359 }
2360
2361 protected override void to_rb(ruby_code_cond cond)
2362 {
2363 cond.write_line("retry");
2364 }
2365
2366 public override string ToString()
2367 {
2368 return $"(:retry)";
2369 }
2370 }
2371
2372 /* (:dot2 a b) */
2373 class dot2_node : node
2374 {
2375 private node _a;
2376 private node _b;
2377
2378 public dot2_node(IMrbParser p, node a, node b)
2379 : base(p, node_type.NODE_DOT2)
2380 {
2381 _a = a;
2382 _b = b;
2383 }
2384
2385 public node a { get { return _a; } }
2386
2387 public node b { get { return _b; } }
2388
2389 public override Element to_xml(xml_code_cond cond)
2390 {
2391 throw new NotImplementedException();
2392 }
2393
2394 protected override void to_rb(ruby_code_cond cond)
2395 {
2396 _a.to_ruby(cond);
2397 cond.write("..");
2398 _b.to_ruby(cond);
2399 }
2400
2401 public override string ToString()
2402 {
2403 return $"(:dot2 {a} {b})";
2404 }
2405 }
2406
2407 /* (:dot3 a b) */
2408 class dot3_node : node
2409 {
2410 private node _a;
2411 private node _b;
2412
2413 public dot3_node(IMrbParser p, node a, node b)
2414 : base(p, node_type.NODE_DOT3)
2415 {
2416 _a = a;
2417 _b = b;
2418 }
2419
2420 public node a { get { return _a; } }
2421
2422 public node b { get { return _b; } }
2423
2424 public override Element to_xml(xml_code_cond cond)
2425 {
2426 throw new NotImplementedException();
2427 }
2428
2429 protected override void to_rb(ruby_code_cond cond)
2430 {
2431 _a.to_ruby(cond);
2432 cond.write("...");
2433 _b.to_ruby(cond);
2434 }
2435
2436 public override string ToString()
2437 {
2438 return $"(:dot3 {a} {b})";
2439 }
2440 }
2441
2442 /* (:colon2 b c) */
2443 class colon2_node : node
2444 {
2445 private node _b;
2446 private mrb_sym _c;
2447
2448 public colon2_node(IMrbParser p, node b, mrb_sym c)
2449 : base(p, node_type.NODE_COLON2)
2450 {
2451 _b = b;
2452 _c = c;
2453 }
2454
2455 public node b { get { return _b; } }
2456 public mrb_sym c { get { return _c; } }
2457
2458 public override Element to_xml(xml_code_cond cond)
2459 {
2460 // TODO:???
2461 var block = cond.CreateElement("class");
2462 block.SetAttribute("const", p.sym2name(((const_node)_b).name));
2463 block.SetAttribute("name", p.sym2name(_c));
2464
2465 return block;
2466 }
2467
2468 protected override void to_rb(ruby_code_cond cond)
2469 {
2470 _b.to_ruby(cond);
2471 cond.write("::" + p.sym2name(_c));
2472 }
2473
2474 public override string ToString()
2475 {
2476 return $"(:colon2 {b} {p.sym2name(c)})";
2477 }
2478 }
2479
2480 /* (:colon3 . c) */
2481 class colon3_node : node
2482 {
2483 private mrb_sym _c;
2484
2485 public colon3_node(IMrbParser p, mrb_sym c)
2486 : base(p, node_type.NODE_COLON3)
2487 {
2488 _c = c;
2489 }
2490
2491 public mrb_sym c { get { return _c; } }
2492
2493 public override Element to_xml(xml_code_cond cond)
2494 {
2495 throw new NotImplementedException();
2496 }
2497
2498 protected override void to_rb(ruby_code_cond cond)
2499 {
2500 cond.write("::" + p.sym2name(_c));
2501 }
2502
2503 public override string ToString()
2504 {
2505 return $"(:colon3 . {p.sym2name(c)})";
2506 }
2507 }
2508
2509 /* (:and a b) */
2510 class and_node : node
2511 {
2512 private node _a;
2513 private node _b;
2514
2515 public and_node(IMrbParser p, node a, node b)
2516 : base(p, node_type.NODE_AND)
2517 {
2518 _a = a;
2519 _b = b;
2520 }
2521
2522 public node a { get { return _a; } }
2523
2524 public node b { get { return _b; } }
2525
2526 public override Element to_xml(xml_code_cond cond)
2527 {
2528 var block = cond.CreateElement("block");
2529 block.SetAttribute("type", "logic_operation");
2530
2531 var field = cond.CreateElement("field");
2532 field.SetAttribute("name", "OP");
2533 field.AppendChild(cond.CreateTextNode("AND"));
2534 block.AppendChild(field);
2535
2536 var value = cond.CreateElement("value");
2537 value.SetAttribute("name", "A");
2538 value.AppendChild(_a.to_xml(cond));
2539 block.AppendChild(value);
2540
2541 value = cond.CreateElement("value");
2542 value.SetAttribute("name", "B");
2543 value.AppendChild(_b.to_xml(cond));
2544 block.AppendChild(value);
2545
2546 return block;
2547 }
2548
2549 protected override void to_rb(ruby_code_cond cond)
2550 {
2551 _a.to_ruby(cond);
2552 cond.write(" && ");
2553 _b.to_ruby(cond);
2554 }
2555
2556 public override string ToString()
2557 {
2558 return $"(:and {a} {b})";
2559 }
2560 }
2561
2562 /* (:or a b) */
2563 class or_node : node
2564 {
2565 private node _a;
2566 private node _b;
2567
2568 public or_node(IMrbParser p, node a, node b)
2569 : base(p, node_type.NODE_OR)
2570 {
2571 _a = a;
2572 _b = b;
2573 }
2574
2575 public node a { get { return _a; } }
2576 public node b { get { return _b; } }
2577
2578 public override Element to_xml(xml_code_cond cond)
2579 {
2580 var block = cond.CreateElement("block");
2581 block.SetAttribute("type", "logic_operation");
2582
2583 var field = cond.CreateElement("field");
2584 field.SetAttribute("name", "OP");
2585 field.AppendChild(cond.CreateTextNode("OR"));
2586 block.AppendChild(field);
2587
2588 var value = cond.CreateElement("value");
2589 value.SetAttribute("name", "A");
2590 value.AppendChild(_a.to_xml(cond));
2591 block.AppendChild(value);
2592
2593 value = cond.CreateElement("value");
2594 value.SetAttribute("name", "B");
2595 value.AppendChild(_b.to_xml(cond));
2596 block.AppendChild(value);
2597
2598 return block;
2599 }
2600
2601 protected override void to_rb(ruby_code_cond cond)
2602 {
2603 _a.to_ruby(cond);
2604 cond.write(" || ");
2605 _b.to_ruby(cond);
2606 }
2607
2608 public override string ToString()
2609 {
2610 return $"(:or {a} {b})";
2611 }
2612 }
2613
2614 /* (:array a...) */
2615 class array_node : node
2616 {
2617 private node[] _array = new node[0];
2618 private bool _item_per_line;
2619
2620 public array_node(IMrbParser p, node a)
2621 : base(p, node_type.NODE_ARRAY)
2622 {
2623 dump_recur(_array, a);
2624 }
2625
2626 public array_node(IMrbParser p, node[] a, bool item_per_line = false)
2627 : base(p, node_type.NODE_ARRAY)
2628 {
2629 _array = (node[])_array.Concat(a);
2630 _item_per_line = item_per_line;
2631 }
2632
2633
2634 public node[] array { get { return _array; } }
2635
2636 public override Element to_xml(xml_code_cond cond)
2637 {
2638 var block = cond.CreateElement("block");
2639 block.SetAttribute("type", "lists_create_with");
2640
2641 var mutation = cond.CreateElement("mutation");
2642 mutation.SetAttribute("items", _array.Length.ToString());
2643 block.AppendChild(mutation);
2644
2645 int i = 0;
2646 foreach (var item in _array) {
2647 var value = cond.CreateElement("value");
2648 value.SetAttribute("name", $"ADD{i}");
2649 value.AppendChild(_array[i].to_xml(cond));
2650 block.AppendChild(value);
2651 i++;
2652 }
2653
2654 return block;
2655 }
2656
2657 protected override void to_rb(ruby_code_cond cond)
2658 {
2659 cond.increment_nest();
2660 cond.write("[");
2661 if (_item_per_line) {
2662 cond.separate_line();
2663 cond.increment_indent();
2664 }
2665 int i = _array.Length;
2666 foreach (var item in _array) {
2667 item.to_ruby(cond);
2668 i--;
2669 if (i > 0) {
2670 if (_item_per_line) {
2671 cond.write(",");
2672 cond.separate_line();
2673 }
2674 else
2675 cond.write(", ");
2676 }
2677 else if (_item_per_line) {
2678 cond.decrement_indent();
2679 cond.separate_line();
2680 }
2681 }
2682 cond.write("]");
2683 cond.decrement_nest();
2684 }
2685
2686 public override string ToString()
2687 {
2688 var str = $"(:array ";
2689 foreach (var n in array) {
2690 str += $"{n} ";
2691 }
2692 return str + ")";
2693 }
2694 }
2695
2696 /* (:splat . a) */
2697 class splat_node : node
2698 {
2699 private node _a;
2700
2701 public splat_node(IMrbParser p, node a)
2702 : base(p, node_type.NODE_SPLAT)
2703 {
2704 _a = a;
2705 }
2706
2707 public node a { get { return _a; } }
2708
2709 public override Element to_xml(xml_code_cond cond)
2710 {
2711 throw new NotImplementedException();
2712 }
2713
2714 protected override void to_rb(ruby_code_cond cond)
2715 {
2716 cond.write("*");
2717 _a.to_ruby(cond);
2718 }
2719
2720 public override string ToString()
2721 {
2722 return $"(:splat . {a})";
2723 }
2724 }
2725
2726 /* (:hash (k . v) (k . v)...) */
2727 class hash_node : node
2728 {
2729 public class kv_t
2730 {
2731 public node key;
2732 public node value;
2733
2734 public kv_t(node key, node value)
2735 {
2736 this.key = key;
2737 this.value = value;
2738 }
2739
2740 public override string ToString()
2741 {
2742 return $"({key} . {value})";
2743 }
2744 }
2745 kv_t[] _kvs = new kv_t[0];
2746
2747 public hash_node(IMrbParser p, node a)
2748 : base(p, node_type.NODE_HASH)
2749 {
2750 while (a != null) {
2751 var kv = new kv_t((node)((node)a.car).car, (node)((node)a.car).cdr);
2752 _kvs.Push(kv);
2753 a = (node)a.cdr;
2754 }
2755 }
2756
2757 public hash_node(IMrbParser p, kv_t[] items)
2758 : base(p, node_type.NODE_HASH)
2759 {
2760 _kvs = (kv_t[])_kvs.Concat(items);
2761 }
2762
2763 public kv_t[] kvs { get { return _kvs; } }
2764
2765 public override Element to_xml(xml_code_cond cond)
2766 {
2767 throw new NotImplementedException();
2768 }
2769
2770 protected override void to_rb(ruby_code_cond cond)
2771 {
2772 if (cond.nest != 0)
2773 cond.write("{");
2774 else
2775 cond.write_line("{");
2776 int i = _kvs.Length;
2777 foreach (var kv in _kvs) {
2778 kv.key.to_ruby(cond);
2779 cond.write(" => ");
2780 kv.value.to_ruby(cond);
2781 i--; if (i > 0) cond.write(", ");
2782 }
2783 if (cond.nest != 0)
2784 cond.write("}");
2785 else
2786 cond.write_line("}");
2787 }
2788
2789 public override string ToString()
2790 {
2791 var str = $"(:hash ";
2792 foreach (var n in kvs) {
2793 str += $"{n} ";
2794 }
2795 return str + ")";
2796 }
2797 }
2798
2799 /* (:sym . a) */
2800 class sym_node : node
2801 {
2802 private mrb_sym _name;
2803
2804 public sym_node(IMrbParser p, mrb_sym sym)
2805 : base(p, node_type.NODE_SYM)
2806 {
2807 _name = sym;
2808 }
2809
2810 public mrb_sym name { get { return _name; } }
2811
2812 public override Element to_xml(xml_code_cond cond)
2813 {
2814 var block = cond.CreateElement("block");
2815 block.SetAttribute("type", "variables_get");
2816
2817 var field = cond.CreateElement("field");
2818 field.SetAttribute("name", "VAR");
2819 field.AppendChild(cond.CreateTextNode(":" + p.sym2name(_name)));
2820 block.AppendChild(field);
2821
2822 return block;
2823 }
2824
2825 protected override void to_rb(ruby_code_cond cond)
2826 {
2827 cond.write(":" + p.sym2name(_name));
2828 }
2829
2830 public override string ToString()
2831 {
2832 return $"(:sym . {p.sym2name(name)})";
2833 }
2834 }
2835
2836 /* (:lvar . a) */
2837 class lvar_node : node
2838 {
2839 private mrb_sym _name;
2840
2841 public lvar_node(IMrbParser p, mrb_sym sym)
2842 : base(p, node_type.NODE_LVAR)
2843 {
2844 _name = sym;
2845 }
2846
2847 public mrb_sym name { get { return _name; } }
2848
2849 public override Element to_xml(xml_code_cond cond)
2850 {
2851 var block = cond.CreateElement("block");
2852 block.SetAttribute("type", "variables_get");
2853
2854 var field = cond.CreateElement("field");
2855 field.SetAttribute("name", "VAR");
2856 field.AppendChild(cond.CreateTextNode(p.sym2name(_name)));
2857 block.AppendChild(field);
2858
2859 return block;
2860 }
2861
2862 protected override void to_rb(ruby_code_cond cond)
2863 {
2864 cond.write(p.sym2name(_name));
2865 }
2866
2867 public override string ToString()
2868 {
2869 return $"(:lvar . {p.sym2name(name)})";
2870 }
2871 }
2872
2873 /* (:gvar . a) */
2874 class gvar_node : node
2875 {
2876 private mrb_sym _name;
2877
2878 public gvar_node(IMrbParser p, mrb_sym sym)
2879 : base(p, node_type.NODE_GVAR)
2880 {
2881 _name = sym;
2882 }
2883
2884 public mrb_sym name { get { return _name; } }
2885
2886 public override Element to_xml(xml_code_cond cond)
2887 {
2888 var block = cond.CreateElement("block");
2889 block.SetAttribute("type", "variables_get");
2890
2891 var field = cond.CreateElement("field");
2892 field.SetAttribute("name", "VAR");
2893 field.AppendChild(cond.CreateTextNode(p.sym2name(_name)));
2894 block.AppendChild(field);
2895
2896 return block;
2897 }
2898
2899 protected override void to_rb(ruby_code_cond cond)
2900 {
2901 cond.write(p.sym2name(_name));
2902 }
2903
2904 public override string ToString()
2905 {
2906 return $"(:gvar . {p.sym2name(name)})";
2907 }
2908 }
2909
2910 /* (:ivar . a) */
2911 class ivar_node : node
2912 {
2913 private mrb_sym _name;
2914
2915 public ivar_node(IMrbParser p, mrb_sym sym)
2916 : base(p, node_type.NODE_IVAR)
2917 {
2918 _name = sym;
2919 }
2920
2921 public mrb_sym name { get { return _name; } }
2922
2923 public override Element to_xml(xml_code_cond cond)
2924 {
2925 var block = cond.CreateElement("block");
2926 block.SetAttribute("type", "variables_get");
2927
2928 var field = cond.CreateElement("field");
2929 field.SetAttribute("name", "VAR");
2930 field.AppendChild(cond.CreateTextNode(p.sym2name(_name)));
2931 block.AppendChild(field);
2932
2933 return block;
2934 }
2935
2936 protected override void to_rb(ruby_code_cond cond)
2937 {
2938 cond.write(p.sym2name(_name));
2939 }
2940
2941 public override string ToString()
2942 {
2943 return $"(:ivar . {p.sym2name(name)})";
2944 }
2945 }
2946
2947 /* (:cvar . a) */
2948 class cvar_node : node
2949 {
2950 private mrb_sym _name;
2951
2952 public cvar_node(IMrbParser p, mrb_sym sym)
2953 : base(p, node_type.NODE_CVAR)
2954 {
2955 _name = sym;
2956 }
2957
2958 public mrb_sym name { get { return _name; } }
2959
2960 public override Element to_xml(xml_code_cond cond)
2961 {
2962 var block = cond.CreateElement("block");
2963 block.SetAttribute("type", "variables_get");
2964
2965 var field = cond.CreateElement("field");
2966 field.SetAttribute("name", "VAR");
2967 field.AppendChild(cond.CreateTextNode(p.sym2name(_name)));
2968 block.AppendChild(field);
2969
2970 return block;
2971 }
2972
2973 protected override void to_rb(ruby_code_cond cond)
2974 {
2975 cond.write(p.sym2name(_name));
2976 }
2977
2978 public override string ToString()
2979 {
2980 return $"(:cvar . {p.sym2name(name)})";
2981 }
2982 }
2983
2984 /* (:const . a) */
2985 class const_node : node
2986 {
2987 private mrb_sym _name;
2988
2989 public const_node(IMrbParser p, mrb_sym sym)
2990 : base(p, node_type.NODE_CONST)
2991 {
2992 _name = sym;
2993 }
2994
2995 public mrb_sym name { get { return _name; } }
2996
2997 public override Element to_xml(xml_code_cond cond)
2998 {
2999 var block = cond.CreateElement("block");
3000 block.SetAttribute("type", "variables_get");
3001
3002 var field = cond.CreateElement("field");
3003 field.SetAttribute("name", "VAR");
3004 field.AppendChild(cond.CreateTextNode(p.sym2name(_name)));
3005 block.AppendChild(field);
3006
3007 return block;
3008 }
3009
3010 protected override void to_rb(ruby_code_cond cond)
3011 {
3012 cond.write(p.sym2name(_name));
3013 }
3014
3015 public override string ToString()
3016 {
3017 return $"(:const . {p.sym2name(name)})";
3018 }
3019 }
3020
3021 /* (:undef a...) */
3022 class undef_node : node
3023 {
3024 private mrb_sym[] _syms = new mrb_sym[0];
3025
3026 public undef_node(IMrbParser p, mrb_sym sym)
3027 : base(p, node_type.NODE_UNDEF)
3028 {
3029 _syms.Push(sym);
3030 }
3031
3032 public mrb_sym[] syms { get { return _syms; } }
3033
3034 public override void append(node b)
3035 {
3036 _syms.Push((mrb_sym)b.car);
3037 }
3038
3039 public override Element to_xml(xml_code_cond cond)
3040 {
3041 throw new NotImplementedException();
3042 }
3043
3044 protected override void to_rb(ruby_code_cond cond)
3045 {
3046 cond.write("undef");
3047 int i = _syms.Length;
3048 if (i > 0)
3049 cond.write(" ");
3050 foreach (var sym in _syms) {
3051 cond.write(p.sym2name(sym));
3052 i--;
3053 if (i > 0)
3054 cond.write(", ");
3055 }
3056 }
3057
3058 public override string ToString()
3059 {
3060 var str = "(:undef ";
3061 foreach (var n in syms) {
3062 str += $"{p.sym2name(n)}, ";
3063 }
3064 return str + ")";
3065 }
3066 }
3067
3068 /* (:class class super body) */
3069 class class_node : node
3070 {
3071 private string _prefix;
3072 private node _type;
3073 private mrb_sym _name;
3074 private node _super;
3075 private mrb_sym _arg;
3076 private node _body;
3077
3078 public class_node(IMrbParser p, node c, node s, node b)
3079 : base(p, node_type.NODE_CLASS)
3080 {
3081 if (c.car is int) {
3082 var type = (int)c.car;
3083 if (type == 0) {
3084 _prefix = ""/*":"*/;
3085 _name = (mrb_sym)c.cdr;
3086 }
3087 else if (type == 1) {
3088 _prefix = "::";
3089 _name = (mrb_sym)c.cdr;
3090 }
3091 }
3092 else {
3093 _prefix = "::";
3094 _type = (node)c.car;
3095 _name = (mrb_sym)c.cdr;
3096 }
3097 _super = s;
3098 var a = p.locals_node();
3099 _arg = (a.Length == 0) ? 0 : a[0];
3100 _body = b;
3101 }
3102
3103 public class_node(IMrbParser p, mrb_sym name, node s, node b)
3104 : base(p, node_type.NODE_CLASS)
3105 {
3106 _prefix = "";
3107 _name = name;
3108 _super = s;
3109 _body = b;
3110 }
3111
3112 public string prefix { get { return _prefix; } }
3113 public mrb_sym name { get { return _name; } }
3114 public node super { get { return _super; } }
3115 public node body { get { return _body; } }
3116
3117 public override Element to_xml(xml_code_cond cond)
3118 {
3119 // TODO:クラス?
3120 var block = cond.CreateElement("class");
3121 block.SetAttribute("name", p.sym2name(_name));
3122
3123 if (_super != null) {
3124 var field = cond.CreateElement("field");
3125 field.SetAttribute("name", "SUPER");
3126 field.AppendChild(_super.to_xml(cond));
3127 block.AppendChild(field);
3128 }
3129
3130 var statement = cond.CreateElement("statement");
3131 statement.SetAttribute("name", "BODY");
3132 statement.AppendChild(_body.to_xml(cond));
3133 block.AppendChild(statement);
3134
3135 return block;
3136 }
3137
3138 protected override void to_rb(ruby_code_cond cond)
3139 {
3140 cond.write("class ");
3141 if (_type != null)
3142 _type.to_ruby(cond);
3143 if (_prefix != null)
3144 cond.write(_prefix);
3145 cond.write(p.sym2name(_name) + " ");
3146 if (_super != null) {
3147 cond.write("< ");
3148 if (_super != null)
3149 _super.to_ruby(cond);
3150 }
3151 cond.increment_indent();
3152 _body.to_ruby(cond);
3153 cond.decrement_indent();
3154 cond.write_line("end");
3155 }
3156
3157 public override string ToString()
3158 {
3159 return $"(:class {prefix}{p.sym2name(name)} {super} {body})";
3160 }
3161 }
3162
3163 /* (:sclass obj body) */
3164 class sclass_node : node
3165 {
3166 private node _obj;
3167 private mrb_sym[] _super;
3168 private node _body;
3169
3170 public sclass_node(IMrbParser p, node o, node b)
3171 : base(p, node_type.NODE_SCLASS)
3172 {
3173 _obj = o;
3174 _super = p.locals_node();
3175 _body = b;
3176 }
3177
3178 public node obj { get { return _obj; } }
3179 public node body { get { return _body; } }
3180
3181 public override Element to_xml(xml_code_cond cond)
3182 {
3183 throw new NotImplementedException();
3184 }
3185
3186 protected override void to_rb(ruby_code_cond cond)
3187 {
3188 cond.write("class << ");
3189 _obj.to_ruby(cond);
3190 /*if (_super != null) {
3191 cond.write(">");
3192 _super.to_ruby(cond);
3193 }*/
3194 cond.increment_indent();
3195 _body.to_ruby(cond);
3196 cond.decrement_indent();
3197 cond.write_line("end");
3198 }
3199
3200 public override string ToString()
3201 {
3202 return $"(:sclass {obj} {body})";
3203 }
3204 }
3205
3206 /* (:module module body) */
3207 class module_node : node
3208 {
3209 private string _prefix;
3210 private mrb_sym _name;
3211 private node _type;
3212 private mrb_sym[] _super;
3213 private node _body;
3214
3215 public module_node(IMrbParser p, node m, node b)
3216 : base(p, node_type.NODE_MODULE)
3217 {
3218 if (m.car is int) {
3219 if ((int)m.car == 0) {
3220 _prefix = ""/*":"*/;
3221 _name = (mrb_sym)m.cdr;
3222 }
3223 else if ((int)m.car == 1) {
3224 _prefix = "::";
3225 _name = (mrb_sym)m.cdr;
3226 }
3227 }
3228 else {
3229 _prefix = "::";
3230 _type = (node)m.car;
3231 _name = (mrb_sym)m.cdr;
3232 }
3233 _super = p.locals_node();
3234 _body = b;
3235 }
3236
3237 public string prefix { get { return _prefix; } }
3238 public mrb_sym name { get { return _name; } }
3239 public object type { get { return _type; } }
3240 public node body { get { return _body; } }
3241
3242 public override Element to_xml(xml_code_cond cond)
3243 {
3244 throw new NotImplementedException();
3245 }
3246
3247 protected override void to_rb(ruby_code_cond cond)
3248 {
3249 cond.write("module " + p.sym2name(_name) + " ");
3250 if (_super != null) {
3251 if (_type != null)
3252 _type.to_ruby(cond);
3253 foreach (var s in _super) {
3254 if (_prefix != null)
3255 cond.write(_prefix + "::");
3256 cond.write(p.sym2name(s));
3257 }
3258 }
3259 cond.increment_indent();
3260 _body.to_ruby(cond);
3261 cond.decrement_indent();
3262 cond.write_line("end");
3263 }
3264
3265 public override string ToString()
3266 {
3267 return $"(:module {prefix}{p.sym2name(name)} {body})";
3268 }
3269 }
3270
3271 public class args_t
3272 {
3273 IMrbParser p;
3274 public mrb_sym name;
3275 public node arg;
3276
3277 public args_t(IMrbParser p)
3278 {
3279 this.p = p;
3280 }
3281
3282 public override string ToString()
3283 {
3284 return $"({p.sym2name(name)} {arg})";
3285 }
3286
3287 internal void to_ruby(ruby_code_cond cond)
3288 {
3289 cond.write(p.sym2name(name));
3290 if (arg != null) {
3291 cond.write(" = ");
3292 arg.to_ruby(cond);
3293 }
3294 }
3295 }
3296
3297 /* (:def m lv (arg . body)) */
3298 class def_node : node
3299 {
3300 private mrb_sym _name;
3301 private mrb_sym[] _local_variables = new mrb_sym[0];
3302 private arg_node[] _mandatory_args = new arg_node[0];
3303 private args_t[] _optional_args = new args_t[0];
3304 private mrb_sym _rest;
3305 private arg_node[] _post_mandatory_args = new arg_node[0];
3306 private mrb_sym _blk;
3307 private node _body;
3308
3309 public def_node(IMrbParser p, mrb_sym m, node a, node b)
3310 : base(p, node_type.NODE_DEF)
3311 {
3312 _name = m;
3313 _local_variables = (mrb_sym[])_local_variables.Concat(p.locals_node());
3314 if (a != null) {
3315 node n = a;
3316
3317 if (n.car != null) {
3318 dump_recur(_mandatory_args, (node)n.car);
3319 }
3320 n = (node)n.cdr;
3321 if (n.car != null) {
3322 var n2 = (node)n.car;
3323
3324 while (n2 != null) {
3325 var arg = new args_t(p);
3326 arg.name = (mrb_sym)((node)n2.car).car;
3327 arg.arg = (node)((node)n2.car).cdr;
3328 _optional_args.Push(arg);
3329 n2 = (node)n2.cdr;
3330 }
3331 }
3332 n = (node)n.cdr;
3333 if (n.car != null) {
3334 _rest = (mrb_sym)n.car;
3335 }
3336 n = (node)n.cdr;
3337 if (n.car != null) {
3338 dump_recur(_post_mandatory_args, (node)n.car);
3339 }
3340 if (n.cdr != null) {
3341 _blk = (mrb_sym)n.cdr;
3342 }
3343 }
3344 _body = b;
3345 if (_body is ensure_node) {
3346 ((ensure_node)_body).def = true;
3347 }
3348 }
3349
3350 public def_node(IMrbParser p, mrb_sym m, arg_node[] a, node b)
3351 : base(p, node_type.NODE_DEF)
3352 {
3353 _name = m;
3354 _mandatory_args = (arg_node[])_mandatory_args.Concat(a);
3355 _body = b;
3356 }
3357
3358 public mrb_sym name { get { return _name; } }
3359 public mrb_sym[] local_variables { get { return _local_variables; } }
3360 public arg_node[] mandatory_args { get { return _mandatory_args; } }
3361 internal args_t[] optional_args { get { return _optional_args; } }
3362 public mrb_sym rest { get { return _rest; } }
3363 public arg_node[] post_mandatory_args { get { return _post_mandatory_args; } }
3364 public mrb_sym blk { get { return _blk; } }
3365 public node body { get { return _body; } }
3366
3367 public override Element to_xml(xml_code_cond cond)
3368 {
3369 var block = cond.CreateElement("block");
3370 block.SetAttribute("type", "procedures_defreturn");
3371
3372 var field = cond.CreateElement("field");
3373 field.SetAttribute("name", "NAME");
3374 field.AppendChild(cond.CreateTextNode(p.sym2name(_name)));
3375 block.AppendChild(field);
3376
3377 Element bxml;
3378 if (_body != null && (bxml = _body.to_xml(cond)) != null) {
3379 var statement = cond.CreateElement("statement");
3380 statement.SetAttribute("name", "STACK");
3381 statement.AppendChild(bxml);
3382 block.AppendChild(statement);
3383 }
3384
3385 return block;
3386 }
3387
3388 protected override void to_rb(ruby_code_cond cond)
3389 {
3390 cond.increment_nest();
3391 cond.write("def " + p.sym2name(_name) + "(");
3392 int i = _mandatory_args.Length + _optional_args.Length
3393 + (_rest != 0 ? 1 : 0) + _post_mandatory_args.Length
3394 + (_blk != 0 ? 1 : 0);
3395 if (i > 0) {
3396 foreach (var a in _mandatory_args) {
3397 a.to_ruby(cond);
3398 i--; if (i > 0) cond.write(", ");
3399 }
3400 foreach (var a in _optional_args) {
3401 a.to_ruby(cond);
3402 i--; if (i > 0) cond.write(", ");
3403 }
3404 if (_rest != 0) {
3405 cond.write("*");
3406 if (_rest != (mrb_sym)(-1))
3407 cond.write(p.sym2name(_rest));
3408 i--; if (i > 0) cond.write(", ");
3409 foreach (var a in _post_mandatory_args) {
3410 a.to_ruby(cond);
3411 i--; if (i > 0) cond.write(", ");
3412 }
3413 }
3414 if (_blk != 0) {
3415 cond.write("&" + p.sym2name(_blk));
3416 }
3417 }
3418 cond.write(")");
3419 cond.decrement_nest();
3420 cond.increment_indent();
3421 _body.to_ruby(cond);
3422 cond.decrement_indent();
3423 cond.write_line("end");
3424 }
3425
3426 public override string ToString()
3427 {
3428 var str = $"(:def {p.sym2name(name)} ";
3429 foreach (var n in local_variables) {
3430 str += $"{p.sym2name(n)}, ";
3431 }
3432 str += $" (";
3433 foreach (var n in mandatory_args) {
3434 str += $"{n}, ";
3435 }
3436 foreach (var n in optional_args) {
3437 str += $"{n}, ";
3438 }
3439 str += $"{p.sym2name(rest)}, ";
3440 foreach (var n in post_mandatory_args) {
3441 str += $"{n}, ";
3442 }
3443 str += $"{p.sym2name(blk)}, ";
3444 return str + $" . {body}))";
3445 }
3446 }
3447
3448 /* (:sdef obj m lv (arg . body)) */
3449 class sdef_node : node
3450 {
3451 private node _obj;
3452 private mrb_sym _name;
3453 private mrb_sym[] _lv;
3454 private arg_node[] _mandatory_args = new arg_node[0];
3455 private args_t[] _optional_args = new args_t[0];
3456 private mrb_sym _rest;
3457 private arg_node[] _post_mandatory_args = new arg_node[0];
3458 private mrb_sym _blk;
3459 private node _body;
3460
3461 public sdef_node(IMrbParser p, node o, mrb_sym m, node a, node b)
3462 : base(p, node_type.NODE_SDEF)
3463 {
3464 _obj = o;
3465 _name = m;
3466 _lv = p.locals_node();
3467 if (a != null) {
3468 node n = a;
3469
3470 if (n.car != null) {
3471 dump_recur(_mandatory_args, (node)n.car);
3472 }
3473 n = (node)n.cdr;
3474 if (n.car != null) {
3475 var n2 = (node)n.car;
3476
3477 while (n2 != null) {
3478 var arg = new args_t(p);
3479 arg.name = (mrb_sym)((node)n2.car).car;
3480 arg.arg = (node)((node)n2.car).cdr;
3481 _optional_args.Push(arg);
3482 n2 = (node)n2.cdr;
3483 }
3484 }
3485 n = (node)n.cdr;
3486 if (n.car != null) {
3487 _rest = (mrb_sym)n.car;
3488 }
3489 n = (node)n.cdr;
3490 if (n.car != null) {
3491 dump_recur(_post_mandatory_args, (node)n.car);
3492 }
3493 _blk = (mrb_sym)n.cdr;
3494 }
3495 _body = b;
3496 }
3497
3498 public node obj { get { return _obj; } }
3499 public mrb_sym name { get { return _name; } }
3500 public arg_node[] mandatory_args { get { return _mandatory_args; } }
3501 internal args_t[] optional_args { get { return _optional_args; } }
3502 public mrb_sym rest { get { return _rest; } }
3503 public arg_node[] post_mandatory_args { get { return _post_mandatory_args; } }
3504 public mrb_sym blk { get { return _blk; } }
3505 public node body { get { return _body; } }
3506
3507 public override Element to_xml(xml_code_cond cond)
3508 {
3509 throw new NotImplementedException();
3510 }
3511
3512 protected override void to_rb(ruby_code_cond cond)
3513 {
3514 cond.increment_nest();
3515 cond.write("def self." + p.sym2name(_name) + "(");
3516 int i = _mandatory_args.Length + _optional_args.Length
3517 + (_rest != 0 ? 1 : 0) + _post_mandatory_args.Length
3518 + (_blk != 0 ? 1 : 0);
3519 if (i > 0) {
3520 foreach (var a in _mandatory_args) {
3521 a.to_ruby(cond);
3522 i--; if (i > 0) cond.write(", ");
3523 }
3524 foreach (var a in _optional_args) {
3525 a.to_ruby(cond);
3526 i--; if (i > 0) cond.write(", ");
3527 }
3528 if (_rest != 0) {
3529 if (_rest == (mrb_sym)(-1))
3530 cond.write("*");
3531 else
3532 cond.write(p.sym2name(_rest));
3533 i--; if (i > 0) cond.write(", ");
3534 foreach (var a in _post_mandatory_args) {
3535 a.to_ruby(cond);
3536 i--; if (i > 0) cond.write(", ");
3537 }
3538 }
3539 if (_blk != 0) {
3540 cond.write("&" + p.sym2name(_blk));
3541 }
3542 }
3543 cond.write(")");
3544 cond.decrement_nest();
3545 cond.increment_indent();
3546 _body.to_ruby(cond);
3547 cond.decrement_indent();
3548 cond.write_line("end");
3549 }
3550
3551 public override string ToString()
3552 {
3553 var str = $"(:sdef {obj} {p.sym2name(name)} (";
3554 foreach (var n in mandatory_args) {
3555 str += $"{n}, ";
3556 }
3557 foreach (var n in optional_args) {
3558 str += $"{n}, ";
3559 }
3560 str += $"{p.sym2name(rest)}, ";
3561 foreach (var n in post_mandatory_args) {
3562 str += $"{n}, ";
3563 }
3564 str += $"{p.sym2name(blk)}, ";
3565 return str + $" . {body}))";
3566 }
3567 }
3568
3569 /* (:arg . sym) */
3570 class arg_node : node
3571 {
3572 private mrb_sym _name;
3573
3574 public arg_node(IMrbParser p, mrb_sym sym)
3575 : base(p, node_type.NODE_ARG)
3576 {
3577 _name = sym;
3578 }
3579
3580 public mrb_sym name { get { return _name; } }
3581
3582 public override Element to_xml(xml_code_cond cond)
3583 {
3584 throw new NotImplementedException();
3585 }
3586
3587 protected override void to_rb(ruby_code_cond cond)
3588 {
3589 cond.write(p.sym2name(_name));
3590 }
3591
3592 public override string ToString()
3593 {
3594 return $"(:arg . {p.sym2name(name)})";
3595 }
3596 }
3597
3598 /* (:block_arg . a) */
3599 class block_arg_node : node
3600 {
3601 private node _a;
3602
3603 public block_arg_node(IMrbParser p, node a)
3604 : base(p, node_type.NODE_BLOCK_ARG)
3605 {
3606 _a = a;
3607 }
3608
3609 public node a { get { return _a; } }
3610
3611 public override Element to_xml(xml_code_cond cond)
3612 {
3613 throw new NotImplementedException();
3614 }
3615
3616 protected override void to_rb(ruby_code_cond cond)
3617 {
3618 cond.write("&");
3619 _a.to_ruby(cond);
3620 }
3621
3622 public override string ToString()
3623 {
3624 return $"(:block_arg . {a})";
3625 }
3626 }
3627
3628 /* (:block arg body) */
3629 class block_node : node
3630 {
3631 private mrb_sym[] _local_variables = new mrb_sym[0];
3632 private node[] _mandatory_args = new node[0];
3633 private args_t[] _optional_args = new args_t[0];
3634 private mrb_sym _rest;
3635 private node[] _post_mandatory_args = new node[0];
3636 private mrb_sym _blk;
3637 private node _body;
3638 private bool _brace;
3639
3640 public block_node(IMrbParser p, node args, node body, bool brace)
3641 : base(p, node_type.NODE_BLOCK)
3642 {
3643 _local_variables = (mrb_sym[])_local_variables.Concat(p.locals_node());
3644 if (args != null) {
3645 node n = args;
3646
3647 if (n.car != null) {
3648 dump_recur(_mandatory_args, (node)n.car);
3649 }
3650 n = (node)n.cdr;
3651 if (n.car != null) {
3652 var n2 = (node)n.car;
3653
3654 while (n2 != null) {
3655 var arg = new args_t(p);
3656 arg.name = (mrb_sym)((node)n2.car).car;
3657 arg.arg = (node)((node)n2.car).cdr;
3658 _optional_args.Push(arg);
3659 n2 = (node)n2.cdr;
3660 }
3661 }
3662 n = (node)n.cdr;
3663 if (n.car != null) {
3664 _rest = (mrb_sym)n.car;
3665 }
3666 n = (node)n.cdr;
3667 if (n.car != null) {
3668 dump_recur(_post_mandatory_args, (node)n.car);
3669 }
3670 if (n.cdr != null) {
3671 _blk = (mrb_sym)n.cdr;
3672 }
3673 }
3674 _body = body;
3675 if (_body is ensure_node) {
3676 ((ensure_node)_body).def = true;
3677 }
3678 _brace = brace;
3679 }
3680
3681 public block_node(IMrbParser p, node[] args, node body, bool brace)
3682 : base(p, node_type.NODE_BLOCK)
3683 {
3684 _mandatory_args = (node[])_mandatory_args.Concat(args);
3685 _body = body;
3686 if (_body is ensure_node) {
3687 ((ensure_node)_body).def = true;
3688 }
3689 _brace = brace;
3690 }
3691
3692 public mrb_sym[] local_variables { get { return _local_variables; } }
3693 public node[] mandatory_args { get { return _mandatory_args; } }
3694 internal args_t[] optional_args { get { return _optional_args; } }
3695 public mrb_sym rest { get { return _rest; } }
3696 public node[] post_mandatory_args { get { return _post_mandatory_args; } }
3697 public mrb_sym blk { get { return _blk; } }
3698 public node body { get { return _body; } }
3699
3700 public override Element to_xml(xml_code_cond cond)
3701 {
3702 throw new NotImplementedException();
3703 }
3704
3705 protected override void to_rb(ruby_code_cond cond)
3706 {
3707 string beg, end;
3708 if (_brace) {
3709 beg = " {";
3710 end = "}";
3711 }
3712 else {
3713 beg = " do";
3714 end = "end";
3715 }
3716
3717 cond.increment_nest();
3718 cond.write(beg);
3719 int i = _mandatory_args.Length + _optional_args.Length
3720 + (_rest != 0 ? 1 : 0) + _post_mandatory_args.Length
3721 + (_blk != 0 ? 1 : 0);
3722 if (i > 0) {
3723 cond.write(" |");
3724 foreach (var a in _mandatory_args) {
3725 a.to_ruby(cond);
3726 i--; if (i > 0) cond.write(", ");
3727 }
3728 foreach (var a in _optional_args) {
3729 a.to_ruby(cond);
3730 i--; if (i > 0) cond.write(", ");
3731 }
3732 if (_rest != 0) {
3733 cond.write("*");
3734 if (_rest != (mrb_sym)(-1))
3735 cond.write(p.sym2name(_rest));
3736 i--; if (i > 0) cond.write(", ");
3737 foreach (var a in _post_mandatory_args) {
3738 a.to_ruby(cond);
3739 i--; if (i > 0) cond.write(", ");
3740 }
3741 }
3742 if (_blk != 0) {
3743 cond.write("&" + p.sym2name(_blk));
3744 }
3745 cond.write("|");
3746 }
3747 cond.decrement_nest();
3748 cond.increment_indent();
3749 _body.to_ruby(cond);
3750 cond.decrement_indent();
3751 cond.write_line(end);
3752 }
3753
3754 public override string ToString()
3755 {
3756 var str = $"(:block ";
3757 foreach (var n in mandatory_args) {
3758 str += $"{n}, ";
3759 }
3760 foreach (var n in optional_args) {
3761 str += $"{n}, ";
3762 }
3763 return str + $" . {body}))";
3764 }
3765 }
3766
3767 /* (:lambda arg body) */
3768 class lambda_node : node
3769 {
3770 private mrb_sym[] _local_variables = new mrb_sym[0];
3771 private node[] _mandatory_args = new node[0];
3772 private args_t[] _optional_args = new args_t[0];
3773 private mrb_sym _rest;
3774 private node[] _post_mandatory_args = new node[0];
3775 private mrb_sym _blk;
3776 private node _body;
3777
3778 public lambda_node(IMrbParser p, node a, node b)
3779 : base(p, node_type.NODE_LAMBDA)
3780 {
3781 _local_variables = (mrb_sym[])_local_variables.Concat(p.locals_node());
3782 if (a != null) {
3783 node n = a;
3784
3785 if (n.car != null) {
3786 dump_recur(_mandatory_args, (node)n.car);
3787 }
3788 n = (node)n.cdr;
3789 if (n.car != null) {
3790 var n2 = (node)n.car;
3791
3792 while (n2 != null) {
3793 var arg = new args_t(p);
3794 arg.name = (mrb_sym)((node)n2.car).car;
3795 arg.arg = (node)((node)n2.car).cdr;
3796 _optional_args.Push(arg);
3797 n2 = (node)n2.cdr;
3798 }
3799 }
3800 n = (node)n.cdr;
3801 if (n.car != null) {
3802 _rest = (mrb_sym)n.car;
3803 }
3804 n = (node)n.cdr;
3805 if (n.car != null) {
3806 dump_recur(_post_mandatory_args, (node)n.car);
3807 }
3808 if (n.cdr != null) {
3809 _blk = (mrb_sym)n.cdr;
3810 }
3811 }
3812 _body = b;
3813 if (_body is ensure_node) {
3814 ((ensure_node)_body).def = true;
3815 }
3816 }
3817
3818 public mrb_sym[] local_variables { get { return _local_variables; } }
3819 public node[] mandatory_args { get { return _mandatory_args; } }
3820 internal args_t[] optional_args { get { return _optional_args; } }
3821 public mrb_sym rest { get { return _rest; } }
3822 public node[] post_mandatory_args { get { return _post_mandatory_args; } }
3823 public mrb_sym blk { get { return _blk; } }
3824 public node body { get { return _body; } }
3825
3826 public override Element to_xml(xml_code_cond cond)
3827 {
3828 throw new NotImplementedException();
3829 }
3830
3831 protected override void to_rb(ruby_code_cond cond)
3832 {
3833 cond.increment_nest();
3834 cond.write("{");
3835 int i = _mandatory_args.Length + _optional_args.Length
3836 + (_rest != 0 ? 1 : 0) + _post_mandatory_args.Length
3837 + (_blk != 0 ? 1 : 0);
3838 if (i > 0) {
3839 cond.write(" |");
3840 foreach (var a in _mandatory_args) {
3841 a.to_ruby(cond);
3842 i--; if (i > 0) cond.write(", ");
3843 }
3844 foreach (var a in _optional_args) {
3845 a.to_ruby(cond);
3846 i--; if (i > 0) cond.write(", ");
3847 }
3848 if (_rest != 0) {
3849 cond.write("*");
3850 if (_rest != (mrb_sym)(-1))
3851 cond.write(p.sym2name(_rest));
3852 i--; if (i > 0) cond.write(", ");
3853 foreach (var a in _post_mandatory_args) {
3854 a.to_ruby(cond);
3855 i--; if (i > 0) cond.write(", ");
3856 }
3857 }
3858 if (_blk != 0) {
3859 cond.write("&" + p.sym2name(_blk));
3860 }
3861 cond.write("|");
3862 }
3863 cond.decrement_nest();
3864 cond.increment_indent();
3865 _body.to_ruby(cond);
3866 cond.decrement_indent();
3867 cond.write_line("}");
3868 }
3869
3870 public override string ToString()
3871 {
3872 var str = $"(:lambda ";
3873 foreach (var n in mandatory_args) {
3874 str += $"{n}, ";
3875 }
3876 foreach (var n in optional_args) {
3877 str += $"{n}, ";
3878 }
3879 return str + $" . {body}))";
3880 }
3881 }
3882
3883 /* (:asgn lhs rhs) */
3884 class asgn_node : node
3885 {
3886 private node _lhs;
3887 private node _rhs;
3888
3889 public asgn_node(IMrbParser p, node a, node b)
3890 : base(p, node_type.NODE_ASGN)
3891 {
3892 _lhs = a;
3893 _rhs = b;
3894 }
3895
3896 public node lhs { get { return _lhs; } }
3897 public node rhs { get { return _rhs; } }
3898
3899 public override Element to_xml(xml_code_cond cond)
3900 {
3901 var block = cond.CreateElement("block");
3902 block.SetAttribute("type", "variables_set");
3903
3904 var field = cond.CreateElement("field");
3905 field.SetAttribute("name", "VAR");
3906 switch ((node_type)_lhs.car) {
3907 case node_type.NODE_GVAR:
3908 field.AppendChild(cond.CreateTextNode(p.sym2name(((gvar_node)_lhs).name)));
3909 break;
3910 case node_type.NODE_CVAR:
3911 field.AppendChild(cond.CreateTextNode(p.sym2name(((cvar_node)_lhs).name)));
3912 break;
3913 case node_type.NODE_IVAR:
3914 field.AppendChild(cond.CreateTextNode(p.sym2name(((ivar_node)_lhs).name)));
3915 break;
3916 case node_type.NODE_LVAR:
3917 field.AppendChild(cond.CreateTextNode(p.sym2name(((lvar_node)_lhs).name)));
3918 break;
3919 default:
3920 // TODO: list[0] = ...?
3921 field.AppendChild(_lhs.to_xml(cond));
3922 break;
3923 }
3924 block.AppendChild(field);
3925
3926 var value = cond.CreateElement("value");
3927 value.SetAttribute("name", "VALUE");
3928 block.AppendChild(value);
3929
3930 value.AppendChild(_rhs.to_xml(cond));
3931
3932 return block;
3933 }
3934
3935 protected override void to_rb(ruby_code_cond cond)
3936 {
3937 cond.increment_nest();
3938 _lhs.to_ruby(cond);
3939 cond.write(" = ");
3940 _rhs.to_ruby(cond);
3941 cond.decrement_nest();
3942 cond.write_line();
3943 }
3944
3945 public override string ToString()
3946 {
3947 return $"(:asgn {lhs} {rhs})";
3948 }
3949 }
3950
3951 /* (:masgn mlhs=(pre rest post) mrhs) */
3952 class masgn_node : node
3953 {
3954 public class mlhs_t
3955 {
3956 public node[] pre = new node[0];
3957 public node rest;
3958 public bool rest_empty;
3959 public node[] post = new node[0];
3960
3961 public override string ToString()
3962 {
3963 var str = "(";
3964 foreach (var p in pre) {
3965 str += $"{p} ";
3966 }
3967 str += $"{rest} ";
3968 foreach (var p in post) {
3969 str += $"{p} ";
3970 }
3971 return str + ")";
3972 }
3973
3974 internal void to_ruby(ruby_code_cond cond)
3975 {
3976 int i = pre.Length + (rest != null ? 1 : 0) + post.Length;
3977 foreach (var p in pre) {
3978 p.to_ruby(cond);
3979 i--; if (i > 0) cond.write(", ");
3980 }
3981 if (rest != null) {
3982 rest.to_ruby(cond);
3983 i--; if (i > 0) cond.write(", ");
3984 }
3985 foreach (var p in post) {
3986 p.to_ruby(cond);
3987 i--; if (i > 0) cond.write(", ");
3988 }
3989 }
3990 }
3991 private mlhs_t _mlhs;
3992 private node _mrhs;
3993
3994 public masgn_node(IMrbParser p, node a, node b)
3995 : base(p, node_type.NODE_MASGN)
3996 {
3997 _mlhs = new mlhs_t();
3998 {
3999 node n2 = a;
4000
4001 if (n2.car != null) {
4002 dump_recur(_mlhs.pre, (node)n2.car);
4003 }
4004 n2 = (node)n2.cdr;
4005 if (n2 != null) {
4006 if (n2.car != null) {
4007 if (n2.car is int && (int)n2.car == -1) {
4008 _mlhs.rest = null; //(empty)?
4009 _mlhs.rest_empty = true;
4010 }
4011 else {
4012 _mlhs.rest = (node)n2.car;
4013 }
4014 }
4015 n2 = (node)n2.cdr;
4016 if (n2 != null) {
4017 if (n2.car != null) {
4018 dump_recur(_mlhs.post, (node)n2.car);
4019 }
4020 }
4021 }
4022 }
4023 _mrhs = b;
4024 }
4025
4026 public mlhs_t mlhs { get { return _mlhs; } }
4027 public node mrhs { get { return _mrhs; } }
4028
4029 public override Element to_xml(xml_code_cond cond)
4030 {
4031 throw new NotImplementedException();
4032 }
4033
4034 protected override void to_rb(ruby_code_cond cond)
4035 {
4036 _mlhs.to_ruby(cond);
4037 cond.write(" = ");
4038 if (_mrhs != null)
4039 _mrhs.to_ruby(cond);
4040 }
4041
4042 public override string ToString()
4043 {
4044 return $"(:masgn {mlhs} {mrhs})";
4045 }
4046
4047 internal bool remove(mrb_sym[] args)
4048 {
4049 bool m = false;
4050 foreach (var a in _mlhs.pre) {
4051 var arg = a as arg_node;
4052 if (arg != null) {
4053 var i = Array.IndexOf(args, arg.name);
4054 m = i >= 0;
4055 if (m)
4056 args.Splice(i, 1);
4057 }
4058 else {
4059 var masgn = a as masgn_node;
4060 m = masgn.remove(args);
4061 }
4062 if (m)
4063 return true;
4064 }
4065 if (_mlhs.rest != null) {
4066 var rest = _mlhs.rest as arg_node;
4067 if (rest != null) {
4068 var i = Array.IndexOf(args, rest.name);
4069 m = i >= 0;
4070 if (m) {
4071 args.Splice(i, 1);
4072 return true;
4073 }
4074 }
4075 }
4076 foreach (var a in _mlhs.post) {
4077 var arg = a as arg_node;
4078 if (arg != null) {
4079 var i = Array.IndexOf(args, arg.name);
4080 m = i >= 0;
4081 if (m)
4082 args.Splice(i, 1);
4083 }
4084 else {
4085 var masgn = a as masgn_node;
4086 m = masgn.remove(args);
4087 }
4088 if (m)
4089 return true;
4090 }
4091 return m;
4092 }
4093 }
4094
4095 /* (:asgn lhs rhs) */
4096 class op_asgn_node : node
4097 {
4098 private node _lhs;
4099 private mrb_sym _op;
4100 private node _rhs;
4101
4102 public op_asgn_node(IMrbParser p, node lhs, mrb_sym op, node rhs)
4103 : base(p, node_type.NODE_OP_ASGN)
4104 {
4105 _lhs = lhs;
4106 _op = op;
4107 _rhs = rhs;
4108 }
4109
4110 public node lhs { get { return _lhs; } }
4111 public mrb_sym op { get { return _op; } }
4112 public node rhs { get { return _rhs; } }
4113
4114 public override Element to_xml(xml_code_cond cond)
4115 {
4116 // TODO:Rubyの演算は数値だけとは限らない
4117 var block = cond.CreateElement("block");
4118 block.SetAttribute("type", "math_arithmetic");
4119
4120 var field = cond.CreateElement("field");
4121 field.SetAttribute("name", "OP");
4122 switch (p.sym2name(op)) {
4123 case "+": field.AppendChild(cond.CreateTextNode("ADD")); break;
4124 case "-": field.AppendChild(cond.CreateTextNode("MINUS")); break;
4125 case "*": field.AppendChild(cond.CreateTextNode("MULTIPLY")); break;
4126 case "/": field.AppendChild(cond.CreateTextNode("DIVIDE")); break;
4127 case "**": field.AppendChild(cond.CreateTextNode("POWER")); break;
4128 }
4129 block.AppendChild(field);
4130
4131 var value = cond.CreateElement("value");
4132 value.SetAttribute("name", "A");
4133 value.AppendChild(lhs.to_xml(cond));
4134 block.AppendChild(value);
4135
4136 value = cond.CreateElement("value");
4137 value.SetAttribute("name", "B");
4138 value.AppendChild(rhs.to_xml(cond));
4139 block.AppendChild(value);
4140
4141 return block;
4142 }
4143
4144 protected override void to_rb(ruby_code_cond cond)
4145 {
4146 cond.increment_nest();
4147 _lhs.to_ruby(cond);
4148 cond.write(" " + p.sym2name(_op) + "= ");
4149 _rhs.to_ruby(cond);
4150 cond.decrement_nest();
4151 cond.write_line();
4152 }
4153
4154 public override string ToString()
4155 {
4156 return $"(:asgn {lhs} {p.sym2name(op)} {rhs})";
4157 }
4158 }
4159
4160 class negate_node : node
4161 {
4162 node _n;
4163
4164 public negate_node(IMrbParser p, node n)
4165 : base(p, node_type.NODE_NEGATE)
4166 {
4167 this._n = n;
4168 }
4169
4170 public node n { get { return _n; } }
4171
4172 public override Element to_xml(xml_code_cond cond)
4173 {
4174 var block = cond.CreateElement("block");
4175 block.SetAttribute("type", "math_single");
4176
4177 var field = cond.CreateElement("field");
4178 field.SetAttribute("name", "OP");
4179 field.AppendChild(cond.CreateTextNode("NEG"));
4180 block.AppendChild(field);
4181
4182 var value = cond.CreateElement("value");
4183 value.SetAttribute("name", "NUM");
4184 value.AppendChild(_n.to_xml(cond));
4185 block.AppendChild(value);
4186
4187 return block;
4188 }
4189
4190 protected override void to_rb(ruby_code_cond cond)
4191 {
4192 cond.write("-");
4193 _n.to_ruby(cond);
4194 }
4195
4196 public override string ToString()
4197 {
4198 return $"(:nagete {n})";
4199 }
4200 }
4201
4202 /* (:int . i) */
4203 class int_node : node, IEvaluatable
4204 {
4205 private Uint8Array _s;
4206 private int _base;
4207
4208 public int_node(IMrbParser p, Uint8Array s, int @base)
4209 : base(p, node_type.NODE_INT)
4210 {
4211 _s = MrbParser.strdup(s, 0);
4212 _base = @base;
4213 }
4214
4215 public int_node(IMrbParser p, int i, int @base = 10)
4216 : base(p, node_type.NODE_INT)
4217 {
4218 string str = "";
4219 switch (@base) {
4220 case 2:
4221 for (uint b = 0x80000000u; b != 0; b >>= 1) {
4222 str += (b & i) != 0 ? "1" : "0";
4223 }
4224 break;
4225 case 8:
4226 for (int s = 30; s > 0; s -= 3) {
4227 str = ((i << s) & 0xE).ToString() + str;
4228 }
4229 break;
4230 case 16:
4231 str = i.ToString("X");
4232 break;
4233 default:
4234 @base = 10;
4235 str = i.ToString();
4236 break;
4237 }
4238 _s = MrbParser.UTF8StringToArray(str);
4239 _base = @base;
4240 }
4241
4242 public Uint8Array num { get { return _s; } }
4243 public int @base { get { return _base; } }
4244
4245 public override Element to_xml(xml_code_cond cond)
4246 {
4247 var block = cond.CreateElement("block");
4248 block.SetAttribute("type", "math_number");
4249
4250 var field = cond.CreateElement("field");
4251 field.SetAttribute("name", "NUM");
4252 field.AppendChild(cond.CreateTextNode(GetString()));
4253 block.AppendChild(field);
4254
4255 return block;
4256 }
4257
4258 protected override void to_rb(ruby_code_cond cond)
4259 {
4260 switch (_base) {
4261 case 2:
4262 cond.write("0b" + MrbParser.UTF8ArrayToString(_s, 0));
4263 break;
4264 case 8:
4265 cond.write("0o" + MrbParser.UTF8ArrayToString(_s, 0));
4266 break;
4267 case 16:
4268 cond.write("0x" + MrbParser.UTF8ArrayToString(_s, 0));
4269 break;
4270 default:
4271 cond.write(MrbParser.UTF8ArrayToString(_s, 0));
4272 break;
4273 }
4274 }
4275
4276 public override string ToString()
4277 {
4278 string num = GetString();
4279 return $"(:int . {num})";
4280 }
4281
4282 private string GetString()
4283 {
4284 string num;
4285
4286 switch (_base) {
4287 case 2:
4288 num = "0b" + MrbParser.UTF8ArrayToString(_s, 0);
4289 break;
4290 case 8:
4291 num = "0o" + MrbParser.UTF8ArrayToString(_s, 0);
4292 break;
4293 case 16:
4294 num = "0x" + MrbParser.UTF8ArrayToString(_s, 0);
4295 break;
4296 default:
4297 num = MrbParser.UTF8ArrayToString(_s, 0);
4298 break;
4299 }
4300
4301 return num;
4302 }
4303
4304 internal long to_i()
4305 {
4306 var str = MrbParser.UTF8ArrayToString(_s, 0);
4307 return Convert.ToInt64(str, _base);
4308 }
4309
4310 public node evaluate(string method, node[] args)
4311 {
4312 if (args.Length != 1)
4313 return null;
4314
4315 var arg = args[0];
4316 var a = to_i();
4317
4318 if (arg is int_node) {
4319 var b = ((int_node)arg).to_i();
4320
4321 switch (method) {
4322 case "+": {
4323 var c = MrbParser.UTF8StringToArray((a + b).ToString());
4324 return new int_node(p, c, 10);
4325 }
4326 case "-": {
4327 var c = MrbParser.UTF8StringToArray((a - b).ToString());
4328 return new int_node(p, c, 10);
4329 }
4330 case "*": {
4331 var c = MrbParser.UTF8StringToArray((a * b).ToString());
4332 return new int_node(p, c, 10);
4333 }
4334 case "/": {
4335 var c = MrbParser.UTF8StringToArray((a / b).ToString());
4336 return new int_node(p, c, 10);
4337 }
4338 case "%": {
4339 var c = MrbParser.UTF8StringToArray((a % b).ToString());
4340 return new int_node(p, c, 10);
4341 }
4342 case "==": {
4343 if (a == b)
4344 return new true_node(p);
4345 else
4346 return new false_node(p);
4347 }
4348 case "&": {
4349 var c = MrbParser.UTF8StringToArray((a & b).ToString());
4350 return new int_node(p, c, 10);
4351 }
4352 case "|": {
4353 var c = MrbParser.UTF8StringToArray((a | b).ToString());
4354 return new int_node(p, c, 10);
4355 }
4356 case "^": {
4357 var c = MrbParser.UTF8StringToArray((a ^ b).ToString());
4358 return new int_node(p, c, 10);
4359 }
4360 case "<<": {
4361 var c = MrbParser.UTF8StringToArray((a << (int)b).ToString());
4362 return new int_node(p, c, 10);
4363 }
4364 case ">>": {
4365 var c = MrbParser.UTF8StringToArray((a >> (int)b).ToString());
4366 return new int_node(p, c, 10);
4367 }
4368 }
4369 }
4370 else if (arg is float_node) {
4371 var b = ((float_node)arg).to_f();
4372
4373 switch (method) {
4374 case "+": {
4375 var c = MrbParser.UTF8StringToArray((a + b).ToString());
4376 return new float_node(p, c);
4377 }
4378 case "-": {
4379 var c = MrbParser.UTF8StringToArray((a - b).ToString());
4380 return new float_node(p, c);
4381 }
4382 case "*": {
4383 var c = MrbParser.UTF8StringToArray((a * b).ToString());
4384 return new float_node(p, c);
4385 }
4386 case "/": {
4387 var c = MrbParser.UTF8StringToArray((a / b).ToString());
4388 return new float_node(p, c);
4389 }
4390 case "%": {
4391 var c = MrbParser.UTF8StringToArray((a % b).ToString());
4392 return new float_node(p, c);
4393 }
4394 case "==": {
4395 if (a == b)
4396 return new true_node(p);
4397 else
4398 return new false_node(p);
4399 }
4400 }
4401 }
4402
4403 return null;
4404 }
4405 }
4406
4407 /* (:float . i) */
4408 class float_node : node, IEvaluatable
4409 {
4410 private Uint8Array _s;
4411
4412 public float_node(IMrbParser p, Uint8Array s)
4413 : base(p, node_type.NODE_FLOAT)
4414 {
4415 _s = MrbParser.strdup(s, 0);
4416 }
4417
4418 public float_node(IMrbParser p, double f)
4419 : base(p, node_type.NODE_FLOAT)
4420 {
4421 _s = MrbParser.UTF8StringToArray(f.ToString());
4422 }
4423
4424 public Uint8Array num { get { return _s; } }
4425
4426 public override Element to_xml(xml_code_cond cond)
4427 {
4428 var block = cond.CreateElement("block");
4429 block.SetAttribute("type", "math_number");
4430
4431 var field = cond.CreateElement("field");
4432 field.SetAttribute("name", "NUM");
4433 field.AppendChild(cond.CreateTextNode(MrbParser.UTF8ArrayToString(_s, 0)));
4434 block.AppendChild(field);
4435
4436 return block;
4437 }
4438
4439 protected override void to_rb(ruby_code_cond cond)
4440 {
4441 cond.write(MrbParser.UTF8ArrayToString(_s, 0));
4442 }
4443
4444 public override string ToString()
4445 {
4446 return $"(:float . {num})";
4447 }
4448
4449 internal double to_f()
4450 {
4451 var str = MrbParser.UTF8ArrayToString(_s, 0);
4452 return Convert.ToDouble(str);
4453 }
4454
4455 public node evaluate(string method, node[] args)
4456 {
4457 if (args.Length != 1)
4458 return null;
4459
4460 var arg = args[0];
4461 var a = to_f();
4462
4463 if (arg is int_node) {
4464 var b = ((int_node)arg).to_i();
4465
4466 switch (method) {
4467 case "+": {
4468 var c = MrbParser.UTF8StringToArray((a + b).ToString());
4469 return new float_node(p, c);
4470 }
4471 case "-": {
4472 var c = MrbParser.UTF8StringToArray((a - b).ToString());
4473 return new float_node(p, c);
4474 }
4475 case "*": {
4476 var c = MrbParser.UTF8StringToArray((a * b).ToString());
4477 return new float_node(p, c);
4478 }
4479 case "/": {
4480 var c = MrbParser.UTF8StringToArray((a / b).ToString());
4481 return new float_node(p, c);
4482 }
4483 case "%": {
4484 var c = MrbParser.UTF8StringToArray((a % b).ToString());
4485 return new float_node(p, c);
4486 }
4487 case "==": {
4488 if (a == b)
4489 return new true_node(p);
4490 else
4491 return new false_node(p);
4492 }
4493 }
4494 }
4495 else if (arg is float_node) {
4496 var b = ((float_node)arg).to_f();
4497
4498 switch (method) {
4499 case "+": {
4500 var c = MrbParser.UTF8StringToArray((a + b).ToString());
4501 return new float_node(p, c);
4502 }
4503 case "-": {
4504 var c = MrbParser.UTF8StringToArray((a - b).ToString());
4505 return new float_node(p, c);
4506 }
4507 case "*": {
4508 var c = MrbParser.UTF8StringToArray((a * b).ToString());
4509 return new float_node(p, c);
4510 }
4511 case "/": {
4512 var c = MrbParser.UTF8StringToArray((a / b).ToString());
4513 return new float_node(p, c);
4514 }
4515 case "%": {
4516 var c = MrbParser.UTF8StringToArray((a % b).ToString());
4517 return new float_node(p, c);
4518 }
4519 case "==": {
4520 if (a == b)
4521 return new true_node(p);
4522 else
4523 return new false_node(p);
4524 }
4525 }
4526 }
4527
4528 return null;
4529 }
4530 }
4531
4532 /* (:str . (s . len)) */
4533 class str_node : node, IEvaluatable
4534 {
4535 private Uint8Array _str;
4536 private int _len;
4537
4538 public str_node(IMrbParser p, Uint8Array s, int len)
4539 : base(p, node_type.NODE_STR)
4540 {
4541 _str = MrbParser.strndup(s, 0, len);
4542 _len = len;
4543 }
4544
4545 public str_node(IMrbParser p, string s)
4546 : base(p, node_type.NODE_STR)
4547 {
4548 _str = MrbParser.UTF8StringToArray(s);
4549 _len = _str.Length;
4550 }
4551
4552 public Uint8Array str { get { return _str; } }
4553 public int len { get { return _len; } }
4554
4555 public override Element to_xml(xml_code_cond cond)
4556 {
4557 var block = cond.CreateElement("block");
4558 block.SetAttribute("type", "text");
4559
4560 var field = cond.CreateElement("field");
4561 field.SetAttribute("name", "TEXT");
4562 field.AppendChild(cond.CreateTextNode(MrbParser.UTF8ArrayToString(_str, 0)));
4563 block.AppendChild(field);
4564
4565 return block;
4566 }
4567
4568 protected override void to_rb(ruby_code_cond cond)
4569 {
4570 bool esc;
4571 var str = MrbParser.UTF8ArrayToStringEsc(_str, 0, out esc);
4572 if (esc)
4573 cond.write("\"" + str.Replace("\"", "\\\"") + "\"");
4574 else
4575 cond.write("'" + str.Replace("'", "\\'") + "'");
4576 }
4577
4578 public override string ToString()
4579 {
4580 return $"(:str . ('{str}' . {len}))";
4581 }
4582
4583 public string to_s()
4584 {
4585 return MrbParser.UTF8ArrayToString(_str, 0);
4586 }
4587
4588 public node evaluate(string method, node[] args)
4589 {
4590 var s = to_s();
4591
4592 switch (method) {
4593 case "<=>": {
4594 if ((args.Length != 1) || !(args[0] is str_node))
4595 break;
4596 var c = MrbParser.UTF8StringToArray(String.Compare(s, ((str_node)args[0]).to_s()).ToString());
4597 return new int_node(p, c, 10);
4598 }
4599 case "==": {
4600 if ((args.Length != 1) || !(args[0] is str_node))
4601 break;
4602 if (String.Compare(s, ((str_node)args[0]).to_s()) == 0)
4603 return new true_node(p);
4604 else
4605 return new true_node(p);
4606 }
4607 case "+": {
4608 if ((args.Length != 1) || !(args[0] is str_node))
4609 break;
4610 var t = MrbParser.UTF8StringToArray(s + ((str_node)args[0]).to_s());
4611 return new str_node(p, t, t.Length - 1);
4612 }
4613 case "*": {
4614 int a;
4615 if (args.Length != 1)
4616 break;
4617 if (args[0] is int_node)
4618 a = (int)((int_node)args[0]).to_i();
4619 else if (args[0] is float_node)
4620 a = (int)((float_node)args[0]).to_f();
4621 else
4622 break;
4623 var sb = new StringBuilder();
4624 for (var i = 0; i < a; i++) {
4625 sb.Append(a);
4626 }
4627 var t = MrbParser.UTF8StringToArray(sb.ToString());
4628 return new str_node(p, t, t.Length - 1);
4629 }
4630 }
4631
4632 return null;
4633 }
4634 }
4635
4636 /* (:dstr . a) */
4637 class dstr_node : node
4638 {
4639 private node[] _a = new node[0];
4640
4641 public dstr_node(IMrbParser p, node a)
4642 : base(p, node_type.NODE_DSTR)
4643 {
4644 dump_recur(_a, a);
4645 }
4646
4647 public node[] a { get { return _a; } }
4648
4649 public override Element to_xml(xml_code_cond cond)
4650 {
4651 throw new NotImplementedException();
4652 }
4653
4654 protected override void to_rb(ruby_code_cond cond)
4655 {
4656 cond.increment_nest();
4657 cond.write("\"");
4658 foreach (var i in _a) {
4659 var s = i as str_node;
4660 if (s != null) {
4661 var str = MrbParser.UTF8ArrayToString(s.str, 0);
4662 cond.write(str.Replace("\"", "\\\""));
4663 }
4664 else {
4665 cond.write("#{");
4666 i.to_ruby(cond);
4667 cond.write("}");
4668 }
4669 }
4670 cond.write("\"");
4671 cond.decrement_nest();
4672 }
4673
4674 public override string ToString()
4675 {
4676 var str = $"(:dstr . ";
4677 foreach (var n in a) {
4678 str += $"{n} ";
4679 }
4680 return str + ")";
4681 }
4682 }
4683
4684 /* (:str . (s . len)) */
4685 class xstr_node : node
4686 {
4687 private Uint8Array _str;
4688 private int _len;
4689
4690 public xstr_node(IMrbParser p, Uint8Array s, int len)
4691 : base(p, node_type.NODE_XSTR)
4692 {
4693 _str = MrbParser.strndup(s, 0, len);
4694 _len = len;
4695 }
4696
4697 public Uint8Array str { get { return _str; } }
4698 public int len { get { return _len; } }
4699
4700 public override Element to_xml(xml_code_cond cond)
4701 {
4702 throw new NotImplementedException();
4703 }
4704
4705 protected override void to_rb(ruby_code_cond cond)
4706 {
4707 cond.write("%x(");
4708 cond.write(MrbParser.UTF8ArrayToString(_str, 0));
4709 cond.write(")");
4710 }
4711
4712 public override string ToString()
4713 {
4714 return $"(:str . ({str} . {len}))";
4715 }
4716 }
4717
4718 /* (:xstr . a) */
4719 class dxstr_node : node
4720 {
4721 private node[] _a = new node[0];
4722
4723 public dxstr_node(IMrbParser p, node a)
4724 : base(p, node_type.NODE_DXSTR)
4725 {
4726 dump_recur(_a, a);
4727 }
4728
4729 public node[] a { get { return _a; } }
4730
4731 public override Element to_xml(xml_code_cond cond)
4732 {
4733 throw new NotImplementedException();
4734 }
4735
4736 protected override void to_rb(ruby_code_cond cond)
4737 {
4738 foreach (var i in _a) {
4739 i.to_ruby(cond);
4740 }
4741 }
4742
4743 public override string ToString()
4744 {
4745 var str = $"(:xstr . ";
4746 foreach (var n in a) {
4747 str += $"{n} ";
4748 }
4749 return str + ")";
4750 }
4751 }
4752
4753 /* (:dsym . a) */
4754 class dsym_node : node
4755 {
4756 private dstr_node _a;
4757
4758 public dsym_node(IMrbParser p, node a)
4759 : base(p, node_type.NODE_DSYM)
4760 {
4761 _a = new dstr_node(p, a);
4762 }
4763
4764 public node[] a { get { return _a.a; } }
4765
4766 public override Element to_xml(xml_code_cond cond)
4767 {
4768 throw new NotImplementedException();
4769 }
4770
4771 protected override void to_rb(ruby_code_cond cond)
4772 {
4773 cond.write(":");
4774 _a.to_ruby(cond);
4775 }
4776
4777 public override string ToString()
4778 {
4779 return $"(:dsym . {a})";
4780 }
4781 }
4782
4783 /* (:regx . (a . a)) */
4784 class regx_node : node
4785 {
4786 Uint8Array _pattern;
4787 Uint8Array _flags;
4788 Uint8Array _encp;
4789
4790 public regx_node(IMrbParser p, Uint8Array pattern, Uint8Array flags, Uint8Array encp)
4791 : base(p, node_type.NODE_REGX)
4792 {
4793 _pattern = pattern;
4794 _flags = flags;
4795 _encp = encp;
4796 }
4797
4798 public Uint8Array pattern { get { return _pattern; } }
4799 public Uint8Array flags { get { return _flags; } }
4800 public Uint8Array encp { get { return _encp; } }
4801
4802 public override Element to_xml(xml_code_cond cond)
4803 {
4804 throw new NotImplementedException();
4805 }
4806
4807 protected override void to_rb(ruby_code_cond cond)
4808 {
4809 cond.write("/" + MrbParser.UTF8ArrayToString(_pattern, 0));
4810 cond.write("/" + MrbParser.UTF8ArrayToString(_flags, 0));
4811 cond.write("/" + MrbParser.UTF8ArrayToString(_encp, 0));
4812 cond.write("/");
4813 }
4814
4815 public override string ToString()
4816 {
4817 return $"(:regx . ({pattern} . {flags} . {encp}))";
4818 }
4819 }
4820
4821 /* (:dregx . a) */
4822 class dregx_node : node
4823 {
4824 private node[] _a = new node[0];
4825 private Uint8Array _opt;
4826 private Uint8Array _tail;
4827
4828 public dregx_node(IMrbParser p, node a, node b)
4829 : base(p, node_type.NODE_DREGX)
4830 {
4831 dump_recur(_a, a);
4832 _tail = (Uint8Array)((node)b.cdr).car;
4833 _opt = (Uint8Array)((node)b.cdr).cdr;
4834 }
4835
4836 public node[] a { get { return _a; } }
4837 public Uint8Array opt { get { return _opt; } }
4838 public Uint8Array tail { get { return _tail; } }
4839
4840 public override Element to_xml(xml_code_cond cond)
4841 {
4842 throw new NotImplementedException();
4843 }
4844
4845 protected override void to_rb(ruby_code_cond cond)
4846 {
4847 foreach (var i in _a) {
4848 i.to_ruby(cond);
4849 }
4850 cond.write(MrbParser.UTF8ArrayToString(_opt, 0));
4851 cond.write(MrbParser.UTF8ArrayToString(_tail, 0));
4852 }
4853
4854 public override string ToString()
4855 {
4856 var str = $"(:dregx . ";
4857 foreach (var n in a) {
4858 str += $"{n} ";
4859 }
4860 return str + $"{opt} {tail})";
4861 }
4862 }
4863
4864 /* (:backref . n) */
4865 class back_ref_node : node
4866 {
4867 private int _n;
4868
4869 public back_ref_node(IMrbParser p, int n)
4870 : base(p, node_type.NODE_BACK_REF)
4871 {
4872 _n = n;
4873 }
4874
4875 public int n { get { return _n; } }
4876
4877 public override Element to_xml(xml_code_cond cond)
4878 {
4879 throw new NotImplementedException();
4880 }
4881
4882 protected override void to_rb(ruby_code_cond cond)
4883 {
4884 cond.write(n.ToString());
4885 }
4886
4887 public override string ToString()
4888 {
4889 return $"(:backref . {n})";
4890 }
4891 }
4892
4893 /* (:nthref . n) */
4894 class nth_ref_node : node
4895 {
4896 private int _n;
4897
4898 public nth_ref_node(IMrbParser p, int n)
4899 : base(p, node_type.NODE_NTH_REF)
4900 {
4901 _n = n;
4902 }
4903
4904 public int n { get { return _n; } }
4905
4906 public override Element to_xml(xml_code_cond cond)
4907 {
4908 throw new NotImplementedException();
4909 }
4910
4911 protected override void to_rb(ruby_code_cond cond)
4912 {
4913 cond.write(n.ToString());
4914 }
4915
4916 public override string ToString()
4917 {
4918 return $"(:nthref . {n})";
4919 }
4920 }
4921
4922 /* (:heredoc . a) */
4923 class heredoc_node : node
4924 {
4925 private parser_heredoc_info _info;
4926
4927 public heredoc_node(IMrbParser p)
4928 : base(p, node_type.NODE_HEREDOC)
4929 {
4930 _info = new parser_heredoc_info();
4931 }
4932
4933 public parser_heredoc_info info { get { return _info; } }
4934
4935 public override Element to_xml(xml_code_cond cond)
4936 {
4937 var block = cond.CreateElement("block");
4938 block.SetAttribute("type", "text");
4939
4940 var field = cond.CreateElement("field");
4941 field.SetAttribute("name", "TEXT");
4942 field.AppendChild(cond.CreateTextNode(info.GetString()));
4943 block.AppendChild(field);
4944
4945 return block;
4946 }
4947
4948 protected override void to_rb(ruby_code_cond cond)
4949 {
4950 _info.to_ruby(cond);
4951 }
4952
4953 public override string ToString()
4954 {
4955 return $"(:heredoc . {info})";
4956 }
4957 }
4958
4959 class literal_delim_node : node
4960 {
4961 public literal_delim_node(IMrbParser p)
4962 : base(p, node_type.NODE_LITERAL_DELIM)
4963 {
4964 }
4965
4966 public override Element to_xml(xml_code_cond cond)
4967 {
4968 throw new NotImplementedException();
4969 }
4970
4971 protected override void to_rb(ruby_code_cond cond)
4972 {
4973 }
4974
4975 public override string ToString()
4976 {
4977 return $"(:literal_delim)";
4978 }
4979 }
4980
4981 /* (:words . a) */
4982 class words_node : node
4983 {
4984 private node[] _a = new node[0];
4985
4986 public words_node(IMrbParser p, node a)
4987 : base(p, node_type.NODE_WORDS)
4988 {
4989 dump_recur(_a, a);
4990 }
4991
4992 public node[] a { get { return _a; } }
4993
4994 public override Element to_xml(xml_code_cond cond)
4995 {
4996 throw new NotImplementedException();
4997 }
4998
4999 protected override void to_rb(ruby_code_cond cond)
5000 {
5001 cond.write("%w(");
5002 foreach (var i in _a) {
5003 i.to_ruby(cond);
5004 }
5005 cond.write(")");
5006 }
5007
5008 public override string ToString()
5009 {
5010 return $"(:words . {a})";
5011 }
5012 }
5013
5014 /* (:symbols . a) */
5015 class symbols_node : node
5016 {
5017 private node[] _a = new node[0];
5018
5019 public symbols_node(IMrbParser p, node a)
5020 : base(p, node_type.NODE_SYMBOLS)
5021 {
5022 dump_recur(_a, a);
5023 }
5024
5025 public node[] a { get { return _a; } }
5026
5027 public override Element to_xml(xml_code_cond cond)
5028 {
5029 throw new NotImplementedException();
5030 }
5031
5032 protected override void to_rb(ruby_code_cond cond)
5033 {
5034 cond.write("%i{");
5035 foreach (var i in _a) {
5036 i.to_ruby(cond);
5037 }
5038 cond.write("}");
5039 }
5040
5041 public override string ToString()
5042 {
5043 return $"(:symbols . {a})";
5044 }
5045 }
5046
5047 class filename_node : str_node
5048 {
5049 public filename_node(IMrbParser p, Uint8Array s, int len)
5050 : base(p, s, len)
5051 {
5052 }
5053
5054 protected override void to_rb(ruby_code_cond cond)
5055 {
5056 cond.write("__FILE__");
5057 }
5058 }
5059
5060 class lineno_node : int_node
5061 {
5062 public lineno_node(IMrbParser p, int lineno)
5063 : base(p, MrbParser.UTF8StringToArray(lineno.ToString()), 10)
5064 {
5065 }
5066
5067 protected override void to_rb(ruby_code_cond cond)
5068 {
5069 cond.write("__LINE__");
5070 }
5071 }
5072}
Note: See TracBrowser for help on using the repository browser.