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

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

typedef struct _JTBOOL {
	int refcnt;
	JTCODE_INTERFACE* jtcode_interface;
	JTBOOL_INTERFACE* jtbool_interface;
	LOGICAL_INTERFACE* logical_interface;
	//
	int value;
} JTBOOL;

IMPLEMENT_JTCODE_INTERFACE(JTBOOL, jtbool)
IMPLEMENT_JTBOOL_INTERFACE(JTBOOL, jtbool)
IMPLEMENT_LOGICAL_INTERFACE(JTBOOL, jtbool)

const INTERFACE_MAP jtbool_interface_map[] = {
	{ JTCODE_INTERFACE_ID, offsetof(JTBOOL, jtcode_interface), &jtcode_interface },
	{ JTBOOL_INTERFACE_ID, offsetof(JTBOOL, jtbool_interface), &jtbool_interface },
	{ LOGICAL_INTERFACE_ID, offsetof(JTBOOL, logical_interface), &logical_interface },
	{ 0/*終端*/ },
};

JTCODE_INTERFACE**
jtbool_create(int value)
{
	static JTBOOL jtbool[2] = {
		{ 1/*refcnt*/, &jtcode_interface, &jtbool_interface, &logical_interface, 0/* value */ }, /* 唯一の"偽"オブジェクト */
		{ 1/*refcnt*/, &jtcode_interface, &jtbool_interface, &logical_interface, 1/* value */ }, /* 唯一の"真"オブジェクト */
	};
	value = value != 0; /* 真ならば1、偽ならば0とする */
	return safe_addref(&jtbool[value].jtcode_interface);
}

static void
jtbool_delete(JTBOOL* this)
{
	DIE(); /* 有り得ない */
}

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

static JTCODE_INTERFACE**
jtcode_run(JTCODE_INTERFACE** intf)
{
	return safe_addref(intf); /* 呼び出し元のために+1 */
}

/*****************************************************************************
 *	JTBOOL_INTERFACE
 *****************************************************************************/

static int
jtbool_get_value(JTBOOL_INTERFACE** intf)
{
	JTBOOL* this = CONTAINING_RECORD(intf, JTBOOL, jtbool_interface);

	/* 値を返します。 */
	return this->value;
}

/*****************************************************************************
 *	LOGICAL_INTERFACE
 *****************************************************************************/

static JTCODE_INTERFACE**
logical_not(LOGICAL_INTERFACE** intf)
{
	JTBOOL* this = CONTAINING_RECORD(intf, JTBOOL, logical_interface);

	return jtbool_create(!this->value);
}

static JTCODE_INTERFACE**
logical_or(LOGICAL_INTERFACE** intf, JTCODE_INTERFACE** code)
{
	JTBOOL* this = CONTAINING_RECORD(intf, JTBOOL, logical_interface);
	//
	JTBOOL_INTERFACE** jtbool = NULL;
	int value;

	safe_assign_interface(jtbool, code, JTBOOL_INTERFACE);
	if(!jtbool) {
		DIE(); /* JTBOOL_INTERFACEが必要 */
	}
	value = (*jtbool)->get_value(jtbool);
	safe_release(jtbool);

	return jtbool_create(this->value || value);
}

static JTCODE_INTERFACE**
logical_and(LOGICAL_INTERFACE** intf, JTCODE_INTERFACE** code)
{
	JTBOOL* this = CONTAINING_RECORD(intf, JTBOOL, logical_interface);
	//
	JTBOOL_INTERFACE** jtbool = NULL;
	int value;

	safe_assign_interface(jtbool, code, JTBOOL_INTERFACE);
	if(!jtbool) {
		DIE(); /* JTBOOL_INTERFACEが必要 */
	}
	value = (*jtbool)->get_value(jtbool);
	safe_release(jtbool);

	return jtbool_create(this->value && value);
}

