/*
 *  ADP (Another Data Processor) www.adp.la
 *  Copyright (C) 2010 Katsuhisa Ohfuji <katsuhisa@ohfuji.name>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License version 2 as
 *  published by the Free Software Foundation.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *  MA 02110-1301, USA.
 */
#include "adp.h"

// 必ずPObject &dstの引数の実体を作成すること（これはサボれない）
PObject *PString::add(const PObject &dst, PObjectArray *objs, bool w) const	{ return dst.add(*this, objs, w); }
PObject *PString::add(const PString &src, PObjectArray *objs, bool w) const	{ 
	if ( src.value.empty()) {
		return this->clone(objs);
	}
	if ( value.empty() ) {
		return src.clone(objs);
	}
	string result_ = src.value + this->value;
	return pmm.newPString(objs,result_);	
}


PObject *PDouble::add(const PObject &dst, PObjectArray *objs, bool w) const	{ return dst.add(*this, objs, w); }
PObject *PDouble::add(const PDouble &src, PObjectArray *objs, bool w) const	{ return pmm.newPDouble(objs, src.value + value); }
PObject *PDouble::add(const PInteger &src, PObjectArray *objs, bool w) const { return pmm.newPDouble(objs, src.value + value); }
PObject *PInteger::add(const PObject &dst, PObjectArray *objs, bool w) const { return dst.add(*this, objs, w); }
PObject *PInteger::add(const PDouble &src, PObjectArray *objs, bool w) const { return pmm.newPDouble(objs, src.value + value); }
PObject *PInteger::add(const PInteger &src, PObjectArray *objs, bool w) const { return pmm.newPInteger(objs, src.value + value); }
PObject *PList::add(const PObject &dst, PObjectArray *objs, bool w) const { return dst.add(*this, objs, w); }
PObject *PList::add(const PList &src, PObjectArray *objs, bool w) const	{ 
		// srcが[]の場合、dst(this)を返す
		if ( src.lvalue == &pnil && src.rvalue == &pnil ) {
			return this->clone(objs);
		}
		
		// dst(this)が[]の場合、srcを返す
		if ( lvalue == &pnil && rvalue == &pnil ) {
			return src.clone(objs);
		}

		// Listの結合 src.rvalueをサーチし最後にdst(this)を加える
		PList *result = src.clone(objs);

		// rvalueをサーチ
		PList *list = result;
		while ( list && list->rvalue != &pnil ) {
			list = dynamic_cast<PList *>(list->rvalue);
		}

		// 最後にdstを追加
		if ( list ) list->rvalue = this->clone(objs);
		
		return result;
		
	}
PObject *PList::add(const PArray &src, PObjectArray *objs, bool w) const	{ 
		PArray *result = 0;
		if ( !w ) {
			result = src.clone(objs);
		} else {
			result = const_cast<PArray*>(&src);
		}
		
		// [A]の対応
		if ( typeid(*lvalue) != typeid(const PList) && typeid(*rvalue) == typeid(PNil) ) {
			result->value.push_back(lvalue->clone(objs));
			return result;
		}

		// [A|B] の対応（ハッシュの要素の対応）
		if ( typeid(*lvalue) != typeid(const PList) && typeid(*rvalue) != typeid(const PList) ) {
			result->value.push_back(rvalue->clone(objs));
			string key;
			if ( lvalue->cnv_string(key) ) {
				assert( result->type == false );
				result->hamap_[key] = result->value.size() - 1;
			}
			return result;
		}

		// [a,b,c,d,e...]ないし、[[A|B],[C|D],[E|F]....]のみ対応
		const PList *list = this;

		while ( list ) {
			const PObject *value_ = list->lvalue;
			const PList	*vl = dynamic_cast<const PList *>(value_);
			if ( vl == 0 ) {	// [a,b,c,d,e...]
				result->value.push_back(value_->clone(objs));
			} else {			// [[A|B],[C|D],[E|F]....]
				result->value.push_back(vl->rvalue->clone(objs));
				string key;
				if ( vl->lvalue->cnv_string(key) ) {
					assert( result->type == false );
					result->hamap_[key] = result->value.size() - 1;
				}
			}
			list = dynamic_cast<const PList *>(list->rvalue);
		}
	
		return result;
	}
PObject *PArray::add(const PObject &dst, PObjectArray *objs, bool w) const { return dst.add(*this, objs, w); }
PObject *PArray::add(const PArray &src, PObjectArray *objs, bool w) const { 
		PArray *result = 0;
		if ( !w ) {
			result = pmm.newPArray(objs, src);
		} else {
			result = const_cast<PArray*>(&src);
		}
		size_t	siz = result->value.size();
		// Valueの追加
		for ( PObjectArray::const_iterator i = value.begin(); i < value.end(); i++ ) {
			result->value.push_back(*i);
		}
		// Hashの追加
		for ( PHashArrayMap::const_iterator i = hamap_.begin(); i != hamap_.end(); i++ ) {
			 assert(result->type==false);
			 result->hamap_[i->first] = i->second + siz; 
		}
		result->constant &= constant;	// constantはAND
		result->args = false ;	// 引数でない
		result->type = false;	// タイプではない
		result->brace;			// braceは左辺（src）のものを継承
		return result;
	}

PObject *PString::sub(const PObject &dst, PObjectArray *objs) const	{ return 0; }
PObject *PDouble::sub(const PObject &dst, PObjectArray *objs) const	{ return dst.sub(*this,objs); }
PObject *PDouble::sub(const PDouble &src, PObjectArray *objs) const		{ return pmm.newPDouble(objs, src.value - value); }
PObject *PDouble::sub(const PInteger &src, PObjectArray *objs) const	{ return pmm.newPDouble(objs, src.value - value); }
PObject *PInteger::sub(const PObject &dst, PObjectArray *objs) const	{ return dst.sub(*this,objs); }
PObject *PInteger::sub(const PDouble &src, PObjectArray *objs) const	{ return pmm.newPDouble(objs, src.value - value); }
PObject *PInteger::sub(const PInteger &src, PObjectArray *objs) const	{ return pmm.newPInteger(objs, src.value - value);}
PObject *PList::sub(const PObject &dst, PObjectArray *objs) const		{ return 0; }
PObject *PArray::sub(const PObject &dst, PObjectArray *objs) const	{ return 0; }

PObject *PString::mul(const PObject &dst, PObjectArray *objs) const	{ return 0; }
PObject *PDouble::mul(const PObject &dst, PObjectArray *objs) const	{ return dst.mul(*this,objs); }
PObject *PDouble::mul(const PDouble &src, PObjectArray *objs) const		{ return pmm.newPDouble(objs, src.value * value); }
PObject *PDouble::mul(const PInteger &src, PObjectArray *objs) const	{ return pmm.newPDouble(objs, src.value * value); }
PObject *PInteger::mul(const PObject &dst, PObjectArray *objs) const	{ return dst.mul(*this,objs); }
PObject *PInteger::mul(const PDouble &src, PObjectArray *objs) const	{ return pmm.newPDouble(objs, src.value * value); }
PObject *PInteger::mul(const PInteger &src, PObjectArray *objs) const	{ return pmm.newPInteger(objs, src.value * value);}
PObject *PList::mul(const PObject &dst, PObjectArray *objs) const		{ return 0; }
PObject *PArray::mul(const PObject &dst, PObjectArray *objs) const	{ return 0; }

PObject *PString::div(const PObject &dst, PObjectArray *objs) const	{ return 0; }
PObject *PDouble::div(const PObject &dst, PObjectArray *objs) const	{ return dst.div(*this,objs); }
PObject *PDouble::div(const PDouble &src, PObjectArray *objs) const		{ return pmm.newPDouble(objs, src.value / value); }
PObject *PDouble::div(const PInteger &src, PObjectArray *objs) const	{ return pmm.newPDouble(objs, src.value / value); }
PObject *PInteger::div(const PObject &dst, PObjectArray *objs) const	{ return dst.div(*this,objs); }
PObject *PInteger::div(const PDouble &src, PObjectArray *objs) const	{ return pmm.newPDouble(objs,src.value / value); }
PObject *PInteger::div(const PInteger &src, PObjectArray *objs) const	{ return pmm.newPInteger(objs,src.value / value);}
PObject *PList::div(const PObject &dst, PObjectArray *objs) const		{ return 0; }
PObject *PArray::div(const PObject &dst, PObjectArray *objs) const	{ return 0; }

PObject *PString::mod(const PObject &dst, PObjectArray *objs) const	{ return 0; }
PObject *PDouble::mod(const PObject &dst, PObjectArray *objs) const	{ return 0; }
PObject *PInteger::mod(const PObject &dst, PObjectArray *objs) const	{ return dst.mod(*this,objs); }
PObject *PInteger::mod(const PInteger &src, PObjectArray *objs) const	{ return pmm.newPInteger(objs,src.value % value);}
PObject *PList::mod(const PObject &dst, PObjectArray *objs) const		{ return 0; }
PObject *PArray::mod(const PObject &dst, PObjectArray *objs) const	{ return 0; }

bool PString::cmp(const PObject &dst, int &result) const	{ return dst.cmp(*this, result); }
bool PString::cmp(const PString &src, int &result) const	{ result = sign<int>(strcmp(src.c_str(), c_str())); return true; }
bool PDouble::cmp(const PObject &dst, int &result) const	{ return dst.cmp(*this, result); }
bool PDouble::cmp(const PDouble &src, int &result) const	{ result = sign<double>(src.value - value); return true; }
bool PDouble::cmp(const PInteger &src, int &result) const	{ result = sign<double>(src.value - value); return true; }
bool PInteger::cmp(const PObject &dst, int &result) const	{ return dst.cmp(*this, result); }
bool PInteger::cmp(const PDouble &src, int &result) const	{ result = sign<double>(src.value - value); return true; }
bool PInteger::cmp(const PInteger &src, int &result) const	{ result = sign<PINTEGER>(src.value - value); return true; }
bool PList::cmp(const PObject &dst, int &result) const	{ return 0; }
bool PArray::cmp(const PObject &dst, int &result) const	{ return 0; }


// 式のコンパイル
ExpressionTree *ExpressionCompileContext::makeExpressionTree_Term(CompileContext &c)
{
	if ( find( termchar.begin(), termchar.end(), *c) != termchar.end() ) {
		c.skip();
		return 0;
	}
	if ( c.eof() ) {
		c.err( "C0027: formula syntax error: unexpected end of file ");
		return 0;
	}
	// '('が出てきたときは括弧の処理を行う。
	if ( *c == '(' ) {
		string	back = termchar;
		termchar.clear();
		termchar.push_back(')');
		c.next();
		ExpressionTree *ret = makeExpressionTree(c);
		termchar = back;
		c.next();
		return ret;
	}

	PObject *o = c.createObject();	// ここではエラーチェックをしない（呼び出し元に任せる）
	if ( !o ) {
		c.skip();
		return 0;
	}
	PObject *p = o->compile(c);
	
	// 述語名が変項の場合の処理
	//   （配列変項ではない場合）
	PVeriable *vp = dynamic_cast<PVeriable*>(p);
	if ( *c == '(' && (vp && !vp->isargs()) ) {
		PPredicate *pp = get_gc()->factory.createObject<PPredicate>();
		pp->setName(p);
		c.next();
		pp->compileArglist(c);
		p = pp;
	}
	c.skip();
	return newExpressionTree(p);
}

ExpressionTree *ExpressionCompileContext::makeExpressionTree_Symbolhash(CompileContext &c)
{
	ExpressionTree *left = makeExpressionTree_Term(c);
	while ( !c.eof() && *c == ':' ) { // シンボル形式のハッシュ参照
		string op = "{";
		ExpressionTree *right = makeExpressionTree_Term(c);	// 式の中
		left = newExpressionTree( op, left, right); // 結果は{}と同じように扱う
	}
	return left;
}

ExpressionTree *ExpressionCompileContext::makeExpressionTree_hash(CompileContext &c)
{
	ExpressionTree *left = makeExpressionTree_Symbolhash(c);
	string op;
	char endop;
	while ( getOperatorHash(c, op, endop) && !c.eof() ) { // ハッシュ演算子があると式とみなす 
		ExpressionTree *right = makeExpressionTree_Symbolhash(c);	// 式の中
		if ( *c == endop ) {
			c.next();
		} else {
			c.err( cformat("C0039: invalid hash access end '%c', expect ']' or '}' ", *c));
		}
		left = newExpressionTree( op, left, right);
	}
	return left;
}

ExpressionTree *ExpressionCompileContext::makeExpressionTree_method(CompileContext &c)
{
	ExpressionTree *left = makeExpressionTree_hash(c);
	string op;
	while ( getOperatorMethod(c, op) && !c.eof() ) { // 乗除算演算子があると式とみなす 
		ExpressionTree *right = makeExpressionTree_hash(c);	// 式の中
		left = newExpressionTree( op, left, right);
	}
	return left;
}

ExpressionTree *ExpressionCompileContext::makeExpressionTree_unary(CompileContext &c)
{
	ExpressionTree *left = 0;
	string op;
	if ( getOperatorUnary(c, op) && !c.eof() ) { // 単項演算子があると式とみなす 
		ExpressionTree *right = makeExpressionTree_method(c);
		left = newExpressionTree( op, 0, right);
	} else {
		left = makeExpressionTree_method(c);
	}
	return left;
}

ExpressionTree *ExpressionCompileContext::makeExpressionTree_mul(CompileContext &c)
{
	ExpressionTree *left = makeExpressionTree_unary(c);
	string op;
	while ( getOperatorMul(c, op) && !c.eof() ) { // 乗除算演算子があると式とみなす 
		ExpressionTree *right = makeExpressionTree_unary(c);	// 式の中
		left = newExpressionTree( op, left, right);
	}
	return left;
}

ExpressionTree *ExpressionCompileContext::makeExpressionTree_add(CompileContext &c)
{
	ExpressionTree *left = makeExpressionTree_mul(c);
	string op;
	while ( getOperatorAdd(c, op) && !c.eof() ) { // 加減演算子があると式とみなす 
		ExpressionTree *right = makeExpressionTree_mul(c);	// 式の中
		left = newExpressionTree( op, left, right);
	}
	return left;
}

ExpressionTree *ExpressionCompileContext::makeExpressionTree_cmp(CompileContext &c)
{
	ExpressionTree *left = makeExpressionTree_add(c);	// 左辺値
	string op;
	while ( getOperatorCMP(c, op) && !c.eof() ) { // 比較演算子があると式とみなす 
		ExpressionTree *right = makeExpressionTree_add(c);	// 右辺値
		left = newExpressionTree( op, left, right);
	}
	return left;
}

ExpressionTree *ExpressionCompileContext::makeExpressionTree_and(CompileContext &c)
{
	ExpressionTree *left = makeExpressionTree_cmp(c);	// 左辺値 
	string op;
	while ( getOperatorAND(c, op) && !c.eof() ) {
		ExpressionTree *right = makeExpressionTree_cmp(c);	// 右辺値
		left = newExpressionTree( op, left, right);
	}
	return left;
}

ExpressionTree *ExpressionCompileContext::makeExpressionTree_xor(CompileContext &c)
{
	ExpressionTree *left = makeExpressionTree_and(c);	// 左辺値 
	string op;
	while ( getOperatorXOR(c, op) && !c.eof() ) {
		ExpressionTree *right = makeExpressionTree_and(c);	// 右辺値
		left = newExpressionTree( op, left, right);
	}
	return left;
}

ExpressionTree *ExpressionCompileContext::makeExpressionTree_or(CompileContext &c)
{
	ExpressionTree *left = makeExpressionTree_xor(c);	// 左辺値
	string op;
	while ( getOperatorOR(c, op) && !c.eof() ) {
		ExpressionTree *right = makeExpressionTree_xor(c);	// 右辺値
		left = newExpressionTree( op, left, right);
	}
	return left;
}

ExpressionTree *ExpressionCompileContext::makeExpressionTree(CompileContext &c)
{
	ExpressionTree *left = makeExpressionTree_or(c);	// 左辺値
	string op;
	while ( getOperatorLET(c, op) && !c.eof() ) {	// 代入演算子があると式とみなす 
		ExpressionTree *right = makeExpressionTree_or(c);	// 右辺値
		left = newExpressionTree( op, left, right);
	}
	return left;
}

PObject *ExpressionCompileContext::makeCode(CompileContext &c, ExpressionTree *exp, PObject *dst)
{	
	if ( !exp ) return 0;
	if ( exp->obj ) return exp->obj;
	if ( !exp->op.empty() ) {
		// make code normal. 
		PObject *left = makeCode(c, exp->left, 0);

		// Optimaize when using equal operator (==) and numeric operator(+-*/%&|^) . 
		if ( strcmp( exp->op.c_str(), "==") == 0 ) {
			if ( exp->right != 0 && !exp->right->op.empty() ) {
				return makeCode( c, exp->right, left);
			}
		}

		PObject *right = makeCode(c, exp->right, 0);
		if ( !left || !right ) {
			if ( (strcmp(exp->op.c_str(), "-") != 0 && strcmp(exp->op.c_str(), "~") != 0 && strcmp(exp->op.c_str(), "=") != 0) || right == 0 ) {
				c.err( cformat("C0028: invalid operator '%s' for unary operator ", exp->op.c_str()) );
				return 0;
			}
		}

		// left がPredicateなら戻り値を取得するようにする 
		PPredicate *p = dynamic_cast<PPredicate*>(left);
		if ( p ) {
			p->compileHereName(c, true);			
			left = p->addResultArg(c);
		}
		

		// method formula 
		if ( strcmp(exp->op.c_str(), ".") == 0 ) {
			PPredicate *r = dynamic_cast<PPredicate*>(right);
			if ( r == 0 ) {
				c.err("C0040: not function or predicate for the method call ");
				return 0;
			}
			// Optimaize pipe (bypass input to output) 
			if ( r->name->c_str() && strcmp( r->name->c_str(), "pipe") == 0 ) {
				return left;	
			} else {
				r->addMethodArg(c, left, dst);
				return right;
			}
		}

		// right がPredicateなら戻り値を取得するようにする 
		p = dynamic_cast<PPredicate*>(right);
		if ( p ) {
			p->compileHereName(c, true);			
			right = p->addResultArg(c);
		}

		p = get_gc()->factory.createObject<PPredicate>();
		PObject *ret;
		if ( strcmp(exp->op.c_str(), "+") == 0 ) {
			if ( dst ) {
				ret = p->make3Operator( c, "_add", left, right, dst, false);
			} else {
				ret = p->make3Operator( c, "_add", left, right, true);
			}
		} else if ( strcmp(exp->op.c_str(), "-") == 0 ) {
			if ( left ) {
				if ( dst ) {
					ret = p->make3Operator( c, "_sub", left, right, dst, false);
				} else {
					ret = p->make3Operator( c, "_sub", left, right, true);
				}
			} else {
				if ( dst ) {
					ret = p->make2Operator( c, "_neg", right, dst, false);
				} else {
					ret = p->make1Operator( c, "_neg", right, true);
				}
			}
		} else if ( strcmp(exp->op.c_str(), "~") == 0 ) {
				if ( dst ) {
					ret = p->make2Operator( c, "_not", right, dst, false);
				} else {
					ret = p->make1Operator( c, "_not", right, true);
				}
		} else if ( strcmp(exp->op.c_str(), "*") == 0 ) {
			if ( dst ) {
				ret = p->make3Operator( c, "_mul", left, right, dst, false);
			} else {
				ret = p->make3Operator( c, "_mul", left, right, true);
			}
		} else if ( strcmp(exp->op.c_str(), "/") == 0 ) {
			if ( dst ) {
				ret = p->make3Operator( c, "_div", left, right, dst, false);
			} else {
				ret = p->make3Operator( c, "_div", left, right, true);
			}
		} else if ( strcmp(exp->op.c_str(), "%") == 0 ) {
			if ( dst ) {
				ret = p->make3Operator( c, "_mod", left, right, dst, false);
			} else {
				ret = p->make3Operator( c, "_mod", left, right, true);
			}
		} else if ( strcmp(exp->op.c_str(), "<") == 0 ) {
			if ( dst ) c.err("C0031: invalid operator '==' for the operator '<' result ");
			ret = p->make2Operator( c, "_lt", left, right, false);
		} else if ( strcmp(exp->op.c_str(), "<=") == 0 ) {
			if ( dst ) c.err("C0032: invalid operator '==' for the operator '<=' result ");
			ret = p->make2Operator( c, "_le", left, right, false);
		} else if ( strcmp(exp->op.c_str(), ">") == 0 ) {
			if ( dst ) c.err("C0033: invalid operator '==' for the operator '>' result ");
			ret = p->make2Operator( c, "_gt", left, right, false);
		} else if ( strcmp(exp->op.c_str(), ">=") == 0 ) {
			if ( dst ) c.err("C0034: invalid operator '==' for the operator '>=' result ");
			ret = p->make2Operator( c, "_ge", left, right, false);
		} else if ( strcmp(exp->op.c_str(), "==") == 0 ) {
			if ( dst ) c.err("C0035: invalid operator '==' for the operator '==' result ");
			ret = p->make2Operator( c, "_equ", left, right, false);
		} else if ( strcmp(exp->op.c_str(), "!=") == 0 ) {
			if ( dst ) c.err("C0036: invalid operator '==' for the operator '!=' result ");
			ret = p->make2Operator( c, "_neq", left, right, false);
		} else if ( strcmp(exp->op.c_str(), "<>") == 0 ) {
			if ( dst ) c.err("C0037: invalid operator '==' for the operator '<>' result ");
			ret = p->make2Operator( c, "_neq", left, right, false);
		} else if ( strcmp(exp->op.c_str(), "&") == 0 ) {
			if ( dst ) {
				ret = p->make3Operator( c, "_and", left, right, dst, false);
			} else {
				ret = p->make3Operator( c, "_and", left, right, true);
			}
		} else if ( strcmp(exp->op.c_str(), "^") == 0 ) {
			if ( dst ) {
				ret = p->make3Operator( c, "_xor", left, right, dst, false);
			} else {
				ret = p->make3Operator( c, "_xor", left, right, true);
			}
		} else if ( strcmp(exp->op.c_str(), "|") == 0 ) {
			if ( dst ) {
				ret = p->make3Operator( c, "_or", left, right, dst, false);
			} else {
				ret = p->make3Operator( c, "_or", left, right, true);
			}
		} else if ( strcmp(exp->op.c_str(), "=") == 0 ) {
			if ( left ) {
				ret = p->make2Operator( c, "_let", right, left, false);
			} else {
				if ( dst ) {
					ret = p->make2Operator( c, "_equ", dst, right, false);
				} else {
					ret = right;
				}
			}
		} else if ( strcmp(exp->op.c_str(), "+=") == 0 ) {
			ret = p->make2Operator( c, "_letadd", right, left, false);
		} else if ( strcmp(exp->op.c_str(), "-=") == 0 ) {
			ret = p->make2Operator( c, "_letsub", right, left, false);
		} else if ( strcmp(exp->op.c_str(), "*=") == 0 ) {
			ret = p->make2Operator( c, "_letmul", right, left, false);
		} else if ( strcmp(exp->op.c_str(), "/=") == 0 ) {
			ret = p->make2Operator( c, "_letdiv", right, left, false);
		} else if ( strcmp(exp->op.c_str(), "%=") == 0 ) {
			ret = p->make2Operator( c, "_letmod", right, left, false);
		} else if ( strcmp(exp->op.c_str(), "&=") == 0 ) {
			ret = p->make2Operator( c, "_letand", right, left, false);
		} else if ( strcmp(exp->op.c_str(), "|=") == 0 ) {
			ret = p->make2Operator( c, "_letor", right, left, false);
		} else if ( strcmp(exp->op.c_str(), "^=") == 0 ) {
			ret = p->make2Operator( c, "_letxor", right, left, false);
		} else if ( strcmp(exp->op.c_str(), "[") == 0 ) {
			if ( dst ) {
				// == との統合を行っているのでresult_returnはfalseにしておく（ユニフィケーションを実行する） 
				ret = p->make3Operator( c, "item", left, right, dst, false, false);
			} else {
				ret = p->make3Operator( c, "item", left, right, true, true);
			}
		} else if ( strcmp(exp->op.c_str(), "{") == 0 ) {
			if ( dst ) {
				// == との統合を行っているのでresult_returnはfalseにしておく（ユニフィケーションを実行する） 
				ret = p->make3Operator( c, "itemkey", left, right, dst, false, false);
			} else {
				ret = p->make3Operator( c, "itemkey", left, right, true, true);
			}
		}
		return ret;
	}
	c.err("C0029: nothing expression ");
	return 0;	
}

PObject *ExpressionCompileContext::compileExpression(CompileContext &c, bool funcflg)
{
	ExpressionTree *exp = makeExpressionTree(c);
	if ( !exp ) return 0;
	if ( !exp->obj && !c.goalcontext ) {
		c.err("C0030: not any expression ");
		return 0;
	}
	PObject *r = makeCode(c,exp,0);

	PPredicate *p = dynamic_cast<PPredicate*>(r);
	if ( p ) {
		p->compileHereName(c,funcflg);
	}

	// 関数形式の変換を行う 
	if ( funcflg ) {
		if ( p ) {
			r = p->addResultArg(c);
		}
	}
	return r;
}
