4
|
1 #include <functional>
|
|
2 #include <iostream>
|
|
3 #include <iomanip>
|
|
4 #include "node.h"
|
|
5 #include "compiler.h"
|
|
6 #include "script-parser.hh"
|
|
7
|
|
8 // コード生成用
|
|
9 CNodeValue CNodeValue::MakeNodeValue(compiler *c, CNode *node)
|
|
10 {
|
|
11 switch (node->op()) {
|
|
12 case OP_CONST:
|
|
13 return CNodeValue(CONST, node->value());
|
|
14
|
|
15 case OP_VALUE:
|
|
16 {
|
|
17 const CValueTag *tag = c->GetValueTag(node->string());
|
|
18 if (tag == 0) {
|
|
19 c->error(node->location(), "変数" + node->string() + "は未定義です。");
|
|
20 return CNodeValue(VALUE, 0);
|
|
21 }
|
|
22 return CNodeValue(VALUE, tag->addr_);
|
|
23 }
|
|
24 }
|
|
25 return node->analyze(c);
|
|
26 }
|
|
27
|
|
28 // 一時変数の管理
|
|
29 CNodeValue CNodeValue::MakeTempValue(compiler *c, int value)
|
|
30 {
|
|
31 if (value < 0)
|
|
32 return CNodeValue(c, TEMP, c->AllocTempValue());
|
|
33 return CNodeValue(VALUE, value);
|
|
34 }
|
|
35
|
|
36 void CNodeValue::ReleaseTempValue()
|
|
37 {
|
|
38 c_->ReleaseTempValue(value_);
|
|
39 }
|
|
40
|
|
41 void CNodeValue::UseTempValue()
|
|
42 {
|
|
43 c_->UseTempValue(value_);
|
|
44 }
|
|
45
|
|
46 int CNodeValue::value() const
|
|
47 {
|
|
48 if (type_ == TEMP)
|
|
49 return c_->GetTempAddr(value_);
|
|
50 return value_;
|
|
51 }
|
|
52
|
|
53 // ノード生成
|
|
54 // ただし、定数同士の計算は、leftノードに結果を代入し、それを返す
|
|
55
|
|
56 CNode *CNode::MakeNode(compiler &c, const yy::location& l, int op, CNode *left, CNode *right)
|
|
57 {
|
|
58 if (right == 0) {
|
|
59 switch (op) {
|
|
60 case OP_NEG:
|
|
61 if (left->op_ == OP_CONST) { // 定数演算を計算する
|
|
62 left->value_ = -left->value_;
|
|
63 return left;
|
|
64 }
|
|
65 break;
|
|
66 }
|
|
67 return new CNode(l, op, left);
|
|
68 }
|
|
69
|
|
70 // 定数演算を計算する
|
|
71 if (left->op_ == OP_CONST && right->op_ == OP_CONST) {
|
|
72 switch (op) {
|
|
73 case OP_EQ:
|
|
74 left->value_ = (left->value_ == right->value_)? 1: 0;
|
|
75 break;
|
|
76
|
|
77 case OP_NE:
|
|
78 left->value_ = (left->value_ != right->value_)? 1: 0;
|
|
79 break;
|
|
80
|
|
81 case OP_GT:
|
|
82 left->value_ = (left->value_ > right->value_)? 1: 0;
|
|
83 break;
|
|
84
|
|
85 case OP_GE:
|
|
86 left->value_ = (left->value_ >= right->value_)? 1: 0;
|
|
87 break;
|
|
88
|
|
89 case OP_LT:
|
|
90 left->value_ = (left->value_ < right->value_)? 1: 0;
|
|
91 break;
|
|
92
|
|
93 case OP_LE:
|
|
94 left->value_ = (left->value_ <= right->value_)? 1: 0;
|
|
95 break;
|
|
96
|
|
97 case OP_MINUS:
|
|
98 left->value_ -= right->value_;
|
|
99 break;
|
|
100
|
|
101 case OP_PLUS:
|
|
102 left->value_ += right->value_;
|
|
103 break;
|
|
104
|
|
105 case OP_TIMES:
|
|
106 left->value_ *= right->value_;
|
|
107 break;
|
|
108
|
|
109 case OP_DIVIDE:
|
|
110 if (right->value_ == 0) {
|
|
111 c.error(l, "定数計算を0で除算しました。");
|
|
112 }
|
|
113 else {
|
|
114 left->value_ /= right->value_;
|
|
115 }
|
|
116 break;
|
|
117
|
|
118 case OP_MOD:
|
|
119 if (right->value_ == 0) {
|
|
120 c.error(l, "定数計算を0で除算しました。");
|
|
121 }
|
|
122 else {
|
|
123 left->value_ %= right->value_;
|
|
124 }
|
|
125 break;
|
|
126
|
|
127 default:
|
|
128 return new CNode(l, op, left, right);
|
|
129 }
|
|
130 delete right;
|
|
131 return left;
|
|
132 }
|
|
133 return new CNode(l, op, left, right);
|
|
134 }
|
|
135
|
|
136 CNodeValue CNode::analyze(compiler *c, int ret)
|
|
137 {
|
|
138 switch (op_) {
|
|
139 case OP_NEG:
|
|
140 return c->MakeNeg(ret, CNodeValue::MakeNodeValue(c, left_));
|
|
141
|
|
142 case OP_RANDFUNC:
|
|
143 return c->MakeRand(ret, CNodeValue::MakeNodeValue(c, left_));
|
|
144
|
|
145 case OP_CONST:
|
|
146 return c->MakeMoveC(ret, value_);
|
|
147
|
|
148 case OP_VALUE:
|
|
149 return c->MakeMoveV(ret, CNodeValue::MakeNodeValue(c, this));
|
|
150 }
|
|
151
|
|
152 CNodeValue left = CNodeValue::MakeNodeValue(c, left_);
|
|
153 CNodeValue right = CNodeValue::MakeNodeValue(c, right_);
|
|
154
|
|
155 // 整数計算ノードの処理
|
|
156 return c->MakeOp(op_, ret, left, right);
|
|
157 }
|
|
158
|
|
159 // 代入命令を生成
|
|
160 //
|
|
161 // a = b
|
|
162 // > mov a, b
|
|
163 //
|
|
164 CNodeValue CAssign::analyze(compiler *c)
|
|
165 {
|
|
166 const CValueTag *tag = c->GetValueTag(value_->string());
|
|
167 if (tag == 0) {
|
|
168 tag = c->AddValue(value_->string());
|
|
169 }
|
|
170 if (tag == 0) {
|
|
171 c->error(l_, "変数 " + value_->string() + " が定義できません。");
|
|
172 return CNodeValue();
|
|
173 }
|
|
174 return expr_->analyze(c, tag->addr_);
|
|
175 }
|