/*
 * adhoc.cpp
 *
 *  Created on: Nov 28, 2015
 *      Author: pgess
 */

#include "pass/adhocpass.h"
#include "query/context.h"

namespace xreate {
	AdhocScheme*
	AdhocPass::determineForScope(CodeScope* entry){
		const ScopePacked scopeId = man->clasp->pack(entry);
		const Domain& domain = queryContext->getContext(scopeId);
		AdhocScheme* scheme = nullptr;

		for (const Expression& context: domain){
			if (context.__state != Expression::IDENT) continue;

			if (__schemes.count(context.getValueString())){
				assert(!scheme && "ambiguous context");
				scheme = __schemes.at(context.getValueString());
			}
		}

		assert(scheme && "Appropriate context not found");
		return scheme;
	}

	const TypeAnnotation&
	AdhocScheme::getResultType(){
		return __resultType;
	}

	CodeScope*
	AdhocScheme::getImplementationForCommand(const std::string& comm) {
		assert(__commands.count(comm) && "Adhoc not defined");
		return 	__commands.at(comm);
	}

	AdhocScheme::AdhocScheme(const Expression& scheme):
		__resultType(scheme.type), __context(scheme.getValueString()) {

		Expression cases = scheme.getOperands()[0];
		for (const Expression& exprCase: cases.getOperands()){
			CodeScope* blockComm = exprCase.blocks.front();
			std::string nameCase = blockComm->getBody().operands[0].getValueString();

			CodeScope* blockImpl = *(++exprCase.blocks.begin());
			__commands.emplace(nameCase, blockImpl);
		}
	}

	const std::string&
	AdhocScheme::getContext(){
		return __context;
	}

	/*
	void
	AdhocPass::process(const Expression& expression, PassContext context, const std::string& varDecl=""){
		if (expression == Exp)
	}
	*/

	void
	AdhocPass::run(){
		queryContext = reinterpret_cast<ContextQuery*>(man->clasp->registerQuery(new ContextQuery(), QueryId::ContextQuery));

		auto range = man->root->__interfacesData.equal_range(ASTInterface::Adhoc);
		for (auto i=range.first; i!= range.second; ++i){
			AdhocScheme* scheme = new AdhocScheme(i->second);
			__schemes.emplace(scheme->getContext(), scheme);
		}
	}
}




