/*
 *  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.
 */

#ifndef ADP_COMPILE_H
#define ADP_COMPILE_H

struct BinaryObjectFormat {

	static void put_bool(string &str, bool value) {
		str.push_back(value ? 1 : 0);
	}

	static bool get_bool(string &str, size_t idx = 0) {
		return str.c_str()[idx + 0] != 0 ? true : false;
	}

	static void put_int(string &str, int value) {
		str.push_back((char)((value >> 24) & 0xff));
		str.push_back((char)((value >> 16) & 0xff));
		str.push_back((char)((value >>  8) & 0xff));
		str.push_back((char)( value & 0xff));
	}

	static int get_int(string &str, size_t idx = 0) {
		return str.c_str()[idx + 0] << 24 |
			   str.c_str()[idx + 1] << 16 |
			   str.c_str()[idx + 2] <<  8 |
			   str.c_str()[idx + 3];
	}

	static void put_long_long(string &str, long long value) {
		str.push_back((char)((value >> 56) & 0xff));
		str.push_back((char)((value >> 48) & 0xff));
		str.push_back((char)((value >> 40) & 0xff));
		str.push_back((char)((value >> 32) & 0xff));
		str.push_back((char)((value >> 24) & 0xff));
		str.push_back((char)((value >> 16) & 0xff));
		str.push_back((char)((value >>  8) & 0xff));
		str.push_back((char)( value & 0xff));
	}

	static long long get_long_long(string &str, size_t idx = 0) {
		return (long long)str.c_str()[idx + 0] << 56 |
			   (long long)str.c_str()[idx + 1] << 48 |
			   (long long)str.c_str()[idx + 2] << 40 |
			   (long long)str.c_str()[idx + 3] << 32 |
			   (long long)str.c_str()[idx + 4] << 24 |
			   (long long)str.c_str()[idx + 5] << 16 |
			   (long long)str.c_str()[idx + 6] <<  8 |
			   (long long)str.c_str()[idx + 7];
	}

	static void put_string(string &str, const string &value) {
		put_long_long( str, value.size());
		str += value;
	}

	static void get_string(string &str, size_t idx, string &value) {
		long long siz = get_long_long( str, idx);
		value = str.substr( idx + 8, (size_t)siz);
	}


	static PObject *readObject( string &str, PObjectArray *pobjs, size_t &pos);

	static void make( string &str, int code) {
		put_int(str, code);
		put_long_long(str, 0);
		put_int(str, 0); // reserve
	}

	static void make( string &str, int code, const string &obj) {
		put_int(str, code);
		put_long_long(str, obj.size());		
		put_int(str, 0); // reserve
		str += obj;
	}
};


// PObject ADPの各言語要素のオブジェクト
class PObject {
	friend class PMemoryManager;
public:
	// コンパイル関係	
	virtual bool isMyObject(char keychar) const = 0;		// 文字からオブジェクトを決める
	virtual PObject *compile(CompileContext &c, bool funcflg) { return this;};	// コンパイルする
	virtual void recompile(ostream &s) const = 0;	// リコンパイルする

	// バイナリフォーマット
	virtual bool Bread(string &, PObjectArray *) { return false; };
	virtual bool Bwrite(string &) const { return false; };
	virtual int	 Bcode() const { return 0; }

	// JSONパース関係
	virtual bool isMyJsonHead(const string &src, size_t pos) const { return false; };	// 文字からオブジェクトを決める
	virtual PObject *parseJson(const string &src, size_t &pos, PObjectArray *pobjs) { return 0; };

	// オブジェクトの複製を作成する
	virtual PObject *clone(PObjectArray *objs) const = 0;

	// ハッシュ値
	virtual PINTEGER chash() const = 0;
	virtual bool cmatch(const PObject *dst) const = 0;

	// 定数オブジェクトの確認
	virtual bool isc() const = 0;

	// 変項の確認
	virtual bool isveriable() const { return false; };

	// 引数展開の確認
	virtual bool isargs() const { return false; };

	// コレクションクラス？
	virtual bool iscollection() const { return false; };

	// pridicateの取得（upgoalで使用）
	virtual const PPredicate *getPredicate(VLocal *hlocal) const { return 0; };

	// pridicate nameの取得（getPridicateNameで使用）
	virtual const string *getPredicateName(bool &docache, VLocal *hlocal) const { return 0; };

	// ユニフィケーション
	virtual bool unify(const PObject &goal, ExecContextRoot *c, VLocal *hlocal, VLocal	*glocal) const { return false; }
	virtual bool unify(const PNil &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const { return false; }
	virtual bool unify(const PString &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const { return false; }
	virtual bool unify(const PDouble &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal)  const { return false; }
	virtual bool unify(const PInteger &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal)  const { return false; }
	virtual bool unify(const PList &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const { return false; }
	virtual bool unify(const PArray &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const { return false; }
	virtual bool unify(const PPredicate &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const { return false; }
	virtual bool unify(const PVeriable &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const { return false; }
	virtual bool unify(const PEVeriable &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const { return false; }
	virtual bool unify(const PWildCard &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const { return true; }

	// ユニフィケーション（localなしc->glを使用）
	virtual bool unify(const PObject &goal, ExecContextRoot *c) const { return false; }
	virtual bool unify(const PNil &horn, ExecContextRoot *c) const { return false; }
	virtual bool unify(const PString &horn, ExecContextRoot *c) const { return false; }
	virtual bool unify(const PDouble &horn, ExecContextRoot *c)  const { return false; }
	virtual bool unify(const PInteger &horn, ExecContextRoot *c)  const { return false; }
	virtual bool unify(const PList &horn, ExecContextRoot *c) const { return false; }
	virtual bool unify(const PArray &horn, ExecContextRoot *c) const { return false; }
	virtual bool unify(const PPredicate &horn, ExecContextRoot *c) const { return false; }
	virtual bool unify(const PVeriable &horn, ExecContextRoot *c) const { return false; }
	virtual bool unify(const PEVeriable &horn, ExecContextRoot *c) const { return false; }
	virtual bool unify(const PWildCard &horn, ExecContextRoot *c) const { return true; }


	// 値の取得(unify時に使用、必要なら代入用の変更PEVariableを作成する）
	virtual const PObject *getval( ExecContextRoot *) const { return this; }
	virtual const PObject *getval( ExecContextRoot *, VLocal *) const { return this; }

	// 値の取得
	virtual const char *c_str() const { return 0; };
	virtual const double *c_double() const { return 0; };
	virtual const PINTEGER32 *c_integer32(ExecContextRoot *) const { return 0; };
	virtual const PINTEGER	*c_integer() const { return 0; };
	virtual const PINTEGER	*c_integer(ExecContextRoot *) const { return 0; };

	// ラベルの取得（変数の名前の取得：PArrayのハッシュで使用）
	virtual const char *label() const { return 0; };

	// 変換して値を取得
	virtual bool cnv_string(string &value) const { return false; };
	virtual bool cnv_double(double &value) const { return false; };
	virtual bool cnv_integer(PINTEGER &value) const { return false; };
	virtual void cnv_csv(string &value, char sep, char quote) const {};
	virtual void cnv_json(string &value) const { value += "\"\""; };

	// ストリームへ出力
	virtual void print(FILE *out) const {
		string value;
		value.reserve(8192);
		cnv_string(value);
		fwrite( value.c_str(), value.size(), 1, out);
	};

	// PMMによるデリート
	virtual void del() = 0;

	// オペレーター
	virtual PObject *add(const PObject &dst, PObjectArray *objs) const { return 0; };
	virtual PObject *add(const PString &src, PObjectArray *objs) const { return 0; };
	virtual PObject *add(const PDouble &src, PObjectArray *objs) const { return 0; };
	virtual PObject *add(const PInteger &src, PObjectArray *objs) const { return 0; };
	virtual PObject *add(const PList &src, PObjectArray *objs) const { return 0; };
	virtual PObject *add(const PArray &src, PObjectArray *objs) const { return 0; };

	virtual PObject *sub(const PObject &dst, PObjectArray *objs) const { return 0; };
	virtual PObject *sub(const PString &src, PObjectArray *objs) const { return 0; };
	virtual PObject *sub(const PDouble &src, PObjectArray *objs) const { return 0; };
	virtual PObject *sub(const PInteger &src, PObjectArray *objs) const { return 0; };
	virtual PObject *sub(const PList &src, PObjectArray *objs) const { return 0; };
	virtual PObject *sub(const PArray &src, PObjectArray *objs) const { return 0; };

	virtual PObject *mul(const PObject &dst, PObjectArray *objs) const { return 0; };
	virtual PObject *mul(const PString &src, PObjectArray *objs) const { return 0; };
	virtual PObject *mul(const PDouble &src, PObjectArray *objs) const { return 0; };
	virtual PObject *mul(const PInteger &src, PObjectArray *objs) const { return 0; };
	virtual PObject *mul(const PList &src, PObjectArray *objs) const { return 0; };
	virtual PObject *mul(const PArray &src, PObjectArray *objs) const { return 0; };

	virtual PObject *div(const PObject &dst, PObjectArray *objs) const { return 0; };
	virtual PObject *div(const PString &src, PObjectArray *objs) const { return 0; };
	virtual PObject *div(const PDouble &src, PObjectArray *objs) const { return 0; };
	virtual PObject *div(const PInteger &src, PObjectArray *objs) const { return 0; };
	virtual PObject *div(const PList &src, PObjectArray *objs) const { return 0; };
	virtual PObject *div(const PArray &src, PObjectArray *objs) const { return 0; };

	virtual PObject *mod(const PObject &dst, PObjectArray *objs) const { return 0; };
	virtual PObject *mod(const PString &src, PObjectArray *objs) const { return 0; };
	virtual PObject *mod(const PDouble &src, PObjectArray *objs) const { return 0; };
	virtual PObject *mod(const PInteger &src, PObjectArray *objs) const { return 0; };
	virtual PObject *mod(const PList &src, PObjectArray *objs) const { return 0; };
	virtual PObject *mod(const PArray &src, PObjectArray *objs) const { return 0; };

	virtual bool cmp(const PObject &dst, int &result) const { return 0; };
	virtual bool cmp(const PString &src, int &result) const { return false; };
	virtual bool cmp(const PDouble &src, int &result) const { return false; };
	virtual bool cmp(const PInteger &src, int &result) const { return false; };
	virtual bool cmp(const PList &src, int &result) const { return false; };
	virtual bool cmp(const PArray &src, int &result) const { return false; };

	// デストラクタ
	virtual ~PObject() {} ;
};

class PNil : public PObject {
public:
	virtual bool isMyObject(char keychar) const { return false ;}
	virtual void recompile(ostream &s ) const { s << "NIL";  }

	// バイナリフォーマット
	virtual bool Bread(string &, PObjectArray *) { return true; };
	virtual bool Bwrite(string &buf) const {
	 		BinaryObjectFormat::make( buf, Bcode());
			return true; 
	};
	virtual int	 Bcode() const { return 100; }

	// JSONパース関係
	virtual bool isMyJsonHead(const string &src, size_t pos) const { 
		if ( pos + 4 < src.size() && memcmp( src.c_str() + pos, "null", 4) == 0 ) return true;
		return false;	
	};		// 文字からオブジェクトを決める
	virtual PObject *parseJson(const string &src, size_t &pos, PObjectArray *pobjs) { 
		pos += 4;
		return this; 
	};


	virtual PNil *clone(PObjectArray*) const;

	// ハッシュ値
	virtual PINTEGER chash() const { return -1; };
	virtual bool cmatch(const PObject *dst) const { 
		const PNil *d = dynamic_cast<const PNil *>(dst);
		if ( !d ) return false;
		return true;
	};

	virtual bool isc() const { return true; };
	// ユニフィケーション
	virtual bool unify(const PObject &goal, ExecContextRoot *c, VLocal *hlocal, VLocal	*glocal) const;
	virtual bool unify(const PNil &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const;
	virtual bool unify(const PList &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const;
	virtual bool unify(const PVeriable &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const;
	virtual bool unify(const PEVeriable &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const;

	// ユニフィケーション(no local)
	virtual bool unify(const PObject &goal, ExecContextRoot *c) const;
	virtual bool unify(const PNil &horn, ExecContextRoot *c) const;
	virtual bool unify(const PList &horn, ExecContextRoot *c) const;
	virtual bool unify(const PVeriable &horn, ExecContextRoot *c) const;
	virtual bool unify(const PEVeriable &horn, ExecContextRoot *c) const;

	// 変換して値を取得
	virtual bool cnv_string(string &value) const { return true; };

	virtual void cnv_json(string &value) const { value += "null"; };

	// ストリームへ出力
	virtual void print(FILE *out) const {
		fputs("NIL", out);
	};

	// メモリマネージャによるdelete 
	virtual void del();

	// デストラクタ
	virtual ~PNil() {}
};
EXTERN	PNil	pnil;

class PString : public PObject {
	friend class PMemoryManager;

public:
	string	value;
	PString() : value() {}
	explicit PString( const char *p) : value(p) {}
	explicit PString( const string &p) : value(p) {}
	explicit PString( string::const_iterator begin, string::const_iterator end) : value(begin,end) {}
	explicit PString( const PString &rhs) : value(rhs.value) {}

	virtual bool isMyObject(char keychar) const { return keychar == '"' || keychar == '\'' || keychar == ':';}
	virtual PObject *compile(CompileContext &c, bool);
	        PObject *compileSymbol(CompileContext &c);
	virtual void recompile( ostream &s ) const { 
		s << '\"';
		for ( string::const_iterator i = value.begin(); i < value.end(); i++ ) {
			if ( *i == '\\' || *i == '"' ) s << '\\';
			s << *i;
		}
		s << '\"';
	}

	// バイナリフォーマット
	virtual bool Bread(string &buf, PObjectArray *) { 
		value = buf;		
		return true;
	};
	virtual bool Bwrite(string &buf) const { 
		BinaryObjectFormat::make( buf, Bcode(), value);
		return true;
	};
	virtual int	 Bcode() const { return 130; }

	// JSONパース関係
	virtual bool isMyJsonHead(const string &src, size_t pos) const { 
		return src[pos] == '"';
	};		// 文字からオブジェクトを決める
	virtual PObject *parseJson(const string &src, size_t &pos, PObjectArray *pobjs);

	virtual PString *clone(PObjectArray *objs) const;

	// ハッシュ値
	virtual PINTEGER chash() const { 
		return string_hash(value);
	};

	virtual bool cmatch(const PObject *dst) const { 
		const PString *d = dynamic_cast<const PString *>(dst);
		if ( !d ) return false;
		if ( this == d ) return true;
		if ( value.compare( d->value) ) return false;
		return true;
	};

	virtual bool isc() const { return true; };

	// pridicate nameの取得（getPridicateNameで使用）
	virtual const string *getPredicateName(bool &docache, VLocal *hlocal) const { return &value; };

	// ユニフィケーション
	virtual bool unify(const PObject &goal, ExecContextRoot *c, VLocal *hlocal, VLocal	*glocal) const;
	virtual bool unify(const PString &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const;
	virtual bool unify(const PVeriable &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const;
	virtual bool unify(const PEVeriable &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const;

	// ユニフィケーション(no local)
	virtual bool unify(const PObject &goal, ExecContextRoot *c) const;
	virtual bool unify(const PString &horn, ExecContextRoot *c) const;
	virtual bool unify(const PVeriable &horn, ExecContextRoot *c) const;
	virtual bool unify(const PEVeriable &horn, ExecContextRoot *c) const;

	// 値の取得
	virtual const char *c_str() const { return value.c_str(); };

	// 変換して値を取得
	virtual bool cnv_string(string &value_) const { value_ += value; return true; };
	virtual bool cnv_double(double &value_) const { value_ = atof(value.c_str()); return true; };
	virtual bool cnv_integer(PINTEGER &value_) const { value_ = atoll(value.c_str()); return true; };
	virtual void cnv_csv(string &value_, char sep, char quote) const { 
		char checks[] = { '\r', '\n', sep, quote, '\0' };
		size_t pos = strcspn( value.c_str(), checks);
		size_t len = strlen( value.c_str());
		if ( value.c_str()[pos] == '\0' ) {
			value_ += value;
		} else {
			value_.push_back(quote);
			for ( string::const_iterator i = this->value.begin(); i < this->value.end(); i++ ) {
				value_.push_back(*i);
				if ( *i == quote ) {
					value_.push_back(quote);
				}
			}
			value_.push_back(quote);
		}
	};

	virtual void cnv_json( string &value_) const {
		str2json(value, value_);
	}

	// ストリームへ出力
	virtual void print(FILE *out) const {
		fwrite( value.c_str(), value.size(), 1, out);
	};


	// メモリマネージャによるdelete 
	virtual void del();

	// デストラクタ
	virtual ~PString() {}

	// Operator
	virtual PObject *add(const PObject &dst, PObjectArray *objs) const;
	virtual PObject *add(const PString &src, PObjectArray *objs) const;
	virtual PObject *sub(const PObject &dst, PObjectArray *objs) const;
	virtual PObject *mul(const PObject &dst, PObjectArray *objs) const;
	virtual PObject *div(const PObject &dst, PObjectArray *objs) const;
	virtual PObject *mod(const PObject &dst, PObjectArray *objs) const;
	virtual bool cmp(const PObject &dst, int &result) const;
	virtual bool cmp(const PString &src, int &result) const;
};

class PDouble : public PObject {
	friend class PMemoryManager;

public:
	double	value;

	explicit PDouble() : value(0) {}
	explicit PDouble( const PDouble &rhs) : value(rhs.value) {}
	explicit PDouble( const double rhs) : value(rhs) {}

	virtual bool isMyObject(char keychar) const {return isdigit(keychar) != 0 || keychar == '-';}
	virtual PObject *compile(CompileContext &c, bool);
	virtual void recompile(ostream &s ) const { s << value;  }

	// バイナリフォーマット
	virtual bool Bread(string &buf, PObjectArray *) { 
		value = atof( buf.c_str());
		return true;
	};
	virtual bool Bwrite(string &buf) const { 
		string str = cformat( "%.18e", value);
		BinaryObjectFormat::make( buf, Bcode(), str);
		return true;
	};
	virtual int	 Bcode() const { return 20; }

	
	// JSONパース関係
	virtual bool isMyJsonHead(const string &src, size_t pos) const { 
		return isdigit(src[pos]) != 0 || src[pos] == '-';
	};		// 文字からオブジェクトを決める
	virtual PObject *parseJson(const string &src, size_t &pos, PObjectArray *pobjs);
	
	virtual PDouble *clone(PObjectArray *objs) const;

	// ハッシュ値
	virtual PINTEGER chash() const { return (int)value; }

	virtual bool cmatch(const PObject *dst) const { 
		const PDouble *d = dynamic_cast<const PDouble *>(dst);
		if ( !d ) return false;
		if ( value != d->value ) return false;
		return true;
	};
		
	virtual bool isc() const { return true; };

	// ユニフィケーション
	virtual bool unify(const PObject &goal, ExecContextRoot *c, VLocal *hlocal, VLocal	*glocal) const;
	virtual bool unify(const PDouble &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const;
	virtual bool unify(const PInteger &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const;
	virtual bool unify(const PVeriable &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const;
	virtual bool unify(const PEVeriable &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const;

	// ユニフィケーション(no local)
	virtual bool unify(const PObject &goal, ExecContextRoot *c) const;
	virtual bool unify(const PDouble &horn, ExecContextRoot *c) const;
	virtual bool unify(const PInteger &horn, ExecContextRoot *c) const;
	virtual bool unify(const PVeriable &horn, ExecContextRoot *c) const;
	virtual bool unify(const PEVeriable &horn, ExecContextRoot *c) const;

	//値の取得
	virtual const double *c_double() const { return &value; };

	// 変換して値を取得
	virtual bool cnv_string(string &value_) const { 
		if ( fabs(value - (long)value) < DBL_EPSILON ) {
			cformat_cat(value_, "%.0f", value);
		} else {
			cformat_cat(value_, "%f", value);
		}
		return true;
	};
	virtual bool cnv_double(double &value_) const { value_ = value; return true; };
	virtual bool cnv_integer(PINTEGER &value_) const { value_ = (int)value; return true; };
	virtual void cnv_csv(string &value_, char sep, char quote) const { 
		cnv_string(value_);
	}
	
	virtual void cnv_json( string &value_) const {
		cnv_string(value_);
	}
	
	// ストリームへ出力
	virtual void print(FILE *out) const {
		fprintf( out, "%f", value);
	};

	// メモリマネージャによるdelete 
	virtual void del();

	// デストラクタ
	virtual ~PDouble() {}

	// Operator 
	virtual PObject *add(const PObject &dst, PObjectArray *objs) const;
	virtual PObject *add(const PDouble &src, PObjectArray *objs) const;
	virtual PObject *add(const PInteger &src, PObjectArray *objs) const;
	virtual PObject *sub(const PObject &dst, PObjectArray *objs) const;
	virtual PObject *sub(const PDouble &src, PObjectArray *objs) const;
	virtual PObject *sub(const PInteger &src, PObjectArray *objs) const;
	virtual PObject *mul(const PObject &dst, PObjectArray *objs) const;
	virtual PObject *mul(const PDouble &src, PObjectArray *objs) const;
	virtual PObject *mul(const PInteger &src, PObjectArray *objs) const;
	virtual PObject *div(const PObject &dst, PObjectArray *objs) const;
	virtual PObject *div(const PDouble &src, PObjectArray *objs) const;
	virtual PObject *div(const PInteger &src, PObjectArray *objs) const;
	virtual PObject *mod(const PObject &dst, PObjectArray *objs) const;
	virtual bool cmp(const PObject &dst, int &result) const;
	virtual bool cmp(const PDouble &src, int &result) const;
	virtual bool cmp(const PInteger &src, int &result) const;
};

class PInteger : public PObject {
	friend class PMemoryManager;
public:
	PINTEGER	value;

	explicit PInteger() : value(0) {}
	explicit PInteger( const PInteger &rhs) : value(rhs.value) {}
	explicit PInteger( const PINTEGER rhs) : value(rhs) {}

	virtual bool isMyObject(char keychar) const {return isdigit(keychar) != 0 || keychar == '-';}
	virtual void recompile(ostream &s ) const { s << value;  }

	// バイナリフォーマット
	virtual bool Bread(string &buf, PObjectArray *) { 
		value = BinaryObjectFormat::get_long_long(buf, 0);
		return true;
	};
	virtual bool Bwrite(string &buf) const { 
		string str;
		BinaryObjectFormat::put_long_long( str, value);
		BinaryObjectFormat::make( buf, Bcode(), str);
		return true;
	};
	virtual int	 Bcode() const { return 80; }

	// JSONパース関係
	virtual bool isMyJsonHead(const string &src, size_t pos) const { 
		if ( pos + 4 < src.size() && memcmp( src.c_str() + pos, "true", 4) == 0 ) return true;
		if ( pos + 5 < src.size() && memcmp( src.c_str() + pos, "false", 5) == 0 ) return true;
		return false;
	};
	virtual PObject *parseJson(const string &src, size_t &pos, PObjectArray *pobjs) { 
		if (  memcmp( src.c_str() + pos, "true", 4) == 0 ) {
			value = -1;
			pos += 4;
		} else if ( memcmp( src.c_str() + pos, "false", 5) == 0 ) {
			value = 0;
			pos += 5;
		}
		return this;
	};

	virtual PInteger *clone(PObjectArray *objs) const;

	// ハッシュ値
	virtual PINTEGER chash() const { return value; }

	virtual bool cmatch(const PObject *dst) const { 
		const PInteger *d = dynamic_cast<const PInteger *>(dst);
		if ( !d ) return false;
		if ( value != d->value ) return false;
		return true;
	};

	virtual bool isc() const { return true; };
	// ユニフィケーション
	virtual bool unify(const PObject &goal, ExecContextRoot *c, VLocal *hlocal, VLocal	*glocal) const;
	virtual bool unify(const PDouble &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const;
	virtual bool unify(const PInteger &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const;
	virtual bool unify(const PVeriable &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const;
	virtual bool unify(const PEVeriable &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const;

	// ユニフィケーション(no local)
	virtual bool unify(const PObject &goal, ExecContextRoot *c) const;
	virtual bool unify(const PDouble &horn, ExecContextRoot *c) const;
	virtual bool unify(const PInteger &horn, ExecContextRoot *c) const;
	virtual bool unify(const PVeriable &horn, ExecContextRoot *c) const;
	virtual bool unify(const PEVeriable &horn, ExecContextRoot *c) const;

	// 値の取得
	mutable PINTEGER32	value32;
	virtual const PINTEGER32 *c_integer32(ExecContextRoot *) const { 
		if ( value <= INT_MAX ) {
			value32 = (PINTEGER32)value; 
			return &value32;
		} else {
			return 0;
		}
	};
	virtual const PINTEGER *c_integer() const { return &value; };
	virtual const PINTEGER *c_integer(ExecContextRoot *) const { return &value; };

	// 変換して値を取得
	virtual bool NOALIAS_FUNC cnv_string(string &value_) const { 
		char buf[sizeof(PINTEGER)*3+1];
		int  idx = sizeof(buf) - 1;
		buf[idx] = '\0';
		PINTEGER v = value;
		if ( v < 0 ) {
			value_.push_back('-');
			v = -value;
		}

		do {
			buf[--idx] = v % 10 + '0';
			v = v / 10;
		} while ( v > 0 ); 
	
		value_ += buf + idx;
		return true;
	};
	virtual bool cnv_double(double &value_) const { value_ = static_cast<double>(value); return true; };
	virtual bool cnv_integer(PINTEGER &value_) const { value_ = value; return true; };
	virtual void cnv_csv(string &value_, char sep, char quote) const { 
		cnv_string(value_);
	}
	virtual void cnv_json( string &value_) const {
		cnv_string(value_);
	}
	
	// ストリームへ出力
	virtual void NOALIAS_FUNC print(FILE *out) const {
		char buf[sizeof(PINTEGER)*3+1];
		int  idx = sizeof(buf) - 1;
		buf[idx] = '\0';
		PINTEGER v = value;
		if ( value < 0 ) {
			v = -value;
		}
		do {
			buf[--idx] = v % 10 + '0';
			v = v / 10;
		} while ( v > 0 ); 
		if ( value < 0 ) {
			buf[--idx] = '-';
		}

		fputs( buf + idx, out);
	};

	// メモリマネージャによるdelete 
	virtual void del();

	// デストラクタ
	virtual ~PInteger() {}

	// Operator
	virtual PObject *add(const PObject &dst, PObjectArray *objs) const;
	virtual PObject *add(const PDouble &src, PObjectArray *objs) const;
	virtual PObject *add(const PInteger &src, PObjectArray *objs) const;
	virtual PObject *sub(const PObject &dst, PObjectArray *objs) const;
	virtual PObject *sub(const PDouble &src, PObjectArray *objs) const;
	virtual PObject *sub(const PInteger &src, PObjectArray *objs) const;
	virtual PObject *mul(const PObject &dst, PObjectArray *objs) const;
	virtual PObject *mul(const PDouble &src, PObjectArray *objs) const;
	virtual PObject *mul(const PInteger &src, PObjectArray *objs) const;
	virtual PObject *div(const PObject &dst, PObjectArray *objs) const;
	virtual PObject *div(const PDouble &src, PObjectArray *objs) const;
	virtual PObject *div(const PInteger &src, PObjectArray *objs) const;
	virtual PObject *mod(const PObject &dst, PObjectArray *objs) const;
	virtual PObject *mod(const PInteger &src, PObjectArray *objs) const;
	virtual bool cmp(const PObject &dst, int &result) const;
	virtual bool cmp(const PDouble &src, int &result) const;
	virtual bool cmp(const PInteger &src, int &result) const;
};
EXTERN	PInteger	pzero;
EXTERN	PInteger	ptrue;

class PList : public PObject {
	friend class PMemoryManager;
	PObject *lvalue;
	PObject *rvalue;
	bool	constant;
public:
	void init() { lvalue = &pnil; rvalue = &pnil; constant = false; }
	void init(const PList &rhs) { lvalue = rhs.lvalue; rvalue = rhs.rvalue; constant = rhs.constant; }
	void init(PObject *lvalue_, PObject *rvalue_) { lvalue = lvalue_; rvalue = rvalue_; constant = lvalue->isc() && rvalue->isc(); }
	void init(PObject *lvalue_, PObject *rvalue_, bool constant_) { lvalue = lvalue_; rvalue = rvalue_; constant = constant_; }
	explicit PList() { init(); };
	explicit PList( const PList &rhs) { init(rhs); }
	explicit PList( PObject *lvalue_, PObject *rvalue_) { init(lvalue_, rvalue_); }
	explicit PList( PObject *lvalue_, PObject *rvalue_, bool constant_) {init(lvalue_, rvalue_,constant_);}

	const PObject *lval() const { return lvalue; }
	const PObject *rval() const { return rvalue; }

	virtual bool isMyObject(char keychar) const { return keychar == '[' ? true : false;}
	virtual PObject *compile(CompileContext &c, bool funcflg);
	virtual void recompile(ostream &s) const { 
			s << '[';
			if ( lvalue != 0 && typeid(*lvalue) != typeid(PNil) ) lvalue->recompile(s);
			if ( rvalue != 0 ) {
				if ( typeid(*rvalue) == typeid(PNil) ) {
					;
				} else if ( typeid(*rvalue) == typeid(PList) ) {
					s << ',';
					dynamic_cast<const PList*>(rvalue)->recompile2(s);
				} else {
					s << '|';
					rvalue->recompile(s);
				}
			}
			s << ']';
		}
	void recompile2(ostream &s) const {
			if ( lvalue != 0 && typeid(*lvalue) != typeid(PNil) ) lvalue->recompile(s);
			if ( rvalue != 0 ) {
				if ( typeid(*rvalue) == typeid(PNil) ) {
					;
				} else if ( typeid(*rvalue) == typeid(PList) ) {
					s << ',';
					dynamic_cast<const PList*>(rvalue)->recompile2(s);
				} else {
					s << '|';
					rvalue->recompile(s);
				}
			}
		}

	// バイナリフォーマット
	virtual bool Bread(string &buf, PObjectArray *pobjs) { 
		constant = BinaryObjectFormat::get_bool(buf, 0);
		size_t pos = 1;
		lvalue = BinaryObjectFormat::readObject( buf, pobjs, pos);
		rvalue = BinaryObjectFormat::readObject( buf, pobjs, pos);
		if ( !lvalue || !rvalue ) return false;
		return true;
	};
	virtual bool Bwrite(string &buf) const { 
		// constant 1バイト
		// leftオブジェクト
		// rightオブジェクト
		string str;
		BinaryObjectFormat::put_bool( str, constant);
		bool ret = lvalue->Bwrite(str);
		ret &= rvalue->Bwrite(str);
		BinaryObjectFormat::make( buf, Bcode(), str);
		return ret;
	};
	virtual int	 Bcode() const { return 90; }


	virtual PList *clone(PObjectArray *objs) const;

	// ハッシュ値
	virtual PINTEGER chash() const { 
		PINTEGER h = 0; 
		if ( lvalue ) h += lvalue->chash();
		if ( rvalue ) h += rvalue->chash();
		return h;
	}

	virtual bool cmatch(const PObject *dst) const { 
		const PList *d = dynamic_cast<const PList *>(dst);
		if ( !d ) return false;
		if ( this == d ) return true;
		if ( !lvalue ) {
			if ( !d->lvalue ) return false;
		} else {
			if ( !d->lvalue ) {
				if ( !lvalue->cmatch(d->lvalue) ) return false;
			}
		}
		if ( !rvalue ) {
			if ( !d->rvalue ) return false;
		} else {
			if ( !d->rvalue ) {
				if ( !rvalue->cmatch(d->rvalue) ) return false;
			}
		}
		return true;
	};

	virtual bool isc() const { return constant; };

	// コレクションクラス？
	virtual bool iscollection() const { return true; };

	// ユニフィケーション
	virtual bool unify(const PObject &goal, ExecContextRoot *c, VLocal *hlocal, VLocal	*glocal) const;
	virtual bool unify(const PNil &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const;
	virtual bool unify(const PList &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const;
	virtual bool unify(const PVeriable &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const;
	virtual bool unify(const PEVeriable &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const;

	// ユニフィケーション(no local)
	virtual bool unify(const PObject &goal, ExecContextRoot *c) const;
	virtual bool unify(const PNil &horn, ExecContextRoot *c) const;
	virtual bool unify(const PList &horn, ExecContextRoot *c) const;
	virtual bool unify(const PVeriable &horn, ExecContextRoot *c) const;
	virtual bool unify(const PEVeriable &horn, ExecContextRoot *c) const;

	// 値の取得
	virtual const PObject *getval( ExecContextRoot *) const;
	virtual const PObject *getval( ExecContextRoot *c, VLocal *vlocal)  const;


	// 変換して値を取得
	virtual bool cnv_string(string &value) const { 
		value += '[';
		if ( lvalue != 0 && typeid(*lvalue) != typeid(PNil) ) {
			lvalue->cnv_string(value);
		}
		if ( rvalue != 0 ) {
			if ( typeid(*rvalue) == typeid(PNil) ) {
				;
			} else if ( typeid(*rvalue) == typeid(PList) ) {
				value += ',';
				dynamic_cast<const PList*>(rvalue)->cnv_string2(value);
			} else {
				value += '|';
				rvalue->cnv_string(value);
			}
		}
		value += "]";
		return true;
	};

	bool cnv_string2(string &value) const {
		if ( lvalue != 0 && typeid(*lvalue) != typeid(PNil) ) {
			lvalue->cnv_string(value);
		}
		if ( rvalue != 0 ) {
			if ( typeid(*rvalue) == typeid(PNil) ) {
				;
			} else if ( typeid(*rvalue) == typeid(PList) ) {
				value += ',';
				dynamic_cast<const PList*>(rvalue)->cnv_string2(value);
			} else {
				value += '|';
				rvalue->cnv_string(value);
			}
		}
		return true;
	};
	virtual void cnv_csv(string &value_, char sep, char quote) const { 
		cnv_string(value_);
	}

	// Operator
	virtual PObject *add(const PObject &dst, PObjectArray *objs) const;
	virtual PObject *add(const PList &src, PObjectArray *objs) const;
	virtual PObject *add(const PArray &src, PObjectArray *objs) const;
	virtual PObject *sub(const PObject &dst, PObjectArray *objs) const;
	virtual PObject *mul(const PObject &dst, PObjectArray *objs) const;
	virtual PObject *div(const PObject &dst, PObjectArray *objs) const;
	virtual PObject *mod(const PObject &dst, PObjectArray *objs) const;
	virtual bool cmp(const PObject &dst, int &result) const;

	// メモリマネージャによるdelete 
	virtual void del();

	// デストラクタ
	virtual ~PList() {}
};


class PArray : public PObject {
friend class PMemoryManager;
friend class PList;
friend class PPredicate;
public:
	PHashArrayMap	hamap;
private:
	bool			constant;
	bool			args;
public:
	bool			brace;
	PObjectArray	value;

	void init() { value.clear(), hamap.clear(), constant = true; args = false; brace = false; }
	void init( size_t	siz, PObject *o, bool brace_ = false) { value.assign(siz,o), hamap.clear(), constant = o->isc(); args = o->isargs(); brace = brace_; }
	void init( const PArray &rhs) { value = rhs.value; hamap = rhs.hamap; constant = rhs.constant; args = rhs.args; brace = rhs.brace; }
	void init( const PArray &rhs, size_t s, size_t e) {
		value.clear();
		constant = true;
		args = false;
		brace = false;
		value.reserve(e - s);
		for ( PObjectArray::const_iterator i = rhs.value.begin() + s; i < rhs.value.begin() + e; i++) {
			const PObject *p = *i;
			value.push_back(p);
			if ( p->label() ) hamap.insert( PHashArrayPair( p->label(), value.size() - 1) );
			constant = constant && p->isc();
			args = args || p->isargs();
		}
	}
	explicit PArray() {init();}
	explicit PArray( size_t	siz, PObject *o, bool brace_ = false) { init( siz, o,  brace_); }
	explicit PArray( const PArray &rhs) { init(rhs); }
	explicit PArray( const PArray &rhs, size_t s, size_t e) { init( rhs, s, e); }

	virtual bool isMyObject(char keychar) const { return keychar == '{' ? true : false;}
	virtual PObject *compile(CompileContext &c, bool funcflg);
	virtual void recompile(ostream &s) const { 
			s << ( !brace ? '(' : '{' );
			for ( PObjectArray::const_iterator i = value.begin(); i < value.end(); i++) {
				if ( i != this->value.begin() ) {
					s << ",";
				}
				if ( hamap.size() > 0 ) {
					for ( PHashArrayMap::const_iterator ki = hamap.begin(); ki != hamap.end(); ki++ ) {
						if ( ki->second == i - value.begin() ) {
							s << '"' << ki->first << '"' << "=>";
							break;
						}
					}
				}
				(*i)->recompile(s);
			}
			s << (!brace ? ')' : '}');
		}

	// バイナリフォーマット
	virtual bool Bread(string &buf, PObjectArray *pobjs) { 
		constant = BinaryObjectFormat::get_bool(buf, 0);
		args = BinaryObjectFormat::get_bool(buf, 1);
		brace = BinaryObjectFormat::get_bool(buf, 2);
		long long	hacnt = BinaryObjectFormat::get_long_long(buf, 3);
		size_t	pos = 11;
		for ( int i = 0; i < hacnt; i++ ) {
			string	key;
			BinaryObjectFormat::get_string(buf, pos, key);
			pos += 8 + key.size();
			long long	idx = BinaryObjectFormat::get_long_long(buf, pos);
			hamap[key] = (size_t)idx;
			pos += 8;
		}
		long long	objcnt = BinaryObjectFormat::get_long_long(buf, pos);
		pos += 8;
		for ( int i = 0; i < objcnt; i++ ) {
			const PObject *p = BinaryObjectFormat::readObject( buf, pobjs, pos);
			if ( p == 0 ) return false;
			value.push_back(p);
		}
		return true;
	};
	virtual bool Bwrite(string &buf) const { 
		bool ret = true;
		// constant 1バイト
		// args		1バイト
		// brace	1バイト
		// hamap
		// value
		string str;
		BinaryObjectFormat::put_bool( str, constant);
		BinaryObjectFormat::put_bool( str, args);
		BinaryObjectFormat::put_bool( str, brace);
		BinaryObjectFormat::put_long_long( str, hamap.size());
		for ( PHashArrayMap::const_iterator i = hamap.begin(); i != hamap.end(); i++ ) {
			BinaryObjectFormat::put_string( str, i->first);
			BinaryObjectFormat::put_long_long( str, i->second);
		}
		BinaryObjectFormat::put_long_long( str, value.size());
		for ( PObjectArray::const_iterator i = value.begin(); i < value.end(); i++ ) {
			(*i)->Bwrite(str);
		}

		BinaryObjectFormat::make( buf, Bcode(), str);
		return ret;
	};
	virtual int	 Bcode() const { return 10; }

	// JSONパース関係
	virtual bool isMyJsonHead(const string &src, size_t pos) const { 
		return src[pos] == '{' || src[pos] == '[';
	};		// 文字からオブジェクトを決める
	virtual PObject *parseJson(const string &src, size_t &pos, PObjectArray *pobjs);


	virtual PArray *clone(PObjectArray *objs) const;
	
	// ハッシュ値
	virtual PINTEGER chash() const { 
		PINTEGER h = 0; 
		for ( PObjectArray::const_iterator i = value.begin(); i < value.end(); i++ ) {
			h += (*i)->chash();
		}
		return h;
	}	

	virtual bool cmatch(const PObject *dst) const { 
		const PArray *d = dynamic_cast<const PArray *>(dst);
		if ( !d ) return false;
		if ( this == d ) return true;
		
		size_t	siz = value.size();
		if ( siz != d->value.size() ) return false;
		for (size_t i = 0; i < siz; i++ ) {
			if ( !value[i]->cmatch(d->value[i]) ) return false;
		}
		return true;
	};
	
	virtual bool isc() const { return constant; };

	// コレクションクラス？
	virtual bool iscollection() const { return true; }

	size_t size() const { return value.size(); }
	const PObject	*back() { return value.back(); }
	void push_back(const PObject *p) { value.push_back(p); }
	void push_back(const PObject *p, const string &label) { value.push_back(p); hamap[label] = value.size() - 1; }
	void insert_front(const PObject *p) { value.insert(value.begin(), p); }
	PObjectArray::const_iterator begin() const { return value.begin(); }
	PObjectArray::const_iterator end() const { return value.end(); }
	const PObject *front() const { return value.front(); }
	const PObject *back() const { return value.back(); }
	const PObject *operator [](const size_t idx) const { return value[idx]; }
	const PObject *operator [](const string &key) const { 
		PHashArrayMap::const_iterator hai = hamap.find(key);
		if ( hai != hamap.end() ) {
			return value[hai->second];
		} else {
			return &pnil;
		}
	}

	int find_key( const string &key ) const {
		PHashArrayMap::const_iterator hai = hamap.find(key);
		if ( hai != hamap.end() ) {
			return hai->second;
		}
		return -1;
	}
	
	int find_value( const string &fnd ) const {
		for ( size_t i = 0; i < value.size(); i++ ) {
			const PObject *dst =value[i];
			if ( dst->c_str() && strcmp( fnd.c_str(), dst->c_str()) == 0 ) return i;
		}
		return -1;
	}

	void set(size_t idx, const PObject *o, const string *label = 0) { 
		value[idx] = o;
		if ( label ) hamap[*label] = idx;
	}
	void clear() { value.clear(); constant = true; }

	// ユニフィケーション
	virtual bool unify(const PObject &goal, ExecContextRoot *c, VLocal *hlocal, VLocal	*glocal) const;
	virtual bool unify(const PNil &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const;
	virtual bool unify(const PArray &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const;
	virtual bool unify(const PVeriable &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const;
	virtual bool unify(const PEVeriable &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const;

	// ユニフィケーション(no local)
	virtual bool unify(const PObject &goal, ExecContextRoot *c) const;
	virtual bool unify(const PNil &horn, ExecContextRoot *c) const;
	virtual bool unify(const PArray &horn, ExecContextRoot *c) const;
	virtual bool unify(const PVeriable &horn, ExecContextRoot *c) const;
	virtual bool unify(const PEVeriable &horn, ExecContextRoot *c) const;

	// 値の取得
	virtual const PObject *getval( ExecContextRoot *c)  const;
	virtual const PObject *getval( ExecContextRoot *c, VLocal *vlocal)  const;

	// 変換して値を取得
	virtual bool cnv_string(string &value) const { 
		value += (!brace ? '(' : '{');
		for ( PObjectArray::const_iterator i = this->value.begin(); i < this->value.end(); i++) {
			if ( i != this->value.begin() ) {
				value += ", ";
			}
			if ( hamap.size() > 0 ) {
				for ( PHashArrayMap::const_iterator ki = hamap.begin(); ki != hamap.end(); ki++ ) {
					if ( ki->second == i - this->value.begin() ) {
						value += ki->first;
						value += " => ";
						break;
					}
				}
			}
			(*i)->cnv_string(value);
		}
		value += (!brace ? ')' : '}');
		return true;
	};
	virtual void cnv_csv(string &value_, char sep, char quote) const { 
		for ( PObjectArray::const_iterator i = this->value.begin(); i < this->value.end(); i++) {
			if ( i != this->value.begin() ) {
				value_ += sep;
			}
			(*i)->cnv_csv(value_,sep,quote);
		}
	}

	virtual void cnv_json(string &value_) const { 
		if ( hamap.empty() ) {
			// Array として変換
			value_.push_back('[');
			for ( PObjectArray::const_iterator i = this->value.begin(); i < this->value.end(); i++) {
				if ( i != this->value.begin() ) {
					value_ += ", ";
				}
				(*i)->cnv_json(value_);
			}
			value_.push_back(']');
		} else {
			value_.push_back('{');
			bool	flg = true;
			for ( PObjectArray::const_iterator i = this->value.begin(); i < this->value.end(); i++) {
				for ( PHashArrayMap::const_iterator ki = hamap.begin(); ki != hamap.end(); ki++ ) {
					if ( ki->second == i - this->value.begin() ) {
						if ( flg ) {
							flg = false;
						} else {
							value_ += ", ";
						}
						str2json( ki->first, value_);
						value_ += ":";
						value[ki->second]->cnv_json(value_);
						break;
					}
				}
			}
			value_.push_back('}');
		}
	}


	// Operator
	virtual PObject *add(const PObject &dst, PObjectArray *objs) const;
	virtual PObject *add(const PArray &src, PObjectArray *objs) const;
	virtual PObject *sub(const PObject &dst, PObjectArray *objs) const;
	virtual PObject *mul(const PObject &dst, PObjectArray *objs) const;
	virtual PObject *div(const PObject &dst, PObjectArray *objs) const;
	virtual PObject *mod(const PObject &dst, PObjectArray *objs) const;
	virtual bool cmp(const PObject &dst, int &result) const;

	// メモリマネージャによるdelete 
	virtual void del();

	// デストラクタ
	virtual ~PArray() {}
};


struct PredicateOption {
	bool	first_true;			// ~!,~+ firstの呼び出しは必ずtrueになる（!,+の時セット） 
	bool	backtrack_false;	// ~!,~? backtrackの呼び出しは必ずfalseになる(!,?の時セット） 
	bool	debug;				// ~d デバッグ指定（一部述語で対応）
	bool	result_array;		// @ trueの時、戻り値が配列になる 
	bool	cachable;			// $ trueの時、キャッシュ 
	bool	result_return;		// ? trueの時、評価結果を戻り値とする 
	bool	only_one_call;		// ! trueの時、バックトラック時に必ずfalseとなる
								// ※ ?,!を同時に指定できる。この場合、2回目は実行されない。

	void	clear() {
		first_true = false;
		backtrack_false = false;
		debug = false;
		result_array = false;
		cachable = false;
		result_return = false;
		only_one_call = false;
	}
};

class ExpressionCompileContext;
class PPredicate : public PObject {
	friend class PHorn;
	friend class PMemoryManager;
	friend class PGoal;
	friend class ExpressionCompileContext;
	friend struct ExecContextRoot;
	friend struct ExecContextBase;
public:
	string			nspace;		//  名前空間
	const PObject	*name;		// コンパイル時にPStringまたは、PVeriableに
	PArray			arglist;	// 引数リスト
	bool			constant;
	PredicateOption	opt;		// ポストフィックスオプション
	mutable ExecContext_Factory	*factory;	// ExecContext_Factoryへのポインタ
	mutable PHorns				*horns;		// 評価中のHornsへのポインタ
public:	
	void init() { nspace = ""; name = 0; arglist.clear(); constant = false; opt.clear(); factory = 0; horns = 0; }
	void init( const PPredicate &rhs) { nspace = ""; name = rhs.name; arglist = rhs.arglist; constant = rhs.constant; opt = rhs.opt; factory = 0; horns = 0; }	// 浅いコピー
	void init( const string &nspace_, const PObject *name_, const PArray *arglist_, const PredicateOption &opt_) { nspace = nspace_; name =name_; arglist = *arglist_; constant = name_->isc() && arglist_->isc(); opt = opt_; factory = 0; horns = 0; } 
	void init( const string &nspace_, PString *name_, PString *klass_, PString *message_, PString *where_) { // catch Predicate 元
		nspace = nspace_;
		name = name_;
		arglist.clear();
		constant = true;
		opt.clear();
		factory = 0;
		horns = 0;
		arglist.push_back(klass_);
		arglist.push_back(message_);
		arglist.push_back(where_);
	}

	explicit PPredicate() { init(); }
	explicit PPredicate( const PPredicate &rhs) { init(rhs); }
	explicit PPredicate( const string &nspace_, const PObject *name_, const PArray *arglist_, const PredicateOption &opt_) { init( nspace_, name_, arglist_, opt_); }
	explicit PPredicate( const string &nspace_, PString *name_, PString *klass_, PString *message_, PString *where_) { init( nspace_, name_, klass_, message_, where_); }
	bool	empty() const { return name == 0; };
	void	setName( PObject *v ) { name = v; };
	const PObject	&getName() const { return *name; };
	const PObject	*getNamePtr() const { return name; };
	bool	ncmp( const char *ptr) const { 
		if ( !name ) return false;
		const char *p = name->c_str();
		if ( p ) {
			return strcmp( p, ptr) == 0;
		}
		return false;
	};
	PObjectArray::const_iterator begin() const { return arglist.begin(); }
	PObjectArray::const_iterator end() const { return arglist.end(); }
	const PObject *front() const { return arglist.front(); };
	const PObject *back() const { return arglist.back(); };
	const PObject *operator [](size_t idx) const { return arglist[idx]; };
    size_t  size() const { return arglist.size(); }
	
	virtual bool isMyObject(char keychar) const {return isalpha(keychar) != 0 || keychar == '_' || keychar == '!' || keychar == '='; }	// ?? 変項と述語頭部の区別は終わりの(で行う？
	virtual PObject *compile(CompileContext &c, bool funcflg);
			PObject *compile(CompileContext &c, bool funcflg, const PObject *firstarg, const PObject *primaryarg);
			PObject *compilePredicate(CompileContext &c, bool funcflg, const PObject *firstarg, const PObject *primaryarg);
			bool compileName(CompileContext &c);
			bool compileArglist(CompileContext &c, char endlist = ')', bool ppflg = false);
			bool compilecode_argments(const string &code, CompileContext &c);
	virtual void recompile(ostream &s ) const { 
			if ( !nspace.empty() ) {
				s << nspace << "::";
			}

			if ( typeid(*name) == typeid(const PString) ) {
				s << dynamic_cast<const PString*>(name)->value;
			} else {
				name->recompile(s);
			}
			
			if ( opt.result_array ) {
				s << "@";
			}			
			if ( opt.cachable ) {
				s << "$";
			}

			if ( opt.first_true == true || opt.backtrack_false == true || opt.debug == true ) {
				s << "~";
			}
			if ( opt.debug == true ) {
				s << "d";
			}

			if ( opt.first_true == true && opt.backtrack_false == true ) {
				s << "!";
			} else if ( opt.first_true == false && opt.backtrack_false == true ) {
				s << "?";
			} else if ( opt.first_true == true && opt.backtrack_false == false ) {
				s << "+";
			} else if ( opt.first_true == false && opt.backtrack_false == false ) {
				// s << "*"; // default
			}

			arglist.recompile(s);
		}
	virtual PPredicate *clone(PObjectArray *objs) const;
	
	// ハッシュ値
	virtual PINTEGER chash() const { 
		PINTEGER h = 0; 
		if ( name ) h += name->chash();
		h += arglist.chash();
		return h;
	}	

	virtual bool cmatch(const PObject *dst) const { 
		const PPredicate *d = dynamic_cast<const PPredicate *>(dst);
		if ( !d ) return false;
		if ( this == d ) return true;

		if ( opt.result_array != d->opt.result_array ) return false;
		if ( !name->cmatch( d->name ) ) return false;
		if ( !arglist.cmatch( &d->arglist ) ) return false;

		return true;
	};


	virtual bool isc() const { return constant; };
	
	// pridicateの取得（upgoalで使用）
	virtual const PPredicate *getPredicate(VLocal *hlocal) const { return this; };
	
	// ユニフィケーション
	virtual bool unify(const PObject &goal, ExecContextRoot *c, VLocal *hlocal, VLocal	*glocal) const;
	virtual bool unify(const PPredicate &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const;
	virtual bool unify(const PVeriable &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const;
	virtual bool unify(const PEVeriable &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const;

	// ユニフィケーション(no local)
	virtual bool unify(const PObject &goal, ExecContextRoot *c) const;
	virtual bool unify(const PPredicate &horn, ExecContextRoot *c) const;
	virtual bool unify(const PVeriable &horn, ExecContextRoot *c) const;
	virtual bool unify(const PEVeriable &horn, ExecContextRoot *c) const;

	// 値の取得
	virtual const PObject *getval( ExecContextRoot *c) const;
	virtual const PObject *getval( ExecContextRoot *c, VLocal *vlocal) const;

	// メモリマネージャによるdelete 
	virtual void del();

	// デストラクタ
	virtual ~PPredicate() {}

	void make_code_onearg(const string &code, PObject *obj);
	void make_code_onearg(const string &code, const string &str);


	PObject *make3Operator(CompileContext &c, string ope, PObject *src1, PObject *src2, PObject *dst, bool funcflg);
	PObject *make3Operator(CompileContext &c, string ope, PObject *src1, PObject *src2, bool funcflg);
	PObject *make2Operator(CompileContext &c, string ope, PObject *src, PObject *dst, bool funcflg);
	PObject *make1Operator(CompileContext &c, string ope, PObject *src, bool funcflg);

	const PredicateOption &getOpt() const { return opt; };
};


class PVeriable : public PObject {
	friend class PMemoryManager;
	friend class PWildCard;
	friend class PEVeriable;
protected:
	string	name;
	bool	args;
public:
	size_t	idx;

public:
	PVeriable() : name(),idx(0), args(false) { --idx; }
	explicit PVeriable( const PVeriable &rhs) : name(rhs.name), idx(rhs.idx), args(rhs.args) {}
	
	virtual bool isMyObject(char keychar) const { return (keychar == '$' || keychar == '@' ) ? true : false;}
	virtual PObject *compile(CompileContext &c, bool);
			void makeVeriable(CompileContext &c, const string &name_, bool args = false);
			bool makeVeriable(CompileContext &c, const PObject *o, bool args = false);
			void addVary(CompileContext &c);
	virtual void recompile(ostream &s ) const { s << (args ? '@' : '$') << name;  }

	// バイナリフォーマット
	//virtual bool Bread(string &buf, PObjectArray &)
	virtual bool Bwrite(string &buf) const {
		return pnil.Bwrite(buf);	// Veriableの保存はpnilとする。
	}
	virtual int	 Bcode() const { return 140; }


	virtual PVeriable *clone(PObjectArray *objs) const;

	// ハッシュ値
	virtual PINTEGER chash() const { 
		return /*string_hash(name) + idx +*/ '$';
	};

	virtual bool cmatch(const PObject *dst) const { 
		return true;
	};

	virtual bool isc() const { return false; };

	// 変項の確認
	virtual bool isveriable() const { return true; };

	// 引数展開の確認
	virtual bool isargs() const { return args; };

	// pridicateの取得（upgoalで使用）
	virtual const PPredicate *getPredicate(VLocal *hlocal) const;

	// pridicate nameの取得（getPridicateNameで使用）
	virtual const string *getPredicateName(bool &docache, VLocal *hlocal) const;
	
	// ユニフィケーション
	virtual bool unify(const PObject &goal, ExecContextRoot *c, VLocal *hlocal, VLocal	*glocal) const;
	virtual bool unify(const PNil &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const;
	virtual bool unify(const PString &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const;
	virtual bool unify(const PDouble &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const;
	virtual bool unify(const PInteger &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const;
	virtual bool unify(const PList &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const;
	virtual bool unify(const PArray &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const;
	virtual bool unify(const PPredicate &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const;
	virtual bool unify(const PVeriable &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const;
	virtual bool unify(const PEVeriable &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const;

	// ユニフィケーション(no local)
	virtual bool unify(const PObject &goal, ExecContextRoot *c) const;
	virtual bool unify(const PNil &horn, ExecContextRoot *c) const;
	virtual bool unify(const PString &horn, ExecContextRoot *c) const;
	virtual bool unify(const PDouble &horn, ExecContextRoot *c) const;
	virtual bool unify(const PInteger &horn, ExecContextRoot *c) const;
	virtual bool unify(const PList &horn, ExecContextRoot *c) const;
	virtual bool unify(const PArray &horn, ExecContextRoot *c) const;
	virtual bool unify(const PPredicate &horn, ExecContextRoot *c) const;
	virtual bool unify(const PVeriable &horn, ExecContextRoot *c) const;
	virtual bool unify(const PEVeriable &horn, ExecContextRoot *c) const;

	// 変項のunify本体で使うテンプレート関数
	template <class T> bool vunify(const T &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const {
		const PObject *gitem =  (*glocal)[idx];
		if ( gitem == 0 ) {
			(*glocal)[idx] = &horn;
		} else {
			return gitem->unify( horn, c, glocal, hlocal);
		}
		return true;
	}

	// 変項のunify本体で使うテンプレート関数
	template <class T> bool vunify_getval(const T &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const {
		const PObject *gitem =  (*glocal)[idx];
		if ( gitem == 0 ) {
			(*glocal)[idx] = horn.getval(c, hlocal);
		} else {
			return gitem->unify( horn, c, glocal, hlocal);
		}
		return true;
	}

	// 値の取得
	virtual const PObject *getval( ExecContextRoot *c) const ;
	virtual const PObject *getval( ExecContextRoot *c, VLocal *vlocal) const ;
	// 値の取得
	virtual const PINTEGER32 *c_integer32(ExecContextRoot *c) const ;
	virtual const PINTEGER *c_integer(ExecContextRoot *c) const ;

	// ラベルの取得（変数の名前の取得：PArrayのハッシュで使用）
	virtual const char *label() const { return name.c_str(); };

	// メモリマネージャによるdelete 
	virtual void del();

	// デストラクタ
	virtual ~PVeriable() {}

	const string &getName() const { return name; }
	string &nameRef() { return name; }
};

class PWildCard : public PObject {
	bool	args;

public:
	PWildCard() : args(false) {}
	explicit PWildCard( const PVeriable &rhs) : args(rhs.args)  {}
	
	virtual bool isMyObject(char keychar) const { return false;}	// 変項の亜種として作成される
	virtual void recompile(ostream &s ) const { s << '$' ; }

	// バイナリフォーマット
	virtual bool Bread(string &buf, PObjectArray *) { 
		args = BinaryObjectFormat::get_bool(buf, 0);
		return true;
	};
	virtual bool Bwrite(string &buf) const { 
		// args 1 バイト
		string str;
		BinaryObjectFormat::put_bool( str, args);
		BinaryObjectFormat::make( buf, Bcode(), str);
		return true;
	};
	virtual int	 Bcode() const { return 150; }

	virtual PWildCard *clone(PObjectArray *objs) const ;

	// ハッシュ値
	virtual PINTEGER chash() const { 
		return '$';
	};
	
	virtual bool cmatch(const PObject *dst) const { 
		return true;
	};
	
	virtual bool isc() const { return false; };

	// 変項の確認
	virtual bool isveriable() const { return true; };

	// ユニフィケーション
	virtual bool unify(const PObject &goal, ExecContextRoot *c, VLocal *hlocal, VLocal	*glocal) const { return true; }
	virtual bool unify(const PNil &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const {	return true; }
	virtual bool unify(const PString &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const { return true;	}
	virtual bool unify(const PDouble &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal)  const { return true; }
	virtual bool unify(const PInteger &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal)  const { return true; }
	virtual bool unify(const PList &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const { return true; }
	virtual bool unify(const PArray &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const { return true; }
	virtual bool unify(const PPredicate &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const { return true; }
	virtual bool unify(const PVeriable &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const { return true; }
	virtual bool unify(const PWildCard &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const { return true; }
	virtual bool unify(const PEVeriable &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const{ return true; }

	// ユニフィケーション(no local)
	virtual bool unify(const PObject &goal, ExecContextRoot *c) const { return true; }
	virtual bool unify(const PNil &horn, ExecContextRoot *c) const {	return true; }
	virtual bool unify(const PString &horn, ExecContextRoot *c) const { return true;	}
	virtual bool unify(const PDouble &horn, ExecContextRoot *c)  const { return true; }
	virtual bool unify(const PInteger &horn, ExecContextRoot *c)  const { return true; }
	virtual bool unify(const PList &horn, ExecContextRoot *c) const { return true; }
	virtual bool unify(const PArray &horn, ExecContextRoot *c) const { return true; }
	virtual bool unify(const PPredicate &horn, ExecContextRoot *c) const { return true; }
	virtual bool unify(const PVeriable &horn, ExecContextRoot *c) const { return true; }
	virtual bool unify(const PWildCard &horn, ExecContextRoot *c) const { return true; }
	virtual bool unify(const PEVeriable &horn, ExecContextRoot *c) const{ return true; }

	// 値の取得
	// 代入

	// メモリマネージャによるdelete 
	virtual void del();

	// デストラクタ
	virtual ~PWildCard() {}
};
EXTERN	PWildCard	pwildcard;

class PEVeriable : public PObject {
	friend class PMemoryManager;
protected:
	string	name;
	bool	args;
public:
	size_t	idx;
	VLocal	*vl;

public:
	PEVeriable() : 	name(),idx(0), args(false), vl(0) { --idx;}

	void init( const PVeriable &rhs, VLocal *vl_) { name =rhs.name; idx = rhs.idx; args = rhs.args; vl = vl_; }
	void init( const PEVeriable &rhs) { name =rhs.name; idx = rhs.idx; args = rhs.args; vl = rhs.vl; }
	explicit PEVeriable( const PVeriable &rhs, VLocal *vl_) { init(rhs, vl_); }
	explicit PEVeriable( const PEVeriable &rhs) {init(rhs);}

	virtual int	 Bcode() const { return 30; }
	
	virtual bool isMyObject(char keychar) const { return false;} // 実行時にしか作成されない
	virtual void recompile(ostream &s ) const { s << '$' << name << "." << vl << "." << idx;  }
	virtual PEVeriable *clone(PObjectArray *objs) const ;

	// ハッシュ値
	virtual PINTEGER chash() const { 
		return /*string_hash(name) + idx + vidx + '$' +*/ '$';
	};

	virtual bool cmatch(const PObject *dst) const { 
		return true;
	};

	virtual bool isc() const { return false; };

	// 変項の確認
	virtual bool isveriable() const { return true; };

	// 引数展開の確認
	virtual bool isargs() const { return args; };
	
	// pridicateの取得（upgoalで使用）
	virtual const PPredicate *getPredicate(VLocal *hlocal) const;

	// pridicate nameの取得（getPridicateNameで使用）
	virtual const string *getPredicateName(bool &docache, VLocal *hlocal) const;
	
	// ユニフィケーション
	virtual bool unify(const PObject &goal, ExecContextRoot *c, VLocal *hlocal, VLocal	*glocal) const;
	virtual bool unify(const PNil &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const;
	virtual bool unify(const PString &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const;
	virtual bool unify(const PDouble &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const;
	virtual bool unify(const PInteger &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const;
	virtual bool unify(const PList &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const;
	virtual bool unify(const PArray &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const;
	virtual bool unify(const PPredicate &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const;
	virtual bool unify(const PVeriable &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const;
	virtual bool unify(const PEVeriable &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const;

	// ユニフィケーション(no local)
	virtual bool unify(const PObject &goal, ExecContextRoot *c) const;
	virtual bool unify(const PNil &horn, ExecContextRoot *c) const;
	virtual bool unify(const PString &horn, ExecContextRoot *c) const;
	virtual bool unify(const PDouble &horn, ExecContextRoot *c) const;
	virtual bool unify(const PInteger &horn, ExecContextRoot *c) const;
	virtual bool unify(const PList &horn, ExecContextRoot *c) const;
	virtual bool unify(const PArray &horn, ExecContextRoot *c) const;
	virtual bool unify(const PPredicate &horn, ExecContextRoot *c) const;
	virtual bool unify(const PVeriable &horn, ExecContextRoot *c) const;
	virtual bool unify(const PEVeriable &horn, ExecContextRoot *c) const;

	// 変項のunify本体で使うテンプレート関数
	template <class T> bool vunify(const T &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const;

	// 変項のunify本体で使うテンプレート関数
	template <class T> bool vunify_getval(const T &horn, ExecContextRoot *c, VLocal *glocal, VLocal *hlocal) const;

	// 値の取得
	virtual const PObject *getval( ExecContextRoot *c) const;
	virtual const PObject *getval( ExecContextRoot *c, VLocal *) const;
	// 値の取得
	virtual const PINTEGER32 *c_integer32(ExecContextRoot *c) const ;
	virtual const PINTEGER *c_integer(ExecContextRoot *c) const ;

	// メモリマネージャによるdelete 
	virtual void del();
	
	// デストラクタ
	virtual ~PEVeriable() {}
};


class PGoal : public PObject {
	friend class PMemoryManager;
	friend struct ExecContext;
	friend class PHorn;
	PObjectArray	body;
	bool			constant;
	bool			nobacktrack;	// バックトラックを受け付けない（ゴールの一番最後が!で終わっている）

public:
	PGoal() : body(), constant(false), nobacktrack(false) {}
	explicit PGoal( const PGoal &rhs) : body(rhs.body), constant(rhs.constant), nobacktrack(rhs.nobacktrack) {}

	virtual bool isMyObject(char keychar) const { return keychar == ',' ? true : false;}
	virtual PObject *compile(CompileContext &c, bool);
			void addBody(PObject *o) { body.push_back(o); }
			void compileOutcode_htmlescape(CompileContext &c);
			void compileOutcode_awpescape(CompileContext &c);
			void compileOutcode_raw(CompileContext &c);
			void compileOutcode_urlencode(CompileContext &c);
	virtual void recompile(ostream &s ) const { 
			for ( PObjectArray::const_iterator i = body.begin(); i < body.end(); i++ ) {
				s << ',';
				(*i)->recompile(s);
			}
			if ( nobacktrack ) {
				s << ",!";
			}
			s << ";";
		}
	virtual PGoal *clone(PObjectArray *objs) const;
	
	// ハッシュ値
	virtual PINTEGER chash() const { 
		PINTEGER h = 0;
		for ( PObjectArray::const_iterator i = body.begin(); i < body.end(); i++ ) {
			h += (*i)->chash();
		}
		return h;
	};
	
	virtual bool cmatch(const PObject *dst) const { 
		const PGoal *d = dynamic_cast<const PGoal *>(dst);
		if ( !d ) return false;
		if ( this == d ) return true;

		size_t siz = d->body.size();
		if ( siz != body.size() ) return false;
		for ( size_t i = 0; i < siz; i++ ) {
			if ( !body[i]->cmatch(d->body[i]) ) return false;
		}

		return true;
	};

	virtual bool isc() const { return constant; };

	// メモリマネージャによるdelete 
	virtual void del();

	virtual ~PGoal() {}

	const PObjectArray &getGoal() const { return body; }
	size_t	size() const { return body.size(); }
	bool	empty() const { return body.empty(); }
	const PObject *getPredicate( size_t idx) const { return body[idx]; }
	void	make_prt_code(const string &str);
};
typedef vector<PGoal *> PGoalsp;


class PHorn : public PObject {
	friend struct ExecContext;
	PPredicate	head;
	PGoal		body;
	size_t		vcnt;
	VNames		vnames;
	bool		constant;
public:
	PHorn() : head(), body(), vcnt(0), vnames(), constant(false) {}
	explicit PHorn( const PHorn &rhs) : head(rhs.head), body(rhs.body), vcnt(rhs.vcnt), vnames(rhs.vcnt), constant(rhs.constant) {}
	
	virtual bool isMyObject(char keychar) const {return keychar == '+' ? true : false;}
	virtual PObject *compile(CompileContext &c, bool);
	virtual void recompile(ostream &s ) const { 
			if ( !head.empty() ) {
				s << '+';
				head.recompile(s);
			}
			body.recompile(s);
		}
	virtual PHorn *clone(PObjectArray *objs) const;

	// ハッシュ値
	virtual PINTEGER chash() const { 
		return head.chash() + body.chash() + (int)vcnt;
	};

	virtual bool cmatch(const PObject *dst) const { 
		const PHorn *d = dynamic_cast<const PHorn *>(dst);
		if ( !d ) return false;
		if ( this == d ) return true;

		if ( vcnt != d->vcnt ) return false;
		if ( head.cmatch( &d->head ) ) return false;
		if ( body.cmatch( &d->body ) ) return false;

		return true;
	};

	virtual bool isc() const { return constant; };

	// メモリマネージャによるdelete 
	virtual void del();

	virtual ~PHorn() {}

	PPredicate &getHead() { return head; }
	PGoal &getGoal() { return body; }
	size_t	getVcnt() { return vcnt; }
	VNames &getVnames() { return vnames; }
	void setGoal( PGoal &goal_, VNames &vnames_ ) {
		body = goal_;
		vcnt = vnames_.size();
		vnames = vnames_;
		constant = goal_.isc();
	}
	bool upHorn( const PPredicate &goal, ExecContext &c, bool skipnamechk);
	bool headName( string &name) {
		const PObject *pobj = head.getNamePtr();
		return pobj != 0 && pobj->cnv_string(name);
	}
};

class PHorns : public PObject {
	vector<PHorn*>	horns;
	bool			constant;
public:	
	PHorns() : horns(), constant(true) {}
	explicit PHorns( const PHorns &rhs) : horns(rhs.horns), constant(rhs.constant) {}

	virtual bool isMyObject(char keychar) const {return keychar == '+' ? true : false;}
	virtual PObject *compile(CompileContext &c, bool); 
	virtual void recompile(ostream &s ) const { 
			for ( vector<PHorn*>::const_iterator i = horns.begin(); i < horns.end(); i++ ) {
				(*i)->recompile(s);
				s << endl;
			}
		}	
	virtual PHorns *clone(PObjectArray *objs) const;

	// ハッシュ値
	virtual PINTEGER chash() const { 
		PINTEGER h = 0;
		for ( vector<PHorn*>::const_iterator i = horns.begin(); i < horns.end(); i++ ) {
			h += (*i)->chash();
		}
		return h;
	};

	virtual bool cmatch(const PObject *dst) const { 
		const PHorns *d = dynamic_cast<const PHorns *>(dst);
		if ( !d ) return false;
		if ( this == d ) return true;

		size_t siz = d->horns.size();
		if ( siz != horns.size() ) return false;
		for ( size_t i = 0; i < siz; i++ ) {
			if ( !horns[i]->cmatch(d->horns[i]) ) return false;
		}

		return true;
	};

	virtual bool isc() const { return constant; };

	// メモリマネージャによるdelete 
	virtual void del();

	// デストラクタ
	virtual ~PHorns() {}

	void addHorn(PHorn *horn_);
	void addGoal(PGoal &goal_, VNames &vnames_);
	void erase( size_t i);
	void addPHorns(PHorns &horns_);
	size_t	size() { return horns.size(); }
	bool	empty() { return horns.empty(); }
	PHorn	&upHorn(size_t idx) { return *horns[idx]; }
};


class PHornBase : public PObject {
	map< string, PHorns*>	hornbase;
	bool					constant;
public:
	PHornBase() : hornbase(), constant(true) {}
	explicit PHornBase( const PHornBase &rhs) : hornbase(rhs.hornbase), constant(rhs.constant) {}

	virtual bool isMyObject(char keychar) const {return keychar == '+' ? true : false;}
	virtual PObject *compile(CompileContext &c, bool); 
	virtual void recompile(ostream &s ) const { 
			for ( map< string, PHorns*>::const_iterator i = hornbase.begin(); i != hornbase.end(); i++ ) {
				i->second->recompile(s);
			}
		}	
	virtual PHornBase *clone(PObjectArray *objs) const;

	// ハッシュ値
	virtual PINTEGER chash() const { 
		PINTEGER h = 0;

		for ( map< string, PHorns*>::const_iterator i = hornbase.begin(); i != hornbase.end(); i++ ) {
			h += i->second->chash();
		}
		return h;
	};
	
	virtual bool cmatch(const PObject *dst) const { 
		const PHornBase *d = dynamic_cast<const PHornBase *>(dst);
		if ( !d ) return false;
		if ( this == d ) return true;

		if ( hornbase.size() != d->hornbase.size() ) return false;

		for ( map< string, PHorns*>::const_iterator i = hornbase.begin(); i != hornbase.end(); i++ ) {
			map< string, PHorns*>::const_iterator f = d->hornbase.find(i->first);
			if ( f == d->hornbase.end() ) return false;
			if ( !i->second->cmatch(f->second) ) return false;
		}

		return true;
	};
	
	virtual bool isc() const { return constant; };

	// メモリマネージャによるdelete 
	virtual void del();

	// デストラクタ
	virtual ~PHornBase() {}

	size_t	size() { return hornbase.size(); }
	bool	empty() { return hornbase.empty(); }
	PHorns	*upHorns(const string &name) { 
		map<string,PHorns*>::iterator horns;
		if ( (horns = hornbase.find(name)) == hornbase.end() ) {
			return 0;
		}
		return horns->second;
	}
	
	void addPHornBase( const PHornBase &src );

};


// PObject管理
// 実行ファイルと同等の寿命を持つオブジェクトの管理を行う
// 名称を変えた方がよい？
class PObjectFactory {
	PObjectArray povec;			// コンパイル時に使用
	PObjectArray pobloadvec;	// bload時に使用
	PObjectArray ponews;		// newオブジェクト管理Array

public:
	PObjectFactory() {
		PNil	*pnil_ = new PNil();
		PString *pstring_ = new PString();
		PDouble *pdouble_ = new PDouble();
		PInteger *pinteger_ = new PInteger();
		PVeriable *pveriable_ = new PVeriable();
		PEVeriable *peveriable_ = new PEVeriable();
		PWildCard *pwildcard_ = new PWildCard();
		PList *plist_ = new PList();
		PArray *parray_ = new PArray();
		PPredicate *ppredicate_ = new PPredicate();
		PGoal *pgoal_ = new PGoal();
		PHorn *phorn_ = new PHorn();
		PHorns *phorns_ = new PHorns();

		povec.push_back(pnil_);
		povec.push_back(pstring_);
		povec.push_back(pdouble_);
		povec.push_back(pveriable_);
		povec.push_back(plist_);
		povec.push_back(parray_);
		povec.push_back(ppredicate_);
		povec.push_back(pgoal_);
		povec.push_back(phorn_);
		povec.push_back(phorns_ );

		pobloadvec.push_back(pnil_);
		pobloadvec.push_back(pstring_);
		pobloadvec.push_back(pdouble_);
		pobloadvec.push_back(pinteger_);
		pobloadvec.push_back(pveriable_);
		pobloadvec.push_back(peveriable_);
		pobloadvec.push_back(pwildcard_);
		pobloadvec.push_back(plist_);
		pobloadvec.push_back(parray_);
		pobloadvec.push_back(ppredicate_);
		pobloadvec.push_back(pgoal_);
		pobloadvec.push_back(phorn_);
		pobloadvec.push_back(phorns_ );
	}

	template < typename T >	T* createObject() {
		T* p = new T();
		ponews.push_back(p);
		return p;
	}

	PObject *createPObject( char c) {
		for ( PObjectArray::iterator i = povec.begin(); i < povec.end(); i++ ) {
			if ( (*i)->isMyObject(c) ) {
				PObject *p = (*i)->clone(&ponews);
				return p;
			}
		}
		return 0;
	}

	PObject *createPObjectBload( int code, PObjectArray *pobjs) {
		for ( PObjectArray::iterator i = pobloadvec.begin(); i < pobloadvec.end(); i++ ) {
			if ( code == (*i)->Bcode() ) {
				PObject *p = (*i)->clone(pobjs);
				return p;
			}
		}
		return 0;
	}

	PObject *createPObjectJSON( const string &src, size_t &pos, PObjectArray *pobjs ) {
		for ( PObjectArray::iterator i = pobloadvec.begin(); i < pobloadvec.end(); i++ ) {
			if ( (*i)->isMyJsonHead(src, pos) ) {
				PObject *p = (*i)->clone(pobjs);
				return p;
			}
		}
		return 0;
	}


	PObject *clone(PObject *src) {
		PObject *p = src->clone(&ponews);
		return p;
	}

	PObjectArray *pobjs() { return &ponews; };

	void DeleteObject(PObject *obj) {
		size_t siz = ponews.size();
		ponews.erase( remove( ponews.begin(), ponews.end(), obj), ponews.end());
		if ( siz != ponews.size() ) {
			delete obj;	// 削除リストにあったらdelete
		}
	}

	~PObjectFactory() {
		for_each(pobloadvec.begin(), pobloadvec.end(), MyDeleteObject());
		pobloadvec.clear();
		// for_each(povec.rbegin(), povec.rend(), MyDeleteObject()); // pobloadvecにあるオブジェクトを使っている為、このベクターでdeleteは不要
		povec.clear();
		for_each(ponews.begin(), ponews.end(), MyDeleteObject());
		ponews.clear();
	}
};

// PObject管理
// new・deleteを頻繁に行うオブジェクトの管理
class PMemoryManager {
	Array<PString*>		psvec;
	MyLockObject		slock;
	Array<PDouble*>		pdvec;
	MyLockObject		dlock;
	Array<PInteger*>	pivec;
	MyLockObject		ilock;
	Array<PList*>		plvec;
	MyLockObject		llock;
	Array<PArray*>		pavec;
	MyLockObject		alock;
	Array<PPredicate*>	ppvec;
	MyLockObject		plock;
//	Array<PVeriable*>	pvvec;
//	MyLockObject		vlock;
	Array<PEVeriable*>	pevec;
	MyLockObject		elock;
//	Array<PGoal*>		pgvec;
//	MyLockObject		glock;
public:
	PMemoryManager() {
		psvec.reserve(1024);
		pdvec.reserve(1024);
		pivec.reserve(1024);
		plvec.reserve(1024);
		pavec.reserve(1024);
		ppvec.reserve(1024);
	//	pvvec.reserve(1024);
		pevec.reserve(1024);
	//	pgvec.reserve(1024);
		InitMyLockObject( &slock);
		InitMyLockObject( &dlock);
		InitMyLockObject( &ilock);
		InitMyLockObject( &llock);
		InitMyLockObject( &alock);
		InitMyLockObject( &plock);
	//	InitMyLockObject( &vlock);
		InitMyLockObject( &elock);
	//	InitMyLockObject( &glock);
	}

	PString *newPString(PObjectArray *objs, const char *value) {
		MyLockSection lock(slock);
		PString *p;
		if ( !psvec.empty() ) {
			p = psvec.back();
			psvec.pop_back();
			p->value = value;
		} else {
			p = new PString(value);
		}
		objs->push_back(p);
		return p;
	}

	PString *newPString(PObjectArray *objs, const string &value) {
		MyLockSection lock(slock);
		PString *p;
		if ( !psvec.empty() ) {
			p = psvec.back();
			psvec.pop_back();
			p->value = value;
		} else {
			p = new PString(value);
		}
		objs->push_back(p);
		return p;
	}

	PString *newPString(PObjectArray *objs, string::const_iterator begin, string::const_iterator end) {
		MyLockSection lock(slock);
		PString *p;
		if ( !psvec.empty() ) {
			p = psvec.back();
			psvec.pop_back();
			p->value.assign( begin, end);
		} else {
			p = new PString( begin, end);
		}
		objs->push_back(p);
		return p;
	}

	PString *newPString(PObjectArray *objs, const PString &src) {
		MyLockSection lock(slock);
		PString *p;
		if ( !psvec.empty() ) {
			p = psvec.back();
			psvec.pop_back();
			p->value = src.value;
		} else {
			p = new PString(src);
		}
		objs->push_back(p);
		return p;
	}

	PDouble *newPDouble(PObjectArray *objs, double value) {
		MyLockSection lock(dlock);
		PDouble *p;
		if ( !pdvec.empty() ) {
			p = pdvec.back();
			pdvec.pop_back();
			p->value = value;
		} else {
			p = new PDouble(value);
		}
		objs->push_back(p);
		return p;
	}

	PDouble *newPDouble(PObjectArray *objs, const PDouble &src) {
		MyLockSection lock(dlock);
		PDouble *p;
		if ( !pdvec.empty() ) {
			p = pdvec.back();
			pdvec.pop_back();
			p->value = src.value;
		} else {
			p = new PDouble(src);
		}
		objs->push_back(p);
		return p;
	}

	PInteger *newPInteger(PObjectArray *objs, PINTEGER value) {
		MyLockSection lock(ilock);
		PInteger *p;
		if ( !pivec.empty() ) {
			p = pivec.back();
			pivec.pop_back();
			p->value = value;
		} else {
			p = new PInteger(value);
		}
		objs->push_back(p);
		return p;
	}

	PInteger *newPInteger(PObjectArray *objs, const PInteger &src) {
		MyLockSection lock(ilock);
		PInteger *p;
		if ( !pivec.empty() ) {
			p = pivec.back();
			pivec.pop_back();
			p->value = src.value;
		} else {
			p = new PInteger(src);
		}
		objs->push_back(p);
		return p;
	}
	
	PList *newPList(PObjectArray *objs, PObject *lvalue_, PObject *rvalue_) {
		MyLockSection lock(llock);
		PList *p;
		if ( !plvec.empty() ) {
			p = plvec.back();
			plvec.pop_back();
			p->init(lvalue_, rvalue_);
		} else {
			p = new PList(lvalue_, rvalue_);
		}
		objs->push_back(p);
		return p;
	}
	PList *newPList(PObjectArray *objs, PObject *lvalue_, PObject *rvalue_, bool constant_) {
		MyLockSection lock(llock);
		PList *p;
		if ( !plvec.empty() ) {
			p = plvec.back();
			plvec.pop_back();
			p->init(lvalue_, rvalue_, constant_);
		} else {
			p = new PList(lvalue_, rvalue_, constant_);
		}
		objs->push_back(p);
		return p;
	}
	PArray *newPArray(PObjectArray *objs) {
		MyLockSection lock(alock);
		PArray *p;
		if ( !pavec.empty() ) {
			p = pavec.back(); 
			pavec.pop_back(); 
			p->init();
		} else {
			p = new PArray();
		}
		objs->push_back(p);
		return p;
	}
	PArray *newPArray(PObjectArray *objs,  size_t	siz, PObject *o, bool brace_ = false) {
		MyLockSection lock(alock);
		PArray *p;
		if ( !pavec.empty() ) {
			p = pavec.back(); 
			pavec.pop_back(); 
			p->init(siz, o, brace_);
		} else {
			p = new PArray(siz, o, brace_);
		}
		objs->push_back(p);
		return p;
	}
	PArray *newPArray(PObjectArray *objs, const PArray &rhs) {
		MyLockSection lock(alock);
		PArray *p;
		if ( !pavec.empty() ) {
			p = pavec.back(); 
			pavec.pop_back(); 
			p->init(rhs);
		} else {
			p = new PArray(rhs);
		}
		objs->push_back(p);
		return p;
	}
	PArray *newPArray(PObjectArray *objs,  const PArray &rhs, size_t s, size_t e) {
		MyLockSection lock(alock);
		PArray *p;
		if ( !pavec.empty() ) {
			p = pavec.back(); 
			pavec.pop_back(); 
			p->init( rhs, s, e);
		} else {
			p = new PArray(rhs, s, e);
		}
		objs->push_back(p);
		return p;
	}	
	
	PPredicate *newPPredicate(PObjectArray *objs) {
		MyLockSection lock(plock);
		PPredicate *p;
		if ( !ppvec.empty() ) {
			p = ppvec.back(); 
			ppvec.pop_back(); 
			p->init();
		} else {
			p = new PPredicate();
		}
		objs->push_back(p);
		return p;
	}
	PPredicate *newPPredicate(PObjectArray *objs,const string &nspace_, const PObject *no, const PArray *ao, const PredicateOption &opt) {
		MyLockSection lock(plock);
		PPredicate *p;
		if ( !ppvec.empty() ) {
			p = ppvec.back(); 
			ppvec.pop_back(); 
			p->init( nspace_, no, ao, opt);
		} else {
			p = new PPredicate( nspace_, no, ao, opt);
		}
		objs->push_back(p);
		return p;
	}
	PPredicate *newPPredicate(PObjectArray *objs,const string &nspace_, PString *name_, PString *klass_, PString *message_, PString *where_) {
		MyLockSection lock(plock);
		PPredicate *p;
		if ( !ppvec.empty() ) {
			p = ppvec.back(); 
			ppvec.pop_back(); 
			p->init( nspace_, name_, klass_, message_, where_);
		} else {
			p = new PPredicate( nspace_, name_, klass_, message_, where_);
		}
		objs->push_back(p);
		return p;
	}

//	PVeriable *newPVeriable() {
//		MyLockSection lock(vlock);
//		if ( !pvvec.empty() ) {
//			PVeriable *p = pvvec.back(); pvvec.pop_back(); return p;
//		} else {
//			return new PVeriable();
//		}
//	}
	PEVeriable *newPEVeriable(PObjectArray *objs, const PVeriable &v, VLocal *vl_) {
		MyLockSection lock(elock);
		PEVeriable *p;
		if ( !pevec.empty() ) {
			p = pevec.back(); 
			pevec.pop_back(); 
			p->init( v, vl_);
		} else {
			p = new PEVeriable(v, vl_);
		}
		objs->push_back(p);
		return p;
	}
	PEVeriable *newPEVeriable(PObjectArray *objs, const PEVeriable &src) {
		MyLockSection lock(elock);
		PEVeriable *p;
		if ( !pevec.empty() ) {
			p = pevec.back(); 
			pevec.pop_back(); 
			p->init(src);
		} else {
			p = new PEVeriable(src);
		}
		objs->push_back(p);
		return p;
	}

//	PGoal *newPGoal() {
//		MyLockSection lock(glock);
//		if ( !pgvec.empty() ) {
//			PGoal *p = pgvec.back(); pgvec.pop_back(); return p;
//		} else {
//			return new PGoal();
//		}
//	}
	void mydelete(PString *p) { MyLockSection lock(slock); psvec.push_back(p); }
	void mydelete(PDouble *p) { MyLockSection lock(dlock); pdvec.push_back(p); }
	void mydelete(PInteger *p) { MyLockSection lock(ilock); pivec.push_back(p); }
	void mydelete(PList *p) { MyLockSection lock(llock); plvec.push_back(p); }
	void mydelete(PArray *p) { MyLockSection lock(alock); pavec.push_back(p); }
	void mydelete(PPredicate *p) { MyLockSection lock(plock); ppvec.push_back(p); }
//	void mydelete(PVeriable *p) { MyLockSection lock(vlock); pvvec.push_back(p); }
	void mydelete(PEVeriable *p) { MyLockSection lock(elock); pevec.push_back(p); }
//	void mydelete(PGoal *p) { MyLockSection lock(glock); pgvec.push_back(p); }

	~PMemoryManager() {
		if ( !psvec.empty() ) { /*cout << "ssize=" << psvec.size() << endl;*/ for_each(psvec.begin(), psvec.end(), MyDeleteObject()); psvec.clear(); }
		if ( !pdvec.empty() ) { /*cout << "dsize=" << pdvec.size() << endl;*/ for_each(pdvec.begin(), pdvec.end(), MyDeleteObject()); pdvec.clear(); }
		if ( !pivec.empty() ) { /*cout << "isize=" << pivec.size() << endl;*/ for_each(pivec.begin(), pivec.end(), MyDeleteObject()); pivec.clear(); }
		if ( !plvec.empty() ) { /*cout << "lsize=" << plvec.size() << endl;*/ for_each(plvec.begin(), plvec.end(), MyDeleteObject()); plvec.clear(); }
		if ( !pavec.empty() ) { /*cout << "asize=" << pavec.size() << endl;*/ for_each(pavec.begin(), pavec.end(), MyDeleteObject()); pavec.clear(); }
		if ( !ppvec.empty() ) { /*cout << "psize=" << ppvec.size() << endl;*/ for_each(ppvec.begin(), ppvec.end(), MyDeleteObject()); ppvec.clear(); }
//		if ( !pvvec.empty() ) { /*cout << "vsize=" << pvvec.size() << endl;*/ for_each(pvvec.begin(), pvvec.end(), MyDeleteObject()); pvvec.clear(); }
//		for ( Array<PEVeriable*>::iterator i = pevec.begin(); i < pevec.end(); i++ ) {
//			(*i)->recompile( cout); cout << endl;
//		}
		if ( !pevec.empty() ) { /*cout << "esize=" << pevec.size() << endl;*/ for_each(pevec.begin(), pevec.end(), MyDeleteObject()); pevec.clear(); }
//		if ( !pgvec.empty() ) { /*cout << "gsize=" << pgvec.size() << endl;*/ for_each(pgvec.begin(), pgvec.end(), MyDeleteObject()); pgvec.clear(); }

		DeleteMyLockObject( &slock);
		DeleteMyLockObject( &dlock);
		DeleteMyLockObject( &ilock);
		DeleteMyLockObject( &llock);
		DeleteMyLockObject( &alock);
		DeleteMyLockObject( &plock);
	//	DeleteMyLockObject( &vlock);
		DeleteMyLockObject( &elock);
	//	DeleteMyLockObject( &glock);

	}

	template< typename _T > static void del(PObjectArray *objs, const _T *obj) {
		if ( objs->back() == obj ) {
			 objs->pop_back(); 
		} else {
			objs->erase( remove( objs->begin(), objs->end(), obj), objs->end());
		}
		obj->del();
	}

};
extern PMemoryManager pmm;
// オブジェクトの破棄
struct PMMDeleteObject {
	void operator() (const PObject* obj) {
		const_cast<PObject*>(obj)->del();
	}
};

// オブジェクトの移動
struct MoveObject {
	PObjectArray &dst;
	MoveObject( PObjectArray &dst_) : dst(dst_) {}
	void operator() (const PObject* obj) {
		dst.push_back(obj);
	}
};

class CompileContext {
	vector<string>			s_filepath;
	vector<string>			s_fname;
	vector<string>			s_includedir;
	vector<string>			s_src;
	vector<size_t>			s_lcnt;
	vector<size_t>			s_ccnt;
	vector<size_t>			s_pos;

public:
	string						filepath;
	string						fname;
	string						includedir;
private:
	size_t						lcnt;
	size_t						plcnt;
	size_t						ccnt;
	size_t						pccnt;

	string						src;
	string::iterator			sin;
	bool						eofflg;

public:
	VNames						vary;
	bool						result;
	vector<string>				errmsg;
	PGoal						*goalcontext;	// 現在、コンパイル中のゴール節：式を処理する為に必要

	PPredicate					*p_head;		// 直前にコンパイルした述語ヘッド
	VNames						p_vary;			// その変数配列
	
	
public:
	CompileContext(const char *fpath, bool existchk) : 
		s_filepath(), s_fname(), s_includedir(), s_src(), s_lcnt(), s_ccnt(), s_pos(), 
		filepath(fpath), lcnt(1), plcnt(0), ccnt(1), pccnt(0), sin(), eofflg(false), vary(), result(true), errmsg(), goalcontext(0), p_head(0), p_vary() {

		eofflg = !open_file(fpath, existchk, "");
	} 

	CompileContext(const char *src_) : 
		s_filepath(), s_fname(), s_includedir(), s_src(), s_lcnt(), s_ccnt(), s_pos(), 
		filepath(""), lcnt(1), plcnt(0), ccnt(1), pccnt(0), sin(), eofflg(false), vary(), result(true), errmsg(), goalcontext(0), p_head(0), p_vary() {

		src = src_;
		sin = src.begin();
	} 


	void include_file(const char *fpath, bool existchk, const char *includedir_ ) {
		push_file();
		if ( !open_file( fpath, existchk, includedir_) ) {
			pop_file();
		}
	}

protected:
	void push_file() {
		s_filepath.push_back(filepath);
		s_fname.push_back(fname);
		s_includedir.push_back(includedir);
		s_src.push_back(src);
		s_lcnt.push_back(lcnt);
		s_ccnt.push_back(ccnt);
		s_pos.push_back(sin - src.begin());
		lcnt = 1;
		ccnt = 1;
	}
	
	void pop_file() {
		if ( eofflg || s_filepath.empty() ) {
			eofflg = true;
			return;
		}
		filepath = s_filepath.back();
		fname = s_fname.back();
		includedir = s_includedir.back();
		src = s_src.back();
		lcnt = s_lcnt.back();
		ccnt = s_ccnt.back();
		sin = src.begin() + s_pos.back();
		s_filepath.pop_back();
		s_fname.pop_back();
		s_includedir.pop_back();
		s_src.pop_back();
		s_lcnt.pop_back();
		s_ccnt.pop_back();
		s_pos.pop_back();
	}

	bool open_file(const char *fpath, bool existchk, const char *includedir_ ) {
		basic_ifstream<char> inputFile;

		includedir = includedir_;
		const char	*p = strrchr(fpath, '\\');
		if ( p != 0 ) {
			filepath = fpath;
			fname  = string( p + 1, /*fpath + */ strlen(fpath));	//	vine linux だとダメ？（要確認）
			inputFile.open(fpath, ios_base::in | ios::binary);
		} else {
			fname = filepath = fpath;
			inputFile.open(fpath, ios_base::in | ios::binary);
			// ファイルの存在確認
			if ( !inputFile.is_open() && strcmp( includedir_, "") != 0 ) {
				inputFile.clear();
				filepath = includedir;
				filepath += "\\";
				filepath += fpath;
				inputFile.open(filepath.c_str(), ios_base::in | ios::binary);
			}
		}
		// ファイルの存在確認
		if ( inputFile.is_open() ) {
			// 全て読み込む
			istreambuf_iterator<char> sin_(inputFile);
			string	text(sin_, istreambuf_iterator< char >());
			src = text;
			sin = src.begin();
			return true;
		} else if ( existchk ) {
			string errstr = cformat( "C0001: file not found '%s' ", fpath);
			err(errstr.c_str());
			inputFile.clear();
			return false;
		}
		return false;
	};

public:
	char operator *() { return *sin; }

	PObject *createObject(PObjectFactory &factory, bool errchk = true) {
		PObject *o = factory.createPObject(*sin);
		if ( o == 0 && errchk ) {
			string errstr = cformat( "C0002: unexpected charactor '%c' ", *sin);
			err(errstr.c_str());
			return 0;
		}
		return o;
	}

	void next() {
		next_noskip();
		skip();
	}

	void next_noskip() {
		if ( sin == src.end() ) {
			pop_file();
		}
		if ( eofflg ) return;
		if ( sin < src.end() ) {
			if ( *sin == '\n' ) { lcnt++; ccnt = 0; }
			sin++;
			ccnt++;
		}
		if ( sin >= src.end() ) {
			pop_file();
		}
	}

	void skip() {
		if ( sin == src.end() ) {
			pop_file();
		}
		if ( eofflg ) return;
		if ( *sin !=' ' && *sin !='\t' && *sin !='\r' && *sin !='\n' ) return;
		do {
			while ( !eofflg && (*sin==' ' || *sin=='\t' || *sin=='\r' || *sin=='\n') ) {
				next_noskip();
			}
			while ( !eofflg && *sin =='#' ) {
				newline();
			}
		} while ( !eofflg && (*sin==' ' || *sin=='\t' || *sin=='\r' || *sin=='\n') );
	}

	void newline() { // comment
		while ( !eofflg && *sin != '\n' ) {
			next_noskip();
		}
		while ( !eofflg && (*sin == '\r' || *sin == '\n') ) {
			next_noskip();
		}
	}

	void push_back() {
		if ( sin > src.begin() ) {
			--sin;
			--ccnt;
		}
	}


	bool eof() {
		return eofflg;
	}

	void err( const char *msg) {
		if ( lcnt == plcnt && ccnt == pccnt ) {	// 同じ所でエラーとなっている
			next();
			return;
		}
		plcnt = lcnt; 
		pccnt = ccnt;
		result = false;
		string fmsg = cformat( "%s(%d,%d):%s", fname.c_str(), lcnt, ccnt, msg);
		errmsg.push_back(fmsg);
	}

	void err( const string msg) {
		err(msg.c_str());
	}

};

class BackupGoalContext {
	CompileContext &backup_c;
	PGoal	*backup;
public:
	BackupGoalContext(CompileContext &c, PGoal *newone) : backup_c(c){
		backup = backup_c.goalcontext;
		backup_c.goalcontext = newone;
	}
	~BackupGoalContext() { 
		backup_c.goalcontext = backup;
	}
};

struct ExpressionTree {
	string			op;
	PObject			*obj;	// これが0以外なら終端（以下の２つは0のはず）
	ExpressionTree	*left;
	ExpressionTree	*right;
public:
	ExpressionTree(	string &op_, ExpressionTree *left_, ExpressionTree *right_) : op(op_), obj(0), left(left_), right(right_) {};
	ExpressionTree(	PObject *obj_) : op(), obj(obj_), left(0), right(0) {};
};

class ExpressionCompileContext {
	vector<ExpressionTree*>	objs;
	string					termchar;
public:
	ExpressionCompileContext(const char termchar_) : objs(), termchar() { termchar.push_back(termchar_);};
	ExpressionCompileContext(const char *termchar_) : objs(), termchar(termchar_) {};

	ExpressionTree *newExpressionTree(string &op_, ExpressionTree *left_ = 0, ExpressionTree *right_ = 0) { 
		ExpressionTree *et = new ExpressionTree(op_, left_, right_);
		objs.push_back(et);
		return et;
	}
	ExpressionTree *newExpressionTree( PObject *obj_) {
		ExpressionTree *et = new ExpressionTree(obj_);
		objs.push_back(et);
		return et;
	}

	bool getOperatorUnary(CompileContext &c, string &ope) {
		// 単項演算子の - * /
		if ( *c == '-' ) {
			c.next_noskip();
			if ( isdigit(*c) != 0 ) {	// 数値が続く場合、数値のマイナスとして扱う 
				c.push_back();
				return false;
			}
			ope.clear();
			ope.push_back('-');
			c.skip();
			return true;
		} else if ( *c == '~' ) { // bit not　
			c.next_noskip();
			ope.clear();
			ope.push_back('~');
			c.skip();
			return true;
		}
		
		return false;
	}

	bool getOperatorMul(CompileContext &c, string &ope) {
		// * /
		// % (%>はダメ）
		if ( *c != '*' && *c != '/' && *c != '%' ) return false;
		string str;
		str.push_back(*c);
		
		c.next_noskip();
		if ( str[0] == '%' && *c =='>' ) { // %> 
			c.push_back();
			return false;
		} else if ( *c == '=' ) {	//  assigment operators  
			c.push_back();
			return false;
		}
		c.skip();
		ope = str;
		return true;
	}

	bool getOperatorAdd(CompileContext &c, string &ope) {
		// + -
		if ( *c != '+' && *c != '-' ) return false;
		string str;
		str.push_back(*c);
		
		c.next_noskip();
		if ( *c == '=' ) {	//  assigment operators  
			c.push_back();
			return false;
		}
		c.skip();
		ope = str;
		return true;
	}

	bool getOperatorCMP(CompileContext &c, string &ope) {
		// < <=
		// > >=
		// == (=はダメ）
		// != (!はダメ）
		// <>
		if ( *c != '<' && *c != '>' && *c != '=' && *c != '!' ) return false;
		string str;
		str.push_back(*c);
		
		c.next_noskip();
		if ( *c =='=' ) {
			str.push_back(*c);
			c.next();
		} else if ( str[0] == '<' && *c == '>' ) {
			str.push_back(*c);
			c.next();
		} else if ( str[0] == '=' || str[0] == '!' ) {
			c.push_back();
			return false;
		} else { //str[0] == '<' || str[0] == '>'
			c.skip();
		}
		ope = str;
		return true;
	}

	bool getOperatorAND(CompileContext &c, string &ope) {
		if ( *c != '&' ) return false;
		string str;
		str.push_back(*c);
		
		c.next_noskip();
		if ( *c == '=' ) {	//  assigment operators  
			c.push_back();
			return false;
		}
		c.skip();
		ope = str;
		return true;
	}
	
	bool getOperatorXOR(CompileContext &c, string &ope) {
		if ( *c != '^' ) return false;
		string str;
		str.push_back(*c);
		
		c.next_noskip();
		if ( *c == '=' ) {	//  assigment operators  
			c.push_back();
			return false;
		}
		c.skip();
		ope = str;
		return true;
	}

	bool getOperatorOR(CompileContext &c, string &ope) {
		if ( *c != '|' ) return false;
		string str;
		str.push_back(*c);
		
		c.next_noskip();
		if ( *c == '=' ) {	//  assigment operators  
			c.push_back();
			return false;
		}
		c.skip();
		ope = str;
		return true;
	}


	bool getOperatorLET(CompileContext &c, string &ope) {
		// += -= *= /= %= 
		// &= ^= |= 
		if ( *c != '=' && *c != '+' && *c != '-' &&  *c != '*' && *c != '/' && *c != '%'  && 
			 *c != '&' && *c != '^' && *c != '|'  ) return false;
		string str;
		str.push_back(*c);

		c.next_noskip();
		if ( str[0] == '=' ) {
			// =の場合、== と => はダメ 
			if  (*c == '=' || *c == '>') { 
				c.push_back(); 
				return false;
			}
		} else { 
			// =以外の場合、+= 等でないとダメ  
			if  (*c != '=' ) { 
				c.push_back(); 
				return false;
			}
			str.push_back(*c);
		} 
		c.skip();
		ope = str;
		return true;
	}

	ExpressionTree *makeExpressionTree_Term(CompileContext &c, bool &funcflg);
	ExpressionTree *makeExpressionTree_unary(CompileContext &c, bool &funcflg);
	ExpressionTree *makeExpressionTree_mul(CompileContext &c, bool &funcflg);
	ExpressionTree *makeExpressionTree_add(CompileContext &c, bool &funcflg);
	ExpressionTree *makeExpressionTree_cmp(CompileContext &c, bool &funcflg);
	ExpressionTree *makeExpressionTree_and(CompileContext &c, bool &funcflg);
	ExpressionTree *makeExpressionTree_xor(CompileContext &c, bool &funcflg);
	ExpressionTree *makeExpressionTree_or(CompileContext &c, bool &funcflg);
	ExpressionTree *makeExpressionTree(CompileContext &c, bool funcflg);
	PObject *makeCode(CompileContext &c, ExpressionTree *exp, PObject *dst);
	PObject *compileExpression(CompileContext &c, bool funcflg);
	~ExpressionCompileContext()	{
		for_each( objs.rbegin(), objs.rend(), MyDeleteObject());
	}
};

#endif
