#include <common/CastHelper.h>

#include <registry/Registry.h>
#include <exception>

namespace abstraction {

std::shared_ptr < abstraction::Value > CastHelper::eval ( abstraction::TemporariesHolder &, const std::shared_ptr < abstraction::Value > & param, const std::string & type ) {
	if ( abstraction::Registry::isCastNoOp ( type, param->getType ( ) ) ) {
		return param;
	}

	std::shared_ptr < abstraction::OperationAbstraction > res = abstraction::Registry::getCastAbstraction ( type, param->getType ( ) );
	res->attachInput ( param, 0 );

	std::shared_ptr < abstraction::Value > result = res->eval ( );
	if ( ! result )
		throw std::invalid_argument ( "Eval of cast to " + type + " failed." );

	if ( abstraction::Registry::hasNormalize ( result->getType ( ) ) ) {
		std::shared_ptr < abstraction::OperationAbstraction > normalize = abstraction::Registry::getNormalizeAbstraction ( result->getType ( ) );
		normalize->attachInput ( result, 0 );
		result = normalize->eval ( );
		if ( ! result )
			throw std::invalid_argument ( "Eval of normalize of cast to " + type + " failed." );
	}

	return result;
}

} /* namespace abstraction */
