//
// Object_Expr
//

#include "AScript.h"
#include "Expr.h"

namespace AScript {

bool Object_Expr::IsExpr() const { return true; }

Object_Expr::Object_Expr(const Object_Expr &obj) :
								Object(obj), _pExpr(obj._pExpr->IncRef())
{
}

Object_Expr::~Object_Expr()
{
	Expr::Delete(_pExpr);
}

Object *Object_Expr::Clone() const
{
	return new Object_Expr(*this);
}

String Object_Expr::ToString(Signal sig, bool exprFlag)
{
	String str;
	if (_pExpr->IsValue() || _pExpr->IsSymbol() || _pExpr->IsFunction()) {
		if (exprFlag) str += _T('`');
		str += _pExpr->ToString(sig);
	} else if (exprFlag) {
		if (_pExpr->IsUnary() || _pExpr->IsBinary()) {
			str += _T("`(");
			str += _pExpr->ToString(sig);
			str += _T(")");
		} else {
			str += _T("`");
			str += _pExpr->ToString(sig);
		}
	} else {
		str += _pExpr->ToString(sig);
	}
	return str;
}

// Expr#each() {block}
AScript_DeclareMethod(Expr, each)
{
	DeclareBlock(OCCUR_Once);
}

AScript_ImplementMethod(Expr, each)
{
	const Expr *pExpr = Object_Expr::GetSelfObj(context)->GetExpr();
	if (!pExpr->IsContainer()) {
		sig.SetError(ERR_ValueError, _T("not a container expression"));
		return Value::Null;
	}
	const Expr_Container *pExprContainer =
							dynamic_cast<const Expr_Container *>(pExpr);
	const Function *pFuncBlock = GetBlockFunction(env, sig, context);
	if (sig.IsSignalled()) return Value::Null;
	Environment envBlock(&env, ENVTYPE_Block);
	foreach_const (ExprList, ppExprEach, pExprContainer->GetExprList()) {
		const Expr *pExprEach = *ppExprEach;
		Object_Expr *pObj = new Object_Expr(env.GetClass_Expr(), pExprEach->IncRef());
		Value value(pObj, VTYPE_Object);
		pFuncBlock->Eval(envBlock, sig, Context(ValueList(value)));
		AScript_BlockSignalHandlerInLoop(sig, value, Value::Null)
	}
	return Value::Null;
}

// Expr#child()
AScript_DeclareMethod(Expr, child)
{
}

AScript_ImplementMethod(Expr, child)
{
	const Expr *pExpr = Object_Expr::GetSelfObj(context)->GetExpr();
	
	return Value::Null;
}

// Expr#left()
AScript_DeclareMethod(Expr, left)
{
}

AScript_ImplementMethod(Expr, left)
{
	const Expr *pExpr = Object_Expr::GetSelfObj(context)->GetExpr();
	
	return Value::Null;
}

// Expr#right()
AScript_DeclareMethod(Expr, right)
{
}

AScript_ImplementMethod(Expr, right)
{
	const Expr *pExpr = Object_Expr::GetSelfObj(context)->GetExpr();
	
	return Value::Null;
}

// Assignment
Class_Expr::Class_Expr(Class *pClassSuper, const Symbol *pSymbol) :
												Class(pClassSuper, pSymbol)
{
	AScript_AssignMethod(Expr, each);
	AScript_AssignMethod(Expr, child);
	AScript_AssignMethod(Expr, left);
	AScript_AssignMethod(Expr, right);
}

Object *Class_Expr::CreateDescendant(Environment &env, Signal sig, Class *pClass)
{
	ERROREND(env, _T("this function must not be called"));
	return NULL;
}

}
