/*
 *	jtdotexpr.c
 *
 *	JoyToyインタプリタ
 *
 *	* Sun Jan 01 00:00:00 JST 2006 Naoyuki Sawa
 *	- 作成開始。
 *	* Tue Jan 31 00:00:00 JST 2006 Naoyuki Sawa
 *	- 1st リリース。
 *	* Sat Jun 17 05:26:02 JST 2006 Naoyuki Sawa
 *	- FIELD_OFFSET()→offsetof()に変更。
 */
#include "app.h"

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

typedef struct _JTDOTEXPR {
	int refcnt;
	JTCODE_INTERFACE* jtcode_interface;
	//
	JTCODE_INTERFACE** code;	/* オブジェクト */
	JTSYMBOL_INTERFACE** symbol;	/* フィールド変数名を表すシンボル */
} JTDOTEXPR;

IMPLEMENT_JTCODE_INTERFACE(JTDOTEXPR, jtdotexpr)

const INTERFACE_MAP jtdotexpr_interface_map[] = {
	{ JTCODE_INTERFACE_ID, offsetof(JTDOTEXPR, jtcode_interface), &jtcode_interface },
	{ 0/*終端*/ },
};

JTCODE_INTERFACE**
jtdotexpr_create(JTCODE_INTERFACE** code, JTSYMBOL_INTERFACE** symbol)
{
	JTDOTEXPR* this = calloc(1, sizeof(JTDOTEXPR));
	if(!this) {
		DIE(); /* メモリ不足 */
	}
	this->refcnt = 1;
	apply_interface_map(this, jtdotexpr_interface_map);

	/* オブジェクト、フィールド変数名を表すシンボルを格納します。 */
	safe_assign(this->code, code);
	safe_assign(this->symbol, symbol);

	return &this->jtcode_interface;
}

static void
jtdotexpr_delete(JTDOTEXPR* this)
{
	/* オブジェクト、フィールド変数名を表すシンボルを解放します。 */
	safe_release(this->code);
	safe_release(this->symbol);

	free(this);
}

/*****************************************************************************
 *	JTCODE_INTERFACE
 *****************************************************************************/

static JTCODE_INTERFACE**
jtcode_run(JTCODE_INTERFACE** intf)
{
	JTDOTEXPR* this = CONTAINING_RECORD(intf, JTDOTEXPR, jtcode_interface);
	//
	JTCODE_INTERFACE** code = NULL;
	JTOBJECT_INTERFACE** object = NULL;

	/* フィールド変数の値を取得する直前のタイミングで、オブジェクトを評価します。 */
	safe_attach(code, (*this->code)->run(this->code)); /* シンボルを解決して、オブジェクトを取得する処理など */
	safe_assign_interface(object, code, JTOBJECT_INTERFACE);
	if(!object) {
		DIE(); /* オブジェクトでない (読み込んだプログラムのエラー) */
	}

	/* フィールド変数の値を取得します。 */
	safe_attach(code, (*object)->get_field_value(object, this->symbol));
	if(!code) {
		DIE(); /* フィールド変数が定義されていない */
	}

	/* 不要になったインターフェイスを解放します。 */
	safe_release(object);

	return code;
}

