Mercurial > hg > Members > nobuyasu > SampleSource
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), ¶m)); | |
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 } |