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

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

typedef struct _JTNEW {
	int refcnt;
	JTCODE_INTERFACE* jtcode_interface;
	//
	JTSYMBOL_INTERFACE** symbol;	/* 複製元のオブジェクト名を表すシンボル */
	JTCODE_INTERFACE** body;	/* 初期化ブロック、または、NULL */
} JTNEW;

IMPLEMENT_JTCODE_INTERFACE(JTNEW, jtnew)

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

JTCODE_INTERFACE**
jtnew_create(JTSYMBOL_INTERFACE** symbol, JTCODE_INTERFACE** body)
{
	JTNEW* this = calloc(1, sizeof(JTNEW));
	if(!this) {
		DIE(); /* メモリ不足 */
	}
	this->refcnt = 1;
	apply_interface_map(this, jtnew_interface_map);

	/* 複製元のオブジェクト名を表すシンボル、初期化ブロックを格納します。 */
	safe_assign(this->symbol, symbol);
	safe_assign(this->body, body);

	return &this->jtcode_interface;
}

static void
jtnew_delete(JTNEW* this)
{
	/* 複製元のオブジェクト名を表すシンボル、初期化ブロックを解放します。 */
	safe_release(this->symbol);
	safe_release(this->body);

	free(this);
}

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

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

	/* シンボルに対応する、オブジェクトを取得します。 */
	safe_attach(code, joytoy_get_symbol_value(this->symbol));
	if(!code) {
		DIE(); /* 未定義 (読み込んだプログラムのエラー) */
	}
	safe_assign_interface(object, code, JTOBJECT_INTERFACE);
	if(!object) {
		DIE(); /* 関数でない (読み込んだプログラムのエラー) */
	}

	/* オブジェクトを複製します。 */
	safe_attach(code, jtobject_clone(object));
	safe_assign_interface(object, code, JTOBJECT_INTERFACE);
	if(!object) {
		DIE(); /* 有り得ない */
	}

	/* 初期化ブロックが有れば、実行します。 */
	if(this->body) {
		JTCODE_INTERFACE** tmp = NULL;

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

		/* 複製先のオブジェクトを、実行対象とします。 */
		joytoy_set_object(object);

		/* 初期化ブロックを実行します。 */
		safe_attach(tmp, (*this->body)->run(this->body));

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

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

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

	return code;
}

