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

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

typedef struct _JTVAR {
	int refcnt;
	JTCODE_INTERFACE* jtcode_interface;
	JTVAR_INTERFACE* jtvar_interface;
	//
	JTSYMBOL_INTERFACE** name;	/* 変数名を表すシンボル */
	JTCODE_INTERFACE** code;	/* 変数の初期値 */
} JTVAR;

IMPLEMENT_JTCODE_INTERFACE(JTVAR, jtvar)
IMPLEMENT_JTVAR_INTERFACE(JTVAR, jtvar)

const INTERFACE_MAP jtvar_interface_map[] = {
	{ JTCODE_INTERFACE_ID, offsetof(JTVAR, jtcode_interface), &jtcode_interface },
	{ JTVAR_INTERFACE_ID, offsetof(JTVAR, jtvar_interface), &jtvar_interface },
	{ 0/*終端*/ },
};

JTCODE_INTERFACE**
jtvar_create(JTSYMBOL_INTERFACE** name, JTCODE_INTERFACE** code)
{
	JTVAR* this = calloc(1, sizeof(JTVAR));
	if(!this) {
		DIE(); /* メモリ不足 */
	}
	this->refcnt = 1;
	apply_interface_map(this, jtvar_interface_map);

	/* 変数名を表すシンボルを格納します。 */
	safe_assign(this->name, name);

	/* 変数の初期値を格納します。 */
	safe_assign(this->code, code);

	return &this->jtcode_interface;
}

static void
jtvar_delete(JTVAR* this)
{
	/* 変数名を表すシンボルを解放します。 */
	safe_release(this->name);

	/* 変数の初期値を解放します。 */
	safe_release(this->code);

	free(this);
}

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

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

	/* 変数の初期値を解決します。 */
	safe_attach(code, (*this->code)->run(this->code));

	/* 変数を定義します。 */
	joytoy_def_symbol_value(this->name, code);

	return code;
}

/*****************************************************************************
 *	JTVAR_INTERFACE
 *****************************************************************************/

static JTSYMBOL_INTERFACE**
jtvar_get_name(JTVAR_INTERFACE** intf)
{
	JTVAR* this = CONTAINING_RECORD(intf, JTVAR, jtvar_interface);

	/* 変数名を表すシンボルを返します。 */
	return safe_addref(this->name); /* 呼び出し元のために+1 */
}

static JTCODE_INTERFACE**
jtvar_get_code(JTVAR_INTERFACE** intf)
{
	JTVAR* this = CONTAINING_RECORD(intf, JTVAR, jtvar_interface);

	/* 変数の初期値を返します。 */
	return safe_addref(this->code); /* 呼び出し元のために+1 */
}
