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_);
+}