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

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

ファイルヘッダーコメントを追加

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