//March 2020

#include "compilation/intrinsics.h"
#include "compilation/containers.h"
#include "analysis/utils.h"
#include "llvmlayer.h"

using namespace std;

namespace xreate{ namespace compilation{

llvm::Value*
IntrinsicCompiler::compile(const Expression& e, const Context& context, const std::string& hintAlias){
  switch ((IntrinsicFn) e.getValueDouble()){
    case IntrinsicFn::ARR_INIT:{
      return nullptr;
//      const ExpandedType& typAggr = context.pass->man->root->getType(e);
//      llvm::Type* typAggrRaw = context.pass->man->llvm->toLLVMType(typAggr);
//      llvm::Value* lengthRaw = context.scope->process(e.operands.at(0));
//
//      ContainerInst engine(context);
//      return engine.array_init(lengthRaw, typAggrRaw);
    }

    case IntrinsicFn::CON_KEYS:
      return con_keys(e, context, hintAlias);

    default: break;
  }

  assert(false);
  return nullptr;
}

Expression
IntrinsicCompiler::interpret(const Expression& e){
  switch ((IntrinsicFn) e.getValueDouble()){
    case IntrinsicFn::REC_FIELDS: {
      return rec_fields(e);
    }
    default: break;
  }

  assert(false);
  return Expression();
}

Expression
IntrinsicCompiler::rec_fields(const Expression& e){
  TypesHelper helper(__man->llvm);
  assert(e.operands.size() == 1);

  const Expression argTypeE = e.operands.at(0);
  assert(argTypeE.__state == Expression::STRING);
  const string& argTypeS = argTypeE.getValueString();
  const ExpandedType argTypeT = __man->root->findType(argTypeS);

  const auto& fields = helper.getRecordFields(argTypeT);
  return analysis::representVecStr(fields);
}

llvm::Value*
IntrinsicCompiler::con_keys(const Expression& e, const Context& context, const std::string& hintAlias){
  const Expression& aggrE = e.operands.at(0);
  const ExpandedType& aggrT = context.pass->man->root->getType(aggrE);
  llvm::Value* aggrRaw = context.scope->process(aggrE);

  std::unique_ptr<containers::IContainersIR> compiler(containers::IContainersIR::create(
    aggrE, aggrT.get(), context
  ));

  return compiler->keys(aggrRaw, hintAlias);
}
}}