/* 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/.
 *
 * File:   lambdas.cpp
 * Author: pgess <v.melnychenko@xreate.org>
 *
 * Created in April, 2020
 */

#include "compilation/lambdas.h"
#include "llvmlayer.h"
#include "compilation/resources.h"

using namespace xreate::compilation;
using namespace std;

unsigned LambdaBruteFn::__counter = 0;

std::string
LambdaBruteFn::prepareName(){
  return string(LAMBDA_PREFIX) + "_" + __hintAlias + "_" + to_string(__counter++);
}

std::vector<llvm::Type*>
LambdaBruteFn::prepareSignature(){
  return getScopeSignature(IBruteFunction::__entry);
}

llvm::Type*
LambdaBruteFn::prepareResult(){
  LLVMLayer* llvm = IBruteFunction::pass->man->llvm;
  AST* ast = IBruteFunction::pass->man->root;

  return  llvm->toLLVMType(ast->getType(__entry->getBody()));
}

llvm::Function::arg_iterator
LambdaBruteFn::prepareBindings(){
  CodeScope* entry = IBruteFunction::__entry;
  IBruteScope* entryCompilation = IBruteFunction::getBruteScope(entry);
  llvm::Function::arg_iterator fargsI = IBruteFunction::raw->arg_begin();

  for (std::string &arg : entry->__bindings) {
    ScopedSymbol argid{entry->__identifiers[arg], versions::VERSION_NONE};

    entryCompilation->bindArg(&*fargsI, argid);
    fargsI->setName(arg);
    ++fargsI;
  }

  return fargsI;
}

void
LambdaBruteFn::applyAttributes(){
  raw->addFnAttr(llvm::Attribute::AlwaysInline);
}

llvm::Function*
LambdaIR::compile(CodeScope* body, const std::string& hintAlias){
  LambdaBruteFn fnLambda(body, __pass, hintAlias);

  return fnLambda.compile();
}
