/* 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:   containers.h
 * Author: pgess <v.melnychenko@xreate.org>
 */

#ifndef CODEINSTRUCTIONS_H
#define CODEINSTRUCTIONS_H

#include "ast.h"

#include "llvmlayer.h"
#include "pass/compilepass.h"
#include "compilation/advancedinstructions.h"
#include "query/containers.h"

namespace xreate {
    namespace containers {

using namespace llvm;

/** \brief Factory to create relevant iterator based on solution 
 * provided by xreate::containers::Query
 * \sa xreate::containers::Query
 */
class Iterator{
public :
    virtual llvm::Value* begin() =0;
    virtual llvm::Value* end() = 0;
    virtual llvm::Value* get(llvm::Value* index,const std::string& hintRetVar="") = 0;
    virtual llvm::Value* advance(llvm::Value* index, const std::string& hintRetVar="")=0;
    virtual ~Iterator(){};

    static Iterator* create(xreate::compilation::Context context, const xreate::Symbol& var);
};

template<ImplementationType I>
class IteratorForward;

/** \brief Possible container implementation. Represents computation on the fly 
 *  \sa xreate::containers::Iterator, \sa xreate::containers::Query
 */
template<>
class IteratorForward<ON_THE_FLY> : public Iterator {
private:
    LLVMLayer* llvm;
    const xreate::Symbol current;
    const Symbol source;
    const ImplementationLinkedList linkedlist;
    const CodeScope* const sourceScope;
            //TODO initialize and mark as const (three fields)
    compilation::ICodeScopeUnit* sourceUnit;
    compilation::IFunctionUnit* function; //TODO is used somewhere?
    const Expression& sourceDecl;
    compilation::Context context;
    llvm::Type* sourceRawType =nullptr;

public:
    IteratorForward(const compilation::Context& ctx, const xreate::Symbol& s, const ImplementationRec<ON_THE_FLY>& implementation)
    :   llvm(ctx.pass->man->llvm), 
        current(s), 
        source(implementation.source), 
        linkedlist(source), 
        sourceScope(source.scope),
        sourceUnit(ctx.function->getScopeUnit(source.scope)),
        sourceDecl(CodeScope::getDefinition(source)),
        context(ctx)
    {}
    
    llvm::Value* begin() override;
    llvm::Value* end() override;
    llvm::Value* get(llvm::Value* index,const std::string& hintRetVar="") override;
    llvm::Value* advance(llvm::Value* index, const std::string& hintRetVar="") override;
};

/** \brief Possible container implementation. Represents contiguous in memory(array) implementation
 *  \sa xreate::containers::Iterator, \sa xreate::containers::Query
 */
template<>
class IteratorForward<SOLID>: public Iterator{
    size_t __length;
    llvm::Value* __container;
    LLVMLayer* llvm;
    
public:
    IteratorForward(const compilation::Context& ctx, const xreate::Symbol& symbolContainer, const ImplementationRec<SOLID>& implementation);
    llvm::Value* begin() override;
    llvm::Value* end() override;
    llvm::Value* get(llvm::Value* index,const std::string& hintRetVar="") override;
    llvm::Value* advance(llvm::Value* index, const std::string& hintRetVar="") override;
};
}}

#endif //CODEINSTRUCTIONS_H
