0
|
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 }
|