/*
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

/*
 * Author: pgess <v.melnychenko@xreate.org>
 * Created on July 9, 2018, 6:04 PM
 */

#include "compilation/polymorph.h"
using namespace std;

namespace xreate{
namespace polymorph{

//PolymorphFnInvocation::PolymorphFnInvocation(const latereasoning::LateAnnotation& selector,
//                                             std::list<ManagedFnPtr> calleeSpecializations,
//                                             CompilePass* pass,
//                                             PolymorphQuery* query,
//                                             LLVMLayer* llvm,
//                                             latereasoning::LateReasoningCompiler* compiler)
//: __selector(selector), __calleeSpecializations(calleeSpecializations),
//__pass(pass), __query(query), __llvm(llvm), __compiler(compiler) { }
//
//llvm::Value*
//PolymorphFnInvocation::operator()(std::vector<llvm::Value *>&& args, const std::string& hintDecl) {
//    std::map<Selector, ManagedFnPtr> dictSelectors;
//    for(ManagedFnPtr specialization : __calleeSpecializations) {
//        dictSelectors.emplace(specialization->guard, specialization);
//    }
//
//    compilation::IBruteFunction* specAny = __pass->getFunctionUnit(__calleeSpecializations.front());
//    return __compiler->compileAutoExpand(
//        __selector,
//        specAny->prepareResult(),
//        hintDecl,
//        [this, &args, hintDecl, &dictSelectors](const Gringo::Symbol & selectorRaw) {
//            const Expression & selectorE = __query->getValue(selectorRaw);
//            assert(dictSelectors.count(selectorE) && "Inappropriate specialization guard");
//            compilation::BruteFnInvocation* invoc = new compilation::BruteFnInvocation(
//                __pass->getFunctionUnit(dictSelectors.at(selectorE))->compile(),
//                __llvm);
//
//            return invoc->operator()(move(args), hintDecl);
//        });
//}

bool isFnGuarded(const std::string& fn, const AST& root){
  const std::list<ManagedFnPtr>& specs = root.getFnSpecializations(fn);

  //Extern function
  if(specs.size() == 0){
    return false;
  }

  //No other specializations. Check if it has no guard
  if(specs.size() == 1){
    if(!specs.front()->guard.isValid()){
      return false;
    }
  }

  return true;
}

}}
