/*
 *	joytoy.h
 *
 *	JoyToyインタプリタ
 *
 *	* Sun Jan 01 00:00:00 JST 2006 Naoyuki Sawa
 *	- 作成開始。
 *	* Tue Jan 31 00:00:00 JST 2006 Naoyuki Sawa
 *	- 1st リリース。
 *	* Tue Nov 07 13:20:17 JST 2006 Naoyuki Sawa
 *	- 全モジュールにおいて、clipmisc.hのARRAY→LIST名前変更に追従しました。
 */
#ifndef __JOYTOY_H__
#define __JOYTOY_H__

/*****************************************************************************
 *	
 *****************************************************************************/

/* NOTE: INTERFACE_MAP[]の定義を、static配列でなくグローバル配列としている理由:
 *
 *	Visual C++ 6.0は、static配列を前方参照するための、配列宣言ができません。
 *
 *		<例> --- GCCはOK、Visual C++ 6.0はエラー ---
 *			static int array[]; // 宣言
 *			void foo() {
 *				// array[]を使う処理
 *			}
 *			static int array[] = { ... }; // 定義
 *
 *	上のコードは、P/ECE開発環境のGCCならば問題なくコンパイルできるのですが、
 *	Visual C++ 6.0では、エラーになってしまいます。
 *
 *	Visual C++ 6.0で、static配列宣言を行うには、宣言時に"static"を指定せず、
 *	定義時にのみ"static"を指定すれば良いみたいです。(実験より)
 *
 *		<例> --- Visual C++ 6.0はOK、GCCはエラー ---
 *			int array[]; // 宣言
 *			void foo() {
 *				// array[]を使う処理
 *			}
 *			static int array[] = { ... }; // 定義
 *
 *	しかし、この方法は、GCCでエラーになってしまいます。
 *
 *	結局、Visual C++ 6,0とGCCの、両方のコンパイラでコンパイルするためには、
 *	static配列でなく、グローバル配列を用いる方法しか無いみたいです。
 *
 *		<例> --- GCC、Visual C++ 6.0、どちでもOK ---
 *			extern int array[]; // 宣言
 *			void foo() {
 *				// array[]を使う処理
 *			}
 *			int array[] = { ... }; // 定義
 */
#define IMPLEMENT_UNKNOWN_INTERFACE_METHODS(CC, cc, II, ii)		\
static void* ii##_query_interface(II##_INTERFACE** intf, int id) {	\
	CC##* this = CONTAINING_RECORD(intf, CC, ii##_interface);	\
	          extern const INTERFACE_MAP cc##_interface_map[];	\
	return query_interface_map(this, id, cc##_interface_map);	\
}									\
static void ii##_addref(II##_INTERFACE** intf) {			\
	CC##* this = CONTAINING_RECORD(intf, CC, ii##_interface);	\
	this->refcnt++;							\
}									\
static void ii##_release(II##_INTERFACE** intf) {			\
	CC##* this = CONTAINING_RECORD(intf, CC, ii##_interface);	\
	if(!--this->refcnt) { static void cc##_delete(CC* this);	\
	                                  cc##_delete(    this); }	\
}

/* リスト情報と、マップ情報のうち、使用頻度の高いものを、共通で定義することにします。
 * 使用頻度の低いものは、その都度、定義してください。
 */
extern const LIST_INFO ptr_list_info;			/* LIST<void*> */
extern const LIST_INFO jtcode_list_info;		/* LIST<JTCODE_INTERFACE**> */
extern const LIST_INFO jtsymbol_list_info;		/* LIST<JTSYMBOL_INTERFACE**> */
extern const MAP_INFO str_to_int_map_info;		/* MAP<char*,int> */
extern const MAP_INFO jtsymbol_to_jtcode_map_info;	/* MAP<JTSYMBOL_INTERFACE**,JTCODE_INTERFACE**> */

/*****************************************************************************
 *	STRING_BUFFER
 *****************************************************************************/

/* 変更可能な文字列を表すインターフェイスです。
 */
DEFINE_INTERFACE(STRING_BUFFER_INTERFACE, 1134015322/*2005/12/08 13:15:22*/,

	/* 文字列バッファを空の文字列にします。
	 */
	void (*empty)(STRING_BUFFER_INTERFACE** intf);

	/* 文字列バッファに文字を追加します。
	 * [in]
	 *	str		追加する文字列。
	 */
	void (*append_char)(STRING_BUFFER_INTERFACE** intf, int c);

	/* 文字列バッファに文字列を追加します。
	 * [in]
	 *	str		追加する文字列。
	 */
	void (*append_string)(STRING_BUFFER_INTERFACE** intf, const char* str);

	/* 文字列バッファの直接操作を開始します。
	 * [in]
	 *	min_len		文字列バッファの最小の長さ(文字数)。終端文字(nul)は含みません。
	 * [out]
	 *	戻り値		文字列バッファへのポインタ。
	 * [note]
	 *	* 現在の文字列長とmin_lenの大小により、以下のような動作を行います。
	 *	- 現在の文字列長がmin_len以上の場合は、現在の文字列バッファをそのまま返します。
	 *	- 現在の文字列長がmin_len未満の場合は、文字列バッファを(min_len+1)に拡張します。
	 *	  その後、呼び出し元に、拡張した文字列バッファを返します。
	 *	  拡張した文字列バッファの先頭部分は、(現在の文字列内容+'\0')を維持しています。
	 *	* 文字列バッファの直接操作が完了したら、unlock()を呼び出して変更を確定してください。
	 *	  文字列バッファの内容を変更しなかった場合に限り、unlock()の呼び出しを省略できます。
	 *	  文字列バッファの参照のために本関数を呼び出す場合は、min_len=0としてください。
	 */
	char* (*lock)(STRING_BUFFER_INTERFACE** intf, int min_len);

	/* 文字列バッファの直接操作を終了します。
	 * [in]
	 *	new_len		文字列バッファ内の文字列の長さ(文字数)。終端文字(nul)は含みません。
	 *			文字列がnulで終わる場合は、-1を指定すると、実際の長さを用います。
	 * [note]
	 *	* 文字列バッファ内の文字列がnulで終わらない場合は、new_lenを明示する必要があります。
	 *	* unlock()を呼び出すと、直前のlock()で得たポインタが無効になります。
	 */
	void (*unlock)(STRING_BUFFER_INTERFACE** intf, int new_len);
);

#define IMPLEMENT_STRING_BUFFER_INTERFACE(CC, cc)						\
IMPLEMENT_UNKNOWN_INTERFACE_METHODS(CC, cc, STRING_BUFFER, string_buffer)			\
static void string_buffer_empty(STRING_BUFFER_INTERFACE** intf);				\
static void string_buffer_append_char(STRING_BUFFER_INTERFACE** intf, int c);			\
static void string_buffer_append_string(STRING_BUFFER_INTERFACE** intf, const char* str);	\
static char* string_buffer_lock(STRING_BUFFER_INTERFACE** intf, int min_len);			\
static void string_buffer_unlock(STRING_BUFFER_INTERFACE** intf, int new_len);			\
static STRING_BUFFER_INTERFACE string_buffer_interface = {					\
	string_buffer_query_interface,								\
	string_buffer_addref,									\
	string_buffer_release,									\
	string_buffer_empty,									\
	string_buffer_append_char,								\
	string_buffer_append_string,								\
	string_buffer_lock,									\
	string_buffer_unlock,									\
};

/*--------------------------------------------------------------------------*/

/* 文字列バッファオブジェクトを作成します。
 * [note]
 *	* 文字列バッファオブジェクトの初期状態は、空の文字列です。
 */
STRING_BUFFER_INTERFACE** string_buffer_create();

/*****************************************************************************
 *	JTCODE
 *****************************************************************************/

/* 構文解析器(Parser)が読み込む、コードを表すインターフェイスです。
 */
DEFINE_INTERFACE(JTCODE_INTERFACE, 1133690556/*2005/12/04 19:02:36*/,

	/* コードを実行します。
	 * [out]
	 *	戻り値		コードの実行結果を表す値。
	 *			実行結果の無いコードは、NULLを返す場合もあります。
	 * [note]
	 *	* インタプリタの動作は、概ね、以下のようになります。
	 *	  1 . Parserがプログラムの一部を読み込み、その部分に対応するコードを作成する。
	 *	  2a. 一般的な文の場合は、ただちにそのコードを実行する。
	 *	  2b. または、if()やwhile()のBodyに相当するコードの場合は、条件に従って実行する。
	 *	  2c. または、関数のBodyに相当するコードの場合は、関数が呼ばれたときに実行する。
	 */
	JTCODE_INTERFACE** (*run)(JTCODE_INTERFACE** intf);
);

#define IMPLEMENT_JTCODE_INTERFACE(CC, cc)			\
IMPLEMENT_UNKNOWN_INTERFACE_METHODS(CC, cc, JTCODE, jtcode)	\
static JTCODE_INTERFACE** jtcode_run(JTCODE_INTERFACE** intf);	\
static JTCODE_INTERFACE jtcode_interface = {			\
	jtcode_query_interface,					\
	jtcode_addref,						\
	jtcode_release,						\
	jtcode_run,						\
};

/*****************************************************************************
 *	TOKEN
 *****************************************************************************/

/* TOKEN_INTERFACE::get_type()で返される、トークンのタイプを表す値です。
 * - 予約語シンボルテーブルは、joytoy.cの中のinit_reserved()で作成しています。
 */
enum {
	/* 0〜255 */		/* a,+,<,etc...	code = NULL, type = 文字コード */
	/*    256 */		/* (欠番) */
	TOKEN_TYPE_INT = 257,	/* 123		code = jtint_create() */
	TOKEN_TYPE_STRING,	/* "abc"	code = jtstring_create() */
	TOKEN_TYPE_SYMBOL,	/* abc		code = jtsymbol_intern() */
	TOKEN_TYPE_TRUE,	/* true		code = NULL */
	TOKEN_TYPE_FALSE,	/* false	code = NULL */
	TOKEN_TYPE_EQ,		/* ==		code = NULL */
	TOKEN_TYPE_NE,		/* !=		code = NULL */
	TOKEN_TYPE_LE,		/* <=		code = NULL */
	TOKEN_TYPE_GE,		/* >=		code = NULL */
	TOKEN_TYPE_AND,		/* &&		code = NULL */
	TOKEN_TYPE_OR,		/* ||		code = NULL */
	TOKEN_TYPE_IF,		/* if		code = NULL */
	TOKEN_TYPE_ELSE,	/* else		code = NULL */
	TOKEN_TYPE_WHILE,	/* while	code = NULL */
	TOKEN_TYPE_FUN,		/* fun		code = NULL */
	TOKEN_TYPE_VAR,		/* var		code = NULL */
	TOKEN_TYPE_OBJECT,	/* object	code = NULL */
	TOKEN_TYPE_NEW,		/* new		code = NULL */
	/* TODO: トークンのタイプが増えたら、ここに追加してください。 */
};

/* 字句解析器(Lexer)が読み込む、トークンを表すインターフェイスです。
 */
DEFINE_INTERFACE(TOKEN_INTERFACE, 1133640193/*2005/12/04 05:03:13*/,

	/* トークンのタイプを取得します。
	 * [out]
	 *	戻り値		トークンのタイプを表す値。
	 *			文字コード、または、TOKEN_TYPE_*定数です。
	 */
	int (*get_type)(TOKEN_INTERFACE** intf);

	/* トークンの値を取得します。
	 * [out]
	 *	戻り値		トークンの値を表すコード。
	 *			コードを持たないタイプの場合は、NULLとなります。
	 */
	JTCODE_INTERFACE** (*get_code)(TOKEN_INTERFACE** intf);
);

#define IMPLEMENT_TOKEN_INTERFACE(CC, cc)				\
IMPLEMENT_UNKNOWN_INTERFACE_METHODS(CC, cc, TOKEN, token)		\
static int token_get_type(TOKEN_INTERFACE** intf);			\
static JTCODE_INTERFACE** token_get_code(TOKEN_INTERFACE** intf);	\
static TOKEN_INTERFACE token_interface = {				\
	token_query_interface,						\
	token_addref,							\
	token_release,							\
	token_get_type,							\
	token_get_code,							\
};

/*--------------------------------------------------------------------------*/

/* トークンオブジェクトを作成します。
 * [in]
 *	type		トークンのタイプを表す値。
 *	code		トークンの値を表すコード。
 * [note]
 *	* typeとcodeの種類(またはNULL)の組み合わせは、TOKEN_TYPE_*定数のコメントに従ってください。
 *	  token_create()関数は、typeとcodeの組み合わせが正しいか否かを、検査していません。
 */
TOKEN_INTERFACE** token_create(int type, JTCODE_INTERFACE** code);

/*****************************************************************************
 *	LEXER
 *****************************************************************************/

/* 字句解析器(Lexer)を表すインターフェイスです。
 */
DEFINE_INTERFACE(LEXER_INTERFACE, 1133678182/*2005/12/04 15:36:22*/,

	/* これまでに読み込んだ行数を取得します。
	 * [out]
	 *	戻り値		行数。
	 */
	int (*get_line)(LEXER_INTERFACE** intf);

	/* 次のトークンを読み込みます。
	 * [out]
	 *	戻り値		読み込んだトークン。
	 *			ファイル終端に達したら、NULLを返します。
	 */
	TOKEN_INTERFACE** (*get_token)(LEXER_INTERFACE** intf);

	/* 読み込んだトークンを一つ、戻します。
	 * [in]
	 *	token		戻すトークン。
	 * [note]
	 *	* ファイル終端を意味する、NULLを戻すことはできません。
	 *	  NULLを指定してunget_token()を呼び出すと、アサートします。
	 *	* 連続して二つのトークンを戻すことはできません。
	 *	  即ち、unget_token()を呼び出したら、次は必ずget_token()を呼ぶ必要があります。
	 *	  連続して二回、unget_token()を呼び出すと、アサートします。
	 */
	void (*unget_token)(LEXER_INTERFACE** intf, TOKEN_INTERFACE** token);
);

#define IMPLEMENT_LEXER_INTERFACE(CC, cc)					\
IMPLEMENT_UNKNOWN_INTERFACE_METHODS(CC, cc, LEXER, lexer)			\
static int lexer_get_line(LEXER_INTERFACE** intf);				\
static TOKEN_INTERFACE** lexer_get_token(LEXER_INTERFACE** intf);		\
static void lexer_unget_token(LEXER_INTERFACE** intf, TOKEN_INTERFACE** token);	\
static LEXER_INTERFACE lexer_interface = {					\
	lexer_query_interface,							\
	lexer_addref,								\
	lexer_release,								\
	lexer_get_line,								\
	lexer_get_token,							\
	lexer_unget_token,							\
};

/*--------------------------------------------------------------------------*/

/* 字句解析器オブジェクトを作成します。
 * [in]
 *	in		入力ストリーム。
 */
LEXER_INTERFACE** lexer_create(FILE* in);

/*****************************************************************************
 *	ARITHMETIC
 *****************************************************************************/

/* 算術演算の機能を表すインターフェイスです。
 */
DEFINE_INTERFACE(ARITHMETIC_INTERFACE, 1134194844/*2005/12/10 15:07:24*/,
	JTCODE_INTERFACE** (*neg)(ARITHMETIC_INTERFACE** intf);
	JTCODE_INTERFACE** (*add)(ARITHMETIC_INTERFACE** intf, JTCODE_INTERFACE** code);
	JTCODE_INTERFACE** (*sub)(ARITHMETIC_INTERFACE** intf, JTCODE_INTERFACE** code);
	JTCODE_INTERFACE** (*mul)(ARITHMETIC_INTERFACE** intf, JTCODE_INTERFACE** code);
	JTCODE_INTERFACE** (*div)(ARITHMETIC_INTERFACE** intf, JTCODE_INTERFACE** code);
);

#define IMPLEMENT_ARITHMETIC_INTERFACE(CC, cc)							\
IMPLEMENT_UNKNOWN_INTERFACE_METHODS(CC, cc, ARITHMETIC, arithmetic)				\
static JTCODE_INTERFACE** arithmetic_neg(ARITHMETIC_INTERFACE** intf);				\
static JTCODE_INTERFACE** arithmetic_add(ARITHMETIC_INTERFACE** intf, JTCODE_INTERFACE** code);	\
static JTCODE_INTERFACE** arithmetic_sub(ARITHMETIC_INTERFACE** intf, JTCODE_INTERFACE** code);	\
static JTCODE_INTERFACE** arithmetic_mul(ARITHMETIC_INTERFACE** intf, JTCODE_INTERFACE** code);	\
static JTCODE_INTERFACE** arithmetic_div(ARITHMETIC_INTERFACE** intf, JTCODE_INTERFACE** code);	\
static ARITHMETIC_INTERFACE arithmetic_interface = {						\
	arithmetic_query_interface,								\
	arithmetic_addref,									\
	arithmetic_release,									\
	arithmetic_neg,										\
	arithmetic_add,										\
	arithmetic_sub,										\
	arithmetic_mul,										\
	arithmetic_div,										\
};

/*****************************************************************************
 *	LOGICAL
 *****************************************************************************/

/* 論理演算の機能を表すインターフェイスです。
 */
DEFINE_INTERFACE(LOGICAL_INTERFACE, 1134462480/*2005/12/13 17:28:00*/,
	JTCODE_INTERFACE** (*not)(LOGICAL_INTERFACE** intf);
	JTCODE_INTERFACE** (*or)(LOGICAL_INTERFACE** intf, JTCODE_INTERFACE** code);
	JTCODE_INTERFACE** (*and)(LOGICAL_INTERFACE** intf, JTCODE_INTERFACE** code);
);

#define IMPLEMENT_LOGICAL_INTERFACE(CC, cc)							\
IMPLEMENT_UNKNOWN_INTERFACE_METHODS(CC, cc, LOGICAL, logical)					\
static JTCODE_INTERFACE** logical_not(LOGICAL_INTERFACE** intf);				\
static JTCODE_INTERFACE** logical_or(LOGICAL_INTERFACE** intf, JTCODE_INTERFACE** code);	\
static JTCODE_INTERFACE** logical_and(LOGICAL_INTERFACE** intf, JTCODE_INTERFACE** code);	\
static LOGICAL_INTERFACE logical_interface = {							\
	logical_query_interface,								\
	logical_addref,										\
	logical_release,									\
	logical_not,										\
	logical_or,										\
	logical_and,										\
};

/*****************************************************************************
 *	COMPARE
 *****************************************************************************/

/* 比較演算の機能を表すインターフェイスです。
 */
DEFINE_INTERFACE(COMPARE_INTERFACE, 1134194992/*2005/12/10 15:09:52*/,

	/* 自分と、相手のコードを比較します。
	 * [in]
	 *	code		相手のコード。
	 * [out]
	 *	戻り値		自分のコードが小さければ、負値を返します。
	 *			自分のコードが大きければ、正値を返します。
	 *			両社が等しければ、ゼロを返します。
	 * [note]
	 *	* 自分と、相手のコードが比較可能かどうかは、実装依存です。
	 *	  2006/01/11現在、比較可能なオブジェクトの組み合わせは、以下のとおりです。
	 *	  ・自分 = JTINT   、相手 = JTINT
	 *	  ・自分 = JTSTRING、相手 = JTSTRING
	 *	* JTBOOLは比較不可能であることに注意してください。
	 *	  オリジナルのJoyToyは、真偽値同士の比較も可能な仕様となっていますが、
	 *	  真偽値同士の算術比較は、本来、無意味だと思うので、仕様を削りました。
	 */
	int (*compare)(COMPARE_INTERFACE** intf, JTCODE_INTERFACE** code);
);

#define IMPLEMENT_COMPARE_INTERFACE(CC, cc)					\
IMPLEMENT_UNKNOWN_INTERFACE_METHODS(CC, cc, COMPARE, compare)			\
static int compare_compare(COMPARE_INTERFACE** intf, JTCODE_INTERFACE** code);	\
static COMPARE_INTERFACE compare_interface = {					\
	compare_query_interface,						\
	compare_addref,								\
	compare_release,							\
	compare_compare,							\
};

/*****************************************************************************
 *	JTINT
 *****************************************************************************/

/* 数値の機能を表すインターフェイスです。
 */
DEFINE_INTERFACE(JTINT_INTERFACE, 1133695426/*2005/12/04 20:23:46*/,

	/* 数値を取得します。
	 * [out]
	 *	戻り値		数値。
	 */
	int (*get_value)(JTINT_INTERFACE** intf);
);

#define IMPLEMENT_JTINT_INTERFACE(CC, cc)			\
IMPLEMENT_UNKNOWN_INTERFACE_METHODS(CC, cc, JTINT, jtint)	\
static int jtint_get_value(JTINT_INTERFACE** intf);		\
static JTINT_INTERFACE jtint_interface = {			\
	jtint_query_interface,					\
	jtint_addref,						\
	jtint_release,						\
	jtint_get_value,					\
};

/*--------------------------------------------------------------------------*/

/* 数値コードを作成します。
 * [in]
 *	value		数値。
 * [note]
 *	* 数値コード(JTINT_INTERFACE)は、数値(int)を、コードとして扱うためのラッパーです。
 *	  即ち、変更不可能な数値と見なせます。
 */
JTCODE_INTERFACE** jtint_create(int value);

/*****************************************************************************
 *	JTSTRING
 *****************************************************************************/

/* 文字列の機能を表すインターフェイスです。
 */
DEFINE_INTERFACE(JTSTRING_INTERFACE, 1134500258/*2005/12/14 03:57:38*/,

	/* AsciiZ文字列を取得します。
	 * [out]
	 *	戻り値		AsciiZ文字列へのポインタ。
	 * [note]
	 *	* 戻り値のポインタは、オブジェクト内のAsciiZ文字列を直接参照しています。
	 *	  オブジェクトが消滅すると、戻り値のポインタも、無効化となります。
	 *	  戻り値のポインタを保存して、後で使ったりしないよう、注意してください。
	 */
	const char* (*get_string)(JTSTRING_INTERFACE** intf);
);

#define IMPLEMENT_JTSTRING_INTERFACE(CC, cc)				\
IMPLEMENT_UNKNOWN_INTERFACE_METHODS(CC, cc, JTSTRING, jtstring)		\
static const char* jtstring_get_string(JTSTRING_INTERFACE** intf);	\
static JTSTRING_INTERFACE jtstring_interface = {			\
	jtstring_query_interface,					\
	jtstring_addref,						\
	jtstring_release,						\
	jtstring_get_string,						\
};

/*--------------------------------------------------------------------------*/

/* 文字列コードを作成します。
 * [in]
 *	str		AsciiZ文字列へのポインタ。
 * [note]
 *	* jtstring_create()は、指定されたAsciiZ文字列を複製し、格納します。
 *	  関数が処理を返したら、呼びだし元は、AsciiZ文字列を解放して構いません。
 */
JTCODE_INTERFACE** jtstring_create(const char* str);

/*****************************************************************************
 *	JTSYMBOL
 *****************************************************************************/

/* シンボルの機能を表すインターフェイスです。
 */
DEFINE_INTERFACE(JTSYMBOL_INTERFACE, 1133695749/*2005/12/04 20:29:09*/,

	/* シンボルの名前を取得します。
	 * [out]
	 *	戻り値		名前を表すAsciiZ文字列へのポインタ。
	 * [note]
	 *	* 戻り値のポインタは、オブジェクト内のAsciiZ文字列を直接参照しています。
	 *	  オブジェクトが消滅すると、戻り値のポインタも、無効化となります。
	 *	  戻り値のポインタを保存して、後で使ったりしないよう、注意してください。
	 */
	const char* (*get_name)(JTSYMBOL_INTERFACE** intf);
);

#define IMPLEMENT_JTSYMBOL_INTERFACE(CC, cc)				\
IMPLEMENT_UNKNOWN_INTERFACE_METHODS(CC, cc, JTSYMBOL, jtsymbol)		\
static const char* jtsymbol_get_name(JTSYMBOL_INTERFACE** intf);	\
static JTSYMBOL_INTERFACE jtsymbol_interface = {			\
	jtsymbol_query_interface,					\
	jtsymbol_addref,						\
	jtsymbol_release,						\
	jtsymbol_get_name,						\
};

/*--------------------------------------------------------------------------*/

/* シンボルコードを作成します。
 * [in]
 *	name		名前。
 * [note]
 *	* 既に同名のシンボルコードが在る場合は、同じオブジェクトを共有します。
 *	  従って、二つのシンボルコードの等価判定は、ポインタ比較にて行えます。
 */
JTCODE_INTERFACE** jtsymbol_intern(const char* name);

/*****************************************************************************
 *	JTBOOL
 *****************************************************************************/

/* 真偽値の機能を表すインターフェイスです。
 */
DEFINE_INTERFACE(JTBOOL_INTERFACE, 1134564980/*2005/12/14 21:56:20*/,

	/* 真偽値を取得します。
	 * [out]
	 *	戻り値		真ならば0以外の値を返します。
	 *			偽ならば0を返します。
	 */
	int (*get_value)(JTBOOL_INTERFACE** intf);
);

#define IMPLEMENT_JTBOOL_INTERFACE(CC, cc)			\
IMPLEMENT_UNKNOWN_INTERFACE_METHODS(CC, cc, JTBOOL, jtbool)	\
static int jtbool_get_value(JTBOOL_INTERFACE** intf);		\
static JTBOOL_INTERFACE jtbool_interface = {			\
	jtbool_query_interface,					\
	jtbool_addref,						\
	jtbool_release,						\
	jtbool_get_value,					\
};

/*--------------------------------------------------------------------------*/

/* 真偽値コードを作成します。
 * [in]
 *	value		0以外の値を指定すると、真を表す真偽値コードを作成します。
 *			0        を指定すると、偽を表す真偽値コードを作成します。
 * [note]
 *	* 真、および、偽を表す真偽値コードは、インタプリタ全体で唯一です。
 *	  jtbool_create(0以外の値)は、常に、同じインターフェイスポインタを返します。
 *	  jtbool_create(0        )は、常に、同じインターフェイスポインタを返します。
 */
JTCODE_INTERFACE** jtbool_create(int value);

/*****************************************************************************
 *	JTUNEXPR
 *****************************************************************************/

/* 単項演算式コードを作成します。
 * [in]
 *	op		演算子。
 *	code		値。
 * [note]
 *	*  2006/01/12現在、指定可能な演算子は、以下のとおりです。
 *
 *		演算子		codeに必要なｲﾝﾀｰﾌｪｲｽ	ｵﾍﾟﾚｰｼｮﾝ
 *		------		--------------------	--------
 *		'-'		ARITHMETIC_INTERFACE	neg()
 *		'!'		LOGICAL_INTERFACE	not()
 */
JTCODE_INTERFACE** jtunexpr_create(int op, JTCODE_INTERFACE** code);

/*****************************************************************************
 *	JTBINEXPR
 *****************************************************************************/

/* 二項演算式コードを作成します。
 * [in]
 *	op		演算子。
 *	code1		左辺値。
 *	code2		右辺値。
 * [note]
 *	*  2006/01/12現在、指定可能な演算子は、以下のとおりです。
 *
 *		演算子		codeに必要なｲﾝﾀｰﾌｪｲｽ	ｵﾍﾟﾚｰｼｮﾝ
 *		------		--------------------	--------
 *		'+'		ARITHMETIC_INTERFACE	add()
 *		'-'		ARITHMETIC_INTERFACE	sub()
 *		'*'		ARITHMETIC_INTERFACE	mul()
 *		'/'		ARITHMETIC_INTERFACE	div()
 *		TOKEN_TYPE_OR	LOGICAL_INTERFACE	or()
 *		TOKEN_TYPE_AND	LOGICAL_INTERFACE	and()
 *		TOKEN_TYPE_EQ	COMPARE_INTERFACE	compare()
 *		TOKEN_TYPE_NE	COMPARE_INTERFACE	compare()
 *		TOKEN_TYPE_LE	COMPARE_INTERFACE	compare()
 *		TOKEN_TYPE_GE	COMPARE_INTERFACE	compare()
 *		'<'		COMPARE_INTERFACE	compare()
 *		'>'		COMPARE_INTERFACE	compare()
 *		'='		JTSYMBOL_INTERFACE	joytoy_set_symbol_value
 */
JTCODE_INTERFACE** jtbinexpr_create(int op, JTCODE_INTERFACE** code1, JTCODE_INTERFACE** code2);

/*****************************************************************************
 *	JTDOTEXPR
 *****************************************************************************/

/* オブジェクトのフィールド変数の値を取得する、コードを作成します。
 * [in]
 *	code		オブジェクト。
 *	symbol		フィールド変数名を表すシンボル。
 */
JTCODE_INTERFACE** jtdotexpr_create(JTCODE_INTERFACE** code, JTSYMBOL_INTERFACE** symbol);

/*****************************************************************************
 *	JTDOTASSIGN
 *****************************************************************************/

/* オブジェクトのフィールド変数の値を設定する、コードを作成します。
 * [in]
 *	code		オブジェクト。
 *	symbol		フィールド変数名を表すシンボル。
 *	value		フィールド変数に設定する値。
 */
JTCODE_INTERFACE** jtdotassign_create(JTCODE_INTERFACE** code, JTSYMBOL_INTERFACE** symbol, JTCODE_INTERFACE** value);

/*****************************************************************************
 *	JTDOTCALL
 *****************************************************************************/

/* オブジェクトのメソッドを呼び出す、コードを作成します。
 * [in]
 *	code		オブジェクト。
 *	symbol		メソッド名を表すシンボル。
 *	args_list	実引数リスト。
 *			(JTCODE_INTERFACE**)をリスト要素とする、配列リストです。
 *			「list_create(&jtcode_list_info);」で、作成してください。
 */
JTCODE_INTERFACE** jtdotcall_create(JTCODE_INTERFACE** code, JTSYMBOL_INTERFACE** symbol, LIST/*<JTCODE_INTERFACE**>*/ * args_list);

/*****************************************************************************
 *	JTNEW
 *****************************************************************************/

/* オブジェクトを複製する、コードを作成します。
 * [in]
 *	symbol		複製元のオブジェクト名を表すシンボル。
 *	body		初期化ブロック。
 *			初期化ブロックが無い場合は、NULLを指定してください。
 */
JTCODE_INTERFACE** jtnew_create(JTSYMBOL_INTERFACE** symbol, JTCODE_INTERFACE** body);

/*****************************************************************************
 *	JTIF
 *****************************************************************************/

/* if文コードを作成します。
 * [in]
 *	cond		条件式。
 *	then_body;	条件式が真のときに実行する文。
 *	else_body;	条件式が偽のときに実行する文。
 *			elseブロックの無いif文の場合は、else_bodyにNULLを指定してください。
 */
JTCODE_INTERFACE** jtif_create(JTCODE_INTERFACE** cond, JTCODE_INTERFACE** then_body, JTCODE_INTERFACE** else_body);

/*****************************************************************************
 *	JTWHILE
 *****************************************************************************/

/* while文コードを作成します。
 * [in]M
 *	cond		条件式。
 *	body		条件式が真の間、実行し続ける文。
 */
JTCODE_INTERFACE** jtwhile_create(JTCODE_INTERFACE** cond, JTCODE_INTERFACE** body);

/*****************************************************************************
 *	JTBLOCK
 *****************************************************************************/

/* ブロックコードを作成します。
 * [in]
 *	stmt_list	文リスト。
 *			(JTCODE_INTERFACE**)をリスト要素とする、配列リストです。
 *			「list_create(&jtcode_list_info);」で、作成してください。
 * [note]
 *	- jtblock_create()は、文リストを複製して、保持します。
 *	  jtblock_create()が制御を返したら、呼び出し側は、文リストを解放して構いません。
 */
JTCODE_INTERFACE** jtblock_create(LIST/*<JTCODE_INTERFACE**>*/ * stmt_list);

/****************************************************************************
 *	JTOBJECT
 ****************************************************************************/

/* オブジェクトの機能を表すインターフェイスです。
 */
DEFINE_INTERFACE(JTOBJECT_INTERFACE, 1137559251/*2006/01/18 13:40:51*/,

	/* フィールド変数の値を取得します。
	 * [in]
	 *	symbol		フィールド変数名を表すシンボル。
	 * [out]
	 *	戻り値		フィールド変数の値。
	 * [note]
	 *	* フィールド変数が定義されていなければ、NULLを返します。
	 */
	JTCODE_INTERFACE** (*get_field_value)(JTOBJECT_INTERFACE** intf, JTSYMBOL_INTERFACE** symbol);

	/* フィールド変数の値を設定します。
	 * [in]
	 *	symbol		フィールド変数名を表すシンボル。
	 *	value		フィールド変数の値。
	 * [note]
	 *	* フィールド変数が定義されていなければ、アサートします。
	 */
	void (*set_field_value)(JTOBJECT_INTERFACE** intf, JTSYMBOL_INTERFACE** symbol, JTCODE_INTERFACE** value);
);

#define IMPLEMENT_JTOBJECT_INTERFACE(CC, cc)										\
IMPLEMENT_UNKNOWN_INTERFACE_METHODS(CC, cc, JTOBJECT, jtobject)								\
static JTCODE_INTERFACE** jtobject_get_field_value(JTOBJECT_INTERFACE** intf, JTSYMBOL_INTERFACE** symbol);		\
static void jtobject_set_field_value(JTOBJECT_INTERFACE** intf, JTSYMBOL_INTERFACE** symbol, JTCODE_INTERFACE** value);	\
static JTOBJECT_INTERFACE jtobject_interface = {									\
	jtobject_query_interface,											\
	jtobject_addref,												\
	jtobject_release,												\
	jtobject_get_field_value,											\
	jtobject_set_field_value,											\
};

/*--------------------------------------------------------------------------*/

/* オブジェクトを作成します。
 * [in]
 *	slots_table		スロットテーブル。
 *				スロットテーブルには、フィールド変数定義、または、メソッド定義を登録しておいてください。
 *				フィールド変数定義を表すコードは、JTVAR_INTERFACEをサポートしている必要があります。(jtvar_create()にて作成)
 *				メソッド      定義を表すコードは、JTFUN_INTERFACEをサポートしている必要があります。(jtfun_create()にて作成)
 * [note]
 *	* 「スロット」とは、「フィールド変数定義」と「メソッド定義」の総称です。
 *	- 2006/01/27現在、プログラム中のコメント記述が、「スロット」と「フィールド変数」の区別があいまいなままなので、注意してください。
 *	  「フィールド変数」という言葉を、「フィールド変数」と「メソッド」の両者を表す目的で、使ってしまっていたりします。
 *	  (オブジェクト自身から見ると、フィールド変数とメソッドの区別は無く、それを取得した側において、変数として扱うか関数として扱うかの違いしか無いからです)
 */
JTCODE_INTERFACE** jtobject_create(MAP/*<JTSYMBOL_INTERFACE**,JTCODE_INTERFACE**>*/ * slots_table);

/* オブジェクトを複製します。
 * [in]
 *	object			複製元のオブジェクト。
 * [out]
 *	戻り値			複製したオブジェクト。
 * [note]
 *	* "obj_dst = new obj_src { ... };"を実行するために利用します。
 *	* 複製元のオブジェクト1の、全てのスロットを持つ、新しいオブジェクトを作成します。
 *	  スロットの値は、“浅いコピー”を行います。
 *	* 引数objectに指定できるのは、jtobject_create()が返したJTCODE_INTERFACEに対して、QueryInterfaceすることで得られたJTOBJECT_INTERFACEだけです。
 *	  2006/01/29現在、JTOBJECT_INTERFACEインターフェイスをサポートしているのは、jtobject_create()だけなので、この点を注意する必要はありませんが、
 *	  もし、今後、他の方法でJTOBJECT_INTERFACEをサポートするオブジェクトが生成できるように変更した場合に、
 *	  そのようなオブジェクトの複製を作成するために、本関数を利用することはできないので、注意してください。
 */
JTCODE_INTERFACE** jtobject_clone(JTOBJECT_INTERFACE** object);

/* オブジェクトを合成します。
 * [in]
 *	object1			合成元のオブジェクト1。
 *	object2			合成元のオブジェクト2。
 * [out]
 *	戻り値			合成したオブジェクト。
 * [note]
 *	* "obj_dst = obj_src1 + obj_src2;"を実行するために利用します。
 *	* 複製元のオブジェクト1とオブジェクト2の、全てのスロットを持つ、新しいオブジェクトを作成します。
 *	  スロットの値は、“浅いコピー”を行います。
 *	- 複製元のオブジェクト1とオブジェクト2に、同じ名前のスロットが存在する場合、オブジェクト2のスロットを優先します。
 *	* 引数objectに指定できるのは、jtobject_create()が返したJTCODE_INTERFACEに対して、QueryInterfaceすることで得られたJTOBJECT_INTERFACEだけです。
 *	  2006/01/29現在、JTOBJECT_INTERFACEインターフェイスをサポートしているのは、jtobject_create()だけなので、この点を注意する必要はありませんが、
 *	  もし、今後、他の方法でJTOBJECT_INTERFACEをサポートするオブジェクトが生成できるように変更した場合に、
 *	  そのようなオブジェクトの合成を作成するために、本関数を利用することはできないので、注意してください。
 */
JTCODE_INTERFACE** jtobject_merge(JTOBJECT_INTERFACE** object1, JTOBJECT_INTERFACE** object2);

/*****************************************************************************
 *	JTVAR
 *****************************************************************************/

/* 変数定義の機能を表すインターフェイスです。
 */
DEFINE_INTERFACE(JTVAR_INTERFACE, 1137548428/*2006/01/18 10:40:28*/,

	/* 変数名を表すシンボルを取得します。
	 * [out]
	 *	戻り値		変数名を表すシンボル。
	 */
	JTSYMBOL_INTERFACE** (*get_name)(JTVAR_INTERFACE** intf);

	/* 変数の初期値を取得します。
	 * [out]
	 *	戻り値		変数の初期値。
	 */
	JTCODE_INTERFACE** (*get_code)(JTVAR_INTERFACE** intf);
);

#define IMPLEMENT_JTVAR_INTERFACE(CC, cc)				\
IMPLEMENT_UNKNOWN_INTERFACE_METHODS(CC, cc, JTVAR, jtvar)		\
static JTSYMBOL_INTERFACE** jtvar_get_name(JTVAR_INTERFACE** intf);	\
static JTCODE_INTERFACE** jtvar_get_code(JTVAR_INTERFACE** intf);	\
static JTVAR_INTERFACE jtvar_interface = {				\
	jtvar_query_interface,						\
	jtvar_addref,							\
	jtvar_release,							\
	jtvar_get_name,							\
	jtvar_get_code,							\
};

/*--------------------------------------------------------------------------*/
/* 変数定義コードを作成します。
 * [in]
 *	name		変数名を表すシンボル。
 *	code		変数の初期値。
 */
JTCODE_INTERFACE** jtvar_create(JTSYMBOL_INTERFACE** name, JTCODE_INTERFACE** code);

/****************************************************************************
 *	JTFUN
 ****************************************************************************/

/* 関数の機能を表すインターフェイスです。
 */
DEFINE_INTERFACE(JTFUN_INTERFACE, 1135529565/*2005/12/26 01:52:45*/,

	/* 関数名を表すシンボルを取得します。
	 * [out]
	 *	戻り値		関数名を表すシンボル。
	 */
	JTSYMBOL_INTERFACE** (*get_name)(JTFUN_INTERFACE** intf);

	/* 関数を実行します。
	 * [in]
	 *	args_list	実引数リスト。
	 *			関数を呼び出す直前のタイミングで、あらかじめ実引数を評価しておいてください。
	 *			実際には、その処理は、JTFUNCALL_INTERFACE::run()が行うので、特に意識する必要はありません。
	 *	object		メソッドの実行対象となるオブジェクト。
	 *			メソッドならば、指定必須です。NULLを指定するとアサートします。
	 *			通常の関数ならば、無視します。何を指定しても構いません。
	 */
	JTCODE_INTERFACE** (*call)(JTFUN_INTERFACE** intf, LIST/*<JTCODE_INTERFACE**>*/ * args_list, JTOBJECT_INTERFACE** object);
);

#define IMPLEMENT_JTFUN_INTERFACE(CC, cc)												\
IMPLEMENT_UNKNOWN_INTERFACE_METHODS(CC, cc, JTFUN, jtfun)										\
static JTSYMBOL_INTERFACE** jtfun_get_name(JTFUN_INTERFACE** intf);									\
static JTCODE_INTERFACE** jtfun_call(JTFUN_INTERFACE** intf, LIST/*<JTCODE_INTERFACE**>*/ * args_list, JTOBJECT_INTERFACE** object);	\
static JTFUN_INTERFACE jtfun_interface = {												\
	jtfun_query_interface,														\
	jtfun_addref,															\
	jtfun_release,															\
	jtfun_get_name,															\
	jtfun_call,															\
};

/*--------------------------------------------------------------------------*/

/* 関数定義を作成します。
 * [in]
 *	name		関数名を表すシンボル。
 *	params_list	仮引数リスト。
 *			(JTSYMBOL_INTERFACE**)をリスト要素とする、配列リストです。
 *			「list_create(&jtsymbol_list_info);」で、作成してください。
 *	body		関数の本体。
 *	method		通常の関数ならば、0を指定してください。
 *			メソッドならば、0以外の値を指定してください。
 * [note]
 *	- jtfun_create()は、仮引数リストを複製して、保持します。
 *	  jtfun_create()が制御を返したら、呼び出し側は、仮引数リストを解放して構いません。
 */
JTCODE_INTERFACE** jtfun_create(JTSYMBOL_INTERFACE** name, LIST/*<JTSYMBOL_INTERFACE**>*/ * params_list, JTCODE_INTERFACE** body, int method);

/*--------------------------------------------------------------------------*/

/* 組み込み関数を作成します。
 * [in]
 *	name		組み込み関数名を表すシンボル。
 *	call		組み込み関数の処理を行う関数。
 * [note]
 *	* jtprim_〜_craete()から呼ばれます。(内部使用)
 */
JTCODE_INTERFACE** jtprim_create(const char* name, JTCODE_INTERFACE** (*call)(LIST/*<JTCODE_INTERFACE**>*/ * args_list));

/* 文字列を表示する、組み込み関数を作成します。
 * [note]
 *	* prim_init()から、一度だけ呼ばれます。(内部使用)
 */
JTCODE_INTERFACE** jtprim_print_create();

/* 最大値を求める、組み込み関数を作成します。
 * [note]
 *	* prim_init()から、一度だけ呼ばれます。(内部使用)
 */
JTCODE_INTERFACE** jtprim_max_create();

/* TODO: 組み込み関数が増えたら、ここに追加してください。 */

/*****************************************************************************
 *	JTFUNCALL
 *****************************************************************************/

/* 関数呼び出しコードを作成します。
 * [in]
 *	symbol		関数名を表すシンボル。
 *	args_list	実引数リスト。
 *			(JTCODE_INTERFACE**)をリスト要素とする、配列リストです。
 *			「list_create(&jtcode_list_info);」で、作成してください。
 * [note]
 *	- jtfuncall_create()は、実引数リストを複製して、保持します。
 *	  jtfuncall_create()が制御を返したら、呼び出し側は、実引数リストを解放して構いません。
 */
JTCODE_INTERFACE** jtfuncall_create(JTSYMBOL_INTERFACE** symbol, LIST/*<JTCODE_INTERFACE**>*/ * args_list);

/****************************************************************************
 *	PARSER
 ****************************************************************************/

/* 構文解析器(Parser)を表すインターフェイスです。
 */
DEFINE_INTERFACE(PARSER_INTERFACE, 1133770284/*2005/12/05 17:11:24*/,

	/* 次のコードを読み込みます。
	 * [out]
	 *	戻り値		読み込んだコード。
	 */
	JTCODE_INTERFACE** (*parse)(PARSER_INTERFACE** intf);
);

#define IMPLEMENT_PARSER_INTERFACE(CC, cc)				\
IMPLEMENT_UNKNOWN_INTERFACE_METHODS(CC, cc, PARSER, parser)		\
static JTCODE_INTERFACE** parser_parse(PARSER_INTERFACE** intf);	\
static PARSER_INTERFACE parser_interface = {				\
	parser_query_interface,						\
	parser_addref,							\
	parser_release,							\
	parser_parse,							\
};

/*--------------------------------------------------------------------------*/

/* 構文解析器オブジェクトを作成します。
 * [in]
 *	lexer		構文解析器への入力となる、字句解析器。
 */
PARSER_INTERFACE** parser_create(LEXER_INTERFACE** lexer);

/****************************************************************************
 *	JOYTOY
 ****************************************************************************/

/* JoyToyインタプリタを実行します。
 * [in]
 *	in		入力ストリーム。
 * [out]
 *	
 */
void joytoy_main(FILE* in);

/* コードの内容を表示します。
 * [in]
 *	code		コード。
 * [note]
 *	* 組み込み関数printを実装している、jtprim_print.cから利用しています。
 *	  クラス別の場合分け処理を、joytoy.cに集中させるために、処理を分離しました。
 *	- いずれにせよ、この処理はテスト的なものであり、
 *	  本当は、各クラスに文字列化インターフェイスを実装させるべきです。
 */
void joytoy_print(JTCODE_INTERFACE** code);

/* 予約語テーブルを検索します。
 * [in]
 *	name		予約語名。
 * [out]
 *	戻り値		指定された名前の予約語が有れば、予約語のタイプを返します。
 *			さもなくば、負値を返します。
 */
int joytoy_get_reserved(const char* name);

/* 関数フレームに入ります。
 */
void joytoy_enter();

/* 関数フレームを抜けます。
 */
void joytoy_leave();

/* 現在の関数フレームの、実行対象オブジェクトを取得します。
 * [out]
 *	戻り値		メソッドを実行中ならば、実行対象オブジェクトを返します。
 *			グローバル、または、通常の関数を実行中ならば、NULLを返します。
 */
JTOBJECT_INTERFACE** joytoy_get_object();

/* 現在の関数フレームの、実行対象オブジェクトを設定します。
 * [in]
 *	object		実行対象オブジェクト。
 */
void joytoy_set_object(JTOBJECT_INTERFACE** object);

/* 変数の値を取得します。
 * [in]
 *	symbol		変数名を表すシンボル。
 * [out]
 *	戻り値		変数の値。
 * [note]
 *	* 通常の関数、または、メソッドを実行中であり、ローカル変数が定義されていたら、ローカル変数の値を取得します。
 *	  メソッドを実行中であり、フィールド変数が定義されていたら、フィールド変数の値を取得します。
 *	  グローバル変数が定義されていたら、グローバル変数の値を取得します。
 *	  いずれにも該当しなければ、NULLを返します。
 */
JTCODE_INTERFACE** joytoy_get_symbol_value(JTSYMBOL_INTERFACE** symbol);

/* 変数の値を設定します。
 * [in]
 *	symbol		変数名を表すシンボル。
 *	value		変数の値。
 * [note]
 *	* 通常の関数、または、メソッドを実行中であり、ローカル変数が定義されていたら、ローカル変数の値を設定します。
 *	  メソッドを実行中であり、フィールド変数が定義されていたら、フィールド変数の値を設定します。
 *	  グローバル変数が定義されていたら、グローバル変数の値を設定します。
 *	  いずれにも該当しなければ、アサートします。
 */
void joytoy_set_symbol_value(JTSYMBOL_INTERFACE** symbol, JTCODE_INTERFACE** value);

/* 新しい変数を定義します。
 * [in]
 *	symbol		変数名を表すシンボル。
 *	value		変数の初期値。
 * [note]
 *	* 通常の関数、または、メソッドを実行中ならば、ローカル変数を定義します。
 *	  さもなくば、グローバル変数を定義します。
 *	  いずれの場合も、既に同名の変数が定義されていたら、アサートします。
 */
void joytoy_def_symbol_value(JTSYMBOL_INTERFACE** symbol, JTCODE_INTERFACE** value);

#endif /*__JOYTOY_H__*/
