comparison Bison-Flex/BasicCompiler-MemoryBase/node.cpp @ 4:805d39d28230

add Compiler-stackbase
author nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
date Tue, 17 May 2011 08:00:38 +0900
parents
children
comparison
equal deleted inserted replaced
3:3cea2e8a0e4b 4:805d39d28230
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 }