Mercurial > hg > Members > nobuyasu > myCompiler
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Bison-Flex/BasicCompiler-MemoryBase/node.cpp Tue May 17 08:00:38 2011 +0900 @@ -0,0 +1,175 @@ +#include <functional> +#include <iostream> +#include <iomanip> +#include "node.h" +#include "compiler.h" +#include "script-parser.hh" + +// コード生成用 +CNodeValue CNodeValue::MakeNodeValue(compiler *c, CNode *node) +{ + switch (node->op()) { + case OP_CONST: + return CNodeValue(CONST, node->value()); + + case OP_VALUE: + { + const CValueTag *tag = c->GetValueTag(node->string()); + if (tag == 0) { + c->error(node->location(), "変数" + node->string() + "は未定義です。"); + return CNodeValue(VALUE, 0); + } + return CNodeValue(VALUE, tag->addr_); + } + } + return node->analyze(c); +} + +// 一時変数の管理 +CNodeValue CNodeValue::MakeTempValue(compiler *c, int value) +{ + if (value < 0) + return CNodeValue(c, TEMP, c->AllocTempValue()); + return CNodeValue(VALUE, value); +} + +void CNodeValue::ReleaseTempValue() +{ + c_->ReleaseTempValue(value_); +} + +void CNodeValue::UseTempValue() +{ + c_->UseTempValue(value_); +} + +int CNodeValue::value() const +{ + if (type_ == TEMP) + return c_->GetTempAddr(value_); + return value_; +} + +// ノード生成 +// ただし、定数同士の計算は、leftノードに結果を代入し、それを返す + +CNode *CNode::MakeNode(compiler &c, const yy::location& l, int op, CNode *left, CNode *right) +{ + if (right == 0) { + switch (op) { + case OP_NEG: + if (left->op_ == OP_CONST) { // 定数演算を計算する + left->value_ = -left->value_; + return left; + } + break; + } + return new CNode(l, op, left); + } + + // 定数演算を計算する + if (left->op_ == OP_CONST && right->op_ == OP_CONST) { + switch (op) { + case OP_EQ: + left->value_ = (left->value_ == right->value_)? 1: 0; + break; + + case OP_NE: + left->value_ = (left->value_ != right->value_)? 1: 0; + break; + + case OP_GT: + left->value_ = (left->value_ > right->value_)? 1: 0; + break; + + case OP_GE: + left->value_ = (left->value_ >= right->value_)? 1: 0; + break; + + case OP_LT: + left->value_ = (left->value_ < right->value_)? 1: 0; + break; + + case OP_LE: + left->value_ = (left->value_ <= right->value_)? 1: 0; + break; + + case OP_MINUS: + left->value_ -= right->value_; + break; + + case OP_PLUS: + left->value_ += right->value_; + break; + + case OP_TIMES: + left->value_ *= right->value_; + break; + + case OP_DIVIDE: + if (right->value_ == 0) { + c.error(l, "定数計算を0で除算しました。"); + } + else { + left->value_ /= right->value_; + } + break; + + case OP_MOD: + if (right->value_ == 0) { + c.error(l, "定数計算を0で除算しました。"); + } + else { + left->value_ %= right->value_; + } + break; + + default: + return new CNode(l, op, left, right); + } + delete right; + return left; + } + return new CNode(l, op, left, right); +} + +CNodeValue CNode::analyze(compiler *c, int ret) +{ + switch (op_) { + case OP_NEG: + return c->MakeNeg(ret, CNodeValue::MakeNodeValue(c, left_)); + + case OP_RANDFUNC: + return c->MakeRand(ret, CNodeValue::MakeNodeValue(c, left_)); + + case OP_CONST: + return c->MakeMoveC(ret, value_); + + case OP_VALUE: + return c->MakeMoveV(ret, CNodeValue::MakeNodeValue(c, this)); + } + + CNodeValue left = CNodeValue::MakeNodeValue(c, left_); + CNodeValue right = CNodeValue::MakeNodeValue(c, right_); + + // 整数計算ノードの処理 + return c->MakeOp(op_, ret, left, right); +} + +// 代入命令を生成 +// +// a = b +// > mov a, b +// +CNodeValue CAssign::analyze(compiler *c) +{ + const CValueTag *tag = c->GetValueTag(value_->string()); + if (tag == 0) { + tag = c->AddValue(value_->string()); + } + if (tag == 0) { + c->error(l_, "変数 " + value_->string() + " が定義できません。"); + return CNodeValue(); + } + return expr_->analyze(c, tag->addr_); +}