#ifndef CODEINSTRUCTIONS_H
#define CODEINSTRUCTIONS_H

#include "llvmlayer.h"
#include "ast.h"
#include <llvm/IR/Value.h>
#include <vector>

namespace xreate {
    namespace containers {

class Instructions {
public:
    Instructions(CodeScope *current, LLVMLayer* layer);
    llvm::Value* compileIndex(const Symbol& dataSymbol, std::vector<llvm::Value*> indexes, std::string ident="");
    llvm::Value* compileGetElement(std::string varIn, llvm::Value* stateLoop, std::string ident="");

        /*
        *    - map Computation -> Llvm_Array: Prohibited, we do not know a result size
        *    - map Llvm_Array -> Computation: considered in `compileGetElement`
        *    - map Llvm_Array -> Llvm_Array considered by this method
        */
    llvm::Value* compileMapArray(const Expression &expr, const std::string hintRetVar="");
    llvm::Value* compileFold(const Expression& fold, const std::string& ident="");
    llvm::Value* compileIf(const Expression& exprIf, const std::string& ident);

    llvm::Value *compileConstantArray(const Expression &expr, const std::string&  hintRetVar="");

private:
    CodeScope* scope;
    LLVMLayer* llvm;

    llvm::IntegerType* const tyNum;
};



    }}

#endif //CODEINSTRUCTIONS_H

/*
    template<Operator Instruction>
    struct InstructionClasses {};

    template<>
    struct InstructionClasses<Operator::LIST> {
        typedef InstructionList Impl;
    };

    template<>
    struct InstructionClasses<Operator::MAP> {
        typedef InstructionMap Impl;
    };

    template<Operator Instruction>
    class CodeInstruction: public InstructionClasses<Instruction>::Impl
    {
        typedef  typename InstructionClasses<Instruction>::Impl InstructionImpl;

    public:
        CodeInstruction(CodeScope* parent)
                : InstructionImpl(parent)
        {}

        llvm::Value *
        compileExpression(const Expression &expr, LLVMLayer &l, const std::string * const hintRetVar)
        {
            if (expr.op == Instruction)
                return InstructionImpl::compileDefault(expr, l, hintRetVar);

            return CodeScope::compileExpression(expr, l, hintRetVar);
        }
    };
}
*/