comparison Bison-Flex/Compiler-StackBase/EUC/node.cpp @ 0:db40c85cad7a default tip

upload sample source
author nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
date Mon, 09 May 2011 03:11:59 +0900
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:db40c85cad7a
1 //
2 // ノード
3 //
4 // (c)2008 Chihiro.SAKAMOTO HyperWorks
5 //
6 #include <functional>
7 #include <iostream>
8 #include <iomanip>
9 #include "node.h"
10 #include "compiler.h"
11 #include "script-parser.hh"
12
13 // ノード生成
14 // ただし、定数同士の計算は、leftノードに結果を代入し、それを返す
15
16 CNode *CNode::MakeNode(compiler &c, const yy::location& l, int op, CNode *left, CNode *right)
17 {
18 if (right == 0) {
19 switch (op) {
20 case OP_NEG:
21 if (left->op_ == OP_CONST) { // 定数演算を計算する
22 left->value_ = -left->value_;
23 return left;
24 }
25 break;
26 }
27 return new CNode(l, op, left);
28 }
29
30 // 定数演算を計算する
31 if (left->op_ == OP_CONST && right->op_ == OP_CONST) {
32 switch (op) {
33 case OP_LOGAND:
34 left->value_ = (left->value_ && right->value_)? 1: 0;
35 break;
36
37 case OP_LOGOR:
38 left->value_ = (left->value_ || right->value_)? 1: 0;
39 break;
40
41 case OP_EQ:
42 left->value_ = (left->value_ == right->value_)? 1: 0;
43 break;
44
45 case OP_NE:
46 left->value_ = (left->value_ != right->value_)? 1: 0;
47 break;
48
49 case OP_GT:
50 left->value_ = (left->value_ > right->value_)? 1: 0;
51 break;
52
53 case OP_GE:
54 left->value_ = (left->value_ >= right->value_)? 1: 0;
55 break;
56
57 case OP_LT:
58 left->value_ = (left->value_ < right->value_)? 1: 0;
59 break;
60
61 case OP_LE:
62 left->value_ = (left->value_ <= right->value_)? 1: 0;
63 break;
64
65 case OP_AND:
66 left->value_ &= right->value_;
67 break;
68
69 case OP_OR:
70 left->value_ |= right->value_;
71 break;
72
73 case OP_LSHIFT:
74 left->value_ <<= right->value_;
75 break;
76
77 case OP_RSHIFT:
78 left->value_ >>= right->value_;
79 break;
80
81 case OP_MINUS:
82 left->value_ -= right->value_;
83 break;
84
85 case OP_PLUS:
86 left->value_ += right->value_;
87 break;
88
89 case OP_TIMES:
90 left->value_ *= right->value_;
91 break;
92
93 case OP_DIVIDE:
94 if (right->value_ == 0) {
95 c.error(l, "定数計算を0で除算しました。");
96 }
97 else {
98 left->value_ /= right->value_;
99 }
100 break;
101
102 case OP_MOD:
103 if (right->value_ == 0) {
104 c.error(l, "定数計算を0で除算しました。");
105 }
106 else {
107 left->value_ %= right->value_;
108 }
109 break;
110
111 default:
112 return new CNode(l, op, left, right);
113 }
114 delete right;
115 return left;
116 }
117
118 // 文字列同士の定数計算
119 if (left->op_ == OP_STRING && right->op_ == OP_STRING) {
120 if (op == OP_PLUS) {
121 *left->string_ += *right->string_;
122 delete right;
123 return left;
124 }
125
126 int value = 0;
127 switch (op) {
128 case OP_EQ:
129 if (*left->string_ == *right->string_)
130 value = 1;
131 break;
132
133 case OP_NE:
134 if (*left->string_ != *right->string_)
135 value = 1;
136 break;
137
138 case OP_GT:
139 if (*left->string_ > *right->string_)
140 value = 1;
141 break;
142
143 case OP_GE:
144 if (*left->string_ >= *right->string_)
145 value = 1;
146 break;
147
148 case OP_LT:
149 if (*left->string_ < *right->string_)
150 value = 1;
151 break;
152
153 case OP_LE:
154 if (*left->string_ <= *right->string_)
155 value = 1;
156 break;
157
158 default:
159 c.error(l, "文字列同士ではできない計算です");
160 break;
161 }
162 delete left;
163 delete right;
164 return new CNode(l, OP_CONST, value);
165 }
166 return new CNode(l, op, left, right);
167 }
168
169 // ノードのpush処理
170 int CNode::push(compiler *c) const
171 {
172 switch (op_) {
173 case OP_NEG:
174 if (left_->push(c) == TYPE_STRING)
175 c->error(l_, "文字列には許されない計算です。");
176 c->OpNeg();
177 return TYPE_INTEGER;
178
179 case OP_CONST:
180 c->PushConst(value_);
181 return TYPE_INTEGER;
182
183 case OP_STRING:
184 c->PushString(*string_);
185 return TYPE_STRING;
186 }
187
188 int left_type = left_->push(c);
189 int right_type = right_->push(c);
190
191 if (left_type != right_type)
192 c->error(l_, "文字列と整数間で計算できません。");
193
194 // 整数計算ノードの処理
195 if (left_type == TYPE_INTEGER) {
196 switch (op_) {
197 case OP_LOGAND:
198 c->OpLogAnd();
199 break;
200
201 case OP_LOGOR:
202 c->OpLogOr();
203 break;
204
205 case OP_EQ:
206 c->OpEq();
207 break;
208
209 case OP_NE:
210 c->OpNe();
211 break;
212
213 case OP_GT:
214 c->OpGt();
215 break;
216
217 case OP_GE:
218 c->OpGe();
219 break;
220
221 case OP_LT:
222 c->OpLt();
223 break;
224
225 case OP_LE:
226 c->OpLe();
227 break;
228
229 case OP_AND:
230 c->OpAnd();
231 break;
232
233 case OP_OR:
234 c->OpOr();
235 break;
236
237 case OP_LSHIFT:
238 c->OpLeftShift();
239 break;
240
241 case OP_RSHIFT:
242 c->OpRightShift();
243 break;
244
245 case OP_MINUS:
246 c->OpSub();
247 break;
248
249 case OP_PLUS:
250 c->OpAdd();
251 break;
252
253 case OP_TIMES:
254 c->OpMul();
255 break;
256
257 case OP_DIVIDE:
258 c->OpDiv();
259 break;
260
261 case OP_MOD:
262 c->OpMod();
263 break;
264
265 default:
266 c->error(l_, "内部エラー:処理できない計算ノードがありました。");
267 break;
268 }
269 return TYPE_INTEGER;
270 }
271
272 // 文字列計算ノードの処理
273 switch (op_) {
274 case OP_EQ:
275 c->OpStrEq();
276 return TYPE_INTEGER;
277
278 case OP_NE:
279 c->OpStrNe();
280 return TYPE_INTEGER;
281
282 case OP_GT:
283 c->OpStrGt();
284 return TYPE_INTEGER;
285
286 case OP_GE:
287 c->OpStrGe();
288 return TYPE_INTEGER;
289
290 case OP_LT:
291 c->OpStrLt();
292 return TYPE_INTEGER;
293
294 case OP_LE:
295 c->OpStrLe();
296 return TYPE_INTEGER;
297
298 case OP_PLUS:
299 c->OpStrAdd();
300 break;
301
302 default:
303 c->error(l_, "文字列では計算できない式です。");
304 break;
305 }
306 return TYPE_STRING;
307 }
308
309 // ノードのpop
310 // 計算ノードはpopできない
311
312 int CNode::pop(compiler *c) const
313 {
314 c->error(l_, "内部エラー:計算ノードをpopしています。");
315 return TYPE_INTEGER;
316 }
317
318 // 変数ノードのpush
319 int CValueNode::push(compiler *c) const
320 {
321 if (op_ != OP_VALUE) {
322 c->error(l_, "内部エラー:変数ノードに変数以外が登録されています。");
323 }
324 else {
325 const CValueTag *tag = c->GetValueTag(*string_);
326 if (tag == 0) {
327 c->error(l_, "変数 " + *string_ + " は定義されていません。");
328 }
329 else {
330 // 参照型変数は、引数にしか存在しない
331 if (tag->type_ >= TYPE_INTEGER_REF) {
332 if (left_) { // 配列
333 left_->push(c);
334 c->PushLocalArrayRef(tag->addr_);
335 }
336 else {
337 c->PushLocalRef(tag->addr_);
338 }
339 return tag->type_ - TYPE_INTEGER_REF;
340 }
341 if (tag->global_) { // 外部変数
342 if (left_) { // 配列
343 left_->push(c);
344 c->PushArray(tag->addr_);
345 }
346 else {
347 c->PushValue(tag->addr_);
348 }
349 }
350 else { // ローカル変数
351 if (left_) { // 配列
352 left_->push(c);
353 c->PushLocalArray(tag->addr_);
354 }
355 else {
356 c->PushLocal(tag->addr_);
357 }
358 }
359 return tag->type_;
360 }
361 }
362 return TYPE_INTEGER;
363 }
364
365 // 変数ノードのpop
366 int CValueNode::pop(compiler *c) const
367 {
368 if (op_ != OP_VALUE) {
369 c->error(l_, "内部エラー:変数ノードに変数以外が登録されています。");
370 }
371 else {
372 const CValueTag *tag = c->GetValueTag(*string_);
373 if (tag == 0) {
374 c->error(l_, "変数 " + *string_ + " は定義されていません。");
375 }
376 else {
377 // 参照型変数は、引数にしか存在しない
378 if (tag->type_ >= TYPE_INTEGER_REF) {
379 if (left_) { // 配列
380 left_->push(c);
381 c->PopLocalArrayRef(tag->addr_);
382 }
383 else {
384 c->PopLocalRef(tag->addr_);
385 }
386 return tag->type_ - TYPE_INTEGER_REF;
387 }
388 if (tag->global_) { // 外部変数
389 if (left_) { // 配列
390 left_->push(c);
391 c->PopArray(tag->addr_);
392 }
393 else {
394 c->PopValue(tag->addr_);
395 }
396 }
397 else { // ローカル変数
398 if (left_) { // 配列
399 left_->push(c);
400 c->PopLocalArray(tag->addr_);
401 }
402 else {
403 c->PopLocal(tag->addr_);
404 }
405 }
406 return tag->type_;
407 }
408 }
409 return TYPE_INTEGER;
410 }
411
412 // 関数呼び出し
413
414 struct set_arg {
415 compiler *comp_;
416 const CFunctionTag *func_;
417 mutable int index_;
418 set_arg(compiler *comp, const CFunctionTag *func): comp_(comp), func_(func), index_(0)
419 {
420 }
421
422 void operator()(CNode *node) const
423 {
424 int type = func_->GetArg(index_++);
425 if (type >= TYPE_INTEGER_REF) { // 参照
426 if (node->op() != OP_VALUE) {
427 comp_->error(node->location(), "参照型引数に、変数以外は指定できません。");
428 }
429 else {
430 const CValueTag *tag = comp_->GetValueTag(node->string());
431 if (tag == 0) {
432 comp_->error(node->location(), "変数 " + node->string() + " は定義されていません。");
433 }
434 else if (tag->type_ >= TYPE_INTEGER_REF) { // 参照
435 // 参照型変数は、ローカルしかない
436 if (node->left()) {
437 node->left()->push(comp_);
438 comp_->PushLocal(tag->addr_);
439 comp_->OpAdd();
440 }
441 else {
442 comp_->PushLocal(tag->addr_);
443 }
444 }
445 else {
446 if (TypeToRef(tag->type_) != type) {
447 comp_->error(node->location(), "引数の型が合いません。");
448 }
449 int addr = tag->addr_;
450 if (tag->global_) // 外部変数
451 addr |= vm::vcpu::global_flag;
452 // アドレスをpush
453 if (node->left()) { // 配列
454 if (node->left()->op() == OP_CONST) {
455 comp_->PushAddr(addr + node->left()->value());
456 }
457 else {
458 node->left()->push(comp_);
459 comp_->PushArrayAddr(addr);
460 }
461 }
462 else {
463 comp_->PushAddr(addr);
464 }
465 }
466 }
467 }
468 else {
469 if (node->push(comp_) != type) {
470 comp_->error(node->location(), "引数の型が合いません。");
471 }
472 }
473 }
474 } ;
475
476 int CFunctionNode::push(compiler *c) const
477 {
478 const CFunctionTag *tag = c->GetFunctionTag(*string_);
479 if (tag == NULL) {
480 c->error(l_, "関数 " + *string_ + "は、定義されていません。");
481 return TYPE_INTEGER;
482 }
483
484 int arg_size = (args_)? args_->size(): 0;
485 if (tag->ArgSize() != arg_size) {
486 c->error(l_, "引数の数が合いません。");
487 }
488
489 // 引数をpush
490 if (args_ && tag->ArgSize() == arg_size) {
491 args_->for_each(set_arg(c, tag));
492 }
493
494 // 引数の数をpush
495 c->PushConst(arg_size);
496
497 if (tag->IsSystem()) {
498 c->OpSysCall(tag->GetIndex()); // システムコール
499 }
500 else {
501 c->OpCall(tag->GetIndex()); // スクリプト上の関数
502 }
503
504 return tag->type_;
505 }
506
507 // 関数にpopはできないのでエラーメッセージを出す
508 int CFunctionNode::pop(compiler *c) const
509 {
510 c->error(l_, "内部エラー:関数ノードをpopした");
511 return TYPE_INTEGER;
512 }
513
514 // 変数定義
515
516 struct add_value {
517 compiler *comp_;
518 int type_;
519 add_value(compiler *comp, int type): comp_(comp), type_(type)
520 {
521 }
522
523 void operator()(CValueNode *node)
524 {
525 comp_->AddValue(node->location(), type_, node->string(), node->left());
526 }
527 } ;
528
529 void CDecl::analyze(compiler *c)
530 {
531 list_->for_each(add_value(c, type_));
532 }
533
534 // 代入命令を生成
535 //
536 // a = b
537 // > push b
538 // > pop a
539 //
540 // a += b
541 // > push a
542 // > push b
543 // > add
544 // > pop a
545 //
546 void CAssign::analyze(compiler *c)
547 {
548 if (op_ != '=')
549 value_->push(c);
550
551 if (expr_->push(c) == TYPE_INTEGER) {
552 switch (op_) {
553 case '+':
554 c->OpAdd();
555 break;
556
557 case '-':
558 c->OpSub();
559 break;
560
561 case '*':
562 c->OpMul();
563 break;
564
565 case '/':
566 c->OpDiv();
567 break;
568
569 case '%':
570 c->OpMod();
571 break;
572 }
573 if (value_->pop(c) != TYPE_INTEGER)
574 c->error(l_, "文字列型に整数を代入しています。");
575 return;
576 }
577
578 switch (op_) {
579 case '+':
580 c->OpStrAdd();
581 break;
582
583 case '=':
584 break;
585
586 default:
587 c->error(l_, "文字列では許されない計算です。");
588 break;
589 }
590 if (value_->pop(c) != TYPE_STRING)
591 c->error(l_, "整数型に文字列を代入しています。");
592 }
593
594 // '{' '}' で囲まれた文の生成
595
596 void CStateBlock::analyze(compiler *c)
597 {
598 // ローカル変数の定義
599 if (decls_) {
600 decls_->for_each(std::bind2nd(std::mem_fun(&CDecl::analyze), c));
601 c->AllocStack();
602 }
603
604 // 文のコード生成
605 if (states_) {
606 states_->for_each(std::bind2nd(std::mem_fun(&CStatement::analyze), c));
607 }
608 }
609
610 // NOP
611
612 void CNopStatement::analyze(compiler *c)
613 {
614 // 何もしない
615 }
616
617 // 代入
618
619 void CAssignStatement::analyze(compiler *c)
620 {
621 assign_->analyze(c);
622 }
623
624 // 関数呼び出し
625
626 void CFunctionStatement::analyze(compiler *c)
627 {
628 int type = node_.push(c);
629 if (type != TYPE_VOID)
630 c->OpPop(); // 戻り値を捨てるためのpop
631 }
632
633 // IF文
634 //
635 // if (expr) A
636 // > push expr
637 // > jmp_nc L1
638 // > A
639 // > L1:
640 //
641 // if (expr) A else B
642 // > push expr
643 // > jmp_nc L1
644 // > A
645 // > jmp L2
646 // > L1:
647 // > B
648 // > L2:
649 //
650 void CIfStatement::analyze(compiler *c)
651 {
652 expr_->push(c);
653 int label1 = c->MakeLabel();
654 c->OpJmpNC(label1);
655 then_statement_->analyze(c);
656
657 if (else_statement_) {
658 int label2 = c->MakeLabel();
659 c->OpJmp(label2);
660 c->SetLabel(label1);
661 else_statement_->analyze(c);
662 c->SetLabel(label2);
663 }
664 else {
665 c->SetLabel(label1);
666 }
667 }
668
669 // FOR文
670 //
671 // for (init; expr; next) A
672 // > init
673 // > L1:
674 // > push expr
675 // > jmp_nc L2
676 // > A
677 // > next
678 // > jmp L1
679 // > L2:
680 //
681 void CForStatement::analyze(compiler *c)
682 {
683 int label1 = c->MakeLabel();
684 int label2 = c->MakeLabel();
685
686 int break_label = c->SetBreakLabel(label2);
687
688 init_->analyze(c);
689 c->SetLabel(label1);
690 expr_->push(c);
691 c->OpJmpNC(label2);
692 statement_->analyze(c);
693 next_->analyze(c);
694 c->OpJmp(label1);
695 c->SetLabel(label2);
696
697 c->SetBreakLabel(break_label);
698 }
699
700 // WHILE文
701 //
702 // while (expr) A
703 // > L1:
704 // > push expr
705 // > jmp_nc L2
706 // > A
707 // > jmp L1
708 // > L2:
709 //
710 void CWhileStatement::analyze(compiler *c)
711 {
712 int label1 = c->MakeLabel();
713 int label2 = c->MakeLabel();
714
715 int break_label = c->SetBreakLabel(label2);
716
717 c->SetLabel(label1);
718 expr_->push(c);
719 c->OpJmpNC(label2);
720 statement_->analyze(c);
721 c->OpJmp(label1);
722 c->SetLabel(label2);
723
724 c->SetBreakLabel(break_label);
725 }
726
727 // SWITCH文
728 //
729 // switch (expr) {
730 // case A:
731 // STATE_A
732 // break;
733 // case B:
734 // STATE_B
735 // break;
736 // default:
737 // STATE_C
738 // break;
739 // }
740 // > push expr
741 // > push A
742 // > test L1 ; stack上の2値を比較し、等しければpopしてJmp
743 // > push B
744 // > test L2
745 // > pop
746 // > jmp L3
747 // > L1:
748 // > STATE_A
749 // > jmp L0 ; break
750 // > L2:
751 // > STATE_B
752 // > jmp L0 ; break
753 // > L3:
754 // > STATE_C
755 // > jmp L0 ; break
756 // > L0:
757 //
758 void CSwitchStatement::analyze(compiler *c)
759 {
760 expr_->push(c);
761
762 if (list_) {
763 int label = c->MakeLabel(); // L0ラベル作成
764 int break_label = c->SetBreakLabel(label);
765 int default_label = label;
766
767 case_action_param param(c, default_label);
768
769 list_->for_each(std::bind2nd(std::mem_fun(&CStatement::case_analyze), &param));
770 c->OpPop();
771 c->OpJmp(default_label);
772
773 list_->for_each(std::bind2nd(std::mem_fun(&CStatement::analyze), c));
774 c->SetLabel(label);
775
776 c->SetBreakLabel(break_label);
777 }
778 }
779
780 // CASE文
781 //
782 // switch文の特殊処理
783 //
784 void CCaseStatement::analyze(compiler *c)
785 {
786 c->SetLabel(label_);
787 }
788
789 void CCaseStatement::case_analyze(case_action_param *param)
790 {
791 compiler *c = param->comp_;
792
793 label_ = c->MakeLabel();
794 if (expr_->op() != OP_CONST)
795 c->error(l_, "case 文には定数のみ指定できます。");
796 expr_->push(c);
797 c->OpTest(label_);
798 }
799
800 // DEFAULT文
801 //
802 // switch文の特殊処理
803 //
804 void CDefaultStatement::analyze(compiler *c)
805 {
806 c->SetLabel(label_);
807 }
808
809 void CDefaultStatement::case_analyze(case_action_param *param)
810 {
811 label_ = param->comp_->MakeLabel();
812 param->default_label = label_;
813 }
814
815 // BREAK文
816 //
817 // 登録されているJump先へのJmp命令を生成
818 //
819 void CBreakStatement::analyze(compiler *c)
820 {
821 if (!c->JmpBreakLabel()) {
822 c->error(l_, "breakがswitch/for/while外に有ります");
823 }
824 }
825
826 // RETURN文
827 //
828 // RETURNコマンドを生成
829 //
830 void CReturnStatement::analyze(compiler *c)
831 {
832 if (c->GetFunctionType() == TYPE_VOID) { // 戻り値無し
833 if (expr_ != 0) {
834 c->error(l_, "void関数に戻り値が設定されています");
835 }
836 c->OpReturn();
837 }
838 else {
839 if (expr_ == 0) {
840 c->error(l_, "関数の戻り値がありません");
841 }
842 else {
843 int expr_type = expr_->push(c); // 戻り値をpush
844 if (expr_type != c->GetFunctionType()) {
845 c->error(l_, "戻り値の型が合いません");
846 }
847 }
848 c->OpReturnV();
849 }
850 }
851
852 // 文ブロック
853 //
854 // 再帰的にすべての文を解析
855 //
856 void CBlockStatement::analyze(compiler *c)
857 {
858 c->BlockIn();
859 block_->analyze(c);
860 c->BlockOut();
861 }