view 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 source

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